gmyth/src/gmyth_livetv.c
author rosfran
Tue Apr 03 20:12:01 2007 +0100 (2007-04-03)
branchtrunk
changeset 490 b15d16fb4039
parent 486 56b98fd15019
child 493 32148e79242d
permissions -rwxr-xr-x
[svn r495] Some more code clean-ups.
     1 /**
     2  * GMyth Library
     3  *
     4  * @file gmyth/gmyth_livetv.c
     5  * 
     6  * @brief <p> GMythLiveTV starts a remote TV session with the MythTV backend.
     7  *
     8  * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
     9  * @author Rosfran Lins Borges <rosfran.borges@indt.org.br>
    10  *
    11  *//*
    12  * 
    13  * This program is free software; you can redistribute it and/or modify
    14  * it under the terms of the GNU Lesser General Public License as published by
    15  * the Free Software Foundation; either version 2 of the License, or
    16  * (at your option) any later version.
    17  *
    18  * This program is distributed in the hope that it will be useful,
    19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    21  * GNU General Public License for more details.
    22  *
    23  * You should have received a copy of the GNU Lesser General Public License
    24  * along with this program; if not, write to the Free Software
    25  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    26  */
    27   
    28 #ifdef HAVE_CONFIG_H
    29 #include "config.h"
    30 #endif
    31 
    32 #include "gmyth_livetv.h" 
    33 #include "gmyth_remote_util.h"
    34 #include "gmyth_tvchain.h"
    35 #include "gmyth_socket.h"
    36 #include "gmyth_backendinfo.h"
    37 #include "gmyth_debug.h"
    38 
    39 #include "gmyth_file_transfer.h"
    40 #include "gmyth_monitor_handler.h"
    41 
    42 #include "gmyth_common.h"
    43 
    44 static void gmyth_livetv_class_init          (GMythLiveTVClass *klass);
    45 static void gmyth_livetv_init                (GMythLiveTV *object);
    46 
    47 static void gmyth_livetv_dispose  (GObject *object);
    48 static void gmyth_livetv_finalize (GObject *object);
    49 
    50 static gint tvchain_curr_index = -1; 
    51 
    52 /*static GStaticMutex lock = G_STATIC_MUTEX_INIT;*/
    53 
    54 #define GMYTHTV_TRANSFER_MAX_WAITS	    100
    55 
    56 G_DEFINE_TYPE(GMythLiveTV, gmyth_livetv, G_TYPE_OBJECT)
    57 
    58 static void
    59 gmyth_livetv_class_init (GMythLiveTVClass *klass)
    60 {
    61 	GObjectClass *gobject_class;
    62 
    63 	gobject_class = (GObjectClass *) klass;
    64 
    65 	gobject_class->dispose  = gmyth_livetv_dispose;
    66 	gobject_class->finalize = gmyth_livetv_finalize;	
    67 }
    68 
    69 static void
    70 gmyth_livetv_init (GMythLiveTV *livetv)
    71 {
    72     livetv->monitor = NULL;
    73 	livetv->backend_info = NULL;
    74 	livetv->local_hostname = NULL;
    75 	livetv->file_transfer = NULL;
    76 	livetv->setup_done = FALSE;
    77 	
    78 	livetv->socket = NULL;
    79 	livetv->recorder = NULL;
    80 	livetv->tvchain = NULL;
    81 	livetv->proginfo = NULL;
    82 	livetv->uri = NULL;
    83 	
    84 	livetv->mutex = g_mutex_new();
    85 }
    86 
    87 static void
    88 gmyth_livetv_dispose  (GObject *object)
    89 {	
    90 	GMythLiveTV *livetv = GMYTH_LIVETV (object);
    91 
    92     if (livetv->disposed) {
    93         /* If dispose did already run, return. */
    94         return;
    95     }
    96     
    97     /* Make sure dispose does not run twice. */
    98     livetv->disposed = TRUE;
    99 
   100 	if ( livetv->monitor != NULL ) {
   101 		g_object_unref (livetv->monitor);
   102 		livetv->monitor = NULL;
   103 	}
   104 	
   105 	if ( livetv->recorder != NULL ) {
   106         //gmyth_recorder_close(livetv->recorder);
   107 		g_object_unref (livetv->recorder);
   108 		livetv->recorder = NULL;
   109 	}
   110 
   111 	if ( livetv->socket != NULL ) {
   112 		g_object_unref (livetv->socket);
   113 		livetv->socket = NULL;
   114 	}
   115 	
   116 	if ( livetv->tvchain != NULL ) {
   117 		g_object_unref (livetv->tvchain);
   118 		livetv->tvchain = NULL;
   119 	}
   120 
   121 	if ( livetv->proginfo != NULL ) {
   122 		g_object_unref (livetv->proginfo);
   123 		livetv->proginfo = NULL;
   124 	}
   125 	
   126 	if ( livetv->file_transfer != NULL ) {
   127 		g_object_unref (livetv->file_transfer);
   128 		livetv->file_transfer = NULL;
   129 	}
   130 	
   131 	if ( livetv->backend_info != NULL ) {
   132 		g_object_unref (livetv->backend_info);
   133 		livetv->backend_info = NULL;
   134 	}
   135 	
   136 	if ( livetv->uri != NULL ) {
   137 		g_object_unref (livetv->uri);
   138 		livetv->uri = NULL;
   139 	}
   140 	
   141 	if ( livetv->mutex != NULL ) {
   142 		g_mutex_free (livetv->mutex);
   143 		livetv->mutex = NULL;
   144 	}
   145     
   146     if ( livetv->local_hostname != NULL ) {
   147         g_string_free (livetv->local_hostname, TRUE);
   148         livetv->local_hostname = NULL;
   149     }
   150 
   151 	G_OBJECT_CLASS (gmyth_livetv_parent_class)->dispose (object);
   152 }
   153 
   154 static void
   155 gmyth_livetv_finalize (GObject *object)
   156 {
   157 	g_signal_handlers_destroy (object);
   158 
   159 	G_OBJECT_CLASS ( gmyth_livetv_parent_class )->finalize ( object );
   160 }
   161 
   162 /**
   163  * Creates a new GMythLiveTV instance
   164  * 
   165  * @return a newly allocated GMythLiveTV instance
   166  */
   167 GMythLiveTV*
   168 gmyth_livetv_new (GMythBackendInfo *backend_info)
   169 {
   170 	GMythLiveTV *livetv = GMYTH_LIVETV ( g_object_new( GMYTH_LIVETV_TYPE, NULL ) );
   171     
   172 	livetv->backend_info = backend_info;
   173     g_object_ref (livetv->backend_info);
   174 
   175 	return livetv;
   176 }
   177 
   178 /**
   179  * The GObject signal handler function, from which all status messages 
   180  * from the Monitor Handler will be advertized, all time it receives
   181  * LiveTV status messages from the MythTV backend
   182  * 
   183  * @param monitor a GMythMonitorHandler instance
   184  * @param msg_code the MythTV's server numeric status code
   185  * @param message the message's string description
   186  * @param user_data pointer to the GMythLiveTV instance
   187  */
   188 static void
   189 gmyth_livetv_monitor_signal_handler( GMythMonitorHandler *monitor, gint msg_code, 
   190 							gchar* message, gpointer user_data )
   191 {
   192 	GMythLiveTV *live_tv = GMYTH_LIVETV ( user_data );
   193 	
   194 	gmyth_debug( "LIVETV Signal handler ( msg = %s, code = %d, live_tv param = %s, user_data = %s )\n", message, msg_code, live_tv != NULL ? "" : 
   195 					"NULL", user_data != NULL ? "" : "NULL" );
   196 	
   197 	if ( NULL == live_tv )
   198 	{
   199 		gmyth_debug( "LiveTV_obj is equals to NULL!!!" );
   200 		return;
   201 	}		
   202 	
   203 	switch ( msg_code ) 
   204 	{
   205 		
   206 		case GMYTH_BACKEND_PROGRAM_INFO_CHANGED:
   207 		{
   208 			gmyth_debug( "LIVETV Program Changed request received [ msg = %s ]. Watching if the new "\
   209 				"TV Chain ID is the same as the old one...\n", message );
   210 			if ( g_ascii_strcasecmp ( message, (gmyth_tvchain_get_id( live_tv->tvchain ))->str ) != 0 ) {				
   211 				gmyth_debug( "OK!!! MOVED to the next program chain [actual == %s]!", 
   212 										(gmyth_tvchain_get_id( live_tv->tvchain ))->str );
   213 				/* advertises the FileTransfer about the program info changed */
   214 				if ( live_tv->file_transfer != NULL )
   215 				{
   216 					gmyth_debug( "Emitting signal to the FileTransfer... [ \"program-info-changed \" ]" );
   217 					
   218 					gmyth_file_transfer_emit_program_info_changed_signal( live_tv->file_transfer,
   219 		             msg_code, (gpointer)(live_tv->recorder) );
   220 		             
   221 					/* gmyth_livetv_monitor_handler_stop( live_tv ); */
   222 				} else
   223 					gmyth_debug( "LIVETV file_transfer is NULL!!! Cannot move to the next program chain event received.\n");				
   224 			}
   225 			break;
   226 		}
   227 		case GMYTH_BACKEND_DONE_RECORDING:
   228 		{
   229 			gmyth_debug( "LIVETV Program Changed request received [ msg = %s ]. Watching if the new "\
   230 				"TV Chain ID is the same as the old one...\n", message );
   231 			if ( g_ascii_strcasecmp ( message, (gmyth_tvchain_get_id( live_tv->tvchain ))->str ) != 0 ) {				
   232 				gmyth_debug( "OK!!! MOVED to the next program chain [actual == %s]!", 
   233 										(gmyth_tvchain_get_id( live_tv->tvchain ))->str );
   234 				/* advertises the FileTransfer about the program info changed */
   235 				if ( live_tv->file_transfer != NULL )
   236 				{
   237 					gmyth_debug( "Emitting signal to the FileTransfer... [ \"backend-done-recording\" ]" );
   238 					
   239 					gmyth_file_transfer_emit_program_info_changed_signal( live_tv->file_transfer,
   240 		             msg_code, (gpointer)(live_tv->recorder) );
   241 		             
   242 				} else
   243 					gmyth_debug( "LIVETV file_transfer is NULL!!! Cannot move to the next program chain event received.\n");				
   244 			}
   245 			break;
   246 		}
   247 		case GMYTH_BACKEND_STOP_LIVETV:
   248 		{
   249 			gmyth_debug( "LIVETV Stop LiveTV request received [ msg = %s ]. Going out the "\
   250 				"LiveTV...\n", message );
   251 			/* stops the LiveTV */
   252 			if ( live_tv != NULL )
   253 			{
   254 				gmyth_debug( "Going out the LiveTV... [ \"quit-livetv\" ]" );
   255 				
   256 				g_object_unref( live_tv );
   257 			} else
   258 				gmyth_debug( "LIVETV file_transfer is NULL!!! Cannot move to the next program chain event received.\n");				
   259 			
   260 			break;
   261 		}
   262 		default:
   263 			break;		
   264 	} /* switch (Monitor Handler messages) */
   265 	
   266 }
   267 
   268 /**
   269  * Starts the Monitor Handler to this GMythLiveTV session, in order
   270  * to receive the status messages from the MythTV's backend server 
   271  * 
   272  * @param live_tv the GMythLiveTV instance
   273  * 
   274  * @return <code>true</code> if the Monitor Handler start-up process
   275  * 	   had been concluded succcesfully 
   276  */
   277 gboolean
   278 gmyth_livetv_monitor_handler_start( GMythLiveTV *livetv )
   279 {
   280 	gboolean res = TRUE;
   281 	
   282 	if ( livetv->monitor != NULL )
   283 	{
   284 		g_object_unref( livetv->monitor );
   285 		livetv->monitor	= NULL;
   286 	}
   287 	
   288   livetv->monitor = gmyth_monitor_handler_new ( );
   289   
   290   res = gmyth_monitor_handler_open (livetv->monitor, livetv->backend_info->hostname, 
   291   				livetv->backend_info->port );
   292   
   293   if ( res == TRUE )
   294   {
   295   	gmyth_debug("Connect MythTV Monitor event socket! Trying to start the message handler...");
   296   	
   297   	res = gmyth_monitor_handler_start ( livetv->monitor );
   298   	
   299   	if (res)
   300   	{
   301   		gmyth_debug("MythTV Monitor event socket connected and listening!");
   302   		g_signal_connect ( G_OBJECT (livetv->monitor), "backend-events-handler",
   303                   (GCallback)gmyth_livetv_monitor_signal_handler,
   304                   livetv );
   305   	}
   306   	else
   307   	{
   308   		gmyth_debug("Problems when trying to start MythTV Monitor event socket!");
   309   		goto error;  		
   310   	}
   311   }
   312   
   313 error:
   314 	return res;
   315   
   316 }
   317 
   318 /**
   319  * Stops the Monitor Handler to this GMythLiveTV session, in order
   320  * to stop receiving the status messages from the MythTV's backend server 
   321  * 
   322  * @param live_tv the GMythLiveTV instance
   323  * 
   324  * @return <code>true</code> if the Monitor Handler shutdown process
   325  * 	   had been concluded succcesfully 
   326  */
   327 void
   328 gmyth_livetv_monitor_handler_stop( GMythLiveTV *livetv )
   329 {
   330 	
   331   if ( livetv->monitor != NULL )
   332   {
   333   	g_object_unref( livetv->monitor );
   334   	livetv->monitor = NULL;
   335   } 
   336   
   337 }
   338 
   339 #if 0
   340 static gchar*
   341 gmyth_livetv_create_remote_url( GMythLiveTV *livetv )
   342 {
   343 	gchar *uri = g_strdup("");
   344 	gmyth_backend_info_get_remote_h
   345 	
   346 	//gmyth_backend(livetv->backend_info)
   347 	
   348 	return uri;
   349 }
   350 #endif
   351 
   352 /**
   353  * Configures the GMythLiveTV session, sends SPAWN_LIVETV message, 
   354  * sets the channel name, and gets the first program info about the
   355  * actual recording 
   356  * 
   357  * @param live_tv the GMythLiveTV instance
   358  * @param channel the channel name (the chan_name field, from the tvchain table)
   359  * @param backend_info the GMythBackendInfo describing the remote server
   360  * 
   361  * @return <code>true</code> if the LiveTV's recorder instance configuration 
   362  * 				had been concluded succcesfully 
   363  */
   364 static gboolean
   365 gmyth_livetv_setup_recorder_channel_name (GMythLiveTV *livetv, gchar* channel)
   366 {
   367 	gboolean res = TRUE;
   368     
   369     g_return_val_if_fail (livetv != NULL, FALSE);
   370     
   371 	if ( NULL == livetv->socket ) {
   372 		livetv->socket = gmyth_socket_new ();
   373 		
   374 		/* FIME: Implement this at gmyth_socket */
   375 		res = gmyth_socket_connect_to_backend (livetv->socket, livetv->backend_info->hostname,
   376 				livetv->backend_info->port, TRUE);
   377 		if (!res) {
   378 			gmyth_debug ("[%s] LiveTV can not connect to backend", __FUNCTION__);	
   379 			res = FALSE;
   380 			goto error;
   381 		}
   382 	}
   383 	
   384 	g_mutex_lock( livetv->mutex );
   385 	
   386 	livetv->is_livetv = TRUE;
   387 	
   388 	livetv->local_hostname  = gmyth_socket_get_local_hostname ();
   389 
   390 	if ( livetv->local_hostname == NULL ) {
   391 		res = FALSE;
   392 		goto error;
   393 	}
   394 	
   395 	if  ( livetv->recorder != NULL )
   396 	{
   397 		g_object_unref( livetv->recorder );
   398 		livetv->recorder= NULL;
   399 	} 
   400 	
   401 	if ( gmyth_remote_util_get_free_recorder_count (livetv->socket) <= 0 ) {
   402 		
   403 #ifdef GMYTH_USE_DEBUG
   404 		gmyth_debug ("No free remote encoder available.");
   405 #endif
   406 		res = FALSE;
   407 		goto error;
   408 	}
   409 
   410 	/* Gets the recorder num */
   411 	livetv->recorder = remote_request_next_free_recorder (livetv->socket, -1);
   412 	gmyth_socket_close_connection (livetv->socket);
   413 
   414 	if ( NULL == livetv->recorder ) {
   415 		gmyth_debug ("[%s] None remote encoder available", __FUNCTION__);
   416 		res = FALSE;
   417 		goto error;
   418 	}
   419 	
   420 	/* Init remote encoder. Opens its control socket. */
   421 	res = gmyth_recorder_setup(livetv->recorder);
   422 	if ( !res ) {
   423 		gmyth_debug ("[%s] Fail while setting remote encoder\n", __FUNCTION__);
   424 		res = FALSE;
   425 		goto error;
   426 	}
   427     
   428 	/* Creates livetv chain handler */
   429 	livetv->tvchain = gmyth_tvchain_new();
   430 	gmyth_tvchain_initialize ( livetv->tvchain, livetv->backend_info );
   431 
   432 	if ( livetv->tvchain == NULL || livetv->tvchain->tvchain_id == NULL ) {
   433 		res = FALSE;
   434 		goto error;
   435 	}
   436 	
   437 	// Spawn live tv. Uses the socket to send mythprotocol data to start livetv in the backend (remotelly)
   438 	res = gmyth_recorder_spawntv ( livetv->recorder,
   439 			gmyth_tvchain_get_id(livetv->tvchain) );
   440 	if (!res) {
   441 		gmyth_debug ("[%s] Fail while spawn tv\n", __FUNCTION__);
   442 		res = FALSE;
   443 		goto error;
   444 	}
   445 	
   446   if ( res == TRUE ) {
   447     /* loop finished, set the max tries variable to zero again... */
   448     gint wait_to_transfer = 0;
   449 
   450     while (wait_to_transfer++ < GMYTHTV_TRANSFER_MAX_WAITS &&
   451         (gmyth_recorder_is_recording (livetv->recorder) == FALSE))
   452       g_usleep (300);
   453 
   454 		if ( channel != NULL ) 
   455 		{
   456 			/* Pauses remote encoder. */
   457 			res = gmyth_recorder_pause_recording(livetv->recorder);
   458 			if ( !res ) {
   459 				gmyth_debug ("[%s] Fail while pausing remote encoder\n", __FUNCTION__);
   460 				res = FALSE;
   461 				goto error;
   462 			}
   463 	
   464     	  	if ( gmyth_recorder_check_channel_name( livetv->recorder, channel ) )
   465     	  	{
   466     		  	if ( gmyth_recorder_set_channel_name( livetv->recorder, channel ) )
   467     		  	{
   468     		  		gmyth_debug( "Channel changed!!! [%s].\n", channel );
   469     		  	}
   470     	  	}
   471 	
   472 		} /* if - changes the channel number */
   473     sleep (4);                  /* FIXME: this is evil (tpm) */
   474   }
   475   
   476   /* DEBUG message */  
   477 	GMythProgramInfo* prog_info = gmyth_recorder_get_current_program_info( livetv->recorder );
   478 	
   479 	if ( NULL == prog_info )
   480 	{
   481 		gmyth_debug( "ProgramInfo is equals to NULL!!!" );
   482 		
   483     gint i;
   484     gchar *channame = NULL;
   485 
   486     gmyth_debug( "Problem getting current proginfo!\n" );
   487 
   488     /*
   489      * mythbackend must not be tuned in to a channel, so keep
   490      * changing channels until we find a valid one, or until
   491      * we decide to give up.
   492      */
   493     for (i=1; i<1000; i++) {
   494 			if ( channame != NULL )
   495 				g_free(channame);
   496       channame = g_strdup_printf( "%d", i );
   497       if (gmyth_recorder_set_channel_name(livetv->recorder, channame) < 0) {
   498       	continue;
   499       }
   500       prog_info = gmyth_recorder_get_next_program_info(livetv->recorder, BROWSE_DIRECTION_UP);
   501       if (prog_info != NULL)
   502       	break;
   503     }
   504 
   505 	} /* if - Program Info */
   506 	
   507 	/* prints program info data text */ 
   508 #ifdef GMYTH_USE_DEBUG	
   509 	gmyth_debug( "New ProgramInfo...\n" );
   510 	gmyth_program_info_print( prog_info );
   511 #endif	
   512 
   513 	/* check if the program chain could be obtained from the MythTV protocol message */
   514 	if ( prog_info != NULL )
   515 	{
   516 #ifdef GMYTH_USE_DEBUG
   517 		gmyth_debug( "Program Info: %s\n", gmyth_program_info_to_string( prog_info ) );
   518 #endif
   519 		livetv->proginfo = prog_info;
   520 		/* testing change channel */
   521 		//gmyth_recorder_spawntv_no_tvchain( livetv->recorder );
   522 	} else {
   523 		
   524 		/* check for the program info in the TV program chain could be obtained 
   525 		   from the MythTV MySQL database */
   526 
   527 		/* Reload all TV chain from Mysql database. */
   528 		gmyth_tvchain_reload_all (livetv->tvchain);
   529 	
   530 		if ( livetv->tvchain == NULL ) {
   531 			res = FALSE;
   532 			goto error;
   533 		}
   534 		
   535 		/* Get program info from database using chanid and starttime */
   536 		livetv->proginfo = gmyth_tvchain_get_program_at (livetv->tvchain, tvchain_curr_index++ );
   537 		if ( livetv->proginfo == NULL ) {
   538 			gmyth_debug ("[%s] LiveTV not successfully started.\n", __FUNCTION__ );
   539 			res = FALSE;
   540 			goto error;
   541 		} else {
   542 			res = TRUE;
   543 			gmyth_debug ("GMythLiveTV: All requests to backend to start TV were OK. [%s]\n", livetv->proginfo->pathname->str );
   544 		}
   545 		
   546 	}
   547 	
   548 	livetv->uri = (GMythURI*)gmyth_backend_info_get_uri( livetv->backend_info );
   549 	
   550 	g_mutex_unlock( livetv->mutex );
   551 
   552 	if ( !gmyth_livetv_monitor_handler_start( livetv ) )
   553 	{
   554 		res = FALSE;
   555 		gmyth_debug( "LiveTV MONITOR handler error on setup!" );
   556 		goto error;		
   557 	}
   558 	
   559 	livetv->setup_done = TRUE;
   560 	
   561 	return res;
   562 
   563 error:
   564 	gmyth_debug( "[%s] ERROR running LiveTV setup.\n", __FUNCTION__ );
   565 
   566     res = FALSE;
   567 
   568     g_string_free( livetv->local_hostname, TRUE );
   569 
   570 	if ( livetv->recorder != NULL ) {
   571 		g_object_unref (livetv->recorder);
   572 		livetv->recorder = NULL;
   573 	}
   574 
   575 	if ( livetv->tvchain != NULL ) {
   576 		g_object_unref (livetv->tvchain);
   577 		livetv->tvchain = NULL;
   578 	}
   579 
   580 	if ( livetv->proginfo != NULL ) {
   581 		g_object_unref (livetv->proginfo);
   582 		livetv->proginfo = NULL;
   583 	}
   584 
   585 	if ( livetv->monitor != NULL ) {
   586 		g_object_unref (livetv->monitor);
   587 		livetv->monitor = NULL;
   588 	}
   589 
   590 	return res;
   591 
   592 }
   593 
   594 /**
   595  * Setup the GMythLiveTV session, sends SPAWN_LIVETV message, 
   596  * sets the channel name, and gets the first program info about the
   597  * actual recording 
   598  * 
   599  * @param live_tv the GMythLiveTV instance
   600  * @param channel the channel name, in numerical format
   601  * @param backend_info the GMythBackendInfo describing the remote server
   602  * 
   603  * @return <code>true</code> if the LiveTV's recorder instance configuration 
   604  * 				had been concluded succcesfully 
   605  */
   606 static gboolean
   607 gmyth_livetv_setup_recorder ( GMythLiveTV *livetv, gint channel)
   608 {
   609 	return gmyth_livetv_setup_recorder_channel_name ( livetv, ( channel != -1 ) ? 
   610 				g_strdup_printf( "%d", channel ) : NULL );
   611 }
   612 
   613 /**
   614  * Setup the GMythLiveTV session, sends SPAWN_LIVETV message, 
   615  * sets the channel name (numerical format), and gets the first program info about the
   616  * actual recording 
   617  * 
   618  * @param live_tv the GMythLiveTV instance
   619  * @param channel the channel name, in numerical format
   620  * @param backend_info the GMythBackendInfo describing the remote server
   621  * 
   622  * @return <code>true</code> if the LiveTV's recorder instance configuration 
   623  * 				had been concluded succcesfully 
   624  */
   625 gboolean
   626 gmyth_livetv_channel_setup ( GMythLiveTV *livetv, gint channel )
   627 {
   628 	return gmyth_livetv_setup_recorder ( livetv, channel );
   629 }
   630 
   631 /**
   632  * Setup the GMythLiveTV session, sends SPAWN_LIVETV message, 
   633  * sets the channel name (string format), and gets the first program info about the
   634  * actual recording 
   635  * 
   636  * @param live_tv the GMythLiveTV instance
   637  * @param channel the channel name, in numerical format
   638  * @param backend_info the GMythBackendInfo describing the remote server
   639  * 
   640  * @return <code>true</code> if the LiveTV's recorder instance configuration 
   641  * 				had been concluded succcesfully 
   642  */
   643 gboolean
   644 gmyth_livetv_channel_name_setup ( GMythLiveTV *livetv, gchar* channel )
   645 {
   646 	return gmyth_livetv_setup_recorder_channel_name ( livetv, channel );
   647 }
   648 
   649 /**
   650  * Setup the GMythLiveTV session, sends SPAWN_LIVETV message, 
   651  * and gets the first program info about the actual recording
   652  * (doesn't changes the channel). 
   653  * 
   654  * @param live_tv the GMythLiveTV instance
   655  * @param backend_info the GMythBackendInfo describing the remote server
   656  * 
   657  * @return <code>true</code> if the LiveTV's recorder instance configuration 
   658  * 				had been concluded succcesfully 
   659  */
   660 gboolean
   661 gmyth_livetv_setup ( GMythLiveTV *livetv )
   662 {
   663 	return gmyth_livetv_setup_recorder ( livetv, -1 );
   664 }
   665 
   666 /**
   667  * Gets the next program info from this GMythLiveTV session.
   668  * 
   669  * @param live_tv the GMythLiveTV instance
   670  * 
   671  * @return <code>true</code> if the next program info could be got 
   672  */
   673 gboolean
   674 gmyth_livetv_next_program_chain ( GMythLiveTV *livetv )
   675 {
   676 	gboolean res = TRUE;
   677 	GMythProgramInfo *prog_info = NULL;
   678 	
   679 	if ( !livetv->setup_done )
   680 	{
   681 		gmyth_debug ( "Call the setup function first!" );
   682 		goto error;		
   683 	}
   684 	
   685 	gmyth_debug( "Current ProgramInfo...\n" );
   686 	prog_info = gmyth_recorder_get_current_program_info( livetv->recorder );
   687 	
   688 	if ( prog_info != NULL )
   689 	{
   690 		livetv->proginfo = prog_info;
   691 	} else {
   692 		gmyth_debug( "ProgramInfo equals to NULL!!! Getting the next program info..." );
   693 		prog_info = gmyth_recorder_get_next_program_info( livetv->recorder, BROWSE_DIRECTION_RIGHT );
   694 		livetv->proginfo = prog_info;		
   695 	}
   696 	/* prints program info data text */ 
   697 #ifdef GMYTH_USE_DEBUG
   698 	gmyth_program_info_print( prog_info );
   699 #endif
   700 
   701 	if ( prog_info != NULL ) {		
   702 		res = TRUE;
   703 		livetv->proginfo = prog_info;
   704 		gmyth_debug ("GMythLiveTV: All requests to backend to start TV were OK, program info changed.");
   705 	} else {
   706 		gmyth_debug ("[%s] LiveTV not successfully started on the next program chain.\n", __FUNCTION__ );
   707 		goto error;
   708 	}
   709 	
   710 	livetv->setup_done = TRUE;
   711 
   712 	return res;
   713 
   714 error:
   715 	gmyth_debug( "[%s] ERROR running LiveTV setup.\n", __FUNCTION__ );
   716 
   717     res = FALSE;
   718     
   719     g_string_free( livetv->local_hostname, TRUE );
   720 
   721 	if ( livetv->recorder != NULL ) {
   722 		g_object_unref (livetv->recorder);
   723 		livetv->recorder = NULL;
   724 	}
   725 
   726 	if ( livetv->tvchain != NULL ) {
   727 		g_object_unref (livetv->tvchain);
   728 		livetv->tvchain = NULL;
   729 	}
   730 
   731 	if ( livetv->proginfo != NULL ) {
   732 		g_object_unref (livetv->proginfo);
   733 		livetv->proginfo = NULL;
   734 	}
   735 
   736 	return res;
   737 }
   738 
   739 /**
   740  * Creates a File Transfer session, using all configuration information
   741  * got from the actual program info.
   742  * 
   743  * @param live_tv the GMythLiveTV instance
   744  * 
   745  * @return the actual GMythFileTransfer instance, generated using the
   746  * 		data got from the actual program info.
   747  */
   748 GMythFileTransfer *
   749 gmyth_livetv_create_file_transfer( GMythLiveTV *livetv )
   750 {
   751 	//GMythURI* uri = NULL;
   752 	
   753 	if ( NULL == livetv )
   754 		goto done;
   755 	
   756 	if ( !livetv->setup_done )
   757 	{
   758 		gmyth_debug( "Error: You must do the LiveTV setup, just before generating the FileTransfer from LiveTV source!" );
   759 		goto done;
   760 	}
   761 	
   762 #ifdef GMYTH_USE_DEBUG
   763 	if ( livetv->proginfo != NULL )
   764   	gmyth_debug( "URI path (from program info) = %s.\n", livetv->proginfo->pathname->str );
   765   else
   766   	gmyth_debug( "URI path (from URI) = %s.\n", livetv->uri->uri->str );
   767 #endif
   768   
   769   g_mutex_lock( livetv->mutex );
   770   
   771   if ( livetv->file_transfer != NULL )
   772   {
   773   	/*gmyth_file_transfer_close( livetv->file_transfer );*/
   774   	g_object_unref( livetv->file_transfer );
   775   	livetv->file_transfer = NULL;
   776   }  	
   777 
   778   if ( livetv->uri != NULL )  
   779   {
   780   	/* 
   781   	if ( livetv->uri->path != NULL )
   782   	{
   783   		g_string_free( livetv->uri->path, FALSE );
   784   		livetv->uri->path = NULL;
   785   	}
   786   	*/
   787 #ifdef GMYTH_USE_DEBUG
   788   	gmyth_debug( "URI is not NULL, creating from the ProgramInfo pathname... (%s)", livetv->proginfo->pathname->str );
   789 #endif
   790   	livetv->uri->path = g_string_erase(livetv->uri->path, 0, -1);
   791   	livetv->uri->path = g_string_new( g_strrstr( livetv->proginfo->pathname->str, "/" ) );
   792   } else {
   793 #ifdef GMYTH_USE_DEBUG
   794   	gmyth_debug( "URI is NULL, creating from the ProgramInfo pathname... (%s)", livetv->proginfo->pathname->str );
   795 #endif
   796   	livetv->uri = gmyth_uri_new_with_value( livetv->proginfo->pathname->str );
   797   }
   798   	
   799   if ( NULL == livetv->uri )
   800   {  	
   801   	gmyth_debug( "Couldn't parse the URI to start LiveTV! [ uri = %s ]", livetv->proginfo->pathname->str );
   802   	goto done;  	
   803   }
   804  
   805 	livetv->file_transfer = gmyth_file_transfer_new( livetv->backend_info );
   806 
   807   if ( NULL == livetv->file_transfer ) 
   808   {
   809   	gmyth_debug( "Error: couldn't create the FileTransfer from LiveTV source!" );
   810     goto done;
   811   }
   812   
   813     g_object_ref( livetv->file_transfer );
   814 
   815   /* gmyth_file_transfer_settimeout( livetv->file_transfer, TRUE ); */
   816 	
   817   g_mutex_unlock( livetv->mutex );
   818 
   819 done:
   820 	/*
   821 	if ( uri != NULL )
   822 	{
   823 		g_object_unref( uri );
   824 		uri = NULL;
   825 	}
   826 	*/	
   827 	
   828 	return livetv->file_transfer;
   829 	
   830 }
   831 
   832 /**
   833  * Stops this LiveTV session.
   834  * 
   835  * @param live_tv the GMythLiveTV instance
   836  */
   837 void
   838 gmyth_livetv_stop_playing (GMythLiveTV *livetv) 
   839 {
   840 	gmyth_debug ("Stopping the LiveTV...\n");
   841 
   842 	if (livetv->is_livetv) {
   843 		if ( !gmyth_recorder_stop_livetv (livetv->recorder) ) {
   844 			gmyth_debug ("[%s] Error while stoping remote encoder", __FUNCTION__);	
   845 		}
   846 		
   847 		if ( !gmyth_recorder_finish_recording(livetv->recorder) ) {
   848 			gmyth_debug ("[%s] Error while finishing recording on remote encoder", __FUNCTION__);	
   849 		}
   850 	}
   851 }
   852 
   853 gboolean
   854 gmyth_livetv_is_playing (GMythLiveTV *livetv)
   855 {
   856 	return TRUE;
   857 }
   858 
   859 void
   860 gmyth_livetv_start_playing (GMythLiveTV *livetv)
   861 {
   862 
   863 	// TODO
   864 
   865 }
   866