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