1.1 --- a/gst-plugins-mythtv/src/gstmythtvsrc.c Tue May 01 17:22:20 2007 +0100
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,1259 +0,0 @@
1.4 -/* GStreamer MythTV Plug-in
1.5 - * Copyright (C) <2006> Rosfran Borges <rosfran.borges@indt.org.br>
1.6 - *
1.7 - * This library is free software; you can redistribute it and/or
1.8 - * modify it under the terms of the GNU Library General Public
1.9 - * License as published by the Free Software Foundation; either
1.10 - * version 2 of the License, or (at your option) any later version.
1.11 - *
1.12 - * This library is distributed in the hope that it will be useful,
1.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1.15 - * Library General Public License for more details.
1.16 - *
1.17 - * You should have received a copy of the GNU Library General Public
1.18 - * License along with this library; if not, write to the
1.19 - * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
1.20 - * Boston, MA 02111-1307, USA.
1.21 - */
1.22 -/**
1.23 - * SECTION:element-mythtvsrc
1.24 - *
1.25 - * <refsect2>
1.26 - * <para>
1.27 - * MythTVSrc allows to access a remote MythTV backend streaming Video/Audio server,
1.28 - * and to render audio and video content through a TCP/IP connection to a specific
1.29 - * port on this server, and based on a known MythTV protocol that is based on
1.30 - * some message passing, such as REQUEST_BLOCK on a specified number of bytes, to get
1.31 - * some chunk of remote file data.
1.32 - * You should pass the information aboute the remote MythTV backend server
1.33 - * through the <link linkend="GstMythTVSrc--location">location</link> property.
1.34 - * </para>
1.35 - * <title>Examples</title>
1.36 - * <para>
1.37 - * If you want to get the LiveTV content (set channel, TV tuner, RemoteEncoder,
1.38 - * Recorder),
1.39 - * put the following URI:
1.40 - *
1.41 - * <programlisting>
1.42 - * myth://xxx.xxx.xxx.xxx:6543/livetv?channel=BBC
1.43 - * </programlisting>
1.44 - *
1.45 - * This URI will say to the gmyth library to configure the Recorder instance (used to
1.46 - * change the channel, start the TV multimedia content transmition, etc.), using
1.47 - * the IP address (xxx.xxx.xxx.xxx) and port number (6543) of the MythTV backend
1.48 - * server, and setting the channel name to "BBC".
1.49 - *
1.50 - * To get a already recorded the MythTV NUV file, put the following URI:
1.51 - *
1.52 - * <programlisting>
1.53 - * myth://xxx.xxx.xxx.xxx:6543/filename.nuv
1.54 - * </programlisting>
1.55 - *
1.56 - * This URI will say to the gmyth library to configure the Recorder instance (used to
1.57 - * change the channel, start the TV multimedia content transmition, etc.), using
1.58 - * the IP address (xxx.xxx.xxx.xxx) and port number (6543) of the MythTV backend
1.59 - * server, and setting the channel name to "BBC".
1.60 - *
1.61 - * Another possible way to use the LiveTV content, and just in the case you want to
1.62 - * use the mysql database, put the location URI in the following format:
1.63 - *
1.64 - * <programlisting>
1.65 - * myth://mythtv:mythtv@xxx.xxx.xxx.xxx:6543/?mythconverg&channel=9
1.66 - * </programlisting>
1.67 - *
1.68 - * Where the first field is the protocol (myth), the second and third are user
1.69 - * name (mythtv) and password (mythtv), then backend host name and port number,
1.70 - * and the last field is the database name (mythconverg).
1.71 - * </para>
1.72 - * </refsect2>
1.73 - */
1.74 -#ifdef HAVE_CONFIG_H
1.75 -#include "config.h"
1.76 -#endif
1.77 -
1.78 -#include "gstmythtvsrc.h"
1.79 -#include <gmyth/gmyth_file.h>
1.80 -#include <gmyth/gmyth_file_transfer.h>
1.81 -#include <gmyth/gmyth_file_local.h>
1.82 -#include <gmyth/gmyth_livetv.h>
1.83 -
1.84 -#include <gmyth/gmyth_socket.h>
1.85 -#include <gmyth/gmyth_tvchain.h>
1.86 -
1.87 -#include <string.h>
1.88 -#include <unistd.h>
1.89 -
1.90 -GST_DEBUG_CATEGORY_STATIC (mythtvsrc_debug);
1.91 -#define GST_CAT_DEFAULT mythtvsrc_debug
1.92 -
1.93 -#define GST_GMYTHTV_ID_NUM 1
1.94 -
1.95 -#define GST_GMYTHTV_CHANNEL_DEFAULT_NUM (-1)
1.96 -
1.97 -#define GMYTHTV_VERSION_DEFAULT 30
1.98 -
1.99 -#define GMYTHTV_TRANSFER_MAX_WAITS 100
1.100 -
1.101 -#define GMYTHTV_TRANSFER_MAX_RESENDS 2
1.102 -
1.103 -#define GMYTHTV_TRANSFER_MAX_BUFFER (128*1024)
1.104 -
1.105 -#define MAX_READ_SIZE (4*1024)
1.106 -
1.107 -#define GST_FLOW_ERROR_NO_DATA (-101)
1.108 -
1.109 -#define REQUEST_MAX_SIZE (64*1024)
1.110 -
1.111 -#define INTERNAL_BUFFER_SIZE (90*1024)
1.112 -
1.113 -static const GstElementDetails gst_mythtv_src_details =
1.114 -GST_ELEMENT_DETAILS ("MythTV client source",
1.115 - "Source/Network",
1.116 - "Control and receive data as a client over the network "
1.117 - "via raw socket connections using the MythTV protocol",
1.118 - "Rosfran Borges <rosfran.borges@indt.org.br>");
1.119 -
1.120 -static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
1.121 - GST_PAD_SRC,
1.122 - GST_PAD_ALWAYS,
1.123 - GST_STATIC_CAPS ("video/x-nuv"));
1.124 -
1.125 -enum
1.126 -{
1.127 - PROP_0,
1.128 - PROP_LOCATION,
1.129 -#ifndef GST_DISABLE_GST_DEBUG
1.130 - PROP_GMYTHTV_DBG,
1.131 -#endif
1.132 - PROP_GMYTHTV_VERSION,
1.133 - PROP_GMYTHTV_LIVE,
1.134 - PROP_GMYTHTV_LIVEID,
1.135 - PROP_GMYTHTV_LIVE_CHAINID,
1.136 - PROP_GMYTHTV_ENABLE_TIMING_POSITION,
1.137 - PROP_GMYTHTV_CHANNEL_NUM,
1.138 - PROP_GMYTHTV_MAX_TRY
1.139 -};
1.140 -
1.141 -static void gst_mythtv_src_clear (GstMythtvSrc *mythtv_src);
1.142 -
1.143 -static void gst_mythtv_src_finalize (GObject * gobject);
1.144 -
1.145 -static GstFlowReturn gst_mythtv_src_create (GstPushSrc * psrc,
1.146 - GstBuffer ** outbuf);
1.147 -
1.148 -static gboolean gst_mythtv_src_start (GstBaseSrc * bsrc);
1.149 -static gboolean gst_mythtv_src_stop (GstBaseSrc * bsrc);
1.150 -static gboolean gst_mythtv_src_get_size (GstBaseSrc * bsrc, guint64 * size);
1.151 -static gboolean gst_mythtv_src_is_seekable (GstBaseSrc * push_src);
1.152 -
1.153 -static gboolean gst_mythtv_src_do_seek (GstBaseSrc * base,
1.154 - GstSegment * segment);
1.155 -
1.156 -static GstStateChangeReturn
1.157 -gst_mythtv_src_change_state (GstElement * element, GstStateChange transition);
1.158 -
1.159 -static void gst_mythtv_src_set_property (GObject * object, guint prop_id,
1.160 - const GValue * value, GParamSpec * pspec);
1.161 -static void gst_mythtv_src_get_property (GObject * object, guint prop_id,
1.162 - GValue * value, GParamSpec * pspec);
1.163 -
1.164 -static void gst_mythtv_src_uri_handler_init (gpointer g_iface,
1.165 - gpointer iface_data);
1.166 -
1.167 -static gboolean gst_mythtv_src_handle_query (GstPad * pad, GstQuery * query);
1.168 -
1.169 -static gboolean gst_mythtv_src_handle_event (GstPad * pad, GstEvent * event);
1.170 -
1.171 -static GMythFileReadResult do_read_request_response (GstMythtvSrc * src, guint size,
1.172 - GByteArray * data_ptr);
1.173 -
1.174 -static void
1.175 -_urihandler_init (GType type)
1.176 -{
1.177 - static const GInterfaceInfo urihandler_info = {
1.178 - gst_mythtv_src_uri_handler_init,
1.179 - NULL,
1.180 - NULL
1.181 - };
1.182 -
1.183 - g_type_add_interface_static (type, GST_TYPE_URI_HANDLER, &urihandler_info);
1.184 -
1.185 - GST_DEBUG_CATEGORY_INIT (mythtvsrc_debug, "mythtvsrc", 0, "MythTV src");
1.186 -}
1.187 -
1.188 -GST_BOILERPLATE_FULL (GstMythtvSrc, gst_mythtv_src, GstPushSrc,
1.189 - GST_TYPE_PUSH_SRC, _urihandler_init)
1.190 -
1.191 - static void gst_mythtv_src_base_init (gpointer g_class)
1.192 -{
1.193 - GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
1.194 -
1.195 - gst_element_class_add_pad_template (element_class,
1.196 - gst_static_pad_template_get (&srctemplate));
1.197 -
1.198 - gst_element_class_set_details (element_class, &gst_mythtv_src_details);
1.199 -
1.200 - element_class->change_state = gst_mythtv_src_change_state;
1.201 -
1.202 -}
1.203 -
1.204 -static void
1.205 -gst_mythtv_src_class_init (GstMythtvSrcClass * klass)
1.206 -{
1.207 - GObjectClass *gobject_class;
1.208 - GstPushSrcClass *gstpushsrc_class;
1.209 - GstBaseSrcClass *gstbasesrc_class;
1.210 -
1.211 - gobject_class = (GObjectClass *) klass;
1.212 - gstbasesrc_class = (GstBaseSrcClass *) klass;
1.213 - gstpushsrc_class = (GstPushSrcClass *) klass;
1.214 -
1.215 - gobject_class->set_property = gst_mythtv_src_set_property;
1.216 - gobject_class->get_property = gst_mythtv_src_get_property;
1.217 - gobject_class->finalize = gst_mythtv_src_finalize;
1.218 -
1.219 - g_object_class_install_property
1.220 - (gobject_class, PROP_LOCATION,
1.221 - g_param_spec_string ("location", "Location",
1.222 - "The location. In the form:"
1.223 - "\n\t\t\tmyth://a.com/file.nuv"
1.224 - "\n\t\t\tmyth://a.com:23223/file.nuv "
1.225 - "\n\t\t\ta.com/file.nuv - default scheme 'myth'",
1.226 - "", G_PARAM_READWRITE));
1.227 -
1.228 - g_object_class_install_property
1.229 - (gobject_class, PROP_GMYTHTV_VERSION,
1.230 - g_param_spec_int ("mythtv-version", "mythtv-version",
1.231 - "Change MythTV version", 26, 30, 26, G_PARAM_READWRITE));
1.232 -
1.233 - g_object_class_install_property
1.234 - (gobject_class, PROP_GMYTHTV_LIVEID,
1.235 - g_param_spec_int ("mythtv-live-id", "mythtv-live-id",
1.236 - "Change MythTV version",
1.237 - 0, 200, GST_GMYTHTV_ID_NUM, G_PARAM_READWRITE));
1.238 -
1.239 - g_object_class_install_property
1.240 - (gobject_class, PROP_GMYTHTV_LIVE_CHAINID,
1.241 - g_param_spec_string ("mythtv-live-chainid", "mythtv-live-chainid",
1.242 - "Sets the MythTV chain ID (from TV Chain)", "", G_PARAM_READWRITE));
1.243 -
1.244 - g_object_class_install_property
1.245 - (gobject_class, PROP_GMYTHTV_LIVE,
1.246 - g_param_spec_boolean ("mythtv-live", "mythtv-live",
1.247 - "Enable MythTV Live TV content streaming", FALSE, G_PARAM_READWRITE));
1.248 -
1.249 - g_object_class_install_property
1.250 - (gobject_class, PROP_GMYTHTV_ENABLE_TIMING_POSITION,
1.251 - g_param_spec_boolean ("mythtv-enable-timing-position",
1.252 - "mythtv-enable-timing-position",
1.253 - "Enable MythTV Live TV content size continuous updating", FALSE,
1.254 - G_PARAM_READWRITE));
1.255 -
1.256 - g_object_class_install_property
1.257 - (gobject_class, PROP_GMYTHTV_CHANNEL_NUM,
1.258 - g_param_spec_string ("mythtv-channel", "mythtv-channel",
1.259 - "Change MythTV channel number",
1.260 - "", G_PARAM_READWRITE));
1.261 -
1.262 - g_object_class_install_property
1.263 - (gobject_class, PROP_GMYTHTV_MAX_TRY,
1.264 - g_param_spec_int ("max-try", "max-try",
1.265 - "Set the max try for get MythTV free recorder",
1.266 - 0, G_MAXINT, 10, G_PARAM_READWRITE));
1.267 -
1.268 -
1.269 -#ifndef GST_DISABLE_GST_DEBUG
1.270 - g_object_class_install_property
1.271 - (gobject_class, PROP_GMYTHTV_DBG,
1.272 - g_param_spec_boolean ("mythtv-debug", "mythtv-debug",
1.273 - "Enable MythTV debug messages", FALSE, G_PARAM_READWRITE));
1.274 -#endif
1.275 -
1.276 - gstbasesrc_class->start = gst_mythtv_src_start;
1.277 - gstbasesrc_class->stop = gst_mythtv_src_stop;
1.278 - gstbasesrc_class->get_size = gst_mythtv_src_get_size;
1.279 - gstbasesrc_class->is_seekable = gst_mythtv_src_is_seekable;
1.280 -
1.281 - gstbasesrc_class->do_seek = gst_mythtv_src_do_seek;
1.282 - gstpushsrc_class->create = gst_mythtv_src_create;
1.283 -
1.284 - GST_DEBUG_CATEGORY_INIT (mythtvsrc_debug, "mythtvsrc", 0,
1.285 - "MythTV Client Source");
1.286 -}
1.287 -
1.288 -static void
1.289 -gst_mythtv_src_init (GstMythtvSrc * this, GstMythtvSrcClass * g_class)
1.290 -{
1.291 - this->file = NULL;
1.292 -
1.293 - this->unique_setup = FALSE;
1.294 -
1.295 - this->mythtv_version = GMYTHTV_VERSION_DEFAULT;
1.296 -
1.297 - this->state = GST_MYTHTV_SRC_FILE_TRANSFER;
1.298 -
1.299 - this->bytes_read = 0;
1.300 -
1.301 - this->prev_content_size = 0;
1.302 -
1.303 - this->content_size = 0;
1.304 - this->read_offset = 0;
1.305 -
1.306 - this->content_size_last = 0;
1.307 -
1.308 - this->live_tv = FALSE;
1.309 -
1.310 - this->enable_timing_position = FALSE;
1.311 - this->update_prog_chain = FALSE;
1.312 -
1.313 - this->user_agent = g_strdup ("mythtvsrc");
1.314 - this->update_prog_chain = FALSE;
1.315 -
1.316 - this->channel_name = NULL;
1.317 -
1.318 - this->eos = FALSE;
1.319 -
1.320 - this->bytes_queue = NULL;
1.321 -
1.322 - this->wait_to_transfer = 0;
1.323 - this->try_number = 0;
1.324 - this->max_try = 10;
1.325 -
1.326 - gst_base_src_set_format (GST_BASE_SRC (this), GST_FORMAT_BYTES);
1.327 -
1.328 - gst_pad_set_event_function (GST_BASE_SRC_PAD (GST_BASE_SRC (this)),
1.329 - gst_mythtv_src_handle_event);
1.330 - gst_pad_set_query_function (GST_BASE_SRC_PAD (GST_BASE_SRC (this)),
1.331 - gst_mythtv_src_handle_query);
1.332 -
1.333 -}
1.334 -
1.335 -static void
1.336 -gst_mythtv_src_clear (GstMythtvSrc *mythtv_src)
1.337 -{
1.338 - mythtv_src->unique_setup = FALSE;
1.339 - mythtv_src->try_number = 0;
1.340 -
1.341 - if (mythtv_src->spawn_livetv) {
1.342 - g_object_unref (mythtv_src->spawn_livetv);
1.343 - mythtv_src->spawn_livetv = NULL;
1.344 - }
1.345 -
1.346 - if (mythtv_src->file) {
1.347 - g_object_unref (mythtv_src->file);
1.348 - mythtv_src->file = NULL;
1.349 - }
1.350 -
1.351 - if (mythtv_src->backend_info) {
1.352 - g_object_unref (mythtv_src->backend_info);
1.353 - mythtv_src->backend_info = NULL;
1.354 - }
1.355 -
1.356 - if (mythtv_src->bytes_queue) {
1.357 - g_byte_array_free (mythtv_src->bytes_queue, TRUE);
1.358 - mythtv_src->bytes_queue = NULL;
1.359 - }
1.360 -
1.361 -}
1.362 -
1.363 -static void
1.364 -gst_mythtv_src_finalize (GObject * gobject)
1.365 -{
1.366 - GstMythtvSrc *this = GST_MYTHTV_SRC (gobject);
1.367 -
1.368 - gst_mythtv_src_clear (this);
1.369 -
1.370 - if (this->uri_name) {
1.371 - g_free (this->uri_name);
1.372 - this->uri_name = NULL;
1.373 - }
1.374 -
1.375 - if (this->user_agent) {
1.376 - g_free (this->user_agent);
1.377 - this->user_agent = NULL;
1.378 - }
1.379 -
1.380 - G_OBJECT_CLASS (parent_class)->finalize (gobject);
1.381 -}
1.382 -
1.383 -static GMythFileReadResult
1.384 -do_read_request_response (GstMythtvSrc * src, guint size, GByteArray *data_ptr)
1.385 -{
1.386 - gint read = 0;
1.387 - guint sizetoread = size;
1.388 - gint max_iters = GMYTHTV_TRANSFER_MAX_RESENDS;
1.389 - GMythFileReadResult result;
1.390 -
1.391 - GST_LOG_OBJECT (src, "Starting: Reading %d bytes...", sizetoread);
1.392 -
1.393 - /* Loop sending the Myth File Transfer request:
1.394 - * Retry whilst authentication fails and we supply it. */
1.395 -
1.396 - while (sizetoread == size && --max_iters > 0) {
1.397 - /* if ( gmyth_backend_info_is_local_file(src->backend_info) ) */
1.398 - if ( IS_GMYTH_FILE_LOCAL(src->file) )
1.399 - result = gmyth_file_local_read ( GMYTH_FILE_LOCAL(src->file),
1.400 - data_ptr, sizetoread, src->live_tv);
1.401 - else if ( IS_GMYTH_FILE_TRANSFER(src->file) )
1.402 - result = gmyth_file_transfer_read ( GMYTH_FILE_TRANSFER(src->file),
1.403 - data_ptr, sizetoread, src->live_tv);
1.404 -
1.405 - if (data_ptr->len > 0) {
1.406 - read += data_ptr->len;
1.407 - sizetoread -= data_ptr->len;
1.408 - } else if (data_ptr->len < 0) {
1.409 - if (src->live_tv == FALSE) {
1.410 - result = GMYTH_FILE_READ_EOF;
1.411 - goto eos;
1.412 - } else {
1.413 - if (result == GMYTH_FILE_READ_ERROR) { /* -314 */
1.414 - GST_INFO_OBJECT (src, "[LiveTV] FileTransfer READ_ERROR!");
1.415 - goto done;
1.416 - } else if (result == GMYTH_FILE_READ_NEXT_PROG_CHAIN) { /* -315 */
1.417 - GST_INFO_OBJECT (src,
1.418 - "[LiveTV] FileTransfer - Go to the next program chain!");
1.419 - continue;
1.420 - }
1.421 - goto done;
1.422 - }
1.423 -
1.424 - } else if (data_ptr->len == 0)
1.425 - goto done;
1.426 -
1.427 - if (read == sizetoread)
1.428 - goto done;
1.429 - }
1.430 -
1.431 - if ((read < 0 && !src->live_tv) || max_iters == 0){
1.432 - result = GMYTH_FILE_READ_EOF;
1.433 - goto eos;
1.434 - }
1.435 -
1.436 - goto done;
1.437 -
1.438 -eos:
1.439 - src->eos = TRUE;
1.440 -
1.441 -done:
1.442 - return result;
1.443 -}
1.444 -
1.445 -static GstFlowReturn
1.446 -gst_mythtv_src_create (GstPushSrc * psrc, GstBuffer ** outbuf)
1.447 -{
1.448 - GstMythtvSrc *src;
1.449 - GstFlowReturn ret = GST_FLOW_OK;
1.450 - guint buffer_size_inter = 0;
1.451 -
1.452 - src = GST_MYTHTV_SRC (psrc);
1.453 -
1.454 - /* The caller should know the number of bytes and not read beyond EOS. */
1.455 - if (G_UNLIKELY (src->eos))
1.456 - goto eos;
1.457 - if (G_UNLIKELY (src->update_prog_chain))
1.458 - goto change_progchain;
1.459 -
1.460 - GST_DEBUG_OBJECT (src, "offset = %" G_GUINT64_FORMAT ", size = %d...",
1.461 - src->read_offset, MAX_READ_SIZE);
1.462 -
1.463 - GST_DEBUG_OBJECT (src, "Create: buffer_remain: %d, buffer_size = %d.",
1.464 - (gint) src->buffer_remain, src->bytes_queue->len);
1.465 -
1.466 -program_chain_changed:
1.467 - /* just get from the byte array, no network effort... */
1.468 - if ((src->buffer_remain = src->bytes_queue->len) < MAX_READ_SIZE) {
1.469 - GByteArray *buffer;
1.470 - GMythFileReadResult result = GMYTH_FILE_READ_OK;
1.471 -
1.472 - buffer = NULL;
1.473 - buffer_size_inter = (INTERNAL_BUFFER_SIZE - src->buffer_remain);
1.474 -
1.475 - if (buffer_size_inter > REQUEST_MAX_SIZE)
1.476 - buffer_size_inter = REQUEST_MAX_SIZE;
1.477 -
1.478 - buffer = g_byte_array_new ();
1.479 -
1.480 - result = do_read_request_response (src, buffer_size_inter, buffer);
1.481 -
1.482 - if (G_UNLIKELY (buffer->len < 0)) {
1.483 -
1.484 - if (buffer != NULL) {
1.485 - g_byte_array_free (buffer, TRUE);
1.486 - buffer = NULL;
1.487 - }
1.488 -
1.489 - if (src->live_tv || ( result == GMYTH_FILE_READ_NEXT_PROG_CHAIN ))
1.490 - goto change_progchain;
1.491 - else
1.492 - goto read_error;
1.493 - } else if (G_UNLIKELY (read == 0)) {
1.494 -
1.495 - if (buffer != NULL) {
1.496 - g_byte_array_free (buffer, TRUE);
1.497 - buffer = NULL;
1.498 - }
1.499 -
1.500 - if (!src->live_tv)
1.501 - goto done;
1.502 - else
1.503 - goto program_chain_changed;
1.504 - }
1.505 -
1.506 - if (G_UNLIKELY (src->update_prog_chain))
1.507 - {
1.508 - if (buffer != NULL) {
1.509 - g_byte_array_free (buffer, TRUE);
1.510 - buffer = NULL;
1.511 - }
1.512 - goto change_progchain;
1.513 - }
1.514 -
1.515 - src->bytes_queue =
1.516 - g_byte_array_append (src->bytes_queue, buffer->data, buffer->len);
1.517 - if (buffer->len > buffer_size_inter)
1.518 - GST_WARNING_OBJECT (src,
1.519 - "INCREASED buffer size! Backend sent more than we ask him... (%d)",
1.520 - abs (buffer->len - buffer_size_inter));
1.521 -
1.522 - src->buffer_remain += buffer->len;
1.523 -
1.524 - if (buffer != NULL) {
1.525 - g_byte_array_free (buffer, TRUE);
1.526 - buffer = NULL;
1.527 - }
1.528 -
1.529 - GST_DEBUG_OBJECT (src,
1.530 - "BYTES READ (actual) = %d, BYTES READ (cumulative) = %llu, "
1.531 - "OFFSET = %llu, CONTENT SIZE = %llu.", read,
1.532 - src->bytes_read, src->read_offset, src->content_size);
1.533 -
1.534 - }
1.535 -
1.536 - guint buffer_size =
1.537 - (src->buffer_remain < MAX_READ_SIZE) ? src->buffer_remain : MAX_READ_SIZE;
1.538 -
1.539 - *outbuf = gst_buffer_new ();
1.540 -
1.541 - /* gets the first buffer_size bytes from the byte array buffer variable */
1.542 - /* guint8 *buf = g_memdup( src->bytes_queue->data, buffer_size ); */
1.543 -
1.544 - GST_DEBUG_OBJECT (src, "read from network? %s!, buffer_remain = %d",
1.545 - (buffer_size_inter ==
1.546 - 0) ? "NO, got from buffer" : "YES, go see the backend's log file",
1.547 - src->buffer_remain);
1.548 -
1.549 - GST_BUFFER_SIZE (*outbuf) = buffer_size;
1.550 - GST_BUFFER_MALLOCDATA (*outbuf) = g_malloc0 (GST_BUFFER_SIZE (*outbuf));
1.551 - GST_BUFFER_DATA (*outbuf) = GST_BUFFER_MALLOCDATA (*outbuf);
1.552 - g_memmove (GST_BUFFER_DATA ((*outbuf)), src->bytes_queue->data,
1.553 - GST_BUFFER_SIZE (*outbuf));
1.554 - GST_BUFFER_OFFSET (*outbuf) = src->read_offset;
1.555 - GST_BUFFER_OFFSET_END (*outbuf) =
1.556 - src->read_offset + GST_BUFFER_SIZE (*outbuf);
1.557 -
1.558 - src->buffer_remain -= GST_BUFFER_SIZE (*outbuf);
1.559 -
1.560 - src->read_offset += GST_BUFFER_SIZE (*outbuf);
1.561 - src->bytes_read += GST_BUFFER_SIZE (*outbuf);
1.562 - GST_DEBUG_OBJECT (src, "Buffer output with size: %d",
1.563 - GST_BUFFER_SIZE (*outbuf));
1.564 -
1.565 - /* flushs the newly buffer got from byte array */
1.566 - src->bytes_queue =
1.567 - g_byte_array_remove_range (src->bytes_queue, 0, buffer_size);
1.568 -
1.569 - GST_DEBUG_OBJECT ( src, "Got buffer: BUFFER --->SIZE = %d, OFFSET = %llu, "
1.570 - "OFFSET_END = %llu.", GST_BUFFER_SIZE (*outbuf),
1.571 - GST_BUFFER_OFFSET (*outbuf), GST_BUFFER_OFFSET_END (*outbuf) );
1.572 -
1.573 - GST_DEBUG_OBJECT (src, "CONTENT_SIZE = %llu, BYTES_READ = %llu.",
1.574 - src->content_size, src->bytes_read);
1.575 -
1.576 - if ( G_UNLIKELY (src->eos) || ( !src->live_tv
1.577 - && ( src->bytes_read >= src->content_size ) ) )
1.578 - goto eos;
1.579 -
1.580 -done:
1.581 - {
1.582 - const gchar *reason = gst_flow_get_name (ret);
1.583 -
1.584 - GST_DEBUG_OBJECT (src, "DONE task, reason %s", reason);
1.585 - return ret;
1.586 - }
1.587 -eos:
1.588 - {
1.589 - const gchar *reason = gst_flow_get_name (ret);
1.590 -
1.591 - GST_DEBUG_OBJECT (src, "pausing task, reason %s", reason);
1.592 - return GST_FLOW_UNEXPECTED;
1.593 - }
1.594 - /* ERRORS */
1.595 -read_error:
1.596 - {
1.597 - GST_ELEMENT_ERROR (src, RESOURCE, READ,
1.598 - (NULL), ("Could not read any bytes (%i, %s)", read, src->uri_name));
1.599 - return GST_FLOW_ERROR;
1.600 - }
1.601 -change_progchain:
1.602 - {
1.603 - GST_ELEMENT_ERROR (src, RESOURCE, READ,
1.604 - (NULL), ("Seek failed, go to the next program info... (%i, %s)", read,
1.605 - src->uri_name));
1.606 -
1.607 -/*
1.608 - TODO: need to send a new segment event to NUVDemux?
1.609 - gst_pad_push_event (GST_BASE_SRC_PAD (GST_BASE_SRC (psrc)),
1.610 - gst_event_new_new_segment (TRUE, 1.0, GST_FORMAT_TIME, 0, -1, 0));
1.611 -*/
1.612 -
1.613 - goto program_chain_changed;
1.614 - }
1.615 -
1.616 -}
1.617 -
1.618 -gint64
1.619 -gst_mythtv_src_get_position (GstMythtvSrc * src)
1.620 -{
1.621 -
1.622 - gint64 size_tmp = 0;
1.623 - guint max_tries = 2;
1.624 -
1.625 - if (src->live_tv == TRUE && (abs (src->content_size - src->bytes_read) <
1.626 - GMYTHTV_TRANSFER_MAX_BUFFER)) {
1.627 -
1.628 - get_file_pos:
1.629 - g_usleep (10);
1.630 - size_tmp = gmyth_recorder_get_file_position (src->spawn_livetv->recorder);
1.631 - if (size_tmp > (src->content_size + GMYTHTV_TRANSFER_MAX_BUFFER))
1.632 - src->content_size = size_tmp;
1.633 - else if (size_tmp > 0 && --max_tries > 0)
1.634 - goto get_file_pos;
1.635 - GST_LOG_OBJECT (src, "GET_POSITION: file_position = %lld", size_tmp);
1.636 - /* sets the last content size amount before it can be updated */
1.637 - src->prev_content_size = src->content_size;
1.638 - }
1.639 -
1.640 - return src->content_size;
1.641 -
1.642 -}
1.643 -
1.644 -static gboolean
1.645 -gst_mythtv_src_do_seek (GstBaseSrc * base, GstSegment * segment)
1.646 -{
1.647 - GstMythtvSrc *src = GST_MYTHTV_SRC (base);
1.648 - gint64 new_offset = -1;
1.649 - gint64 actual_seek = segment->start;
1.650 - gboolean ret = TRUE;
1.651 -
1.652 - GST_LOG_OBJECT (src, "seek, segment: %" GST_SEGMENT_FORMAT, segment);
1.653 -
1.654 - if (segment->format == GST_FORMAT_TIME) {
1.655 - goto done;
1.656 - }
1.657 - GST_LOG_OBJECT (src,
1.658 - "Trying to seek at the value (actual_seek = %lld, read_offset = %lld)",
1.659 - actual_seek, src->read_offset);
1.660 - /* verify if it needs to seek */
1.661 - if (src->read_offset != actual_seek) {
1.662 -
1.663 - /* if ( gmyth_backend_info_is_local_file(src->backend_info) ) */
1.664 - if ( IS_GMYTH_FILE_LOCAL(src->file) )
1.665 - new_offset =
1.666 - gmyth_file_local_seek ( GMYTH_FILE_LOCAL(src->file), segment->start, G_SEEK_SET);
1.667 - else if ( IS_GMYTH_FILE_TRANSFER(src->file) )
1.668 - new_offset =
1.669 - gmyth_file_transfer_seek ( GMYTH_FILE_TRANSFER(src->file), segment->start, SEEK_SET);
1.670 -
1.671 - GST_LOG_OBJECT (src,
1.672 - "Segment offset start = %lld, SRC Offset = %lld, NEW actual backend SEEK Offset = %lld.",
1.673 - segment->start, src->read_offset, new_offset);
1.674 - if (G_UNLIKELY (new_offset < 0)) {
1.675 - ret = FALSE;
1.676 - if (!src->live_tv)
1.677 - goto eos;
1.678 - }
1.679 -
1.680 - src->read_offset = new_offset;
1.681 -
1.682 - if (ret == FALSE) {
1.683 - GST_INFO_OBJECT (src, "Failed to set the SEEK on segment!");
1.684 - }
1.685 -
1.686 - }
1.687 -
1.688 -done:
1.689 - return ret;
1.690 -
1.691 -eos:
1.692 - {
1.693 - GST_DEBUG_OBJECT (src, "EOS found on seeking!!!");
1.694 - return FALSE;
1.695 - }
1.696 -
1.697 -}
1.698 -
1.699 -/* create a socket for connecting to remote server */
1.700 -static gboolean
1.701 -gst_mythtv_src_start (GstBaseSrc * bsrc)
1.702 -{
1.703 - GstMythtvSrc *src = GST_MYTHTV_SRC (bsrc);
1.704 -
1.705 - GString *chain_id_local = NULL;
1.706 - GMythURI *gmyth_uri = NULL;
1.707 - gboolean ret = TRUE;
1.708 -
1.709 - if (src->unique_setup == FALSE) {
1.710 - src->unique_setup = TRUE;
1.711 - } else {
1.712 - goto done;
1.713 - }
1.714 -
1.715 - gmyth_uri = gmyth_uri_new_with_value (src->uri_name);
1.716 - src->backend_info = gmyth_backend_info_new_with_uri (src->uri_name);
1.717 - src->live_tv = gmyth_uri_is_livetv( gmyth_uri );
1.718 - /* testing UPnP... */
1.719 - /* gmyth_backend_info_set_hostname( src->backend_info, NULL ); */
1.720 - if ( src->live_tv ) {
1.721 - src->spawn_livetv = gmyth_livetv_new (src->backend_info);
1.722 -
1.723 - gchar* ch = gmyth_uri_get_channel_name( gmyth_uri );
1.724 - if ( ch != NULL )
1.725 - src->channel_name = ch;
1.726 -
1.727 - if (src->channel_name != NULL) {
1.728 - if (gmyth_livetv_channel_name_setup (src->spawn_livetv, src->channel_name) == FALSE) {
1.729 - GST_INFO_OBJECT (src, "LiveTV setup felt down on error");
1.730 - ret = FALSE;
1.731 - goto init_failed;
1.732 - }
1.733 - } else {
1.734 - if (gmyth_livetv_setup (src->spawn_livetv) == FALSE) {
1.735 - GST_INFO_OBJECT (src, "LiveTV setup felt down on error");
1.736 - ret = FALSE;
1.737 - goto init_failed;
1.738 - }
1.739 - }
1.740 -
1.741 - /* testing change channel... */
1.742 - /* gmyth_recorder_change_channel( src->spawn_livetv->recorder, CHANNEL_DIRECTION_UP ); */
1.743 -
1.744 - src->file = GMYTH_FILE( gmyth_livetv_create_file_transfer (src->spawn_livetv) );
1.745 -
1.746 - if (NULL == src->file) {
1.747 - GST_INFO_OBJECT (src, "[LiveTV] FileTransfer equals to NULL");
1.748 - ret = FALSE;
1.749 - goto init_failed;
1.750 - }
1.751 -
1.752 - /* Check if the file is local to this specific client renderer */
1.753 - if ( gmyth_uri_is_local_file(gmyth_uri) )
1.754 - ret = gmyth_file_local_open( GMYTH_FILE_LOCAL(src->file) );
1.755 - else
1.756 - ret = gmyth_file_transfer_open( GMYTH_FILE_TRANSFER(src->file), src->spawn_livetv->uri != NULL ?
1.757 - gmyth_uri_get_path(src->spawn_livetv->uri) :
1.758 - src->spawn_livetv->proginfo->pathname->str );
1.759 -
1.760 - /* sets the mythtvsrc "location" property */
1.761 - g_object_set (src, "location", gmyth_file_get_uri (src->file), NULL);
1.762 -
1.763 - if ( !ret )
1.764 - {
1.765 - GST_INFO_OBJECT (src, "Error: couldn't open the FileTransfer from LiveTV source!" );
1.766 - g_object_unref( src->file );
1.767 - src->file = NULL;
1.768 - goto init_failed;
1.769 - }
1.770 - } else {
1.771 -
1.772 - /* Check if the file is local to this specific client renderer, and tries to open
1.773 - * a local connection
1.774 - */
1.775 - if ( gmyth_uri_is_local_file(gmyth_uri) )
1.776 - {
1.777 - src->file = GMYTH_FILE(gmyth_file_local_new(src->backend_info));
1.778 - ret = gmyth_file_local_open ( GMYTH_FILE_LOCAL( src->file ) );
1.779 - } else {
1.780 - src->file = GMYTH_FILE(gmyth_file_transfer_new(src->backend_info));
1.781 - ret = gmyth_file_transfer_open ( GMYTH_FILE_TRANSFER(src->file), src->uri_name );
1.782 - }
1.783 -
1.784 - } /* if (else) - recorded FileTransfer */
1.785 -
1.786 - if (NULL == src->file) {
1.787 - GST_INFO_OBJECT (src, "FileTransfer is NULL");
1.788 - goto init_failed;
1.789 - }
1.790 - /*GST_INFO_OBJECT( src, "uri = %s", src->spawn_livetv->file); */
1.791 -
1.792 - if (ret == FALSE) {
1.793 -#ifndef GST_DISABLE_GST_DEBUG
1.794 - if (src->mythtv_msgs_dbg)
1.795 - GST_INFO_OBJECT (src,
1.796 - "MythTV FileTransfer request failed when setting up socket connection!");
1.797 -#endif
1.798 - goto begin_req_failed;
1.799 - }
1.800 -
1.801 - GST_INFO_OBJECT (src,
1.802 - "MythTV FileTransfer filesize = %lld, content_size = %lld!",
1.803 - gmyth_file_get_filesize( src->file ), src->content_size);
1.804 -
1.805 - src->content_size = gmyth_file_get_filesize (src->file);
1.806 -
1.807 - src->do_start = FALSE;
1.808 -
1.809 - /* this is used for the buffer cache */
1.810 - src->bytes_queue = g_byte_array_sized_new (INTERNAL_BUFFER_SIZE);
1.811 - src->buffer_remain = 0;
1.812 -
1.813 - gst_pad_push_event (GST_BASE_SRC_PAD (GST_BASE_SRC (src)),
1.814 - gst_event_new_new_segment (TRUE, 1.0, GST_FORMAT_TIME, 0,
1.815 - src->content_size, 0));
1.816 -
1.817 -done:
1.818 - if (gmyth_uri != NULL)
1.819 - {
1.820 - g_object_unref (gmyth_uri);
1.821 - gmyth_uri = NULL;
1.822 - }
1.823 -
1.824 - if (chain_id_local != NULL) {
1.825 - g_string_free (chain_id_local, TRUE);
1.826 - chain_id_local = NULL;
1.827 - }
1.828 -
1.829 - return TRUE;
1.830 -
1.831 - /* ERRORS */
1.832 -init_failed:
1.833 - if (gmyth_uri != NULL)
1.834 - {
1.835 - g_object_unref (gmyth_uri);
1.836 - gmyth_uri = NULL;
1.837 - }
1.838 -
1.839 - if (src->spawn_livetv != NULL) {
1.840 - g_object_unref (src->spawn_livetv);
1.841 - src->spawn_livetv = NULL;
1.842 - }
1.843 -
1.844 - /*
1.845 - GST_ELEMENT_ERROR (src, LIBRARY, INIT,
1.846 - (NULL), ("Could not initialize MythTV library (%i, %s)", ret,
1.847 - src->uri_name));
1.848 - */
1.849 -
1.850 - if (++src->try_number <= src->max_try) {
1.851 - gst_mythtv_src_clear (src);
1.852 - GST_DEBUG_OBJECT (src, "Starting new try for get free recorder on MythTV");
1.853 - g_usleep (0.5 * G_USEC_PER_SEC);
1.854 - return gst_mythtv_src_start (bsrc);
1.855 - }
1.856 -
1.857 - return FALSE;
1.858 -begin_req_failed:
1.859 - if (gmyth_uri != NULL)
1.860 - {
1.861 - g_object_unref (gmyth_uri);
1.862 - gmyth_uri = NULL;
1.863 - }
1.864 -
1.865 - GST_ELEMENT_ERROR (src, LIBRARY, INIT,
1.866 - (NULL), ("Could not begin request sent to MythTV server (%i, %s)", ret,
1.867 - src->uri_name));
1.868 - return FALSE;
1.869 -
1.870 -}
1.871 -
1.872 -static gboolean
1.873 -gst_mythtv_src_get_size (GstBaseSrc * bsrc, guint64 * size)
1.874 -{
1.875 - GstMythtvSrc *src = GST_MYTHTV_SRC (bsrc);
1.876 - gboolean ret = TRUE;
1.877 -
1.878 - GST_LOG_OBJECT (src, "Differs from previous content size: %d (max.: %d)",
1.879 - abs (src->content_size - src->prev_content_size),
1.880 - GMYTHTV_TRANSFER_MAX_BUFFER);
1.881 -
1.882 - if (src->live_tv) {
1.883 - ret = FALSE;
1.884 - } else if (src->live_tv && src->enable_timing_position
1.885 - && (abs (src->content_size - src->bytes_read) <
1.886 - GMYTHTV_TRANSFER_MAX_BUFFER)) {
1.887 -
1.888 - gint64 new_offset =
1.889 - gmyth_recorder_get_file_position (src->spawn_livetv->recorder);
1.890 - if (new_offset > 0 && new_offset > src->content_size) {
1.891 - src->content_size = new_offset;
1.892 - } else if (new_offset < src->content_size) {
1.893 - src->update_prog_chain = TRUE;
1.894 - }
1.895 -
1.896 - }
1.897 -
1.898 - *size = src->content_size;
1.899 - GST_LOG_OBJECT (src, "Content size = %lld", src->content_size);
1.900 -
1.901 - return ret;
1.902 -
1.903 -}
1.904 -
1.905 -/* close the socket and associated resources
1.906 - * used both to recover from errors and go to NULL state */
1.907 -static gboolean
1.908 -gst_mythtv_src_stop (GstBaseSrc * bsrc)
1.909 -{
1.910 - GstMythtvSrc *src = GST_MYTHTV_SRC (bsrc);
1.911 -
1.912 - gst_mythtv_src_clear (src);
1.913 -
1.914 - /* src->eos = FALSE; */
1.915 -
1.916 - return TRUE;
1.917 -}
1.918 -
1.919 -static gboolean
1.920 -gst_mythtv_src_handle_event (GstPad * pad, GstEvent * event)
1.921 -{
1.922 - GstMythtvSrc *src = GST_MYTHTV_SRC (GST_PAD_PARENT (pad));
1.923 - gint64 cont_size = 0;
1.924 - gboolean ret = FALSE;
1.925 -
1.926 - switch (GST_EVENT_TYPE (event)) {
1.927 - case GST_EVENT_EOS:
1.928 - GST_WARNING_OBJECT (src, "Got EOS event");
1.929 -
1.930 - if (src->live_tv) {
1.931 - cont_size = gst_mythtv_src_get_position (src);
1.932 - if (cont_size > src->content_size) {
1.933 - src->content_size = cont_size;
1.934 - src->eos = FALSE;
1.935 - } else {
1.936 - src->eos = TRUE;
1.937 - gst_element_set_state (GST_ELEMENT (src), GST_STATE_NULL);
1.938 - gst_element_set_locked_state (GST_ELEMENT (src), FALSE);
1.939 - }
1.940 - }
1.941 - break;
1.942 - default:
1.943 - ret = gst_pad_event_default (pad, event);
1.944 - }
1.945 -
1.946 - return ret;
1.947 -}
1.948 -
1.949 -static gboolean
1.950 -gst_mythtv_src_is_seekable (GstBaseSrc * push_src)
1.951 -{
1.952 - return TRUE;
1.953 -}
1.954 -
1.955 -static gboolean
1.956 -gst_mythtv_src_handle_query (GstPad * pad, GstQuery * query)
1.957 -{
1.958 - gboolean res = FALSE;
1.959 - GstMythtvSrc *myth = GST_MYTHTV_SRC (gst_pad_get_parent (pad));
1.960 - GstFormat formt;
1.961 -
1.962 - switch (GST_QUERY_TYPE (query)) {
1.963 - case GST_QUERY_POSITION:
1.964 - {
1.965 - gst_query_parse_position (query, &formt, NULL);
1.966 - if (formt == GST_FORMAT_BYTES) {
1.967 - gst_query_set_position (query, formt, myth->read_offset);
1.968 - GST_DEBUG_OBJECT (myth, "POS %" G_GINT64_FORMAT, myth->read_offset);
1.969 - res = TRUE;
1.970 - } else if (formt == GST_FORMAT_TIME) {
1.971 - res = gst_pad_query_default (pad, query);
1.972 - }
1.973 - break;
1.974 - }
1.975 - case GST_QUERY_DURATION:
1.976 - {
1.977 -#if 0
1.978 - if (myth->duration != 0) {
1.979 - gint64 total;
1.980 - gint64 fps;
1.981 -
1.982 - fps = nuv->h->i_fpsn / nuv->h->i_fpsd;
1.983 - total =
1.984 - gst_util_uint64_scale_int (GST_SECOND, nuv->h->i_video_blocks, fps);
1.985 - }
1.986 -#endif
1.987 -
1.988 - gst_query_parse_duration (query, &formt, NULL);
1.989 - if (formt == GST_FORMAT_BYTES) {
1.990 - gst_query_set_duration (query, formt, myth->content_size);
1.991 - GST_DEBUG_OBJECT (myth, "SIZE %" G_GINT64_FORMAT, myth->content_size);
1.992 - res = TRUE;
1.993 - } else if (formt == GST_FORMAT_TIME) {
1.994 - res = gst_pad_query_default (pad, query);
1.995 - }
1.996 - break;
1.997 - }
1.998 - default:
1.999 - {
1.1000 - res = gst_pad_query_default (pad, query);
1.1001 - break;
1.1002 - }
1.1003 - }
1.1004 -
1.1005 - gst_object_unref (myth);
1.1006 -
1.1007 - return res;
1.1008 -}
1.1009 -
1.1010 -static GstStateChangeReturn
1.1011 -gst_mythtv_src_change_state (GstElement * element, GstStateChange transition)
1.1012 -{
1.1013 - GstStateChangeReturn ret = GST_STATE_CHANGE_FAILURE;
1.1014 - GstMythtvSrc *src = GST_MYTHTV_SRC (element);
1.1015 -
1.1016 - switch (transition) {
1.1017 - case GST_STATE_CHANGE_NULL_TO_READY:
1.1018 - break;
1.1019 - case GST_STATE_CHANGE_READY_TO_PAUSED:
1.1020 - case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
1.1021 - if (src->live_tv) {
1.1022 - if (!gmyth_recorder_send_frontend_ready_command (src->spawn_livetv->
1.1023 - recorder))
1.1024 - GST_WARNING_OBJECT (src,
1.1025 - "Couldn't send the FRONTEND_READY message to the backend!");
1.1026 - else
1.1027 - GST_DEBUG_OBJECT (src, "FRONTEND_READY was sent to the backend");
1.1028 - }
1.1029 - break;
1.1030 - default:
1.1031 - break;
1.1032 - }
1.1033 -
1.1034 - ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1.1035 - if (ret == GST_STATE_CHANGE_FAILURE)
1.1036 - return ret;
1.1037 -
1.1038 - switch (transition) {
1.1039 - case GST_STATE_CHANGE_READY_TO_NULL:
1.1040 - break;
1.1041 - case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
1.1042 - case GST_STATE_CHANGE_PAUSED_TO_READY:
1.1043 - break;
1.1044 - default:
1.1045 - break;
1.1046 - }
1.1047 -
1.1048 - return ret;
1.1049 -}
1.1050 -
1.1051 -static void
1.1052 -gst_mythtv_src_set_property (GObject * object, guint prop_id,
1.1053 - const GValue * value, GParamSpec * pspec)
1.1054 -{
1.1055 - GstMythtvSrc *mythtvsrc = GST_MYTHTV_SRC (object);
1.1056 -
1.1057 - GST_OBJECT_LOCK (mythtvsrc);
1.1058 - switch (prop_id) {
1.1059 - case PROP_LOCATION:
1.1060 - {
1.1061 - if (!g_value_get_string (value)) {
1.1062 - GST_WARNING ("location property cannot be NULL");
1.1063 - break;
1.1064 - }
1.1065 -
1.1066 - if (mythtvsrc->uri_name != NULL) {
1.1067 - g_free (mythtvsrc->uri_name);
1.1068 - mythtvsrc->uri_name = NULL;
1.1069 - }
1.1070 - mythtvsrc->uri_name = g_value_dup_string (value);
1.1071 -
1.1072 - break;
1.1073 - }
1.1074 -#ifndef GST_DISABLE_GST_DEBUG
1.1075 - case PROP_GMYTHTV_DBG:
1.1076 - {
1.1077 - mythtvsrc->mythtv_msgs_dbg = g_value_get_boolean (value);
1.1078 - break;
1.1079 - }
1.1080 -#endif
1.1081 - case PROP_GMYTHTV_VERSION:
1.1082 - {
1.1083 - mythtvsrc->mythtv_version = g_value_get_int (value);
1.1084 - break;
1.1085 - }
1.1086 - case PROP_GMYTHTV_LIVEID:
1.1087 - {
1.1088 - mythtvsrc->live_tv_id = g_value_get_int (value);
1.1089 - break;
1.1090 - }
1.1091 - case PROP_GMYTHTV_LIVE:
1.1092 - {
1.1093 - mythtvsrc->live_tv = g_value_get_boolean (value);
1.1094 - break;
1.1095 - }
1.1096 - case PROP_GMYTHTV_ENABLE_TIMING_POSITION:
1.1097 - {
1.1098 - mythtvsrc->enable_timing_position = g_value_get_boolean (value);
1.1099 - break;
1.1100 - }
1.1101 - case PROP_GMYTHTV_LIVE_CHAINID:
1.1102 - {
1.1103 - if (!g_value_get_string (value)) {
1.1104 - GST_WARNING ("MythTV Live chainid property cannot be NULL");
1.1105 - break;
1.1106 - }
1.1107 -
1.1108 - if (mythtvsrc->live_chain_id != NULL) {
1.1109 - g_free (mythtvsrc->live_chain_id);
1.1110 - mythtvsrc->live_chain_id = NULL;
1.1111 - }
1.1112 - mythtvsrc->live_chain_id = g_value_dup_string (value);
1.1113 - break;
1.1114 - }
1.1115 - case PROP_GMYTHTV_CHANNEL_NUM:
1.1116 - {
1.1117 - mythtvsrc->channel_name = g_value_dup_string (value);
1.1118 - break;
1.1119 - }
1.1120 - case PROP_GMYTHTV_MAX_TRY:
1.1121 - {
1.1122 - mythtvsrc->max_try = g_value_get_int (value);
1.1123 - break;
1.1124 - }
1.1125 - default:
1.1126 - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1.1127 - break;
1.1128 - }
1.1129 -
1.1130 - GST_OBJECT_UNLOCK (mythtvsrc);
1.1131 -}
1.1132 -
1.1133 -static void
1.1134 -gst_mythtv_src_get_property (GObject * object, guint prop_id,
1.1135 - GValue * value, GParamSpec * pspec)
1.1136 -{
1.1137 - GstMythtvSrc *mythtvsrc = GST_MYTHTV_SRC (object);
1.1138 -
1.1139 - GST_OBJECT_LOCK (mythtvsrc);
1.1140 - switch (prop_id) {
1.1141 - case PROP_LOCATION:
1.1142 - {
1.1143 - g_value_set_string (value, mythtvsrc->uri_name);
1.1144 - break;
1.1145 - }
1.1146 -#ifndef GST_DISABLE_GST_DEBUG
1.1147 - case PROP_GMYTHTV_DBG:
1.1148 - g_value_set_boolean (value, mythtvsrc->mythtv_msgs_dbg);
1.1149 - break;
1.1150 -#endif
1.1151 - case PROP_GMYTHTV_VERSION:
1.1152 - {
1.1153 - g_value_set_int (value, mythtvsrc->mythtv_version);
1.1154 - break;
1.1155 - }
1.1156 - case PROP_GMYTHTV_LIVEID:
1.1157 - {
1.1158 - g_value_set_int (value, mythtvsrc->live_tv_id);
1.1159 - break;
1.1160 - }
1.1161 - case PROP_GMYTHTV_LIVE:
1.1162 - g_value_set_boolean (value, mythtvsrc->live_tv);
1.1163 - break;
1.1164 - case PROP_GMYTHTV_ENABLE_TIMING_POSITION:
1.1165 - g_value_set_boolean (value, mythtvsrc->enable_timing_position);
1.1166 - break;
1.1167 - case PROP_GMYTHTV_LIVE_CHAINID:
1.1168 - {
1.1169 - g_value_set_string (value, mythtvsrc->live_chain_id);
1.1170 - break;
1.1171 - }
1.1172 - case PROP_GMYTHTV_CHANNEL_NUM:
1.1173 - {
1.1174 - g_value_set_string (value, mythtvsrc->channel_name);
1.1175 - break;
1.1176 - }
1.1177 - case PROP_GMYTHTV_MAX_TRY:
1.1178 - {
1.1179 - g_value_set_int (value, mythtvsrc->max_try);
1.1180 - break;
1.1181 - }
1.1182 -
1.1183 - default:
1.1184 - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1.1185 - break;
1.1186 - }
1.1187 - GST_OBJECT_UNLOCK (mythtvsrc);
1.1188 -}
1.1189 -
1.1190 -static gboolean
1.1191 -plugin_init (GstPlugin * plugin)
1.1192 -{
1.1193 - return gst_element_register (plugin, "mythtvsrc", GST_RANK_NONE,
1.1194 - GST_TYPE_MYTHTV_SRC);
1.1195 -}
1.1196 -
1.1197 -GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
1.1198 - GST_VERSION_MINOR,
1.1199 - "mythtv",
1.1200 - "lib MythTV src",
1.1201 - plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN);
1.1202 -
1.1203 -
1.1204 -/*** GSTURIHANDLER INTERFACE *************************************************/
1.1205 -static guint
1.1206 -gst_mythtv_src_uri_get_type (void)
1.1207 -{
1.1208 - return GST_URI_SRC;
1.1209 -}
1.1210 -
1.1211 -static gchar **
1.1212 -gst_mythtv_src_uri_get_protocols (void)
1.1213 -{
1.1214 - static gchar *protocols[] = { "myth", "myths", NULL };
1.1215 -
1.1216 - return protocols;
1.1217 -}
1.1218 -
1.1219 -static const gchar *
1.1220 -gst_mythtv_src_uri_get_uri (GstURIHandler * handler)
1.1221 -{
1.1222 - GstMythtvSrc *src = GST_MYTHTV_SRC (handler);
1.1223 -
1.1224 - return src->uri_name;
1.1225 -}
1.1226 -
1.1227 -static gboolean
1.1228 -gst_mythtv_src_uri_set_uri (GstURIHandler * handler, const gchar * uri)
1.1229 -{
1.1230 - GstMythtvSrc *src = GST_MYTHTV_SRC (handler);
1.1231 -
1.1232 - gchar *protocol;
1.1233 -
1.1234 - protocol = gst_uri_get_protocol (uri);
1.1235 - if ((strcmp (protocol, "myth") != 0) && (strcmp (protocol, "myths") != 0)) {
1.1236 - g_free (protocol);
1.1237 - return FALSE;
1.1238 - }
1.1239 - g_free (protocol);
1.1240 - g_object_set (src, "location", uri, NULL);
1.1241 -
1.1242 - return TRUE;
1.1243 -}
1.1244 -
1.1245 -static void
1.1246 -gst_mythtv_src_uri_handler_init (gpointer g_iface, gpointer iface_data)
1.1247 -{
1.1248 - GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface;
1.1249 -
1.1250 - iface->get_type = gst_mythtv_src_uri_get_type;
1.1251 - iface->get_protocols = gst_mythtv_src_uri_get_protocols;
1.1252 - iface->get_uri = gst_mythtv_src_uri_get_uri;
1.1253 - iface->set_uri = gst_mythtv_src_uri_set_uri;
1.1254 -}
1.1255 -
1.1256 -void
1.1257 -size_header_handler (void *userdata, const char *value)
1.1258 -{
1.1259 - GstMythtvSrc *src = GST_MYTHTV_SRC (userdata);
1.1260 -
1.1261 - GST_DEBUG_OBJECT (src, "content size = %lld bytes", src->content_size);
1.1262 -}