[svn r71] Added some new functions: set channel, change program info improvements, faster live TV content rendering.
1.1 --- a/gst-plugins-mythtv/src/gstmythtvsrc.c Mon Nov 06 22:59:51 2006 +0000
1.2 +++ b/gst-plugins-mythtv/src/gstmythtvsrc.c Mon Nov 06 23:12:21 2006 +0000
1.3 @@ -30,19 +30,23 @@
1.4 GST_DEBUG_CATEGORY_STATIC (mythtvsrc_debug);
1.5 #define GST_CAT_DEFAULT mythtvsrc_debug
1.6
1.7 -#define GST_GMYTHTV_ID_NUM 1
1.8 +#define GST_GMYTHTV_ID_NUM 1
1.9 +
1.10 +#define GST_GMYTHTV_CHANNEL_NUM 1000
1.11
1.12 #define GMYTHTV_VERSION_DEFAULT 30
1.13
1.14 #define GMYTHTV_TRANSFER_MAX_WAITS 100
1.15
1.16 -#define GMYTHTV_TRANSFER_MAX_BUFFER 80*1024
1.17 +#define GMYTHTV_TRANSFER_MAX_BUFFER 64*1024
1.18 //( 32*1024 )
1.19
1.20 /* 4*1024 ??? */
1.21 -#define MAX_READ_SIZE 12*1024
1.22 +#define MAX_READ_SIZE 4*1024
1.23 //( 32*1024 )
1.24
1.25 +#define GST_FLOW_ERROR_NO_DATA -101
1.26 +
1.27 /* stablish a maximum iteration value to the IS_RECORDING message */
1.28 static guint wait_to_transfer = 0;
1.29
1.30 @@ -57,7 +61,10 @@
1.31 GST_PAD_ALWAYS,
1.32 GST_STATIC_CAPS ("video/x-nuv") );
1.33
1.34 -static GStaticMutex update_size_mutex = G_STATIC_MUTEX_INIT;
1.35 +static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
1.36 + GST_PAD_SINK,
1.37 + GST_PAD_ALWAYS,
1.38 + GST_STATIC_CAPS ("video/x-nuv") );
1.39
1.40 enum
1.41 {
1.42 @@ -71,7 +78,8 @@
1.43 PROP_GMYTHTV_LIVE,
1.44 PROP_GMYTHTV_LIVEID,
1.45 PROP_GMYTHTV_LIVE_CHAINID,
1.46 - PROP_GMYTHTV_ENABLE_TIMING_POSITION
1.47 + PROP_GMYTHTV_ENABLE_TIMING_POSITION,
1.48 + PROP_GMYTHTV_CHANNEL_NUM
1.49 };
1.50
1.51 static void gst_mythtv_src_finalize (GObject * gobject);
1.52 @@ -101,7 +109,6 @@
1.53
1.54 static gint do_read_request_response (GstMythtvSrc *src, guint64 offset,
1.55 guint size, GstBuffer **outbuf);
1.56 -//static gboolean gst_mythtv_src_sink_activate_pull (GstPad * srcpad, gboolean active);
1.57
1.58 static void
1.59 _urihandler_init (GType type)
1.60 @@ -169,19 +176,19 @@
1.61 g_object_class_install_property
1.62 (gobject_class, PROP_GMYTHTV_VERSION,
1.63 g_param_spec_int ("mythtv-version", "mythtv-version",
1.64 - "Change Myth TV version",
1.65 + "Change MythTV version",
1.66 26, 30, 26, G_PARAM_READWRITE));
1.67
1.68 g_object_class_install_property
1.69 (gobject_class, PROP_GMYTHTV_LIVEID,
1.70 g_param_spec_int ("mythtv-live-id", "mythtv-live-id",
1.71 - "Change Myth TV version",
1.72 + "Change MythTV version",
1.73 0, 200, GST_GMYTHTV_ID_NUM, G_PARAM_READWRITE));
1.74
1.75 g_object_class_install_property
1.76 (gobject_class, PROP_GMYTHTV_LIVE_CHAINID,
1.77 g_param_spec_string ("mythtv-live-chainid", "mythtv-live-chainid",
1.78 - "Sets the Myth TV chain ID (from TV Chain)",
1.79 + "Sets the MythTV chain ID (from TV Chain)",
1.80 "", G_PARAM_READWRITE));
1.81
1.82 g_object_class_install_property
1.83 @@ -195,6 +202,12 @@
1.84 g_param_spec_boolean ("mythtv-enable-timing-position", "mythtv-enable-timing-position",
1.85 "Enable MythTV Live TV content size continuous updating",
1.86 FALSE, G_PARAM_READWRITE));
1.87 +
1.88 + g_object_class_install_property
1.89 + (gobject_class, PROP_GMYTHTV_CHANNEL_NUM,
1.90 + g_param_spec_int ("mythtv-channel", "mythtv-channel",
1.91 + "Change MythTV channel number",
1.92 + 0, 200, GST_GMYTHTV_CHANNEL_NUM, G_PARAM_READWRITE));
1.93
1.94 #ifndef GST_DISABLE_GST_DEBUG
1.95 g_object_class_install_property
1.96 @@ -223,6 +236,8 @@
1.97 this->unique_setup = FALSE;
1.98
1.99 this->mythtv_version = GMYTHTV_VERSION_DEFAULT;
1.100 +
1.101 + this->state = GST_MYTHTV_SRC_FILE_TRANSFER;
1.102
1.103 this->bytes_read = 0;
1.104
1.105 @@ -242,8 +257,20 @@
1.106 this->mythtv_caps = NULL;
1.107 this->update_prog_chain = FALSE;
1.108
1.109 + this->channel_num = 0;
1.110 +
1.111 this->eos = FALSE;
1.112
1.113 + this->adapter = NULL;
1.114 +
1.115 + this->sinkpad = gst_pad_new_from_static_template (&sinktemplate, "sink");
1.116 + gst_element_add_pad (GST_ELEMENT (this), this->sinkpad);
1.117 +
1.118 + /*
1.119 + this->srcpad = gst_pad_new_from_static_template (&srctemplate, "src");
1.120 + gst_element_add_pad (GST_ELEMENT (this), this->srcpad);
1.121 + */
1.122 +
1.123 gst_base_src_set_format( GST_BASE_SRC( this ), GST_FORMAT_BYTES );
1.124
1.125 gst_base_src_set_live ( GST_BASE_SRC( this ), TRUE );
1.126 @@ -273,7 +300,7 @@
1.127 }
1.128
1.129 if (this->spawn_livetv) {
1.130 - //g_object_unref (this->spawn_livetv);
1.131 + g_object_unref (this->spawn_livetv);
1.132 this->spawn_livetv = NULL;
1.133 }
1.134
1.135 @@ -299,13 +326,16 @@
1.136 /* Loop sending the Myth File Transfer request:
1.137 * Retry whilst authentication fails and we supply it. */
1.138 gint len = 0;
1.139 +
1.140 + /* max number of buffer resend interactions */
1.141 + //guint max_tries = 3;
1.142
1.143 GST_OBJECT_LOCK(src);
1.144
1.145 while ( sizetoread > 0 ) {
1.146
1.147 len = gmyth_file_transfer_read( src->file_transfer,
1.148 - GST_BUFFER_DATA( *outbuf ) + read, sizetoread, TRUE );
1.149 + GST_BUFFER_DATA( *outbuf ) + read, sizetoread, TRUE );
1.150
1.151 if ( len > 0 ) {
1.152 read += len;
1.153 @@ -313,49 +343,43 @@
1.154 }
1.155 else if ( len <= 0 )
1.156 {
1.157 + read = -1;
1.158
1.159 if ( src->live_tv == FALSE )
1.160 {
1.161 - goto eos;
1.162 + goto eos;
1.163 }
1.164 else
1.165 {
1.166 - if ( len == GMYTHTV_FILE_TRANSFER_READ_ERROR ) { /* -314 */
1.167 - src->update_prog_chain = TRUE;
1.168 - if ( gst_mythtv_src_next_program_chain ( src ) )
1.169 - continue;
1.170 - else
1.171 - goto eos;
1.172 - } else
1.173 - if ( abs( src->content_size - src->prev_content_size ) < GMYTHTV_TRANSFER_MAX_BUFFER ) {
1.174 - src->update_prog_chain = TRUE;
1.175 - if ( src->enable_timing_position ) {
1.176 - gint64 size_tmp = 0;
1.177 - if (src->live_tv == TRUE) {
1.178 -get_file_pos:
1.179 - size_tmp = gmyth_file_transfer_get_file_position( src->file_transfer );
1.180 - if ( size_tmp > ( src->content_size + GMYTHTV_TRANSFER_MAX_BUFFER ) )
1.181 - src->content_size = size_tmp;
1.182 - else if ( size_tmp > 0 )
1.183 - goto get_file_pos;
1.184 - g_print( "\t[%s]\tGET_POSITION: file_position = %lld\n",
1.185 - __FUNCTION__, size_tmp );
1.186 - }
1.187 - } else if ( abs( src->content_size - src->prev_content_size ) < GMYTHTV_TRANSFER_MAX_BUFFER ) {
1.188 - src->prev_content_size = src->content_size;
1.189 - gint64 new_offset = gmyth_file_transfer_get_file_position( src->file_transfer );
1.190 - if ( new_offset > 0 ) {
1.191 - if ( src->content_size < new_offset ) {
1.192 - src->content_size = new_offset;
1.193 - }
1.194 - } else {
1.195 - src->update_prog_chain = TRUE;
1.196 - }
1.197 - }
1.198 - goto done;
1.199 - }
1.200 - goto done;
1.201 - }
1.202 + if ( len == GMYTHTV_FILE_TRANSFER_READ_ERROR ) { /* -314 */
1.203 + src->update_prog_chain = TRUE;
1.204 + goto done;
1.205 + } else
1.206 + if ( abs( src->content_size - src->bytes_read ) < GMYTHTV_TRANSFER_MAX_BUFFER ) {
1.207 + src->update_prog_chain = TRUE;
1.208 + if ( src->enable_timing_position ) {
1.209 + gint64 size_tmp = 0;
1.210 + get_file_pos:
1.211 + size_tmp = gmyth_file_transfer_get_file_position( src->file_transfer );
1.212 + if ( size_tmp > ( src->content_size + GMYTHTV_TRANSFER_MAX_BUFFER ) )
1.213 + src->content_size = size_tmp;
1.214 + else if ( size_tmp > 0 )
1.215 + goto get_file_pos;
1.216 + g_print( "\t[%s]\tGET_POSITION: file_position = %lld\n",
1.217 + __FUNCTION__, size_tmp );
1.218 + } else if ( abs( src->content_size - src->bytes_read ) < GMYTHTV_TRANSFER_MAX_BUFFER ) {
1.219 + src->prev_content_size = src->content_size;
1.220 + gint64 new_offset = gmyth_file_transfer_get_file_position( src->file_transfer );
1.221 + if ( new_offset > 0 && src->content_size <= new_offset ) {
1.222 + src->content_size = new_offset;
1.223 + } else {
1.224 + src->update_prog_chain = TRUE;
1.225 + }
1.226 + }
1.227 + goto done;
1.228 + }
1.229 + goto done;
1.230 + }
1.231
1.232 }
1.233
1.234 @@ -366,6 +390,7 @@
1.235 if ( read > 0 ) {
1.236 src->read_offset += read;
1.237 src->bytes_read += read;
1.238 + //src->content_size += src->bytes_read;
1.239
1.240 g_print( "[%s]\tBYTES READ (actual) = %d, BYTES READ (cumulative) = %llu, "\
1.241 "OFFSET = %llu, CONTENT SIZE = %llu.\n", __FUNCTION__, read, src->bytes_read,
1.242 @@ -432,8 +457,12 @@
1.243 //src->icy_caps ? src->icy_caps :
1.244 GST_PAD_CAPS (GST_BASE_SRC_PAD (GST_BASE_SRC (psrc))), outbuf);
1.245
1.246 - if (G_UNLIKELY (ret != GST_FLOW_OK))
1.247 - goto done;
1.248 + if (G_UNLIKELY (ret != GST_FLOW_OK)) {
1.249 + if ( src->live_tv )
1.250 + goto change_progchain;
1.251 + else
1.252 + goto done;
1.253 + }
1.254
1.255 read = do_read_request_response ( src, src->read_offset, size, outbuf );
1.256
1.257 @@ -477,43 +506,16 @@
1.258 // go to the next program chain
1.259 src->unique_setup = FALSE;
1.260 src->update_prog_chain = TRUE;
1.261 - //gst_mythtv_src_next_program_chain( src );
1.262 - return -101;
1.263 +
1.264 + //GST_OBJECT_LOCK(src);
1.265 + gst_mythtv_src_next_program_chain( src );
1.266 + //GST_OBJECT_UNLOCK(src);
1.267 +
1.268 + return GST_FLOW_ERROR_NO_DATA;
1.269 }
1.270
1.271 }
1.272
1.273 -void
1.274 -update_size_func( void *mythtv_data )
1.275 -{
1.276 - GstMythtvSrc *src;
1.277 -
1.278 - g_return_if_fail( mythtv_data != NULL );
1.279 -
1.280 - src = GST_MYTHTV_SRC ( mythtv_data );
1.281 -
1.282 - g_static_mutex_lock( &update_size_mutex );
1.283 -
1.284 - if ( src->do_start ) {
1.285 - if ( src->enable_timing_position ) {
1.286 - gint64 size_tmp = 0;
1.287 - if (src->live_tv == TRUE) {
1.288 -get_file_pos:
1.289 - g_usleep( 50 );
1.290 - size_tmp = gmyth_file_transfer_get_file_position( src->file_transfer );
1.291 - if ( size_tmp > ( src->content_size + GMYTHTV_TRANSFER_MAX_BUFFER ) )
1.292 - src->content_size = size_tmp;
1.293 - else if ( size_tmp > 0 )
1.294 - goto get_file_pos;
1.295 - g_print( "\t[%s]\tGET_POSITION: file_position = %lld\n",
1.296 - __FUNCTION__, size_tmp );
1.297 - }
1.298 - }
1.299 - }
1.300 - g_static_mutex_unlock( &update_size_mutex );
1.301 -
1.302 -}
1.303 -
1.304 gint64
1.305 gst_mythtv_src_get_position ( GstMythtvSrc* src )
1.306 {
1.307 @@ -566,7 +568,7 @@
1.308 ret = FALSE;
1.309 GST_OBJECT_UNLOCK( src );
1.310 goto init_failed;
1.311 - }
1.312 + }
1.313
1.314 /* set up the uri variable */
1.315 src->uri_name = g_strdup( src->spawn_livetv->proginfo->pathname->str );
1.316 @@ -575,8 +577,8 @@
1.317 src->live_chain_id = g_strdup( chain_id_local->str );
1.318 g_print( "\t[%s]\tLocal chain ID = %s.\n", __FUNCTION__, src->live_chain_id );
1.319 }
1.320 - src->live_tv_id = src->spawn_livetv->remote_encoder->recorder_num;
1.321 - g_print ( "[%s] LiveTV id = %d, URI path = %s.\n", __FUNCTION__, src->live_tv_id, src->uri_name );
1.322 + src->live_tv_id = src->spawn_livetv->recorder->recorder_num;
1.323 + g_print ( "[%s] LiveTV id = %d, URI path = %s.\n", __FUNCTION__, src->live_tv_id, src->uri_name );
1.324 }
1.325
1.326 src->file_transfer = gmyth_file_transfer_new( src->live_tv_id,
1.327 @@ -595,7 +597,8 @@
1.328 /* loop finished, set the max tries variable to zero again... */
1.329 wait_to_transfer = 0;
1.330
1.331 - while ( wait_to_transfer++ < GMYTHTV_TRANSFER_MAX_WAITS && ( gmyth_file_transfer_is_recording( src->file_transfer ) == FALSE
1.332 + while ( wait_to_transfer++ < GMYTHTV_TRANSFER_MAX_WAITS &&
1.333 + ( gmyth_file_transfer_is_recording( src->file_transfer ) == FALSE
1.334 /*|| ( gmyth_file_transfer_get_file_position( src->file_transfer ) < ( src->content_size + 327680 ) )*/ ) )
1.335 g_usleep( 100 );
1.336 }
1.337 @@ -649,8 +652,12 @@
1.338
1.339 if ( !src->live_tv )
1.340 goto init_failed;
1.341 -
1.342 - src->update_prog_chain = FALSE;
1.343 +
1.344 + if (src->unique_setup == FALSE) {
1.345 + src->unique_setup = TRUE;
1.346 + } else {
1.347 + goto done;
1.348 + }
1.349
1.350 if (src->file_transfer) {
1.351 g_object_unref (src->file_transfer);
1.352 @@ -663,6 +670,7 @@
1.353
1.354 if ( src->live_tv ) {
1.355 if ( gmyth_livetv_next_program_chain( src->spawn_livetv ) == FALSE ) {
1.356 + g_print( "\n\n[%s]\t\tFailed to go to the next program chain!!!\n\n", __FUNCTION__ );
1.357 ret = FALSE;
1.358 goto init_failed;
1.359 }
1.360 @@ -673,7 +681,7 @@
1.361 src->live_chain_id = g_strdup( chain_id_local->str );
1.362 g_print( "\t[%s]\tLocal chain ID = %s.\n", __FUNCTION__, src->live_chain_id );
1.363 }
1.364 - src->live_tv_id = src->spawn_livetv->remote_encoder->recorder_num;
1.365 + src->live_tv_id = src->spawn_livetv->recorder->recorder_num;
1.366 g_print ( "[%s] LiveTV id = %d, URI path = %s.\n", __FUNCTION__, src->live_tv_id, src->uri_name );
1.367 }
1.368
1.369 @@ -694,7 +702,7 @@
1.370 g_usleep( 200 );
1.371
1.372 while ( wait_to_transfer++ < GMYTHTV_TRANSFER_MAX_WAITS &&
1.373 - ( gmyth_file_transfer_is_recording( src->file_transfer ) == FALSE ) )
1.374 + ( gmyth_file_transfer_is_recording( src->file_transfer ) == FALSE ) )
1.375 g_usleep( 1000 );
1.376 }
1.377
1.378 @@ -722,13 +730,17 @@
1.379 #endif
1.380
1.381 src->content_size = src->file_transfer->filesize;
1.382 - while ( src->content_size < GMYTHTV_TRANSFER_MAX_BUFFER )
1.383 + while ( src->content_size < GMYTHTV_TRANSFER_MAX_BUFFER*4 )
1.384 src->content_size = gst_mythtv_src_get_position( src );
1.385
1.386 - //src->read_offset = 0;
1.387 + src->read_offset = 0;
1.388
1.389 - //src->update_prog_chain = FALSE;
1.390 + src->update_prog_chain = FALSE;
1.391 +
1.392 + gst_pad_push_event ( src->sinkpad,
1.393 + gst_event_new_new_segment (TRUE, 1.0, GST_FORMAT_BYTES, 0, src->content_size, 0 ) );
1.394
1.395 +done:
1.396 return TRUE;
1.397
1.398 /* ERRORS */
1.399 @@ -823,25 +835,22 @@
1.400 {
1.401 GstMythtvSrc *src = GST_MYTHTV_SRC (bsrc);
1.402 gboolean ret = TRUE;
1.403 - g_print( "[%s] Difference from previous content size: %d (max.: %d)\n", __FUNCTION__,
1.404 + g_print( "[%s] Differs from previous content size: %d (max.: %d)\n", __FUNCTION__,
1.405 abs( src->content_size - src->prev_content_size ), GMYTHTV_TRANSFER_MAX_BUFFER );
1.406
1.407 if (src->content_size <= 0) {
1.408 ret= FALSE;
1.409 } else if ( src->live_tv && ( abs( src->content_size - src->bytes_read ) <
1.410 - GMYTHTV_TRANSFER_MAX_BUFFER ) ) {
1.411 + GMYTHTV_TRANSFER_MAX_BUFFER ) ) {
1.412 //g_static_mutex_lock( &update_size_mutex );
1.413 //GST_OBJECT_LOCK(src);
1.414 - src->prev_content_size = src->content_size;
1.415 +
1.416 gint64 new_offset = gmyth_file_transfer_get_file_position( src->file_transfer );
1.417 - if ( new_offset > 0 ) {
1.418 - if ( src->content_size < new_offset ) {
1.419 - src->content_size = new_offset;
1.420 - }
1.421 - } else {
1.422 - if ( src->live_tv )
1.423 - src->update_prog_chain = TRUE;
1.424 - }
1.425 + if ( new_offset > 0 && new_offset > src->content_size ) {
1.426 + src->content_size = new_offset;
1.427 + } else if ( new_offset < src->content_size ) {
1.428 + src->update_prog_chain = TRUE;
1.429 + }
1.430
1.431 if ( src->enable_timing_position ) {
1.432 gint64 size_tmp = 0;
1.433 @@ -857,6 +866,9 @@
1.434 __FUNCTION__, size_tmp );
1.435 }
1.436 }
1.437 +
1.438 + src->prev_content_size = src->content_size;
1.439 +
1.440 //GST_OBJECT_UNLOCK(src);
1.441 //g_static_mutex_unlock( &update_size_mutex );
1.442 }
1.443 @@ -988,68 +1000,142 @@
1.444 }
1.445
1.446 #if 0
1.447 -static gboolean
1.448 -gst_nuv_demux_sink_activate (GstPad * sinkpad)
1.449 +static GstFlowReturn
1.450 +gst_mythtv_src_file_transfer( GstMythtvSrc *src )
1.451 {
1.452 - gboolean res = TRUE;
1.453 - GstNuvDemux *nuv = GST_NUV_DEMUX (gst_pad_get_parent (sinkpad));
1.454 + GstFlowReturn ret = GST_FLOW_OK;
1.455 + GstBuffer *buf = NULL;
1.456 + gint read = -1;
1.457 +
1.458 + /* The caller should know the number of bytes and not read beyond EOS. */
1.459 + if ( G_UNLIKELY (src->eos) )
1.460 + goto eos;
1.461 + if ( G_UNLIKELY (src->update_prog_chain) )
1.462 + goto change_progchain;
1.463
1.464 - if (gst_pad_check_pull_range (sinkpad)) {
1.465 - nuv->mode = 0;
1.466 - nuv->adapter = NULL;
1.467 - res = gst_pad_activate_pull (sinkpad, TRUE);
1.468 - } else {
1.469 - nuv->mode = 1;
1.470 - nuv->adapter = gst_adapter_new ();
1.471 - res = gst_pad_activate_push (sinkpad, TRUE);
1.472 + do {
1.473 +
1.474 + /* Create the buffer. */
1.475 + buf = gst_buffer_new_and_alloc (4096);
1.476 +
1.477 + ret = gst_mythtv_src_read_bytes( src, GST_BUFFER_SIZE(buf), TRUE, &buf );
1.478 + if ( ret != GST_FLOW_OK )
1.479 + return ret;
1.480 +
1.481 + read = do_read_request_response ( src, src->read_offset, GST_BUFFER_SIZE(buf), &buf );
1.482 +
1.483 + if (G_UNLIKELY (src->update_prog_chain) )
1.484 + goto change_progchain;
1.485 +
1.486 + if (G_UNLIKELY (read <= 0) || buf == NULL) {
1.487 + if ( src->live_tv )
1.488 + goto change_progchain;
1.489 + else
1.490 + goto read_error;
1.491 + }
1.492 +
1.493 + if ( GST_FLOW_OK != ( ret = gst_pad_push ( src->sinkpad, buf ) ) ) {
1.494 + goto done;
1.495 + }
1.496 +
1.497 + } while(TRUE);
1.498 +
1.499 +done:
1.500 + {
1.501 + const gchar *reason = gst_flow_get_name (ret);
1.502 +
1.503 + GST_DEBUG_OBJECT (src, "DONE task, reason %s", reason);
1.504 + return ret;
1.505 + }
1.506 +eos:
1.507 + {
1.508 + const gchar *reason = gst_flow_get_name (ret);
1.509 +
1.510 + GST_DEBUG_OBJECT (src, "pausing task, reason %s", reason);
1.511 + return GST_FLOW_UNEXPECTED;
1.512 }
1.513 -
1.514 - g_object_unref (nuv);
1.515 - return res;
1.516 -}
1.517 -
1.518 -static gboolean
1.519 -gst_nuv_demux_sink_activate_pull (GstPad * sinkpad, gboolean active)
1.520 -{
1.521 - GstNuvDemux *nuv = GST_NUV_DEMUX (gst_pad_get_parent (sinkpad));
1.522 -
1.523 - if (active) {
1.524 - gst_pad_start_task (sinkpad, (GstTaskFunction) gst_nuv_demux_loop, sinkpad);
1.525 - } else {
1.526 - gst_pad_stop_task (sinkpad);
1.527 + /* ERRORS */
1.528 +read_error:
1.529 + {
1.530 + GST_ELEMENT_ERROR (src, RESOURCE, READ,
1.531 + (NULL), ("Could not read any bytes (%i, %s)", read,
1.532 + src->uri_name));
1.533 + return GST_FLOW_ERROR;
1.534 }
1.535 - gst_object_unref (nuv);
1.536 -
1.537 - return TRUE;
1.538 +change_progchain:
1.539 + {
1.540 + GST_ELEMENT_ERROR (src, RESOURCE, READ,
1.541 + (NULL), ("Seek failed, go to the next program info... (%i, %s)", read,
1.542 + src->uri_name));
1.543 + // go to the next program chain
1.544 + src->unique_setup = FALSE;
1.545 + src->update_prog_chain = TRUE;
1.546 + src->mode = GST_MYTHTV_SRC_NEXT_PROGRAM_CHAIN;
1.547 +
1.548 + //GST_OBJECT_LOCK(src);
1.549 + //gst_mythtv_src_next_program_chain( src );
1.550 + //GST_OBJECT_UNLOCK(src);
1.551 + return GST_FLOW_OK;//GST_FLOW_ERROR_NO_DATA;
1.552 + }
1.553 }
1.554
1.555 static GstFlowReturn
1.556 -gst_nuv_demux_chain (GstPad * pad, GstBuffer * buf)
1.557 +gst_mythtv_src_play (GstPad * pad)
1.558 {
1.559 - GstNuvDemux *nuv = GST_NUV_DEMUX (gst_pad_get_parent (pad));
1.560 + GstFlowReturn res = GST_FLOW_OK;
1.561 + GstMythtvSrc *src = GST_MYTHTV_SRC (GST_PAD_PARENT (pad));
1.562 +
1.563 + switch ( src->state ) {
1.564 + case GST_MYTHTV_SRC_FILE_TRANSFER:
1.565 + res = gst_mythtv_src_file_transfer( src );
1.566 + if ((res != GST_FLOW_OK) && (res != GST_FLOW_ERROR_NO_DATA)) {
1.567 + goto pause;
1.568 + }
1.569 + break;
1.570 + case GST_MYTHTV_SRC_NEXT_PROGRAM_CHAIN:
1.571 + src->read_offset = 0;
1.572 + src->bytes_read = 0;
1.573 + src->unique_setup = FALSE;
1.574 + if ( !gst_mythtv_src_next_program_chain( src ) ) {
1.575 + goto pause;
1.576 + }
1.577 + src->state = GST_MYTHTV_SRC_FILE_TRANSFER;
1.578 + break;
1.579 + case GST_MYTHTV_SRC_INVALID_DATA:
1.580 + goto pause;
1.581 + break;
1.582 + default:
1.583 + g_assert_not_reached ();
1.584 + }
1.585
1.586 - gst_adapter_push (nuv->adapter, buf);
1.587 + GST_DEBUG_OBJECT (src, "state: %d res:%s", src->state,
1.588 + gst_flow_get_name (res));
1.589
1.590 - return gst_nuv_demux_play (pad);
1.591 -}
1.592 + return GST_FLOW_OK;
1.593
1.594 -static void
1.595 -gst_nuv_demux_loop (GstPad * pad)
1.596 -{
1.597 - gst_nuv_demux_play (pad);
1.598 +pause:
1.599 + GST_LOG_OBJECT (src, "pausing task, reason %s", gst_flow_get_name (res));
1.600 + gst_pad_pause_task (src->srcpad);
1.601 + if (GST_FLOW_IS_FATAL (res)) {
1.602 + GST_ELEMENT_ERROR (src, STREAM, FAILED,
1.603 + ("Internal data stream error."),
1.604 + ("streaming stopped, reason %s", gst_flow_get_name (res)));
1.605 + gst_pad_send_event( src->sinkpad, gst_event_new_eos() );
1.606 + }
1.607 + return res;
1.608 }
1.609 #endif
1.610
1.611 static GstStateChangeReturn
1.612 gst_mythtv_src_change_state (GstElement * element, GstStateChange transition)
1.613 {
1.614 - GstStateChangeReturn ret = GST_STATE_CHANGE_NO_PREROLL;
1.615 + GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; //GST_STATE_CHANGE_NO_PREROLL;
1.616 GstMythtvSrc *src = GST_MYTHTV_SRC (element);
1.617
1.618 switch (transition) {
1.619 case GST_STATE_CHANGE_NULL_TO_READY:
1.620 src->do_start = TRUE;
1.621 - src->unique_setup = FALSE;
1.622 + src->unique_setup = FALSE;
1.623 break;
1.624 case GST_STATE_CHANGE_READY_TO_PAUSED:
1.625 case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
1.626 @@ -1066,16 +1152,23 @@
1.627 switch (transition) {
1.628 case GST_STATE_CHANGE_READY_TO_NULL:
1.629 g_print( "[%s] READY to NULL called!\n", __FUNCTION__ );
1.630 + if ( src->live_tv && src->update_prog_chain ) {
1.631 + gst_pad_push_event ( src->sinkpad,
1.632 + gst_event_new_new_segment (TRUE, 1.0, GST_FORMAT_BYTES, 0, src->content_size, 0 ) );
1.633 + gst_element_set_state ( GST_ELEMENT (src), GST_STATE_READY );
1.634 + }
1.635 break;
1.636 case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
1.637 g_print( "[%s] PLAYING to PAUSED called!\n", __FUNCTION__ );
1.638 - break;
1.639 case GST_STATE_CHANGE_PAUSED_TO_READY:
1.640 g_print( "[%s] PAUSED to READY called!\n", __FUNCTION__ );
1.641 if ( src->live_tv && src->update_prog_chain ) {
1.642 - src->read_offset = 0;
1.643 - src->bytes_read = 0;
1.644 - gst_mythtv_src_next_program_chain( src );
1.645 + src->read_offset = 0;
1.646 + src->bytes_read = 0;
1.647 + src->unique_setup = FALSE;
1.648 + //GST_OBJECT_LOCK( src );
1.649 + gst_mythtv_src_next_program_chain( src );
1.650 + //GST_OBJECT_UNLOCK( src );
1.651 }
1.652 break;
1.653 default:
1.654 @@ -1150,7 +1243,11 @@
1.655 mythtvsrc->live_chain_id = g_value_dup_string (value);
1.656 break;
1.657 }
1.658 -
1.659 + case PROP_GMYTHTV_CHANNEL_NUM:
1.660 + {
1.661 + mythtvsrc->channel_num = g_value_get_int (value);
1.662 + break;
1.663 + }
1.664 default:
1.665 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1.666 break;
1.667 @@ -1216,6 +1313,11 @@
1.668 g_value_set_string ( value, str );
1.669 break;
1.670 }
1.671 + case PROP_GMYTHTV_CHANNEL_NUM:
1.672 + {
1.673 + g_value_set_int ( value, mythtvsrc->channel_num );
1.674 + break;
1.675 + }
1.676 default:
1.677 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
1.678 break;
2.1 --- a/gst-plugins-mythtv/src/gstmythtvsrc.h Mon Nov 06 22:59:51 2006 +0000
2.2 +++ b/gst-plugins-mythtv/src/gstmythtvsrc.h Mon Nov 06 23:12:21 2006 +0000
2.3 @@ -18,6 +18,7 @@
2.4
2.5 #include <gst/gst.h>
2.6 #include <gst/base/gstpushsrc.h>
2.7 +#include <gst/base/gstadapter.h>
2.8 #include <stdio.h>
2.9
2.10 #include <gmyth/gmyth_socket.h>
2.11 @@ -40,6 +41,13 @@
2.12 typedef struct _GstMythtvSrc GstMythtvSrc;
2.13 typedef struct _GstMythtvSrcClass GstMythtvSrcClass;
2.14
2.15 +
2.16 +typedef enum {
2.17 + GST_MYTHTV_SRC_FILE_TRANSFER,
2.18 + GST_MYTHTV_SRC_NEXT_PROGRAM_CHAIN,
2.19 + GST_MYTHTV_SRC_INVALID_DATA
2.20 +} GstMythtvState;
2.21 +
2.22 struct _GstMythtvSrc {
2.23 GstBaseSrc element;
2.24
2.25 @@ -47,6 +55,8 @@
2.26 GMythFileTransfer *file_transfer;
2.27
2.28 GMythLiveTV *spawn_livetv;
2.29 +
2.30 + GstMythtvState state;
2.31
2.32 gchar *uri_name;
2.33 gchar *user_agent;
2.34 @@ -64,6 +74,7 @@
2.35 guint64 bytes_read;
2.36
2.37 gint64 read_offset;
2.38 + gint64 old_offset;
2.39
2.40 gboolean eos;
2.41
2.42 @@ -76,9 +87,18 @@
2.43 gboolean enable_timing_position;
2.44
2.45 gint live_tv_id;
2.46 +
2.47 + gint channel_num;
2.48 +
2.49 + guint mode;
2.50
2.51 /* MythTV capabilities */
2.52 GstCaps *mythtv_caps;
2.53 +
2.54 + GstPad *sinkpad;
2.55 + GstPad *srcpad;
2.56 +
2.57 + GstAdapter *adapter;
2.58
2.59 /* enable Myth TV debug messages */
2.60 gboolean mythtv_msgs_dbg;