gmyth/src/gmyth_file_transfer.c
author leo_sobral
Fri Mar 23 15:26:38 2007 +0000 (2007-03-23)
branchtrunk
changeset 444 d6603c86582f
parent 439 ee220ab67ffd
child 446 d260ed30f4de
permissions -rwxr-xr-x
[svn r449] warnings removed
rosfran@41
     1
/**
rosfran@68
     2
 * GMyth Library
rosfran@68
     3
 *
rosfran@68
     4
 * @file gmyth/gmyth_file_transfer.c
rosfran@68
     5
 * 
rosfran@68
     6
 * @brief <p> GMythFileTransfer deals with the file streaming media remote/local
rosfran@68
     7
 * transfering to the MythTV frontend.
rosfran@68
     8
 *
rosfran@68
     9
 * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
rosfran@68
    10
 * @author Rosfran Lins Borges <rosfran.borges@indt.org.br>
rosfran@68
    11
 *
rosfran@68
    12
 *//*
rosfran@68
    13
 * 
rosfran@68
    14
 * This program is free software; you can redistribute it and/or modify
rosfran@68
    15
 * it under the terms of the GNU Lesser General Public License as published by
rosfran@68
    16
 * the Free Software Foundation; either version 2 of the License, or
rosfran@68
    17
 * (at your option) any later version.
rosfran@68
    18
 *
rosfran@68
    19
 * This program is distributed in the hope that it will be useful,
rosfran@68
    20
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
rosfran@68
    21
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
rosfran@68
    22
 * GNU General Public License for more details.
rosfran@68
    23
 *
rosfran@68
    24
 * You should have received a copy of the GNU Lesser General Public License
rosfran@68
    25
 * along with this program; if not, write to the Free Software
rosfran@68
    26
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
rosfran@68
    27
 *
rosfran@68
    28
 * GStreamer MythTV plug-in properties:
rosfran@41
    29
 * - location (backend server hostname/URL) [ex.: myth://192.168.1.73:28722/1000_1092091.nuv]
rosfran@41
    30
 * - path (qurl - remote file to be opened)
rosfran@68
    31
 * - port number *   
rosfran@41
    32
 */
leo_sobral@213
    33
 
leo_sobral@213
    34
#ifdef HAVE_CONFIG_H
leo_sobral@213
    35
#include "config.h"
leo_sobral@213
    36
#endif
rosfran@41
    37
rosfran@42
    38
#include "gmyth_file_transfer.h"
rosfran@435
    39
#include "gmyth_recorder.h"
rosfran@216
    40
#include "gmyth_util.h"
rosfran@216
    41
#include "gmyth_socket.h"
rosfran@216
    42
#include "gmyth_stringlist.h"
rosfran@216
    43
#include "gmyth_debug.h"
rosfran@216
    44
#include "gmyth_uri.h"
rosfran@216
    45
#include "gmyth_marshal.h"
rosfran@216
    46
rosfran@41
    47
#include <unistd.h>
rosfran@41
    48
#include <glib.h>
rosfran@41
    49
rosfran@41
    50
#include <arpa/inet.h>
rosfran@41
    51
#include <sys/types.h>
rosfran@41
    52
#include <sys/socket.h>
rosfran@41
    53
#include <netdb.h>
rosfran@41
    54
#include <errno.h>
rosfran@41
    55
#include <stdlib.h>
melunko@117
    56
#include <assert.h>
rosfran@41
    57
melunko@112
    58
#define GMYTHTV_QUERY_HEADER		"QUERY_FILETRANSFER "
rosfran@41
    59
rosfran@41
    60
/* default values to the file transfer parameters */
rosfran@97
    61
#define GMYTHTV_USER_READ_AHEAD			TRUE
rosfran@97
    62
#define GMYTHTV_RETRIES							-1
rosfran@54
    63
#define GMYTHTV_FILE_SIZE						0
rosfran@41
    64
melunko@313
    65
#define GMYTHTV_BUFFER_SIZE					64*1024
rosfran@41
    66
rosfran@54
    67
#define GMYTHTV_VERSION							30
rosfran@41
    68
rosfran@41
    69
#define GMYTHTV_TRANSFER_MAX_WAITS	700
rosfran@41
    70
rosfran@41
    71
#ifdef GMYTHTV_ENABLE_DEBUG
rosfran@54
    72
#define GMYTHTV_ENABLE_DEBUG				1
rosfran@41
    73
#else
rosfran@41
    74
#undef GMYTHTV_ENABLE_DEBUG
rosfran@41
    75
#endif
rosfran@41
    76
rosfran@41
    77
/* this NDEBUG is to maintain compatibility with GMyth library */
rosfran@41
    78
#ifndef NDEBUG
rosfran@54
    79
#define GMYTHTV_ENABLE_DEBUG				1
rosfran@41
    80
#endif
rosfran@41
    81
rosfran@41
    82
enum myth_sock_types {
rosfran@41
    83
  GMYTH_PLAYBACK_TYPE = 0,
rosfran@41
    84
  GMYTH_MONITOR_TYPE,
rosfran@41
    85
  GMYTH_FILETRANSFER_TYPE,
rosfran@41
    86
  GMYTH_RINGBUFFER_TYPE
rosfran@41
    87
};
rosfran@41
    88
rosfran@216
    89
#define GMYTH_FILE_TRANSFER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GMYTH_FILE_TRANSFER_TYPE, GMythFileTransferPrivate))
rosfran@216
    90
rosfran@216
    91
struct _GMythFileTransferPrivate {
rosfran@435
    92
	GMythRecorder *recorder;
rosfran@216
    93
	
rosfran@216
    94
	gboolean do_next_program_chain;
leo_sobral@439
    95
	gboolean disposed;
rosfran@216
    96
};
rosfran@115
    97
rosfran@41
    98
static void gmyth_file_transfer_class_init          (GMythFileTransferClass *klass);
rosfran@41
    99
static void gmyth_file_transfer_init                (GMythFileTransfer *object);
rosfran@41
   100
rosfran@41
   101
static void gmyth_file_transfer_dispose  (GObject *object);
rosfran@41
   102
static void gmyth_file_transfer_finalize (GObject *object);
rosfran@41
   103
rosfran@216
   104
static void gmyth_file_transfer_program_info_changed( GMythFileTransfer *transfer, 
rosfran@435
   105
										gint msg_code, gpointer livetv_recorder );
rosfran@216
   106
melunko@112
   107
static gboolean gmyth_connect_to_backend (GMythFileTransfer *transfer);
rosfran@41
   108
rosfran@41
   109
void gmyth_file_transfer_close( GMythFileTransfer *transfer );
rosfran@41
   110
rosfran@381
   111
static gboolean myth_control_acquire_context( GMythFileTransfer *transfer, gboolean do_wait );
rosfran@97
   112
rosfran@381
   113
static gboolean myth_control_release_context( GMythFileTransfer *transfer );
rosfran@97
   114
rosfran@41
   115
G_DEFINE_TYPE(GMythFileTransfer, gmyth_file_transfer, G_TYPE_OBJECT)
rosfran@41
   116
rosfran@41
   117
static void
rosfran@41
   118
gmyth_file_transfer_class_init (GMythFileTransferClass *klass)
rosfran@41
   119
{
rosfran@41
   120
  GObjectClass *gobject_class;
rosfran@216
   121
  GMythFileTransferClass *gtransfer_class;
rosfran@41
   122
rosfran@41
   123
  gobject_class = (GObjectClass *) klass;
rosfran@216
   124
  gtransfer_class = (GMythFileTransferClass *) gobject_class;
rosfran@41
   125
rosfran@41
   126
  gobject_class->dispose  = gmyth_file_transfer_dispose;
rosfran@41
   127
  gobject_class->finalize = gmyth_file_transfer_finalize;
rosfran@216
   128
  
rosfran@216
   129
  g_type_class_add_private (gobject_class, sizeof (GMythFileTransferPrivate));
rosfran@216
   130
  
rosfran@233
   131
	gtransfer_class->program_info_changed_handler = gmyth_file_transfer_program_info_changed;
rosfran@233
   132
  
rosfran@216
   133
	gtransfer_class->program_info_changed_handler_signal_id = 
rosfran@233
   134
		  g_signal_new ( "program-info-changed",
rosfran@216
   135
		                 G_TYPE_FROM_CLASS (gtransfer_class),
rosfran@216
   136
		                 G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
rosfran@216
   137
		                 0,
rosfran@216
   138
										 NULL,
rosfran@216
   139
										 NULL,
rosfran@216
   140
										 gmyth_marshal_VOID__INT_POINTER,
rosfran@216
   141
										 G_TYPE_NONE,
rosfran@216
   142
										 2,
rosfran@216
   143
										 G_TYPE_INT,
rosfran@233
   144
										 G_TYPE_POINTER );
rosfran@216
   145
rosfran@41
   146
}
rosfran@41
   147
melunko@112
   148
static void
melunko@112
   149
gmyth_file_transfer_init (GMythFileTransfer *transfer)
rosfran@41
   150
{ 
melunko@112
   151
  g_return_if_fail( transfer != NULL );
melunko@112
   152
melunko@112
   153
  transfer->readposition = 0;
melunko@112
   154
  transfer->filesize = GMYTHTV_FILE_SIZE;
rosfran@216
   155
  
rosfran@216
   156
  transfer->priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer);	
rosfran@216
   157
  
rosfran@216
   158
  transfer->priv->do_next_program_chain = FALSE;
rosfran@435
   159
  transfer->priv->recorder = NULL;
melunko@112
   160
melunko@112
   161
  transfer->control_sock = NULL;
melunko@112
   162
  transfer->sock = NULL;
rosfran@177
   163
  
rosfran@220
   164
  transfer->mutex = g_mutex_new();
rosfran@220
   165
  
rosfran@233
   166
	g_signal_connect ( G_OBJECT (transfer), "program-info-changed",
rosfran@233
   167
              (GCallback)(GMYTH_FILE_TRANSFER_GET_CLASS(transfer)->program_info_changed_handler),
rosfran@233
   168
              NULL );
rosfran@233
   169
rosfran@41
   170
}
rosfran@41
   171
rosfran@41
   172
static void
rosfran@41
   173
gmyth_file_transfer_dispose  (GObject *object)
rosfran@336
   174
{	
rosfran@192
   175
	GMythFileTransfer *transfer = GMYTH_FILE_TRANSFER (object);
leo_sobral@439
   176
leo_sobral@439
   177
    if (transfer->priv->disposed) {
leo_sobral@439
   178
        /* If dispose did already run, return. */
leo_sobral@439
   179
        return;
leo_sobral@439
   180
    }
leo_sobral@439
   181
    
leo_sobral@439
   182
    /* Make sure dispose does not run twice. */
leo_sobral@439
   183
    transfer->priv->disposed = TRUE;
leo_sobral@439
   184
    
leo_sobral@439
   185
  if ( transfer->mutex != NULL ) {
rosfran@220
   186
  	g_mutex_free( transfer->mutex );
rosfran@220
   187
  	transfer->mutex = NULL;
rosfran@220
   188
  }
rosfran@220
   189
  
leo_sobral@439
   190
  if ( transfer->control_sock != NULL ) {
rosfran@192
   191
  	g_object_unref( transfer->control_sock );
rosfran@192
   192
  	transfer->control_sock = NULL;
rosfran@192
   193
  }  
rosfran@192
   194
  
leo_sobral@439
   195
  if ( transfer->sock != NULL ) {
rosfran@192
   196
  	g_object_unref( transfer->sock );
rosfran@192
   197
  	transfer->sock = NULL;
renatofilho@187
   198
  }
rosfran@336
   199
  
leo_sobral@439
   200
  if ( transfer->backend_info != NULL ) {
leo_sobral@439
   201
  	g_object_unref( transfer->backend_info );
leo_sobral@439
   202
  	transfer->backend_info = NULL;
leo_sobral@439
   203
  }
leo_sobral@439
   204
  
leo_sobral@439
   205
  if ( transfer->priv->recorder != NULL ) {
rosfran@435
   206
  	g_object_unref( transfer->priv->recorder );
rosfran@435
   207
  	transfer->priv->recorder = NULL;
rosfran@336
   208
  }
leo_sobral@439
   209
  
leo_sobral@439
   210
  if ( transfer->filename != NULL ) {
rosfran@192
   211
  	g_free( transfer->filename );
rosfran@192
   212
  	transfer->filename = NULL;
renatofilho@187
   213
  }
renatofilho@187
   214
rosfran@41
   215
  G_OBJECT_CLASS (gmyth_file_transfer_parent_class)->dispose (object);
rosfran@41
   216
}
rosfran@41
   217
rosfran@101
   218
static void
rosfran@41
   219
gmyth_file_transfer_finalize (GObject *object)
rosfran@41
   220
{
rosfran@41
   221
  g_signal_handlers_destroy (object);
rosfran@41
   222
rosfran@41
   223
  G_OBJECT_CLASS (gmyth_file_transfer_parent_class)->finalize (object);
rosfran@41
   224
}
rosfran@41
   225
rosfran@419
   226
/** 
rosfran@420
   227
 * Creates a new instance of GMythFileTransfer.
rosfran@420
   228
 * 
rosfran@420
   229
 * @param backend_info The BackendInfo instance, with all the MythTV network 
rosfran@420
   230
 * 										 configuration data.
rosfran@419
   231
 * 
rosfran@419
   232
 * @return a new instance of the File Transfer. 
rosfran@419
   233
 */
melunko@112
   234
GMythFileTransfer*
leo_sobral@439
   235
gmyth_file_transfer_new (GMythBackendInfo *backend_info)
rosfran@41
   236
{
renatofilho@166
   237
  GMythFileTransfer *transfer = GMYTH_FILE_TRANSFER (g_object_new (GMYTH_FILE_TRANSFER_TYPE, NULL));
rosfran@177
   238
  
leo_sobral@439
   239
  transfer->backend_info = backend_info;
renatofilho@187
   240
  g_object_ref (transfer->backend_info);
rosfran@41
   241
rosfran@177
   242
  return transfer;
rosfran@177
   243
}
rosfran@177
   244
rosfran@420
   245
/** 
rosfran@420
   246
 * Creates a new instance of GMythFileTransfer.
rosfran@420
   247
 * 
rosfran@420
   248
 * @param uri_str The URI poiting to the MythTV backend server.
rosfran@420
   249
 * 
rosfran@420
   250
 * @return a new instance of the File Transfer. 
rosfran@420
   251
 */
rosfran@177
   252
GMythFileTransfer* 
renatofilho@187
   253
gmyth_file_transfer_new_with_uri (const gchar* uri_str)
rosfran@177
   254
{
rosfran@177
   255
  GMythFileTransfer *transfer = GMYTH_FILE_TRANSFER (g_object_new (GMYTH_FILE_TRANSFER_TYPE, NULL));
melunko@158
   256
melunko@201
   257
  transfer->backend_info = gmyth_backend_info_new_with_uri (uri_str);
renatofilho@187
   258
rosfran@41
   259
  return transfer;
rosfran@41
   260
}
rosfran@41
   261
rosfran@420
   262
/** 
rosfran@420
   263
 * Open a File Transfer connection in order to get a remote file.
rosfran@420
   264
 * 
rosfran@420
   265
 * @param transfer The actual File Transfer instance. 
rosfran@420
   266
 * @param filename The file name of the remote file to be transfered to the client.
rosfran@420
   267
 * 
rosfran@420
   268
 * @return <code>true</code>, if the connection opening had been done successfully. 
rosfran@420
   269
 */
rosfran@41
   270
gboolean
renatofilho@187
   271
gmyth_file_transfer_open (GMythFileTransfer *transfer, const gchar* filename)
rosfran@41
   272
{
rosfran@41
   273
  gboolean ret = TRUE;
rosfran@177
   274
  
renatofilho@202
   275
  g_return_val_if_fail (transfer != NULL, FALSE);
rosfran@343
   276
  g_return_val_if_fail (filename != NULL && strlen(filename) > 0, FALSE);
rosfran@177
   277
  
renatofilho@202
   278
  if (transfer->filename != NULL)
rosfran@184
   279
  {
renatofilho@202
   280
    g_free (transfer->filename);
renatofilho@202
   281
    transfer->filename = NULL;
rosfran@184
   282
  }
renatofilho@202
   283
rosfran@343
   284
  transfer->filename = g_strdup( filename );
rosfran@184
   285
  
rosfran@41
   286
  /* configure the control socket */
melunko@112
   287
  if (transfer->control_sock == NULL) { 
renatofilho@143
   288
    if (!gmyth_connect_to_backend (transfer)) {
renatofilho@187
   289
      gmyth_debug ("Connection to backend failed (Control Socket).\n");
rosfran@41
   290
      ret = FALSE;
rosfran@41
   291
    }
rosfran@41
   292
  } else {
rosfran@41
   293
    g_warning("Remote transfer control socket already created.\n");
rosfran@41
   294
  }
rosfran@177
   295
  
rosfran@205
   296
  gmyth_debug ("Got file with size = %lld.\n", transfer->filesize);
rosfran@205
   297
  
rosfran@41
   298
  return ret;
rosfran@41
   299
}
rosfran@41
   300
rosfran@420
   301
/** 
rosfran@420
   302
 * Connect a File Transfer binary client socket to a remote file.
rosfran@420
   303
 * 
rosfran@420
   304
 * @param transfer The actual File Transfer instance. 
rosfran@420
   305
 * 
rosfran@420
   306
 * @return <code>true</code>, if the connection had been configured successfully. 
rosfran@420
   307
 */
rosfran@115
   308
static gboolean
melunko@112
   309
gmyth_connect_to_backend (GMythFileTransfer *transfer)
rosfran@41
   310
{
renatofilho@143
   311
  GString *base_str = NULL;
rosfran@177
   312
  GString *hostname = NULL;
melunko@158
   313
  GMythStringList *strlist = NULL; 
renatofilho@143
   314
  gboolean ret = TRUE;
rosfran@41
   315
melunko@112
   316
  g_return_val_if_fail (transfer != NULL, FALSE );
rosfran@381
   317
  
rosfran@381
   318
  myth_control_acquire_context( transfer, TRUE );
rosfran@41
   319
renatofilho@143
   320
  base_str = g_string_new ("");
rosfran@41
   321
melunko@112
   322
  /* Creates the control socket */
rosfran@356
   323
  
renatofilho@143
   324
  if (transfer->control_sock != NULL) {
renatofilho@143
   325
    g_object_unref (transfer->control_sock);
renatofilho@143
   326
    transfer->control_sock = NULL;
renatofilho@143
   327
  }
rosfran@356
   328
  
leo_sobral@439
   329
  if ( NULL == transfer->control_sock )
leo_sobral@439
   330
  {
rosfran@356
   331
  	transfer->control_sock = gmyth_socket_new();
renatofilho@143
   332
rosfran@356
   333
	  // Connects the socket, send Mythtv ANN command and verify Mythtv protocol version 
rosfran@356
   334
	  if (!gmyth_socket_connect_to_backend (transfer->control_sock,
rosfran@356
   335
	        transfer->backend_info->hostname, transfer->backend_info->port, TRUE)) {
rosfran@356
   336
	
rosfran@356
   337
	    g_object_unref (transfer->control_sock);
rosfran@356
   338
	    transfer->control_sock = NULL;
rosfran@356
   339
	    return FALSE;
rosfran@356
   340
	  }
rosfran@356
   341
	  
leo_sobral@439
   342
  }
melunko@112
   343
    
melunko@112
   344
  /* Creates the data socket */
renatofilho@143
   345
  if (transfer->sock != NULL) {
renatofilho@143
   346
    g_object_unref (transfer->sock);
renatofilho@143
   347
    transfer->sock = NULL;
rosfran@356
   348
  }  
rosfran@356
   349
  
rosfran@356
   350
  //if ( NULL == transfer->sock ) {	
rosfran@356
   351
	  transfer->sock = gmyth_socket_new ();
rosfran@356
   352
	  gmyth_socket_connect (transfer->sock, transfer->backend_info->hostname, transfer->backend_info->port);
rosfran@356
   353
	  gmyth_debug("Connecting file transfer... (%s, %d)", transfer->backend_info->hostname, transfer->backend_info->port);	  
rosfran@356
   354
  //}
rosfran@356
   355
  
rosfran@356
   356
  if ( transfer->control_sock != NULL )
rosfran@356
   357
  {
rosfran@356
   358
	
rosfran@356
   359
	  strlist = gmyth_string_list_new();
rosfran@356
   360
	  hostname = gmyth_socket_get_local_hostname();
rosfran@356
   361
	  gmyth_debug( "[%s] MythTV version (from backend) = %d.\n", __FUNCTION__, transfer->control_sock->mythtv_version );
rosfran@356
   362
	  if ( transfer->control_sock->mythtv_version > 26 )
rosfran@356
   363
	  	g_string_printf( base_str, "ANN FileTransfer %s 1 -1", hostname->str);
rosfran@356
   364
	  else
rosfran@356
   365
	  	g_string_printf( base_str, "ANN FileTransfer %s", hostname->str);
rosfran@356
   366
	
rosfran@356
   367
	  gmyth_string_list_append_string (strlist, base_str );
rosfran@356
   368
	  gmyth_string_list_append_char_array (strlist, transfer->filename);
rosfran@356
   369
	
rosfran@356
   370
	  gmyth_socket_write_stringlist (transfer->sock, strlist );
rosfran@356
   371
	  gmyth_socket_read_stringlist (transfer->sock, strlist );
rosfran@356
   372
	    
rosfran@356
   373
	  /* file identification used in future file transfer requests to backend */
rosfran@356
   374
	  transfer->file_id = gmyth_string_list_get_int( strlist, 1 );
rosfran@356
   375
	
rosfran@356
   376
	  /* Myth URI stream file size - decoded using two 8-bytes sequences (64 bits/long long types) */
rosfran@356
   377
	  transfer->filesize = gmyth_util_decode_long_long( strlist, 2 );
rosfran@356
   378
	
rosfran@356
   379
	  gmyth_debug ( "[%s] ***** Received: recordernum = %d, filesize = %" G_GUINT64_FORMAT "\n", __FUNCTION__,
rosfran@356
   380
	          transfer->file_id, transfer->filesize );
rosfran@356
   381
	
rosfran@356
   382
	  if (transfer->filesize < 0 ) {
rosfran@356
   383
	      gmyth_debug ( "[%s] Got filesize equals to %llu is lesser than 0 [invalid stream file]\n", __FUNCTION__, transfer->filesize );
rosfran@356
   384
	      g_object_unref (transfer->sock);
rosfran@356
   385
	      transfer->sock = NULL;
rosfran@356
   386
	      ret = FALSE;
rosfran@356
   387
	      goto cleanup;
rosfran@356
   388
	  }
rosfran@356
   389
	  
rosfran@356
   390
  } /* if - Control Socket is not equals to NULL? */
melunko@112
   391
  
renatofilho@143
   392
cleanup:
rosfran@41
   393
rosfran@381
   394
	myth_control_release_context( transfer );
rosfran@381
   395
rosfran@41
   396
  if ( strlist != NULL )
rosfran@41
   397
    g_object_unref( strlist );
rosfran@356
   398
  
rosfran@356
   399
  if ( base_str != NULL )
rosfran@356
   400
  	g_string_free (base_str, TRUE);
rosfran@356
   401
  	
rosfran@356
   402
  if ( hostname != NULL )
rosfran@356
   403
  	g_string_free (hostname, TRUE);
rosfran@41
   404
renatofilho@143
   405
  return ret;
rosfran@41
   406
}    
rosfran@41
   407
rosfran@420
   408
/** 
rosfran@420
   409
 * Receives a GObject signal coming from a LiveTV instance, all the time a 
rosfran@420
   410
 * program info changes.
rosfran@420
   411
 * 
rosfran@420
   412
 * @param transfer The actual File Transfer instance. 
rosfran@420
   413
 * @param msg_code The MythTV backend message status code.
rosfran@420
   414
 * @param live_tv A pointer to the LiveTV instance. * 
rosfran@420
   415
 */
rosfran@233
   416
void
rosfran@233
   417
gmyth_file_transfer_emit_program_info_changed_signal ( GMythFileTransfer *transfer, gint msg_code,
rosfran@435
   418
			gpointer live_tv_recorder ) 
rosfran@233
   419
{
rosfran@233
   420
				/*
rosfran@233
   421
	g_signal_emit_by_name ( G_OBJECT(transfer),
rosfran@233
   422
         "program-info-changed",
rosfran@233
   423
         msg_code, live_tv );
rosfran@233
   424
         */
rosfran@233
   425
         
rosfran@233
   426
  gmyth_debug( "Calling signal handler... [FILE_TRANSFER]" );
rosfran@233
   427
rosfran@233
   428
  g_signal_emit ( transfer,
rosfran@233
   429
         GMYTH_FILE_TRANSFER_GET_CLASS (transfer)->program_info_changed_handler_signal_id,
rosfran@233
   430
         0, /* details */
rosfran@435
   431
         msg_code, live_tv_recorder );
rosfran@233
   432
rosfran@233
   433
}
rosfran@233
   434
rosfran@420
   435
/** 
rosfran@420
   436
 * Checks if the actual File Transfer connection is open.
rosfran@420
   437
 * 
rosfran@420
   438
 * @param transfer The actual File Transfer instance. 
rosfran@420
   439
 * 
rosfran@420
   440
 * @return <code>true</code>, if the File Transfer connection is opened. 
rosfran@420
   441
 */
melunko@112
   442
gboolean
melunko@112
   443
gmyth_file_transfer_is_open (GMythFileTransfer *transfer)
rosfran@41
   444
{
melunko@112
   445
    GMythStringList *strlist;
melunko@112
   446
    GString *query;
rosfran@41
   447
melunko@112
   448
    g_return_val_if_fail (transfer->control_sock != NULL, FALSE);
melunko@112
   449
    g_return_val_if_fail (transfer->sock != NULL, FALSE);
rosfran@381
   450
    
rosfran@381
   451
    myth_control_acquire_context( transfer, TRUE );
rosfran@41
   452
melunko@112
   453
    strlist = gmyth_string_list_new();
melunko@112
   454
    query = g_string_new (GMYTHTV_QUERY_HEADER);
melunko@112
   455
    g_string_append_printf (query, "%d", transfer->file_id );
rosfran@41
   456
melunko@112
   457
    gmyth_string_list_append_string (strlist, query );
melunko@112
   458
    gmyth_string_list_append_char_array( strlist, "IS_OPEN" );
rosfran@41
   459
melunko@112
   460
    gmyth_socket_write_stringlist( transfer->control_sock, strlist );
melunko@112
   461
    gmyth_socket_read_stringlist( transfer->control_sock, strlist );
rosfran@381
   462
    
rosfran@381
   463
    myth_control_release_context( transfer );
rosfran@41
   464
melunko@112
   465
    g_string_free (query, TRUE);
melunko@112
   466
    g_object_unref (strlist);
rosfran@41
   467
melunko@112
   468
    return ( strlist != NULL && gmyth_string_list_get_int( strlist, 0 ) == 1 );
rosfran@41
   469
}
rosfran@41
   470
rosfran@420
   471
/** 
rosfran@420
   472
 * Closes a remote File Transfer connection.
rosfran@420
   473
 * 
rosfran@420
   474
 * @param transfer The actual File Transfer instance. 
rosfran@420
   475
 */
melunko@112
   476
void
rosfran@41
   477
gmyth_file_transfer_close( GMythFileTransfer *transfer )
rosfran@41
   478
{
rosfran@41
   479
  GMythStringList *strlist;
melunko@112
   480
  GString *query;
rosfran@41
   481
melunko@112
   482
  g_return_if_fail (transfer->control_sock != NULL);
rosfran@381
   483
  
rosfran@381
   484
  myth_control_acquire_context( transfer, TRUE );
rosfran@41
   485
rosfran@41
   486
  strlist = gmyth_string_list_new( );
melunko@112
   487
  query = g_string_new (GMYTHTV_QUERY_HEADER);
melunko@112
   488
  g_string_append_printf( query, "%d", transfer->file_id);
rosfran@41
   489
melunko@112
   490
  gmyth_string_list_append_string( strlist, query );
rosfran@41
   491
  gmyth_string_list_append_char_array( strlist, "DONE" );
rosfran@41
   492
melunko@112
   493
  if ( gmyth_socket_sendreceive_stringlist(transfer->control_sock, strlist) <= 0 ) {
melunko@112
   494
    // fixme: time out???
rosfran@381
   495
    gmyth_debug ( "Remote file timeout.\n" );
rosfran@41
   496
  }
rosfran@41
   497
melunko@112
   498
  g_string_free (query, TRUE);
melunko@112
   499
  g_object_unref (strlist);
melunko@112
   500
melunko@112
   501
  if (transfer->sock) {
rosfran@41
   502
    g_object_unref( transfer->sock );
rosfran@41
   503
    transfer->sock = NULL;
rosfran@41
   504
  }
rosfran@41
   505
melunko@112
   506
  if (transfer->control_sock) {
rosfran@41
   507
    g_object_unref( transfer->control_sock );
rosfran@41
   508
    transfer->control_sock = NULL;
rosfran@41
   509
  } 
rosfran@381
   510
rosfran@381
   511
  myth_control_release_context( transfer );
rosfran@381
   512
rosfran@41
   513
}
rosfran@41
   514
rosfran@420
   515
/** 
rosfran@420
   516
 * Do a seek operation (moves the read/write file pointer) on a remote file.
rosfran@420
   517
 * 
rosfran@420
   518
 * @param transfer The actual File Transfer instance. 
rosfran@420
   519
 * @param pos The position to be moved in the remote file.
rosfran@420
   520
 * @param whence Tells to what direction seek movement should be done.
rosfran@420
   521
 * 
rosfran@420
   522
 * @return The actual position on the remote file (after seek has been done). 
rosfran@420
   523
 */
rosfran@41
   524
gint64
rosfran@41
   525
gmyth_file_transfer_seek(GMythFileTransfer *transfer, guint64 pos, gint whence)
rosfran@41
   526
{
melunko@112
   527
  GMythStringList *strlist = gmyth_string_list_new();
melunko@112
   528
  GString *query;
rosfran@41
   529
melunko@112
   530
  g_return_val_if_fail (transfer->sock != NULL, -1);
melunko@112
   531
  g_return_val_if_fail (transfer->control_sock != NULL, -1);
rosfran@41
   532
melunko@112
   533
  strlist = gmyth_string_list_new();
melunko@112
   534
  query = g_string_new (GMYTHTV_QUERY_HEADER);
melunko@112
   535
  g_string_append_printf (query, "%d", transfer->file_id);
rosfran@97
   536
  
rosfran@384
   537
  /* myth_control_acquire_context( transfer, TRUE ); */
rosfran@41
   538
melunko@112
   539
  gmyth_string_list_append_string( strlist, query );
rosfran@41
   540
  gmyth_string_list_append_char_array( strlist, "SEEK" );
rosfran@41
   541
  gmyth_string_list_append_uint64( strlist, pos );
rosfran@41
   542
  
rosfran@41
   543
  gmyth_string_list_append_int( strlist, whence );  
rosfran@41
   544
rosfran@41
   545
  if (pos > 0 )
rosfran@41
   546
    gmyth_string_list_append_uint64( strlist, pos );
rosfran@41
   547
  else
rosfran@41
   548
    gmyth_string_list_append_uint64( strlist, transfer->readposition );
rosfran@41
   549
  
rosfran@41
   550
  gmyth_socket_sendreceive_stringlist( transfer->control_sock, strlist );
rosfran@41
   551
rosfran@41
   552
  gint64 retval = gmyth_string_list_get_int64(strlist, 0);
rosfran@41
   553
  transfer->readposition = retval;
renatofilho@131
   554
  gmyth_debug ( "[%s] got reading position pointer from the streaming = %lld\n", 
rosfran@41
   555
      __FUNCTION__, retval );
rosfran@41
   556
melunko@427
   557
  g_object_unref (strlist);
melunko@427
   558
  g_string_free (query, TRUE);
melunko@427
   559
rosfran@384
   560
  /* myth_control_release_context( transfer ); */
rosfran@41
   561
rosfran@41
   562
  return retval;
rosfran@41
   563
}
rosfran@41
   564
rosfran@420
   565
/** 
rosfran@420
   566
 * Acquire access to a remote file socket read/write pointer.
rosfran@420
   567
 * 
rosfran@420
   568
 * @param transfer The actual File Transfer instance.
rosfran@420
   569
 * @param do_wait Waits or not on a GCond, when trying to read from the remote socket.
rosfran@420
   570
 * 
rosfran@420
   571
 * @return <code>true</code>, if the acquire had been got. 
rosfran@420
   572
 */
rosfran@97
   573
static gboolean 
rosfran@381
   574
myth_control_acquire_context( GMythFileTransfer *transfer, gboolean do_wait )
rosfran@97
   575
{
rosfran@97
   576
	gboolean ret = TRUE;	
rosfran@140
   577
	//guint max_iter = 50;
rosfran@97
   578
	
rosfran@381
   579
	g_mutex_lock( transfer->mutex );
rosfran@97
   580
	
rosfran@97
   581
  //while ( !has_io_access ) 
rosfran@97
   582
  //	g_cond_wait( io_watcher_cond, mutex );
rosfran@97
   583
  	
rosfran@97
   584
  //has_io_access = FALSE;
rosfran@97
   585
  
rosfran@97
   586
  //myth_control_acquire_context (FALSE);
rosfran@140
   587
   
rosfran@140
   588
  /* 
rosfran@97
   589
  if ( do_wait ) {
rosfran@120
   590
  	while ( --max_iter > 0 && !g_main_context_wait( io_watcher_context, io_watcher_cond, mutex ) )
rosfran@97
   591
  		ret = FALSE;
rosfran@97
   592
  } else if ( !g_main_context_acquire( io_watcher_context ) )
rosfran@97
   593
  	ret = FALSE;
rosfran@140
   594
  */
rosfran@140
   595
  	
rosfran@140
   596
  //g_static_mutex_lock( &st_mutex );
rosfran@97
   597
  
rosfran@97
   598
  return ret;
rosfran@97
   599
}
rosfran@97
   600
rosfran@420
   601
/** 
rosfran@420
   602
 * Release access to a remote file socket read/write pointer.
rosfran@420
   603
 * 
rosfran@420
   604
 * @param transfer The actual File Transfer instance.
rosfran@420
   605
 * 
rosfran@420
   606
 * @return <code>true</code>, if the socket read/write permissions had been releaseds. 
rosfran@420
   607
 */
rosfran@97
   608
static gboolean 
rosfran@381
   609
myth_control_release_context( GMythFileTransfer *transfer ) 
rosfran@97
   610
{
rosfran@97
   611
	gboolean ret = TRUE;
rosfran@140
   612
    
rosfran@140
   613
  //g_static_mutex_unlock( &st_mutex );
rosfran@97
   614
  
rosfran@140
   615
	//g_main_context_release( io_watcher_context );
rosfran@140
   616
  
rosfran@140
   617
  //g_main_context_wakeup( io_watcher_context );
rosfran@97
   618
  
rosfran@97
   619
  //has_io_access = TRUE;
rosfran@97
   620
rosfran@97
   621
  //g_cond_broadcast( io_watcher_cond );
rosfran@97
   622
  
rosfran@381
   623
  g_mutex_unlock( transfer->mutex );  
rosfran@97
   624
 
rosfran@97
   625
  return ret;
rosfran@97
   626
}
rosfran@97
   627
rosfran@420
   628
/** 
rosfran@420
   629
 * Reads a block from a remote file.
rosfran@420
   630
 * 
rosfran@420
   631
 * @param transfer The actual File Transfer instance.
rosfran@420
   632
 * @param data A GByteArray instance, where all the binary data representing 
rosfran@420
   633
 * 						 the remote file will be stored.
rosfran@420
   634
 * @param size The block size, in bytes, to be requested from a remote file.
rosfran@420
   635
 * @param read_unlimited Tells the backend to read indefinitely (LiveTV), or only 
rosfran@420
   636
 * 											 gets the actual size
rosfran@420
   637
 * 
rosfran@420
   638
 * @return The actual block size (in bytes) returned by REQUEST_BLOCK message,
rosfran@420
   639
 * 				or the error code. 
rosfran@420
   640
 */
rosfran@41
   641
gint 
rosfran@115
   642
gmyth_file_transfer_read(GMythFileTransfer *transfer, GByteArray *data, gint size, gboolean read_unlimited)
rosfran@41
   643
{
rosfran@177
   644
  gint bytes_sent = 0;
rosfran@41
   645
  gsize bytes_read = 0;
melunko@112
   646
  gsize total_read = 0;
melunko@112
   647
  
melunko@112
   648
  GError *error = NULL;
melunko@112
   649
  
rosfran@41
   650
  GIOChannel *io_channel;
rosfran@41
   651
  GIOChannel *io_channel_control;
rosfran@41
   652
rosfran@41
   653
  GIOCondition io_cond;
rosfran@41
   654
  GIOCondition io_cond_control;
rosfran@220
   655
  GIOStatus io_status = G_IO_STATUS_NORMAL, io_status_control = G_IO_STATUS_NORMAL;
rosfran@220
   656
  
rosfran@420
   657
  gboolean ret = TRUE;
rosfran@41
   658
melunko@112
   659
  GString *query;
rosfran@115
   660
  
rosfran@41
   661
  g_return_val_if_fail ( data != NULL, -2 );
rosfran@101
   662
rosfran@41
   663
  io_channel = transfer->sock->sd_io_ch;
rosfran@41
   664
  io_channel_control = transfer->control_sock->sd_io_ch;
rosfran@41
   665
rosfran@41
   666
  io_status = g_io_channel_set_encoding( io_channel, NULL, &error );
rosfran@41
   667
  if ( io_status == G_IO_STATUS_NORMAL )
renatofilho@131
   668
    gmyth_debug ( "[%s] Setting encoding to binary data socket).\n", __FUNCTION__ );
rosfran@41
   669
rosfran@41
   670
  io_cond = g_io_channel_get_buffer_condition( io_channel );  
rosfran@41
   671
rosfran@41
   672
  io_cond_control = g_io_channel_get_buffer_condition( io_channel );
melunko@112
   673
  if ( transfer->sock == NULL || ( io_status == G_IO_STATUS_ERROR ) ) {
rosfran@41
   674
    g_printerr( "gmyth_file_transfer_read(): Called with no raw socket.\n" );
melunko@112
   675
    return -1;
rosfran@41
   676
  }
rosfran@41
   677
melunko@112
   678
  if ( transfer->control_sock == NULL || ( io_status_control == G_IO_STATUS_ERROR ) ) {
rosfran@41
   679
    g_printerr( "gmyth_file_transfer_read(): Called with no control socket.\n" );
melunko@112
   680
    return -1;
rosfran@41
   681
  }
rosfran@41
   682
melunko@112
   683
  query = g_string_new (GMYTHTV_QUERY_HEADER);
melunko@112
   684
  g_string_append_printf ( query, "%d", transfer->file_id );
renatofilho@131
   685
  gmyth_debug ("[%s] Transfer_query = %s\n", __FUNCTION__, query->str );
rosfran@41
   686
  
rosfran@177
   687
  /* send requests to the maximum number of REQUEST_BLOCK messages */
rosfran@197
   688
  guint max_tries = 5;
rosfran@177
   689
  
rosfran@381
   690
  myth_control_acquire_context( transfer, TRUE );
rosfran@140
   691
  
rosfran@177
   692
  while (total_read == 0 && --max_tries > 0) {
renatofilho@143
   693
    GMythStringList *strlist = gmyth_string_list_new();
melunko@112
   694
melunko@112
   695
    gmyth_string_list_append_char_array( strlist, query->str );
rosfran@101
   696
    gmyth_string_list_append_char_array( strlist, "REQUEST_BLOCK" );
melunko@112
   697
    gmyth_string_list_append_int( strlist, size );
melunko@112
   698
melunko@112
   699
    // Request the block to the backend
melunko@112
   700
    gmyth_socket_write_stringlist( transfer->control_sock, strlist );
melunko@112
   701
melunko@112
   702
    // Receives the backand answer    
rosfran@101
   703
    gmyth_socket_read_stringlist( transfer->control_sock, strlist );
rosfran@101
   704
rosfran@220
   705
    if ( strlist != NULL && gmyth_string_list_length( strlist ) > 0 ) 
rosfran@220
   706
    { 
renatofilho@143
   707
	    bytes_sent = gmyth_string_list_get_int( strlist,  0 ); // -1 on backend error
renatofilho@143
   708
	    gmyth_debug ( "[%s] got SENT buffer message = %d\n", __FUNCTION__, bytes_sent );
rosfran@89
   709
rosfran@409
   710
    	if ( bytes_sent > 0 )
rosfran@220
   711
    	{
rosfran@220
   712
        gchar *data_buffer = g_new0 ( gchar, bytes_sent );    
rosfran@220
   713
   	    while ( 0 != bytes_sent ) 
rosfran@220
   714
   	    { 
rosfran@220
   715
          io_status = g_io_channel_read_chars( io_channel, data_buffer + total_read, 
rosfran@220
   716
	    				(gsize) bytes_sent,	&bytes_read, &error );
rosfran@220
   717
rosfran@220
   718
	        total_read += bytes_read;
rosfran@220
   719
          bytes_sent -= bytes_read;
rosfran@342
   720
rosfran@220
   721
            /* append new data to the increasing byte array */
rosfran@220
   722
	    		data = g_byte_array_append (data, (const guint8*)data_buffer, bytes_read);
rosfran@220
   723
	        gmyth_debug ("Total transfer data read: %d\n", total_read);
rosfran@220
   724
        }
rosfran@220
   725
        g_free (data_buffer);
rosfran@409
   726
      } else if ( bytes_sent <= 0 && !read_unlimited ) {
rosfran@409
   727
      	total_read = GMYTHTV_FILE_TRANSFER_READ_ERROR;
rosfran@409
   728
    		g_object_unref (strlist);
rosfran@409
   729
    		strlist = NULL;
rosfran@409
   730
    		break;
rosfran@409
   731
    	}
rosfran@435
   732
    } else if ( !read_unlimited || !(transfer->priv != NULL && transfer->priv->recorder != NULL &&
rosfran@302
   733
					transfer->priv->do_next_program_chain) ) {
rosfran@177
   734
    	total_read = GMYTHTV_FILE_TRANSFER_READ_ERROR;
rosfran@177
   735
    	g_object_unref (strlist);
rosfran@302
   736
    	strlist = NULL;
rosfran@177
   737
    	break;
melunko@112
   738
    }
rosfran@353
   739
    if ( strlist!=NULL )
rosfran@353
   740
    {
rosfran@353
   741
	    g_object_unref (strlist);
rosfran@353
   742
	    strlist = NULL;
rosfran@353
   743
    }
rosfran@353
   744
  } /* while - iterates through bytes until reaches the end of stream */
rosfran@342
   745
rosfran@406
   746
  if ( read_unlimited && ( bytes_sent == 0 ) && ( max_tries == 0 ) )
rosfran@234
   747
	{
rosfran@234
   748
		gmyth_debug( "Trying to move to the next program chain..." );
rosfran@234
   749
		transfer->priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer);
rosfran@234
   750
		
rosfran@435
   751
		if ( transfer->priv != NULL && transfer->priv->recorder != NULL &&
rosfran@234
   752
					transfer->priv->do_next_program_chain )
rosfran@234
   753
		{
rosfran@234
   754
		
rosfran@356
   755
			  total_read = GMYTHTV_FILE_TRANSFER_NEXT_PROG_CHAIN;	
rosfran@234
   756
		
rosfran@356
   757
	  		//g_mutex_lock( transfer->mutex );
rosfran@234
   758
	  		
rosfran@435
   759
	  		//ret = gmyth_livetv_next_program_chain( transfer->priv->recorder );
rosfran@435
   760
	  		GMythProgramInfo *prog_info = gmyth_recorder_get_current_program_info( transfer->priv->recorder );
rosfran@234
   761
	  		
rosfran@356
   762
	  		if ( prog_info != NULL && prog_info->pathname != NULL && strlen( prog_info->pathname->str ) > 0 &&
rosfran@356
   763
	  						g_ascii_strcasecmp( prog_info->pathname->str, transfer->filename ) != 0 )
rosfran@356
   764
	  			ret = gmyth_file_transfer_open ( transfer, g_strrstr( prog_info->pathname->str, "/" ) );
rosfran@342
   765
	  		
rosfran@356
   766
	  		if ( prog_info != NULL )
rosfran@356
   767
	  			g_object_unref( prog_info );
rosfran@356
   768
	  			
rosfran@356
   769
	  		//g_mutex_unlock( transfer->mutex );
rosfran@234
   770
  		
rosfran@234
   771
			if ( !ret )
rosfran@356
   772
				gmyth_debug( "Cannot change to the next program info!" );
rosfran@234
   773
			else
rosfran@356
   774
				gmyth_debug( "OK!!! MOVED to the next program info [%s]!", 
rosfran@356
   775
										transfer->filename );						
rosfran@234
   776
		}
rosfran@234
   777
rosfran@234
   778
	} /* if */
rosfran@234
   779
  
rosfran@381
   780
  myth_control_release_context( transfer );
renatofilho@143
   781
  g_string_free (query, TRUE);
rosfran@41
   782
renatofilho@143
   783
  if ( error != NULL ) {
renatofilho@143
   784
    gmyth_debug ("Cleaning-up ERROR: %s [msg = %s, code = %d]\n", __FUNCTION__, error->message, 
renatofilho@143
   785
	    error->code);
renatofilho@143
   786
    g_error_free (error);
renatofilho@143
   787
  }
melunko@112
   788
  
rosfran@216
   789
  if ( total_read > 0 )
rosfran@220
   790
  	transfer->readposition += total_read;  	
rosfran@177
   791
  	
melunko@112
   792
  return total_read;
rosfran@41
   793
}
rosfran@41
   794
rosfran@420
   795
rosfran@216
   796
static void 
rosfran@216
   797
gmyth_file_transfer_program_info_changed( GMythFileTransfer *transfer, 
rosfran@435
   798
										gint msg_code, gpointer livetv_recorder )
rosfran@216
   799
{
rosfran@435
   800
	GMythRecorder *recorder = GMYTH_RECORDER( livetv_recorder );
rosfran@216
   801
	
rosfran@220
   802
	gmyth_debug( "Program info changed! ( file transfer orig. = %p, ptr. = [%s], user data = [%s] )", transfer, 
rosfran@435
   803
		livetv_recorder != NULL ? "[NOT NULL]" : "[NULL]", livetv != NULL ? "[NOT NULL]" : "[NULL]" );
rosfran@216
   804
	
rosfran@435
   805
	if ( NULL != recorder )
rosfran@216
   806
	{
rosfran@216
   807
		gmyth_debug( "YES, the requested program info movement on the LiveTV transfer is authentical!" );
rosfran@216
   808
	}
rosfran@216
   809
	
rosfran@216
   810
	transfer->priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer);	
leo_sobral@439
   811
    
rosfran@435
   812
	g_object_ref(recorder);
rosfran@435
   813
	
rosfran@435
   814
	transfer->priv->recorder = recorder;
leo_sobral@439
   815
rosfran@216
   816
	transfer->priv->do_next_program_chain = TRUE;
rosfran@216
   817
}
rosfran@216
   818
rosfran@420
   819
/** 
rosfran@420
   820
 * Sets the timeout flag of a file being transfered.
rosfran@420
   821
 * 
rosfran@420
   822
 * @param transfer The actual File Transfer instance.
rosfran@420
   823
 * @param fast If this is <code>true</code>, sets the remote timeout to be as fast
rosfran@420
   824
 * 						as possible.
rosfran@420
   825
 * 
rosfran@420
   826
 * @return <code>true</code>, if the acquire had been got. 
rosfran@420
   827
 */
melunko@112
   828
gboolean 
rosfran@41
   829
gmyth_file_transfer_settimeout( GMythFileTransfer *transfer, gboolean fast )
rosfran@41
   830
{
rosfran@41
   831
rosfran@41
   832
  GMythStringList *strlist = NULL;
rosfran@41
   833
melunko@112
   834
  g_return_val_if_fail (transfer->sock != NULL, FALSE);
melunko@112
   835
  g_return_val_if_fail (transfer->control_sock != NULL, FALSE);
rosfran@381
   836
  
rosfran@381
   837
  myth_control_acquire_context( transfer, TRUE );
rosfran@41
   838
rosfran@41
   839
  strlist = gmyth_string_list_new(); 
melunko@112
   840
  gmyth_string_list_append_char_array( strlist, GMYTHTV_QUERY_HEADER );
rosfran@41
   841
  gmyth_string_list_append_char_array( strlist, "SET_TIMEOUT" );
rosfran@41
   842
  gmyth_string_list_append_int( strlist, fast ); 
rosfran@41
   843
rosfran@381
   844
  gint strlist_len = gmyth_socket_sendreceive_stringlist( transfer->control_sock, 
rosfran@381
   845
  				strlist );
rosfran@381
   846
  
rosfran@381
   847
  if ( strlist_len > 0 )
rosfran@381
   848
  	gmyth_debug( "Yes, timeout was changed: %s.", gmyth_string_list_get_char_array( strlist, 0 ) );
rosfran@381
   849
  else
rosfran@381
   850
  	gmyth_debug( "Timeout cannot be changed!" );
rosfran@381
   851
  	
melunko@427
   852
  myth_control_release_context( transfer );
rosfran@41
   853
rosfran@381
   854
  gmyth_debug ( "%s setting timeout flag of this file transfer = %s\n", 
rosfran@381
   855
  		strlist_len > 0 ? "Yes," : "NOT", fast ? "FAST" : "NOT FAST" );
rosfran@41
   856
melunko@427
   857
  g_object_unref (strlist);
melunko@427
   858
melunko@112
   859
  return TRUE;
rosfran@41
   860
}
rosfran@41
   861
rosfran@420
   862
/** 
rosfran@420
   863
 * Gets the actual file size of the binary content.
rosfran@420
   864
 * 
rosfran@420
   865
 * @param transfer The actual File Transfer instance.
rosfran@420
   866
 * 
rosfran@420
   867
 * @return The actual file size in bytes. 
rosfran@420
   868
 */
melunko@117
   869
guint64
melunko@117
   870
gmyth_file_transfer_get_filesize (GMythFileTransfer *transfer)
melunko@117
   871
{
renatofilho@206
   872
    g_return_val_if_fail (transfer != NULL, 0);
melunko@117
   873
    return transfer->filesize;
melunko@117
   874
}