[svn r42] Added FileTransfer, URI and LiveTV functionalities (moved from the MythTV plug-in). trunk
authorrosfran
Mon Oct 23 16:02:15 2006 +0100 (2006-10-23)
branchtrunk
changeset 41686549eb5657
parent 40 ba5dc9bff3a1
child 42 9a5f5a33cd87
[svn r42] Added FileTransfer, URI and LiveTV functionalities (moved from the MythTV plug-in).
gmyth/src/Makefile.am
gmyth/src/gmyth_file_transfer.c
gmyth/src/gmyth_file_transfer.h
gmyth/src/gmyth_livetv.c
gmyth/src/gmyth_livetv.h
gmyth/src/gmyth_stringlist.h
gmyth/src/gmyth_uri.c
gmyth/src/gmyth_uri.h
     1.1 --- a/gmyth/src/Makefile.am	Mon Oct 23 15:42:46 2006 +0100
     1.2 +++ b/gmyth/src/Makefile.am	Mon Oct 23 16:02:15 2006 +0100
     1.3 @@ -14,7 +14,10 @@
     1.4  	gmyth_util.c				\
     1.5  	gmyth_query.c				\
     1.6  	gmyth_socket.c				\
     1.7 -	gmyth_stringlist.c			
     1.8 +	gmyth_stringlist.c			\
     1.9 +	gmyth_file_transfer.c			\
    1.10 +	gmyth_livetv.c				\
    1.11 +	gmyth_uri.c
    1.12  
    1.13  libgmyth_la_CFLAGS = 			\
    1.14  	-DDATADIR=\"$(pkgdatadir)\" \
    1.15 @@ -51,7 +54,10 @@
    1.16  	gmyth_query.h 				\
    1.17  	gmyth_socket.h 				\
    1.18  	gmyth_remote_util.h			\
    1.19 -	gmyth_stringlist.h 			
    1.20 +	gmyth_stringlist.h 			\
    1.21 +	gmyth_file_transfer.h			\
    1.22 +	gmyth_livetv.h				\
    1.23 +	gmyth_uri.h
    1.24  
    1.25  CLEANFILES = $(BUILT_SOURCES)
    1.26  
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/gmyth/src/gmyth_file_transfer.c	Mon Oct 23 16:02:15 2006 +0100
     2.3 @@ -0,0 +1,1050 @@
     2.4 +/* vim: set sw=2: -*- Mode: C; tab-width: 2; indent-tabs-mode: t; c-basic-offset: 2; c-indent-level: 2-*- */
     2.5 +/**
     2.6 + * GStreamer plug-in properties:
     2.7 + * - location (backend server hostname/URL) [ex.: myth://192.168.1.73:28722/1000_1092091.nuv]
     2.8 + * - path (qurl - remote file to be opened)
     2.9 + * - port number
    2.10 + *   @author Rosfran Lins Borges <rosfran.borges@indt.org.br>
    2.11 + */
    2.12 +
    2.13 +#include <gmyth/gmyth_file_transfer.h>
    2.14 +#include <gmyth/gmyth_uri.h>
    2.15 +#include <gmyth/gmyth_livetv.h>
    2.16 +#include <gmyth/gmyth_util.h>
    2.17 +#include <gmyth/gmyth_socket.h>
    2.18 +#include <gmyth/gmyth_stringlist.h>
    2.19 +
    2.20 +#include <unistd.h>
    2.21 +#include <glib.h>
    2.22 +
    2.23 +#include <arpa/inet.h>
    2.24 +#include <sys/types.h>
    2.25 +#include <sys/socket.h>
    2.26 +#include <netdb.h>
    2.27 +#include <errno.h>
    2.28 +#include <stdlib.h>
    2.29 +
    2.30 +#define GMYTHTV_QUERY_HEADER "QUERY_FILETRANSFER"
    2.31 +#define GMYTHTV_RECORDER_HEADER "QUERY_RECORDER"
    2.32 +
    2.33 +/* default values to the file transfer parameters */
    2.34 +#define GMYTHTV_USER_READ_AHEAD	FALSE
    2.35 +#define GMYTHTV_RETRIES			1
    2.36 +#define GMYTHTV_FILE_SIZE		-1
    2.37 +
    2.38 +#define GMYTHTV_BUFFER_SIZE		8*1024
    2.39 +
    2.40 +#define GMYTHTV_VERSION			30
    2.41 +
    2.42 +#define GMYTHTV_TRANSFER_MAX_WAITS	700
    2.43 +
    2.44 +#ifdef GMYTHTV_ENABLE_DEBUG
    2.45 +#define GMYTHTV_ENABLE_DEBUG	1
    2.46 +#else
    2.47 +#undef GMYTHTV_ENABLE_DEBUG
    2.48 +#endif
    2.49 +
    2.50 +/* this NDEBUG is to maintain compatibility with GMyth library */
    2.51 +#ifndef NDEBUG
    2.52 +#define GMYTHTV_ENABLE_DEBUG	1
    2.53 +#endif
    2.54 +
    2.55 +static guint wait_to_transfer = 0;
    2.56 +
    2.57 +enum myth_sock_types {
    2.58 +  GMYTH_PLAYBACK_TYPE = 0,
    2.59 +  GMYTH_MONITOR_TYPE,
    2.60 +  GMYTH_FILETRANSFER_TYPE,
    2.61 +  GMYTH_RINGBUFFER_TYPE
    2.62 +};
    2.63 +
    2.64 +static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
    2.65 +
    2.66 +static GMainContext *io_watcher_context = NULL;
    2.67 +
    2.68 +static void gmyth_file_transfer_class_init          (GMythFileTransferClass *klass);
    2.69 +static void gmyth_file_transfer_init                (GMythFileTransfer *object);
    2.70 +
    2.71 +static void gmyth_file_transfer_dispose  (GObject *object);
    2.72 +static void gmyth_file_transfer_finalize (GObject *object);
    2.73 +
    2.74 +static GMythSocket *myth_connect_to_transfer_backend( GMythFileTransfer **transfer, guint sock_type );
    2.75 +static void* myth_init_io_watchers( void *data );
    2.76 +
    2.77 +void gmyth_file_transfer_close( GMythFileTransfer *transfer );
    2.78 +
    2.79 +G_DEFINE_TYPE(GMythFileTransfer, gmyth_file_transfer, G_TYPE_OBJECT)
    2.80 +
    2.81 +#if 0
    2.82 +static guint64
    2.83 +mmyth_util_decode_long_long( GMythStringList *strlist, guint offset  )
    2.84 +{
    2.85 +
    2.86 +  guint64 ret_value = 0LL;
    2.87 +
    2.88 +  g_return_val_if_fail( strlist != NULL, ret_value );
    2.89 +
    2.90 +  if ( offset < gmyth_string_list_length( strlist ))
    2.91 +    g_printerr( "[%s] Offset is lower than the GMythStringList (offset = %d)!\n", __FUNCTION__, offset );
    2.92 +  g_return_val_if_fail( offset < gmyth_string_list_length( strlist ), ret_value );
    2.93 +
    2.94 +  gint l1 = gmyth_string_list_get_int( strlist, offset );
    2.95 +  gint l2 = gmyth_string_list_get_int( strlist, offset + 1 );
    2.96 +
    2.97 +  ret_value = ((guint64)(l2) & 0xffffffffLL) | ((guint64)(l1) << 32);
    2.98 +
    2.99 +  return ret_value;
   2.100 +
   2.101 +}
   2.102 +#endif
   2.103 +
   2.104 +static void
   2.105 +gmyth_file_transfer_class_init (GMythFileTransferClass *klass)
   2.106 +{
   2.107 +  GObjectClass *gobject_class;
   2.108 +
   2.109 +  gobject_class = (GObjectClass *) klass;
   2.110 +
   2.111 +  gobject_class->dispose  = gmyth_file_transfer_dispose;
   2.112 +  gobject_class->finalize = gmyth_file_transfer_finalize;
   2.113 +}
   2.114 +
   2.115 +  static void
   2.116 +gmyth_file_transfer_init (GMythFileTransfer *gmyth_file_transfer)
   2.117 +{ 
   2.118 +  g_return_if_fail( gmyth_file_transfer != NULL );
   2.119 +  gmyth_file_transfer->mythtv_version = GMYTHTV_VERSION;
   2.120 +}
   2.121 +
   2.122 +static void
   2.123 +gmyth_file_transfer_dispose  (GObject *object)
   2.124 +{
   2.125 +  GMythFileTransfer *gmyth_file_transfer = GMYTH_FILE_TRANSFER(object);
   2.126 +
   2.127 +  gmyth_file_transfer_close( gmyth_file_transfer );
   2.128 +
   2.129 +  G_OBJECT_CLASS (gmyth_file_transfer_parent_class)->dispose (object);
   2.130 +}
   2.131 +
   2.132 +  static void
   2.133 +gmyth_file_transfer_finalize (GObject *object)
   2.134 +{
   2.135 +  g_signal_handlers_destroy (object);
   2.136 +
   2.137 +  G_OBJECT_CLASS (gmyth_file_transfer_parent_class)->finalize (object);
   2.138 +}
   2.139 +
   2.140 +  GMythFileTransfer*
   2.141 +gmyth_file_transfer_new (gint num, GString *uri_str, gshort port, gint mythtv_version)
   2.142 +{
   2.143 +  GMythFileTransfer *transfer = GMYTH_FILE_TRANSFER ( g_object_new (
   2.144 +	GMYTH_FILE_TRANSFER_TYPE, FALSE ));
   2.145 +
   2.146 +  if ( mythtv_version > 0 )
   2.147 +    transfer->mythtv_version = mythtv_version;
   2.148 +
   2.149 +  transfer->card_id = num;
   2.150 +
   2.151 +  transfer->rec_id = -1;
   2.152 +
   2.153 +  transfer->recordernum = num;
   2.154 +  transfer->uri = gmyth_uri_new ( uri_str->str );
   2.155 +
   2.156 +  transfer->hostname = g_string_new( gmyth_uri_gethost(transfer->uri) );
   2.157 +  g_print( "\t--> transfer->hostname = %s\n", transfer->hostname->str );
   2.158 +
   2.159 +  if ( port >= 0 )
   2.160 +    transfer->port = port;
   2.161 +  else
   2.162 +    transfer->port = gmyth_uri_getport( transfer->uri );
   2.163 +
   2.164 +  g_print( "\t--> transfer->port = %d\n", transfer->port );
   2.165 +
   2.166 +  transfer->readposition = 0;
   2.167 +  transfer->filesize = GMYTHTV_FILE_SIZE;
   2.168 +  transfer->timeoutisfast = FALSE;
   2.169 +
   2.170 +  transfer->userreadahead = GMYTHTV_USER_READ_AHEAD;
   2.171 +  transfer->retries = GMYTHTV_RETRIES;  
   2.172 +
   2.173 +  transfer->live_tv = FALSE;
   2.174 +
   2.175 +  transfer->query = g_string_new( GMYTHTV_QUERY_HEADER );
   2.176 +  g_string_append_printf ( transfer->query, " %d", transfer->recordernum );
   2.177 +  g_print( "\t--> transfer->query = %s\n", transfer->query->str );
   2.178 +
   2.179 +  transfer->control_sock = NULL;
   2.180 +  transfer->event_sock = NULL;
   2.181 +  transfer->sock = NULL;
   2.182 +
   2.183 +  return transfer;
   2.184 +}
   2.185 +
   2.186 +gboolean
   2.187 +gmyth_file_transfer_livetv_setup( GMythFileTransfer **transfer, GMythSocket *live_socket )
   2.188 +{
   2.189 +	(*transfer)->sock = live_socket;
   2.190 +	g_object_ref( live_socket );
   2.191 +
   2.192 +	return TRUE;
   2.193 +}
   2.194 +
   2.195 +gboolean
   2.196 +gmyth_file_transfer_playback_setup( GMythFileTransfer **transfer, gboolean live_tv )
   2.197 +{
   2.198 +
   2.199 +  gboolean ret = TRUE;
   2.200 +
   2.201 +  (*transfer)->live_tv = live_tv;
   2.202 +
   2.203 +  printf("[%s] Running config to the %s...\n", __FUNCTION__, live_tv ? "LiveTV" : "FileTransfer" );
   2.204 +
   2.205 +  /* configure the control socket */
   2.206 +  if ((*transfer)->control_sock == NULL) { 
   2.207 +
   2.208 +    if ( myth_connect_to_transfer_backend ( transfer, GMYTH_PLAYBACK_TYPE ) == NULL ) {
   2.209 +      g_printerr( "Connection to backend failed (Control Socket).\n" );
   2.210 +      ret = FALSE;
   2.211 +    }
   2.212 +
   2.213 +  } else {
   2.214 +    g_warning("Remote transfer control socket already created.\n");
   2.215 +  }
   2.216 +
   2.217 +  return ret;
   2.218 +
   2.219 +}
   2.220 +
   2.221 +gboolean
   2.222 +gmyth_file_transfer_setup( GMythFileTransfer **transfer, gboolean live_tv )
   2.223 +{
   2.224 +  GMythStringList *strlist = NULL;
   2.225 +
   2.226 +  gboolean ret = TRUE;
   2.227 +
   2.228 +  (*transfer)->live_tv = live_tv;
   2.229 +
   2.230 +  printf("[%s] Running config to the %s...\n", __FUNCTION__, live_tv ? "LiveTV" : "FileTransfer" );
   2.231 +
   2.232 +#if 0
   2.233 +  /* configure the control socket */
   2.234 +  if ((*transfer)->event_sock == NULL) { 
   2.235 +
   2.236 +    if ( myth_connect_to_transfer_backend ( transfer, GMYTH_MONITOR_TYPE ) == NULL ) {
   2.237 +      g_printerr( "Connection to backend failed (Event Socket).\n" );
   2.238 +      ret = FALSE;
   2.239 +    }
   2.240 +
   2.241 +  } else {
   2.242 +    g_warning("Remote transfer control socket already created.\n");
   2.243 +  }
   2.244 +#endif
   2.245 +
   2.246 +  /* configure the socket */
   2.247 +  if ( (*transfer)->sock == NULL ) { 
   2.248 +
   2.249 +    //if ( live_tv == FALSE ) {
   2.250 +
   2.251 +    if ( myth_connect_to_transfer_backend ( transfer, GMYTH_FILETRANSFER_TYPE ) == NULL ) {
   2.252 +      g_printerr ("Connection to backend failed (Raw Transfer Socket).\n");
   2.253 +      ret = FALSE;
   2.254 +    }
   2.255 +
   2.256 +    if ( !(*transfer)->live_tv && (*transfer)->control_sock != NULL) {
   2.257 +      strlist = gmyth_string_list_new();
   2.258 +      g_string_printf ( (*transfer)->query, "%s %d", GMYTHTV_QUERY_HEADER, (*transfer)->recordernum );
   2.259 +
   2.260 +      gmyth_string_list_append_string( strlist, (*transfer)->query );
   2.261 +      gmyth_string_list_append_char_array( strlist, "IS_OPEN" );
   2.262 +
   2.263 +      gmyth_socket_write_stringlist( (*transfer)->control_sock, strlist );
   2.264 +      gmyth_socket_read_stringlist( (*transfer)->control_sock, strlist );
   2.265 +
   2.266 +      if ( strlist!=NULL && gmyth_string_list_get_int( strlist, 0 ) == 1 ) {
   2.267 +	g_print( "[%s] Remote Myth FileTransfer socket is open!\n", __FUNCTION__ );
   2.268 +      } else {
   2.269 +	g_print( "[%s] Remote Myth FileTransfer socket is CLOSED! See the MythTV Server Backend for configuration details...\n", __FUNCTION__ );
   2.270 +	ret = FALSE;
   2.271 +      }
   2.272 +    }
   2.273 +
   2.274 +  } else {
   2.275 +    g_warning("Remote transfer (raw) socket already created.\n");
   2.276 +  }
   2.277 +
   2.278 +  return ret;
   2.279 +}
   2.280 +
   2.281 +static GMythSocket *
   2.282 +myth_connect_to_transfer_backend( GMythFileTransfer **transfer, guint sock_type )
   2.283 +{
   2.284 +  GMythSocket *sock = NULL;
   2.285 +
   2.286 +  g_return_val_if_fail( transfer != NULL && *transfer != NULL, NULL );
   2.287 +  g_return_val_if_fail( (*transfer)->uri != NULL, NULL );
   2.288 +
   2.289 +  g_static_mutex_lock (&mutex);
   2.290 +
   2.291 +  gchar *path_dir = gmyth_uri_getpath( (*transfer)->uri );
   2.292 +  //g_print( "\t--> %s: path_dir = %s\n", __FUNCTION__, path_dir );
   2.293 +
   2.294 +  gchar *stype = g_strdup( "" );
   2.295 +
   2.296 +  //  if ( (*transfer)->live_tv == FALSE ) {
   2.297 +
   2.298 +  sock = gmyth_socket_new();
   2.299 +
   2.300 +  gmyth_socket_connect( &sock, (*transfer)->hostname->str, (*transfer)->port );
   2.301 +
   2.302 +  /*
   2.303 +     } else {
   2.304 +     sock = (*transfer)->sock;
   2.305 +     }
   2.306 +     */
   2.307 +#ifdef GMYTHTV_ENABLE_DEBUG
   2.308 +
   2.309 +  g_print( "[%s] --> Creating socket... (%s, %d)\n", __FUNCTION__, (*transfer)->hostname->str, (*transfer)->port );
   2.310 +#endif
   2.311 +
   2.312 +  GMythStringList *strlist = NULL;
   2.313 +
   2.314 +  GString *hostname = g_string_new( gmyth_uri_gethost( (*transfer)->uri ) );
   2.315 +  GString *base_str = g_string_new( "" );
   2.316 +
   2.317 +  if ( gmyth_socket_check_protocol_version_number (sock, (*transfer)->mythtv_version) ) {
   2.318 +
   2.319 +    if (sock == NULL) {
   2.320 +      stype = (sock_type==GMYTH_PLAYBACK_TYPE) ? "control socket" : "file data socket";
   2.321 +      g_printerr( "FileTransfer, open_socket(%s): \n"
   2.322 +	  "\t\t\tCould not connect to server \"%s\" @ port %d\n", stype, 
   2.323 +	  (*transfer)->hostname->str, (*transfer)->port );
   2.324 +      g_object_unref(sock);
   2.325 +      g_static_mutex_unlock (&mutex);
   2.326 +      return NULL;
   2.327 +    }
   2.328 +
   2.329 +    hostname = gmyth_socket_get_local_hostname();
   2.330 +
   2.331 +    g_print( "[%s] local hostname = %s\n", __FUNCTION__, hostname->str  );
   2.332 +
   2.333 +    if ( sock_type == GMYTH_PLAYBACK_TYPE )
   2.334 +    {
   2.335 +      (*transfer)->control_sock = sock;
   2.336 +      g_string_printf( base_str, "ANN Playback %s %d", hostname->str, TRUE );
   2.337 +
   2.338 +      gmyth_socket_send_command( (*transfer)->control_sock, base_str );
   2.339 +      GString *resp = gmyth_socket_receive_response( (*transfer)->control_sock );
   2.340 +      g_print( "[%s] Got Playback response from %s: %s\n", __FUNCTION__, base_str->str, resp->str );
   2.341 +    }
   2.342 +    else if ( sock_type == GMYTH_MONITOR_TYPE )
   2.343 +    {
   2.344 +      (*transfer)->event_sock = sock;
   2.345 +      g_string_printf( base_str, "ANN Monitor %s %d", hostname->str, TRUE );
   2.346 +
   2.347 +      gmyth_socket_send_command( (*transfer)->event_sock, base_str );
   2.348 +      GString *resp = gmyth_socket_receive_response( (*transfer)->event_sock );
   2.349 +      g_print( "[%s] Got Monitor response from %s: %s\n", __FUNCTION__, base_str->str, resp->str );
   2.350 +      //g_thread_create( myth_init_io_watchers, (void*)(*transfer), FALSE, NULL );
   2.351 +      myth_init_io_watchers ( (void*)(*transfer) );
   2.352 +
   2.353 +      g_printerr( "[%s] Watch listener function to the IO control channel on thread %p.\n", __FUNCTION__, g_thread_self() );
   2.354 +
   2.355 +    }
   2.356 +    else if ( sock_type == GMYTH_FILETRANSFER_TYPE )
   2.357 +    {
   2.358 +      (*transfer)->sock = sock;
   2.359 +      strlist = gmyth_string_list_new();
   2.360 +      //g_string_printf( base_str, "ANN FileTransfer %s %d %d", hostname->str,
   2.361 +      //  		transfer->userreadahead, transfer->retries );
   2.362 +      g_string_printf( base_str, "ANN FileTransfer %s", hostname->str );
   2.363 +
   2.364 +      gmyth_string_list_append_string( strlist, base_str );
   2.365 +      gmyth_string_list_append_char_array( strlist, path_dir );
   2.366 +
   2.367 +      gmyth_socket_write_stringlist( (*transfer)->sock, strlist );
   2.368 +      gmyth_socket_read_stringlist( (*transfer)->sock, strlist );
   2.369 +
   2.370 +      /* socket number, where all the stream data comes from - got from the MythTV remote backend */
   2.371 +      (*transfer)->recordernum = gmyth_string_list_get_int( strlist, 1 );
   2.372 +
   2.373 +      /* Myth URI stream file size - decoded using two 8-bytes sequences (64 bits/long long types) */
   2.374 +      (*transfer)->filesize = gmyth_util_decode_long_long( strlist, 2 );
   2.375 +
   2.376 +      printf( "[%s] ***** Received: recordernum = %d, filesize = %" G_GUINT64_FORMAT "\n", __FUNCTION__,
   2.377 +	  (*transfer)->recordernum, (*transfer)->filesize );
   2.378 +
   2.379 +      if ( (*transfer)->filesize <= 0 ) {
   2.380 +	g_print( "[%s] Got filesize equals to %llu is lesser than 0 [invalid stream file]\n", __FUNCTION__, (*transfer)->filesize );
   2.381 +	g_object_unref(sock);
   2.382 +	sock = NULL; 
   2.383 +      }
   2.384 +    }
   2.385 +    else if ( sock_type == GMYTH_RINGBUFFER_TYPE )
   2.386 +    {
   2.387 +      (*transfer)->sock = sock;
   2.388 +      //gmyth_file_transfer_spawntv( (*transfer), NULL );      
   2.389 +
   2.390 +      strlist = gmyth_string_list_new();
   2.391 +      g_string_printf( base_str, "ANN RingBuffer %s %d", hostname->str, (*transfer)->card_id );
   2.392 +
   2.393 +      gmyth_socket_send_command( (*transfer)->sock, base_str );
   2.394 +      GString *resp = gmyth_socket_receive_response( (*transfer)->sock );
   2.395 +      g_print( "[%s] Got RingBuffer response from %s: %s\n", __FUNCTION__, base_str->str, resp->str );
   2.396 +
   2.397 +    }
   2.398 +
   2.399 +  }
   2.400 +
   2.401 +  printf("[%s] ANN %s sent: %s\n", (sock_type==GMYTH_PLAYBACK_TYPE) ? "Playback" : (sock_type==GMYTH_FILETRANSFER_TYPE) ? "FileTransfer" : "Monitor", __FUNCTION__, base_str->str);
   2.402 +
   2.403 +  if ( strlist != NULL )
   2.404 +    g_object_unref( strlist );
   2.405 +
   2.406 +  g_static_mutex_unlock (&mutex);
   2.407 +
   2.408 +  return sock;
   2.409 +}    
   2.410 +
   2.411 +void
   2.412 +gmyth_file_transfer_spawntv ( GMythFileTransfer *file_transfer, 
   2.413 +    GString *tvchain_id )
   2.414 +{
   2.415 +  GMythStringList *str_list;
   2.416 +
   2.417 +  g_debug ("gmyth_file_transfer_spawntv.\n");
   2.418 +
   2.419 +  str_list = gmyth_string_list_new ();
   2.420 +
   2.421 +  g_string_printf( file_transfer->query, "%s %d", GMYTHTV_RECORDER_HEADER, 
   2.422 +      file_transfer->card_id );
   2.423 +  gmyth_string_list_append_string (str_list, file_transfer->query);
   2.424 +  gmyth_string_list_append_string (str_list, g_string_new ("SPAWN_LIVETV"));
   2.425 +  if (tvchain_id!=NULL) {
   2.426 +    gmyth_string_list_append_string (str_list, tvchain_id);
   2.427 +    gmyth_string_list_append_int (str_list, FALSE); // PIP = FALSE (0)
   2.428 +  }
   2.429 +
   2.430 +  gmyth_socket_sendreceive_stringlist ( file_transfer->sock, str_list );
   2.431 +
   2.432 +  //GString *str = NULL;
   2.433 +
   2.434 +  //if (str_list!=NULL && (str = gmyth_string_list_get_string( str_list, 0 )) != NULL && strcasecmp( str->str, "ok" ) != 0 ) {
   2.435 +  //  g_print( "[%s]\t\tSpawnLiveTV is OK!\n", __FUNCTION__ );
   2.436 +  //}
   2.437 +  if (str_list!=NULL)
   2.438 +    g_object_unref (str_list);
   2.439 +
   2.440 +}
   2.441 +
   2.442 +gboolean
   2.443 +gmyth_file_transfer_is_recording ( GMythFileTransfer *file_transfer )
   2.444 +{
   2.445 +  gboolean ret = TRUE;
   2.446 +  
   2.447 +  GMythStringList *str_list = gmyth_string_list_new ();
   2.448 +
   2.449 +  g_debug ( "[%s]\n", __FUNCTION__ );
   2.450 +  g_static_mutex_lock (&mutex);
   2.451 +
   2.452 +  g_string_printf( file_transfer->query, "%s %d", GMYTHTV_RECORDER_HEADER, 
   2.453 +      file_transfer->rec_id >= 0 ? file_transfer->rec_id : file_transfer->card_id );
   2.454 +  gmyth_string_list_append_string (str_list, file_transfer->query);
   2.455 +  gmyth_string_list_append_string (str_list, g_string_new ("IS_RECORDING"));
   2.456 +
   2.457 +  gmyth_socket_sendreceive_stringlist ( file_transfer->control_sock, str_list );
   2.458 +
   2.459 +  if ( str_list != NULL && gmyth_string_list_length(str_list) > 0 ) 
   2.460 +  {
   2.461 +    GString *str = NULL;
   2.462 +    if ( ( str = gmyth_string_list_get_string( str_list, 0 ) ) != NULL && strcmp( str->str, "bad" )!= 0 ) {
   2.463 +      gint is_rec = gmyth_string_list_get_int( str_list, 0 );
   2.464 +      if ( is_rec != 0 )
   2.465 +	ret = TRUE;
   2.466 +      else
   2.467 +	ret = FALSE;
   2.468 +    }
   2.469 +  }  
   2.470 +  g_print( "[%s] %s, stream is %s being recorded!\n", __FUNCTION__, ret ? "YES" : "NO", ret ? "" : "NOT" );
   2.471 +  g_static_mutex_unlock (&mutex);
   2.472 +
   2.473 +  if ( str_list != NULL )
   2.474 +    g_object_unref (str_list);
   2.475 +
   2.476 +  return ret;
   2.477 +
   2.478 +}
   2.479 +
   2.480 +gint64
   2.481 +gmyth_file_transfer_get_file_position ( GMythFileTransfer *file_transfer )
   2.482 +{
   2.483 +  gint64 pos = 0;
   2.484 +
   2.485 +  GMythStringList *str_list = gmyth_string_list_new ();
   2.486 +
   2.487 +  g_debug ( "[%s]\n", __FUNCTION__ );
   2.488 +  g_static_mutex_lock (&mutex);
   2.489 +
   2.490 +  g_string_printf( file_transfer->query, "%s %d", GMYTHTV_RECORDER_HEADER, 
   2.491 +      file_transfer->rec_id >= 0 ? file_transfer->rec_id : file_transfer->card_id );
   2.492 +
   2.493 +  gmyth_string_list_append_string (str_list, file_transfer->query);
   2.494 +  gmyth_string_list_append_string (str_list, g_string_new ("GET_FILE_POSITION"));
   2.495 +
   2.496 +  gmyth_socket_sendreceive_stringlist ( file_transfer->control_sock, str_list );
   2.497 +
   2.498 +  if ( str_list != NULL && gmyth_string_list_length(str_list) > 0 ) 
   2.499 +  {
   2.500 +    GString *str = NULL;
   2.501 +    if ( ( str = gmyth_string_list_get_string( str_list, 0 ) ) != NULL && strstr ( str->str, "bad" ) == NULL )
   2.502 +      pos = gmyth_util_decode_long_long( str_list, 0 );
   2.503 +  } 
   2.504 +  g_static_mutex_unlock (&mutex);
   2.505 +
   2.506 +#ifndef GMYTHTV_ENABLE_DEBUG
   2.507 +
   2.508 +  g_print( "[%s] Got file position = %lld\n", __FUNCTION__, pos );
   2.509 +#endif
   2.510 +  if (str_list!=NULL)
   2.511 +    g_object_unref (str_list);
   2.512 +
   2.513 +  return pos;
   2.514 +
   2.515 +}
   2.516 +
   2.517 +  glong
   2.518 +gmyth_file_transfer_get_recordernum( GMythFileTransfer *transfer )
   2.519 +{
   2.520 +  return transfer->recordernum;
   2.521 +}
   2.522 +
   2.523 +  glong
   2.524 +gmyth_file_transfer_get_filesize( GMythFileTransfer *transfer )
   2.525 +{
   2.526 +  return transfer->filesize;
   2.527 +}
   2.528 +
   2.529 +  gboolean
   2.530 +gmyth_file_transfer_isopen( GMythFileTransfer *transfer )
   2.531 +{
   2.532 +  return (transfer->sock != NULL && transfer->control_sock != NULL);
   2.533 +}
   2.534 +
   2.535 +  void
   2.536 +gmyth_file_transfer_close( GMythFileTransfer *transfer )
   2.537 +{
   2.538 +  GMythStringList *strlist;
   2.539 +
   2.540 +  if (transfer->control_sock == NULL)
   2.541 +    return;
   2.542 +
   2.543 +  strlist = gmyth_string_list_new( );
   2.544 +
   2.545 +  g_string_printf( transfer->query, "%s %d", GMYTHTV_QUERY_HEADER, 
   2.546 +      transfer->recordernum );
   2.547 +  gmyth_string_list_append_string( strlist, transfer->query );
   2.548 +  gmyth_string_list_append_char_array( strlist, "DONE" );
   2.549 +
   2.550 +
   2.551 +  if ( gmyth_socket_sendreceive_stringlist(transfer->control_sock, strlist) <= 0 )
   2.552 +  {
   2.553 +    g_printerr( "Remote file timeout.\n" );
   2.554 +  }
   2.555 +
   2.556 +  if (transfer->sock)
   2.557 +  {
   2.558 +    g_object_unref( transfer->sock );
   2.559 +    transfer->sock = NULL;
   2.560 +  }
   2.561 +
   2.562 +  if (transfer->control_sock)
   2.563 +  {
   2.564 +    g_object_unref( transfer->control_sock );
   2.565 +    transfer->control_sock = NULL;
   2.566 +  } 
   2.567 +
   2.568 +}
   2.569 +
   2.570 +  void
   2.571 +gmyth_file_transfer_reset_controlsock( GMythFileTransfer *transfer )
   2.572 +{
   2.573 +  if (transfer->control_sock == NULL)
   2.574 +  {
   2.575 +    g_printerr( "gmyth_file_transfer_reset_controlsock(): Called with no control socket" );
   2.576 +    return;
   2.577 +  }
   2.578 +
   2.579 +  GString *str = gmyth_socket_receive_response( transfer->control_sock );
   2.580 +
   2.581 +  g_string_free( str, TRUE );
   2.582 +}
   2.583 +
   2.584 +void
   2.585 +gmyth_file_transfer_reset_sock( GMythFileTransfer *transfer )
   2.586 +{
   2.587 +  if ( transfer->sock == NULL )
   2.588 +  {
   2.589 +    g_printerr( "gmyth_file_transfer_reset_sock(): Called with no raw socket" );
   2.590 +    return;
   2.591 +  }
   2.592 +
   2.593 +  GString *str = gmyth_socket_receive_response( transfer->sock );
   2.594 +
   2.595 +  g_string_free( str, TRUE );
   2.596 +}
   2.597 +
   2.598 +void
   2.599 +gmyth_file_transfer_reset( GMythFileTransfer *transfer )
   2.600 +{
   2.601 +  gmyth_file_transfer_reset_controlsock( transfer );
   2.602 +  gmyth_file_transfer_reset_sock( transfer );
   2.603 +}
   2.604 +
   2.605 +gint64
   2.606 +gmyth_file_transfer_seek(GMythFileTransfer *transfer, guint64 pos, gint whence)
   2.607 +{
   2.608 +  if (transfer->sock == NULL)
   2.609 +  {
   2.610 +    g_printerr( "[%s] gmyth_file_transfer_seek(): Called with no socket", __FUNCTION__ );
   2.611 +    return 0;
   2.612 +  }
   2.613 +
   2.614 +  if (transfer->control_sock == NULL)
   2.615 +    return 0;
   2.616 +
   2.617 +  // if (!controlSock->isOpen() || controlSock->error())
   2.618 +  //   return 0;
   2.619 +
   2.620 +  GMythStringList *strlist = gmyth_string_list_new();
   2.621 +  g_string_printf (transfer->query, "%s %d", GMYTHTV_QUERY_HEADER, transfer->recordernum);
   2.622 +  gmyth_string_list_append_string( strlist, transfer->query );
   2.623 +  gmyth_string_list_append_char_array( strlist, "SEEK" );
   2.624 +  gmyth_string_list_append_uint64( strlist, pos );
   2.625 +  
   2.626 +  gmyth_string_list_append_int( strlist, whence );  
   2.627 +
   2.628 +  if (pos > 0 )
   2.629 +    gmyth_string_list_append_uint64( strlist, pos );
   2.630 +  else
   2.631 +    gmyth_string_list_append_uint64( strlist, transfer->readposition );
   2.632 +  
   2.633 +  gmyth_socket_sendreceive_stringlist( transfer->control_sock, strlist );
   2.634 +
   2.635 +  gint64 retval = gmyth_string_list_get_int64(strlist, 0);
   2.636 +  transfer->readposition = retval;
   2.637 +  g_print( "[%s] got reading position pointer from the streaming = %lld\n", 
   2.638 +      __FUNCTION__, retval );
   2.639 +
   2.640 +  //gmyth_file_transfer_reset( transfer );
   2.641 +
   2.642 +  return retval;
   2.643 +}
   2.644 +
   2.645 +static gboolean
   2.646 +myth_control_sock_listener( GIOChannel *source, GIOCondition condition, gpointer data )
   2.647 +{
   2.648 +
   2.649 +  GIOStatus ret;
   2.650 +  GError *err = NULL;
   2.651 +  gchar *msg = g_strdup("");
   2.652 +  
   2.653 +  g_static_mutex_lock( &mutex );  
   2.654 +
   2.655 +  gsize len;
   2.656 +  if (condition & G_IO_HUP)
   2.657 +    g_error ("Read end of pipe died!\n");
   2.658 +  ret = g_io_channel_read_line ( source, &msg, &len, NULL, &err);
   2.659 +  if ( ret == G_IO_STATUS_ERROR )
   2.660 +    g_error ("[%s] Error reading: %s\n", __FUNCTION__, err != NULL ? err->message : "" );
   2.661 +  g_print ("\n\n\n\n\n\n[%s]\t\tEVENT: Read %u bytes: %s\n\n\n\n\n", __FUNCTION__, len, msg != NULL ? msg : "" );
   2.662 +  if ( msg != NULL )
   2.663 +    g_free (msg);
   2.664 +    
   2.665 +  g_static_mutex_unlock( &mutex );
   2.666 +
   2.667 +  return TRUE;
   2.668 +
   2.669 +}
   2.670 +
   2.671 +static void*
   2.672 +myth_init_io_watchers( void *data )
   2.673 +{
   2.674 +  GMythFileTransfer *transfer = (GMythFileTransfer*)data;
   2.675 +  io_watcher_context = g_main_context_new();
   2.676 +  GMainLoop *loop = g_main_loop_new( NULL, FALSE );
   2.677 +
   2.678 +  GSource *source = NULL;
   2.679 +
   2.680 +  if ( transfer->event_sock->sd_io_ch != NULL )
   2.681 +    source = g_io_create_watch( transfer->event_sock->sd_io_ch, G_IO_IN | G_IO_HUP );
   2.682 +  else
   2.683 +  	goto cleanup;
   2.684 +
   2.685 +  g_source_set_callback ( source, (GSourceFunc)myth_control_sock_listener, NULL, NULL );
   2.686 +
   2.687 +  g_source_attach( source, io_watcher_context );
   2.688 +
   2.689 +  if (source==NULL) {
   2.690 +    g_printerr( "[%s] Error adding watch listener function to the IO control channel!\n", __FUNCTION__ );
   2.691 +    goto cleanup;
   2.692 +  }
   2.693 +  
   2.694 +  g_print( "[%s]\tOK! Starting listener on the MONITOR event socket...\n", __FUNCTION__ );
   2.695 +
   2.696 +  g_main_loop_run( loop );
   2.697 +
   2.698 +cleanup:
   2.699 +  if ( source != NULL )
   2.700 +    g_source_unref( source );
   2.701 +
   2.702 +  g_main_loop_unref( loop );
   2.703 +
   2.704 +  g_main_context_unref( io_watcher_context );
   2.705 +
   2.706 +  return NULL;
   2.707 +}
   2.708 +
   2.709 +
   2.710 +gint 
   2.711 +gmyth_file_transfer_read(GMythFileTransfer *transfer, void *data, gint size, gboolean read_unlimited)
   2.712 +{
   2.713 +  gint recv = 0;
   2.714 +  gsize bytes_read = 0;
   2.715 +  gint sent = 0;
   2.716 +  guint remaining = 0;  
   2.717 +  gboolean response = FALSE;
   2.718 +
   2.719 +  GIOChannel *io_channel;
   2.720 +  GIOChannel *io_channel_control;
   2.721 +
   2.722 +  GIOCondition io_cond;
   2.723 +  GIOCondition io_cond_control;
   2.724 +  GIOStatus io_status = G_IO_STATUS_NORMAL, io_status_control = G_IO_STATUS_NORMAL;   
   2.725 +
   2.726 +  gint buf_len = GMYTHTV_BUFFER_SIZE;
   2.727 +
   2.728 +  GMythStringList *strlist = NULL;
   2.729 +  GError *error = NULL;
   2.730 +
   2.731 +  gchar *trash = g_strdup("");
   2.732 +
   2.733 +  g_return_val_if_fail ( data != NULL, -2 );
   2.734 +
   2.735 +  /* gets the size of the entire file, if the size requested is lesser than 0 */
   2.736 +  if ( size <= 0 )
   2.737 +    size = transfer->filesize;
   2.738 +
   2.739 +  io_channel = transfer->sock->sd_io_ch;
   2.740 +  io_channel_control = transfer->control_sock->sd_io_ch;
   2.741 +
   2.742 +  //g_io_channel_set_flags( io_channel, G_IO_FLAG_APPEND | 
   2.743 +  //    G_IO_STATUS_AGAIN | G_IO_FLAG_IS_READABLE | G_IO_FLAG_IS_WRITEABLE | 
   2.744 +  //    G_IO_FLAG_IS_SEEKABLE, NULL );
   2.745 +
   2.746 +  io_status = g_io_channel_set_encoding( io_channel, NULL, &error );
   2.747 +  if ( io_status == G_IO_STATUS_NORMAL )
   2.748 +    g_print( "[%s] Setting encoding to binary data socket).\n", __FUNCTION__ );
   2.749 +
   2.750 +  io_cond = g_io_channel_get_buffer_condition( io_channel );  
   2.751 +
   2.752 +  io_cond_control = g_io_channel_get_buffer_condition( io_channel );
   2.753 +
   2.754 +  if ( transfer->sock == NULL || ( io_status == G_IO_STATUS_ERROR ) )
   2.755 +  {
   2.756 +    g_printerr( "gmyth_file_transfer_read(): Called with no raw socket.\n" );
   2.757 +    recv = -1;
   2.758 +    goto cleanup;
   2.759 +  }
   2.760 +
   2.761 +  if ( transfer->control_sock == NULL || ( io_status_control == G_IO_STATUS_ERROR ) )
   2.762 +  {
   2.763 +    g_printerr( "gmyth_file_transfer_read(): Called with no control socket.\n" );
   2.764 +    recv = -1;
   2.765 +    goto cleanup;
   2.766 +  }
   2.767 +
   2.768 +  /*
   2.769 +     if (!controlSock->isOpen() || controlSock->error())
   2.770 +     return -1;
   2.771 +     */
   2.772 +
   2.773 +  if ( ( io_cond & G_IO_IN ) != 0 ) {
   2.774 +    do 
   2.775 +    {
   2.776 +      trash = g_new0( gchar, GMYTHTV_BUFFER_SIZE );
   2.777 +
   2.778 +      io_status = g_io_channel_read_chars( io_channel, trash, 
   2.779 +      		GMYTHTV_BUFFER_SIZE, &bytes_read, &error);
   2.780 +
   2.781 +      g_print( "[%s] cleaning buffer on IO binary channel... %d bytes gone!\n", 
   2.782 +      		__FUNCTION__, bytes_read );
   2.783 +      
   2.784 +      if ( trash != NULL )
   2.785 +      	g_free( trash );
   2.786 +      	
   2.787 +      io_cond = g_io_channel_get_buffer_condition( io_channel );
   2.788 +
   2.789 +    } while ( ( io_cond & G_IO_IN ) != 0 && ( io_status != G_IO_STATUS_ERROR ) && (error == NULL) );
   2.790 +
   2.791 +    //if ( trash!= NULL )
   2.792 +    //  g_free( trash );
   2.793 +  }
   2.794 +
   2.795 +  if ( ( io_cond_control & G_IO_IN ) != 0 ) {
   2.796 +    GMythStringList *strlist_tmp = gmyth_string_list_new();
   2.797 +    gmyth_socket_read_stringlist( transfer->control_sock, strlist_tmp );
   2.798 +    g_object_unref( strlist_tmp );
   2.799 +  }
   2.800 +
   2.801 +  wait_to_transfer = 0;
   2.802 +
   2.803 +  //while ( transfer->live_tv && ( gmyth_file_transfer_get_file_position( transfer ) < 4096 ) &&
   2.804 +  //		wait_to_transfer++ < GMYTHTV_TRANSFER_MAX_WAITS )
   2.805 +  //	g_usleep( 1000*50 ); /* waits just for 2/10 second */
   2.806 +
   2.807 +  //g_thread_create( myth_init_io_watchers, (void*)transfer, FALSE, NULL );
   2.808 +  //g_printerr( "[%s] Watch listener function to the IO control channel on thread %p.\n", __FUNCTION__, g_thread_self() );
   2.809 +
   2.810 +  //g_static_mutex_lock (&mutex);
   2.811 +  //strlist = gmyth_string_list_new();
   2.812 +
   2.813 +  g_string_printf ( transfer->query, "%s %d",
   2.814 +  	  /*transfer->live_tv ? GMYTHTV_RECORDER_HEADER :*/  GMYTHTV_QUERY_HEADER, 
   2.815 +      /* transfer->live_tv ? transfer->card_id :*/ transfer->recordernum ); // transfer->recordernum
   2.816 +  g_print( "\t[%s] Transfer_query = %s\n", __FUNCTION__, transfer->query->str );
   2.817 +  
   2.818 +  sent = size;
   2.819 +  remaining = size - recv;  
   2.820 +  //g_static_mutex_unlock( &mutex );
   2.821 +  //data = (void*)g_new0( gchar, size );
   2.822 +
   2.823 +  //g_io_channel_flush( io_channel, NULL );
   2.824 +
   2.825 +  //g_static_mutex_lock( &mutex );
   2.826 +
   2.827 +  io_cond = g_io_channel_get_buffer_condition( io_channel );
   2.828 +
   2.829 +  while ( recv < size  && !response )//&& ( io_cond & G_IO_IN ) != 0 )
   2.830 +  {
   2.831 +  	g_io_channel_flush( io_channel_control, NULL );
   2.832 +  	
   2.833 +    strlist = gmyth_string_list_new();
   2.834 +    gmyth_string_list_append_char_array( strlist, transfer->query->str );
   2.835 +    gmyth_string_list_append_char_array( strlist, 
   2.836 +    		/*transfer->live_tv ? "REQUEST_BLOCK_RINGBUF" :*/ "REQUEST_BLOCK" );
   2.837 +    gmyth_string_list_append_int( strlist, remaining );
   2.838 +	gmyth_socket_write_stringlist( transfer->control_sock, strlist );
   2.839 +	
   2.840 +	guint count_bytes = 0;
   2.841 +      
   2.842 +    do
   2.843 +    {
   2.844 +      //buf_len = ( sent - recv ) > GMYTHTV_BUFFER_SIZE ? GMYTHTV_BUFFER_SIZE : ( sent - recv );
   2.845 +      if ( remaining > GMYTHTV_BUFFER_SIZE ) {
   2.846 +      	buf_len = GMYTHTV_BUFFER_SIZE;
   2.847 +      } else {
   2.848 +      	buf_len = remaining;
   2.849 +      }
   2.850 +	  
   2.851 +      bytes_read = 0;
   2.852 +
   2.853 +      io_status = g_io_channel_read_chars( io_channel, data + recv, 
   2.854 +	  		buf_len, &bytes_read, &error );
   2.855 +	  
   2.856 +	  //g_static_mutex_unlock( &mutex );
   2.857 +      /*
   2.858 +	 GString *sss = g_string_new("");
   2.859 +	 sss = g_string_append_len( sss, (gchar*)data+recv, bytes_read );
   2.860 +
   2.861 +	 g_print( "[%s] Reading buffer (length = %d)\n", __FUNCTION__, bytes_read);
   2.862 +	 */
   2.863 +      if ( bytes_read > 0 )
   2.864 +      {
   2.865 +	//if ( bytes_read <= buf_len )
   2.866 +		  recv += bytes_read;
   2.867 +		  count_bytes += bytes_read;
   2.868 +		  remaining -= bytes_read;
   2.869 +		  g_print( "[%s] Reading buffer (bytes read = %d, remaining = %d)\n", __FUNCTION__, bytes_read, remaining );
   2.870 +		  if ( remaining == 0 ) {
   2.871 +		  	break;
   2.872 +		  }
   2.873 +      } else {
   2.874 +      	break;
   2.875 +      }
   2.876 +      
   2.877 +      //if ( remaining > 0 ) {
   2.878 +
   2.879 +      if ( io_status == G_IO_STATUS_EOF ) {
   2.880 +	g_print( "[%s] got EOS!", __FUNCTION__ );
   2.881 +	break;
   2.882 +      } else if ( io_status == G_IO_STATUS_ERROR ) {
   2.883 +	g_print( "[%s] gmyth_file_transfer_read(): socket error.\n", __FUNCTION__ );
   2.884 +	break;
   2.885 +      }
   2.886 +      //}
   2.887 +
   2.888 +      /* increase buffer size, to allow get more data (do not obey to the buffer size) */
   2.889 +      if ( read_unlimited == TRUE ) {
   2.890 +      	// FOR NOW, DO NOTHING!!!
   2.891 +	//if ( recv > buf_len )
   2.892 +	// sent += (bytes_read - buf_len) + 1;
   2.893 +      }
   2.894 +
   2.895 +      /* verify if the input (read) buffer is ready to receive data */
   2.896 +      io_cond = g_io_channel_get_buffer_condition( io_channel );
   2.897 +
   2.898 +      g_print( "[%s]\t io_cond %s prepared for reading! (G_IO_IN) !!!\n\n", __FUNCTION__, 
   2.899 +      		( ( io_cond & G_IO_IN ) != 0 ) ? "IS" : "IS NOT" );
   2.900 +      		
   2.901 +      //if ( recv == size )
   2.902 +		//break;
   2.903 +
   2.904 +    } while ( remaining > 0 );//&& ( io_status == G_IO_STATUS_NORMAL ) );
   2.905 +    
   2.906 +   // if ( ( recv < size ) ) {
   2.907 +    //	finish_read = FALSE;
   2.908 +    //}
   2.909 +
   2.910 +    io_cond_control = g_io_channel_get_buffer_condition( io_channel_control );
   2.911 +    if ( remaining == 0 )//( io_cond_control & G_IO_IN ) != 0  )
   2.912 +    {
   2.913 +      gmyth_socket_read_stringlist( transfer->control_sock, strlist );
   2.914 +      if ( strlist != NULL && gmyth_string_list_length( strlist ) > 0 ) 
   2.915 +      {
   2.916 +      	sent = gmyth_string_list_get_int( strlist,  0 ); // -1 on backend error
   2.917 +      	g_print( "[%s] got SENT buffer message = %d\n", __FUNCTION__, sent );
   2.918 +      	if ( sent != 0 )
   2.919 +      	{
   2.920 +      		g_print( "[%s]\t received = %d bytes, backend says %d bytes sent, "\
   2.921 +      			"io_cond %s prepared for reading! (G_IO_IN) !!!\n\n", __FUNCTION__, 
   2.922 +	  			recv, sent, ( ( io_cond & G_IO_IN ) != 0 ) ? "IS" : "IS NOT" );
   2.923 +
   2.924 +	  		if ( sent == count_bytes )
   2.925 +	  		{
   2.926 +	  			response = ( recv == size ); 
   2.927 +	  			g_print( "[%s]\t\tsent %d, which is equals to bytes_read = %d\n\n", 
   2.928 +	  						__FUNCTION__, sent, count_bytes );
   2.929 +	  			if ( response == TRUE )
   2.930 +      				break;
   2.931 +	  		}
   2.932 +	  		else
   2.933 +	  		{
   2.934 +	  			g_print( "[%s]\t\tsent %d, which is NOT equals to bytes_read = %d\n\n", 
   2.935 +	  						__FUNCTION__, sent, count_bytes );
   2.936 +	  			goto cleanup;
   2.937 +	  			//response = FALSE;
   2.938 +	  			//break;
   2.939 +	  		}
   2.940 +      	} else {
   2.941 +      		break;
   2.942 +      		//goto cleanup;
   2.943 +      	} // if
   2.944 +      } // if - reading control response from backend
   2.945 +    } else {
   2.946 +    	response = FALSE;
   2.947 +    } // if - stringlist response
   2.948 +    
   2.949 +  } // while
   2.950 +  
   2.951 +  io_cond_control = g_io_channel_get_buffer_condition( io_channel_control );
   2.952 + // io_cond = g_io_channel_get_buffer_condition( io_channel );
   2.953 +
   2.954 +  if ( ( ( io_cond_control & G_IO_IN ) != 0 ) &&  		 
   2.955 +  		( response || ( recv == size ) ) )
   2.956 +  {
   2.957 +    if ( gmyth_socket_read_stringlist( transfer->control_sock, strlist ) > 0 )
   2.958 +    {
   2.959 +      if ( strlist != NULL && gmyth_string_list_length(strlist) > 0 ) 
   2.960 +      {
   2.961 +		sent = gmyth_string_list_get_int( strlist, 0 ); // -1 on backend error
   2.962 +		g_print( "[%s]\t received = %d bytes -\tNOW returning from reading buffer I/O socket "\
   2.963 +				 "[%s prepared for reading]! (G_IO_IN) !!!\n\n", __FUNCTION__, 
   2.964 +	    	sent, ( ( io_cond & G_IO_IN ) != 0 ) ? "IS" : "IS NOT" );
   2.965 +      }
   2.966 +    }
   2.967 +    else
   2.968 +    {
   2.969 +      g_printerr ( "gmyth_file_transfer_read(): No response from control socket.");
   2.970 +      recv = -1;
   2.971 +    }
   2.972 +    
   2.973 +  } 
   2.974 +  else if ( error != NULL )
   2.975 +  {
   2.976 +      g_printerr( "[%s] Error occurred: (%d, %s)\n", __FUNCTION__, error->code, error->message );
   2.977 +  }
   2.978 +
   2.979 +cleanup:
   2.980 +  //g_static_mutex_unlock (&mutex);
   2.981 +
   2.982 +  if ( trash != NULL )
   2.983 +    g_free( trash );
   2.984 +
   2.985 +  if ( strlist != NULL )
   2.986 +    g_object_unref( strlist );
   2.987 +
   2.988 +  g_print( "gmyth_file_transfer_read(): reqd=%d, rcvd=%d, rept=%d, "\
   2.989 +      "(rcvd and rept MUST be the same!)\n", size, 
   2.990 +      recv, sent );
   2.991 +
   2.992 +  //if ( ( recv != size ) || ( sent != size ) ) {
   2.993 +    //recv = size;
   2.994 +  //}
   2.995 +
   2.996 +  if ( error != NULL ) {
   2.997 +    g_printerr( "Cleaning-up ERROR: %s [msg = %s, code = %d]\n", __FUNCTION__, error->message, 
   2.998 +	error->code );
   2.999 +	g_error_free( error );
  2.1000 +  }
  2.1001 +
  2.1002 +  return recv;
  2.1003 +}
  2.1004 +
  2.1005 +void 
  2.1006 +gmyth_file_transfer_settimeout( GMythFileTransfer *transfer, gboolean fast )
  2.1007 +{
  2.1008 +
  2.1009 +  GMythStringList *strlist = NULL;
  2.1010 +
  2.1011 +  if ( transfer->timeoutisfast == fast )
  2.1012 +    return;
  2.1013 +
  2.1014 +  if ( transfer->sock == NULL )
  2.1015 +  {
  2.1016 +    g_printerr( "gmyth_file_transfer_settimeout(): Called with no socket" );
  2.1017 +    return;
  2.1018 +  }
  2.1019 +
  2.1020 +  if ( transfer->control_sock == NULL )
  2.1021 +    return;
  2.1022 +
  2.1023 +  strlist = gmyth_string_list_new(); 
  2.1024 +  gmyth_string_list_append_string( strlist, transfer->query );
  2.1025 +  gmyth_string_list_append_char_array( strlist, "SET_TIMEOUT" );
  2.1026 +  gmyth_string_list_append_int( strlist, fast ); 
  2.1027 +
  2.1028 +  gmyth_socket_write_stringlist( transfer->control_sock, strlist );
  2.1029 +  gmyth_socket_read_stringlist( transfer->control_sock, strlist );
  2.1030 +
  2.1031 +  transfer->timeoutisfast = fast;
  2.1032 +
  2.1033 +}
  2.1034 +
  2.1035 +#ifdef DO_TESTING
  2.1036 +
  2.1037 +  int
  2.1038 +main( int argc, char *argv[] )
  2.1039 +{
  2.1040 +  g_type_init();
  2.1041 +
  2.1042 +  GMythFileTransfer *file_transfer = gmyth_file_transfer_new( 1, 
  2.1043 +      g_string_new("myth://192.168.1.109:6543/jshks.nuv"), -1, GMYTHTV_VERSION );
  2.1044 +  gmyth_file_transfer_setup( &file_transfer );
  2.1045 +  gchar *data = g_strdup("");
  2.1046 +
  2.1047 +  gint num = gmyth_file_transfer_read( file_transfer, data, -1 );
  2.1048 +
  2.1049 +  return 0;
  2.1050 +
  2.1051 +}
  2.1052 +
  2.1053 +#endif
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/gmyth/src/gmyth_file_transfer.h	Mon Oct 23 16:02:15 2006 +0100
     3.3 @@ -0,0 +1,93 @@
     3.4 +/* vim: set sw=2: -*- Mode: C; tab-width: 2; indent-tabs-mode: t; c-basic-offset: 2; c-indent-level: 2-*- */
     3.5 +
     3.6 +#ifndef __GMYTH_FILE_TRANSFER_H__
     3.7 +#define __GMYTH_FILE_TRANSFER_H__
     3.8 +
     3.9 +#include <glib-object.h>
    3.10 +
    3.11 +#include <gmyth/gmyth_socket.h>
    3.12 +#include <gmyth/gmyth_uri.h>
    3.13 +#include <gmyth/gmyth_livetv.h>
    3.14 +
    3.15 +#include <stdio.h>
    3.16 +#include <stdlib.h>
    3.17 +#include <string.h>
    3.18 +#include <netdb.h>
    3.19 +#include <sys/socket.h>
    3.20 +#include <unistd.h>
    3.21 +
    3.22 +#define G_BEGIN_DECLS
    3.23 +
    3.24 +#define GMYTH_FILE_TRANSFER_TYPE               (gmyth_file_transfer_get_type ())
    3.25 +#define GMYTH_FILE_TRANSFER(obj)               (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_FILE_TRANSFER_TYPE, GMythFileTransfer))
    3.26 +#define GMYTH_FILE_TRANSFER_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_FILE_TRANSFER_TYPE, GMythFileTransferClass))
    3.27 +#define IS_GMYTH_FILE_TRANSFER(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_FILE_TRANSFER_TYPE))
    3.28 +#define IS_GMYTH_FILE_TRANSFER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_FILE_TRANSFER_TYPE))
    3.29 +#define GMYTH_FILE_TRANSFER_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_FILE_TRANSFER_TYPE, GMythFileTransferClass))
    3.30 +
    3.31 +
    3.32 +typedef struct _GMythFileTransfer         GMythFileTransfer;
    3.33 +typedef struct _GMythFileTransferClass    GMythFileTransferClass;
    3.34 +
    3.35 +struct _GMythFileTransferClass
    3.36 +{
    3.37 +	GObjectClass parent_class;
    3.38 +
    3.39 +	/* callbacks */
    3.40 +	/* no one for now */
    3.41 +};
    3.42 +
    3.43 +struct _GMythFileTransfer
    3.44 +{
    3.45 +	GObject parent;
    3.46 +
    3.47 +	/* Myth URI structure */
    3.48 +	const GMythURI *uri;
    3.49 +	
    3.50 +	/* MythTV version number */	
    3.51 +	gint mythtv_version;
    3.52 +
    3.53 +	/* socket descriptors */
    3.54 +	GMythSocket *control_sock;
    3.55 +	GMythSocket *event_sock;
    3.56 +	GMythSocket *sock;
    3.57 +
    3.58 +	guint64 readposition;
    3.59 +	guint64 filesize;
    3.60 +	gboolean timeoutisfast;
    3.61 +	gboolean userreadahead;
    3.62 +	gboolean live_tv;
    3.63 +	gint retries;
    3.64 +
    3.65 +	GString *query;
    3.66 +
    3.67 +	gint rec_id;
    3.68 +	gint recordernum;
    3.69 +	gint card_id;
    3.70 +	GString *hostname;
    3.71 +	gint port;
    3.72 +};
    3.73 +
    3.74 +GType          gmyth_file_transfer_get_type        (void);
    3.75 +
    3.76 +GMythFileTransfer* gmyth_file_transfer_new (gint num, GString *hostname, gshort port, gint mythtv_version );
    3.77 +
    3.78 +gint gmyth_file_transfer_read(GMythFileTransfer *transfer, void *data, gint size, gboolean read_unlimited);
    3.79 +
    3.80 +gint64 gmyth_file_transfer_seek(GMythFileTransfer *transfer, guint64 pos, gint whence);
    3.81 +
    3.82 +gboolean gmyth_file_transfer_playback_setup( GMythFileTransfer **transfer, gboolean live_tv );
    3.83 +
    3.84 +gboolean gmyth_file_transfer_setup( GMythFileTransfer **transfer, gboolean live_tv );
    3.85 +
    3.86 +gboolean gmyth_file_transfer_livetv_setup( GMythFileTransfer **transfer, GMythSocket *live_sock );
    3.87 +
    3.88 +void gmyth_file_transfer_spawntv ( GMythFileTransfer *file_transfer, GString *tvchain_id );
    3.89 +
    3.90 +gboolean gmyth_file_transfer_is_recording( GMythFileTransfer *file_transfer );
    3.91 +
    3.92 +gint64  gmyth_file_transfer_get_file_position( GMythFileTransfer *file_transfer );
    3.93 +
    3.94 +#define G_END_DECLS
    3.95 +
    3.96 +#endif /* __GMYTH_FILE_TRANSFER_H__ */
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/gmyth/src/gmyth_livetv.c	Mon Oct 23 16:02:15 2006 +0100
     4.3 @@ -0,0 +1,220 @@
     4.4 +
     4.5 +#include <gmyth/gmyth_context.h>
     4.6 +#include <gmyth/gmyth_remote_util.h>
     4.7 +#include <gmyth/gmyth_tvchain.h>
     4.8 +
     4.9 +#include <gmyth/gmyth_livetv.h>
    4.10 +#include <gmyth/gmyth_file_transfer.h>
    4.11 +
    4.12 +static void gmyth_livetv_class_init          (GMythLiveTVClass *klass);
    4.13 +static void gmyth_livetv_init                (GMythLiveTV *object);
    4.14 +
    4.15 +static void gmyth_livetv_dispose  (GObject *object);
    4.16 +static void gmyth_livetv_finalize (GObject *object);
    4.17 +
    4.18 +static gint tvchain_curr_index = -1; 
    4.19 +
    4.20 +G_DEFINE_TYPE(GMythLiveTV, gmyth_livetv, G_TYPE_OBJECT)
    4.21 +
    4.22 +static void
    4.23 +gmyth_livetv_class_init (GMythLiveTVClass *klass)
    4.24 +{
    4.25 +	GObjectClass *gobject_class;
    4.26 +
    4.27 +	gobject_class = (GObjectClass *) klass;
    4.28 +
    4.29 +	gobject_class->dispose  = gmyth_livetv_dispose;
    4.30 +	gobject_class->finalize = gmyth_livetv_finalize;	
    4.31 +}
    4.32 +
    4.33 +static void
    4.34 +gmyth_livetv_init (GMythLiveTV *livetv)
    4.35 +{
    4.36 +	livetv->backend_hostname = NULL;
    4.37 +	livetv->backend_port = 0;
    4.38 +	livetv->local_hostname = NULL;
    4.39 +
    4.40 +	livetv->remote_encoder = NULL;
    4.41 +	livetv->tvchain = NULL;
    4.42 +	livetv->proginfo = NULL;
    4.43 +}
    4.44 +
    4.45 +static void
    4.46 +gmyth_livetv_dispose  (GObject *object)
    4.47 +{
    4.48 +
    4.49 +	G_OBJECT_CLASS (gmyth_livetv_parent_class)->dispose (object);
    4.50 +}
    4.51 +
    4.52 +static void
    4.53 +gmyth_livetv_finalize (GObject *object)
    4.54 +{
    4.55 +	g_signal_handlers_destroy (object);
    4.56 +
    4.57 +	GMythLiveTV *livetv = GMYTH_LIVETV (object);
    4.58 +
    4.59 +	g_debug ("[%s] Finalizing livetv", __FUNCTION__);
    4.60 +
    4.61 +	if ( livetv->remote_encoder != NULL ) {
    4.62 +		g_object_unref (livetv->remote_encoder);
    4.63 +		livetv->remote_encoder = NULL;
    4.64 +	}
    4.65 +
    4.66 +	if ( livetv->tvchain != NULL ) {
    4.67 +		g_object_unref (livetv->tvchain);
    4.68 +		livetv->tvchain = NULL;
    4.69 +	}
    4.70 +
    4.71 +	if ( livetv->proginfo != NULL ) {
    4.72 +		g_object_unref (livetv->proginfo);
    4.73 +		livetv->proginfo = NULL;
    4.74 +	}
    4.75 +
    4.76 +	G_OBJECT_CLASS ( gmyth_livetv_parent_class )->finalize ( object );
    4.77 +}
    4.78 +
    4.79 +GMythLiveTV*
    4.80 +gmyth_livetv_new ()
    4.81 +{
    4.82 +	GMythLiveTV *livetv = GMYTH_LIVETV ( g_object_new( GMYTH_LIVETV_TYPE, NULL ) );
    4.83 +
    4.84 +	return livetv;
    4.85 +}
    4.86 +
    4.87 +gboolean
    4.88 +gmyth_livetv_setup ( GMythLiveTV *livetv )
    4.89 +{
    4.90 +	GMythSettings *msettings = gmyth_context_get_settings ();
    4.91 +	gboolean res = TRUE;
    4.92 +
    4.93 +	livetv->is_livetv = TRUE;
    4.94 +
    4.95 +	res = gmyth_context_check_connection();
    4.96 +	if (!res) {
    4.97 +		g_warning ("[%s] LiveTV can not connect to backend", __FUNCTION__);	
    4.98 +		res = FALSE;
    4.99 +		goto error;
   4.100 +	}
   4.101 +
   4.102 +	livetv->backend_hostname = gmyth_settings_get_backend_hostname(msettings);
   4.103 +	livetv->backend_port = gmyth_settings_get_backend_port (msettings);
   4.104 +
   4.105 +	livetv->local_hostname  = g_string_new("");    
   4.106 +	gmyth_context_get_local_hostname (livetv->local_hostname);
   4.107 +
   4.108 +	if ( livetv->local_hostname == NULL ) {
   4.109 +		res = FALSE;
   4.110 +		goto error;
   4.111 +	}
   4.112 +
   4.113 +	// Gets the remote encoder num
   4.114 +	livetv->remote_encoder = remote_request_next_free_recorder (-1);
   4.115 +
   4.116 +	if ( livetv->remote_encoder == NULL ) {
   4.117 +		g_warning ("[%s] None remote encoder available", __FUNCTION__);
   4.118 +		res = FALSE;
   4.119 +		goto error;
   4.120 +	}
   4.121 +
   4.122 +	// Creates livetv chain handler
   4.123 +	livetv->tvchain = GMYTH_TVCHAIN ( g_object_new(GMYTH_TVCHAIN_TYPE, NULL) );
   4.124 +	gmyth_tvchain_initialize ( livetv->tvchain, livetv->local_hostname );
   4.125 +
   4.126 +	if ( livetv->tvchain == NULL || livetv->tvchain->tvchain_id == NULL ) {
   4.127 +		res = FALSE;
   4.128 +		goto error;
   4.129 +	}
   4.130 +
   4.131 +	// Init remote encoder. Opens its control socket.
   4.132 +	res = gmyth_remote_encoder_setup(livetv->remote_encoder);
   4.133 +	if ( !res ) {
   4.134 +		g_warning ("[%s] Fail while setting remote encoder\n", __FUNCTION__);
   4.135 +		res = FALSE;
   4.136 +		goto error;
   4.137 +	}
   4.138 +	// Spawn live tv. Uses the socket to send mythprotocol data to start livetv in the backend (remotelly)
   4.139 +	res = gmyth_remote_encoder_spawntv ( livetv->remote_encoder,
   4.140 +			gmyth_tvchain_get_id(livetv->tvchain) );
   4.141 +	if (!res) {
   4.142 +		g_warning ("[%s] Fail while spawn tv\n", __FUNCTION__);
   4.143 +		res = FALSE;
   4.144 +		goto error;
   4.145 +	}
   4.146 +
   4.147 +	// Reload all TV chain from Mysql database.
   4.148 +	gmyth_tvchain_reload_all (livetv->tvchain);
   4.149 +
   4.150 +	if ( livetv->tvchain == NULL ) {
   4.151 +		res = FALSE;
   4.152 +		goto error;
   4.153 +	}
   4.154 +
   4.155 +	// Get program info from database using chanid and starttime
   4.156 +	livetv->proginfo = gmyth_tvchain_get_program_at (livetv->tvchain, tvchain_curr_index++ );
   4.157 +	if ( livetv->proginfo == NULL ) {
   4.158 +		g_warning ("[%s] LiveTV not successfully started.\n", __FUNCTION__ );
   4.159 +		res = FALSE;
   4.160 +		goto error;
   4.161 +	} else {
   4.162 +		g_debug ("[%s] GMythLiveTV: All requests to backend to start TV were OK.\n", __FUNCTION__ );
   4.163 +	}
   4.164 +
   4.165 +	return res;
   4.166 +
   4.167 +error:
   4.168 +	if ( livetv->backend_hostname != NULL ) {
   4.169 +		g_string_free( livetv->backend_hostname, TRUE );
   4.170 +		res = FALSE;
   4.171 +	}
   4.172 +
   4.173 +	if ( livetv->local_hostname != NULL ) {
   4.174 +		g_string_free( livetv->local_hostname, TRUE );
   4.175 +		res = FALSE;
   4.176 +	}
   4.177 +
   4.178 +	if ( livetv->remote_encoder != NULL ) {
   4.179 +		g_object_unref (livetv->remote_encoder);
   4.180 +		livetv->remote_encoder = NULL;
   4.181 +	}
   4.182 +
   4.183 +	if ( livetv->tvchain != NULL ) {
   4.184 +		g_object_unref (livetv->tvchain);
   4.185 +		livetv->tvchain = NULL;
   4.186 +	}
   4.187 +
   4.188 +	if ( livetv->proginfo != NULL ) {
   4.189 +		g_object_unref (livetv->proginfo);
   4.190 +		livetv->proginfo = NULL;
   4.191 +	}
   4.192 +
   4.193 +	return res;
   4.194 +
   4.195 +}
   4.196 +
   4.197 +// FIXME: How to proceed differently between livetv and recorded content
   4.198 +void
   4.199 +gmyth_livetv_stop_playing (GMythLiveTV *livetv) 
   4.200 +{
   4.201 +	g_debug ("[%s] Stopping the LiveTV...\n", __FUNCTION__);
   4.202 +
   4.203 +	if (livetv->is_livetv) {
   4.204 +		if (!gmyth_remote_encoder_stop_livetv (livetv->remote_encoder)) {
   4.205 +			g_warning ("[%s] Error while stoping remote encoder", __FUNCTION__);	
   4.206 +		}
   4.207 +	}
   4.208 +}
   4.209 +
   4.210 +gboolean
   4.211 +gmyth_livetv_is_playing (GMythLiveTV *livetv)
   4.212 +{
   4.213 +	return TRUE;
   4.214 +}
   4.215 +
   4.216 +void
   4.217 +gmyth_livetv_start_playing (GMythLiveTV *livetv)
   4.218 +{
   4.219 +
   4.220 +	// TODO
   4.221 +
   4.222 +}
   4.223 +
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/gmyth/src/gmyth_livetv.h	Mon Oct 23 16:02:15 2006 +0100
     5.3 @@ -0,0 +1,59 @@
     5.4 +#ifndef GMYTH_LIVETV_H_
     5.5 +#define GMYTH_LIVETV_H_
     5.6 +
     5.7 +#include <glib-object.h>
     5.8 +
     5.9 +#include <gmyth/gmyth_remote_encoder.h>
    5.10 +#include <gmyth/gmyth_tvchain.h>
    5.11 +#include <gmyth/gmyth_common.h>
    5.12 +
    5.13 +#include <gmyth/gmyth_file_transfer.h>
    5.14 +
    5.15 +#define G_BEGIN_DECLS
    5.16 +
    5.17 +#define GMYTH_LIVETV_TYPE               (gmyth_livetv_get_type ())
    5.18 +#define GMYTH_LIVETV(obj)               (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_LIVETV_TYPE, GMythLiveTV))
    5.19 +#define GMYTH_LIVETV_CLASS(klass)       (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_LIVETV_TYPE, GMythLiveTVClass))
    5.20 +#define IS_GMYTH_LIVETV(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GMYTH_LIVETV_TYPE))
    5.21 +#define IS_GMYTH_LIVETV_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_LIVETV_TYPE))
    5.22 +#define GMYTH_LIVETV_GET_CLASS(obj)     (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_LIVETV_TYPE, GMythLiveTVClass))
    5.23 +
    5.24 +typedef struct _GMythLiveTV         GMythLiveTV;
    5.25 +typedef struct _GMythLiveTVClass    GMythLiveTVClass;
    5.26 +
    5.27 +struct _GMythLiveTVClass
    5.28 +{
    5.29 +  GObjectClass parent_class;
    5.30 +
    5.31 +  /* callbacks */
    5.32 +};
    5.33 +
    5.34 +struct _GMythLiveTV
    5.35 +{
    5.36 +	GObject parent;
    5.37 +
    5.38 +	// Backend connection related variables
    5.39 +	GString *backend_hostname;
    5.40 +	gint backend_port;
    5.41 +	GString *local_hostname;
    5.42 +
    5.43 +	GMythRemoteEncoder *remote_encoder;
    5.44 +	GMythTVChain *tvchain;
    5.45 +	GMythProgramInfo *proginfo;
    5.46 +
    5.47 +	gboolean is_livetv;
    5.48 +
    5.49 +};
    5.50 +
    5.51 +GType          gmyth_livetv_get_type (void);
    5.52 +
    5.53 +GMythLiveTV* gmyth_livetv_new ();
    5.54 +
    5.55 +void gmyth_livetv_start_playing (GMythLiveTV *livetv);
    5.56 +void gmyth_livetv_stop_playing (GMythLiveTV *livetv);
    5.57 +
    5.58 +gboolean gmyth_livetv_setup (GMythLiveTV *livetv);
    5.59 +
    5.60 +#define G_END_DECLS
    5.61 +
    5.62 +#endif /*GMYTH_LIVETV_H_*/
     6.1 --- a/gmyth/src/gmyth_stringlist.h	Mon Oct 23 15:42:46 2006 +0100
     6.2 +++ b/gmyth/src/gmyth_stringlist.h	Mon Oct 23 16:02:15 2006 +0100
     6.3 @@ -80,6 +80,9 @@
     6.4  GString *           gmyth_string_list_append_uint64 (GMythStringList *strlist, 
     6.5                                                       const guint64 value);
     6.6  
     6.7 +GString *           gmyth_string_list_append_int64 (GMythStringList *strlist, 
     6.8 +                                                     const gint64 value);
     6.9 +
    6.10  GString *           gmyth_string_list_append_char_array (GMythStringList *strlist, 
    6.11                                                           const char* value);
    6.12  GString *           gmyth_string_list_append_string (GMythStringList *strlist, 
    6.13 @@ -87,6 +90,7 @@
    6.14  
    6.15  int                 gmyth_string_list_get_int (GMythStringList *strlist, const gint index);
    6.16  guint64             gmyth_string_list_get_uint64 (GMythStringList *strlist, const gint index);
    6.17 +gint64             gmyth_string_list_get_int64 (GMythStringList *strlist, const gint index);
    6.18  GString *           gmyth_string_list_get_string (GMythStringList *strlist, const gint index);
    6.19  
    6.20  #define gmyth_string_list_get_char_array(strlist, index) \
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/gmyth/src/gmyth_uri.c	Mon Oct 23 16:02:15 2006 +0100
     7.3 @@ -0,0 +1,208 @@
     7.4 +/**
     7.5 + *
     7.6 + *    GMythURI utils
     7.7 + *  - Extracts and parses a URI char string, in according with the RFC 2396
     7.8 + *    [http://www.ietf.org/rfc/rfc2396.txt]
     7.9 + *
    7.10 + *   @author Rosfran Borges (rosfran.borges@indt.org.br)
    7.11 + *
    7.12 + */
    7.13 +
    7.14 +#include <gmyth/gmyth_uri.h>
    7.15 +#include <glib.h>
    7.16 +#include <string.h>
    7.17 +#include <stdlib.h>
    7.18 +
    7.19 +static gint 
    7.20 +gmyth_strstr( const gchar *haystack, const gchar *needle )
    7.21 +{
    7.22 +	
    7.23 +	gchar *strPos;
    7.24 +	
    7.25 +	if (haystack == NULL || needle == NULL)
    7.26 +		return -1;
    7.27 +	strPos = strstr(haystack, needle);
    7.28 +	if (strPos == NULL)
    7.29 +		return -1;
    7.30 +		
    7.31 +	return (strPos - haystack);
    7.32 +
    7.33 +}
    7.34 +
    7.35 +static gboolean
    7.36 +gmyth_uri_isabsolute( const GMythURI *uri )
    7.37 +{
    7.38 +	gboolean ret = FALSE;
    7.39 +	
    7.40 +	g_return_val_if_fail( uri != NULL && uri->uri != NULL && uri->protocol != NULL, FALSE );
    7.41 +	
    7.42 +	if ( gmyth_strstr( uri->uri->str, GMYTH_URI_PROTOCOL_DELIM ) == 0 || strlen(uri->protocol->str) > 0 )
    7.43 +		ret = TRUE;
    7.44 +		
    7.45 +	return ret;	
    7.46 +}
    7.47 +
    7.48 +static gint
    7.49 +gmyth_strrchr( const gchar *str, const gchar *chars, const gint nchars )
    7.50 +{
    7.51 +
    7.52 +	gint strLen;
    7.53 +	gint i, j;
    7.54 +	
    7.55 +	if ( str == NULL || chars == NULL )
    7.56 +		return -1;
    7.57 +		
    7.58 +	strLen = strlen( str );
    7.59 +	for ( i= (strLen-1); 0 <= i; i-- ) {
    7.60 +		for ( j=0; j<nchars; j++ ) {
    7.61 +			if ( str[i] == chars[j] )
    7.62 +				return i;
    7.63 +		}
    7.64 +	}
    7.65 +
    7.66 +	return -1;
    7.67 +
    7.68 +}
    7.69 +
    7.70 +static GMythURI *
    7.71 +gmyth_uri_init( )
    7.72 +{
    7.73 +	GMythURI *uri = g_new0( GMythURI, 1 );
    7.74 +	uri->host = g_string_new("");
    7.75 +	uri->fragment = g_string_new("");
    7.76 +	uri->password = g_string_new("");
    7.77 +	uri->path = g_string_new("");
    7.78 +	uri->protocol = g_string_new("");
    7.79 +	uri->query = g_string_new("");
    7.80 +	uri->uri = g_string_new("");
    7.81 +	uri->user = g_string_new("");
    7.82 +	return uri;
    7.83 +}
    7.84 +
    7.85 +const GMythURI *
    7.86 +gmyth_uri_new( gchar *value )
    7.87 +{
    7.88 +	
    7.89 +	GMythURI *uri = gmyth_uri_init();
    7.90 +
    7.91 +	gchar *protocol;
    7.92 +	gint uriLen;
    7.93 +	gint currIdx;
    7.94 +	gint protoIdx;
    7.95 +	gint atIdx;
    7.96 +	gint colonIdx;
    7.97 +	gint shashIdx;
    7.98 +	gchar *host;
    7.99 +	gint eblacketIdx;
   7.100 +	GString *hostStr;
   7.101 +	GString *portStr;
   7.102 +	gint hostLen;
   7.103 +	gint sharpIdx;
   7.104 +	gint questionIdx;
   7.105 +	gint queryLen;
   7.106 +	
   7.107 +	uriLen = strlen(value);
   7.108 +	uri->uri = g_string_new( value );
   7.109 +		
   7.110 +	currIdx = 0;
   7.111 +	
   7.112 +	/*** Protocol ****/
   7.113 +	protoIdx = gmyth_strstr( value, GMYTH_URI_PROTOCOL_DELIM );
   7.114 +	if (0 < protoIdx) {
   7.115 +		uri->protocol = g_string_append_len( uri->protocol, value, protoIdx );
   7.116 +		currIdx += protoIdx + strlen( GMYTH_URI_PROTOCOL_DELIM );
   7.117 +	}
   7.118 +
   7.119 +	/*** User (Password) ****/
   7.120 +	atIdx = gmyth_strstr( value+currIdx, GMYTH_URI_USER_DELIM );
   7.121 +	if ( 0 < atIdx ) {
   7.122 +		colonIdx = gmyth_strstr( value+currIdx, GMYTH_URI_COLON_DELIM );
   7.123 +
   7.124 +		if (0 < colonIdx && colonIdx < atIdx) {
   7.125 +			uri->user = g_string_append_len( uri->user, value+currIdx,  colonIdx );
   7.126 +			uri->password = g_string_append_len( uri->password, value+currIdx+colonIdx+1, atIdx-(colonIdx+1) );
   7.127 +		}
   7.128 +		else 
   7.129 +			uri->user = g_string_append_len( uri->user, value+currIdx, atIdx - currIdx );
   7.130 +		currIdx += atIdx + 1;
   7.131 +	}
   7.132 +
   7.133 +	/*** Host (Port) ****/
   7.134 +	shashIdx = gmyth_strstr( value+currIdx, GMYTH_URI_SLASH_DELIM );
   7.135 +	if ( 0 < shashIdx )
   7.136 +		uri->host = g_string_append_len( uri->host, value+currIdx, shashIdx );
   7.137 +	else if ( gmyth_uri_isabsolute(uri) == TRUE )
   7.138 +		uri->host = g_string_append_len( uri->host, value+currIdx, strlen(value) - currIdx );
   7.139 +	host = g_strdup( gmyth_uri_gethost(uri) );
   7.140 +	colonIdx = gmyth_strrchr( host, GMYTH_URI_COLON_DELIM, 1 );
   7.141 +	eblacketIdx = gmyth_strrchr( host, GMYTH_URI_EBLACET_DELIM, 1 );
   7.142 +	if ( ( 0 < colonIdx ) && ( eblacketIdx < colonIdx ) ) {
   7.143 +		hostStr = g_string_new( host );
   7.144 +
   7.145 +		hostLen = hostStr->len;
   7.146 +		/**** host ****/
   7.147 +		uri->host = g_string_erase( uri->host, 0, hostLen );
   7.148 +		uri->host = g_string_insert_len( uri->host, 0, hostStr->str, colonIdx );
   7.149 +		//host = gmyth_uri_gethost( uri );
   7.150 +		if (0 < hostLen) {
   7.151 +			if (host[0] == '[' && host[hostLen-1] == ']')
   7.152 +				uri->host = g_string_append_len( uri->host, hostStr->str+1,  colonIdx-2 );
   7.153 +		}
   7.154 +		/**** port ****/
   7.155 +		portStr = g_string_new("");
   7.156 +		portStr = g_string_append_len( portStr, hostStr->str+colonIdx+1, hostLen-colonIdx-1 );
   7.157 +		uri->port = atoi( portStr->str );
   7.158 +		g_string_free( portStr, TRUE );
   7.159 +		g_string_free( hostStr, FALSE );
   7.160 +	}
   7.161 +	else {
   7.162 +		uri->port = GMYTH_URI_KNKOWN_PORT;
   7.163 +		protocol = gmyth_uri_getprotocol(uri);
   7.164 +		if ( strcmp(protocol, GMYTH_URI_PROTOCOL_HTTP) == 0 )
   7.165 +			uri->port = GMYTH_URI_DEFAULT_HTTP_PORT;
   7.166 +		if ( strcmp(protocol, GMYTH_URI_PROTOCOL_FTP) == 0 )
   7.167 +			uri->port = GMYTH_URI_DEFAULT_FTP_PORT;
   7.168 +	}
   7.169 +	
   7.170 +	if (shashIdx > 0) currIdx += shashIdx;
   7.171 +	
   7.172 +	/*
   7.173 +		Handle relative URL
   7.174 +	*/
   7.175 +	if (gmyth_uri_isabsolute(uri) == FALSE)
   7.176 +	{
   7.177 +
   7.178 +		if (shashIdx != 0)
   7.179 +		{
   7.180 +			/* Add slash delimiter at the beginning of the URL,
   7.181 +			   if it doesn't exist 
   7.182 +			*/
   7.183 +			uri->path = g_string_new( GMYTH_URI_SLASH_DELIM );
   7.184 +		}
   7.185 +		uri->path = g_string_append( uri->path, value );
   7.186 +		
   7.187 +	} else {
   7.188 +		/* First set path simply to the rest of URI */
   7.189 +		g_string_append_len( uri->path, value+currIdx,  uriLen-currIdx );
   7.190 +	}
   7.191 +		
   7.192 +	/**** Path (Query/Fragment) ****/
   7.193 +	sharpIdx = gmyth_strstr(value+currIdx, GMYTH_URI_SHARP_DELIM);
   7.194 +	if (0 < sharpIdx) {
   7.195 +		uri->path = g_string_append_len( uri->path, value+currIdx, sharpIdx);
   7.196 +		uri->fragment = g_string_append_len( uri->fragment, 
   7.197 +			value+currIdx+sharpIdx+1, uriLen-(currIdx+sharpIdx+1));
   7.198 +	}
   7.199 +	
   7.200 +	questionIdx = gmyth_strstr( value+currIdx, GMYTH_URI_QUESTION_DELIM );
   7.201 +	if ( 0 < questionIdx ) {
   7.202 +		uri->path = g_string_append_len( uri->path, value+currIdx, questionIdx );
   7.203 +		queryLen = uriLen-(currIdx+questionIdx+1);
   7.204 +		if ( 0 < sharpIdx )
   7.205 +			queryLen -= uriLen - (currIdx+sharpIdx+1);
   7.206 +		uri->query = g_string_append_len( uri->query, value+currIdx+questionIdx+1, queryLen );
   7.207 +	}
   7.208 +	
   7.209 +	return uri;
   7.210 +
   7.211 +}
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/gmyth/src/gmyth_uri.h	Mon Oct 23 16:02:15 2006 +0100
     8.3 @@ -0,0 +1,63 @@
     8.4 +/**
     8.5 + *
     8.6 + *	GMythURI utils
     8.7 + *  - Extracts and parses a URI char string, in according with the RFC 2396 
     8.8 + *    [http://www.ietf.org/rfc/rfc2396.txt]
     8.9 + *
    8.10 + * @author Rosfran Borges (rosfran.borges@indt.org.br)
    8.11 + * 
    8.12 + */
    8.13 +
    8.14 +#ifndef _GMYTH_URI_H_
    8.15 +#define _GMYTH_URI_H_
    8.16 +
    8.17 +#include <glib.h>
    8.18 +
    8.19 +/****************************************
    8.20 +* Define
    8.21 +****************************************/
    8.22 +
    8.23 +#define GMYTH_URI_KNKOWN_PORT (-1)
    8.24 +#define GMYTH_URI_DEFAULT_HTTP_PORT 80
    8.25 +#define GMYTH_URI_DEFAULT_FTP_PORT 21
    8.26 +#define GMYTH_URI_DEFAULT_PATH "/"
    8.27 +#define GMYTH_URI_MAXLEN 256
    8.28 +
    8.29 +#define GMYTH_URI_PROTOCOL_DELIM "://"
    8.30 +#define GMYTH_URI_USER_DELIM "@"
    8.31 +#define GMYTH_URI_COLON_DELIM ":"
    8.32 +#define GMYTH_URI_SLASH_DELIM "/"
    8.33 +#define GMYTH_URI_SBLACET_DELIM "["
    8.34 +#define GMYTH_URI_EBLACET_DELIM "]"
    8.35 +#define GMYTH_URI_SHARP_DELIM "#"
    8.36 +#define GMYTH_URI_QUESTION_DELIM "?"
    8.37 +#define GMYTH_URI_ESCAPING_CHAR "%"
    8.38 +
    8.39 +#define GMYTH_URI_PROTOCOL_MYTH "myth"
    8.40 +#define GMYTH_URI_PROTOCOL_HTTP "http"
    8.41 +#define GMYTH_URI_PROTOCOL_FTP "ftp"
    8.42 +
    8.43 +/****************************************
    8.44 +* Data Type
    8.45 +****************************************/
    8.46 +
    8.47 +typedef struct _GMythURI {
    8.48 +	GString *uri;
    8.49 +	GString *host;
    8.50 +	gint port;
    8.51 +	GString *protocol;
    8.52 +	GString *path;
    8.53 +	GString *fragment;
    8.54 +	GString *user;
    8.55 +	GString *password;
    8.56 +	GString *query;
    8.57 +} GMythURI;
    8.58 +
    8.59 +const GMythURI *gmyth_uri_new( gchar *value );
    8.60 +
    8.61 +#define gmyth_uri_gethost(urip) (urip->host->str)
    8.62 +#define gmyth_uri_getport(urip) (urip->port)
    8.63 +#define gmyth_uri_getprotocol(urip) (urip->protocol->str)
    8.64 +#define gmyth_uri_getpath(urip) (urip->path->str)
    8.65 +
    8.66 +#endif