[svn r865] patch by Tim-Philipp M?ller, release gmyth contex if connection error
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>
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU Lesser General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU Lesser General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 * GStreamer MythTV plug-in properties:
28 * - location (backend server hostname/URL) [ex.: myth://192.168.1.73:28722/1000_1092091.nuv]
29 * - path (qurl - remote file to be opened)
37 #include "gmyth_file_transfer.h"
38 #include "gmyth_recorder.h"
39 #include "gmyth_util.h"
40 #include "gmyth_socket.h"
41 #include "gmyth_stringlist.h"
42 #include "gmyth_debug.h"
43 #include "gmyth_uri.h"
44 #include "gmyth_marshal.h"
49 #include <arpa/inet.h>
50 #include <sys/types.h>
51 #include <sys/socket.h>
57 #define GMYTHTV_QUERY_HEADER "QUERY_FILETRANSFER "
60 #define GMYTH_FILE_TRANSFER_GET_PRIVATE(obj) \
61 (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GMYTH_FILE_TRANSFER_TYPE, GMythFileTransferPrivate))
63 enum myth_sock_types {
64 GMYTH_PLAYBACK_TYPE = 0,
66 GMYTH_FILETRANSFER_TYPE,
70 struct _GMythFileTransferPrivate {
71 GMythRecorder *recorder;
73 gboolean do_next_program_chain;
78 * MythTV version number
85 GMythSocket *control_sock;
91 static void gmyth_file_transfer_class_init(GMythFileTransferClass *
93 static void gmyth_file_transfer_init(GMythFileTransfer * object);
94 static void gmyth_file_transfer_dispose(GObject * object);
95 static void gmyth_file_transfer_finalize(GObject * object);
96 static void _file_transfer_program_info_changed(GMythFileTransfer *
101 static gboolean _connect_to_backend(GMythFileTransfer * transfer);
102 static gboolean _control_acquire_context(GMythFileTransfer * transfer,
104 static gboolean _control_release_context(GMythFileTransfer * transfer);
106 G_DEFINE_TYPE(GMythFileTransfer, gmyth_file_transfer, GMYTH_FILE_TYPE)
107 static void gmyth_file_transfer_class_init(GMythFileTransferClass *
110 GObjectClass *gobject_class;
111 GMythFileTransferClass *gtransfer_class;
113 gobject_class = (GObjectClass *) klass;
114 gtransfer_class = (GMythFileTransferClass *) gobject_class;
116 gobject_class->dispose = gmyth_file_transfer_dispose;
117 gobject_class->finalize = gmyth_file_transfer_finalize;
119 g_type_class_add_private(gobject_class,
120 sizeof(GMythFileTransferPrivate));
122 gtransfer_class->program_info_changed_handler =
123 _file_transfer_program_info_changed;
125 gtransfer_class->program_info_changed_handler_signal_id =
126 g_signal_new("program-info-changed",
127 G_TYPE_FROM_CLASS(gtransfer_class),
128 G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE |
129 G_SIGNAL_NO_HOOKS, 0, NULL, NULL,
130 gmyth_marshal_VOID__INT_POINTER, G_TYPE_NONE, 2,
131 G_TYPE_INT, G_TYPE_POINTER);
136 gmyth_file_transfer_init(GMythFileTransfer * transfer)
138 g_return_if_fail(transfer != NULL);
140 transfer->priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer);
141 transfer->priv->mutex = g_mutex_new();
143 g_signal_connect(G_OBJECT(transfer), "program-info-changed",
144 (GCallback) (GMYTH_FILE_TRANSFER_GET_CLASS
145 (transfer)->program_info_changed_handler),
150 gmyth_file_transfer_dispose(GObject * object)
152 GMythFileTransferPrivate *priv;
153 GMythFileTransfer *transfer = GMYTH_FILE_TRANSFER(object);
155 g_return_if_fail(transfer != NULL);
157 priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer);
159 if (priv->disposed) {
161 * If dispose did already run, return.
167 * Make sure dispose does not run twice.
169 priv->disposed = TRUE;
171 if (priv->mutex != NULL) {
172 g_mutex_free(priv->mutex);
176 if (priv->control_sock != NULL) {
177 g_object_unref(priv->control_sock);
178 priv->control_sock = NULL;
181 if (priv->sock != NULL) {
182 g_object_unref(priv->sock);
186 if (priv->recorder != NULL) {
187 g_object_unref(priv->recorder);
188 priv->recorder = NULL;
191 G_OBJECT_CLASS(gmyth_file_transfer_parent_class)->dispose(object);
195 gmyth_file_transfer_finalize(GObject * object)
197 g_signal_handlers_destroy(object);
199 G_OBJECT_CLASS(gmyth_file_transfer_parent_class)->finalize(object);
203 * Creates a new instance of GMythFileTransfer.
205 * @param backend_info The BackendInfo instance, with all the MythTV network
206 * configuration data.
208 * @return a new instance of the File Transfer.
211 gmyth_file_transfer_new(GMythBackendInfo * backend_info)
213 GMythFileTransfer *transfer = g_object_new(GMYTH_FILE_TRANSFER_TYPE,
218 // GValue val = {0,};
219 // backend_info = g_object_ref( backend_info );
220 gmyth_debug("Creating FileTransfer BackendInfo hostname = %s",
221 gmyth_backend_info_get_hostname(backend_info));
222 // GMythBackendInfo *backend_info = gmyth_backend_info_new_with_uri
224 // g_value_init (&val, G_TYPE_OBJECT);
225 // g_value_set_object (&val, backend_info);
226 // g_object_set (G_OBJECT (transfer), "backend-info", &val, NULL);
232 gmyth_file_transfer_get_file_name(GMythFileTransfer * transfer)
236 g_object_get(G_OBJECT(transfer), "filename", &filename, NULL);
242 * Creates a new instance of GMythFileTransfer.
244 * @param uri_str The URI poiting to the MythTV backend server.
246 * @return a new instance of the File Transfer.
249 gmyth_file_transfer_new_with_uri(const gchar * uri_str)
251 GMythFileTransfer *transfer =
252 GMYTH_FILE_TRANSFER(g_object_new(GMYTH_FILE_TRANSFER_TYPE, NULL));
253 gmyth_debug("URI str = %s", uri_str);
254 // GMythBackendInfo *backend_info = gmyth_backend_info_new_with_uri
257 g_value_init(&val, G_TYPE_OBJECT);
258 g_value_set_object(&val, gmyth_backend_info_new_with_uri(uri_str));
259 g_object_set(G_OBJECT(transfer), "backend-info", &val, NULL);
265 * Open a File Transfer connection in order to get a remote file.
267 * @param transfer The actual File Transfer instance.
268 * @param filename The file name of the remote file to be transferred to the client.
270 * @return <code>true</code>, if the connection opening had been done successfully.
273 gmyth_file_transfer_open(GMythFileTransfer * transfer,
274 const gchar * filename)
277 GMythFileTransferPrivate *priv;
279 g_return_val_if_fail(transfer != NULL, FALSE);
280 g_return_val_if_fail(filename != NULL && strlen(filename) > 0, FALSE);
282 priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer);
284 gmyth_debug("Opening the FileTransfer... (%s)", filename);
286 g_object_set(GMYTH_FILE(transfer), "filename", filename, NULL);
289 * configure the control socket
291 if (TRUE /* priv->control_sock == NULL */ ) {
292 if (!_connect_to_backend(transfer)) {
293 gmyth_debug("Connection to backend failed (Control Socket).");
297 if (priv->do_next_program_chain) {
298 priv->do_next_program_chain = FALSE; // fixme
300 ("New file available before the current file was opened");
301 GMythProgramInfo *prog_info =
302 gmyth_recorder_get_current_program_info(priv->recorder);
304 if (prog_info != NULL && prog_info->pathname != NULL
305 && strlen(prog_info->pathname->str) > 0
306 && g_ascii_strcasecmp(prog_info->pathname->str,
307 gmyth_file_get_file_name(GMYTH_FILE
311 gmyth_file_transfer_open(transfer,
312 g_strrstr(prog_info->
316 if (prog_info != NULL)
317 g_object_unref(prog_info);
320 gmyth_debug("Cannot change to the next program info!");
322 gmyth_debug("OK!!! MOVED to the next program info [%s]!",
323 gmyth_file_get_file_name(GMYTH_FILE
328 ("None new file found. We continue with the same file opened before");
332 gmyth_debug("Remote transfer control socket already created.");
335 gmyth_debug("Got file with size = %lld.\n",
336 gmyth_file_get_filesize(GMYTH_FILE(transfer)));
342 * Connect a File Transfer binary client socket to a remote file.
344 * @param transfer The actual File Transfer instance.
346 * @return <code>true</code>, if the connection had been configured successfully.
349 _connect_to_backend(GMythFileTransfer * transfer)
351 GString *base_str = NULL;
352 GString *hostname = NULL;
353 GMythStringList *strlist = NULL;
355 GMythFileTransferPrivate *priv;
356 GMythBackendInfo *backend_info;
358 g_return_val_if_fail(transfer != NULL, FALSE);
360 g_object_get(GMYTH_FILE(transfer), "backend-info", &backend_info,
363 priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer);
364 _control_acquire_context(transfer, TRUE);
367 * Creates the control socket
370 if (priv->control_sock != NULL) {
371 g_object_unref(priv->control_sock);
372 priv->control_sock = NULL;
375 base_str = g_string_new("");
377 priv->control_sock = gmyth_socket_new();
378 // Connects the socket, send Mythtv ANN command and verify Mythtv
380 if (!gmyth_socket_connect_to_backend(priv->control_sock,
381 backend_info->hostname,
382 backend_info->port, TRUE)) {
384 _control_release_context(transfer);
385 g_object_unref(priv->control_sock);
386 priv->control_sock = NULL;
391 * Creates the data socket
393 if (priv->sock != NULL) {
394 g_object_unref(priv->sock);
398 priv->sock = gmyth_socket_new();
399 gmyth_socket_connect(priv->sock, backend_info->hostname,
401 gmyth_debug("Connecting file transfer... (%s, %d)",
402 backend_info->hostname, backend_info->port);
404 strlist = gmyth_string_list_new();
405 hostname = gmyth_socket_get_local_hostname();
406 gmyth_debug("[%s] MythTV version (from backend) = %d.\n", __FUNCTION__,
407 priv->control_sock->mythtv_version);
408 if (priv->control_sock->mythtv_version > 26)
409 g_string_printf(base_str, "ANN FileTransfer %s 1 -1",
412 g_string_printf(base_str, "ANN FileTransfer %s", hostname->str);
414 gmyth_string_list_append_string(strlist, base_str);
415 gmyth_string_list_append_char_array(strlist,
416 gmyth_file_get_file_name(GMYTH_FILE
419 gmyth_socket_write_stringlist(priv->sock, strlist);
422 * MONITOR Handler - DVB TV Chain update messages!!!
425 gmyth_socket_read_stringlist(priv->sock, strlist);
428 * file identification used in future file transfer requests to
431 priv->file_id = gmyth_string_list_get_int(strlist, 1);
434 * Myth URI stream file size - decoded using two 8-bytes sequences (64
435 * bits/long long types)
437 gmyth_file_set_filesize(GMYTH_FILE(transfer),
438 gmyth_string_list_get_int64(strlist, 2));
440 gmyth_debug("***** Received: recordernum = %d, filesize = %"
441 G_GUINT64_FORMAT "\n", priv->file_id,
442 gmyth_file_get_filesize(GMYTH_FILE(transfer)));
444 if (gmyth_file_get_filesize(GMYTH_FILE(transfer)) < 0) {
446 ("Got filesize equals to %llu is lesser than 0 [invalid stream file]\n",
447 gmyth_file_get_filesize(GMYTH_FILE(transfer)));
448 g_object_unref(priv->sock);
453 _control_release_context(transfer);
456 g_object_unref(strlist);
458 if (base_str != NULL)
459 g_string_free(base_str, TRUE);
461 if (hostname != NULL)
462 g_string_free(hostname, TRUE);
468 * Receives a GObject signal coming from a LiveTV instance, all the time a
469 * program info changes.
471 * @param transfer The actual File Transfer instance.
472 * @param msg_code The MythTV backend message status code.
473 * @param live_tv A pointer to the LiveTV instance. *
476 gmyth_file_transfer_emit_program_info_changed_signal(GMythFileTransfer *
482 gmyth_debug("Calling signal handler... [FILE_TRANSFER]");
484 g_signal_emit(transfer, GMYTH_FILE_TRANSFER_GET_CLASS(transfer)->program_info_changed_handler_signal_id, 0, /* details
486 msg_code, live_tv_recorder);
491 * Checks if the actual File Transfer connection is open.
493 * @param transfer The actual File Transfer instance.
495 * @return <code>true</code>, if the File Transfer connection is opened.
498 gmyth_file_transfer_is_open(GMythFileTransfer * transfer)
500 GMythStringList *strlist;
501 GMythFileTransferPrivate *priv;
504 g_return_val_if_fail(transfer != NULL, FALSE);
506 priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer);
507 g_return_val_if_fail(priv->control_sock != NULL, FALSE);
508 g_return_val_if_fail(priv->sock != NULL, FALSE);
510 _control_acquire_context(transfer, TRUE);
512 strlist = gmyth_string_list_new();
513 query = g_string_new(GMYTHTV_QUERY_HEADER);
514 g_string_append_printf(query, "%d", priv->file_id);
516 gmyth_string_list_append_string(strlist, query);
517 gmyth_string_list_append_char_array(strlist, "IS_OPEN");
519 gmyth_socket_write_stringlist(priv->control_sock, strlist);
520 gmyth_socket_read_stringlist(priv->control_sock, strlist);
522 _control_release_context(transfer);
524 g_string_free(query, TRUE);
525 g_object_unref(strlist);
527 return (strlist != NULL && gmyth_string_list_get_int(strlist, 0) == 1);
531 * Closes a remote File Transfer connection.
533 * @param transfer The actual File Transfer instance.
536 gmyth_file_transfer_close(GMythFileTransfer * transfer)
538 GMythStringList *strlist;
539 GMythFileTransferPrivate *priv;
542 g_return_if_fail(transfer != NULL);
544 priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer);
546 if (priv->control_sock == NULL)
549 _control_acquire_context(transfer, TRUE);
551 strlist = gmyth_string_list_new();
552 query = g_string_new(GMYTHTV_QUERY_HEADER);
553 g_string_append_printf(query, "%d", priv->file_id);
555 gmyth_string_list_append_string(strlist, query);
556 gmyth_string_list_append_char_array(strlist, "DONE");
558 if (gmyth_socket_sendreceive_stringlist(priv->control_sock, strlist) <=
560 // fixme: time out???
561 gmyth_debug("Remote file timeout.\n");
564 g_string_free(query, TRUE);
565 g_object_unref(strlist);
568 g_object_unref(priv->sock);
572 if (priv->control_sock) {
573 g_object_unref(priv->control_sock);
574 priv->control_sock = NULL;
577 _control_release_context(transfer);
581 * Do a seek operation (moves the read/write file pointer) on a remote file.
583 * @param transfer The actual File Transfer instance.
584 * @param pos The position to be moved in the remote file.
585 * @param whence Tells to what direction seek movement should be done.
587 * @return The actual position on the remote file (after seek has been done).
590 gmyth_file_transfer_seek(GMythFileTransfer * transfer, guint64 pos,
593 GMythStringList *strlist = gmyth_string_list_new();
594 GMythFileTransferPrivate *priv;
597 g_return_val_if_fail(transfer != NULL, FALSE);
598 priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer);
600 g_return_val_if_fail(priv->sock != NULL, -1);
601 g_return_val_if_fail(priv->control_sock != NULL, -1);
603 strlist = gmyth_string_list_new();
604 query = g_string_new(GMYTHTV_QUERY_HEADER);
605 g_string_append_printf(query, "%d", priv->file_id);
608 * myth_control_acquire_context( transfer, TRUE );
611 gmyth_string_list_append_string(strlist, query);
612 gmyth_string_list_append_char_array(strlist, "SEEK");
613 gmyth_string_list_append_uint64(strlist, pos);
615 gmyth_string_list_append_int(strlist, whence);
618 gmyth_string_list_append_uint64(strlist, pos);
620 gmyth_string_list_append_uint64(strlist,
621 gmyth_file_get_offset(GMYTH_FILE
624 gmyth_socket_sendreceive_stringlist(priv->control_sock, strlist);
626 gint64 retval = gmyth_string_list_get_int64(strlist, 0);
628 gmyth_file_set_offset(GMYTH_FILE(transfer), retval);
629 gmyth_debug("Got reading position pointer from the streaming = %lld\n",
632 g_object_unref(strlist);
633 g_string_free(query, TRUE);
636 * myth_control_release_context( transfer );
643 * Acquire access to a remote file socket read/write pointer.
645 * @param transfer The actual File Transfer instance.
646 * @param do_wait Waits or not on a GCond, when trying to read from the remote socket.
648 * @return <code>true</code>, if the acquire had been got.
651 _control_acquire_context(GMythFileTransfer * transfer, gboolean do_wait)
654 GMythFileTransferPrivate *priv;
656 g_return_val_if_fail(transfer != NULL, FALSE);
657 priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer);
659 g_mutex_lock(priv->mutex);
664 * Release access to a remote file socket read/write pointer.
666 * @param transfer The actual File Transfer instance.
668 * @return <code>true</code>, if the socket read/write permissions had been releaseds.
671 _control_release_context(GMythFileTransfer * transfer)
674 GMythFileTransferPrivate *priv;
676 g_return_val_if_fail(transfer != NULL, FALSE);
677 priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer);
679 g_mutex_unlock(priv->mutex);
685 * Reads a block from a remote file.
687 * @param transfer The actual File Transfer instance.
688 * @param data A GByteArray instance, where all the binary data representing
689 * the remote file will be stored.
690 * @param size The block size, in bytes, to be requested from a remote file.
691 * @param read_unlimited Tells the backend to read indefinitely (LiveTV), or only
692 * gets the actual size
694 * @return The actual block size (in bytes) returned by REQUEST_BLOCK message,
698 gmyth_file_transfer_read(GMythFileTransfer * transfer, GByteArray * data,
699 gint size, gboolean read_unlimited)
702 gsize bytes_read = 0;
703 gint64 total_read = 0;
704 GMythFileReadResult retval = GMYTH_FILE_READ_OK;
705 GMythFileTransferPrivate *priv;
707 GError *error = NULL;
709 GIOChannel *io_channel;
710 GIOChannel *io_channel_control;
712 GIOCondition io_cond;
713 GIOCondition io_cond_control;
714 GIOStatus io_status = G_IO_STATUS_NORMAL;
715 GIOStatus io_status_control = G_IO_STATUS_NORMAL;
717 GMythStringList *strlist;
718 GMythStringList *ret_strlist = NULL;
722 g_return_val_if_fail(transfer != NULL, FALSE);
723 g_return_val_if_fail(data != NULL, GMYTH_FILE_READ_ERROR);
725 priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer);
727 strlist = gmyth_string_list_new();
729 io_channel = priv->sock->sd_io_ch;
730 io_channel_control = priv->control_sock->sd_io_ch;
732 io_status = g_io_channel_set_encoding(io_channel, NULL, &error);
733 if (io_status == G_IO_STATUS_NORMAL)
734 gmyth_debug("[%s] Setting encoding to binary data socket).\n",
737 io_cond = g_io_channel_get_buffer_condition(io_channel);
739 io_cond_control = g_io_channel_get_buffer_condition(io_channel);
740 if (priv->sock == NULL || (io_status == G_IO_STATUS_ERROR)) {
742 ("gmyth_file_transfer_read(): Called with no raw socket.\n");
743 return GMYTH_FILE_READ_ERROR;
746 if (priv->control_sock == NULL
747 || (io_status_control == G_IO_STATUS_ERROR)) {
749 ("gmyth_file_transfer_read(): Called with no control socket.\n");
750 return GMYTH_FILE_READ_ERROR;
753 query = g_string_new(GMYTHTV_QUERY_HEADER);
754 g_string_append_printf(query, "%d", priv->file_id);
755 gmyth_debug("[%s] Transfer_query = %s\n", __FUNCTION__, query->str);
757 _control_acquire_context(transfer, TRUE);
759 gmyth_string_list_append_char_array(strlist, query->str);
760 gmyth_string_list_append_char_array(strlist, "REQUEST_BLOCK");
761 gmyth_string_list_append_int(strlist, size - total_read);
763 guint iter_count = 3;
768 // Request the block to the backend
769 gmyth_socket_write_stringlist(priv->control_sock, strlist);
771 if (ret_strlist != NULL)
772 g_object_unref(ret_strlist);
774 ret_strlist = gmyth_string_list_new();
775 // Receives the backand answer
776 gmyth_socket_read_stringlist(priv->control_sock, ret_strlist);
778 if (ret_strlist != NULL
779 && gmyth_string_list_length(ret_strlist) > 0) {
780 bytes_sent = gmyth_string_list_get_int(ret_strlist, 0); // -1
784 gmyth_debug("[%s] got SENT buffer message = %d\n",
785 __FUNCTION__, bytes_sent);
788 if (read_unlimited && (bytes_sent == 0)) {
795 while (read_unlimited && (bytes_sent == 0) && iter_count > 0);
797 if (bytes_sent > 0) {
798 gchar *data_buffer = g_new0(gchar, bytes_sent);
800 io_status = g_io_channel_read_chars(io_channel,
803 &bytes_read, &error);
805 if (io_status != G_IO_STATUS_NORMAL) {
806 gmyth_debug("Error on io_channel");
808 g_object_unref(strlist);
809 retval = GMYTH_FILE_READ_ERROR;
814 * append new data to the increasing byte array
817 g_byte_array_append(data, (const guint8 *) data_buffer,
819 gmyth_file_set_offset(GMYTH_FILE(transfer),
820 gmyth_file_get_offset(GMYTH_FILE(transfer)) +
824 && (gmyth_file_get_filesize(GMYTH_FILE(transfer)) > 0)
825 && (gmyth_file_get_offset(GMYTH_FILE(transfer)) ==
826 gmyth_file_get_filesize(GMYTH_FILE(transfer)))) {
827 retval = GMYTH_FILE_READ_EOF;
833 retval = GMYTH_FILE_READ_ERROR;
836 if (strlist != NULL) {
837 g_object_unref(strlist);
841 if (ret_strlist != NULL) {
842 g_object_unref(ret_strlist);
846 if (read_unlimited && (bytes_sent == 0)) {
847 gmyth_debug("Trying to move to the next program chain...");
848 if (priv->recorder != NULL && priv->do_next_program_chain) {
849 priv->do_next_program_chain = FALSE;
850 retval = GMYTH_FILE_READ_NEXT_PROG_CHAIN;
851 GMythProgramInfo *prog_info =
852 gmyth_recorder_get_current_program_info(priv->recorder);
855 ("Comparing if the current prog. info = %s [strlen == %d] is equals to "
856 " %s [strlen == %d]...", prog_info->pathname->str,
857 strlen(prog_info->pathname->str),
858 gmyth_file_get_file_name(GMYTH_FILE(transfer)),
859 strlen(gmyth_file_get_file_name(GMYTH_FILE(transfer))));
861 if (prog_info != NULL && prog_info->pathname != NULL
862 && strlen(prog_info->pathname->str) > 0
864 g_strstr_len(prog_info->pathname->str,
865 strlen(prog_info->pathname->str),
866 gmyth_file_get_file_name(GMYTH_FILE
869 * releasing context got at this function starting...
871 _control_release_context(transfer);
873 gmyth_file_transfer_open(transfer,
874 g_strrstr(prog_info->
877 _control_acquire_context(transfer, TRUE);
879 * acquiring context released at this function stopping...
882 if (prog_info != NULL)
883 g_object_unref(prog_info);
886 gmyth_debug("Cannot change to the next program info!");
889 ("OK!!! MOVED to the next program info [%s]!",
890 gmyth_file_get_file_name(GMYTH_FILE(transfer)));
901 _control_release_context(transfer);
902 g_string_free(query, TRUE);
905 gmyth_debug("Cleaning-up ERROR: %s [msg = %s, code = %d]\n",
906 __FUNCTION__, error->message, error->code);
911 gmyth_file_set_offset(GMYTH_FILE(transfer),
912 gmyth_file_get_offset(GMYTH_FILE
920 _file_transfer_program_info_changed(GMythFileTransfer * transfer,
922 gpointer livetv_recorder)
924 GMythRecorder *recorder;
925 GMythFileTransferPrivate *priv;
927 g_return_if_fail(transfer != NULL);
929 priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer);
931 recorder = GMYTH_RECORDER(livetv_recorder);
933 ("Program info changed! ( file transfer orig. = %p, ptr. = [%s] )",
934 transfer, livetv_recorder != NULL ? "[NOT NULL]" : "[NULL]");
936 if (NULL != recorder) {
938 ("YES, the requested program info movement on the LiveTV transfer is authentical!");
941 priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer);
942 g_object_ref(recorder);
943 priv->recorder = recorder;
944 priv->do_next_program_chain = TRUE;
948 * Sets the timeout flag of a file being transfered.
950 * @param transfer The actual File Transfer instance.
951 * @param fast If this is <code>true</code>, sets the remote timeout to be as fast
954 * @return <code>true</code>, if the acquire had been got.
957 gmyth_file_transfer_settimeout(GMythFileTransfer * transfer, gboolean fast)
959 GMythFileTransferPrivate *priv;
960 GMythStringList *strlist = NULL;
962 g_return_val_if_fail(transfer != NULL, FALSE);
964 priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer);
966 g_return_val_if_fail(priv->sock != NULL, FALSE);
967 g_return_val_if_fail(priv->control_sock != NULL, FALSE);
969 _control_acquire_context(transfer, TRUE);
971 strlist = gmyth_string_list_new();
972 gmyth_string_list_append_char_array(strlist, GMYTHTV_QUERY_HEADER);
973 gmyth_string_list_append_char_array(strlist, "SET_TIMEOUT");
974 gmyth_string_list_append_int(strlist, fast);
977 gmyth_socket_sendreceive_stringlist(priv->control_sock,
981 gmyth_debug("Yes, timeout was changed: %s.",
982 gmyth_string_list_get_char_array(strlist, 0));
984 gmyth_debug("Timeout cannot be changed!");
986 _control_release_context(transfer);
988 gmyth_debug("%s setting timeout flag of this file transfer = %s\n",
989 strlist_len > 0 ? "Yes," : "NOT",
990 fast ? "FAST" : "NOT FAST");
992 g_object_unref(strlist);
998 * Gets the actual file size of the binary content.
1000 * @param transfer The actual File Transfer instance.
1002 * @return The actual file size in bytes.
1005 gmyth_file_transfer_get_filesize(GMythFileTransfer * transfer)
1009 g_return_val_if_fail(transfer != NULL, 0);
1011 g_object_get(GMYTH_FILE(transfer), "file-size", &filesize, NULL);