gmyth/src/gmyth_file_transfer.c
author rosfran
Tue Mar 20 21:23:58 2007 +0000 (2007-03-20)
branchtrunk
changeset 420 c1601c03cc78
parent 419 18916d01fd45
child 427 be6bb250b01a
permissions -rwxr-xr-x
[svn r425] Added internal DOxygen documentation.
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@216
    39
#include "gmyth_livetv.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@216
    92
	
rosfran@216
    93
	GMythLiveTV *livetv;
rosfran@216
    94
	
rosfran@216
    95
	gboolean do_next_program_chain;
rosfran@216
    96
	
rosfran@216
    97
};
rosfran@115
    98
rosfran@41
    99
static void gmyth_file_transfer_class_init          (GMythFileTransferClass *klass);
rosfran@41
   100
static void gmyth_file_transfer_init                (GMythFileTransfer *object);
rosfran@41
   101
rosfran@41
   102
static void gmyth_file_transfer_dispose  (GObject *object);
rosfran@41
   103
static void gmyth_file_transfer_finalize (GObject *object);
rosfran@41
   104
rosfran@216
   105
static void gmyth_file_transfer_program_info_changed( GMythFileTransfer *transfer, 
rosfran@232
   106
										gint msg_code, gpointer livetv_transfer );
rosfran@216
   107
melunko@112
   108
static gboolean gmyth_connect_to_backend (GMythFileTransfer *transfer);
rosfran@41
   109
rosfran@41
   110
void gmyth_file_transfer_close( GMythFileTransfer *transfer );
rosfran@41
   111
rosfran@381
   112
static gboolean myth_control_acquire_context( GMythFileTransfer *transfer, gboolean do_wait );
rosfran@97
   113
rosfran@381
   114
static gboolean myth_control_release_context( GMythFileTransfer *transfer );
rosfran@97
   115
rosfran@41
   116
G_DEFINE_TYPE(GMythFileTransfer, gmyth_file_transfer, G_TYPE_OBJECT)
rosfran@41
   117
rosfran@41
   118
static void
rosfran@41
   119
gmyth_file_transfer_class_init (GMythFileTransferClass *klass)
rosfran@41
   120
{
rosfran@41
   121
  GObjectClass *gobject_class;
rosfran@216
   122
  GMythFileTransferClass *gtransfer_class;
rosfran@41
   123
rosfran@41
   124
  gobject_class = (GObjectClass *) klass;
rosfran@216
   125
  gtransfer_class = (GMythFileTransferClass *) gobject_class;
rosfran@41
   126
rosfran@41
   127
  gobject_class->dispose  = gmyth_file_transfer_dispose;
rosfran@41
   128
  gobject_class->finalize = gmyth_file_transfer_finalize;
rosfran@216
   129
  
rosfran@216
   130
  g_type_class_add_private (gobject_class, sizeof (GMythFileTransferPrivate));
rosfran@216
   131
  
rosfran@233
   132
	gtransfer_class->program_info_changed_handler = gmyth_file_transfer_program_info_changed;
rosfran@233
   133
  
rosfran@216
   134
	gtransfer_class->program_info_changed_handler_signal_id = 
rosfran@233
   135
		  g_signal_new ( "program-info-changed",
rosfran@216
   136
		                 G_TYPE_FROM_CLASS (gtransfer_class),
rosfran@216
   137
		                 G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
rosfran@216
   138
		                 0,
rosfran@216
   139
										 NULL,
rosfran@216
   140
										 NULL,
rosfran@216
   141
										 gmyth_marshal_VOID__INT_POINTER,
rosfran@216
   142
										 G_TYPE_NONE,
rosfran@216
   143
										 2,
rosfran@216
   144
										 G_TYPE_INT,
rosfran@233
   145
										 G_TYPE_POINTER );
rosfran@216
   146
rosfran@41
   147
}
rosfran@41
   148
melunko@112
   149
static void
melunko@112
   150
gmyth_file_transfer_init (GMythFileTransfer *transfer)
rosfran@41
   151
{ 
melunko@112
   152
  g_return_if_fail( transfer != NULL );
melunko@112
   153
melunko@112
   154
  transfer->readposition = 0;
melunko@112
   155
  transfer->filesize = GMYTHTV_FILE_SIZE;
rosfran@216
   156
  
rosfran@216
   157
  transfer->priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer);	
rosfran@216
   158
  
rosfran@216
   159
  transfer->priv->do_next_program_chain = FALSE;
rosfran@216
   160
  transfer->priv->livetv = NULL;
melunko@112
   161
melunko@112
   162
  transfer->control_sock = NULL;
melunko@112
   163
  transfer->sock = NULL;
rosfran@177
   164
  
rosfran@220
   165
  transfer->mutex = g_mutex_new();
rosfran@220
   166
  
rosfran@233
   167
	g_signal_connect ( G_OBJECT (transfer), "program-info-changed",
rosfran@233
   168
              (GCallback)(GMYTH_FILE_TRANSFER_GET_CLASS(transfer)->program_info_changed_handler),
rosfran@233
   169
              NULL );
rosfran@233
   170
rosfran@41
   171
}
rosfran@41
   172
rosfran@41
   173
static void
rosfran@41
   174
gmyth_file_transfer_dispose  (GObject *object)
rosfran@336
   175
{	
rosfran@192
   176
	GMythFileTransfer *transfer = GMYTH_FILE_TRANSFER (object);
rosfran@192
   177
	
rosfran@220
   178
  if ( transfer->mutex != NULL )  
rosfran@220
   179
  {
rosfran@220
   180
  	g_mutex_free( transfer->mutex );
rosfran@220
   181
  	transfer->mutex = NULL;
rosfran@220
   182
  }
rosfran@220
   183
  
rosfran@192
   184
  if ( transfer->control_sock != NULL )  
rosfran@192
   185
  {
rosfran@192
   186
  	g_object_unref( transfer->control_sock );
rosfran@192
   187
  	transfer->control_sock = NULL;
rosfran@192
   188
  }  
rosfran@192
   189
  
rosfran@192
   190
  if ( transfer->sock != NULL )  
rosfran@192
   191
  {
rosfran@192
   192
  	g_object_unref( transfer->sock );
rosfran@192
   193
  	transfer->sock = NULL;
renatofilho@187
   194
  }
rosfran@336
   195
  
rosfran@336
   196
  if ( transfer->priv->livetv != NULL )  
rosfran@336
   197
  {
rosfran@336
   198
  	g_object_unref( transfer->priv->livetv );
rosfran@336
   199
  	transfer->priv->livetv = NULL;
rosfran@336
   200
  }
rosfran@336
   201
rosfran@336
   202
	/*  
rosfran@336
   203
  if ( transfer->priv != NULL )  
rosfran@336
   204
  {
rosfran@336
   205
  	g_object_unref( transfer->priv );
rosfran@336
   206
  	transfer->priv = NULL;
rosfran@336
   207
  }
rosfran@336
   208
  */
rosfran@203
   209
    
rosfran@336
   210
  if ( transfer->filename != NULL )
rosfran@192
   211
  {
rosfran@192
   212
  	g_free( transfer->filename );
rosfran@192
   213
  	transfer->filename = NULL;
renatofilho@187
   214
  }
renatofilho@187
   215
rosfran@41
   216
  G_OBJECT_CLASS (gmyth_file_transfer_parent_class)->dispose (object);
rosfran@41
   217
}
rosfran@41
   218
rosfran@101
   219
static void
rosfran@41
   220
gmyth_file_transfer_finalize (GObject *object)
rosfran@41
   221
{
rosfran@41
   222
  g_signal_handlers_destroy (object);
rosfran@41
   223
rosfran@41
   224
  G_OBJECT_CLASS (gmyth_file_transfer_parent_class)->finalize (object);
rosfran@41
   225
}
rosfran@41
   226
rosfran@419
   227
/** 
rosfran@420
   228
 * Creates a new instance of GMythFileTransfer.
rosfran@420
   229
 * 
rosfran@420
   230
 * @param backend_info The BackendInfo instance, with all the MythTV network 
rosfran@420
   231
 * 										 configuration data.
rosfran@419
   232
 * 
rosfran@419
   233
 * @return a new instance of the File Transfer. 
rosfran@419
   234
 */
melunko@112
   235
GMythFileTransfer*
rosfran@177
   236
gmyth_file_transfer_new ( const GMythBackendInfo *backend_info)
rosfran@41
   237
{
renatofilho@166
   238
  GMythFileTransfer *transfer = GMYTH_FILE_TRANSFER (g_object_new (GMYTH_FILE_TRANSFER_TYPE, NULL));
rosfran@177
   239
  
rosfran@177
   240
  transfer->backend_info = (GMythBackendInfo *)backend_info;
renatofilho@187
   241
  g_object_ref (transfer->backend_info);
rosfran@41
   242
rosfran@177
   243
  return transfer;
rosfran@177
   244
}
rosfran@177
   245
rosfran@420
   246
/** 
rosfran@420
   247
 * Creates a new instance of GMythFileTransfer.
rosfran@420
   248
 * 
rosfran@420
   249
 * @param uri_str The URI poiting to the MythTV backend server.
rosfran@420
   250
 * 
rosfran@420
   251
 * @return a new instance of the File Transfer. 
rosfran@420
   252
 */
rosfran@177
   253
GMythFileTransfer* 
renatofilho@187
   254
gmyth_file_transfer_new_with_uri (const gchar* uri_str)
rosfran@177
   255
{
rosfran@177
   256
  GMythFileTransfer *transfer = GMYTH_FILE_TRANSFER (g_object_new (GMYTH_FILE_TRANSFER_TYPE, NULL));
melunko@158
   257
melunko@201
   258
  transfer->backend_info = gmyth_backend_info_new_with_uri (uri_str);
renatofilho@187
   259
rosfran@41
   260
  return transfer;
rosfran@41
   261
}
rosfran@41
   262
rosfran@420
   263
/** 
rosfran@420
   264
 * Open a File Transfer connection in order to get a remote file.
rosfran@420
   265
 * 
rosfran@420
   266
 * @param transfer The actual File Transfer instance. 
rosfran@420
   267
 * @param filename The file name of the remote file to be transfered to the client.
rosfran@420
   268
 * 
rosfran@420
   269
 * @return <code>true</code>, if the connection opening had been done successfully. 
rosfran@420
   270
 */
rosfran@41
   271
gboolean
renatofilho@187
   272
gmyth_file_transfer_open (GMythFileTransfer *transfer, const gchar* filename)
rosfran@41
   273
{
rosfran@41
   274
  gboolean ret = TRUE;
rosfran@177
   275
  
renatofilho@202
   276
  g_return_val_if_fail (transfer != NULL, FALSE);
rosfran@343
   277
  g_return_val_if_fail (filename != NULL && strlen(filename) > 0, FALSE);
rosfran@356
   278
  /*
rosfran@177
   279
  
renatofilho@202
   280
  if (transfer->filename != NULL)
rosfran@184
   281
  {
renatofilho@202
   282
    g_free (transfer->filename);
renatofilho@202
   283
    transfer->filename = NULL;
rosfran@184
   284
  }
rosfran@356
   285
  */
renatofilho@202
   286
rosfran@343
   287
  transfer->filename = g_strdup( filename );
rosfran@184
   288
  
rosfran@41
   289
  /* configure the control socket */
melunko@112
   290
  if (transfer->control_sock == NULL) { 
renatofilho@143
   291
    if (!gmyth_connect_to_backend (transfer)) {
renatofilho@187
   292
      gmyth_debug ("Connection to backend failed (Control Socket).\n");
rosfran@41
   293
      ret = FALSE;
rosfran@41
   294
    }
rosfran@356
   295
  
rosfran@41
   296
  } else {
rosfran@41
   297
    g_warning("Remote transfer control socket already created.\n");
rosfran@41
   298
  }
rosfran@177
   299
  
rosfran@205
   300
  gmyth_debug ("Got file with size = %lld.\n", transfer->filesize);
rosfran@205
   301
  
rosfran@41
   302
  return ret;
rosfran@41
   303
rosfran@41
   304
}
rosfran@41
   305
rosfran@420
   306
/** 
rosfran@420
   307
 * Connect a File Transfer binary client socket to a remote file.
rosfran@420
   308
 * 
rosfran@420
   309
 * @param transfer The actual File Transfer instance. 
rosfran@420
   310
 * 
rosfran@420
   311
 * @return <code>true</code>, if the connection had been configured successfully. 
rosfran@420
   312
 */
rosfran@115
   313
static gboolean
melunko@112
   314
gmyth_connect_to_backend (GMythFileTransfer *transfer)
rosfran@41
   315
{
renatofilho@143
   316
  GString *base_str = NULL;
rosfran@177
   317
  GString *hostname = NULL;
melunko@158
   318
  GMythStringList *strlist = NULL; 
renatofilho@143
   319
  gboolean ret = TRUE;
rosfran@41
   320
melunko@112
   321
  g_return_val_if_fail (transfer != NULL, FALSE );
rosfran@381
   322
  
rosfran@381
   323
  myth_control_acquire_context( transfer, TRUE );
rosfran@41
   324
renatofilho@143
   325
  base_str = g_string_new ("");
rosfran@41
   326
melunko@112
   327
  /* Creates the control socket */
rosfran@356
   328
  
renatofilho@143
   329
  if (transfer->control_sock != NULL) {
renatofilho@143
   330
    g_object_unref (transfer->control_sock);
renatofilho@143
   331
    transfer->control_sock = NULL;
renatofilho@143
   332
  }
rosfran@356
   333
  
rosfran@356
   334
  //if ( NULL == transfer->control_sock )
rosfran@356
   335
  //{
rosfran@356
   336
  	transfer->control_sock = gmyth_socket_new();
renatofilho@143
   337
rosfran@356
   338
	  // Connects the socket, send Mythtv ANN command and verify Mythtv protocol version 
rosfran@356
   339
	  if (!gmyth_socket_connect_to_backend (transfer->control_sock,
rosfran@356
   340
	        transfer->backend_info->hostname, transfer->backend_info->port, TRUE)) {
rosfran@356
   341
	
rosfran@356
   342
	    g_object_unref (transfer->control_sock);
rosfran@356
   343
	    transfer->control_sock = NULL;
rosfran@356
   344
	    return FALSE;
rosfran@356
   345
	  }
rosfran@356
   346
	  
rosfran@356
   347
  //}
melunko@112
   348
    
melunko@112
   349
  /* Creates the data socket */
renatofilho@143
   350
  if (transfer->sock != NULL) {
renatofilho@143
   351
    g_object_unref (transfer->sock);
renatofilho@143
   352
    transfer->sock = NULL;
rosfran@356
   353
  }  
rosfran@356
   354
  
rosfran@356
   355
  //if ( NULL == transfer->sock ) {	
rosfran@356
   356
	  transfer->sock = gmyth_socket_new ();
rosfran@356
   357
	  gmyth_socket_connect (transfer->sock, transfer->backend_info->hostname, transfer->backend_info->port);
rosfran@356
   358
	  gmyth_debug("Connecting file transfer... (%s, %d)", transfer->backend_info->hostname, transfer->backend_info->port);	  
rosfran@356
   359
  //}
rosfran@356
   360
  
rosfran@356
   361
  if ( transfer->control_sock != NULL )
rosfran@356
   362
  {
rosfran@356
   363
	
rosfran@356
   364
	  strlist = gmyth_string_list_new();
rosfran@356
   365
	  hostname = gmyth_socket_get_local_hostname();
rosfran@356
   366
	  gmyth_debug( "[%s] MythTV version (from backend) = %d.\n", __FUNCTION__, transfer->control_sock->mythtv_version );
rosfran@356
   367
	  if ( transfer->control_sock->mythtv_version > 26 )
rosfran@356
   368
	  	g_string_printf( base_str, "ANN FileTransfer %s 1 -1", hostname->str);
rosfran@356
   369
	  else
rosfran@356
   370
	  	g_string_printf( base_str, "ANN FileTransfer %s", hostname->str);
rosfran@356
   371
	
rosfran@356
   372
	  gmyth_string_list_append_string (strlist, base_str );
rosfran@356
   373
	  gmyth_string_list_append_char_array (strlist, transfer->filename);
rosfran@356
   374
	
rosfran@356
   375
	  gmyth_socket_write_stringlist (transfer->sock, strlist );
rosfran@356
   376
	  gmyth_socket_read_stringlist (transfer->sock, strlist );
rosfran@356
   377
	    
rosfran@356
   378
	  /* file identification used in future file transfer requests to backend */
rosfran@356
   379
	  transfer->file_id = gmyth_string_list_get_int( strlist, 1 );
rosfran@356
   380
	
rosfran@356
   381
	  /* Myth URI stream file size - decoded using two 8-bytes sequences (64 bits/long long types) */
rosfran@356
   382
	  transfer->filesize = gmyth_util_decode_long_long( strlist, 2 );
rosfran@356
   383
	
rosfran@356
   384
	  gmyth_debug ( "[%s] ***** Received: recordernum = %d, filesize = %" G_GUINT64_FORMAT "\n", __FUNCTION__,
rosfran@356
   385
	          transfer->file_id, transfer->filesize );
rosfran@356
   386
	
rosfran@356
   387
	  if (transfer->filesize < 0 ) {
rosfran@356
   388
	      gmyth_debug ( "[%s] Got filesize equals to %llu is lesser than 0 [invalid stream file]\n", __FUNCTION__, transfer->filesize );
rosfran@356
   389
	      g_object_unref (transfer->sock);
rosfran@356
   390
	      transfer->sock = NULL;
rosfran@356
   391
	      ret = FALSE;
rosfran@356
   392
	      goto cleanup;
rosfran@356
   393
	  }
rosfran@356
   394
	  
rosfran@356
   395
  } /* if - Control Socket is not equals to NULL? */
melunko@112
   396
  
renatofilho@143
   397
cleanup:
rosfran@41
   398
rosfran@381
   399
	myth_control_release_context( transfer );
rosfran@381
   400
rosfran@41
   401
  if ( strlist != NULL )
rosfran@41
   402
    g_object_unref( strlist );
rosfran@356
   403
  
rosfran@356
   404
  if ( base_str != NULL )
rosfran@356
   405
  	g_string_free (base_str, TRUE);
rosfran@356
   406
  	
rosfran@356
   407
  if ( hostname != NULL )
rosfran@356
   408
  	g_string_free (hostname, TRUE);
rosfran@41
   409
renatofilho@143
   410
  return ret;
rosfran@41
   411
}    
rosfran@41
   412
rosfran@420
   413
/** 
rosfran@420
   414
 * Receives a GObject signal coming from a LiveTV instance, all the time a 
rosfran@420
   415
 * program info changes.
rosfran@420
   416
 * 
rosfran@420
   417
 * @param transfer The actual File Transfer instance. 
rosfran@420
   418
 * @param msg_code The MythTV backend message status code.
rosfran@420
   419
 * @param live_tv A pointer to the LiveTV instance. * 
rosfran@420
   420
 */
rosfran@233
   421
void
rosfran@233
   422
gmyth_file_transfer_emit_program_info_changed_signal ( GMythFileTransfer *transfer, gint msg_code,
rosfran@233
   423
			gpointer live_tv ) 
rosfran@233
   424
{
rosfran@233
   425
				/*
rosfran@233
   426
	g_signal_emit_by_name ( G_OBJECT(transfer),
rosfran@233
   427
         "program-info-changed",
rosfran@233
   428
         msg_code, live_tv );
rosfran@233
   429
         */
rosfran@233
   430
         
rosfran@233
   431
  gmyth_debug( "Calling signal handler... [FILE_TRANSFER]" );
rosfran@233
   432
rosfran@233
   433
  g_signal_emit ( transfer,
rosfran@233
   434
         GMYTH_FILE_TRANSFER_GET_CLASS (transfer)->program_info_changed_handler_signal_id,
rosfran@233
   435
         0, /* details */
rosfran@233
   436
         msg_code, live_tv );
rosfran@233
   437
rosfran@233
   438
}
rosfran@233
   439
rosfran@420
   440
/** 
rosfran@420
   441
 * Checks if the actual File Transfer connection is open.
rosfran@420
   442
 * 
rosfran@420
   443
 * @param transfer The actual File Transfer instance. 
rosfran@420
   444
 * 
rosfran@420
   445
 * @return <code>true</code>, if the File Transfer connection is opened. 
rosfran@420
   446
 */
melunko@112
   447
gboolean
melunko@112
   448
gmyth_file_transfer_is_open (GMythFileTransfer *transfer)
rosfran@41
   449
{
melunko@112
   450
    GMythStringList *strlist;
melunko@112
   451
    GString *query;
rosfran@41
   452
melunko@112
   453
    g_return_val_if_fail (transfer->control_sock != NULL, FALSE);
melunko@112
   454
    g_return_val_if_fail (transfer->sock != NULL, FALSE);
rosfran@381
   455
    
rosfran@381
   456
    myth_control_acquire_context( transfer, TRUE );
rosfran@41
   457
melunko@112
   458
    strlist = gmyth_string_list_new();
melunko@112
   459
    query = g_string_new (GMYTHTV_QUERY_HEADER);
melunko@112
   460
    g_string_append_printf (query, "%d", transfer->file_id );
rosfran@41
   461
melunko@112
   462
    gmyth_string_list_append_string (strlist, query );
melunko@112
   463
    gmyth_string_list_append_char_array( strlist, "IS_OPEN" );
rosfran@41
   464
melunko@112
   465
    gmyth_socket_write_stringlist( transfer->control_sock, strlist );
melunko@112
   466
    gmyth_socket_read_stringlist( transfer->control_sock, strlist );
rosfran@381
   467
    
rosfran@381
   468
    myth_control_release_context( transfer );
rosfran@41
   469
melunko@112
   470
    g_string_free (query, TRUE);
melunko@112
   471
    g_object_unref (strlist);
rosfran@41
   472
melunko@112
   473
    return ( strlist != NULL && gmyth_string_list_get_int( strlist, 0 ) == 1 );
rosfran@41
   474
}
rosfran@41
   475
rosfran@420
   476
/** 
rosfran@420
   477
 * Closes a remote File Transfer connection.
rosfran@420
   478
 * 
rosfran@420
   479
 * @param transfer The actual File Transfer instance. 
rosfran@420
   480
 */
melunko@112
   481
void
rosfran@41
   482
gmyth_file_transfer_close( GMythFileTransfer *transfer )
rosfran@41
   483
{
rosfran@41
   484
  GMythStringList *strlist;
melunko@112
   485
  GString *query;
rosfran@41
   486
melunko@112
   487
  g_return_if_fail (transfer->control_sock != NULL);
rosfran@381
   488
  
rosfran@381
   489
  myth_control_acquire_context( transfer, TRUE );
rosfran@41
   490
rosfran@41
   491
  strlist = gmyth_string_list_new( );
melunko@112
   492
  query = g_string_new (GMYTHTV_QUERY_HEADER);
melunko@112
   493
  g_string_append_printf( query, "%d", transfer->file_id);
rosfran@41
   494
melunko@112
   495
  gmyth_string_list_append_string( strlist, query );
rosfran@41
   496
  gmyth_string_list_append_char_array( strlist, "DONE" );
rosfran@41
   497
melunko@112
   498
  if ( gmyth_socket_sendreceive_stringlist(transfer->control_sock, strlist) <= 0 ) {
melunko@112
   499
    // fixme: time out???
rosfran@381
   500
    gmyth_debug ( "Remote file timeout.\n" );
rosfran@41
   501
  }
rosfran@41
   502
melunko@112
   503
  g_string_free (query, TRUE);
melunko@112
   504
  g_object_unref (strlist);
melunko@112
   505
melunko@112
   506
  if (transfer->sock) {
rosfran@41
   507
    g_object_unref( transfer->sock );
rosfran@41
   508
    transfer->sock = NULL;
rosfran@41
   509
  }
rosfran@41
   510
melunko@112
   511
  if (transfer->control_sock) {
rosfran@41
   512
    g_object_unref( transfer->control_sock );
rosfran@41
   513
    transfer->control_sock = NULL;
rosfran@41
   514
  } 
rosfran@381
   515
rosfran@381
   516
  myth_control_release_context( transfer );
rosfran@381
   517
rosfran@41
   518
}
rosfran@41
   519
rosfran@420
   520
/** 
rosfran@420
   521
 * Do a seek operation (moves the read/write file pointer) on a remote file.
rosfran@420
   522
 * 
rosfran@420
   523
 * @param transfer The actual File Transfer instance. 
rosfran@420
   524
 * @param pos The position to be moved in the remote file.
rosfran@420
   525
 * @param whence Tells to what direction seek movement should be done.
rosfran@420
   526
 * 
rosfran@420
   527
 * @return The actual position on the remote file (after seek has been done). 
rosfran@420
   528
 */
rosfran@41
   529
gint64
rosfran@41
   530
gmyth_file_transfer_seek(GMythFileTransfer *transfer, guint64 pos, gint whence)
rosfran@41
   531
{
melunko@112
   532
  GMythStringList *strlist = gmyth_string_list_new();
melunko@112
   533
  GString *query;
rosfran@41
   534
melunko@112
   535
  g_return_val_if_fail (transfer->sock != NULL, -1);
melunko@112
   536
  g_return_val_if_fail (transfer->control_sock != NULL, -1);
rosfran@41
   537
melunko@112
   538
  strlist = gmyth_string_list_new();
melunko@112
   539
  query = g_string_new (GMYTHTV_QUERY_HEADER);
melunko@112
   540
  g_string_append_printf (query, "%d", transfer->file_id);
rosfran@97
   541
  
rosfran@384
   542
  /* myth_control_acquire_context( transfer, TRUE ); */
rosfran@41
   543
melunko@112
   544
  gmyth_string_list_append_string( strlist, query );
rosfran@41
   545
  gmyth_string_list_append_char_array( strlist, "SEEK" );
rosfran@41
   546
  gmyth_string_list_append_uint64( strlist, pos );
rosfran@41
   547
  
rosfran@41
   548
  gmyth_string_list_append_int( strlist, whence );  
rosfran@41
   549
rosfran@41
   550
  if (pos > 0 )
rosfran@41
   551
    gmyth_string_list_append_uint64( strlist, pos );
rosfran@41
   552
  else
rosfran@41
   553
    gmyth_string_list_append_uint64( strlist, transfer->readposition );
rosfran@41
   554
  
rosfran@41
   555
  gmyth_socket_sendreceive_stringlist( transfer->control_sock, strlist );
rosfran@41
   556
rosfran@41
   557
  gint64 retval = gmyth_string_list_get_int64(strlist, 0);
rosfran@41
   558
  transfer->readposition = retval;
renatofilho@131
   559
  gmyth_debug ( "[%s] got reading position pointer from the streaming = %lld\n", 
rosfran@41
   560
      __FUNCTION__, retval );
rosfran@41
   561
rosfran@384
   562
  /* myth_control_release_context( transfer ); */
rosfran@41
   563
rosfran@41
   564
  return retval;
rosfran@41
   565
}
rosfran@41
   566
rosfran@420
   567
/** 
rosfran@420
   568
 * Acquire access to a remote file socket read/write pointer.
rosfran@420
   569
 * 
rosfran@420
   570
 * @param transfer The actual File Transfer instance.
rosfran@420
   571
 * @param do_wait Waits or not on a GCond, when trying to read from the remote socket.
rosfran@420
   572
 * 
rosfran@420
   573
 * @return <code>true</code>, if the acquire had been got. 
rosfran@420
   574
 */
rosfran@97
   575
static gboolean 
rosfran@381
   576
myth_control_acquire_context( GMythFileTransfer *transfer, gboolean do_wait )
rosfran@97
   577
{
rosfran@97
   578
	gboolean ret = TRUE;	
rosfran@140
   579
	//guint max_iter = 50;
rosfran@97
   580
	
rosfran@381
   581
	g_mutex_lock( transfer->mutex );
rosfran@97
   582
	
rosfran@97
   583
  //while ( !has_io_access ) 
rosfran@97
   584
  //	g_cond_wait( io_watcher_cond, mutex );
rosfran@97
   585
  	
rosfran@97
   586
  //has_io_access = FALSE;
rosfran@97
   587
  
rosfran@97
   588
  //myth_control_acquire_context (FALSE);
rosfran@140
   589
   
rosfran@140
   590
  /* 
rosfran@97
   591
  if ( do_wait ) {
rosfran@120
   592
  	while ( --max_iter > 0 && !g_main_context_wait( io_watcher_context, io_watcher_cond, mutex ) )
rosfran@97
   593
  		ret = FALSE;
rosfran@97
   594
  } else if ( !g_main_context_acquire( io_watcher_context ) )
rosfran@97
   595
  	ret = FALSE;
rosfran@140
   596
  */
rosfran@140
   597
  	
rosfran@140
   598
  //g_static_mutex_lock( &st_mutex );
rosfran@97
   599
  
rosfran@97
   600
  return ret;
rosfran@97
   601
}
rosfran@97
   602
rosfran@420
   603
/** 
rosfran@420
   604
 * Release access to a remote file socket read/write pointer.
rosfran@420
   605
 * 
rosfran@420
   606
 * @param transfer The actual File Transfer instance.
rosfran@420
   607
 * 
rosfran@420
   608
 * @return <code>true</code>, if the socket read/write permissions had been releaseds. 
rosfran@420
   609
 */
rosfran@97
   610
static gboolean 
rosfran@381
   611
myth_control_release_context( GMythFileTransfer *transfer ) 
rosfran@97
   612
{
rosfran@97
   613
	gboolean ret = TRUE;
rosfran@140
   614
    
rosfran@140
   615
  //g_static_mutex_unlock( &st_mutex );
rosfran@97
   616
  
rosfran@140
   617
	//g_main_context_release( io_watcher_context );
rosfran@140
   618
  
rosfran@140
   619
  //g_main_context_wakeup( io_watcher_context );
rosfran@97
   620
  
rosfran@97
   621
  //has_io_access = TRUE;
rosfran@97
   622
rosfran@97
   623
  //g_cond_broadcast( io_watcher_cond );
rosfran@97
   624
  
rosfran@381
   625
  g_mutex_unlock( transfer->mutex );  
rosfran@97
   626
 
rosfran@97
   627
  return ret;
rosfran@97
   628
}
rosfran@97
   629
rosfran@420
   630
/** 
rosfran@420
   631
 * Reads a block from a remote file.
rosfran@420
   632
 * 
rosfran@420
   633
 * @param transfer The actual File Transfer instance.
rosfran@420
   634
 * @param data A GByteArray instance, where all the binary data representing 
rosfran@420
   635
 * 						 the remote file will be stored.
rosfran@420
   636
 * @param size The block size, in bytes, to be requested from a remote file.
rosfran@420
   637
 * @param read_unlimited Tells the backend to read indefinitely (LiveTV), or only 
rosfran@420
   638
 * 											 gets the actual size
rosfran@420
   639
 * 
rosfran@420
   640
 * @return The actual block size (in bytes) returned by REQUEST_BLOCK message,
rosfran@420
   641
 * 				or the error code. 
rosfran@420
   642
 */
rosfran@41
   643
gint 
rosfran@115
   644
gmyth_file_transfer_read(GMythFileTransfer *transfer, GByteArray *data, gint size, gboolean read_unlimited)
rosfran@41
   645
{
rosfran@177
   646
  gint bytes_sent = 0;
rosfran@41
   647
  gsize bytes_read = 0;
melunko@112
   648
  gsize total_read = 0;
melunko@112
   649
  
melunko@112
   650
  GError *error = NULL;
melunko@112
   651
  
rosfran@41
   652
  GIOChannel *io_channel;
rosfran@41
   653
  GIOChannel *io_channel_control;
rosfran@41
   654
rosfran@41
   655
  GIOCondition io_cond;
rosfran@41
   656
  GIOCondition io_cond_control;
rosfran@220
   657
  GIOStatus io_status = G_IO_STATUS_NORMAL, io_status_control = G_IO_STATUS_NORMAL;
rosfran@220
   658
  
rosfran@420
   659
  gboolean ret = TRUE;
rosfran@41
   660
melunko@112
   661
  GString *query;
rosfran@115
   662
  
rosfran@41
   663
  g_return_val_if_fail ( data != NULL, -2 );
rosfran@101
   664
rosfran@41
   665
  io_channel = transfer->sock->sd_io_ch;
rosfran@41
   666
  io_channel_control = transfer->control_sock->sd_io_ch;
rosfran@41
   667
rosfran@41
   668
  io_status = g_io_channel_set_encoding( io_channel, NULL, &error );
rosfran@41
   669
  if ( io_status == G_IO_STATUS_NORMAL )
renatofilho@131
   670
    gmyth_debug ( "[%s] Setting encoding to binary data socket).\n", __FUNCTION__ );
rosfran@41
   671
rosfran@41
   672
  io_cond = g_io_channel_get_buffer_condition( io_channel );  
rosfran@41
   673
rosfran@41
   674
  io_cond_control = g_io_channel_get_buffer_condition( io_channel );
melunko@112
   675
  if ( transfer->sock == NULL || ( io_status == G_IO_STATUS_ERROR ) ) {
rosfran@41
   676
    g_printerr( "gmyth_file_transfer_read(): Called with no raw socket.\n" );
melunko@112
   677
    return -1;
rosfran@41
   678
  }
rosfran@41
   679
melunko@112
   680
  if ( transfer->control_sock == NULL || ( io_status_control == G_IO_STATUS_ERROR ) ) {
rosfran@41
   681
    g_printerr( "gmyth_file_transfer_read(): Called with no control socket.\n" );
melunko@112
   682
    return -1;
rosfran@41
   683
  }
rosfran@41
   684
melunko@112
   685
  query = g_string_new (GMYTHTV_QUERY_HEADER);
melunko@112
   686
  g_string_append_printf ( query, "%d", transfer->file_id );
renatofilho@131
   687
  gmyth_debug ("[%s] Transfer_query = %s\n", __FUNCTION__, query->str );
rosfran@41
   688
  
rosfran@177
   689
  /* send requests to the maximum number of REQUEST_BLOCK messages */
rosfran@197
   690
  guint max_tries = 5;
rosfran@177
   691
  
rosfran@381
   692
  myth_control_acquire_context( transfer, TRUE );
rosfran@140
   693
  
rosfran@177
   694
  while (total_read == 0 && --max_tries > 0) {
renatofilho@143
   695
    GMythStringList *strlist = gmyth_string_list_new();
melunko@112
   696
melunko@112
   697
    gmyth_string_list_append_char_array( strlist, query->str );
rosfran@101
   698
    gmyth_string_list_append_char_array( strlist, "REQUEST_BLOCK" );
melunko@112
   699
    gmyth_string_list_append_int( strlist, size );
melunko@112
   700
melunko@112
   701
    // Request the block to the backend
melunko@112
   702
    gmyth_socket_write_stringlist( transfer->control_sock, strlist );
melunko@112
   703
melunko@112
   704
    // Receives the backand answer    
rosfran@101
   705
    gmyth_socket_read_stringlist( transfer->control_sock, strlist );
rosfran@101
   706
rosfran@220
   707
    if ( strlist != NULL && gmyth_string_list_length( strlist ) > 0 ) 
rosfran@220
   708
    { 
renatofilho@143
   709
	    bytes_sent = gmyth_string_list_get_int( strlist,  0 ); // -1 on backend error
renatofilho@143
   710
	    gmyth_debug ( "[%s] got SENT buffer message = %d\n", __FUNCTION__, bytes_sent );
rosfran@89
   711
rosfran@409
   712
    	if ( bytes_sent > 0 )
rosfran@220
   713
    	{
rosfran@220
   714
        gchar *data_buffer = g_new0 ( gchar, bytes_sent );    
rosfran@220
   715
   	    while ( 0 != bytes_sent ) 
rosfran@220
   716
   	    { 
rosfran@220
   717
          io_status = g_io_channel_read_chars( io_channel, data_buffer + total_read, 
rosfran@220
   718
	    				(gsize) bytes_sent,	&bytes_read, &error );
rosfran@220
   719
rosfran@220
   720
	        total_read += bytes_read;
rosfran@220
   721
          bytes_sent -= bytes_read;
rosfran@342
   722
rosfran@220
   723
            /* append new data to the increasing byte array */
rosfran@220
   724
	    		data = g_byte_array_append (data, (const guint8*)data_buffer, bytes_read);
rosfran@220
   725
	        gmyth_debug ("Total transfer data read: %d\n", total_read);
rosfran@220
   726
        }
rosfran@220
   727
        g_free (data_buffer);
rosfran@409
   728
      } else if ( bytes_sent <= 0 && !read_unlimited ) {
rosfran@409
   729
      	total_read = GMYTHTV_FILE_TRANSFER_READ_ERROR;
rosfran@409
   730
    		g_object_unref (strlist);
rosfran@409
   731
    		strlist = NULL;
rosfran@409
   732
    		break;
rosfran@409
   733
    	}
rosfran@404
   734
    } else if ( !read_unlimited || !(transfer->priv != NULL && transfer->priv->livetv != NULL &&
rosfran@302
   735
					transfer->priv->do_next_program_chain) ) {
rosfran@177
   736
    	total_read = GMYTHTV_FILE_TRANSFER_READ_ERROR;
rosfran@177
   737
    	g_object_unref (strlist);
rosfran@302
   738
    	strlist = NULL;
rosfran@177
   739
    	break;
melunko@112
   740
    }
rosfran@353
   741
    if ( strlist!=NULL )
rosfran@353
   742
    {
rosfran@353
   743
	    g_object_unref (strlist);
rosfran@353
   744
	    strlist = NULL;
rosfran@353
   745
    }
rosfran@353
   746
  } /* while - iterates through bytes until reaches the end of stream */
rosfran@342
   747
rosfran@406
   748
  if ( read_unlimited && ( bytes_sent == 0 ) && ( max_tries == 0 ) )
rosfran@234
   749
	{
rosfran@234
   750
		gmyth_debug( "Trying to move to the next program chain..." );
rosfran@234
   751
		transfer->priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer);
rosfran@234
   752
		
rosfran@234
   753
		if ( transfer->priv != NULL && transfer->priv->livetv != NULL &&
rosfran@234
   754
					transfer->priv->do_next_program_chain )
rosfran@234
   755
		{
rosfran@234
   756
		
rosfran@356
   757
			  total_read = GMYTHTV_FILE_TRANSFER_NEXT_PROG_CHAIN;	
rosfran@234
   758
		
rosfran@356
   759
	  		//g_mutex_lock( transfer->mutex );
rosfran@234
   760
	  		
rosfran@356
   761
	  		//ret = gmyth_livetv_next_program_chain( transfer->priv->livetv );
rosfran@356
   762
	  		GMythProgramInfo *prog_info = gmyth_recorder_get_current_program_info( transfer->priv->livetv->recorder );
rosfran@234
   763
	  		
rosfran@356
   764
	  		if ( prog_info != NULL && prog_info->pathname != NULL && strlen( prog_info->pathname->str ) > 0 &&
rosfran@356
   765
	  						g_ascii_strcasecmp( prog_info->pathname->str, transfer->filename ) != 0 )
rosfran@356
   766
	  			ret = gmyth_file_transfer_open ( transfer, g_strrstr( prog_info->pathname->str, "/" ) );
rosfran@342
   767
	  		
rosfran@356
   768
	  		if ( prog_info != NULL )
rosfran@356
   769
	  			g_object_unref( prog_info );
rosfran@356
   770
	  			
rosfran@356
   771
	  		//g_mutex_unlock( transfer->mutex );
rosfran@234
   772
  		
rosfran@234
   773
			if ( !ret )
rosfran@356
   774
				gmyth_debug( "Cannot change to the next program info!" );
rosfran@234
   775
			else
rosfran@356
   776
				gmyth_debug( "OK!!! MOVED to the next program info [%s]!", 
rosfran@356
   777
										transfer->filename );						
rosfran@234
   778
		}
rosfran@234
   779
rosfran@234
   780
	} /* if */
rosfran@234
   781
  
rosfran@381
   782
  myth_control_release_context( transfer );
renatofilho@143
   783
  g_string_free (query, TRUE);
rosfran@41
   784
renatofilho@143
   785
  if ( error != NULL ) {
renatofilho@143
   786
    gmyth_debug ("Cleaning-up ERROR: %s [msg = %s, code = %d]\n", __FUNCTION__, error->message, 
renatofilho@143
   787
	    error->code);
renatofilho@143
   788
    g_error_free (error);
renatofilho@143
   789
  }
melunko@112
   790
  
rosfran@216
   791
  if ( total_read > 0 )
rosfran@220
   792
  	transfer->readposition += total_read;  	
rosfran@177
   793
  	
melunko@112
   794
  return total_read;
rosfran@41
   795
}
rosfran@41
   796
rosfran@420
   797
rosfran@216
   798
static void 
rosfran@216
   799
gmyth_file_transfer_program_info_changed( GMythFileTransfer *transfer, 
rosfran@232
   800
										gint msg_code, gpointer livetv_transfer )
rosfran@216
   801
{
rosfran@233
   802
	GMythLiveTV *livetv = GMYTH_LIVETV( livetv_transfer );
rosfran@216
   803
	
rosfran@220
   804
	gmyth_debug( "Program info changed! ( file transfer orig. = %p, ptr. = [%s], user data = [%s] )", transfer, 
rosfran@220
   805
		livetv_transfer != NULL ? "[NOT NULL]" : "[NULL]", livetv != NULL ? "[NOT NULL]" : "[NULL]" );
rosfran@216
   806
	
rosfran@220
   807
	if ( livetv != NULL && transfer == livetv->file_transfer )
rosfran@216
   808
	{
rosfran@216
   809
		gmyth_debug( "YES, the requested program info movement on the LiveTV transfer is authentical!" );
rosfran@216
   810
	}
rosfran@216
   811
	
rosfran@216
   812
	transfer->priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer);	
rosfran@216
   813
	
rosfran@342
   814
	transfer->priv->livetv = livetv;
rosfran@216
   815
	transfer->priv->do_next_program_chain = TRUE;
rosfran@216
   816
	
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
  	
rosfran@381
   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@112
   857
  return TRUE;
rosfran@41
   858
}
rosfran@41
   859
rosfran@420
   860
/** 
rosfran@420
   861
 * Gets the actual file size of the binary content.
rosfran@420
   862
 * 
rosfran@420
   863
 * @param transfer The actual File Transfer instance.
rosfran@420
   864
 * 
rosfran@420
   865
 * @return The actual file size in bytes. 
rosfran@420
   866
 */
melunko@117
   867
guint64
melunko@117
   868
gmyth_file_transfer_get_filesize (GMythFileTransfer *transfer)
melunko@117
   869
{
renatofilho@206
   870
    g_return_val_if_fail (transfer != NULL, 0);
melunko@117
   871
    return transfer->filesize;
melunko@117
   872
}