[svn r71] Added some new functions: set channel, change program info improvements, faster live TV content rendering. trunk
authorrosfran
Mon Nov 06 23:12:21 2006 +0000 (2006-11-06)
branchtrunk
changeset 704ba74b706853
parent 69 f7c91518d8f4
child 71 55c7f31b85aa
[svn r71] Added some new functions: set channel, change program info improvements, faster live TV content rendering.
gst-plugins-mythtv/src/gstmythtvsrc.c
gst-plugins-mythtv/src/gstmythtvsrc.h
     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;