gst-plugins-mythtv/src/gmyth_file_transfer.c
author rosfran
Mon Oct 23 16:02:15 2006 +0100 (2006-10-23)
branchtrunk
changeset 41 686549eb5657
parent 37 324e04989738
permissions -rwxr-xr-x
[svn r42] Added FileTransfer, URI and LiveTV functionalities (moved from the MythTV plug-in).
leo_sobral@2
     1
/* vim: set sw=2: -*- Mode: C; tab-width: 2; indent-tabs-mode: t; c-basic-offset: 2; c-indent-level: 2-*- */
leo_sobral@2
     2
/**
leo_sobral@2
     3
 * GStreamer plug-in properties:
leo_sobral@2
     4
 * - location (backend server hostname/URL) [ex.: myth://192.168.1.73:28722/1000_1092091.nuv]
leo_sobral@2
     5
 * - path (qurl - remote file to be opened)
leo_sobral@2
     6
 * - port number
leo_sobral@2
     7
 *   @author Rosfran Lins Borges <rosfran.borges@indt.org.br>
leo_sobral@2
     8
 */
leo_sobral@2
     9
rosfran@40
    10
#include "gmyth_file_transfer.h"
rosfran@40
    11
#include "gmyth_uri.h"
rosfran@40
    12
#include "gmyth_livetv.h"
leo_sobral@2
    13
#include <gmyth/gmyth_util.h>
leo_sobral@2
    14
#include <gmyth/gmyth_socket.h>
leo_sobral@2
    15
#include <gmyth/gmyth_stringlist.h>
leo_sobral@2
    16
leo_sobral@2
    17
#include <unistd.h>
leo_sobral@2
    18
#include <glib.h>
leo_sobral@2
    19
leo_sobral@2
    20
#include <arpa/inet.h>
leo_sobral@2
    21
#include <sys/types.h>
leo_sobral@2
    22
#include <sys/socket.h>
leo_sobral@2
    23
#include <netdb.h>
leo_sobral@2
    24
#include <errno.h>
leo_sobral@2
    25
#include <stdlib.h>
leo_sobral@2
    26
rosfran@40
    27
#define GMYTHTV_QUERY_HEADER "QUERY_FILETRANSFER"
rosfran@40
    28
#define GMYTHTV_RECORDER_HEADER "QUERY_RECORDER"
leo_sobral@2
    29
leo_sobral@2
    30
/* default values to the file transfer parameters */
rosfran@40
    31
#define GMYTHTV_USER_READ_AHEAD	FALSE
rosfran@40
    32
#define GMYTHTV_RETRIES			1
rosfran@40
    33
#define GMYTHTV_FILE_SIZE		-1
leo_sobral@2
    34
rosfran@40
    35
#define GMYTHTV_BUFFER_SIZE		8*1024
leo_sobral@2
    36
rosfran@40
    37
#define GMYTHTV_VERSION			30
leo_sobral@2
    38
rosfran@40
    39
#define GMYTHTV_TRANSFER_MAX_WAITS	700
leo_sobral@2
    40
rosfran@40
    41
#ifdef GMYTHTV_ENABLE_DEBUG
rosfran@40
    42
#define GMYTHTV_ENABLE_DEBUG	1
leo_sobral@2
    43
#else
rosfran@40
    44
#undef GMYTHTV_ENABLE_DEBUG
leo_sobral@2
    45
#endif
leo_sobral@2
    46
leo_sobral@2
    47
/* this NDEBUG is to maintain compatibility with GMyth library */
leo_sobral@2
    48
#ifndef NDEBUG
rosfran@40
    49
#define GMYTHTV_ENABLE_DEBUG	1
leo_sobral@2
    50
#endif
leo_sobral@2
    51
leo_sobral@2
    52
static guint wait_to_transfer = 0;
leo_sobral@2
    53
leo_sobral@2
    54
enum myth_sock_types {
rosfran@40
    55
  GMYTH_PLAYBACK_TYPE = 0,
rosfran@40
    56
  GMYTH_MONITOR_TYPE,
rosfran@40
    57
  GMYTH_FILETRANSFER_TYPE,
rosfran@40
    58
  GMYTH_RINGBUFFER_TYPE
leo_sobral@2
    59
};
leo_sobral@2
    60
leo_sobral@2
    61
static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
leo_sobral@2
    62
rosfran@37
    63
static GMainContext *io_watcher_context = NULL;
rosfran@37
    64
rosfran@40
    65
static void gmyth_file_transfer_class_init          (GMythFileTransferClass *klass);
rosfran@40
    66
static void gmyth_file_transfer_init                (GMythFileTransfer *object);
leo_sobral@2
    67
rosfran@40
    68
static void gmyth_file_transfer_dispose  (GObject *object);
rosfran@40
    69
static void gmyth_file_transfer_finalize (GObject *object);
leo_sobral@2
    70
rosfran@40
    71
static GMythSocket *myth_connect_to_transfer_backend( GMythFileTransfer **transfer, guint sock_type );
leo_sobral@2
    72
static void* myth_init_io_watchers( void *data );
leo_sobral@2
    73
rosfran@40
    74
void gmyth_file_transfer_close( GMythFileTransfer *transfer );
leo_sobral@2
    75
rosfran@40
    76
G_DEFINE_TYPE(GMythFileTransfer, gmyth_file_transfer, G_TYPE_OBJECT)
leo_sobral@2
    77
rosfran@37
    78
#if 0
leo_sobral@2
    79
static guint64
leo_sobral@2
    80
mmyth_util_decode_long_long( GMythStringList *strlist, guint offset  )
leo_sobral@2
    81
{
leo_sobral@2
    82
leo_sobral@2
    83
  guint64 ret_value = 0LL;
leo_sobral@2
    84
leo_sobral@2
    85
  g_return_val_if_fail( strlist != NULL, ret_value );
leo_sobral@2
    86
leo_sobral@2
    87
  if ( offset < gmyth_string_list_length( strlist ))
leo_sobral@2
    88
    g_printerr( "[%s] Offset is lower than the GMythStringList (offset = %d)!\n", __FUNCTION__, offset );
leo_sobral@2
    89
  g_return_val_if_fail( offset < gmyth_string_list_length( strlist ), ret_value );
leo_sobral@2
    90
leo_sobral@2
    91
  gint l1 = gmyth_string_list_get_int( strlist, offset );
leo_sobral@2
    92
  gint l2 = gmyth_string_list_get_int( strlist, offset + 1 );
leo_sobral@2
    93
leo_sobral@2
    94
  ret_value = ((guint64)(l2) & 0xffffffffLL) | ((guint64)(l1) << 32);
leo_sobral@2
    95
leo_sobral@2
    96
  return ret_value;
leo_sobral@2
    97
leo_sobral@2
    98
}
rosfran@37
    99
#endif
leo_sobral@2
   100
leo_sobral@2
   101
static void
rosfran@40
   102
gmyth_file_transfer_class_init (GMythFileTransferClass *klass)
leo_sobral@2
   103
{
leo_sobral@2
   104
  GObjectClass *gobject_class;
leo_sobral@2
   105
leo_sobral@2
   106
  gobject_class = (GObjectClass *) klass;
leo_sobral@2
   107
rosfran@40
   108
  gobject_class->dispose  = gmyth_file_transfer_dispose;
rosfran@40
   109
  gobject_class->finalize = gmyth_file_transfer_finalize;
leo_sobral@2
   110
}
leo_sobral@2
   111
leo_sobral@2
   112
  static void
rosfran@40
   113
gmyth_file_transfer_init (GMythFileTransfer *gmyth_file_transfer)
leo_sobral@2
   114
{ 
rosfran@40
   115
  g_return_if_fail( gmyth_file_transfer != NULL );
rosfran@40
   116
  gmyth_file_transfer->mythtv_version = GMYTHTV_VERSION;
leo_sobral@2
   117
}
leo_sobral@2
   118
leo_sobral@2
   119
static void
rosfran@40
   120
gmyth_file_transfer_dispose  (GObject *object)
leo_sobral@2
   121
{
rosfran@40
   122
  GMythFileTransfer *gmyth_file_transfer = GMYTH_FILE_TRANSFER(object);
leo_sobral@2
   123
rosfran@40
   124
  gmyth_file_transfer_close( gmyth_file_transfer );
leo_sobral@2
   125
rosfran@40
   126
  G_OBJECT_CLASS (gmyth_file_transfer_parent_class)->dispose (object);
leo_sobral@2
   127
}
leo_sobral@2
   128
leo_sobral@2
   129
  static void
rosfran@40
   130
gmyth_file_transfer_finalize (GObject *object)
leo_sobral@2
   131
{
leo_sobral@2
   132
  g_signal_handlers_destroy (object);
leo_sobral@2
   133
rosfran@40
   134
  G_OBJECT_CLASS (gmyth_file_transfer_parent_class)->finalize (object);
leo_sobral@2
   135
}
leo_sobral@2
   136
rosfran@40
   137
  GMythFileTransfer*
rosfran@40
   138
gmyth_file_transfer_new (gint num, GString *uri_str, gshort port, gint mythtv_version)
leo_sobral@2
   139
{
rosfran@40
   140
  GMythFileTransfer *transfer = GMYTH_FILE_TRANSFER ( g_object_new (
rosfran@40
   141
	GMYTH_FILE_TRANSFER_TYPE, FALSE ));
leo_sobral@2
   142
leo_sobral@2
   143
  if ( mythtv_version > 0 )
leo_sobral@2
   144
    transfer->mythtv_version = mythtv_version;
leo_sobral@2
   145
leo_sobral@2
   146
  transfer->card_id = num;
leo_sobral@2
   147
leo_sobral@2
   148
  transfer->rec_id = -1;
leo_sobral@2
   149
rosfran@30
   150
  transfer->recordernum = num;
rosfran@40
   151
  transfer->uri = gmyth_uri_new ( uri_str->str );
leo_sobral@2
   152
rosfran@40
   153
  transfer->hostname = g_string_new( gmyth_uri_gethost(transfer->uri) );
leo_sobral@2
   154
  g_print( "\t--> transfer->hostname = %s\n", transfer->hostname->str );
leo_sobral@2
   155
leo_sobral@2
   156
  if ( port >= 0 )
leo_sobral@2
   157
    transfer->port = port;
leo_sobral@2
   158
  else
rosfran@40
   159
    transfer->port = gmyth_uri_getport( transfer->uri );
leo_sobral@2
   160
leo_sobral@2
   161
  g_print( "\t--> transfer->port = %d\n", transfer->port );
leo_sobral@2
   162
leo_sobral@2
   163
  transfer->readposition = 0;
rosfran@40
   164
  transfer->filesize = GMYTHTV_FILE_SIZE;
leo_sobral@2
   165
  transfer->timeoutisfast = FALSE;
leo_sobral@2
   166
rosfran@40
   167
  transfer->userreadahead = GMYTHTV_USER_READ_AHEAD;
rosfran@40
   168
  transfer->retries = GMYTHTV_RETRIES;  
leo_sobral@2
   169
leo_sobral@2
   170
  transfer->live_tv = FALSE;
leo_sobral@2
   171
rosfran@40
   172
  transfer->query = g_string_new( GMYTHTV_QUERY_HEADER );
leo_sobral@2
   173
  g_string_append_printf ( transfer->query, " %d", transfer->recordernum );
leo_sobral@2
   174
  g_print( "\t--> transfer->query = %s\n", transfer->query->str );
leo_sobral@2
   175
leo_sobral@2
   176
  transfer->control_sock = NULL;
leo_sobral@2
   177
  transfer->event_sock = NULL;
leo_sobral@2
   178
  transfer->sock = NULL;
leo_sobral@2
   179
leo_sobral@2
   180
  return transfer;
leo_sobral@2
   181
}
leo_sobral@2
   182
leo_sobral@2
   183
gboolean
rosfran@40
   184
gmyth_file_transfer_livetv_setup( GMythFileTransfer **transfer, GMythSocket *live_socket )
leo_sobral@2
   185
{
leo_sobral@2
   186
	(*transfer)->sock = live_socket;
leo_sobral@2
   187
	g_object_ref( live_socket );
leo_sobral@2
   188
leo_sobral@2
   189
	return TRUE;
leo_sobral@2
   190
}
leo_sobral@2
   191
leo_sobral@2
   192
gboolean
rosfran@40
   193
gmyth_file_transfer_playback_setup( GMythFileTransfer **transfer, gboolean live_tv )
leo_sobral@2
   194
{
leo_sobral@2
   195
leo_sobral@2
   196
  gboolean ret = TRUE;
leo_sobral@2
   197
leo_sobral@2
   198
  (*transfer)->live_tv = live_tv;
leo_sobral@2
   199
leo_sobral@2
   200
  printf("[%s] Running config to the %s...\n", __FUNCTION__, live_tv ? "LiveTV" : "FileTransfer" );
leo_sobral@2
   201
leo_sobral@2
   202
  /* configure the control socket */
leo_sobral@2
   203
  if ((*transfer)->control_sock == NULL) { 
leo_sobral@2
   204
rosfran@40
   205
    if ( myth_connect_to_transfer_backend ( transfer, GMYTH_PLAYBACK_TYPE ) == NULL ) {
leo_sobral@2
   206
      g_printerr( "Connection to backend failed (Control Socket).\n" );
leo_sobral@2
   207
      ret = FALSE;
leo_sobral@2
   208
    }
leo_sobral@2
   209
leo_sobral@2
   210
  } else {
leo_sobral@2
   211
    g_warning("Remote transfer control socket already created.\n");
leo_sobral@2
   212
  }
leo_sobral@2
   213
leo_sobral@2
   214
  return ret;
leo_sobral@2
   215
leo_sobral@2
   216
}
leo_sobral@2
   217
leo_sobral@2
   218
gboolean
rosfran@40
   219
gmyth_file_transfer_setup( GMythFileTransfer **transfer, gboolean live_tv )
leo_sobral@2
   220
{
leo_sobral@2
   221
  GMythStringList *strlist = NULL;
leo_sobral@2
   222
leo_sobral@2
   223
  gboolean ret = TRUE;
leo_sobral@2
   224
leo_sobral@2
   225
  (*transfer)->live_tv = live_tv;
leo_sobral@2
   226
leo_sobral@2
   227
  printf("[%s] Running config to the %s...\n", __FUNCTION__, live_tv ? "LiveTV" : "FileTransfer" );
leo_sobral@2
   228
leo_sobral@2
   229
#if 0
rosfran@30
   230
  /* configure the control socket */
rosfran@37
   231
  if ((*transfer)->event_sock == NULL) { 
leo_sobral@2
   232
rosfran@40
   233
    if ( myth_connect_to_transfer_backend ( transfer, GMYTH_MONITOR_TYPE ) == NULL ) {
leo_sobral@2
   234
      g_printerr( "Connection to backend failed (Event Socket).\n" );
leo_sobral@2
   235
      ret = FALSE;
leo_sobral@2
   236
    }
leo_sobral@2
   237
leo_sobral@2
   238
  } else {
leo_sobral@2
   239
    g_warning("Remote transfer control socket already created.\n");
leo_sobral@2
   240
  }
leo_sobral@2
   241
#endif
leo_sobral@2
   242
leo_sobral@2
   243
  /* configure the socket */
leo_sobral@2
   244
  if ( (*transfer)->sock == NULL ) { 
leo_sobral@2
   245
leo_sobral@2
   246
    //if ( live_tv == FALSE ) {
leo_sobral@2
   247
rosfran@40
   248
    if ( myth_connect_to_transfer_backend ( transfer, GMYTH_FILETRANSFER_TYPE ) == NULL ) {
leo_sobral@2
   249
      g_printerr ("Connection to backend failed (Raw Transfer Socket).\n");
leo_sobral@2
   250
      ret = FALSE;
leo_sobral@2
   251
    }
leo_sobral@2
   252
leo_sobral@2
   253
    if ( !(*transfer)->live_tv && (*transfer)->control_sock != NULL) {
leo_sobral@2
   254
      strlist = gmyth_string_list_new();
rosfran@40
   255
      g_string_printf ( (*transfer)->query, "%s %d", GMYTHTV_QUERY_HEADER, (*transfer)->recordernum );
leo_sobral@2
   256
leo_sobral@2
   257
      gmyth_string_list_append_string( strlist, (*transfer)->query );
leo_sobral@2
   258
      gmyth_string_list_append_char_array( strlist, "IS_OPEN" );
leo_sobral@2
   259
leo_sobral@2
   260
      gmyth_socket_write_stringlist( (*transfer)->control_sock, strlist );
leo_sobral@2
   261
      gmyth_socket_read_stringlist( (*transfer)->control_sock, strlist );
leo_sobral@2
   262
leo_sobral@2
   263
      if ( strlist!=NULL && gmyth_string_list_get_int( strlist, 0 ) == 1 ) {
leo_sobral@2
   264
	g_print( "[%s] Remote Myth FileTransfer socket is open!\n", __FUNCTION__ );
leo_sobral@2
   265
      } else {
leo_sobral@2
   266
	g_print( "[%s] Remote Myth FileTransfer socket is CLOSED! See the MythTV Server Backend for configuration details...\n", __FUNCTION__ );
leo_sobral@2
   267
	ret = FALSE;
leo_sobral@2
   268
      }
leo_sobral@2
   269
    }
leo_sobral@2
   270
leo_sobral@2
   271
  } else {
leo_sobral@2
   272
    g_warning("Remote transfer (raw) socket already created.\n");
leo_sobral@2
   273
  }
leo_sobral@2
   274
leo_sobral@2
   275
  return ret;
leo_sobral@2
   276
}
leo_sobral@2
   277
leo_sobral@2
   278
static GMythSocket *
rosfran@40
   279
myth_connect_to_transfer_backend( GMythFileTransfer **transfer, guint sock_type )
leo_sobral@2
   280
{
leo_sobral@2
   281
  GMythSocket *sock = NULL;
leo_sobral@2
   282
leo_sobral@2
   283
  g_return_val_if_fail( transfer != NULL && *transfer != NULL, NULL );
leo_sobral@2
   284
  g_return_val_if_fail( (*transfer)->uri != NULL, NULL );
leo_sobral@2
   285
leo_sobral@2
   286
  g_static_mutex_lock (&mutex);
leo_sobral@2
   287
rosfran@40
   288
  gchar *path_dir = gmyth_uri_getpath( (*transfer)->uri );
leo_sobral@2
   289
  //g_print( "\t--> %s: path_dir = %s\n", __FUNCTION__, path_dir );
leo_sobral@2
   290
leo_sobral@2
   291
  gchar *stype = g_strdup( "" );
leo_sobral@2
   292
leo_sobral@2
   293
  //  if ( (*transfer)->live_tv == FALSE ) {
leo_sobral@2
   294
leo_sobral@2
   295
  sock = gmyth_socket_new();
leo_sobral@2
   296
leo_sobral@2
   297
  gmyth_socket_connect( &sock, (*transfer)->hostname->str, (*transfer)->port );
leo_sobral@2
   298
leo_sobral@2
   299
  /*
leo_sobral@2
   300
     } else {
leo_sobral@2
   301
     sock = (*transfer)->sock;
leo_sobral@2
   302
     }
leo_sobral@2
   303
     */
rosfran@40
   304
#ifdef GMYTHTV_ENABLE_DEBUG
leo_sobral@2
   305
leo_sobral@2
   306
  g_print( "[%s] --> Creating socket... (%s, %d)\n", __FUNCTION__, (*transfer)->hostname->str, (*transfer)->port );
leo_sobral@2
   307
#endif
leo_sobral@2
   308
leo_sobral@2
   309
  GMythStringList *strlist = NULL;
leo_sobral@2
   310
rosfran@40
   311
  GString *hostname = g_string_new( gmyth_uri_gethost( (*transfer)->uri ) );
leo_sobral@2
   312
  GString *base_str = g_string_new( "" );
leo_sobral@2
   313
leo_sobral@2
   314
  if ( gmyth_socket_check_protocol_version_number (sock, (*transfer)->mythtv_version) ) {
leo_sobral@2
   315
leo_sobral@2
   316
    if (sock == NULL) {
rosfran@40
   317
      stype = (sock_type==GMYTH_PLAYBACK_TYPE) ? "control socket" : "file data socket";
leo_sobral@2
   318
      g_printerr( "FileTransfer, open_socket(%s): \n"
leo_sobral@2
   319
	  "\t\t\tCould not connect to server \"%s\" @ port %d\n", stype, 
leo_sobral@2
   320
	  (*transfer)->hostname->str, (*transfer)->port );
leo_sobral@2
   321
      g_object_unref(sock);
leo_sobral@2
   322
      g_static_mutex_unlock (&mutex);
leo_sobral@2
   323
      return NULL;
leo_sobral@2
   324
    }
leo_sobral@2
   325
leo_sobral@2
   326
    hostname = gmyth_socket_get_local_hostname();
leo_sobral@2
   327
leo_sobral@2
   328
    g_print( "[%s] local hostname = %s\n", __FUNCTION__, hostname->str  );
leo_sobral@2
   329
rosfran@40
   330
    if ( sock_type == GMYTH_PLAYBACK_TYPE )
leo_sobral@2
   331
    {
leo_sobral@2
   332
      (*transfer)->control_sock = sock;
rosfran@37
   333
      g_string_printf( base_str, "ANN Playback %s %d", hostname->str, TRUE );
leo_sobral@2
   334
leo_sobral@2
   335
      gmyth_socket_send_command( (*transfer)->control_sock, base_str );
leo_sobral@2
   336
      GString *resp = gmyth_socket_receive_response( (*transfer)->control_sock );
leo_sobral@2
   337
      g_print( "[%s] Got Playback response from %s: %s\n", __FUNCTION__, base_str->str, resp->str );
leo_sobral@2
   338
    }
rosfran@40
   339
    else if ( sock_type == GMYTH_MONITOR_TYPE )
leo_sobral@2
   340
    {
leo_sobral@2
   341
      (*transfer)->event_sock = sock;
leo_sobral@2
   342
      g_string_printf( base_str, "ANN Monitor %s %d", hostname->str, TRUE );
leo_sobral@2
   343
leo_sobral@2
   344
      gmyth_socket_send_command( (*transfer)->event_sock, base_str );
leo_sobral@2
   345
      GString *resp = gmyth_socket_receive_response( (*transfer)->event_sock );
leo_sobral@2
   346
      g_print( "[%s] Got Monitor response from %s: %s\n", __FUNCTION__, base_str->str, resp->str );
rosfran@37
   347
      //g_thread_create( myth_init_io_watchers, (void*)(*transfer), FALSE, NULL );
rosfran@37
   348
      myth_init_io_watchers ( (void*)(*transfer) );
leo_sobral@2
   349
leo_sobral@2
   350
      g_printerr( "[%s] Watch listener function to the IO control channel on thread %p.\n", __FUNCTION__, g_thread_self() );
leo_sobral@2
   351
leo_sobral@2
   352
    }
rosfran@40
   353
    else if ( sock_type == GMYTH_FILETRANSFER_TYPE )
leo_sobral@2
   354
    {
leo_sobral@2
   355
      (*transfer)->sock = sock;
leo_sobral@2
   356
      strlist = gmyth_string_list_new();
leo_sobral@2
   357
      //g_string_printf( base_str, "ANN FileTransfer %s %d %d", hostname->str,
leo_sobral@2
   358
      //  		transfer->userreadahead, transfer->retries );
leo_sobral@2
   359
      g_string_printf( base_str, "ANN FileTransfer %s", hostname->str );
leo_sobral@2
   360
leo_sobral@2
   361
      gmyth_string_list_append_string( strlist, base_str );
leo_sobral@2
   362
      gmyth_string_list_append_char_array( strlist, path_dir );
leo_sobral@2
   363
leo_sobral@2
   364
      gmyth_socket_write_stringlist( (*transfer)->sock, strlist );
leo_sobral@2
   365
      gmyth_socket_read_stringlist( (*transfer)->sock, strlist );
leo_sobral@2
   366
leo_sobral@2
   367
      /* socket number, where all the stream data comes from - got from the MythTV remote backend */
leo_sobral@2
   368
      (*transfer)->recordernum = gmyth_string_list_get_int( strlist, 1 );
leo_sobral@2
   369
leo_sobral@2
   370
      /* Myth URI stream file size - decoded using two 8-bytes sequences (64 bits/long long types) */
rosfran@37
   371
      (*transfer)->filesize = gmyth_util_decode_long_long( strlist, 2 );
leo_sobral@2
   372
leo_sobral@2
   373
      printf( "[%s] ***** Received: recordernum = %d, filesize = %" G_GUINT64_FORMAT "\n", __FUNCTION__,
leo_sobral@2
   374
	  (*transfer)->recordernum, (*transfer)->filesize );
leo_sobral@2
   375
leo_sobral@2
   376
      if ( (*transfer)->filesize <= 0 ) {
leo_sobral@2
   377
	g_print( "[%s] Got filesize equals to %llu is lesser than 0 [invalid stream file]\n", __FUNCTION__, (*transfer)->filesize );
leo_sobral@2
   378
	g_object_unref(sock);
leo_sobral@2
   379
	sock = NULL; 
leo_sobral@2
   380
      }
leo_sobral@2
   381
    }
rosfran@40
   382
    else if ( sock_type == GMYTH_RINGBUFFER_TYPE )
leo_sobral@2
   383
    {
leo_sobral@2
   384
      (*transfer)->sock = sock;
rosfran@40
   385
      //gmyth_file_transfer_spawntv( (*transfer), NULL );      
leo_sobral@2
   386
leo_sobral@2
   387
      strlist = gmyth_string_list_new();
leo_sobral@2
   388
      g_string_printf( base_str, "ANN RingBuffer %s %d", hostname->str, (*transfer)->card_id );
leo_sobral@2
   389
leo_sobral@2
   390
      gmyth_socket_send_command( (*transfer)->sock, base_str );
leo_sobral@2
   391
      GString *resp = gmyth_socket_receive_response( (*transfer)->sock );
leo_sobral@2
   392
      g_print( "[%s] Got RingBuffer response from %s: %s\n", __FUNCTION__, base_str->str, resp->str );
leo_sobral@2
   393
leo_sobral@2
   394
    }
leo_sobral@2
   395
leo_sobral@2
   396
  }
leo_sobral@2
   397
rosfran@40
   398
  printf("[%s] ANN %s sent: %s\n", (sock_type==GMYTH_PLAYBACK_TYPE) ? "Playback" : (sock_type==GMYTH_FILETRANSFER_TYPE) ? "FileTransfer" : "Monitor", __FUNCTION__, base_str->str);
leo_sobral@2
   399
leo_sobral@2
   400
  if ( strlist != NULL )
leo_sobral@2
   401
    g_object_unref( strlist );
leo_sobral@2
   402
leo_sobral@2
   403
  g_static_mutex_unlock (&mutex);
leo_sobral@2
   404
leo_sobral@2
   405
  return sock;
leo_sobral@2
   406
}    
leo_sobral@2
   407
leo_sobral@2
   408
void
rosfran@40
   409
gmyth_file_transfer_spawntv ( GMythFileTransfer *file_transfer, 
leo_sobral@2
   410
    GString *tvchain_id )
leo_sobral@2
   411
{
leo_sobral@2
   412
  GMythStringList *str_list;
leo_sobral@2
   413
rosfran@40
   414
  g_debug ("gmyth_file_transfer_spawntv.\n");
leo_sobral@2
   415
leo_sobral@2
   416
  str_list = gmyth_string_list_new ();
leo_sobral@2
   417
rosfran@40
   418
  g_string_printf( file_transfer->query, "%s %d", GMYTHTV_RECORDER_HEADER, 
leo_sobral@2
   419
      file_transfer->card_id );
leo_sobral@2
   420
  gmyth_string_list_append_string (str_list, file_transfer->query);
leo_sobral@2
   421
  gmyth_string_list_append_string (str_list, g_string_new ("SPAWN_LIVETV"));
leo_sobral@2
   422
  if (tvchain_id!=NULL) {
leo_sobral@2
   423
    gmyth_string_list_append_string (str_list, tvchain_id);
leo_sobral@2
   424
    gmyth_string_list_append_int (str_list, FALSE); // PIP = FALSE (0)
leo_sobral@2
   425
  }
leo_sobral@2
   426
leo_sobral@2
   427
  gmyth_socket_sendreceive_stringlist ( file_transfer->sock, str_list );
leo_sobral@2
   428
leo_sobral@2
   429
  //GString *str = NULL;
leo_sobral@2
   430
leo_sobral@2
   431
  //if (str_list!=NULL && (str = gmyth_string_list_get_string( str_list, 0 )) != NULL && strcasecmp( str->str, "ok" ) != 0 ) {
leo_sobral@2
   432
  //  g_print( "[%s]\t\tSpawnLiveTV is OK!\n", __FUNCTION__ );
leo_sobral@2
   433
  //}
leo_sobral@2
   434
  if (str_list!=NULL)
leo_sobral@2
   435
    g_object_unref (str_list);
leo_sobral@2
   436
leo_sobral@2
   437
}
leo_sobral@2
   438
leo_sobral@2
   439
gboolean
rosfran@40
   440
gmyth_file_transfer_is_recording ( GMythFileTransfer *file_transfer )
leo_sobral@2
   441
{
leo_sobral@2
   442
  gboolean ret = TRUE;
leo_sobral@2
   443
  
leo_sobral@2
   444
  GMythStringList *str_list = gmyth_string_list_new ();
leo_sobral@2
   445
leo_sobral@2
   446
  g_debug ( "[%s]\n", __FUNCTION__ );
leo_sobral@2
   447
  g_static_mutex_lock (&mutex);
leo_sobral@2
   448
rosfran@40
   449
  g_string_printf( file_transfer->query, "%s %d", GMYTHTV_RECORDER_HEADER, 
leo_sobral@2
   450
      file_transfer->rec_id >= 0 ? file_transfer->rec_id : file_transfer->card_id );
leo_sobral@2
   451
  gmyth_string_list_append_string (str_list, file_transfer->query);
leo_sobral@2
   452
  gmyth_string_list_append_string (str_list, g_string_new ("IS_RECORDING"));
leo_sobral@2
   453
leo_sobral@2
   454
  gmyth_socket_sendreceive_stringlist ( file_transfer->control_sock, str_list );
leo_sobral@2
   455
leo_sobral@2
   456
  if ( str_list != NULL && gmyth_string_list_length(str_list) > 0 ) 
leo_sobral@2
   457
  {
leo_sobral@2
   458
    GString *str = NULL;
leo_sobral@2
   459
    if ( ( str = gmyth_string_list_get_string( str_list, 0 ) ) != NULL && strcmp( str->str, "bad" )!= 0 ) {
leo_sobral@2
   460
      gint is_rec = gmyth_string_list_get_int( str_list, 0 );
leo_sobral@2
   461
      if ( is_rec != 0 )
leo_sobral@2
   462
	ret = TRUE;
leo_sobral@2
   463
      else
leo_sobral@2
   464
	ret = FALSE;
leo_sobral@2
   465
    }
leo_sobral@2
   466
  }  
leo_sobral@2
   467
  g_print( "[%s] %s, stream is %s being recorded!\n", __FUNCTION__, ret ? "YES" : "NO", ret ? "" : "NOT" );
leo_sobral@2
   468
  g_static_mutex_unlock (&mutex);
leo_sobral@2
   469
leo_sobral@2
   470
  if ( str_list != NULL )
leo_sobral@2
   471
    g_object_unref (str_list);
leo_sobral@2
   472
leo_sobral@2
   473
  return ret;
leo_sobral@2
   474
leo_sobral@2
   475
}
leo_sobral@2
   476
rosfran@40
   477
gint64
rosfran@40
   478
gmyth_file_transfer_get_file_position ( GMythFileTransfer *file_transfer )
leo_sobral@2
   479
{
rosfran@37
   480
  gint64 pos = 0;
leo_sobral@2
   481
leo_sobral@2
   482
  GMythStringList *str_list = gmyth_string_list_new ();
leo_sobral@2
   483
leo_sobral@2
   484
  g_debug ( "[%s]\n", __FUNCTION__ );
leo_sobral@2
   485
  g_static_mutex_lock (&mutex);
leo_sobral@2
   486
rosfran@40
   487
  g_string_printf( file_transfer->query, "%s %d", GMYTHTV_RECORDER_HEADER, 
leo_sobral@2
   488
      file_transfer->rec_id >= 0 ? file_transfer->rec_id : file_transfer->card_id );
leo_sobral@2
   489
leo_sobral@2
   490
  gmyth_string_list_append_string (str_list, file_transfer->query);
leo_sobral@2
   491
  gmyth_string_list_append_string (str_list, g_string_new ("GET_FILE_POSITION"));
leo_sobral@2
   492
leo_sobral@2
   493
  gmyth_socket_sendreceive_stringlist ( file_transfer->control_sock, str_list );
leo_sobral@2
   494
leo_sobral@2
   495
  if ( str_list != NULL && gmyth_string_list_length(str_list) > 0 ) 
leo_sobral@2
   496
  {
leo_sobral@2
   497
    GString *str = NULL;
rosfran@40
   498
    if ( ( str = gmyth_string_list_get_string( str_list, 0 ) ) != NULL && strstr ( str->str, "bad" ) == NULL )
leo_sobral@2
   499
      pos = gmyth_util_decode_long_long( str_list, 0 );
leo_sobral@2
   500
  } 
leo_sobral@2
   501
  g_static_mutex_unlock (&mutex);
leo_sobral@2
   502
rosfran@40
   503
#ifndef GMYTHTV_ENABLE_DEBUG
leo_sobral@2
   504
rosfran@40
   505
  g_print( "[%s] Got file position = %lld\n", __FUNCTION__, pos );
leo_sobral@2
   506
#endif
leo_sobral@2
   507
  if (str_list!=NULL)
leo_sobral@2
   508
    g_object_unref (str_list);
leo_sobral@2
   509
leo_sobral@2
   510
  return pos;
leo_sobral@2
   511
leo_sobral@2
   512
}
leo_sobral@2
   513
leo_sobral@2
   514
  glong
rosfran@40
   515
gmyth_file_transfer_get_recordernum( GMythFileTransfer *transfer )
leo_sobral@2
   516
{
leo_sobral@2
   517
  return transfer->recordernum;
leo_sobral@2
   518
}
leo_sobral@2
   519
leo_sobral@2
   520
  glong
rosfran@40
   521
gmyth_file_transfer_get_filesize( GMythFileTransfer *transfer )
leo_sobral@2
   522
{
leo_sobral@2
   523
  return transfer->filesize;
leo_sobral@2
   524
}
leo_sobral@2
   525
leo_sobral@2
   526
  gboolean
rosfran@40
   527
gmyth_file_transfer_isopen( GMythFileTransfer *transfer )
leo_sobral@2
   528
{
leo_sobral@2
   529
  return (transfer->sock != NULL && transfer->control_sock != NULL);
leo_sobral@2
   530
}
leo_sobral@2
   531
leo_sobral@2
   532
  void
rosfran@40
   533
gmyth_file_transfer_close( GMythFileTransfer *transfer )
leo_sobral@2
   534
{
leo_sobral@2
   535
  GMythStringList *strlist;
leo_sobral@2
   536
leo_sobral@2
   537
  if (transfer->control_sock == NULL)
leo_sobral@2
   538
    return;
leo_sobral@2
   539
leo_sobral@2
   540
  strlist = gmyth_string_list_new( );
leo_sobral@2
   541
rosfran@40
   542
  g_string_printf( transfer->query, "%s %d", GMYTHTV_QUERY_HEADER, 
leo_sobral@2
   543
      transfer->recordernum );
leo_sobral@2
   544
  gmyth_string_list_append_string( strlist, transfer->query );
leo_sobral@2
   545
  gmyth_string_list_append_char_array( strlist, "DONE" );
leo_sobral@2
   546
leo_sobral@2
   547
leo_sobral@2
   548
  if ( gmyth_socket_sendreceive_stringlist(transfer->control_sock, strlist) <= 0 )
leo_sobral@2
   549
  {
leo_sobral@2
   550
    g_printerr( "Remote file timeout.\n" );
leo_sobral@2
   551
  }
leo_sobral@2
   552
leo_sobral@2
   553
  if (transfer->sock)
leo_sobral@2
   554
  {
leo_sobral@2
   555
    g_object_unref( transfer->sock );
leo_sobral@2
   556
    transfer->sock = NULL;
leo_sobral@2
   557
  }
leo_sobral@2
   558
leo_sobral@2
   559
  if (transfer->control_sock)
leo_sobral@2
   560
  {
leo_sobral@2
   561
    g_object_unref( transfer->control_sock );
leo_sobral@2
   562
    transfer->control_sock = NULL;
leo_sobral@2
   563
  } 
leo_sobral@2
   564
leo_sobral@2
   565
}
leo_sobral@2
   566
leo_sobral@2
   567
  void
rosfran@40
   568
gmyth_file_transfer_reset_controlsock( GMythFileTransfer *transfer )
leo_sobral@2
   569
{
leo_sobral@2
   570
  if (transfer->control_sock == NULL)
leo_sobral@2
   571
  {
rosfran@40
   572
    g_printerr( "gmyth_file_transfer_reset_controlsock(): Called with no control socket" );
leo_sobral@2
   573
    return;
leo_sobral@2
   574
  }
leo_sobral@2
   575
leo_sobral@2
   576
  GString *str = gmyth_socket_receive_response( transfer->control_sock );
leo_sobral@2
   577
leo_sobral@2
   578
  g_string_free( str, TRUE );
leo_sobral@2
   579
}
leo_sobral@2
   580
leo_sobral@2
   581
void
rosfran@40
   582
gmyth_file_transfer_reset_sock( GMythFileTransfer *transfer )
leo_sobral@2
   583
{
leo_sobral@2
   584
  if ( transfer->sock == NULL )
leo_sobral@2
   585
  {
rosfran@40
   586
    g_printerr( "gmyth_file_transfer_reset_sock(): Called with no raw socket" );
leo_sobral@2
   587
    return;
leo_sobral@2
   588
  }
leo_sobral@2
   589
leo_sobral@2
   590
  GString *str = gmyth_socket_receive_response( transfer->sock );
leo_sobral@2
   591
leo_sobral@2
   592
  g_string_free( str, TRUE );
leo_sobral@2
   593
}
leo_sobral@2
   594
leo_sobral@2
   595
void
rosfran@40
   596
gmyth_file_transfer_reset( GMythFileTransfer *transfer )
leo_sobral@2
   597
{
rosfran@40
   598
  gmyth_file_transfer_reset_controlsock( transfer );
rosfran@40
   599
  gmyth_file_transfer_reset_sock( transfer );
leo_sobral@2
   600
}
leo_sobral@2
   601
rosfran@40
   602
gint64
rosfran@40
   603
gmyth_file_transfer_seek(GMythFileTransfer *transfer, guint64 pos, gint whence)
leo_sobral@2
   604
{
leo_sobral@2
   605
  if (transfer->sock == NULL)
leo_sobral@2
   606
  {
rosfran@40
   607
    g_printerr( "[%s] gmyth_file_transfer_seek(): Called with no socket", __FUNCTION__ );
leo_sobral@2
   608
    return 0;
leo_sobral@2
   609
  }
leo_sobral@2
   610
leo_sobral@2
   611
  if (transfer->control_sock == NULL)
leo_sobral@2
   612
    return 0;
leo_sobral@2
   613
leo_sobral@2
   614
  // if (!controlSock->isOpen() || controlSock->error())
leo_sobral@2
   615
  //   return 0;
leo_sobral@2
   616
leo_sobral@2
   617
  GMythStringList *strlist = gmyth_string_list_new();
rosfran@40
   618
  g_string_printf (transfer->query, "%s %d", GMYTHTV_QUERY_HEADER, transfer->recordernum);
rosfran@30
   619
  gmyth_string_list_append_string( strlist, transfer->query );
leo_sobral@2
   620
  gmyth_string_list_append_char_array( strlist, "SEEK" );
leo_sobral@2
   621
  gmyth_string_list_append_uint64( strlist, pos );
rosfran@30
   622
  
rosfran@30
   623
  gmyth_string_list_append_int( strlist, whence );  
leo_sobral@2
   624
leo_sobral@2
   625
  if (pos > 0 )
leo_sobral@2
   626
    gmyth_string_list_append_uint64( strlist, pos );
leo_sobral@2
   627
  else
leo_sobral@2
   628
    gmyth_string_list_append_uint64( strlist, transfer->readposition );
rosfran@30
   629
  
leo_sobral@2
   630
  gmyth_socket_sendreceive_stringlist( transfer->control_sock, strlist );
leo_sobral@2
   631
rosfran@40
   632
  gint64 retval = gmyth_string_list_get_int64(strlist, 0);
leo_sobral@2
   633
  transfer->readposition = retval;
rosfran@40
   634
  g_print( "[%s] got reading position pointer from the streaming = %lld\n", 
leo_sobral@2
   635
      __FUNCTION__, retval );
leo_sobral@2
   636
rosfran@40
   637
  //gmyth_file_transfer_reset( transfer );
leo_sobral@2
   638
leo_sobral@2
   639
  return retval;
leo_sobral@2
   640
}
leo_sobral@2
   641
leo_sobral@2
   642
static gboolean
leo_sobral@2
   643
myth_control_sock_listener( GIOChannel *source, GIOCondition condition, gpointer data )
leo_sobral@2
   644
{
leo_sobral@2
   645
leo_sobral@2
   646
  GIOStatus ret;
leo_sobral@2
   647
  GError *err = NULL;
leo_sobral@2
   648
  gchar *msg = g_strdup("");
rosfran@37
   649
  
rosfran@37
   650
  g_static_mutex_lock( &mutex );  
leo_sobral@2
   651
leo_sobral@2
   652
  gsize len;
leo_sobral@2
   653
  if (condition & G_IO_HUP)
leo_sobral@2
   654
    g_error ("Read end of pipe died!\n");
leo_sobral@2
   655
  ret = g_io_channel_read_line ( source, &msg, &len, NULL, &err);
leo_sobral@2
   656
  if ( ret == G_IO_STATUS_ERROR )
leo_sobral@2
   657
    g_error ("[%s] Error reading: %s\n", __FUNCTION__, err != NULL ? err->message : "" );
leo_sobral@2
   658
  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 : "" );
leo_sobral@2
   659
  if ( msg != NULL )
leo_sobral@2
   660
    g_free (msg);
rosfran@37
   661
    
rosfran@37
   662
  g_static_mutex_unlock( &mutex );
leo_sobral@2
   663
leo_sobral@2
   664
  return TRUE;
leo_sobral@2
   665
leo_sobral@2
   666
}
leo_sobral@2
   667
leo_sobral@2
   668
static void*
leo_sobral@2
   669
myth_init_io_watchers( void *data )
leo_sobral@2
   670
{
rosfran@40
   671
  GMythFileTransfer *transfer = (GMythFileTransfer*)data;
rosfran@37
   672
  io_watcher_context = g_main_context_new();
leo_sobral@2
   673
  GMainLoop *loop = g_main_loop_new( NULL, FALSE );
leo_sobral@2
   674
leo_sobral@2
   675
  GSource *source = NULL;
leo_sobral@2
   676
leo_sobral@2
   677
  if ( transfer->event_sock->sd_io_ch != NULL )
leo_sobral@2
   678
    source = g_io_create_watch( transfer->event_sock->sd_io_ch, G_IO_IN | G_IO_HUP );
rosfran@37
   679
  else
rosfran@37
   680
  	goto cleanup;
leo_sobral@2
   681
leo_sobral@2
   682
  g_source_set_callback ( source, (GSourceFunc)myth_control_sock_listener, NULL, NULL );
leo_sobral@2
   683
rosfran@37
   684
  g_source_attach( source, io_watcher_context );
leo_sobral@2
   685
rosfran@37
   686
  if (source==NULL) {
leo_sobral@2
   687
    g_printerr( "[%s] Error adding watch listener function to the IO control channel!\n", __FUNCTION__ );
rosfran@37
   688
    goto cleanup;
rosfran@37
   689
  }
rosfran@37
   690
  
rosfran@37
   691
  g_print( "[%s]\tOK! Starting listener on the MONITOR event socket...\n", __FUNCTION__ );
leo_sobral@2
   692
leo_sobral@2
   693
  g_main_loop_run( loop );
leo_sobral@2
   694
rosfran@37
   695
cleanup:
rosfran@37
   696
  if ( source != NULL )
rosfran@37
   697
    g_source_unref( source );
leo_sobral@2
   698
leo_sobral@2
   699
  g_main_loop_unref( loop );
leo_sobral@2
   700
rosfran@37
   701
  g_main_context_unref( io_watcher_context );
leo_sobral@2
   702
leo_sobral@2
   703
  return NULL;
leo_sobral@2
   704
}
leo_sobral@2
   705
rosfran@37
   706
rosfran@34
   707
gint 
rosfran@40
   708
gmyth_file_transfer_read(GMythFileTransfer *transfer, void *data, gint size, gboolean read_unlimited)
leo_sobral@2
   709
{
leo_sobral@2
   710
  gint recv = 0;
leo_sobral@2
   711
  gsize bytes_read = 0;
leo_sobral@2
   712
  gint sent = 0;
rosfran@34
   713
  guint remaining = 0;  
leo_sobral@2
   714
  gboolean response = FALSE;
leo_sobral@2
   715
leo_sobral@2
   716
  GIOChannel *io_channel;
leo_sobral@2
   717
  GIOChannel *io_channel_control;
leo_sobral@2
   718
leo_sobral@2
   719
  GIOCondition io_cond;
leo_sobral@2
   720
  GIOCondition io_cond_control;
leo_sobral@2
   721
  GIOStatus io_status = G_IO_STATUS_NORMAL, io_status_control = G_IO_STATUS_NORMAL;   
leo_sobral@2
   722
rosfran@40
   723
  gint buf_len = GMYTHTV_BUFFER_SIZE;
leo_sobral@2
   724
leo_sobral@2
   725
  GMythStringList *strlist = NULL;
leo_sobral@2
   726
  GError *error = NULL;
leo_sobral@2
   727
leo_sobral@2
   728
  gchar *trash = g_strdup("");
leo_sobral@2
   729
leo_sobral@2
   730
  g_return_val_if_fail ( data != NULL, -2 );
leo_sobral@2
   731
leo_sobral@2
   732
  /* gets the size of the entire file, if the size requested is lesser than 0 */
leo_sobral@2
   733
  if ( size <= 0 )
leo_sobral@2
   734
    size = transfer->filesize;
leo_sobral@2
   735
leo_sobral@2
   736
  io_channel = transfer->sock->sd_io_ch;
leo_sobral@2
   737
  io_channel_control = transfer->control_sock->sd_io_ch;
leo_sobral@2
   738
leo_sobral@2
   739
  //g_io_channel_set_flags( io_channel, G_IO_FLAG_APPEND | 
leo_sobral@2
   740
  //    G_IO_STATUS_AGAIN | G_IO_FLAG_IS_READABLE | G_IO_FLAG_IS_WRITEABLE | 
leo_sobral@2
   741
  //    G_IO_FLAG_IS_SEEKABLE, NULL );
leo_sobral@2
   742
leo_sobral@2
   743
  io_status = g_io_channel_set_encoding( io_channel, NULL, &error );
leo_sobral@2
   744
  if ( io_status == G_IO_STATUS_NORMAL )
leo_sobral@2
   745
    g_print( "[%s] Setting encoding to binary data socket).\n", __FUNCTION__ );
leo_sobral@2
   746
leo_sobral@2
   747
  io_cond = g_io_channel_get_buffer_condition( io_channel );  
leo_sobral@2
   748
leo_sobral@2
   749
  io_cond_control = g_io_channel_get_buffer_condition( io_channel );
leo_sobral@2
   750
leo_sobral@2
   751
  if ( transfer->sock == NULL || ( io_status == G_IO_STATUS_ERROR ) )
leo_sobral@2
   752
  {
rosfran@40
   753
    g_printerr( "gmyth_file_transfer_read(): Called with no raw socket.\n" );
leo_sobral@2
   754
    recv = -1;
leo_sobral@2
   755
    goto cleanup;
leo_sobral@2
   756
  }
leo_sobral@2
   757
leo_sobral@2
   758
  if ( transfer->control_sock == NULL || ( io_status_control == G_IO_STATUS_ERROR ) )
leo_sobral@2
   759
  {
rosfran@40
   760
    g_printerr( "gmyth_file_transfer_read(): Called with no control socket.\n" );
leo_sobral@2
   761
    recv = -1;
leo_sobral@2
   762
    goto cleanup;
leo_sobral@2
   763
  }
leo_sobral@2
   764
leo_sobral@2
   765
  /*
leo_sobral@2
   766
     if (!controlSock->isOpen() || controlSock->error())
leo_sobral@2
   767
     return -1;
leo_sobral@2
   768
     */
leo_sobral@2
   769
leo_sobral@2
   770
  if ( ( io_cond & G_IO_IN ) != 0 ) {
leo_sobral@2
   771
    do 
leo_sobral@2
   772
    {
rosfran@40
   773
      trash = g_new0( gchar, GMYTHTV_BUFFER_SIZE );
leo_sobral@2
   774
rosfran@34
   775
      io_status = g_io_channel_read_chars( io_channel, trash, 
rosfran@40
   776
      		GMYTHTV_BUFFER_SIZE, &bytes_read, &error);
leo_sobral@2
   777
rosfran@34
   778
      g_print( "[%s] cleaning buffer on IO binary channel... %d bytes gone!\n", 
rosfran@34
   779
      		__FUNCTION__, bytes_read );
rosfran@34
   780
      
rosfran@34
   781
      if ( trash != NULL )
rosfran@34
   782
      	g_free( trash );
rosfran@34
   783
      	
leo_sobral@2
   784
      io_cond = g_io_channel_get_buffer_condition( io_channel );
leo_sobral@2
   785
rosfran@34
   786
    } while ( ( io_cond & G_IO_IN ) != 0 && ( io_status != G_IO_STATUS_ERROR ) && (error == NULL) );
leo_sobral@2
   787
rosfran@34
   788
    //if ( trash!= NULL )
rosfran@34
   789
    //  g_free( trash );
leo_sobral@2
   790
  }
leo_sobral@2
   791
leo_sobral@2
   792
  if ( ( io_cond_control & G_IO_IN ) != 0 ) {
leo_sobral@2
   793
    GMythStringList *strlist_tmp = gmyth_string_list_new();
leo_sobral@2
   794
    gmyth_socket_read_stringlist( transfer->control_sock, strlist_tmp );
leo_sobral@2
   795
    g_object_unref( strlist_tmp );
leo_sobral@2
   796
  }
leo_sobral@2
   797
leo_sobral@2
   798
  wait_to_transfer = 0;
leo_sobral@2
   799
rosfran@40
   800
  //while ( transfer->live_tv && ( gmyth_file_transfer_get_file_position( transfer ) < 4096 ) &&
rosfran@40
   801
  //		wait_to_transfer++ < GMYTHTV_TRANSFER_MAX_WAITS )
rosfran@30
   802
  //	g_usleep( 1000*50 ); /* waits just for 2/10 second */
leo_sobral@2
   803
leo_sobral@2
   804
  //g_thread_create( myth_init_io_watchers, (void*)transfer, FALSE, NULL );
leo_sobral@2
   805
  //g_printerr( "[%s] Watch listener function to the IO control channel on thread %p.\n", __FUNCTION__, g_thread_self() );
leo_sobral@2
   806
rosfran@30
   807
  //g_static_mutex_lock (&mutex);
rosfran@30
   808
  //strlist = gmyth_string_list_new();
leo_sobral@2
   809
rosfran@31
   810
  g_string_printf ( transfer->query, "%s %d",
rosfran@40
   811
  	  /*transfer->live_tv ? GMYTHTV_RECORDER_HEADER :*/  GMYTHTV_QUERY_HEADER, 
leo_sobral@2
   812
      /* transfer->live_tv ? transfer->card_id :*/ transfer->recordernum ); // transfer->recordernum
leo_sobral@2
   813
  g_print( "\t[%s] Transfer_query = %s\n", __FUNCTION__, transfer->query->str );
rosfran@30
   814
  
leo_sobral@2
   815
  sent = size;
rosfran@34
   816
  remaining = size - recv;  
rosfran@30
   817
  //g_static_mutex_unlock( &mutex );
leo_sobral@2
   818
  //data = (void*)g_new0( gchar, size );
leo_sobral@2
   819
rosfran@30
   820
  //g_io_channel_flush( io_channel, NULL );
rosfran@30
   821
rosfran@34
   822
  //g_static_mutex_lock( &mutex );
leo_sobral@2
   823
leo_sobral@2
   824
  io_cond = g_io_channel_get_buffer_condition( io_channel );
leo_sobral@2
   825
rosfran@34
   826
  while ( recv < size  && !response )//&& ( io_cond & G_IO_IN ) != 0 )
leo_sobral@2
   827
  {
rosfran@34
   828
  	g_io_channel_flush( io_channel_control, NULL );
rosfran@34
   829
  	
rosfran@34
   830
    strlist = gmyth_string_list_new();
rosfran@34
   831
    gmyth_string_list_append_char_array( strlist, transfer->query->str );
rosfran@34
   832
    gmyth_string_list_append_char_array( strlist, 
rosfran@34
   833
    		/*transfer->live_tv ? "REQUEST_BLOCK_RINGBUF" :*/ "REQUEST_BLOCK" );
rosfran@34
   834
    gmyth_string_list_append_int( strlist, remaining );
rosfran@34
   835
	gmyth_socket_write_stringlist( transfer->control_sock, strlist );
rosfran@34
   836
	
rosfran@34
   837
	guint count_bytes = 0;
rosfran@34
   838
      
leo_sobral@2
   839
    do
leo_sobral@2
   840
    {
rosfran@40
   841
      //buf_len = ( sent - recv ) > GMYTHTV_BUFFER_SIZE ? GMYTHTV_BUFFER_SIZE : ( sent - recv );
rosfran@40
   842
      if ( remaining > GMYTHTV_BUFFER_SIZE ) {
rosfran@40
   843
      	buf_len = GMYTHTV_BUFFER_SIZE;
rosfran@34
   844
      } else {
rosfran@34
   845
      	buf_len = remaining;
rosfran@34
   846
      }
rosfran@34
   847
	  
rosfran@34
   848
      bytes_read = 0;
leo_sobral@2
   849
leo_sobral@2
   850
      io_status = g_io_channel_read_chars( io_channel, data + recv, 
rosfran@30
   851
	  		buf_len, &bytes_read, &error );
rosfran@31
   852
	  
rosfran@31
   853
	  //g_static_mutex_unlock( &mutex );
leo_sobral@2
   854
      /*
leo_sobral@2
   855
	 GString *sss = g_string_new("");
leo_sobral@2
   856
	 sss = g_string_append_len( sss, (gchar*)data+recv, bytes_read );
leo_sobral@2
   857
leo_sobral@2
   858
	 g_print( "[%s] Reading buffer (length = %d)\n", __FUNCTION__, bytes_read);
leo_sobral@2
   859
	 */
leo_sobral@2
   860
      if ( bytes_read > 0 )
leo_sobral@2
   861
      {
rosfran@34
   862
	//if ( bytes_read <= buf_len )
rosfran@34
   863
		  recv += bytes_read;
rosfran@34
   864
		  count_bytes += bytes_read;
rosfran@34
   865
		  remaining -= bytes_read;
rosfran@34
   866
		  g_print( "[%s] Reading buffer (bytes read = %d, remaining = %d)\n", __FUNCTION__, bytes_read, remaining );
rosfran@34
   867
		  if ( remaining == 0 ) {
rosfran@34
   868
		  	break;
rosfran@34
   869
		  }
rosfran@34
   870
      } else {
rosfran@34
   871
      	break;
rosfran@34
   872
      }
rosfran@34
   873
      
rosfran@34
   874
      //if ( remaining > 0 ) {
leo_sobral@2
   875
leo_sobral@2
   876
      if ( io_status == G_IO_STATUS_EOF ) {
rosfran@34
   877
	g_print( "[%s] got EOS!", __FUNCTION__ );
leo_sobral@2
   878
	break;
leo_sobral@2
   879
      } else if ( io_status == G_IO_STATUS_ERROR ) {
rosfran@40
   880
	g_print( "[%s] gmyth_file_transfer_read(): socket error.\n", __FUNCTION__ );
leo_sobral@2
   881
	break;
leo_sobral@2
   882
      }
rosfran@34
   883
      //}
leo_sobral@2
   884
leo_sobral@2
   885
      /* increase buffer size, to allow get more data (do not obey to the buffer size) */
leo_sobral@2
   886
      if ( read_unlimited == TRUE ) {
rosfran@34
   887
      	// FOR NOW, DO NOTHING!!!
leo_sobral@2
   888
	//if ( recv > buf_len )
leo_sobral@2
   889
	// sent += (bytes_read - buf_len) + 1;
leo_sobral@2
   890
      }
leo_sobral@2
   891
leo_sobral@2
   892
      /* verify if the input (read) buffer is ready to receive data */
leo_sobral@2
   893
      io_cond = g_io_channel_get_buffer_condition( io_channel );
leo_sobral@2
   894
leo_sobral@2
   895
      g_print( "[%s]\t io_cond %s prepared for reading! (G_IO_IN) !!!\n\n", __FUNCTION__, 
leo_sobral@2
   896
      		( ( io_cond & G_IO_IN ) != 0 ) ? "IS" : "IS NOT" );
rosfran@34
   897
      		
rosfran@34
   898
      //if ( recv == size )
rosfran@34
   899
		//break;
leo_sobral@2
   900
rosfran@34
   901
    } while ( remaining > 0 );//&& ( io_status == G_IO_STATUS_NORMAL ) );
rosfran@34
   902
    
rosfran@34
   903
   // if ( ( recv < size ) ) {
rosfran@34
   904
    //	finish_read = FALSE;
rosfran@34
   905
    //}
leo_sobral@2
   906
leo_sobral@2
   907
    io_cond_control = g_io_channel_get_buffer_condition( io_channel_control );
rosfran@34
   908
    if ( remaining == 0 )//( io_cond_control & G_IO_IN ) != 0  )
leo_sobral@2
   909
    {
leo_sobral@2
   910
      gmyth_socket_read_stringlist( transfer->control_sock, strlist );
rosfran@34
   911
      if ( strlist != NULL && gmyth_string_list_length( strlist ) > 0 ) 
rosfran@34
   912
      {
rosfran@34
   913
      	sent = gmyth_string_list_get_int( strlist,  0 ); // -1 on backend error
rosfran@34
   914
      	g_print( "[%s] got SENT buffer message = %d\n", __FUNCTION__, sent );
rosfran@34
   915
      	if ( sent != 0 )
rosfran@34
   916
      	{
rosfran@34
   917
      		g_print( "[%s]\t received = %d bytes, backend says %d bytes sent, "\
rosfran@34
   918
      			"io_cond %s prepared for reading! (G_IO_IN) !!!\n\n", __FUNCTION__, 
rosfran@34
   919
	  			recv, sent, ( ( io_cond & G_IO_IN ) != 0 ) ? "IS" : "IS NOT" );
leo_sobral@2
   920
rosfran@34
   921
	  		if ( sent == count_bytes )
rosfran@34
   922
	  		{
rosfran@34
   923
	  			response = ( recv == size ); 
rosfran@34
   924
	  			g_print( "[%s]\t\tsent %d, which is equals to bytes_read = %d\n\n", 
rosfran@34
   925
	  						__FUNCTION__, sent, count_bytes );
rosfran@34
   926
	  			if ( response == TRUE )
rosfran@34
   927
      				break;
rosfran@34
   928
	  		}
rosfran@34
   929
	  		else
rosfran@34
   930
	  		{
rosfran@34
   931
	  			g_print( "[%s]\t\tsent %d, which is NOT equals to bytes_read = %d\n\n", 
rosfran@34
   932
	  						__FUNCTION__, sent, count_bytes );
rosfran@34
   933
	  			goto cleanup;
rosfran@34
   934
	  			//response = FALSE;
rosfran@34
   935
	  			//break;
rosfran@34
   936
	  		}
rosfran@34
   937
      	} else {
rosfran@34
   938
      		break;
rosfran@34
   939
      		//goto cleanup;
rosfran@34
   940
      	} // if
rosfran@34
   941
      } // if - reading control response from backend
rosfran@34
   942
    } else {
rosfran@34
   943
    	response = FALSE;
rosfran@34
   944
    } // if - stringlist response
rosfran@34
   945
    
rosfran@34
   946
  } // while
rosfran@34
   947
  
rosfran@34
   948
  io_cond_control = g_io_channel_get_buffer_condition( io_channel_control );
rosfran@34
   949
 // io_cond = g_io_channel_get_buffer_condition( io_channel );
rosfran@34
   950
rosfran@34
   951
  if ( ( ( io_cond_control & G_IO_IN ) != 0 ) &&  		 
rosfran@34
   952
  		( response || ( recv == size ) ) )
leo_sobral@2
   953
  {
leo_sobral@2
   954
    if ( gmyth_socket_read_stringlist( transfer->control_sock, strlist ) > 0 )
leo_sobral@2
   955
    {
rosfran@34
   956
      if ( strlist != NULL && gmyth_string_list_length(strlist) > 0 ) 
rosfran@34
   957
      {
rosfran@34
   958
		sent = gmyth_string_list_get_int( strlist, 0 ); // -1 on backend error
rosfran@34
   959
		g_print( "[%s]\t received = %d bytes -\tNOW returning from reading buffer I/O socket "\
rosfran@34
   960
				 "[%s prepared for reading]! (G_IO_IN) !!!\n\n", __FUNCTION__, 
rosfran@34
   961
	    	sent, ( ( io_cond & G_IO_IN ) != 0 ) ? "IS" : "IS NOT" );
leo_sobral@2
   962
      }
leo_sobral@2
   963
    }
leo_sobral@2
   964
    else
leo_sobral@2
   965
    {
rosfran@40
   966
      g_printerr ( "gmyth_file_transfer_read(): No response from control socket.");
rosfran@31
   967
      recv = -1;
rosfran@31
   968
    }
rosfran@31
   969
    
rosfran@34
   970
  } 
rosfran@34
   971
  else if ( error != NULL )
rosfran@34
   972
  {
rosfran@31
   973
      g_printerr( "[%s] Error occurred: (%d, %s)\n", __FUNCTION__, error->code, error->message );
rosfran@34
   974
  }
leo_sobral@2
   975
leo_sobral@2
   976
cleanup:
rosfran@34
   977
  //g_static_mutex_unlock (&mutex);
leo_sobral@2
   978
leo_sobral@2
   979
  if ( trash != NULL )
leo_sobral@2
   980
    g_free( trash );
leo_sobral@2
   981
leo_sobral@2
   982
  if ( strlist != NULL )
leo_sobral@2
   983
    g_object_unref( strlist );
leo_sobral@2
   984
rosfran@40
   985
  g_print( "gmyth_file_transfer_read(): reqd=%d, rcvd=%d, rept=%d, "\
leo_sobral@2
   986
      "(rcvd and rept MUST be the same!)\n", size, 
leo_sobral@2
   987
      recv, sent );
leo_sobral@2
   988
rosfran@34
   989
  //if ( ( recv != size ) || ( sent != size ) ) {
rosfran@34
   990
    //recv = size;
leo_sobral@2
   991
  //}
leo_sobral@2
   992
rosfran@30
   993
  if ( error != NULL ) {
rosfran@31
   994
    g_printerr( "Cleaning-up ERROR: %s [msg = %s, code = %d]\n", __FUNCTION__, error->message, 
leo_sobral@2
   995
	error->code );
rosfran@30
   996
	g_error_free( error );
rosfran@30
   997
  }
leo_sobral@2
   998
leo_sobral@2
   999
  return recv;
leo_sobral@2
  1000
}
leo_sobral@2
  1001
rosfran@31
  1002
void 
rosfran@40
  1003
gmyth_file_transfer_settimeout( GMythFileTransfer *transfer, gboolean fast )
leo_sobral@2
  1004
{
leo_sobral@2
  1005
leo_sobral@2
  1006
  GMythStringList *strlist = NULL;
leo_sobral@2
  1007
leo_sobral@2
  1008
  if ( transfer->timeoutisfast == fast )
leo_sobral@2
  1009
    return;
leo_sobral@2
  1010
leo_sobral@2
  1011
  if ( transfer->sock == NULL )
leo_sobral@2
  1012
  {
rosfran@40
  1013
    g_printerr( "gmyth_file_transfer_settimeout(): Called with no socket" );
leo_sobral@2
  1014
    return;
leo_sobral@2
  1015
  }
leo_sobral@2
  1016
leo_sobral@2
  1017
  if ( transfer->control_sock == NULL )
leo_sobral@2
  1018
    return;
leo_sobral@2
  1019
leo_sobral@2
  1020
  strlist = gmyth_string_list_new(); 
leo_sobral@2
  1021
  gmyth_string_list_append_string( strlist, transfer->query );
leo_sobral@2
  1022
  gmyth_string_list_append_char_array( strlist, "SET_TIMEOUT" );
leo_sobral@2
  1023
  gmyth_string_list_append_int( strlist, fast ); 
leo_sobral@2
  1024
leo_sobral@2
  1025
  gmyth_socket_write_stringlist( transfer->control_sock, strlist );
leo_sobral@2
  1026
  gmyth_socket_read_stringlist( transfer->control_sock, strlist );
leo_sobral@2
  1027
leo_sobral@2
  1028
  transfer->timeoutisfast = fast;
leo_sobral@2
  1029
leo_sobral@2
  1030
}
leo_sobral@2
  1031
leo_sobral@2
  1032
#ifdef DO_TESTING
leo_sobral@2
  1033
leo_sobral@2
  1034
  int
leo_sobral@2
  1035
main( int argc, char *argv[] )
leo_sobral@2
  1036
{
leo_sobral@2
  1037
  g_type_init();
leo_sobral@2
  1038
rosfran@40
  1039
  GMythFileTransfer *file_transfer = gmyth_file_transfer_new( 1, 
rosfran@40
  1040
      g_string_new("myth://192.168.1.109:6543/jshks.nuv"), -1, GMYTHTV_VERSION );
rosfran@40
  1041
  gmyth_file_transfer_setup( &file_transfer );
leo_sobral@2
  1042
  gchar *data = g_strdup("");
leo_sobral@2
  1043
rosfran@40
  1044
  gint num = gmyth_file_transfer_read( file_transfer, data, -1 );
leo_sobral@2
  1045
leo_sobral@2
  1046
  return 0;
leo_sobral@2
  1047
leo_sobral@2
  1048
}
leo_sobral@2
  1049
leo_sobral@2
  1050
#endif