1.1 --- a/gst-plugins-mythtv/src/gstmythtvsrc.c.new Tue May 01 17:22:20 2007 +0100
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,1033 +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 ( 16*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 -static GstTask *update_size_task = NULL;
1.64 -
1.65 -static GStaticRecMutex update_size_mutex = G_STATIC_REC_MUTEX_INIT;
1.66 -
1.67 -enum
1.68 -{
1.69 - PROP_0,
1.70 - PROP_LOCATION,
1.71 - PROP_URI,
1.72 -#ifndef GST_DISABLE_GST_DEBUG
1.73 - PROP_MYTHTV_DBG,
1.74 -#endif
1.75 - PROP_MYTHTV_VERSION,
1.76 - PROP_MYTHTV_LIVE,
1.77 - PROP_MYTHTV_LIVEID,
1.78 - PROP_MYTHTV_LIVE_CHAINID
1.79 -};
1.80 -
1.81 -static void gst_mythtv_src_finalize (GObject * gobject);
1.82 -
1.83 -static GstFlowReturn gst_mythtv_src_create (GstBaseSrc * psrc,
1.84 - guint64 offset, guint size, GstBuffer ** outbuf);
1.85 -static gboolean gst_mythtv_src_start (GstBaseSrc * bsrc);
1.86 -static gboolean gst_mythtv_src_stop (GstBaseSrc * bsrc);
1.87 -static gboolean gst_mythtv_src_get_size (GstBaseSrc * bsrc, guint64 * size);
1.88 -static gboolean gst_mythtv_src_is_seekable( GstBaseSrc *base_src );
1.89 -
1.90 -static void gst_mythtv_src_set_property (GObject * object, guint prop_id,
1.91 - const GValue * value, GParamSpec * pspec);
1.92 -static void gst_mythtv_src_get_property (GObject * object, guint prop_id,
1.93 - GValue * value, GParamSpec * pspec);
1.94 -
1.95 -static void
1.96 -gst_mythtv_src_uri_handler_init (gpointer g_iface, gpointer iface_data);
1.97 -
1.98 -static gboolean
1.99 -gst_mythtv_src_handle_event (GstPad * pad, GstEvent * event);
1.100 -
1.101 - static void
1.102 -_urihandler_init (GType type)
1.103 -{
1.104 - static const GInterfaceInfo urihandler_info = {
1.105 - gst_mythtv_src_uri_handler_init,
1.106 - NULL,
1.107 - NULL
1.108 - };
1.109 -
1.110 - g_type_add_interface_static (type, GST_TYPE_URI_HANDLER, &urihandler_info);
1.111 -
1.112 - GST_DEBUG_CATEGORY_INIT (mythtvsrc_debug, "mythtvsrc", 0,
1.113 - "MythTV src");
1.114 -}
1.115 -
1.116 -GST_BOILERPLATE_FULL (GstMythtvSrc, gst_mythtv_src, GstBaseSrc,
1.117 - GST_TYPE_BASE_SRC, _urihandler_init);
1.118 -
1.119 - static void
1.120 -gst_mythtv_src_base_init (gpointer g_class)
1.121 -{
1.122 - GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
1.123 -
1.124 - gst_element_class_add_pad_template (element_class,
1.125 - gst_static_pad_template_get (&srctemplate));
1.126 -
1.127 - gst_element_class_set_details (element_class, &gst_mythtv_src_details);
1.128 -}
1.129 -
1.130 - static void
1.131 -gst_mythtv_src_class_init (GstMythtvSrcClass * klass)
1.132 -{
1.133 - GObjectClass *gobject_class;
1.134 - GstBaseSrcClass *gstbasesrc_class;
1.135 -
1.136 - gobject_class = (GObjectClass *) klass;
1.137 - gstbasesrc_class = (GstBaseSrcClass *) klass;
1.138 -
1.139 - gobject_class->set_property = gst_mythtv_src_set_property;
1.140 - gobject_class->get_property = gst_mythtv_src_get_property;
1.141 - gobject_class->finalize = gst_mythtv_src_finalize;
1.142 -
1.143 - g_object_class_install_property
1.144 - (gobject_class, PROP_LOCATION,
1.145 - g_param_spec_string ("location", "Location",
1.146 - "The location. In the form:"
1.147 - "\n\t\t\tmyth://a.com/file.nuv"
1.148 - "\n\t\t\tmyth://a.com:23223/file.nuv "
1.149 - "\n\t\t\ta.com/file.nuv - default scheme 'myth'",
1.150 - "", G_PARAM_READWRITE));
1.151 -
1.152 - g_object_class_install_property
1.153 - (gobject_class, PROP_URI,
1.154 - g_param_spec_string ("uri", "Uri",
1.155 - "The location in form of a URI (deprecated; use location)",
1.156 - "", G_PARAM_READWRITE));
1.157 -
1.158 - g_object_class_install_property
1.159 - (gobject_class, PROP_MYTHTV_VERSION,
1.160 - g_param_spec_int ("mythtv-version", "mythtv-version",
1.161 - "Change Myth TV version",
1.162 - 26, 30, 26, G_PARAM_READWRITE));
1.163 -
1.164 - g_object_class_install_property
1.165 - (gobject_class, PROP_MYTHTV_LIVEID,
1.166 - g_param_spec_int ("mythtv-live-id", "mythtv-live-id",
1.167 - "Change Myth TV version",
1.168 - 0, 200, GST_MYTHTV_ID_NUM, G_PARAM_READWRITE));
1.169 -
1.170 - g_object_class_install_property
1.171 - (gobject_class, PROP_MYTHTV_LIVE_CHAINID,
1.172 - g_param_spec_string ("mythtv-live-chainid", "mythtv-live-chainid",
1.173 - "Sets the Myth TV chain ID (from TV Chain)",
1.174 - "", G_PARAM_READWRITE));
1.175 -
1.176 - g_object_class_install_property
1.177 - (gobject_class, PROP_MYTHTV_LIVE,
1.178 - g_param_spec_boolean ("mythtv-live", "mythtv-live",
1.179 - "Enable MythTV Live TV content streaming",
1.180 - FALSE, G_PARAM_READWRITE));
1.181 -
1.182 -#ifndef GST_DISABLE_GST_DEBUG
1.183 - g_object_class_install_property
1.184 - (gobject_class, PROP_MYTHTV_DBG,
1.185 - g_param_spec_boolean ("mythtv-debug", "mythtv-debug",
1.186 - "Enable MythTV debug messages",
1.187 - FALSE, G_PARAM_READWRITE));
1.188 -#endif
1.189 -
1.190 - gstbasesrc_class->start = gst_mythtv_src_start;
1.191 - gstbasesrc_class->stop = gst_mythtv_src_stop;
1.192 - gstbasesrc_class->get_size = gst_mythtv_src_get_size;
1.193 - gstbasesrc_class->is_seekable = gst_mythtv_src_is_seekable;
1.194 -
1.195 - gstbasesrc_class->create = gst_mythtv_src_create;
1.196 -
1.197 - GST_DEBUG_CATEGORY_INIT (mythtvsrc_debug, "mythtvsrc", 0,
1.198 - "MythTV Client Source");
1.199 -}
1.200 -
1.201 - static void
1.202 -gst_mythtv_src_init (GstMythtvSrc * this, GstMythtvSrcClass * g_class)
1.203 -{
1.204 - this->file_transfer = NULL;
1.205 -
1.206 - this->unique_setup = FALSE;
1.207 -
1.208 - this->mythtv_version = MYTHTV_VERSION_DEFAULT;
1.209 -
1.210 - this->bytes_read = 0;
1.211 -
1.212 - this->content_size = -1;
1.213 - this->read_offset = 0;
1.214 -
1.215 - this->live_tv = FALSE;
1.216 -
1.217 - this->user_agent = g_strdup ("mythtvsrc");
1.218 - this->mythtv_caps = NULL;
1.219 -
1.220 - gst_base_src_set_live ( GST_BASE_SRC( this ), TRUE );
1.221 -
1.222 - gst_pad_set_event_function (GST_BASE_SRC_PAD(GST_BASE_SRC(this)),
1.223 - GST_DEBUG_FUNCPTR (gst_mythtv_src_handle_event));
1.224 -
1.225 -}
1.226 -
1.227 - static void
1.228 -gst_mythtv_src_finalize (GObject * gobject)
1.229 -{
1.230 - GstMythtvSrc *this = GST_MYTHTV_SRC (gobject);
1.231 -
1.232 - g_free (this->user_agent);
1.233 -
1.234 - if (this->mythtv_caps) {
1.235 - gst_caps_unref (this->mythtv_caps);
1.236 - this->mythtv_caps = NULL;
1.237 - }
1.238 -
1.239 - if (this->file_transfer) {
1.240 - g_object_unref (this->file_transfer);
1.241 - this->file_transfer = NULL;
1.242 - }
1.243 -
1.244 - if (this->uri_name) {
1.245 - g_free (this->uri_name);
1.246 - }
1.247 -
1.248 - if (this->user_agent) {
1.249 - g_free (this->user_agent);
1.250 - }
1.251 -
1.252 - if ( update_size_task != NULL ) {
1.253 -
1.254 - if ( GST_TASK_STATE( update_size_task ) != GST_TASK_STOPPED )
1.255 - gst_task_stop( update_size_task );
1.256 -
1.257 - gst_object_unref( update_size_task );
1.258 -
1.259 - update_size_task = NULL;
1.260 -
1.261 - }
1.262 -
1.263 - G_OBJECT_CLASS (parent_class)->finalize (gobject);
1.264 -}
1.265 -
1.266 -#if 0
1.267 - static guint
1.268 -do_seek( GstMythtvSrc *src, guint64 offset, guint size, GstBuffer *outbuf )
1.269 -{
1.270 - guint64 off_uint64 = myth_file_transfer_seek(src->file_transfer, offset, 1);
1.271 -
1.272 - g_print( "[%s] Call MythTV SEEK with offset %llu, got a new one %llu...\n", __FUNCTION__,
1.273 - offset, off_uint64 );
1.274 -
1.275 - return off_uint64;
1.276 -
1.277 -}
1.278 -#endif
1.279 -
1.280 - static guint
1.281 -do_read_request_response (GstMythtvSrc * src, guint64 offset, guint size, GstBuffer * outbuf)
1.282 -{
1.283 - guint read = 0;
1.284 - guint sizetoread = size; //GST_BUFFER_SIZE (outbuf);
1.285 -
1.286 - g_print( "[%s] Reading %d bytes...\n", __FUNCTION__, sizetoread );
1.287 -
1.288 - /* Loop sending the request:
1.289 - * Retry whilst authentication fails and we supply it. */
1.290 -
1.291 - ssize_t len = 0;
1.292 -
1.293 - //GST_OBJECT_LOCK(src);
1.294 -
1.295 - while ( sizetoread > 0 ) {
1.296 -
1.297 - len = myth_file_transfer_read( src->file_transfer,
1.298 - GST_BUFFER_DATA (outbuf) + read, sizetoread, TRUE );
1.299 -
1.300 - if ( len > 0 ) {
1.301 - read += len;
1.302 - src->read_offset += read;
1.303 - sizetoread -= len;
1.304 - } else if ( len < 0 ) {
1.305 - goto done;
1.306 - }
1.307 - else if ( len == 0 ) {
1.308 - if ( src->live_tv == FALSE )
1.309 - goto done;
1.310 - else
1.311 - goto eos;
1.312 -
1.313 - }
1.314 -
1.315 - if ( len == sizetoread )
1.316 - break;
1.317 -
1.318 - }
1.319 -
1.320 - if ( read > 0 ) {
1.321 - src->bytes_read += read;
1.322 -
1.323 - GST_BUFFER_SIZE (outbuf) = read;
1.324 - } else if ( read <= 0 || len <= 0 ) {
1.325 - if ( src->live_tv == FALSE )
1.326 - goto eos;
1.327 - else
1.328 - goto done;
1.329 - }
1.330 - //GST_BUFFER_OFFSET (outbuf) = src->read_offset;
1.331 -
1.332 - g_print( "[%s]\tBYTES READ (actual) = %d, BYTES READ (cumulative) = %llu, "\
1.333 - "OFFSET = %llu, CONTENT SIZE = %llu.\n", __FUNCTION__, read, src->bytes_read,
1.334 - src->read_offset, src->content_size );
1.335 -
1.336 - //GST_OBJECT_UNLOCK(src);
1.337 -
1.338 - if ( len < 0 ) {
1.339 - read = len;
1.340 - if ( src->live_tv == FALSE )
1.341 - goto eos;
1.342 - else
1.343 - goto done;
1.344 - }
1.345 -
1.346 - if ( src->bytes_read < src->content_size )
1.347 - goto done;
1.348 -
1.349 -eos:
1.350 - //GST_OBJECT_UNLOCK(src);
1.351 -
1.352 - src->eos = TRUE;
1.353 -done:
1.354 - //GST_OBJECT_UNLOCK(src);
1.355 -
1.356 - return read;
1.357 -}
1.358 -
1.359 - static GstFlowReturn
1.360 -gst_mythtv_src_create ( GstBaseSrc * psrc, guint64 offset,
1.361 - guint size, GstBuffer **outbuf )
1.362 -{
1.363 - GstMythtvSrc *src;
1.364 - GstFlowReturn ret = GST_FLOW_OK;
1.365 - guint read = 0;
1.366 -
1.367 - src = GST_MYTHTV_SRC (psrc);
1.368 -
1.369 - //src->do_start = FALSE;
1.370 - src->do_start = FALSE;
1.371 - gst_task_join ( update_size_task );
1.372 -
1.373 - g_print( "[%s]\tBUFFER OFFSET = %llu, BUFFER SIZE = %d.\n", __FUNCTION__, offset,
1.374 - size );
1.375 -
1.376 - /* The caller should know the number of bytes and not read beyond EOS. */
1.377 - //if (G_UNLIKELY (src->eos))
1.378 - // goto eos;
1.379 - //g_static_rec_mutex_lock( &update_size_mutex );
1.380 -
1.381 - /* Create the buffer. */
1.382 - ret = gst_pad_alloc_buffer ( GST_BASE_SRC_PAD (GST_BASE_SRC (psrc)),
1.383 - // GST_BUFFER_OFFSET_NONE, GST_BASE_SRC (psrc)->blocksize,
1.384 - offset, size,
1.385 - src->mythtv_caps ? src->mythtv_caps :
1.386 - GST_PAD_CAPS (GST_BASE_SRC_PAD (GST_BASE_SRC (psrc))), outbuf );
1.387 -
1.388 - //if (G_UNLIKELY (ret == GST_FLOW_UNEXPECTED))
1.389 - // goto eos;
1.390 -
1.391 - if (G_UNLIKELY (ret != GST_FLOW_OK))
1.392 - goto eos;
1.393 -
1.394 - if (G_UNLIKELY (ret == GST_FLOW_ERROR))
1.395 - goto read_error;
1.396 -
1.397 - read = do_read_request_response ( src, offset, size, *outbuf );
1.398 -
1.399 - //g_static_rec_mutex_unlock( &update_size_mutex );
1.400 -
1.401 - src->do_start = TRUE;
1.402 - gst_task_start ( update_size_task );
1.403 -
1.404 -#if 0
1.405 - g_static_rec_mutex_lock( &update_size_mutex );
1.406 - src->do_start = FALSE;
1.407 - g_static_rec_mutex_unlock( &update_size_mutex );
1.408 - GST_TASK_SIGNAL( update_size_task );
1.409 -#endif
1.410 -
1.411 - //g_static_rec_mutex_unlock( &update_size_mutex );
1.412 -
1.413 -#if 0
1.414 -#if ENABLE_TIMING_POSITION == 1
1.415 - guint64 size_tmp = 0;
1.416 - if (src->live_tv == TRUE) {
1.417 - //g_usleep( 1000 );
1.418 -get_file_pos:
1.419 - //g_usleep( 100 );
1.420 - size_tmp = myth_file_transfer_get_file_position( src->file_transfer );
1.421 - if ( size_tmp > ( src->content_size + MYTHTV_TRANSFER_MAX_BUFFER ) )
1.422 - src->content_size = size_tmp;
1.423 - else
1.424 - goto get_file_pos;
1.425 - g_print( "\t[%s]\tGET_POSITION: file_position = %llu\n",
1.426 - __FUNCTION__, size_tmp);
1.427 -
1.428 - }
1.429 -#endif
1.430 -#endif
1.431 -
1.432 - //if (G_UNLIKELY (read < 0))
1.433 - // goto read_error;
1.434 -
1.435 - if (G_UNLIKELY(src->eos))
1.436 - goto eos;
1.437 - else
1.438 - goto done;
1.439 -
1.440 -done:
1.441 - return ret;
1.442 -eos:
1.443 -#if 0
1.444 -#if ENABLE_TIMING_POSITION == 1
1.445 - if ( src->live_tv == TRUE ) {
1.446 - //g_usleep( 1000 );
1.447 - guint64 size_tmp = 0;
1.448 -get_file_pos_eos:
1.449 - //g_usleep( 100 );
1.450 - size_tmp = myth_file_transfer_get_file_position( src->file_transfer );
1.451 - if ( size_tmp > ( src->content_size + MYTHTV_TRANSFER_MAX_BUFFER ) )
1.452 - src->content_size = size_tmp;
1.453 - else
1.454 - goto get_file_pos_eos;
1.455 - g_print( "\t[%s]\tGET_POSITION: file_position = %llu\n",
1.456 - __FUNCTION__, size_tmp);
1.457 - goto done;
1.458 - } else
1.459 -#endif
1.460 -#endif
1.461 - {
1.462 - GST_DEBUG_OBJECT (src, "EOS reached");
1.463 - return GST_FLOW_UNEXPECTED;
1.464 - }
1.465 - /* ERRORS */
1.466 -read_error:
1.467 - {
1.468 - GST_ELEMENT_ERROR (src, RESOURCE, READ,
1.469 - (NULL), ("Could not read any bytes (%i, %s)", read,
1.470 - src->uri_name));
1.471 - return GST_FLOW_ERROR;
1.472 - }
1.473 - #if 0
1.474 -need_pause:
1.475 - {
1.476 - const gchar *reason = gst_flow_get_name (ret);
1.477 -
1.478 - GST_DEBUG_OBJECT (src, "pausing task, reason %s", reason);
1.479 - return GST_FLOW_UNEXPECTED;
1.480 - }
1.481 - #endif
1.482 -
1.483 -}
1.484 -
1.485 -#if 0
1.486 -/* The following two charset mangling functions were copied from gnomevfssrc.
1.487 - * Preserve them under the unverified assumption that they do something vaguely
1.488 - * worthwhile.
1.489 - */
1.490 - static char *
1.491 -unicodify (const char *str, int len, ...)
1.492 -{
1.493 - char *ret = NULL, *cset;
1.494 - va_list args;
1.495 - gsize bytes_read, bytes_written;
1.496 -
1.497 - if (g_utf8_validate (str, len, NULL))
1.498 - return g_strndup (str, len >= 0 ? len : strlen (str));
1.499 -
1.500 - va_start (args, len);
1.501 - while ((cset = va_arg (args, char *)) != NULL)
1.502 - {
1.503 - if (!strcmp (cset, "locale"))
1.504 - ret = g_locale_to_utf8 (str, len, &bytes_read, &bytes_written, NULL);
1.505 - else
1.506 - ret = g_convert (str, len, "UTF-8", cset,
1.507 - &bytes_read, &bytes_written, NULL);
1.508 - if (ret)
1.509 - break;
1.510 - }
1.511 - va_end (args);
1.512 -
1.513 - return ret;
1.514 -}
1.515 -
1.516 - static char *
1.517 -gst_mythtv_src_unicodify (const char *str)
1.518 -{
1.519 - return unicodify (str, -1, "locale", "ISO-8859-1", NULL);
1.520 -}
1.521 -#endif
1.522 -
1.523 -void
1.524 -update_size_func( void *mythtv_data )
1.525 -{
1.526 - GstMythtvSrc *src;
1.527 -
1.528 - g_return_if_fail( mythtv_data != NULL );
1.529 -
1.530 - src = GST_MYTHTV_SRC ( mythtv_data );
1.531 - if ( src->do_start ) {
1.532 - #if ENABLE_TIMING_POSITION == 1
1.533 - guint64 size_tmp = 0;
1.534 - if (src->live_tv == TRUE) {
1.535 -get_file_pos:
1.536 - //g_usleep( 50 );
1.537 - size_tmp = myth_file_transfer_get_file_position( src->file_transfer );
1.538 - if ( size_tmp > ( src->content_size + MYTHTV_TRANSFER_MAX_BUFFER ) )
1.539 - src->content_size = size_tmp;
1.540 - else
1.541 - goto get_file_pos;
1.542 - g_print( "\t[%s]\tGET_POSITION: file_position = %llu\n",
1.543 - __FUNCTION__, size_tmp );
1.544 - }
1.545 -#endif
1.546 -}
1.547 - gst_task_pause( update_size_task );
1.548 - // src->do_start = FALSE;
1.549 - //GST_TASK_SIGNAL( update_size_task );
1.550 -
1.551 -}
1.552 -
1.553 -/* create a socket for connecting to remote server */
1.554 - static gboolean
1.555 -gst_mythtv_src_start ( GstBaseSrc * bsrc )
1.556 -{
1.557 - GstMythtvSrc *src = GST_MYTHTV_SRC (bsrc);
1.558 -
1.559 - GString *chain_id_local = NULL;
1.560 -
1.561 - gboolean ret = TRUE;
1.562 -#if 0
1.563 - if (src->live_tv == TRUE && src->file_transfer != NULL) {
1.564 - guint64 size_tmp = myth_file_transfer_get_file_position( src->file_transfer );
1.565 - if (size_tmp > src->content_size)
1.566 - src->content_size = size_tmp;
1.567 - g_print( "\t[%s]\tGET_POSITION: file_position = %llu\n",
1.568 - __FUNCTION__, size_tmp);
1.569 - }
1.570 -#endif
1.571 - if (src->unique_setup == FALSE) {
1.572 - src->unique_setup = TRUE;
1.573 - } else {
1.574 - goto done;
1.575 - }
1.576 -
1.577 - //GST_OBJECT_LOCK(src);
1.578 -
1.579 - if ( src->live_tv ) {
1.580 - src->spawn_livetv = myth_livetv_new( );
1.581 - if ( myth_livetv_setup( src->spawn_livetv ) == FALSE ) {
1.582 - ret = FALSE;
1.583 - goto init_failed;
1.584 - }
1.585 - /* set up the uri variable */
1.586 - src->uri_name = g_strdup( src->spawn_livetv->proginfo->pathname->str );
1.587 - chain_id_local = gmyth_tvchain_get_id( src->spawn_livetv->tvchain );
1.588 - if ( chain_id_local != NULL ) {
1.589 - src->live_chain_id = g_strdup( chain_id_local->str );
1.590 - g_print( "\t[%s]\tLocal chain ID = %s.\n", __FUNCTION__, src->live_chain_id );
1.591 - }
1.592 - src->live_tv_id = src->spawn_livetv->remote_encoder->recorder_num;
1.593 - g_print ( "[%s] LiveTV id = %d, URI path = %s.\n", __FUNCTION__, src->live_tv_id, src->uri_name );
1.594 - }
1.595 -
1.596 - src->file_transfer = myth_file_transfer_new( src->live_tv_id,
1.597 - g_string_new( src->uri_name ), -1, src->mythtv_version );
1.598 -
1.599 - if ( src->file_transfer == NULL ) {
1.600 - //GST_OBJECT_UNLOCK(src);
1.601 -
1.602 - goto init_failed;
1.603 - }
1.604 -
1.605 - if ( src->live_tv ) {
1.606 - g_print ( "[%s] GST MYTHTVSRC: live_chain_id = %s\n", __FUNCTION__, src->live_chain_id );
1.607 - /* sets the MythSocket to the FileTransfer */
1.608 - //ret = myth_file_transfer_livetv_setup( &(src->file_transfer), src->spawn_livetv->remote_encoder->myth_socket );
1.609 - }
1.610 - /* sets the Playback monitor connection */
1.611 - ret = myth_file_transfer_playback_setup( &(src->file_transfer), src->live_tv );
1.612 -
1.613 - if ( src->live_tv == TRUE && ret == TRUE ) {
1.614 - /* loop finished, set the max tries variable to zero again... */
1.615 - wait_to_transfer = 0;
1.616 -
1.617 - while ( wait_to_transfer++ < MYTHTV_TRANSFER_MAX_WAITS && ( myth_file_transfer_is_recording( src->file_transfer ) == FALSE
1.618 - /*|| ( myth_file_transfer_get_file_position( src->file_transfer ) < ( src->content_size + 327680 ) )*/ ) )
1.619 - g_usleep( 100 );
1.620 - }
1.621 -
1.622 - /* sets the FileTransfer instance connection (video/audio download) */
1.623 - ret = myth_file_transfer_setup( &(src->file_transfer), src->live_tv );
1.624 -
1.625 - if ( ret == FALSE ) {
1.626 - //GST_OBJECT_UNLOCK(src);
1.627 -#ifndef GST_DISABLE_GST_DEBUG
1.628 - if ( src->mythtv_msgs_dbg )
1.629 - g_printerr( "MythTV FileTransfer request failed when setting up socket connection!\n" );
1.630 -#endif
1.631 - goto begin_req_failed;
1.632 - }
1.633 -
1.634 - src->content_size = src->file_transfer->filesize;
1.635 -
1.636 - //GST_OBJECT_UNLOCK(src);
1.637 -
1.638 - update_size_task = gst_task_create( update_size_func, src );
1.639 -
1.640 - gst_task_set_lock( update_size_task, &update_size_mutex );
1.641 -
1.642 - g_print( "[%s] Update Size task = %s\n", __FUNCTION__, gst_task_start( update_size_task ) &&
1.643 - GST_TASK_STATE( update_size_task ) == GST_TASK_STARTED ? "OK !" : "ERROR!!!" );
1.644 -
1.645 - src->do_start = TRUE;
1.646 -
1.647 -#if 0
1.648 - const char *str_value;
1.649 - gint gint_value;
1.650 -
1.651 - str_value = ne_get_response_header (src->request, "myth-metaint");
1.652 - if (str_value) {
1.653 - if ( sscanf (str_value, "%d", &gint_value) == 1 ) {
1.654 - if (src->myth_caps) {
1.655 - gst_caps_unref (src->myth_caps);
1.656 - src->myth_caps = NULL;
1.657 - }
1.658 - src->myth_metaint = gint_value;
1.659 -#endif
1.660 - //src->mythtv_caps = gst_caps_new_simple ("application/x-gst_ff-nuv", NULL);
1.661 - // }
1.662 - // }
1.663 -done:
1.664 - return TRUE;
1.665 -
1.666 - /* ERRORS */
1.667 -init_failed:
1.668 - {
1.669 - if (src->spawn_livetv != NULL )
1.670 - g_object_unref( src->spawn_livetv );
1.671 -
1.672 - GST_ELEMENT_ERROR (src, LIBRARY, INIT,
1.673 - (NULL), ("Could not initialize MythTV library (%i, %s)", ret, src->uri_name));
1.674 - return FALSE;
1.675 - }
1.676 -begin_req_failed:
1.677 - {
1.678 - GST_ELEMENT_ERROR (src, LIBRARY, INIT,
1.679 - (NULL), ("Could not begin request sent to MythTV server (%i, %s)", ret, src->uri_name));
1.680 - return FALSE;
1.681 - }
1.682 -}
1.683 -
1.684 -#if 0
1.685 -static gboolean
1.686 -gst_mythtv_src_get_size (GstBaseSrc * bsrc, guint64 * size)
1.687 -{
1.688 - GstMythtvSrc *src;
1.689 - gboolean ret = FALSE;
1.690 -
1.691 - src = GST_MYTHTV_SRC (bsrc);
1.692 -
1.693 - g_static_rec_mutex_lock( &update_size_mutex );
1.694 - src->do_start = FALSE;
1.695 - g_static_rec_mutex_unlock( &update_size_mutex );
1.696 - GST_TASK_SIGNAL( update_size_task );
1.697 -
1.698 -
1.699 - while (1) {
1.700 -
1.701 - g_static_rec_mutex_lock( &update_size_mutex );
1.702 - if ( !src->do_start ) {
1.703 -
1.704 - g_print( "[%s] GET SIZE: do_start? == %s\n", __FUNCTION__, src->do_start ? "YES" : "NO" );
1.705 -
1.706 - GST_TASK_WAIT( update_size_task );
1.707 - } else {
1.708 - if (src->content_size <= 0) {
1.709 - g_static_rec_mutex_unlock( &update_size_mutex );
1.710 - goto done;
1.711 - }
1.712 -
1.713 - *size = src->content_size;
1.714 - src->do_start = FALSE;
1.715 -
1.716 - g_static_rec_mutex_unlock( &update_size_mutex );
1.717 -
1.718 - break;
1.719 - }
1.720 - g_static_rec_mutex_unlock( &update_size_mutex );
1.721 -
1.722 - } // while (1)
1.723 -
1.724 -done:
1.725 - return ret;
1.726 -
1.727 -}
1.728 -#endif
1.729 -
1.730 -static gboolean
1.731 -gst_mythtv_src_get_size (GstBaseSrc * bsrc, guint64 * size)
1.732 -{
1.733 - GstMythtvSrc *src;
1.734 - gboolean ret = TRUE;
1.735 -
1.736 - src = GST_MYTHTV_SRC (bsrc);
1.737 -
1.738 - if (src->content_size <= 0)
1.739 - ret= FALSE;
1.740 -
1.741 - *size = src->content_size;
1.742 -
1.743 - return ret;
1.744 -
1.745 -}
1.746 -/* close the socket and associated resources
1.747 - * used both to recover from errors and go to NULL state */
1.748 - static gboolean
1.749 -gst_mythtv_src_stop (GstBaseSrc * bsrc)
1.750 -{
1.751 - GstMythtvSrc *src;
1.752 -
1.753 - src = GST_MYTHTV_SRC (bsrc);
1.754 -
1.755 - if (src->uri_name) {
1.756 - g_free (src->uri_name);
1.757 - src->uri_name = NULL;
1.758 - }
1.759 -
1.760 - if (src->mythtv_caps) {
1.761 - gst_caps_unref (src->mythtv_caps);
1.762 - src->mythtv_caps = NULL;
1.763 - }
1.764 -
1.765 - src->eos = FALSE;
1.766 -
1.767 - return TRUE;
1.768 -}
1.769 -
1.770 - static gboolean
1.771 -gst_mythtv_src_handle_event (GstPad * pad, GstEvent * event)
1.772 -{
1.773 - GstMythtvSrc *src = GST_MYTHTV_SRC (GST_PAD_PARENT (pad));
1.774 -
1.775 - switch (GST_EVENT_TYPE (event)) {
1.776 - case GST_EVENT_FLUSH_START:
1.777 - src->eos = FALSE;
1.778 - break;
1.779 - //return TRUE;
1.780 -#if 0
1.781 -case GST_EVENT_FLUSH_STOP:
1.782 - src->do_start = TRUE;
1.783 - src->eos = FALSE;
1.784 - gst_element_set_state (GST_ELEMENT(src), GST_STATE_NULL);
1.785 - //gst_element_set_locked_state (GST_ELEMENT(src), TRUE);
1.786 - break;
1.787 -#endif
1.788 - case GST_EVENT_SEEK:
1.789 - {
1.790 - gdouble rate;
1.791 - //gboolean update = TRUE;
1.792 - GstFormat format;
1.793 - GstSeekType cur_type, stop_type;
1.794 - GstSeekFlags flags;
1.795 - gint64 cur = 0, stop = 0;
1.796 - gst_event_parse_seek ( event, &rate, &format,
1.797 - &flags, &cur_type, &cur,
1.798 - &stop_type, &stop );
1.799 -
1.800 - g_print( "[%s] Got EVENT_SEEK.\n", __FUNCTION__ );
1.801 - if ( !( flags & GST_SEEK_FLAG_FLUSH ) ) {
1.802 - g_print( "[%s] Could get the FLAG_FLUSH message.\n", __FUNCTION__ );
1.803 - }
1.804 - //gboolean ret = gst_event_parse_new_segment ( event,
1.805 - // &update, &rate, &format, &start, &stop,
1.806 - // &position );
1.807 - //GstFlowReturn flow_ret = gst_mythtv_src_create (GST_BASE_SRC( GST_PAD_PARENT( psrc ) ),
1.808 - // cur, stop - cur + 1, GstBuffer)
1.809 -
1.810 - }
1.811 - default:
1.812 - return gst_pad_event_default (pad, event);
1.813 - }
1.814 -
1.815 - return gst_pad_event_default (pad, event);
1.816 -}
1.817 -
1.818 - static gboolean
1.819 -gst_mythtv_src_is_seekable( GstBaseSrc *base_src )
1.820 -{
1.821 - return TRUE;
1.822 -}
1.823 -
1.824 - static void
1.825 -gst_mythtv_src_set_property (GObject * object, guint prop_id,
1.826 - const GValue * value, GParamSpec * pspec)
1.827 -{
1.828 - GstMythtvSrc *mythtvsrc = GST_MYTHTV_SRC (object);
1.829 -
1.830 - GST_OBJECT_LOCK (mythtvsrc);
1.831 - switch (prop_id) {
1.832 - case PROP_URI:
1.833 - case PROP_LOCATION:
1.834 - {
1.835 - if (!g_value_get_string (value)) {
1.836 - GST_WARNING ("location property cannot be NULL");
1.837 - goto done;
1.838 - }
1.839 -
1.840 - if (mythtvsrc->uri_name != NULL) {
1.841 - g_free (mythtvsrc->uri_name);
1.842 - mythtvsrc->uri_name = NULL;
1.843 - }
1.844 - mythtvsrc->uri_name = g_value_dup_string (value);
1.845 -
1.846 - break;
1.847 - }
1.848 -#ifndef GST_DISABLE_GST_DEBUG
1.849 - case PROP_MYTHTV_DBG:
1.850 - {
1.851 - mythtvsrc->mythtv_msgs_dbg = g_value_get_boolean (value);
1.852 - break;
1.853 - }
1.854 -#endif
1.855 - case PROP_MYTHTV_VERSION:
1.856 - {
1.857 - mythtvsrc->mythtv_version = g_value_get_int (value);
1.858 - break;
1.859 - }
1.860 - case PROP_MYTHTV_LIVEID:
1.861 - {
1.862 - mythtvsrc->live_tv_id = g_value_get_int (value);
1.863 - break;
1.864 - }
1.865 - case PROP_MYTHTV_LIVE:
1.866 - {
1.867 - mythtvsrc->live_tv = g_value_get_boolean (value);
1.868 - break;
1.869 - }
1.870 - case PROP_MYTHTV_LIVE_CHAINID:
1.871 - {
1.872 - if (!g_value_get_string (value)) {
1.873 - GST_WARNING ("MythTV Live chainid property cannot be NULL");
1.874 - goto done;
1.875 - }
1.876 -
1.877 - if (mythtvsrc->live_chain_id != NULL) {
1.878 - g_free (mythtvsrc->live_chain_id);
1.879 - mythtvsrc->live_chain_id = NULL;
1.880 - }
1.881 - mythtvsrc->live_chain_id = g_value_dup_string (value);
1.882 -
1.883 - break;
1.884 - }
1.885 -
1.886 - default:
1.887 - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1.888 - break;
1.889 - }
1.890 - GST_OBJECT_UNLOCK (mythtvsrc);
1.891 -done:
1.892 - return;
1.893 -}
1.894 -
1.895 - static void
1.896 -gst_mythtv_src_get_property (GObject * object, guint prop_id,
1.897 - GValue * value, GParamSpec * pspec)
1.898 -{
1.899 - GstMythtvSrc *mythtvsrc = GST_MYTHTV_SRC (object);
1.900 -
1.901 - GST_OBJECT_LOCK (mythtvsrc);
1.902 - switch (prop_id) {
1.903 - case PROP_URI:
1.904 - case PROP_LOCATION:
1.905 - {
1.906 - gchar *str = g_strdup( "" );
1.907 -
1.908 - if ( mythtvsrc->uri_name == NULL ) {
1.909 - g_free (mythtvsrc->uri_name);
1.910 - mythtvsrc->uri_name = NULL;
1.911 - } else {
1.912 - str = g_strdup( mythtvsrc->uri_name );
1.913 - }
1.914 - g_value_set_string ( value, str );
1.915 - break;
1.916 - }
1.917 -#ifndef GST_DISABLE_GST_DEBUG
1.918 - case PROP_MYTHTV_DBG:
1.919 - g_value_set_boolean ( value, mythtvsrc->mythtv_msgs_dbg );
1.920 - break;
1.921 -#endif
1.922 - case PROP_MYTHTV_VERSION:
1.923 - {
1.924 - g_value_set_int ( value, mythtvsrc->mythtv_version );
1.925 - break;
1.926 - }
1.927 - case PROP_MYTHTV_LIVEID:
1.928 - {
1.929 - g_value_set_int ( value, mythtvsrc->live_tv_id );
1.930 - break;
1.931 - }
1.932 - case PROP_MYTHTV_LIVE:
1.933 - g_value_set_boolean ( value, mythtvsrc->live_tv );
1.934 - break;
1.935 - case PROP_MYTHTV_LIVE_CHAINID:
1.936 - {
1.937 - gchar *str = g_strdup( "" );
1.938 -
1.939 - if ( mythtvsrc->live_chain_id == NULL ) {
1.940 - g_free (mythtvsrc->live_chain_id);
1.941 - mythtvsrc->live_chain_id = NULL;
1.942 - } else {
1.943 - str = g_strdup( mythtvsrc->live_chain_id );
1.944 - }
1.945 - g_value_set_string ( value, str );
1.946 - break;
1.947 - }
1.948 - default:
1.949 - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1.950 - break;
1.951 - }
1.952 - GST_OBJECT_UNLOCK (mythtvsrc);
1.953 -}
1.954 -
1.955 -/* entry point to initialize the plug-in
1.956 - * initialize the plug-in itself
1.957 - * register the element factories and pad templates
1.958 - * register the features
1.959 - */
1.960 - static gboolean
1.961 -plugin_init (GstPlugin * plugin)
1.962 -{
1.963 - return gst_element_register (plugin, "mythtvsrc", GST_RANK_NONE,
1.964 - GST_TYPE_MYTHTV_SRC);
1.965 -}
1.966 -
1.967 -/* this is the structure that gst-register looks for
1.968 - * so keep the name plugin_desc, or you cannot get your plug-in registered */
1.969 -GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
1.970 - GST_VERSION_MINOR,
1.971 - "mythtv",
1.972 - "lib MythTV src",
1.973 - plugin_init, VERSION, "LGPL", "GStreamer", "http://gstreamer.net/")
1.974 -
1.975 -
1.976 -/*** GSTURIHANDLER INTERFACE *************************************************/
1.977 - static guint
1.978 -gst_mythtv_src_uri_get_type (void)
1.979 -{
1.980 - return GST_URI_SRC;
1.981 -}
1.982 -
1.983 - static gchar **
1.984 -gst_mythtv_src_uri_get_protocols (void)
1.985 -{
1.986 - static gchar *protocols[] = { "myth", "myths", NULL };
1.987 -
1.988 - return protocols;
1.989 -}
1.990 -
1.991 - static const gchar *
1.992 -gst_mythtv_src_uri_get_uri (GstURIHandler * handler)
1.993 -{
1.994 - GstMythtvSrc *src = GST_MYTHTV_SRC (handler);
1.995 -
1.996 - return src->uri_name;
1.997 -}
1.998 -
1.999 - static gboolean
1.1000 -gst_mythtv_src_uri_set_uri (GstURIHandler * handler, const gchar * uri)
1.1001 -{
1.1002 - GstMythtvSrc *src = GST_MYTHTV_SRC (handler);
1.1003 -
1.1004 - gchar *protocol;
1.1005 -
1.1006 - protocol = gst_uri_get_protocol (uri);
1.1007 - if ((strcmp (protocol, "myth") != 0) && (strcmp (protocol, "myths") != 0)) {
1.1008 - g_free (protocol);
1.1009 - return FALSE;
1.1010 - }
1.1011 - g_free (protocol);
1.1012 - g_object_set (src, "location", uri, NULL);
1.1013 -
1.1014 - return TRUE;
1.1015 -}
1.1016 -
1.1017 - static void
1.1018 -gst_mythtv_src_uri_handler_init (gpointer g_iface, gpointer iface_data)
1.1019 -{
1.1020 - GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface;
1.1021 -
1.1022 - iface->get_type = gst_mythtv_src_uri_get_type;
1.1023 - iface->get_protocols = gst_mythtv_src_uri_get_protocols;
1.1024 - iface->get_uri = gst_mythtv_src_uri_get_uri;
1.1025 - iface->set_uri = gst_mythtv_src_uri_set_uri;
1.1026 -}
1.1027 -
1.1028 - void
1.1029 -size_header_handler (void *userdata, const char *value)
1.1030 -{
1.1031 - GstMythtvSrc *src = GST_MYTHTV_SRC (userdata);
1.1032 -
1.1033 - //src->content_size = g_ascii_strtoull (value, NULL, 10);
1.1034 -
1.1035 - GST_DEBUG_OBJECT (src, "content size = %lld bytes", src->content_size);
1.1036 -}