[svn r55] Fixes on the TVChain manipulation, error when trying to get the last program chain.
1.1 --- a/gmyth/src/gmyth_file_transfer.c Thu Oct 26 02:04:40 2006 +0100
1.2 +++ b/gmyth/src/gmyth_file_transfer.c Thu Oct 26 02:05:43 2006 +0100
1.3 @@ -24,29 +24,29 @@
1.4 #include <errno.h>
1.5 #include <stdlib.h>
1.6
1.7 -#define GMYTHTV_QUERY_HEADER "QUERY_FILETRANSFER"
1.8 -#define GMYTHTV_RECORDER_HEADER "QUERY_RECORDER"
1.9 +#define GMYTHTV_QUERY_HEADER "QUERY_FILETRANSFER"
1.10 +#define GMYTHTV_RECORDER_HEADER "QUERY_RECORDER"
1.11
1.12 /* default values to the file transfer parameters */
1.13 -#define GMYTHTV_USER_READ_AHEAD FALSE
1.14 -#define GMYTHTV_RETRIES 1
1.15 -#define GMYTHTV_FILE_SIZE -1
1.16 +#define GMYTHTV_USER_READ_AHEAD FALSE
1.17 +#define GMYTHTV_RETRIES 1
1.18 +#define GMYTHTV_FILE_SIZE 0
1.19
1.20 -#define GMYTHTV_BUFFER_SIZE 8*1024
1.21 +#define GMYTHTV_BUFFER_SIZE 8*1024
1.22
1.23 -#define GMYTHTV_VERSION 30
1.24 +#define GMYTHTV_VERSION 30
1.25
1.26 #define GMYTHTV_TRANSFER_MAX_WAITS 700
1.27
1.28 #ifdef GMYTHTV_ENABLE_DEBUG
1.29 -#define GMYTHTV_ENABLE_DEBUG 1
1.30 +#define GMYTHTV_ENABLE_DEBUG 1
1.31 #else
1.32 #undef GMYTHTV_ENABLE_DEBUG
1.33 #endif
1.34
1.35 /* this NDEBUG is to maintain compatibility with GMyth library */
1.36 #ifndef NDEBUG
1.37 -#define GMYTHTV_ENABLE_DEBUG 1
1.38 +#define GMYTHTV_ENABLE_DEBUG 1
1.39 #endif
1.40
1.41 static guint wait_to_transfer = 0;
1.42 @@ -168,6 +168,8 @@
1.43 transfer->retries = GMYTHTV_RETRIES;
1.44
1.45 transfer->live_tv = FALSE;
1.46 +
1.47 + transfer->backend_msgs = g_hash_table_new( g_int_hash, g_int_equal );
1.48
1.49 transfer->query = g_string_new( GMYTHTV_QUERY_HEADER );
1.50 g_string_append_printf ( transfer->query, " %d", transfer->recordernum );
1.51 @@ -703,6 +705,29 @@
1.52 return NULL;
1.53 }
1.54
1.55 +static gboolean
1.56 +gmyth_file_transfer_is_backend_message( GMythFileTransfer *transfer,
1.57 + GMythStringList* strlist )
1.58 +{
1.59 + gboolean found_backend_msg = FALSE;
1.60 + GString *back_msg = NULL;
1.61 +
1.62 + back_msg = gmyth_string_list_get_string( strlist, 0 );
1.63 + if ( back_msg != NULL && back_msg->str != NULL &&
1.64 + strstr( back_msg->str, "BACKEND" ) != NULL )
1.65 + {
1.66 + found_backend_msg = TRUE;
1.67 + if ( transfer->backend_msgs != NULL ) {
1.68 +
1.69 + g_hash_table_insert ( transfer->backend_msgs,
1.70 + &(transfer->readposition), back_msg );
1.71 +
1.72 + }
1.73 + }
1.74 +
1.75 + return found_backend_msg;
1.76 +
1.77 +}
1.78
1.79 gint
1.80 gmyth_file_transfer_read(GMythFileTransfer *transfer, void *data, gint size, gboolean read_unlimited)
1.81 @@ -724,6 +749,7 @@
1.82
1.83 GMythStringList *strlist = NULL;
1.84 GError *error = NULL;
1.85 + gboolean found_backend_msg = FALSE;
1.86
1.87 gchar *trash = g_strdup("");
1.88
1.89 @@ -819,7 +845,7 @@
1.90
1.91 //g_io_channel_flush( io_channel, NULL );
1.92
1.93 - //g_static_mutex_lock( &mutex );
1.94 + g_static_mutex_lock( &mutex );
1.95
1.96 io_cond = g_io_channel_get_buffer_condition( io_channel );
1.97
1.98 @@ -832,13 +858,57 @@
1.99 gmyth_string_list_append_char_array( strlist,
1.100 /*transfer->live_tv ? "REQUEST_BLOCK_RINGBUF" :*/ "REQUEST_BLOCK" );
1.101 gmyth_string_list_append_int( strlist, remaining );
1.102 - gmyth_socket_write_stringlist( transfer->control_sock, strlist );
1.103 + gmyth_socket_write_stringlist( transfer->control_sock, strlist );
1.104 +
1.105 + gint backend_msg_count = 2;
1.106 +
1.107 + /* iterates until find some non-MythTV backend message */
1.108 + do {
1.109 + gmyth_socket_read_stringlist( transfer->control_sock, strlist );
1.110 + if ( strlist != NULL && gmyth_string_list_length( strlist ) > 0 )
1.111 + {
1.112 + if ( gmyth_file_transfer_is_backend_message( transfer, strlist ) )
1.113 + {
1.114 + recv = 0;
1.115 + sent = 0;
1.116 + response = FALSE;
1.117 + found_backend_msg = TRUE;
1.118 + }
1.119 + else
1.120 + {
1.121 + sent = gmyth_string_list_get_int( strlist, 0 ); // -1 on backend error
1.122 + g_print( "[%s] got SENT buffer message = %d\n", __FUNCTION__, sent );
1.123 + if ( sent != 0 )
1.124 + {
1.125 + g_print( "[%s]\t received = %d bytes, backend says %d bytes sent, "\
1.126 + "io_cond %s prepared for reading! (G_IO_IN) !!!\n\n", __FUNCTION__,
1.127 + recv, sent, ( ( io_cond & G_IO_IN ) != 0 ) ? "IS" : "IS NOT" );
1.128
1.129 - guint count_bytes = 0;
1.130 + if ( sent == remaining )
1.131 + {
1.132 + //response = ( recv == size );
1.133 + g_print( "[%s]\t\tsent %d, which is equals to requested size = %d\n\n",
1.134 + __FUNCTION__, sent, remaining );
1.135 + }
1.136 + else
1.137 + {
1.138 + g_print( "[%s]\t\tsent %d, which is NOT equals to requested size = %d\n\n",
1.139 + __FUNCTION__, sent, remaining );
1.140 + goto cleanup;
1.141 +
1.142 + }
1.143 + } else {
1.144 + break;
1.145 + //goto cleanup;
1.146 + } // if
1.147 + }
1.148 + }
1.149 + } while ( found_backend_msg && --backend_msg_count > 0 );
1.150 +
1.151 + guint count_bytes = 0;
1.152
1.153 do
1.154 {
1.155 - //buf_len = ( sent - recv ) > GMYTHTV_BUFFER_SIZE ? GMYTHTV_BUFFER_SIZE : ( sent - recv );
1.156 if ( remaining > GMYTHTV_BUFFER_SIZE ) {
1.157 buf_len = GMYTHTV_BUFFER_SIZE;
1.158 } else {
1.159 @@ -849,44 +919,39 @@
1.160
1.161 io_status = g_io_channel_read_chars( io_channel, data + recv,
1.162 buf_len, &bytes_read, &error );
1.163 -
1.164 - //g_static_mutex_unlock( &mutex );
1.165 +
1.166 /*
1.167 - GString *sss = g_string_new("");
1.168 - sss = g_string_append_len( sss, (gchar*)data+recv, bytes_read );
1.169 -
1.170 - g_print( "[%s] Reading buffer (length = %d)\n", __FUNCTION__, bytes_read);
1.171 - */
1.172 + GString *sss = g_string_new("");
1.173 + sss = g_string_append_len( sss, (gchar*)data+recv, bytes_read );
1.174 +
1.175 + g_print( "[%s] Reading buffer (length = %d)\n", __FUNCTION__, bytes_read);
1.176 + */
1.177 if ( bytes_read > 0 )
1.178 {
1.179 - //if ( bytes_read <= buf_len )
1.180 - recv += bytes_read;
1.181 - count_bytes += bytes_read;
1.182 - remaining -= bytes_read;
1.183 - g_print( "[%s] Reading buffer (bytes read = %d, remaining = %d)\n", __FUNCTION__, bytes_read, remaining );
1.184 - if ( remaining == 0 ) {
1.185 - break;
1.186 - }
1.187 + recv += bytes_read;
1.188 + count_bytes += bytes_read;
1.189 + remaining -= bytes_read;
1.190 + g_print( "[%s] Reading buffer (bytes read = %d, remaining = %d)\n", __FUNCTION__, bytes_read, remaining );
1.191 + /*
1.192 + if ( remaining == 0 ) {
1.193 + break;
1.194 + }
1.195 + */
1.196 } else {
1.197 break;
1.198 }
1.199 -
1.200 - //if ( remaining > 0 ) {
1.201
1.202 if ( io_status == G_IO_STATUS_EOF ) {
1.203 - g_print( "[%s] got EOS!", __FUNCTION__ );
1.204 - break;
1.205 + g_print( "[%s] got EOS!", __FUNCTION__ );
1.206 + break;
1.207 } else if ( io_status == G_IO_STATUS_ERROR ) {
1.208 - g_print( "[%s] gmyth_file_transfer_read(): socket error.\n", __FUNCTION__ );
1.209 - break;
1.210 + g_print( "[%s] gmyth_file_transfer_read(): socket error.\n", __FUNCTION__ );
1.211 + break;
1.212 }
1.213 - //}
1.214
1.215 /* increase buffer size, to allow get more data (do not obey to the buffer size) */
1.216 if ( read_unlimited == TRUE ) {
1.217 // FOR NOW, DO NOTHING!!!
1.218 - //if ( recv > buf_len )
1.219 - // sent += (bytes_read - buf_len) + 1;
1.220 }
1.221
1.222 /* verify if the input (read) buffer is ready to receive data */
1.223 @@ -894,98 +959,39 @@
1.224
1.225 g_print( "[%s]\t io_cond %s prepared for reading! (G_IO_IN) !!!\n\n", __FUNCTION__,
1.226 ( ( io_cond & G_IO_IN ) != 0 ) ? "IS" : "IS NOT" );
1.227 -
1.228 - //if ( recv == size )
1.229 - //break;
1.230
1.231 } while ( remaining > 0 );//&& ( io_status == G_IO_STATUS_NORMAL ) );
1.232
1.233 - // if ( ( recv < size ) ) {
1.234 - // finish_read = FALSE;
1.235 - //}
1.236 -
1.237 io_cond_control = g_io_channel_get_buffer_condition( io_channel_control );
1.238 if ( remaining == 0 )//( io_cond_control & G_IO_IN ) != 0 )
1.239 {
1.240 - gmyth_socket_read_stringlist( transfer->control_sock, strlist );
1.241 - if ( strlist != NULL && gmyth_string_list_length( strlist ) > 0 )
1.242 - {
1.243 - GString *back_msg = NULL;
1.244 - back_msg = gmyth_string_list_get_string( strlist, 0 );
1.245 - if ( back_msg != NULL && back_msg->str != NULL && strstr( back_msg, "BACKEND" ) != NULL )
1.246 - {
1.247 - recv = 0;
1.248 - sent = 0;
1.249 - }
1.250 - else
1.251 - {
1.252 - sent = gmyth_string_list_get_int( strlist, 0 ); // -1 on backend error
1.253 - g_print( "[%s] got SENT buffer message = %d\n", __FUNCTION__, sent );
1.254 - if ( sent != 0 )
1.255 - {
1.256 - g_print( "[%s]\t received = %d bytes, backend says %d bytes sent, "\
1.257 - "io_cond %s prepared for reading! (G_IO_IN) !!!\n\n", __FUNCTION__,
1.258 - recv, sent, ( ( io_cond & G_IO_IN ) != 0 ) ? "IS" : "IS NOT" );
1.259 -
1.260 - if ( sent == count_bytes )
1.261 - {
1.262 - response = ( recv == size );
1.263 - g_print( "[%s]\t\tsent %d, which is equals to bytes_read = %d\n\n",
1.264 - __FUNCTION__, sent, count_bytes );
1.265 - if ( response == TRUE )
1.266 - break;
1.267 - }
1.268 - else
1.269 - {
1.270 - g_print( "[%s]\t\tsent %d, which is NOT equals to bytes_read = %d\n\n",
1.271 - __FUNCTION__, sent, count_bytes );
1.272 - goto cleanup;
1.273 - //response = FALSE;
1.274 - //break;
1.275 - }
1.276 - } else {
1.277 - break;
1.278 - //goto cleanup;
1.279 - } // if
1.280 - }
1.281 - } // if - reading control response from backend
1.282 - } else {
1.283 - response = FALSE;
1.284 - } // if - stringlist response
1.285 + response = TRUE;
1.286 + break;
1.287 + }
1.288
1.289 } // while
1.290
1.291 io_cond_control = g_io_channel_get_buffer_condition( io_channel_control );
1.292 - // io_cond = g_io_channel_get_buffer_condition( io_channel );
1.293
1.294 - if ( ( ( io_cond_control & G_IO_IN ) != 0 ) &&
1.295 - //( response || ( recv == size ) ) )
1.296 - ( recv <= 0 || sent <= 0 ) )
1.297 + if ( ( ( io_cond_control & G_IO_IN ) != 0 ) /*&&
1.298 + ( response || ( recv == size ) ) )
1.299 + ( recv <= 0 || sent <= 0 ) */ )
1.300 {
1.301 if ( gmyth_socket_read_stringlist( transfer->control_sock, strlist ) > 0 )
1.302 {
1.303 if ( strlist != NULL && gmyth_string_list_length(strlist) > 0 )
1.304 {
1.305 - sent = gmyth_string_list_get_int( strlist, 0 ); // -1 on backend error
1.306 - g_print( "[%s]\t received = %d bytes -\tNOW returning from reading buffer I/O socket "\
1.307 - "[%s prepared for reading]! (G_IO_IN) !!!\n\n", __FUNCTION__,
1.308 - sent, ( ( io_cond & G_IO_IN ) != 0 ) ? "IS" : "IS NOT" );
1.309 + gint backend_code = gmyth_string_list_get_int( strlist, 0 ); // -1 on backend error
1.310 + g_print( "[%s]\t backend code = %d -\t"\
1.311 + "[%s prepared for reading]! (G_IO_IN) !!!\n\n", __FUNCTION__,
1.312 + backend_code, ( ( io_cond & G_IO_IN ) != 0 ) ? "IS" : "IS NOT" );
1.313 }
1.314 }
1.315 - else
1.316 - {
1.317 - g_printerr ( "gmyth_file_transfer_read(): No response from control socket.");
1.318 - recv = -1;
1.319 - }
1.320 -
1.321 - }
1.322 - else if ( error != NULL )
1.323 - {
1.324 - g_printerr( "[%s] Error occurred: (%d, %s)\n", __FUNCTION__, error->code, error->message );
1.325 }
1.326
1.327 cleanup:
1.328 - //g_static_mutex_unlock (&mutex);
1.329 + g_static_mutex_unlock (&mutex);
1.330 + g_io_channel_flush( io_channel_control, NULL );
1.331
1.332 if ( trash != NULL )
1.333 g_free( trash );
1.334 @@ -997,15 +1003,17 @@
1.335 "(rcvd and rept MUST be the same!)\n", size,
1.336 recv, sent );
1.337
1.338 - //if ( ( recv != size ) || ( sent != size ) ) {
1.339 - //recv = size;
1.340 - //}
1.341 -
1.342 if ( error != NULL ) {
1.343 g_printerr( "Cleaning-up ERROR: %s [msg = %s, code = %d]\n", __FUNCTION__, error->message,
1.344 - error->code );
1.345 - g_error_free( error );
1.346 + error->code );
1.347 + g_error_free( error );
1.348 }
1.349 +
1.350 + if ( !response ) {
1.351 + recv = GMYTHTV_FILE_TRANSFER_READ_ERROR;
1.352 + } else {
1.353 + transfer->readposition += recv;
1.354 + }
1.355
1.356 return recv;
1.357 }
2.1 --- a/gmyth/src/gmyth_file_transfer.h Thu Oct 26 02:04:40 2006 +0100
2.2 +++ b/gmyth/src/gmyth_file_transfer.h Thu Oct 26 02:05:43 2006 +0100
2.3 @@ -4,6 +4,7 @@
2.4 #define __GMYTH_FILE_TRANSFER_H__
2.5
2.6 #include <glib-object.h>
2.7 +#include <glib.h>
2.8
2.9 #include "gmyth_socket.h"
2.10 #include "gmyth_uri.h"
2.11 @@ -25,6 +26,7 @@
2.12 #define IS_GMYTH_FILE_TRANSFER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_FILE_TRANSFER_TYPE))
2.13 #define GMYTH_FILE_TRANSFER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_FILE_TRANSFER_TYPE, GMythFileTransferClass))
2.14
2.15 +#define GMYTHTV_FILE_TRANSFER_READ_ERROR -314
2.16
2.17 typedef struct _GMythFileTransfer GMythFileTransfer;
2.18 typedef struct _GMythFileTransferClass GMythFileTransferClass;
2.19 @@ -52,7 +54,7 @@
2.20 GMythSocket *event_sock;
2.21 GMythSocket *sock;
2.22
2.23 - guint64 readposition;
2.24 + gint64 readposition;
2.25 guint64 filesize;
2.26 gboolean timeoutisfast;
2.27 gboolean userreadahead;
2.28 @@ -66,6 +68,9 @@
2.29 gint card_id;
2.30 GString *hostname;
2.31 gint port;
2.32 +
2.33 + /* stores the messages coming from the backend */
2.34 + GHashTable *backend_msgs;
2.35 };
2.36
2.37 GType gmyth_file_transfer_get_type (void);
3.1 --- a/gmyth/src/gmyth_livetv.c Thu Oct 26 02:04:40 2006 +0100
3.2 +++ b/gmyth/src/gmyth_livetv.c Thu Oct 26 02:05:43 2006 +0100
3.3 @@ -162,6 +162,63 @@
3.4 return res;
3.5
3.6 error:
3.7 + g_print( "[%s] ERROR running LiveTV setup.\n", __FUNCTION__ );
3.8 + if ( livetv->backend_hostname != NULL ) {
3.9 + g_string_free( livetv->backend_hostname, TRUE );
3.10 + res = FALSE;
3.11 + }
3.12 +
3.13 + if ( livetv->local_hostname != NULL ) {
3.14 + g_string_free( livetv->local_hostname, TRUE );
3.15 + res = FALSE;
3.16 + }
3.17 +
3.18 + if ( livetv->remote_encoder != NULL ) {
3.19 + g_object_unref (livetv->remote_encoder);
3.20 + livetv->remote_encoder = NULL;
3.21 + }
3.22 +
3.23 + if ( livetv->tvchain != NULL ) {
3.24 + g_object_unref (livetv->tvchain);
3.25 + livetv->tvchain = NULL;
3.26 + }
3.27 +
3.28 + if ( livetv->proginfo != NULL ) {
3.29 + g_object_unref (livetv->proginfo);
3.30 + livetv->proginfo = NULL;
3.31 + }
3.32 +
3.33 + return res;
3.34 +
3.35 +}
3.36 +
3.37 +gboolean
3.38 +gmyth_livetv_next_program_chain ( GMythLiveTV *livetv )
3.39 +{
3.40 + gboolean res = TRUE;
3.41 +
3.42 + // Reload all TV chain from Mysql database.
3.43 + gmyth_tvchain_reload_all (livetv->tvchain);
3.44 +
3.45 + if ( livetv->tvchain == NULL ) {
3.46 + res = FALSE;
3.47 + goto error;
3.48 + }
3.49 +
3.50 + // Get program info from database using chanid and starttime
3.51 + livetv->proginfo = gmyth_tvchain_get_program_at (livetv->tvchain, -1 );
3.52 + if ( livetv->proginfo == NULL ) {
3.53 + g_warning ("[%s] LiveTV not successfully started on the next program chain.\n", __FUNCTION__ );
3.54 + res = FALSE;
3.55 + goto error;
3.56 + } else {
3.57 + g_debug ("[%s] GMythLiveTV: All requests to backend to start TV were OK, TV chain changed.\n", __FUNCTION__ );
3.58 + }
3.59 +
3.60 + return res;
3.61 +
3.62 +error:
3.63 + g_print( "[%s] ERROR running LiveTV setup.\n", __FUNCTION__ );
3.64 if ( livetv->backend_hostname != NULL ) {
3.65 g_string_free( livetv->backend_hostname, TRUE );
3.66 res = FALSE;
4.1 --- a/gmyth/src/gmyth_livetv.h Thu Oct 26 02:04:40 2006 +0100
4.2 +++ b/gmyth/src/gmyth_livetv.h Thu Oct 26 02:05:43 2006 +0100
4.3 @@ -53,6 +53,7 @@
4.4 void gmyth_livetv_stop_playing (GMythLiveTV *livetv);
4.5
4.6 gboolean gmyth_livetv_setup (GMythLiveTV *livetv);
4.7 +gboolean gmyth_livetv_next_program_chain ( GMythLiveTV *livetv );
4.8
4.9 #define G_END_DECLS
4.10
5.1 --- a/gmyth/src/gmyth_tvchain.c Thu Oct 26 02:04:40 2006 +0100
5.2 +++ b/gmyth/src/gmyth_tvchain.c Thu Oct 26 02:05:43 2006 +0100
5.3 @@ -155,7 +155,8 @@
5.4 GString *stmt_str;
5.5
5.6 g_static_mutex_lock( &mutex );
5.7 -
5.8 +
5.9 + /* gets the initial size of the TVChain entries list */
5.10 guint prev_size = g_list_length (tvchain->tvchain_list);
5.11
5.12 g_debug ("[%s] chainid: %s", __FUNCTION__, tvchain->tvchain_id->str);
5.13 @@ -199,6 +200,12 @@
5.14 entry->inputname = g_string_new (msql_row[8]);
5.15
5.16 //m_maxpos = query.value(4).toInt() + 1;
5.17 + g_print( "[%s] Reading TV chain entry: [%s, %s, %s]\n", __FUNCTION__, entry->chanid->str,
5.18 + (gchar*)msql_row[1], (gchar*)msql_row[2] );
5.19 +
5.20 + /* add this to get the actual start timestamp of the last recording */
5.21 + if ( tvchain->cur_startts < entry->starttime )
5.22 + tvchain->cur_startts = entry->starttime;
5.23
5.24 tvchain->tvchain_list = g_list_append (tvchain->tvchain_list, entry);
5.25 }
5.26 @@ -213,6 +220,7 @@
5.27 g_static_mutex_unlock( &mutex );
5.28
5.29 tvchain->cur_pos = gmyth_tvchain_program_is_at (tvchain, tvchain->cur_chanid, tvchain->cur_startts);
5.30 + g_print( "[%s] TVChain current position = %d.\n", __FUNCTION__, tvchain->cur_pos );
5.31
5.32 if (tvchain->cur_pos < 0)
5.33 tvchain->cur_pos = 0;
5.34 @@ -250,10 +258,11 @@
5.35 int count = 0;
5.36 struct LiveTVChainEntry *entry;
5.37 GList *tmp_list = tvchain->tvchain_list;
5.38 + guint list_size = g_list_length (tvchain->tvchain_list);
5.39
5.40 g_static_mutex_lock( &mutex );
5.41
5.42 - for (; tmp_list; tmp_list = tvchain->tvchain_list->next, ++count)
5.43 + for (; tmp_list && ( count < list_size ); tmp_list = tvchain->tvchain_list->next, count++)
5.44 {
5.45 entry = (struct LiveTVChainEntry*) tmp_list->data;
5.46 if (!g_strncasecmp (entry->chanid->str, chanid->str, chanid->len)