# HG changeset patch
# User rosfran
# Date 1161824743 -3600
# Node ID 51fd70b817a8466eefa719fd877ef21704cd4a28
# Parent  26845a19d06e5e0bfdc5455801e719ecc36d3172
[svn r55] Fixes on the TVChain manipulation, error when trying to get the last program chain.

diff -r 26845a19d06e -r 51fd70b817a8 gmyth/src/gmyth_file_transfer.c
--- a/gmyth/src/gmyth_file_transfer.c	Thu Oct 26 02:04:40 2006 +0100
+++ b/gmyth/src/gmyth_file_transfer.c	Thu Oct 26 02:05:43 2006 +0100
@@ -24,29 +24,29 @@
 #include <errno.h>
 #include <stdlib.h>
 
-#define GMYTHTV_QUERY_HEADER "QUERY_FILETRANSFER"
-#define GMYTHTV_RECORDER_HEADER "QUERY_RECORDER"
+#define GMYTHTV_QUERY_HEADER 			"QUERY_FILETRANSFER"
+#define GMYTHTV_RECORDER_HEADER 	"QUERY_RECORDER"
 
 /* default values to the file transfer parameters */
-#define GMYTHTV_USER_READ_AHEAD	FALSE
-#define GMYTHTV_RETRIES			1
-#define GMYTHTV_FILE_SIZE		-1
+#define GMYTHTV_USER_READ_AHEAD			FALSE
+#define GMYTHTV_RETRIES							1
+#define GMYTHTV_FILE_SIZE						0
 
-#define GMYTHTV_BUFFER_SIZE		8*1024
+#define GMYTHTV_BUFFER_SIZE					8*1024
 
-#define GMYTHTV_VERSION			30
+#define GMYTHTV_VERSION							30
 
 #define GMYTHTV_TRANSFER_MAX_WAITS	700
 
 #ifdef GMYTHTV_ENABLE_DEBUG
-#define GMYTHTV_ENABLE_DEBUG	1
+#define GMYTHTV_ENABLE_DEBUG				1
 #else
 #undef GMYTHTV_ENABLE_DEBUG
 #endif
 
 /* this NDEBUG is to maintain compatibility with GMyth library */
 #ifndef NDEBUG
-#define GMYTHTV_ENABLE_DEBUG	1
+#define GMYTHTV_ENABLE_DEBUG				1
 #endif
 
 static guint wait_to_transfer = 0;
@@ -168,6 +168,8 @@
   transfer->retries = GMYTHTV_RETRIES;  
 
   transfer->live_tv = FALSE;
+  
+  transfer->backend_msgs = g_hash_table_new( g_int_hash, g_int_equal );
 
   transfer->query = g_string_new( GMYTHTV_QUERY_HEADER );
   g_string_append_printf ( transfer->query, " %d", transfer->recordernum );
@@ -703,6 +705,29 @@
   return NULL;
 }
 
+static gboolean
+gmyth_file_transfer_is_backend_message( GMythFileTransfer *transfer, 
+			GMythStringList* strlist )
+{	
+	gboolean found_backend_msg = FALSE;	
+	GString *back_msg = NULL;
+	
+	back_msg = gmyth_string_list_get_string( strlist, 0 );
+	if ( back_msg != NULL && back_msg->str != NULL && 
+					strstr( back_msg->str, "BACKEND" ) != NULL )
+	{
+		found_backend_msg = TRUE;
+		if ( transfer->backend_msgs != NULL ) {
+			
+			g_hash_table_insert ( transfer->backend_msgs, 
+						&(transfer->readposition), back_msg );  
+			
+		}
+	}
+	
+	return found_backend_msg;
+	
+}
 
 gint 
 gmyth_file_transfer_read(GMythFileTransfer *transfer, void *data, gint size, gboolean read_unlimited)
@@ -724,6 +749,7 @@
 
   GMythStringList *strlist = NULL;
   GError *error = NULL;
+  gboolean found_backend_msg = FALSE;
 
   gchar *trash = g_strdup("");
 
@@ -819,7 +845,7 @@
 
   //g_io_channel_flush( io_channel, NULL );
 
-  //g_static_mutex_lock( &mutex );
+  g_static_mutex_lock( &mutex );
 
   io_cond = g_io_channel_get_buffer_condition( io_channel );
 
@@ -832,13 +858,57 @@
     gmyth_string_list_append_char_array( strlist, 
     		/*transfer->live_tv ? "REQUEST_BLOCK_RINGBUF" :*/ "REQUEST_BLOCK" );
     gmyth_string_list_append_int( strlist, remaining );
-	gmyth_socket_write_stringlist( transfer->control_sock, strlist );
+		gmyth_socket_write_stringlist( transfer->control_sock, strlist );
+		
+		gint backend_msg_count = 2;
+				
+		/* iterates until find some non-MythTV backend message */
+		do {		
+	    gmyth_socket_read_stringlist( transfer->control_sock, strlist );
+	    if ( strlist != NULL && gmyth_string_list_length( strlist ) > 0 ) 
+	    { 
+	    	if ( gmyth_file_transfer_is_backend_message( transfer, strlist ) )
+	    	{
+	    		recv = 0;
+	    		sent = 0;
+	    		response = FALSE;
+	    		found_backend_msg = TRUE;
+	    	} 
+	    	else 
+	    	{
+	      	sent = gmyth_string_list_get_int( strlist,  0 ); // -1 on backend error
+	      	g_print( "[%s] got SENT buffer message = %d\n", __FUNCTION__, sent );
+	      	if ( sent != 0 )
+	      	{
+	      		g_print( "[%s]\t received = %d bytes, backend says %d bytes sent, "\
+	      			"io_cond %s prepared for reading! (G_IO_IN) !!!\n\n", __FUNCTION__, 
+		  			recv, sent, ( ( io_cond & G_IO_IN ) != 0 ) ? "IS" : "IS NOT" );
 	
-	guint count_bytes = 0;
+		  		if ( sent == remaining )
+		  		{
+		  			//response = ( recv == size ); 
+		  			g_print( "[%s]\t\tsent %d, which is equals to requested size = %d\n\n", 
+		  						__FUNCTION__, sent, remaining );
+		  		}
+		  		else
+		  		{
+		  			g_print( "[%s]\t\tsent %d, which is NOT equals to requested size = %d\n\n", 
+		  						__FUNCTION__, sent, remaining );
+		  			goto cleanup;
+	
+		  		}
+	      	} else {
+	      		break;
+	      		//goto cleanup;
+	      	} // if
+	    	}
+	    }
+		} while ( found_backend_msg && --backend_msg_count > 0 );
+		
+    guint count_bytes = 0;
       
     do
     {
-      //buf_len = ( sent - recv ) > GMYTHTV_BUFFER_SIZE ? GMYTHTV_BUFFER_SIZE : ( sent - recv );
       if ( remaining > GMYTHTV_BUFFER_SIZE ) {
       	buf_len = GMYTHTV_BUFFER_SIZE;
       } else {
@@ -849,44 +919,39 @@
 
       io_status = g_io_channel_read_chars( io_channel, data + recv, 
 	  		buf_len, &bytes_read, &error );
-	  
-	  //g_static_mutex_unlock( &mutex );
+
       /*
-	 GString *sss = g_string_new("");
-	 sss = g_string_append_len( sss, (gchar*)data+recv, bytes_read );
-
-	 g_print( "[%s] Reading buffer (length = %d)\n", __FUNCTION__, bytes_read);
-	 */
+			 GString *sss = g_string_new("");
+			 sss = g_string_append_len( sss, (gchar*)data+recv, bytes_read );
+		
+			 g_print( "[%s] Reading buffer (length = %d)\n", __FUNCTION__, bytes_read);
+	 		*/
       if ( bytes_read > 0 )
       {
-	//if ( bytes_read <= buf_len )
-		  recv += bytes_read;
-		  count_bytes += bytes_read;
-		  remaining -= bytes_read;
-		  g_print( "[%s] Reading buffer (bytes read = %d, remaining = %d)\n", __FUNCTION__, bytes_read, remaining );
-		  if ( remaining == 0 ) {
-		  	break;
-		  }
+			  recv += bytes_read;
+			  count_bytes += bytes_read;
+			  remaining -= bytes_read;
+			  g_print( "[%s] Reading buffer (bytes read = %d, remaining = %d)\n", __FUNCTION__, bytes_read, remaining );
+			  /*
+			  if ( remaining == 0 ) {
+			  	break;
+			  }
+			  */
       } else {
       	break;
       }
-      
-      //if ( remaining > 0 ) {
 
       if ( io_status == G_IO_STATUS_EOF ) {
-	g_print( "[%s] got EOS!", __FUNCTION__ );
-	break;
+				g_print( "[%s] got EOS!", __FUNCTION__ );
+				break;
       } else if ( io_status == G_IO_STATUS_ERROR ) {
-	g_print( "[%s] gmyth_file_transfer_read(): socket error.\n", __FUNCTION__ );
-	break;
+				g_print( "[%s] gmyth_file_transfer_read(): socket error.\n", __FUNCTION__ );
+				break;
       }
-      //}
 
       /* increase buffer size, to allow get more data (do not obey to the buffer size) */
       if ( read_unlimited == TRUE ) {
       	// FOR NOW, DO NOTHING!!!
-	//if ( recv > buf_len )
-	// sent += (bytes_read - buf_len) + 1;
       }
 
       /* verify if the input (read) buffer is ready to receive data */
@@ -894,98 +959,39 @@
 
       g_print( "[%s]\t io_cond %s prepared for reading! (G_IO_IN) !!!\n\n", __FUNCTION__, 
       		( ( io_cond & G_IO_IN ) != 0 ) ? "IS" : "IS NOT" );
-      		
-      //if ( recv == size )
-		//break;
 
     } while ( remaining > 0 );//&& ( io_status == G_IO_STATUS_NORMAL ) );
     
-   // if ( ( recv < size ) ) {
-    //	finish_read = FALSE;
-    //}
-
     io_cond_control = g_io_channel_get_buffer_condition( io_channel_control );
     if ( remaining == 0 )//( io_cond_control & G_IO_IN ) != 0  )
     {
-      gmyth_socket_read_stringlist( transfer->control_sock, strlist );
-      if ( strlist != NULL && gmyth_string_list_length( strlist ) > 0 ) 
-      {
-      	GString *back_msg = NULL;
-      	back_msg = gmyth_string_list_get_string( strlist, 0 );
-      	if ( back_msg != NULL && back_msg->str != NULL && strstr( back_msg, "BACKEND" ) != NULL )
-      	{
-      		recv = 0;
-      		sent = 0;      		      	
-      	} 
-      	else 
-      	{
-	      	sent = gmyth_string_list_get_int( strlist,  0 ); // -1 on backend error
-	      	g_print( "[%s] got SENT buffer message = %d\n", __FUNCTION__, sent );
-	      	if ( sent != 0 )
-	      	{
-	      		g_print( "[%s]\t received = %d bytes, backend says %d bytes sent, "\
-	      			"io_cond %s prepared for reading! (G_IO_IN) !!!\n\n", __FUNCTION__, 
-		  			recv, sent, ( ( io_cond & G_IO_IN ) != 0 ) ? "IS" : "IS NOT" );
-	
-		  		if ( sent == count_bytes )
-		  		{
-		  			response = ( recv == size ); 
-		  			g_print( "[%s]\t\tsent %d, which is equals to bytes_read = %d\n\n", 
-		  						__FUNCTION__, sent, count_bytes );
-		  			if ( response == TRUE )
-	      				break;
-		  		}
-		  		else
-		  		{
-		  			g_print( "[%s]\t\tsent %d, which is NOT equals to bytes_read = %d\n\n", 
-		  						__FUNCTION__, sent, count_bytes );
-		  			goto cleanup;
-		  			//response = FALSE;
-		  			//break;
-		  		}
-	      	} else {
-	      		break;
-	      		//goto cleanup;
-	      	} // if
-      	}
-      } // if - reading control response from backend
-    } else {
-    	response = FALSE;
-    } // if - stringlist response
+    	response = TRUE;
+   		break;
+	  }
     
   } // while
   
   io_cond_control = g_io_channel_get_buffer_condition( io_channel_control );
- // io_cond = g_io_channel_get_buffer_condition( io_channel );
 
-  if ( ( ( io_cond_control & G_IO_IN ) != 0 ) &&  		 
-  		//( response || ( recv == size ) ) )
-  		( recv <= 0  || sent <= 0 )  )
+  if ( ( ( io_cond_control & G_IO_IN ) != 0 ) /*&&  		 
+  		( response || ( recv == size ) ) )
+  		( recv <= 0  || sent <= 0 ) */ )
   {
     if ( gmyth_socket_read_stringlist( transfer->control_sock, strlist ) > 0 )
     {
       if ( strlist != NULL && gmyth_string_list_length(strlist) > 0 ) 
       {
-		sent = gmyth_string_list_get_int( strlist, 0 ); // -1 on backend error
-		g_print( "[%s]\t received = %d bytes -\tNOW returning from reading buffer I/O socket "\
-				 "[%s prepared for reading]! (G_IO_IN) !!!\n\n", __FUNCTION__, 
-	    	sent, ( ( io_cond & G_IO_IN ) != 0 ) ? "IS" : "IS NOT" );
+				gint backend_code = gmyth_string_list_get_int( strlist, 0 ); // -1 on backend error
+				g_print( "[%s]\t backend code = %d -\t"\
+				 		"[%s prepared for reading]! (G_IO_IN) !!!\n\n", __FUNCTION__, 
+	    			backend_code, ( ( io_cond & G_IO_IN ) != 0 ) ? "IS" : "IS NOT" );
       }
     }
-    else
-    {
-      g_printerr ( "gmyth_file_transfer_read(): No response from control socket.");
-      recv = -1;
-    }
-    
-  } 
-  else if ( error != NULL )
-  {
-      g_printerr( "[%s] Error occurred: (%d, %s)\n", __FUNCTION__, error->code, error->message );
   }
 
 cleanup:
-  //g_static_mutex_unlock (&mutex);
+  g_static_mutex_unlock (&mutex);
+  g_io_channel_flush( io_channel_control, NULL );
 
   if ( trash != NULL )
     g_free( trash );
@@ -997,15 +1003,17 @@
       "(rcvd and rept MUST be the same!)\n", size, 
       recv, sent );
 
-  //if ( ( recv != size ) || ( sent != size ) ) {
-    //recv = size;
-  //}
-
   if ( error != NULL ) {
     g_printerr( "Cleaning-up ERROR: %s [msg = %s, code = %d]\n", __FUNCTION__, error->message, 
-	error->code );
-	g_error_free( error );
+			error->code );
+		g_error_free( error );
   }
+  
+  if ( !response ) {
+  	recv = GMYTHTV_FILE_TRANSFER_READ_ERROR;
+  } else {
+  	transfer->readposition += recv;
+  }  
 
   return recv;
 }
diff -r 26845a19d06e -r 51fd70b817a8 gmyth/src/gmyth_file_transfer.h
--- a/gmyth/src/gmyth_file_transfer.h	Thu Oct 26 02:04:40 2006 +0100
+++ b/gmyth/src/gmyth_file_transfer.h	Thu Oct 26 02:05:43 2006 +0100
@@ -4,6 +4,7 @@
 #define __GMYTH_FILE_TRANSFER_H__
 
 #include <glib-object.h>
+#include <glib.h>
 
 #include "gmyth_socket.h"
 #include "gmyth_uri.h"
@@ -25,6 +26,7 @@
 #define IS_GMYTH_FILE_TRANSFER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_FILE_TRANSFER_TYPE))
 #define GMYTH_FILE_TRANSFER_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_FILE_TRANSFER_TYPE, GMythFileTransferClass))
 
+#define GMYTHTV_FILE_TRANSFER_READ_ERROR	-314
 
 typedef struct _GMythFileTransfer         GMythFileTransfer;
 typedef struct _GMythFileTransferClass    GMythFileTransferClass;
@@ -52,7 +54,7 @@
 	GMythSocket *event_sock;
 	GMythSocket *sock;
 
-	guint64 readposition;
+	gint64 readposition;
 	guint64 filesize;
 	gboolean timeoutisfast;
 	gboolean userreadahead;
@@ -66,6 +68,9 @@
 	gint card_id;
 	GString *hostname;
 	gint port;
+	
+	/* stores the messages coming from the backend */
+	GHashTable *backend_msgs;
 };
 
 GType          gmyth_file_transfer_get_type        (void);
diff -r 26845a19d06e -r 51fd70b817a8 gmyth/src/gmyth_livetv.c
--- a/gmyth/src/gmyth_livetv.c	Thu Oct 26 02:04:40 2006 +0100
+++ b/gmyth/src/gmyth_livetv.c	Thu Oct 26 02:05:43 2006 +0100
@@ -162,6 +162,63 @@
 	return res;
 
 error:
+	g_print( "[%s] ERROR running LiveTV setup.\n", __FUNCTION__ );
+	if ( livetv->backend_hostname != NULL ) {
+		g_string_free( livetv->backend_hostname, TRUE );
+		res = FALSE;
+	}
+
+	if ( livetv->local_hostname != NULL ) {
+		g_string_free( livetv->local_hostname, TRUE );
+		res = FALSE;
+	}
+
+	if ( livetv->remote_encoder != NULL ) {
+		g_object_unref (livetv->remote_encoder);
+		livetv->remote_encoder = NULL;
+	}
+
+	if ( livetv->tvchain != NULL ) {
+		g_object_unref (livetv->tvchain);
+		livetv->tvchain = NULL;
+	}
+
+	if ( livetv->proginfo != NULL ) {
+		g_object_unref (livetv->proginfo);
+		livetv->proginfo = NULL;
+	}
+
+	return res;
+
+}
+
+gboolean
+gmyth_livetv_next_program_chain ( GMythLiveTV *livetv )
+{
+	gboolean res = TRUE;
+	
+	// Reload all TV chain from Mysql database.
+	gmyth_tvchain_reload_all (livetv->tvchain);
+
+	if ( livetv->tvchain == NULL ) {
+		res = FALSE;
+		goto error;
+	}
+
+	// Get program info from database using chanid and starttime
+	livetv->proginfo = gmyth_tvchain_get_program_at (livetv->tvchain, -1 );
+	if ( livetv->proginfo == NULL ) {
+		g_warning ("[%s] LiveTV not successfully started on the next program chain.\n", __FUNCTION__ );
+		res = FALSE;
+		goto error;
+	} else {
+		g_debug ("[%s] GMythLiveTV: All requests to backend to start TV were OK, TV chain changed.\n", __FUNCTION__ );
+	}
+
+	return res;
+
+error:
+	g_print( "[%s] ERROR running LiveTV setup.\n", __FUNCTION__ );
 	if ( livetv->backend_hostname != NULL ) {
 		g_string_free( livetv->backend_hostname, TRUE );
 		res = FALSE;
diff -r 26845a19d06e -r 51fd70b817a8 gmyth/src/gmyth_livetv.h
--- a/gmyth/src/gmyth_livetv.h	Thu Oct 26 02:04:40 2006 +0100
+++ b/gmyth/src/gmyth_livetv.h	Thu Oct 26 02:05:43 2006 +0100
@@ -53,6 +53,7 @@
 void gmyth_livetv_stop_playing (GMythLiveTV *livetv);
 
 gboolean gmyth_livetv_setup (GMythLiveTV *livetv);
+gboolean gmyth_livetv_next_program_chain ( GMythLiveTV *livetv );
 
 #define G_END_DECLS
 
diff -r 26845a19d06e -r 51fd70b817a8 gmyth/src/gmyth_tvchain.c
--- a/gmyth/src/gmyth_tvchain.c	Thu Oct 26 02:04:40 2006 +0100
+++ b/gmyth/src/gmyth_tvchain.c	Thu Oct 26 02:05:43 2006 +0100
@@ -155,7 +155,8 @@
 	GString *stmt_str;
 
 	g_static_mutex_lock( &mutex );
-
+	
+	/* gets the initial size of the TVChain entries list */
 	guint prev_size = g_list_length (tvchain->tvchain_list);
 
 	g_debug ("[%s] chainid: %s", __FUNCTION__, tvchain->tvchain_id->str);
@@ -199,6 +200,12 @@
 			entry->inputname = g_string_new (msql_row[8]);
 
 			//m_maxpos = query.value(4).toInt() + 1;
+			g_print( "[%s] Reading TV chain entry: [%s, %s, %s]\n", __FUNCTION__, entry->chanid->str, 
+					(gchar*)msql_row[1], (gchar*)msql_row[2] );
+			
+			/* add this to get the actual start timestamp of the last recording */
+			if ( tvchain->cur_startts < entry->starttime )
+				tvchain->cur_startts = entry->starttime;
 
 			tvchain->tvchain_list = g_list_append (tvchain->tvchain_list, entry);			
 		}
@@ -213,6 +220,7 @@
 	g_static_mutex_unlock( &mutex );
 	
 	tvchain->cur_pos = gmyth_tvchain_program_is_at (tvchain, tvchain->cur_chanid, tvchain->cur_startts);
+	g_print( "[%s] TVChain current position = %d.\n", __FUNCTION__, tvchain->cur_pos );
 
 	if (tvchain->cur_pos < 0)
 		tvchain->cur_pos = 0;
@@ -250,10 +258,11 @@
 	int count = 0;
 	struct LiveTVChainEntry *entry;
 	GList *tmp_list = tvchain->tvchain_list;
+	guint list_size = g_list_length (tvchain->tvchain_list);
 
 	g_static_mutex_lock( &mutex );
 	
-	for (; tmp_list; tmp_list = tvchain->tvchain_list->next, ++count)
+	for (; tmp_list && ( count < list_size ); tmp_list = tvchain->tvchain_list->next, count++)
 	{
 		entry = (struct LiveTVChainEntry*) tmp_list->data;
 		if (!g_strncasecmp (entry->chanid->str, chanid->str, chanid->len)