[svn r695] Fixed erroneous maximum iteration count on reading zero-sized buffers on FileTransfer.
4 * @file gmyth/gmyth_file_transfer.c
6 * @brief <p> GMythFileTransfer deals with the file streaming media remote/local
7 * transfering to the MythTV frontend.
9 * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
10 * @author Rosfran Lins Borges <rosfran.borges@indt.org.br>
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU Lesser General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 * GStreamer MythTV plug-in properties:
29 * - location (backend server hostname/URL) [ex.: myth://192.168.1.73:28722/1000_1092091.nuv]
30 * - path (qurl - remote file to be opened)
38 #include "gmyth_file_transfer.h"
39 #include "gmyth_recorder.h"
40 #include "gmyth_util.h"
41 #include "gmyth_socket.h"
42 #include "gmyth_stringlist.h"
43 #include "gmyth_debug.h"
44 #include "gmyth_uri.h"
45 #include "gmyth_marshal.h"
50 #include <arpa/inet.h>
51 #include <sys/types.h>
52 #include <sys/socket.h>
58 #define GMYTHTV_QUERY_HEADER "QUERY_FILETRANSFER "
61 #define GMYTH_FILE_TRANSFER_GET_PRIVATE(obj) \
62 (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GMYTH_FILE_TRANSFER_TYPE, GMythFileTransferPrivate))
66 GMYTH_PLAYBACK_TYPE = 0,
68 GMYTH_FILETRANSFER_TYPE,
72 struct _GMythFileTransferPrivate
74 GMythRecorder *recorder;
76 gboolean do_next_program_chain;
80 /* MythTV version number */
83 /* socket descriptors */
84 GMythSocket *control_sock;
90 static void gmyth_file_transfer_class_init (GMythFileTransferClass * klass);
91 static void gmyth_file_transfer_init (GMythFileTransfer * object);
92 static void gmyth_file_transfer_dispose (GObject * object);
93 static void gmyth_file_transfer_finalize (GObject * object);
94 static void _file_transfer_program_info_changed (GMythFileTransfer * transfer,
96 gpointer livetv_recorder);
97 static gboolean _connect_to_backend (GMythFileTransfer * transfer);
98 static gboolean _control_acquire_context (GMythFileTransfer * transfer,
100 static gboolean _control_release_context (GMythFileTransfer * transfer);
102 G_DEFINE_TYPE (GMythFileTransfer, gmyth_file_transfer, GMYTH_FILE_TYPE)
103 static void gmyth_file_transfer_class_init (GMythFileTransferClass * klass)
105 GObjectClass *gobject_class;
106 GMythFileTransferClass *gtransfer_class;
108 gobject_class = (GObjectClass *) klass;
109 gtransfer_class = (GMythFileTransferClass *) gobject_class;
111 gobject_class->dispose = gmyth_file_transfer_dispose;
112 gobject_class->finalize = gmyth_file_transfer_finalize;
114 g_type_class_add_private (gobject_class, sizeof (GMythFileTransferPrivate));
116 gtransfer_class->program_info_changed_handler =
117 _file_transfer_program_info_changed;
119 gtransfer_class->program_info_changed_handler_signal_id =
120 g_signal_new ("program-info-changed",
121 G_TYPE_FROM_CLASS (gtransfer_class),
122 G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE |
123 G_SIGNAL_NO_HOOKS, 0, NULL, NULL,
124 gmyth_marshal_VOID__INT_POINTER, G_TYPE_NONE, 2,
125 G_TYPE_INT, G_TYPE_POINTER);
130 gmyth_file_transfer_init (GMythFileTransfer * transfer)
132 g_return_if_fail (transfer != NULL);
134 transfer->priv = GMYTH_FILE_TRANSFER_GET_PRIVATE (transfer);
135 transfer->priv->mutex = g_mutex_new ();
137 g_signal_connect (G_OBJECT (transfer), "program-info-changed",
138 (GCallback) (GMYTH_FILE_TRANSFER_GET_CLASS (transfer)->
139 program_info_changed_handler), NULL);
143 gmyth_file_transfer_dispose (GObject * object)
145 GMythFileTransferPrivate *priv;
146 GMythFileTransfer *transfer = GMYTH_FILE_TRANSFER (object);
148 g_return_if_fail (transfer != NULL);
150 priv = GMYTH_FILE_TRANSFER_GET_PRIVATE (transfer);
154 /* If dispose did already run, return. */
158 /* Make sure dispose does not run twice. */
159 priv->disposed = TRUE;
161 if (priv->mutex != NULL)
163 g_mutex_free (priv->mutex);
167 if (priv->control_sock != NULL)
169 g_object_unref (priv->control_sock);
170 priv->control_sock = NULL;
173 if (priv->sock != NULL)
175 g_object_unref (priv->sock);
179 if (priv->recorder != NULL)
181 g_object_unref (priv->recorder);
182 priv->recorder = NULL;
185 G_OBJECT_CLASS (gmyth_file_transfer_parent_class)->dispose (object);
189 gmyth_file_transfer_finalize (GObject * object)
191 g_signal_handlers_destroy (object);
193 G_OBJECT_CLASS (gmyth_file_transfer_parent_class)->finalize (object);
197 * Creates a new instance of GMythFileTransfer.
199 * @param backend_info The BackendInfo instance, with all the MythTV network
200 * configuration data.
202 * @return a new instance of the File Transfer.
205 gmyth_file_transfer_new (GMythBackendInfo * backend_info)
207 GMythFileTransfer *transfer = g_object_new (GMYTH_FILE_TRANSFER_TYPE,
208 "backend-info", backend_info,
211 //backend_info = g_object_ref( backend_info );
212 gmyth_debug ("Creating FileTransfer BackendInfo hostname = %s",
213 gmyth_backend_info_get_hostname (backend_info));
214 //GMythBackendInfo *backend_info = gmyth_backend_info_new_with_uri (uri_str);
215 //g_value_init (&val, G_TYPE_OBJECT);
216 //g_value_set_object (&val, backend_info);
217 //g_object_set (G_OBJECT (transfer), "backend-info", &val, NULL);
223 gmyth_file_transfer_get_file_name (GMythFileTransfer * transfer)
227 g_object_get (G_OBJECT (transfer), "filename", &filename, NULL);
233 * Creates a new instance of GMythFileTransfer.
235 * @param uri_str The URI poiting to the MythTV backend server.
237 * @return a new instance of the File Transfer.
240 gmyth_file_transfer_new_with_uri (const gchar * uri_str)
242 GMythFileTransfer *transfer =
243 GMYTH_FILE_TRANSFER (g_object_new (GMYTH_FILE_TRANSFER_TYPE, NULL));
244 gmyth_debug ("URI str = %s", uri_str);
245 //GMythBackendInfo *backend_info = gmyth_backend_info_new_with_uri (uri_str);
247 g_value_init (&val, G_TYPE_OBJECT);
248 g_value_set_object (&val, gmyth_backend_info_new_with_uri (uri_str));
249 g_object_set (G_OBJECT (transfer), "backend-info", &val, NULL);
255 * Open a File Transfer connection in order to get a remote file.
257 * @param transfer The actual File Transfer instance.
258 * @param filename The file name of the remote file to be transferred to the client.
260 * @return <code>true</code>, if the connection opening had been done successfully.
263 gmyth_file_transfer_open (GMythFileTransfer * transfer, const gchar * filename)
266 GMythFileTransferPrivate *priv;
268 g_return_val_if_fail (transfer != NULL, FALSE);
269 g_return_val_if_fail (filename != NULL && strlen (filename) > 0, FALSE);
271 priv = GMYTH_FILE_TRANSFER_GET_PRIVATE (transfer);
273 gmyth_debug ("Opening the FileTransfer... (%s)", filename);
275 g_object_set (GMYTH_FILE (transfer), "filename", filename, NULL);
277 /* configure the control socket */
278 if (TRUE/*priv->control_sock == NULL*/)
280 if (!_connect_to_backend (transfer))
282 gmyth_debug ("Connection to backend failed (Control Socket).");
286 if (priv->do_next_program_chain) {
287 priv->do_next_program_chain = FALSE; // fixme
288 gmyth_debug ("New file available before the current file was opened");
289 GMythProgramInfo *prog_info =
290 gmyth_recorder_get_current_program_info (priv->recorder);
292 if (prog_info != NULL && prog_info->pathname != NULL
293 && strlen (prog_info->pathname->str) > 0
294 && g_ascii_strcasecmp (prog_info->pathname->str,
295 gmyth_file_get_file_name (GMYTH_FILE
299 gmyth_file_transfer_open (transfer,
300 g_strrstr (prog_info->pathname->
303 if (prog_info != NULL)
304 g_object_unref (prog_info);
307 gmyth_debug ("Cannot change to the next program info!");
309 gmyth_debug ("OK!!! MOVED to the next program info [%s]!",
310 gmyth_file_get_file_name (GMYTH_FILE (transfer)));
313 gmyth_debug ("XXXXXXXXXXXXXX Oulu tests XXXXXXXXXXXXXXXX");
314 gmyth_debug ("None new file found. We continue with the same file opened before");
320 gmyth_debug ("Remote transfer control socket already created.");
323 gmyth_debug ("Got file with size = %lld.\n",
324 gmyth_file_get_filesize (GMYTH_FILE (transfer)));
330 * Connect a File Transfer binary client socket to a remote file.
332 * @param transfer The actual File Transfer instance.
334 * @return <code>true</code>, if the connection had been configured successfully.
337 _connect_to_backend (GMythFileTransfer * transfer)
339 GString *base_str = NULL;
340 GString *hostname = NULL;
341 GMythStringList *strlist = NULL;
343 GMythFileTransferPrivate *priv;
344 GMythBackendInfo *backend_info;
346 g_return_val_if_fail (transfer != NULL, FALSE);
348 g_object_get (GMYTH_FILE (transfer), "backend-info", &backend_info, NULL);
350 priv = GMYTH_FILE_TRANSFER_GET_PRIVATE (transfer);
351 _control_acquire_context (transfer, TRUE);
353 /* Creates the control socket */
355 if (priv->control_sock != NULL)
357 g_object_unref (priv->control_sock);
358 priv->control_sock = NULL;
361 base_str = g_string_new ("");
363 priv->control_sock = gmyth_socket_new ();
364 // Connects the socket, send Mythtv ANN command and verify Mythtv protocol version
365 if (!gmyth_socket_connect_to_backend (priv->control_sock,
366 backend_info->hostname,
367 backend_info->port, TRUE))
370 g_object_unref (priv->control_sock);
371 priv->control_sock = NULL;
375 /* Creates the data socket */
376 if (priv->sock != NULL)
378 g_object_unref (priv->sock);
382 priv->sock = gmyth_socket_new ();
383 gmyth_socket_connect (priv->sock, backend_info->hostname,
385 gmyth_debug ("Connecting file transfer... (%s, %d)", backend_info->hostname,
388 strlist = gmyth_string_list_new ();
389 hostname = gmyth_socket_get_local_hostname ();
390 gmyth_debug ("[%s] MythTV version (from backend) = %d.\n", __FUNCTION__,
391 priv->control_sock->mythtv_version);
392 if (priv->control_sock->mythtv_version > 26)
393 g_string_printf (base_str, "ANN FileTransfer %s 1 -1", hostname->str);
395 g_string_printf (base_str, "ANN FileTransfer %s", hostname->str);
397 gmyth_string_list_append_string (strlist, base_str);
398 gmyth_string_list_append_char_array (strlist,
399 gmyth_file_get_file_name (GMYTH_FILE
402 gmyth_socket_write_stringlist (priv->sock, strlist);
404 /* MONITOR Handler - DVB TV Chain update messages!!! */
406 gmyth_socket_read_stringlist (priv->sock, strlist);
408 /* file identification used in future file transfer requests to backend */
409 priv->file_id = gmyth_string_list_get_int (strlist, 1);
411 /* Myth URI stream file size - decoded using two 8-bytes sequences (64 bits/long long types) */
412 gmyth_file_set_filesize (GMYTH_FILE (transfer),
413 gmyth_string_list_get_int64 (strlist, 2));
415 gmyth_debug ("***** Received: recordernum = %d, filesize = %"
416 G_GUINT64_FORMAT "\n", priv->file_id,
417 gmyth_file_get_filesize (GMYTH_FILE (transfer)));
419 if (gmyth_file_get_filesize (GMYTH_FILE (transfer)) < 0)
422 ("Got filesize equals to %llu is lesser than 0 [invalid stream file]\n",
423 gmyth_file_get_filesize (GMYTH_FILE (transfer)));
424 g_object_unref (priv->sock);
429 _control_release_context (transfer);
432 g_object_unref (strlist);
434 if (base_str != NULL)
435 g_string_free (base_str, TRUE);
437 if (hostname != NULL)
438 g_string_free (hostname, TRUE);
444 * Receives a GObject signal coming from a LiveTV instance, all the time a
445 * program info changes.
447 * @param transfer The actual File Transfer instance.
448 * @param msg_code The MythTV backend message status code.
449 * @param live_tv A pointer to the LiveTV instance. *
452 gmyth_file_transfer_emit_program_info_changed_signal (GMythFileTransfer *
453 transfer, gint msg_code,
454 gpointer live_tv_recorder)
456 gmyth_debug ("Calling signal handler... [FILE_TRANSFER]");
458 g_signal_emit (transfer, GMYTH_FILE_TRANSFER_GET_CLASS (transfer)->program_info_changed_handler_signal_id, 0, /* details */
459 msg_code, live_tv_recorder);
464 * Checks if the actual File Transfer connection is open.
466 * @param transfer The actual File Transfer instance.
468 * @return <code>true</code>, if the File Transfer connection is opened.
471 gmyth_file_transfer_is_open (GMythFileTransfer * transfer)
473 GMythStringList *strlist;
474 GMythFileTransferPrivate *priv;
477 g_return_val_if_fail (transfer != NULL, FALSE);
479 priv = GMYTH_FILE_TRANSFER_GET_PRIVATE (transfer);
480 g_return_val_if_fail (priv->control_sock != NULL, FALSE);
481 g_return_val_if_fail (priv->sock != NULL, FALSE);
483 _control_acquire_context (transfer, TRUE);
485 strlist = gmyth_string_list_new ();
486 query = g_string_new (GMYTHTV_QUERY_HEADER);
487 g_string_append_printf (query, "%d", priv->file_id);
489 gmyth_string_list_append_string (strlist, query);
490 gmyth_string_list_append_char_array (strlist, "IS_OPEN");
492 gmyth_socket_write_stringlist (priv->control_sock, strlist);
493 gmyth_socket_read_stringlist (priv->control_sock, strlist);
495 _control_release_context (transfer);
497 g_string_free (query, TRUE);
498 g_object_unref (strlist);
500 return (strlist != NULL && gmyth_string_list_get_int (strlist, 0) == 1);
504 * Closes a remote File Transfer connection.
506 * @param transfer The actual File Transfer instance.
509 gmyth_file_transfer_close (GMythFileTransfer * transfer)
511 GMythStringList *strlist;
512 GMythFileTransferPrivate *priv;
515 g_return_if_fail (transfer != NULL);
517 priv = GMYTH_FILE_TRANSFER_GET_PRIVATE (transfer);
519 if (priv->control_sock == NULL)
522 _control_acquire_context (transfer, TRUE);
524 strlist = gmyth_string_list_new ();
525 query = g_string_new (GMYTHTV_QUERY_HEADER);
526 g_string_append_printf (query, "%d", priv->file_id);
528 gmyth_string_list_append_string (strlist, query);
529 gmyth_string_list_append_char_array (strlist, "DONE");
531 if (gmyth_socket_sendreceive_stringlist (priv->control_sock, strlist) <= 0)
533 // fixme: time out???
534 gmyth_debug ("Remote file timeout.\n");
537 g_string_free (query, TRUE);
538 g_object_unref (strlist);
542 g_object_unref (priv->sock);
546 if (priv->control_sock)
548 g_object_unref (priv->control_sock);
549 priv->control_sock = NULL;
552 _control_release_context (transfer);
556 * Do a seek operation (moves the read/write file pointer) on a remote file.
558 * @param transfer The actual File Transfer instance.
559 * @param pos The position to be moved in the remote file.
560 * @param whence Tells to what direction seek movement should be done.
562 * @return The actual position on the remote file (after seek has been done).
565 gmyth_file_transfer_seek (GMythFileTransfer * transfer, guint64 pos,
568 GMythStringList *strlist = gmyth_string_list_new ();
569 GMythFileTransferPrivate *priv;
572 g_return_val_if_fail (transfer != NULL, FALSE);
573 priv = GMYTH_FILE_TRANSFER_GET_PRIVATE (transfer);
575 g_return_val_if_fail (priv->sock != NULL, -1);
576 g_return_val_if_fail (priv->control_sock != NULL, -1);
578 strlist = gmyth_string_list_new ();
579 query = g_string_new (GMYTHTV_QUERY_HEADER);
580 g_string_append_printf (query, "%d", priv->file_id);
582 /* myth_control_acquire_context( transfer, TRUE ); */
584 gmyth_string_list_append_string (strlist, query);
585 gmyth_string_list_append_char_array (strlist, "SEEK");
586 gmyth_string_list_append_uint64 (strlist, pos);
588 gmyth_string_list_append_int (strlist, whence);
591 gmyth_string_list_append_uint64 (strlist, pos);
593 gmyth_string_list_append_uint64 (strlist,
594 gmyth_file_get_offset (GMYTH_FILE
597 gmyth_socket_sendreceive_stringlist (priv->control_sock, strlist);
599 gint64 retval = gmyth_string_list_get_int64 (strlist, 0);
600 gmyth_file_set_offset (GMYTH_FILE (transfer), retval);
601 gmyth_debug ("Got reading position pointer from the streaming = %lld\n",
604 g_object_unref (strlist);
605 g_string_free (query, TRUE);
607 /* myth_control_release_context( transfer ); */
613 * Acquire access to a remote file socket read/write pointer.
615 * @param transfer The actual File Transfer instance.
616 * @param do_wait Waits or not on a GCond, when trying to read from the remote socket.
618 * @return <code>true</code>, if the acquire had been got.
621 _control_acquire_context (GMythFileTransfer * transfer, gboolean do_wait)
624 GMythFileTransferPrivate *priv;
626 g_return_val_if_fail (transfer != NULL, FALSE);
627 priv = GMYTH_FILE_TRANSFER_GET_PRIVATE (transfer);
629 g_mutex_lock (priv->mutex);
634 * Release access to a remote file socket read/write pointer.
636 * @param transfer The actual File Transfer instance.
638 * @return <code>true</code>, if the socket read/write permissions had been releaseds.
641 _control_release_context (GMythFileTransfer * transfer)
644 GMythFileTransferPrivate *priv;
646 g_return_val_if_fail (transfer != NULL, FALSE);
647 priv = GMYTH_FILE_TRANSFER_GET_PRIVATE (transfer);
649 g_mutex_unlock (priv->mutex);
655 * Reads a block from a remote file.
657 * @param transfer The actual File Transfer instance.
658 * @param data A GByteArray instance, where all the binary data representing
659 * the remote file will be stored.
660 * @param size The block size, in bytes, to be requested from a remote file.
661 * @param read_unlimited Tells the backend to read indefinitely (LiveTV), or only
662 * gets the actual size
664 * @return The actual block size (in bytes) returned by REQUEST_BLOCK message,
668 gmyth_file_transfer_read (GMythFileTransfer * transfer, GByteArray * data,
669 gint size, gboolean read_unlimited)
672 gsize bytes_read = 0;
673 gint64 total_read = 0;
674 GMythFileReadResult retval = GMYTH_FILE_READ_OK;
675 GMythFileTransferPrivate *priv;
677 GError *error = NULL;
679 GIOChannel *io_channel;
680 GIOChannel *io_channel_control;
682 GIOCondition io_cond;
683 GIOCondition io_cond_control;
684 GIOStatus io_status = G_IO_STATUS_NORMAL;
685 GIOStatus io_status_control = G_IO_STATUS_NORMAL;
687 GMythStringList *strlist;
688 GMythStringList *ret_strlist = NULL;
692 g_return_val_if_fail (transfer != NULL, FALSE);
693 g_return_val_if_fail (data != NULL, GMYTH_FILE_READ_ERROR);
695 priv = GMYTH_FILE_TRANSFER_GET_PRIVATE (transfer);
697 strlist = gmyth_string_list_new ();
699 io_channel = priv->sock->sd_io_ch;
700 io_channel_control = priv->control_sock->sd_io_ch;
702 io_status = g_io_channel_set_encoding (io_channel, NULL, &error);
703 if (io_status == G_IO_STATUS_NORMAL)
704 gmyth_debug ("[%s] Setting encoding to binary data socket).\n",
707 io_cond = g_io_channel_get_buffer_condition (io_channel);
709 io_cond_control = g_io_channel_get_buffer_condition (io_channel);
710 if (priv->sock == NULL || (io_status == G_IO_STATUS_ERROR))
712 g_printerr ("gmyth_file_transfer_read(): Called with no raw socket.\n");
713 return GMYTH_FILE_READ_ERROR;
716 if (priv->control_sock == NULL || (io_status_control == G_IO_STATUS_ERROR))
719 ("gmyth_file_transfer_read(): Called with no control socket.\n");
720 return GMYTH_FILE_READ_ERROR;
723 query = g_string_new (GMYTHTV_QUERY_HEADER);
724 g_string_append_printf (query, "%d", priv->file_id);
725 gmyth_debug ("[%s] Transfer_query = %s\n", __FUNCTION__, query->str);
727 _control_acquire_context (transfer, TRUE);
729 gmyth_string_list_append_char_array (strlist, query->str);
730 gmyth_string_list_append_char_array (strlist, "REQUEST_BLOCK");
731 gmyth_string_list_append_int (strlist, size - total_read);
733 /* 200??? Is this a TV or a HQ data traffic? */
734 guint iter_count = 4;
740 // Request the block to the backend
741 gmyth_socket_write_stringlist (priv->control_sock, strlist);
743 if (ret_strlist != NULL)
744 g_object_unref (ret_strlist);
746 ret_strlist = gmyth_string_list_new ();
747 // Receives the backand answer
748 gmyth_socket_read_stringlist (priv->control_sock, ret_strlist);
750 if (ret_strlist != NULL && gmyth_string_list_length (ret_strlist) > 0)
752 bytes_sent = gmyth_string_list_get_int (ret_strlist, 0); // -1 on backend error
753 gmyth_debug ("[%s] got SENT buffer message = %d\n", __FUNCTION__,
757 if (read_unlimited && (bytes_sent == 0))
765 while (read_unlimited && (bytes_sent == 0) && iter_count > 0);
769 gchar *data_buffer = g_new0 (gchar, bytes_sent);
770 io_status = g_io_channel_read_chars (io_channel,
773 &bytes_read, &error);
775 if (io_status != G_IO_STATUS_NORMAL)
777 gmyth_debug ("Error on io_channel");
778 g_free (data_buffer);
779 g_object_unref (strlist);
780 retval = GMYTH_FILE_READ_ERROR;
784 /* append new data to the increasing byte array */
786 g_byte_array_append (data, (const guint8 *) data_buffer,
788 gmyth_file_set_offset (GMYTH_FILE (transfer),
789 gmyth_file_get_offset (GMYTH_FILE (transfer)) +
793 && (gmyth_file_get_filesize (GMYTH_FILE (transfer)) > 0)
794 && (gmyth_file_get_offset (GMYTH_FILE (transfer)) ==
795 gmyth_file_get_filesize (GMYTH_FILE (transfer))))
797 retval = GMYTH_FILE_READ_EOF;
801 g_free (data_buffer);
805 retval = GMYTH_FILE_READ_ERROR;
810 g_object_unref (strlist);
814 if (ret_strlist != NULL)
816 g_object_unref (ret_strlist);
820 if (read_unlimited && (bytes_sent == 0))
822 gmyth_debug ("Trying to move to the next program chain...");
823 if (priv->recorder != NULL && priv->do_next_program_chain)
825 priv->do_next_program_chain = FALSE;
826 retval = GMYTH_FILE_READ_NEXT_PROG_CHAIN;
827 GMythProgramInfo *prog_info =
828 gmyth_recorder_get_current_program_info (priv->recorder);
830 if (prog_info != NULL && prog_info->pathname != NULL
831 && strlen (prog_info->pathname->str) > 0
832 && g_ascii_strcasecmp (prog_info->pathname->str,
833 gmyth_file_get_file_name (GMYTH_FILE
837 gmyth_file_transfer_open (transfer,
838 g_strrstr (prog_info->pathname->
841 if (prog_info != NULL)
842 g_object_unref (prog_info);
845 gmyth_debug ("Cannot change to the next program info!");
847 gmyth_debug ("OK!!! MOVED to the next program info [%s]!",
848 gmyth_file_get_file_name (GMYTH_FILE (transfer)));
855 _control_release_context (transfer);
856 g_string_free (query, TRUE);
860 gmyth_debug ("Cleaning-up ERROR: %s [msg = %s, code = %d]\n",
861 __FUNCTION__, error->message, error->code);
862 g_error_free (error);
866 gmyth_file_set_offset (GMYTH_FILE (transfer),
867 gmyth_file_get_offset (GMYTH_FILE (transfer)) +
874 _file_transfer_program_info_changed (GMythFileTransfer * transfer,
875 gint msg_code, gpointer livetv_recorder)
877 GMythRecorder *recorder;
878 GMythFileTransferPrivate *priv;
880 g_return_if_fail (transfer != NULL);
882 priv = GMYTH_FILE_TRANSFER_GET_PRIVATE (transfer);
884 recorder = GMYTH_RECORDER (livetv_recorder);
886 ("Program info changed! ( file transfer orig. = %p, ptr. = [%s] )",
887 transfer, livetv_recorder != NULL ? "[NOT NULL]" : "[NULL]");
889 if (NULL != recorder)
892 ("YES, the requested program info movement on the LiveTV transfer is authentical!");
895 priv = GMYTH_FILE_TRANSFER_GET_PRIVATE (transfer);
896 g_object_ref (recorder);
897 priv->recorder = recorder;
898 priv->do_next_program_chain = TRUE;
902 * Sets the timeout flag of a file being transfered.
904 * @param transfer The actual File Transfer instance.
905 * @param fast If this is <code>true</code>, sets the remote timeout to be as fast
908 * @return <code>true</code>, if the acquire had been got.
911 gmyth_file_transfer_settimeout (GMythFileTransfer * transfer, gboolean fast)
913 GMythFileTransferPrivate *priv;
914 GMythStringList *strlist = NULL;
916 g_return_val_if_fail (transfer != NULL, FALSE);
918 priv = GMYTH_FILE_TRANSFER_GET_PRIVATE (transfer);
920 g_return_val_if_fail (priv->sock != NULL, FALSE);
921 g_return_val_if_fail (priv->control_sock != NULL, FALSE);
923 _control_acquire_context (transfer, TRUE);
925 strlist = gmyth_string_list_new ();
926 gmyth_string_list_append_char_array (strlist, GMYTHTV_QUERY_HEADER);
927 gmyth_string_list_append_char_array (strlist, "SET_TIMEOUT");
928 gmyth_string_list_append_int (strlist, fast);
930 gint strlist_len = gmyth_socket_sendreceive_stringlist (priv->control_sock,
934 gmyth_debug ("Yes, timeout was changed: %s.",
935 gmyth_string_list_get_char_array (strlist, 0));
937 gmyth_debug ("Timeout cannot be changed!");
939 _control_release_context (transfer);
941 gmyth_debug ("%s setting timeout flag of this file transfer = %s\n",
942 strlist_len > 0 ? "Yes," : "NOT", fast ? "FAST" : "NOT FAST");
944 g_object_unref (strlist);
950 * Gets the actual file size of the binary content.
952 * @param transfer The actual File Transfer instance.
954 * @return The actual file size in bytes.
957 gmyth_file_transfer_get_filesize (GMythFileTransfer * transfer)
961 g_return_val_if_fail (transfer != NULL, 0);
963 g_object_get (GMYTH_FILE (transfer), "file-size", &filesize, NULL);