1.1 --- a/mythtv_plugin/gstmythtvsrc.c Wed Sep 20 23:59:48 2006 +0100
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,900 +0,0 @@
1.4 -/* vim: set sw=2: -*- Mode: C; tab-width: 2; indent-tabs-mode: t; c-basic-offset: 2; c-indent-level: 2 -*- */
1.5 -/* GStreamer MythTV Plug-in
1.6 - * Copyright (C) <2006> Rosfran Borges <rosfran.borges@indt.org.br>
1.7 - *
1.8 - * This library is free software; you can redistribute it and/or
1.9 - * modify it under the terms of the GNU Library General Public
1.10 - * License as published by the Free Software Foundation; either
1.11 - * version 2 of the License, or (at your option) any later version.
1.12 - *
1.13 - * This library is distributed in the hope that it will be useful,
1.14 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.15 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1.16 - * Library General Public License for more
1.17 - */
1.18 -
1.19 -#ifdef HAVE_CONFIG_H
1.20 -#include "config.h"
1.21 -#endif
1.22 -
1.23 -#include "gstmythtvsrc.h"
1.24 -#include "myth_file_transfer.h"
1.25 -#include "myth_livetv.h"
1.26 -
1.27 -#include <gmyth/gmyth_socket.h>
1.28 -#include <gmyth/gmyth_tvchain.h>
1.29 -
1.30 -#include <string.h>
1.31 -#include <unistd.h>
1.32 -
1.33 -GST_DEBUG_CATEGORY_STATIC (mythtvsrc_debug);
1.34 -#define GST_CAT_DEFAULT mythtvsrc_debug
1.35 -
1.36 -#define GST_MYTHTV_ID_NUM 1
1.37 -
1.38 -#define MYTHTV_VERSION_DEFAULT 30
1.39 -
1.40 -#define MYTHTV_TRANSFER_MAX_WAITS 100
1.41 -
1.42 -#define MYTHTV_TRANSFER_MAX_BUFFER ( 32*1024 )
1.43 -
1.44 -/* 4*1024 ??? */
1.45 -#define MAX_READ_SIZE ( 32*1024 )
1.46 -
1.47 -#define ENABLE_TIMING_POSITION 1
1.48 -
1.49 -/* stablish a maximum iteration value to the IS_RECORDING message */
1.50 -static guint wait_to_transfer = 0;
1.51 -
1.52 -static const GstElementDetails gst_mythtv_src_details =
1.53 -GST_ELEMENT_DETAILS ("MythTV client source",
1.54 - "Source/Network",
1.55 - "Control and receive data as a client over the network via raw socket connections using the MythTV protocol",
1.56 - "Rosfran Borges <rosfran.borges@indt.org.br>");
1.57 -
1.58 -static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
1.59 - GST_PAD_SRC,
1.60 - GST_PAD_ALWAYS,
1.61 - GST_STATIC_CAPS_ANY);
1.62 -
1.63 -enum
1.64 -{
1.65 - PROP_0,
1.66 - PROP_LOCATION,
1.67 - PROP_URI,
1.68 -#ifndef GST_DISABLE_GST_DEBUG
1.69 - PROP_MYTHTV_DBG,
1.70 -#endif
1.71 - PROP_MYTHTV_VERSION,
1.72 - PROP_MYTHTV_LIVE,
1.73 - PROP_MYTHTV_LIVEID,
1.74 - PROP_MYTHTV_LIVE_CHAINID
1.75 -};
1.76 -
1.77 -static void gst_mythtv_src_finalize (GObject * gobject);
1.78 -
1.79 -static GstFlowReturn gst_mythtv_src_create (GstBaseSrc * psrc,
1.80 - guint64 offset, guint size, GstBuffer ** outbuf);
1.81 -static gboolean gst_mythtv_src_start (GstBaseSrc * bsrc);
1.82 -static gboolean gst_mythtv_src_stop (GstBaseSrc * bsrc);
1.83 -static gboolean gst_mythtv_src_get_size (GstBaseSrc * bsrc, guint64 * size);
1.84 -static gboolean gst_mythtv_src_is_seekable( GstBaseSrc *base_src );
1.85 -
1.86 -static void gst_mythtv_src_set_property (GObject * object, guint prop_id,
1.87 - const GValue * value, GParamSpec * pspec);
1.88 -static void gst_mythtv_src_get_property (GObject * object, guint prop_id,
1.89 - GValue * value, GParamSpec * pspec);
1.90 -
1.91 -static void
1.92 -gst_mythtv_src_uri_handler_init (gpointer g_iface, gpointer iface_data);
1.93 -
1.94 -static gboolean
1.95 -gst_mythtv_src_handle_event (GstPad * pad, GstEvent * event);
1.96 -
1.97 - static void
1.98 -_urihandler_init (GType type)
1.99 -{
1.100 - static const GInterfaceInfo urihandler_info = {
1.101 - gst_mythtv_src_uri_handler_init,
1.102 - NULL,
1.103 - NULL
1.104 - };
1.105 -
1.106 - g_type_add_interface_static (type, GST_TYPE_URI_HANDLER, &urihandler_info);
1.107 -
1.108 - GST_DEBUG_CATEGORY_INIT (mythtvsrc_debug, "mythtvsrc", 0,
1.109 - "MythTV src");
1.110 -}
1.111 -
1.112 -GST_BOILERPLATE_FULL (GstMythtvSrc, gst_mythtv_src, GstBaseSrc,
1.113 - GST_TYPE_BASE_SRC, _urihandler_init);
1.114 -
1.115 - static void
1.116 -gst_mythtv_src_base_init (gpointer g_class)
1.117 -{
1.118 - GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
1.119 -
1.120 - gst_element_class_add_pad_template (element_class,
1.121 - gst_static_pad_template_get (&srctemplate));
1.122 -
1.123 - gst_element_class_set_details (element_class, &gst_mythtv_src_details);
1.124 -}
1.125 -
1.126 - static void
1.127 -gst_mythtv_src_class_init (GstMythtvSrcClass * klass)
1.128 -{
1.129 - GObjectClass *gobject_class;
1.130 - GstBaseSrcClass *gstbasesrc_class;
1.131 -
1.132 - gobject_class = (GObjectClass *) klass;
1.133 - gstbasesrc_class = (GstBaseSrcClass *) klass;
1.134 -
1.135 - gobject_class->set_property = gst_mythtv_src_set_property;
1.136 - gobject_class->get_property = gst_mythtv_src_get_property;
1.137 - gobject_class->finalize = gst_mythtv_src_finalize;
1.138 -
1.139 - g_object_class_install_property
1.140 - (gobject_class, PROP_LOCATION,
1.141 - g_param_spec_string ("location", "Location",
1.142 - "The location. In the form:"
1.143 - "\n\t\t\tmyth://a.com/file.nuv"
1.144 - "\n\t\t\tmyth://a.com:23223/file.nuv "
1.145 - "\n\t\t\ta.com/file.nuv - default scheme 'myth'",
1.146 - "", G_PARAM_READWRITE));
1.147 -
1.148 - g_object_class_install_property
1.149 - (gobject_class, PROP_URI,
1.150 - g_param_spec_string ("uri", "Uri",
1.151 - "The location in form of a URI (deprecated; use location)",
1.152 - "", G_PARAM_READWRITE));
1.153 -
1.154 - g_object_class_install_property
1.155 - (gobject_class, PROP_MYTHTV_VERSION,
1.156 - g_param_spec_int ("mythtv-version", "mythtv-version",
1.157 - "Change Myth TV version",
1.158 - 26, 30, 26, G_PARAM_READWRITE));
1.159 -
1.160 - g_object_class_install_property
1.161 - (gobject_class, PROP_MYTHTV_LIVEID,
1.162 - g_param_spec_int ("mythtv-live-id", "mythtv-live-id",
1.163 - "Change Myth TV version",
1.164 - 0, 200, GST_MYTHTV_ID_NUM, G_PARAM_READWRITE));
1.165 -
1.166 - g_object_class_install_property
1.167 - (gobject_class, PROP_MYTHTV_LIVE_CHAINID,
1.168 - g_param_spec_string ("mythtv-live-chainid", "mythtv-live-chainid",
1.169 - "Sets the Myth TV chain ID (from TV Chain)",
1.170 - "", G_PARAM_READWRITE));
1.171 -
1.172 - g_object_class_install_property
1.173 - (gobject_class, PROP_MYTHTV_LIVE,
1.174 - g_param_spec_boolean ("mythtv-live", "mythtv-live",
1.175 - "Enable MythTV Live TV content streaming",
1.176 - FALSE, G_PARAM_READWRITE));
1.177 -
1.178 -#ifndef GST_DISABLE_GST_DEBUG
1.179 - g_object_class_install_property
1.180 - (gobject_class, PROP_MYTHTV_DBG,
1.181 - g_param_spec_boolean ("mythtv-debug", "mythtv-debug",
1.182 - "Enable MythTV debug messages",
1.183 - FALSE, G_PARAM_READWRITE));
1.184 -#endif
1.185 -
1.186 - gstbasesrc_class->start = gst_mythtv_src_start;
1.187 - gstbasesrc_class->stop = gst_mythtv_src_stop;
1.188 - gstbasesrc_class->get_size = gst_mythtv_src_get_size;
1.189 - gstbasesrc_class->is_seekable = gst_mythtv_src_is_seekable;
1.190 -
1.191 - gstbasesrc_class->create = gst_mythtv_src_create;
1.192 -
1.193 -
1.194 - GST_DEBUG_CATEGORY_INIT (mythtvsrc_debug, "mythtvsrc", 0,
1.195 - "MythTV Client Source");
1.196 -}
1.197 -
1.198 - static void
1.199 -gst_mythtv_src_init (GstMythtvSrc * this, GstMythtvSrcClass * g_class)
1.200 -{
1.201 - this->file_transfer = NULL;
1.202 -
1.203 - this->unique_setup = FALSE;
1.204 -
1.205 - this->mythtv_version = MYTHTV_VERSION_DEFAULT;
1.206 -
1.207 - this->bytes_read = 0;
1.208 -
1.209 - this->content_size = -1;
1.210 - this->read_offset = 0;
1.211 -
1.212 - this->live_tv = FALSE;
1.213 -
1.214 - this->user_agent = g_strdup ("mythtvsrc");
1.215 - this->mythtv_caps = NULL;
1.216 -
1.217 - gst_pad_set_event_function (GST_BASE_SRC_PAD(GST_BASE_SRC(this)),
1.218 - GST_DEBUG_FUNCPTR (gst_mythtv_src_handle_event));
1.219 -
1.220 -}
1.221 -
1.222 - static void
1.223 -gst_mythtv_src_finalize (GObject * gobject)
1.224 -{
1.225 - GstMythtvSrc *this = GST_MYTHTV_SRC (gobject);
1.226 -
1.227 - g_free (this->user_agent);
1.228 -
1.229 - if (this->mythtv_caps) {
1.230 - gst_caps_unref (this->mythtv_caps);
1.231 - this->mythtv_caps = NULL;
1.232 - }
1.233 -
1.234 - if (this->file_transfer) {
1.235 - g_object_unref (this->file_transfer);
1.236 - this->file_transfer = NULL;
1.237 - }
1.238 -
1.239 - if (this->uri_name) {
1.240 - g_free (this->uri_name);
1.241 - }
1.242 -
1.243 - if (this->user_agent) {
1.244 - g_free (this->user_agent);
1.245 - }
1.246 -
1.247 - G_OBJECT_CLASS (parent_class)->finalize (gobject);
1.248 -}
1.249 -
1.250 -#if 0
1.251 - static guint
1.252 -do_seek( GstMythtvSrc *src, guint64 offset, guint size, GstBuffer *outbuf )
1.253 -{
1.254 - guint64 off_uint64 = myth_file_transfer_seek(src->file_transfer, offset, 1);
1.255 -
1.256 - g_print( "[%s] Call MythTV SEEK with offset %llu, got a new one %llu...\n", __FUNCTION__,
1.257 - offset, off_uint64 );
1.258 -
1.259 - return off_uint64;
1.260 -
1.261 -}
1.262 -#endif
1.263 -
1.264 - static guint
1.265 -do_read_request_response (GstMythtvSrc * src, guint64 offset, guint size, GstBuffer * outbuf)
1.266 -{
1.267 - guint read = 0;
1.268 - guint sizetoread = size; //GST_BUFFER_SIZE (outbuf);
1.269 -
1.270 - g_print( "[%s] Reading %d bytes...\n", __FUNCTION__, sizetoread );
1.271 -
1.272 - /* Loop sending the request:
1.273 - * Retry whilst authentication fails and we supply it. */
1.274 -
1.275 - ssize_t len = 0;
1.276 -
1.277 - GST_OBJECT_LOCK(src);
1.278 -
1.279 - while ( sizetoread > 0 ) {
1.280 -
1.281 - len = myth_file_transfer_read( src->file_transfer,
1.282 - GST_BUFFER_DATA (outbuf) + read, sizetoread, TRUE );
1.283 -
1.284 - if ( len > 0 ) {
1.285 - read += len;
1.286 - src->read_offset += read;
1.287 - sizetoread -= len;
1.288 - } else if ( len < 0 ) {
1.289 - goto done;
1.290 - }
1.291 - /*else if ( len == 0 ) {
1.292 - goto eos;
1.293 - }*/
1.294 -
1.295 - if ( len == sizetoread )
1.296 - break;
1.297 -
1.298 - }
1.299 -
1.300 - if ( read > 0 ) {
1.301 - src->bytes_read += read;
1.302 -
1.303 - GST_BUFFER_SIZE (outbuf) = read;
1.304 - } else if ( read <= 0 || len <= 0 ) {
1.305 - if ( src->live_tv == FALSE )
1.306 - goto eos;
1.307 - else
1.308 - goto done;
1.309 - }
1.310 - //GST_BUFFER_OFFSET (outbuf) = src->read_offset;
1.311 -
1.312 - g_print( "[%s]\tBYTES READ (actual) = %d, BYTES READ (cumulative) = %llu, "\
1.313 - "OFFSET = %llu, CONTENT SIZE = %llu.\n", __FUNCTION__, read, src->bytes_read,
1.314 - src->read_offset, src->content_size );
1.315 -
1.316 - GST_OBJECT_UNLOCK(src);
1.317 -
1.318 - if ( len < 0 ) {
1.319 - read = len;
1.320 - if ( src->live_tv == FALSE )
1.321 - goto eos;
1.322 - else
1.323 - goto done;
1.324 - }
1.325 -
1.326 - if ( src->bytes_read < src->content_size )
1.327 - goto done;
1.328 -
1.329 -eos:
1.330 - GST_OBJECT_UNLOCK(src);
1.331 -
1.332 - src->eos = TRUE;
1.333 -done:
1.334 - GST_OBJECT_UNLOCK(src);
1.335 -
1.336 - return read;
1.337 -}
1.338 -
1.339 - static GstFlowReturn
1.340 -gst_mythtv_src_create ( GstBaseSrc * psrc, guint64 offset,
1.341 - guint size, GstBuffer **outbuf )
1.342 -{
1.343 - GstMythtvSrc *src;
1.344 - GstFlowReturn ret = GST_FLOW_OK;
1.345 - guint read;
1.346 - guint64 size_tmp = 0;
1.347 -
1.348 - src = GST_MYTHTV_SRC (psrc);
1.349 -
1.350 - g_print( "[%s]\tBUFFER OFFSET = %llu, BUFFER SIZE = %d.\n", __FUNCTION__, offset,
1.351 - size );
1.352 -
1.353 -
1.354 - /* The caller should know the number of bytes and not read beyond EOS. */
1.355 - if (G_UNLIKELY (src->eos))
1.356 - goto eos;
1.357 -
1.358 - /* Create the buffer. */
1.359 - ret = gst_pad_alloc_buffer ( GST_BASE_SRC_PAD (GST_BASE_SRC (psrc)),
1.360 - // GST_BUFFER_OFFSET_NONE, GST_BASE_SRC (psrc)->blocksize,
1.361 - offset, size,
1.362 - src->mythtv_caps ? src->mythtv_caps :
1.363 - GST_PAD_CAPS (GST_BASE_SRC_PAD (GST_BASE_SRC (psrc))), outbuf );
1.364 -
1.365 - if (G_UNLIKELY (ret == GST_FLOW_UNEXPECTED))
1.366 - goto eos;
1.367 -
1.368 - if (G_UNLIKELY (ret != GST_FLOW_OK))
1.369 - goto done;
1.370 -
1.371 - read = do_read_request_response ( src, offset, size, *outbuf );
1.372 -
1.373 -#if ENABLE_TIMING_POSITION == 1
1.374 - if (src->live_tv == TRUE) {
1.375 - g_usleep( 1000 );
1.376 -get_file_pos:
1.377 - g_usleep( 100 );
1.378 - size_tmp = myth_file_transfer_get_file_position( src->file_transfer );
1.379 - if ( size_tmp > ( src->content_size + MYTHTV_TRANSFER_MAX_BUFFER ) )
1.380 - src->content_size = size_tmp;
1.381 - else
1.382 - goto get_file_pos;
1.383 - g_print( "\t[%s]\tGET_POSITION: file_position = %llu\n",
1.384 - __FUNCTION__, size_tmp);
1.385 -
1.386 - }
1.387 -#endif
1.388 -
1.389 - if (G_UNLIKELY (read < 0))
1.390 - goto read_error;
1.391 -
1.392 - if (G_UNLIKELY(src->eos))
1.393 - goto eos;
1.394 -
1.395 -done:
1.396 - return ret;
1.397 -eos:
1.398 -#if ENABLE_TIMING_POSITION == 1
1.399 - if (src->live_tv == TRUE) {
1.400 - g_usleep( 1000 );
1.401 - guint64 size_tmp = 0;
1.402 -get_file_pos_eos:
1.403 - g_usleep( 100 );
1.404 - size_tmp = myth_file_transfer_get_file_position( src->file_transfer );
1.405 - if ( size_tmp > ( src->content_size + MYTHTV_TRANSFER_MAX_BUFFER ) )
1.406 - src->content_size = size_tmp;
1.407 - else
1.408 - goto get_file_pos_eos;
1.409 - g_print( "\t[%s]\tGET_POSITION: file_position = %llu\n",
1.410 - __FUNCTION__, size_tmp);
1.411 - goto done;
1.412 - } else
1.413 -#endif
1.414 - {
1.415 - GST_DEBUG_OBJECT (src, "EOS reached");
1.416 - return GST_FLOW_UNEXPECTED;
1.417 - }
1.418 - /* ERRORS */
1.419 -read_error:
1.420 - {
1.421 - GST_ELEMENT_ERROR (src, RESOURCE, READ,
1.422 - (NULL), ("Could not read any bytes (%i, %s)", read,
1.423 - src->uri_name));
1.424 - return GST_FLOW_ERROR;
1.425 - }
1.426 -}
1.427 -
1.428 -#if 0
1.429 -/* The following two charset mangling functions were copied from gnomevfssrc.
1.430 - * Preserve them under the unverified assumption that they do something vaguely
1.431 - * worthwhile.
1.432 - */
1.433 - static char *
1.434 -unicodify (const char *str, int len, ...)
1.435 -{
1.436 - char *ret = NULL, *cset;
1.437 - va_list args;
1.438 - gsize bytes_read, bytes_written;
1.439 -
1.440 - if (g_utf8_validate (str, len, NULL))
1.441 - return g_strndup (str, len >= 0 ? len : strlen (str));
1.442 -
1.443 - va_start (args, len);
1.444 - while ((cset = va_arg (args, char *)) != NULL)
1.445 - {
1.446 - if (!strcmp (cset, "locale"))
1.447 - ret = g_locale_to_utf8 (str, len, &bytes_read, &bytes_written, NULL);
1.448 - else
1.449 - ret = g_convert (str, len, "UTF-8", cset,
1.450 - &bytes_read, &bytes_written, NULL);
1.451 - if (ret)
1.452 - break;
1.453 - }
1.454 - va_end (args);
1.455 -
1.456 - return ret;
1.457 -}
1.458 -
1.459 - static char *
1.460 -gst_mythtv_src_unicodify (const char *str)
1.461 -{
1.462 - return unicodify (str, -1, "locale", "ISO-8859-1", NULL);
1.463 -}
1.464 -#endif
1.465 -
1.466 -/* create a socket for connecting to remote server */
1.467 - static gboolean
1.468 -gst_mythtv_src_start ( GstBaseSrc * bsrc )
1.469 -{
1.470 - GstMythtvSrc *src = GST_MYTHTV_SRC (bsrc);
1.471 -
1.472 - GString *chain_id_local = NULL;
1.473 -
1.474 - gboolean ret = TRUE;
1.475 -#if 0
1.476 - if (src->live_tv == TRUE && src->file_transfer != NULL) {
1.477 - guint64 size_tmp = myth_file_transfer_get_file_position( src->file_transfer );
1.478 - if (size_tmp > src->content_size)
1.479 - src->content_size = size_tmp;
1.480 - g_print( "\t[%s]\tGET_POSITION: file_position = %llu\n",
1.481 - __FUNCTION__, size_tmp);
1.482 - }
1.483 -#endif
1.484 - if (src->unique_setup == FALSE) {
1.485 - src->unique_setup = TRUE;
1.486 - } else {
1.487 - goto done;
1.488 - }
1.489 -
1.490 - GST_OBJECT_LOCK(src);
1.491 -
1.492 - if ( src->live_tv ) {
1.493 - src->spawn_livetv = myth_livetv_new( );
1.494 - if ( myth_livetv_setup( src->spawn_livetv ) == FALSE ) {
1.495 - ret = FALSE;
1.496 - goto init_failed;
1.497 - }
1.498 - /* set up the uri variable */
1.499 - src->uri_name = g_strdup( src->spawn_livetv->proginfo->pathname->str );
1.500 - chain_id_local = gmyth_tvchain_get_id( src->spawn_livetv->tvchain );
1.501 - if ( chain_id_local != NULL ) {
1.502 - src->live_chain_id = g_strdup( chain_id_local->str );
1.503 - g_print( "\t[%s]\tLocal chain ID = %s.\n", __FUNCTION__, src->live_chain_id );
1.504 - }
1.505 - src->live_tv_id = src->spawn_livetv->remote_encoder->recorder_num;
1.506 - g_print ( "[%s] LiveTV id = %d, URI path = %s.\n", __FUNCTION__, src->live_tv_id, src->uri_name );
1.507 - }
1.508 -
1.509 - src->file_transfer = myth_file_transfer_new( src->live_tv_id,
1.510 - g_string_new( src->uri_name ), -1, src->mythtv_version );
1.511 -
1.512 - if ( src->file_transfer == NULL ) {
1.513 - GST_OBJECT_UNLOCK(src);
1.514 -
1.515 - goto init_failed;
1.516 - }
1.517 -
1.518 - if ( src->live_tv ) {
1.519 - g_print ( "[%s] GST MYTHTVSRC: live_chain_id = %s\n", __FUNCTION__, src->live_chain_id );
1.520 - /* sets the MythSocket to the FileTransfer */
1.521 - //ret = myth_file_transfer_livetv_setup( &(src->file_transfer), src->spawn_livetv->remote_encoder->myth_socket );
1.522 - }
1.523 - /* sets the Playback monitor connection */
1.524 - ret = myth_file_transfer_playback_setup( &(src->file_transfer), src->live_tv );
1.525 -
1.526 - if ( src->live_tv == TRUE && ret == TRUE ) {
1.527 - /* loop finished, set the max tries variable to zero again... */
1.528 - wait_to_transfer = 0;
1.529 -
1.530 - while ( wait_to_transfer++ < MYTHTV_TRANSFER_MAX_WAITS && ( myth_file_transfer_is_recording( src->file_transfer ) == FALSE
1.531 - /*|| ( myth_file_transfer_get_file_position( src->file_transfer ) < ( src->content_size + 327680 ) )*/ ) )
1.532 - g_usleep( 100 );
1.533 - }
1.534 -
1.535 - /* sets the FileTransfer instance connection (video/audio download) */
1.536 - ret = myth_file_transfer_setup( &(src->file_transfer), src->live_tv );
1.537 -
1.538 - if ( ret == FALSE ) {
1.539 - GST_OBJECT_UNLOCK(src);
1.540 -#ifndef GST_DISABLE_GST_DEBUG
1.541 - if ( src->mythtv_msgs_dbg )
1.542 - g_printerr( "MythTV FileTransfer request failed when setting up socket connection!\n" );
1.543 -#endif
1.544 - goto begin_req_failed;
1.545 - }
1.546 -
1.547 - src->content_size = src->file_transfer->filesize;
1.548 -
1.549 - GST_OBJECT_UNLOCK(src);
1.550 -
1.551 -#if 0
1.552 - const char *str_value;
1.553 - gint gint_value;
1.554 -
1.555 - str_value = ne_get_response_header (src->request, "myth-metaint");
1.556 - if (str_value) {
1.557 - if ( sscanf (str_value, "%d", &gint_value) == 1 ) {
1.558 - if (src->myth_caps) {
1.559 - gst_caps_unref (src->myth_caps);
1.560 - src->myth_caps = NULL;
1.561 - }
1.562 - src->myth_metaint = gint_value;
1.563 -#endif
1.564 - //src->mythtv_caps = gst_caps_new_simple ("application/x-gst_ff-nuv", NULL);
1.565 - // }
1.566 - // }
1.567 -done:
1.568 - return TRUE;
1.569 -
1.570 - /* ERRORS */
1.571 -init_failed:
1.572 - {
1.573 - if (src->spawn_livetv != NULL )
1.574 - g_object_unref( src->spawn_livetv );
1.575 -
1.576 - GST_ELEMENT_ERROR (src, LIBRARY, INIT,
1.577 - (NULL), ("Could not initialize MythTV library (%i, %s)", ret, src->uri_name));
1.578 - return FALSE;
1.579 - }
1.580 -begin_req_failed:
1.581 - {
1.582 - GST_ELEMENT_ERROR (src, LIBRARY, INIT,
1.583 - (NULL), ("Could not begin request sent to MythTV server (%i, %s)", ret, src->uri_name));
1.584 - return FALSE;
1.585 - }
1.586 -}
1.587 -
1.588 - static gboolean
1.589 -gst_mythtv_src_get_size (GstBaseSrc * bsrc, guint64 * size)
1.590 -{
1.591 - GstMythtvSrc *src;
1.592 -
1.593 - src = GST_MYTHTV_SRC (bsrc);
1.594 -#if ENABLE_TIMING_POSITION == 1
1.595 - if (src->live_tv == TRUE) {
1.596 -get_file_pos:
1.597 - g_usleep( 100 );
1.598 - guint64 size_tmp = myth_file_transfer_get_file_position( src->file_transfer );
1.599 - if ( size_tmp > ( src->content_size + MYTHTV_TRANSFER_MAX_BUFFER ) )
1.600 - src->content_size = size_tmp;
1.601 - else
1.602 - goto get_file_pos;
1.603 - g_print( "\t[%s]\tGET_POSITION: file_position = %llu\n",
1.604 - __FUNCTION__, size_tmp);
1.605 - }
1.606 -#endif
1.607 - if (src->content_size <= 0)
1.608 - return FALSE;
1.609 -
1.610 - *size = src->content_size;
1.611 -
1.612 - return TRUE;
1.613 -}
1.614 -
1.615 -/* close the socket and associated resources
1.616 - * used both to recover from errors and go to NULL state */
1.617 - static gboolean
1.618 -gst_mythtv_src_stop (GstBaseSrc * bsrc)
1.619 -{
1.620 - GstMythtvSrc *src;
1.621 -
1.622 - src = GST_MYTHTV_SRC (bsrc);
1.623 -
1.624 - if (src->uri_name) {
1.625 - g_free (src->uri_name);
1.626 - src->uri_name = NULL;
1.627 - }
1.628 -
1.629 - if (src->mythtv_caps) {
1.630 - gst_caps_unref (src->mythtv_caps);
1.631 - src->mythtv_caps = NULL;
1.632 - }
1.633 -
1.634 - src->eos = FALSE;
1.635 -
1.636 - return TRUE;
1.637 -}
1.638 -
1.639 - static gboolean
1.640 -gst_mythtv_src_handle_event (GstPad * pad, GstEvent * event)
1.641 -{
1.642 - GstMythtvSrc *src = GST_MYTHTV_SRC (GST_PAD_PARENT (pad));
1.643 -
1.644 - switch (GST_EVENT_TYPE (event)) {
1.645 - case GST_EVENT_FLUSH_START:
1.646 - src->eos = FALSE;
1.647 - break;
1.648 - //return TRUE;
1.649 - case GST_EVENT_FLUSH_STOP:
1.650 - src->do_start = TRUE;
1.651 - src->eos = FALSE;
1.652 - gst_element_set_state (GST_ELEMENT(src), GST_STATE_NULL);
1.653 - gst_element_set_locked_state (GST_ELEMENT(src), TRUE);
1.654 - break;
1.655 - case GST_EVENT_SEEK:
1.656 - {
1.657 - gdouble rate;
1.658 - //gboolean update = TRUE;
1.659 - GstFormat format;
1.660 - GstSeekType cur_type, stop_type;
1.661 - GstSeekFlags flags;
1.662 - gint64 cur = 0, stop = 0;
1.663 - gst_event_parse_seek ( event, &rate, &format,
1.664 - &flags, &cur_type, &cur,
1.665 - &stop_type, &stop );
1.666 -
1.667 - g_print( "[%s] Got EVENT_SEEK.\n", __FUNCTION__ );
1.668 - if ( !( flags & GST_SEEK_FLAG_FLUSH ) ) {
1.669 - g_print( "[%s] Could get the FLAG_FLUSH message.\n", __FUNCTION__ );
1.670 - }
1.671 - //gboolean ret = gst_event_parse_new_segment ( event,
1.672 - // &update, &rate, &format, &start, &stop,
1.673 - // &position );
1.674 - //GstFlowReturn flow_ret = gst_mythtv_src_create (GST_BASE_SRC( GST_PAD_PARENT( psrc ) ),
1.675 - // cur, stop - cur + 1, GstBuffer)
1.676 -
1.677 - }
1.678 - default:
1.679 - return gst_pad_event_default (pad, event);
1.680 - }
1.681 -
1.682 - return gst_pad_event_default (pad, event);
1.683 -}
1.684 -
1.685 - static gboolean
1.686 -gst_mythtv_src_is_seekable( GstBaseSrc *base_src )
1.687 -{
1.688 - return TRUE;
1.689 -}
1.690 -
1.691 - static void
1.692 -gst_mythtv_src_set_property (GObject * object, guint prop_id,
1.693 - const GValue * value, GParamSpec * pspec)
1.694 -{
1.695 - GstMythtvSrc *mythtvsrc = GST_MYTHTV_SRC (object);
1.696 -
1.697 - GST_OBJECT_LOCK (mythtvsrc);
1.698 - switch (prop_id) {
1.699 - case PROP_URI:
1.700 - case PROP_LOCATION:
1.701 - {
1.702 - if (!g_value_get_string (value)) {
1.703 - GST_WARNING ("location property cannot be NULL");
1.704 - goto done;
1.705 - }
1.706 -
1.707 - if (mythtvsrc->uri_name != NULL) {
1.708 - g_free (mythtvsrc->uri_name);
1.709 - mythtvsrc->uri_name = NULL;
1.710 - }
1.711 - mythtvsrc->uri_name = g_value_dup_string (value);
1.712 -
1.713 - break;
1.714 - }
1.715 -#ifndef GST_DISABLE_GST_DEBUG
1.716 - case PROP_MYTHTV_DBG:
1.717 - {
1.718 - mythtvsrc->mythtv_msgs_dbg = g_value_get_boolean (value);
1.719 - break;
1.720 - }
1.721 -#endif
1.722 - case PROP_MYTHTV_VERSION:
1.723 - {
1.724 - mythtvsrc->mythtv_version = g_value_get_int (value);
1.725 - break;
1.726 - }
1.727 - case PROP_MYTHTV_LIVEID:
1.728 - {
1.729 - mythtvsrc->live_tv_id = g_value_get_int (value);
1.730 - break;
1.731 - }
1.732 - case PROP_MYTHTV_LIVE:
1.733 - {
1.734 - mythtvsrc->live_tv = g_value_get_boolean (value);
1.735 - break;
1.736 - }
1.737 - case PROP_MYTHTV_LIVE_CHAINID:
1.738 - {
1.739 - if (!g_value_get_string (value)) {
1.740 - GST_WARNING ("MythTV Live chainid property cannot be NULL");
1.741 - goto done;
1.742 - }
1.743 -
1.744 - if (mythtvsrc->live_chain_id != NULL) {
1.745 - g_free (mythtvsrc->live_chain_id);
1.746 - mythtvsrc->live_chain_id = NULL;
1.747 - }
1.748 - mythtvsrc->live_chain_id = g_value_dup_string (value);
1.749 -
1.750 - break;
1.751 - }
1.752 -
1.753 - default:
1.754 - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1.755 - break;
1.756 - }
1.757 - GST_OBJECT_UNLOCK (mythtvsrc);
1.758 -done:
1.759 - return;
1.760 -}
1.761 -
1.762 - static void
1.763 -gst_mythtv_src_get_property (GObject * object, guint prop_id,
1.764 - GValue * value, GParamSpec * pspec)
1.765 -{
1.766 - GstMythtvSrc *mythtvsrc = GST_MYTHTV_SRC (object);
1.767 -
1.768 - GST_OBJECT_LOCK (mythtvsrc);
1.769 - switch (prop_id) {
1.770 - case PROP_URI:
1.771 - case PROP_LOCATION:
1.772 - {
1.773 - gchar *str = g_strdup( "" );
1.774 -
1.775 - if ( mythtvsrc->uri_name == NULL ) {
1.776 - g_free (mythtvsrc->uri_name);
1.777 - mythtvsrc->uri_name = NULL;
1.778 - } else {
1.779 - str = g_strdup( mythtvsrc->uri_name );
1.780 - }
1.781 - g_value_set_string ( value, str );
1.782 - break;
1.783 - }
1.784 -#ifndef GST_DISABLE_GST_DEBUG
1.785 - case PROP_MYTHTV_DBG:
1.786 - g_value_set_boolean ( value, mythtvsrc->mythtv_msgs_dbg );
1.787 - break;
1.788 -#endif
1.789 - case PROP_MYTHTV_VERSION:
1.790 - {
1.791 - g_value_set_int ( value, mythtvsrc->mythtv_version );
1.792 - break;
1.793 - }
1.794 - case PROP_MYTHTV_LIVEID:
1.795 - {
1.796 - g_value_set_int ( value, mythtvsrc->live_tv_id );
1.797 - break;
1.798 - }
1.799 - case PROP_MYTHTV_LIVE:
1.800 - g_value_set_boolean ( value, mythtvsrc->live_tv );
1.801 - break;
1.802 - case PROP_MYTHTV_LIVE_CHAINID:
1.803 - {
1.804 - gchar *str = g_strdup( "" );
1.805 -
1.806 - if ( mythtvsrc->live_chain_id == NULL ) {
1.807 - g_free (mythtvsrc->live_chain_id);
1.808 - mythtvsrc->live_chain_id = NULL;
1.809 - } else {
1.810 - str = g_strdup( mythtvsrc->live_chain_id );
1.811 - }
1.812 - g_value_set_string ( value, str );
1.813 - break;
1.814 - }
1.815 - default:
1.816 - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1.817 - break;
1.818 - }
1.819 - GST_OBJECT_UNLOCK (mythtvsrc);
1.820 -}
1.821 -
1.822 -/* entry point to initialize the plug-in
1.823 - * initialize the plug-in itself
1.824 - * register the element factories and pad templates
1.825 - * register the features
1.826 - */
1.827 - static gboolean
1.828 -plugin_init (GstPlugin * plugin)
1.829 -{
1.830 - return gst_element_register (plugin, "mythtvsrc", GST_RANK_NONE,
1.831 - GST_TYPE_MYTHTV_SRC);
1.832 -}
1.833 -
1.834 -/* this is the structure that gst-register looks for
1.835 - * so keep the name plugin_desc, or you cannot get your plug-in registered */
1.836 -GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
1.837 - GST_VERSION_MINOR,
1.838 - "mythtv",
1.839 - "lib MythTV src",
1.840 - plugin_init, VERSION, "LGPL", "GStreamer", "http://gstreamer.net/")
1.841 -
1.842 -
1.843 -/*** GSTURIHANDLER INTERFACE *************************************************/
1.844 - static guint
1.845 -gst_mythtv_src_uri_get_type (void)
1.846 -{
1.847 - return GST_URI_SRC;
1.848 -}
1.849 -
1.850 - static gchar **
1.851 -gst_mythtv_src_uri_get_protocols (void)
1.852 -{
1.853 - static gchar *protocols[] = { "myth", "myths", NULL };
1.854 -
1.855 - return protocols;
1.856 -}
1.857 -
1.858 - static const gchar *
1.859 -gst_mythtv_src_uri_get_uri (GstURIHandler * handler)
1.860 -{
1.861 - GstMythtvSrc *src = GST_MYTHTV_SRC (handler);
1.862 -
1.863 - return src->uri_name;
1.864 -}
1.865 -
1.866 - static gboolean
1.867 -gst_mythtv_src_uri_set_uri (GstURIHandler * handler, const gchar * uri)
1.868 -{
1.869 - GstMythtvSrc *src = GST_MYTHTV_SRC (handler);
1.870 -
1.871 - gchar *protocol;
1.872 -
1.873 - protocol = gst_uri_get_protocol (uri);
1.874 - if ((strcmp (protocol, "myth") != 0) && (strcmp (protocol, "myths") != 0)) {
1.875 - g_free (protocol);
1.876 - return FALSE;
1.877 - }
1.878 - g_free (protocol);
1.879 - g_object_set (src, "location", uri, NULL);
1.880 -
1.881 - return TRUE;
1.882 -}
1.883 -
1.884 - static void
1.885 -gst_mythtv_src_uri_handler_init (gpointer g_iface, gpointer iface_data)
1.886 -{
1.887 - GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface;
1.888 -
1.889 - iface->get_type = gst_mythtv_src_uri_get_type;
1.890 - iface->get_protocols = gst_mythtv_src_uri_get_protocols;
1.891 - iface->get_uri = gst_mythtv_src_uri_get_uri;
1.892 - iface->set_uri = gst_mythtv_src_uri_set_uri;
1.893 -}
1.894 -
1.895 - void
1.896 -size_header_handler (void *userdata, const char *value)
1.897 -{
1.898 - GstMythtvSrc *src = GST_MYTHTV_SRC (userdata);
1.899 -
1.900 - //src->content_size = g_ascii_strtoull (value, NULL, 10);
1.901 -
1.902 - GST_DEBUG_OBJECT (src, "content size = %lld bytes", src->content_size);
1.903 -}