# HG changeset patch # User renatofilho # Date 1175718967 -3600 # Node ID f92a59c9a9a5fefa81f65201a30a48bb5b3cdbb5 # Parent 9900800a8dd6270546d6eed025f14ea3d379224b [svn r505] fixed gmyth_file_transfer class diff -r 9900800a8dd6 -r f92a59c9a9a5 gmyth/src/gmyth_file_transfer.c --- a/gmyth/src/gmyth_file_transfer.c Wed Apr 04 21:18:43 2007 +0100 +++ b/gmyth/src/gmyth_file_transfer.c Wed Apr 04 21:36:07 2007 +0100 @@ -57,27 +57,9 @@ #define GMYTHTV_QUERY_HEADER "QUERY_FILETRANSFER " -/* default values to the file transfer parameters */ -#define GMYTHTV_USER_READ_AHEAD TRUE -#define GMYTHTV_RETRIES -1 -#define GMYTHTV_FILE_SIZE 0 -#define GMYTHTV_BUFFER_SIZE 64*1024 - -#define GMYTHTV_VERSION 30 - -#define GMYTHTV_TRANSFER_MAX_WAITS 700 - -#ifdef GMYTHTV_ENABLE_DEBUG -#define GMYTHTV_ENABLE_DEBUG 1 -#else -#undef GMYTHTV_ENABLE_DEBUG -#endif - -/* this NDEBUG is to maintain compatibility with GMyth library */ -#ifndef NDEBUG -#define GMYTHTV_ENABLE_DEBUG 1 -#endif +#define GMYTH_FILE_TRANSFER_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GMYTH_FILE_TRANSFER_TYPE, GMythFileTransferPrivate)) enum myth_sock_types { GMYTH_PLAYBACK_TYPE = 0, @@ -86,134 +68,135 @@ GMYTH_RINGBUFFER_TYPE }; -#define GMYTH_FILE_TRANSFER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GMYTH_FILE_TRANSFER_TYPE, GMythFileTransferPrivate)) - struct _GMythFileTransferPrivate { GMythRecorder *recorder; gboolean do_next_program_chain; gboolean disposed; gboolean livetv_wait; + gint64 offset; + guint64 filesize; + + /* Myth URI structure */ + gchar *filename; + GMythBackendInfo *backend_info; + + /* MythTV version number */ + gint mythtv_version; + + /* socket descriptors */ + GMythSocket *control_sock; + GMythSocket *sock; + GMutex *mutex; + gint file_id; }; static void gmyth_file_transfer_class_init (GMythFileTransferClass *klass); static void gmyth_file_transfer_init (GMythFileTransfer *object); - -static void gmyth_file_transfer_dispose (GObject *object); -static void gmyth_file_transfer_finalize (GObject *object); - -static void gmyth_file_transfer_program_info_changed( GMythFileTransfer *transfer, - gint msg_code, gpointer livetv_recorder ); - -static gboolean gmyth_connect_to_backend (GMythFileTransfer *transfer); - -void gmyth_file_transfer_close( GMythFileTransfer *transfer ); - -static gboolean myth_control_acquire_context( GMythFileTransfer *transfer, gboolean do_wait ); - -static gboolean myth_control_release_context( GMythFileTransfer *transfer ); +static void gmyth_file_transfer_dispose (GObject *object); +static void gmyth_file_transfer_finalize (GObject *object); +static void _file_transfer_program_info_changed(GMythFileTransfer *transfer, + gint msg_code, gpointer livetv_recorder); +static gboolean _connect_to_backend (GMythFileTransfer *transfer); +static gboolean _control_acquire_context (GMythFileTransfer *transfer, gboolean do_wait); +static gboolean _control_release_context (GMythFileTransfer *transfer); G_DEFINE_TYPE(GMythFileTransfer, gmyth_file_transfer, G_TYPE_OBJECT) static void gmyth_file_transfer_class_init (GMythFileTransferClass *klass) { - GObjectClass *gobject_class; - GMythFileTransferClass *gtransfer_class; + GObjectClass *gobject_class; + GMythFileTransferClass *gtransfer_class; - gobject_class = (GObjectClass *) klass; - gtransfer_class = (GMythFileTransferClass *) gobject_class; + gobject_class = (GObjectClass *) klass; + gtransfer_class = (GMythFileTransferClass *) gobject_class; - gobject_class->dispose = gmyth_file_transfer_dispose; - gobject_class->finalize = gmyth_file_transfer_finalize; + gobject_class->dispose = gmyth_file_transfer_dispose; + gobject_class->finalize = gmyth_file_transfer_finalize; - g_type_class_add_private (gobject_class, sizeof (GMythFileTransferPrivate)); + g_type_class_add_private (gobject_class, sizeof (GMythFileTransferPrivate)); - gtransfer_class->program_info_changed_handler = gmyth_file_transfer_program_info_changed; + gtransfer_class->program_info_changed_handler = _file_transfer_program_info_changed; gtransfer_class->program_info_changed_handler_signal_id = - g_signal_new ( "program-info-changed", - G_TYPE_FROM_CLASS (gtransfer_class), - G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS, - 0, - NULL, - NULL, - gmyth_marshal_VOID__INT_POINTER, - G_TYPE_NONE, - 2, - G_TYPE_INT, - G_TYPE_POINTER ); + g_signal_new ("program-info-changed", + G_TYPE_FROM_CLASS (gtransfer_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS, + 0, + NULL, + NULL, + gmyth_marshal_VOID__INT_POINTER, + G_TYPE_NONE, + 2, + G_TYPE_INT, + G_TYPE_POINTER ); } static void gmyth_file_transfer_init (GMythFileTransfer *transfer) { - g_return_if_fail( transfer != NULL ); + GMythFileTransferPrivate *priv; + g_return_if_fail( transfer != NULL ); - transfer->readposition = 0; - transfer->filesize = GMYTHTV_FILE_SIZE; + priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer); + priv->mutex = g_mutex_new(); - transfer->priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer); - - transfer->priv->do_next_program_chain = FALSE; - transfer->priv->recorder = NULL; - - transfer->control_sock = NULL; - transfer->sock = NULL; - - transfer->mutex = g_mutex_new(); - - g_signal_connect ( G_OBJECT (transfer), "program-info-changed", - (GCallback)(GMYTH_FILE_TRANSFER_GET_CLASS(transfer)->program_info_changed_handler), - NULL ); - + g_signal_connect ( G_OBJECT (transfer), "program-info-changed", + (GCallback)(GMYTH_FILE_TRANSFER_GET_CLASS(transfer)->program_info_changed_handler), + NULL ); } static void gmyth_file_transfer_dispose (GObject *object) { + GMythFileTransferPrivate *priv; GMythFileTransfer *transfer = GMYTH_FILE_TRANSFER (object); - if (transfer->priv->disposed) { + g_return_if_fail( transfer != NULL ); + + priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer); + + if (priv->disposed) { /* If dispose did already run, return. */ return; } /* Make sure dispose does not run twice. */ - transfer->priv->disposed = TRUE; + priv->disposed = TRUE; - if ( transfer->mutex != NULL ) { - g_mutex_free( transfer->mutex ); - transfer->mutex = NULL; - } - - if ( transfer->control_sock != NULL ) { - g_object_unref( transfer->control_sock ); - transfer->control_sock = NULL; - } - - if ( transfer->sock != NULL ) { - g_object_unref( transfer->sock ); - transfer->sock = NULL; - } - - if ( transfer->backend_info != NULL ) { - g_object_unref( transfer->backend_info ); - transfer->backend_info = NULL; - } - - if ( transfer->priv->recorder != NULL ) { - g_object_unref( transfer->priv->recorder ); - transfer->priv->recorder = NULL; - } - - if ( transfer->filename != NULL ) { - g_free( transfer->filename ); - transfer->filename = NULL; - } + if (priv->mutex != NULL ) { + g_mutex_free (priv->mutex ); + priv->mutex = NULL; + } - G_OBJECT_CLASS (gmyth_file_transfer_parent_class)->dispose (object); + if (priv->control_sock != NULL ) { + g_object_unref (priv->control_sock ); + priv->control_sock = NULL; + } + + if (priv->sock != NULL ) { + g_object_unref (priv->sock); + priv->sock = NULL; + } + + if (priv->backend_info != NULL ) { + g_object_unref (priv->backend_info ); + priv->backend_info = NULL; + } + + if (priv->recorder != NULL ) { + g_object_unref (priv->recorder ); + priv->recorder = NULL; + } + + if (priv->filename != NULL ) { + g_free (priv->filename ); + priv->filename = NULL; + } + + G_OBJECT_CLASS (gmyth_file_transfer_parent_class)->dispose (object); } static void @@ -236,11 +219,19 @@ gmyth_file_transfer_new (GMythBackendInfo *backend_info) { GMythFileTransfer *transfer = GMYTH_FILE_TRANSFER (g_object_new (GMYTH_FILE_TRANSFER_TYPE, NULL)); + GMythFileTransferPrivate *priv = GMYTH_FILE_TRANSFER_GET_PRIVATE (transfer); - transfer->backend_info = backend_info; - g_object_ref (transfer->backend_info); + priv->backend_info = g_object_ref (backend_info); + return transfer; +} - return transfer; + +gchar* +gmyth_file_transfer_get_file_name (GMythFileTransfer *transfer) +{ + GMythFileTransferPrivate *priv = GMYTH_FILE_TRANSFER_GET_PRIVATE (transfer); + + return g_strdup (priv->filename); } /** @@ -254,9 +245,9 @@ gmyth_file_transfer_new_with_uri (const gchar* uri_str) { GMythFileTransfer *transfer = GMYTH_FILE_TRANSFER (g_object_new (GMYTH_FILE_TRANSFER_TYPE, NULL)); + GMythFileTransferPrivate *priv = GMYTH_FILE_TRANSFER_GET_PRIVATE (transfer); - transfer->backend_info = gmyth_backend_info_new_with_uri (uri_str); - + priv->backend_info = gmyth_backend_info_new_with_uri (uri_str); return transfer; } @@ -271,32 +262,34 @@ gboolean gmyth_file_transfer_open (GMythFileTransfer *transfer, const gchar* filename) { - gboolean ret = TRUE; + gboolean ret = TRUE; + GMythFileTransferPrivate *priv; - g_return_val_if_fail (transfer != NULL, FALSE); - g_return_val_if_fail (filename != NULL && strlen(filename) > 0, FALSE); + g_return_val_if_fail (transfer != NULL, FALSE); + g_return_val_if_fail (filename != NULL && strlen(filename) > 0, FALSE); + + priv = GMYTH_FILE_TRANSFER_GET_PRIVATE (transfer); + + if (priv->filename != NULL) + { + gmyth_file_transfer_close (transfer); + } + + priv->filename = g_strdup( filename ); + + /* configure the control socket */ + if (priv->control_sock == NULL) { + if (!_connect_to_backend (transfer)) { + gmyth_debug ("Connection to backend failed (Control Socket).\n"); + ret = FALSE; + } + } else { + gmyth_debug("Remote transfer control socket already created.\n"); + } - if (transfer->filename != NULL) - { - g_free (transfer->filename); - transfer->filename = NULL; - } + gmyth_debug ("Got file with size = %lld.\n", priv->filesize); - transfer->filename = g_strdup( filename ); - - /* configure the control socket */ - if (transfer->control_sock == NULL) { - if (!gmyth_connect_to_backend (transfer)) { - gmyth_debug ("Connection to backend failed (Control Socket).\n"); - ret = FALSE; - } - } else { - gmyth_debug("Remote transfer control socket already created.\n"); - } - - gmyth_debug ("Got file with size = %lld.\n", transfer->filesize); - - return ret; + return ret; } /** @@ -307,103 +300,91 @@ * @return true, if the connection had been configured successfully. */ static gboolean -gmyth_connect_to_backend (GMythFileTransfer *transfer) +_connect_to_backend (GMythFileTransfer *transfer) { - GString *base_str = NULL; - GString *hostname = NULL; - GMythStringList *strlist = NULL; - gboolean ret = TRUE; + GString *base_str = NULL; + GString *hostname = NULL; + GMythStringList *strlist = NULL; + gboolean ret = TRUE; + GMythFileTransferPrivate *priv; - g_return_val_if_fail (transfer != NULL, FALSE ); + g_return_val_if_fail (transfer != NULL, FALSE ); + + priv = GMYTH_FILE_TRANSFER_GET_PRIVATE (transfer); + _control_acquire_context (transfer, TRUE); + + + /* Creates the control socket */ + + if (priv->control_sock != NULL) { + g_object_unref (priv->control_sock); + priv->control_sock = NULL; + } + + base_str = g_string_new (""); - myth_control_acquire_context( transfer, TRUE ); + priv->control_sock = gmyth_socket_new(); + // Connects the socket, send Mythtv ANN command and verify Mythtv protocol version + if (!gmyth_socket_connect_to_backend (priv->control_sock, + priv->backend_info->hostname, priv->backend_info->port, TRUE)) { + + g_object_unref (priv->control_sock); + priv->control_sock = NULL; + return FALSE; + } + + /* Creates the data socket */ + if (priv->sock != NULL) { + g_object_unref (priv->sock); + priv->sock = NULL; + } - base_str = g_string_new (""); + priv->sock = gmyth_socket_new (); + gmyth_socket_connect (priv->sock, priv->backend_info->hostname, priv->backend_info->port); + gmyth_debug ("Connecting file transfer... (%s, %d)", priv->backend_info->hostname, priv->backend_info->port); + + strlist = gmyth_string_list_new(); + hostname = gmyth_socket_get_local_hostname(); + gmyth_debug( "[%s] MythTV version (from backend) = %d.\n", __FUNCTION__, priv->control_sock->mythtv_version ); + if (priv->control_sock->mythtv_version > 26 ) + g_string_printf (base_str, "ANN FileTransfer %s 1 -1", hostname->str); + else + g_string_printf (base_str, "ANN FileTransfer %s", hostname->str); + + gmyth_string_list_append_string (strlist, base_str ); + gmyth_string_list_append_char_array (strlist, priv->filename); + + gmyth_socket_write_stringlist (priv->sock, strlist ); + gmyth_socket_read_stringlist (priv->sock, strlist ); + + /* file identification used in future file transfer requests to backend */ + priv->file_id = gmyth_string_list_get_int (strlist, 1); + + /* Myth URI stream file size - decoded using two 8-bytes sequences (64 bits/long long types) */ + priv->filesize = gmyth_util_decode_long_long (strlist, 2); + + gmyth_debug ( "[%s] ***** Received: recordernum = %d, filesize = %" G_GUINT64_FORMAT "\n", __FUNCTION__, + transfer->file_id, transfer->priv->filesize ); + + if (priv->filesize < 0 ) { + gmyth_debug ( "[%s] Got filesize equals to %llu is lesser than 0 [invalid stream file]\n", __FUNCTION__, priv->filesize); + g_object_unref (priv->sock); + priv->sock = NULL; + ret = FALSE; + } + + _control_release_context( transfer ); - /* Creates the control socket */ + if (strlist != NULL) + g_object_unref (strlist); - if (transfer->control_sock != NULL) { - g_object_unref (transfer->control_sock); - transfer->control_sock = NULL; - } - - if ( NULL == transfer->control_sock ) - { - transfer->control_sock = gmyth_socket_new(); + if (base_str != NULL) + g_string_free (base_str, TRUE); + + if (hostname != NULL ) + g_string_free (hostname, TRUE); - // Connects the socket, send Mythtv ANN command and verify Mythtv protocol version - if (!gmyth_socket_connect_to_backend (transfer->control_sock, - transfer->backend_info->hostname, transfer->backend_info->port, TRUE)) { - - g_object_unref (transfer->control_sock); - transfer->control_sock = NULL; - return FALSE; - } - - } - - /* Creates the data socket */ - if (transfer->sock != NULL) { - g_object_unref (transfer->sock); - transfer->sock = NULL; - } - - //if ( NULL == transfer->sock ) { - transfer->sock = gmyth_socket_new (); - gmyth_socket_connect (transfer->sock, transfer->backend_info->hostname, transfer->backend_info->port); - gmyth_debug("Connecting file transfer... (%s, %d)", transfer->backend_info->hostname, transfer->backend_info->port); - //} - - if ( transfer->control_sock != NULL ) - { - - strlist = gmyth_string_list_new(); - hostname = gmyth_socket_get_local_hostname(); - gmyth_debug( "[%s] MythTV version (from backend) = %d.\n", __FUNCTION__, transfer->control_sock->mythtv_version ); - if ( transfer->control_sock->mythtv_version > 26 ) - g_string_printf( base_str, "ANN FileTransfer %s 1 -1", hostname->str); - else - g_string_printf( base_str, "ANN FileTransfer %s", hostname->str); - - gmyth_string_list_append_string (strlist, base_str ); - gmyth_string_list_append_char_array (strlist, transfer->filename); - - gmyth_socket_write_stringlist (transfer->sock, strlist ); - gmyth_socket_read_stringlist (transfer->sock, strlist ); - - /* file identification used in future file transfer requests to backend */ - transfer->file_id = gmyth_string_list_get_int( strlist, 1 ); - - /* Myth URI stream file size - decoded using two 8-bytes sequences (64 bits/long long types) */ - transfer->filesize = gmyth_util_decode_long_long( strlist, 2 ); - - gmyth_debug ( "[%s] ***** Received: recordernum = %d, filesize = %" G_GUINT64_FORMAT "\n", __FUNCTION__, - transfer->file_id, transfer->filesize ); - - if (transfer->filesize < 0 ) { - gmyth_debug ( "[%s] Got filesize equals to %llu is lesser than 0 [invalid stream file]\n", __FUNCTION__, transfer->filesize ); - g_object_unref (transfer->sock); - transfer->sock = NULL; - ret = FALSE; - goto cleanup; - } - - } /* if - Control Socket is not equals to NULL? */ - -cleanup: - - myth_control_release_context( transfer ); - - if ( strlist != NULL ) - g_object_unref( strlist ); - - if ( base_str != NULL ) - g_string_free (base_str, TRUE); - - if ( hostname != NULL ) - g_string_free (hostname, TRUE); - - return ret; + return ret; } /** @@ -418,18 +399,12 @@ gmyth_file_transfer_emit_program_info_changed_signal ( GMythFileTransfer *transfer, gint msg_code, gpointer live_tv_recorder ) { - /* - g_signal_emit_by_name ( G_OBJECT(transfer), - "program-info-changed", - msg_code, live_tv ); - */ - gmyth_debug( "Calling signal handler... [FILE_TRANSFER]" ); g_signal_emit ( transfer, GMYTH_FILE_TRANSFER_GET_CLASS (transfer)->program_info_changed_handler_signal_id, 0, /* details */ - msg_code, live_tv_recorder ); + msg_code, live_tv_recorder); } @@ -444,29 +419,33 @@ gmyth_file_transfer_is_open (GMythFileTransfer *transfer) { GMythStringList *strlist; + GMythFileTransferPrivate *priv; GString *query; - g_return_val_if_fail (transfer->control_sock != NULL, FALSE); - g_return_val_if_fail (transfer->sock != NULL, FALSE); - - myth_control_acquire_context( transfer, TRUE ); + g_return_val_if_fail (transfer != NULL, FALSE); + + priv = GMYTH_FILE_TRANSFER_GET_PRIVATE (transfer); + g_return_val_if_fail (priv->control_sock != NULL, FALSE); + g_return_val_if_fail (priv->sock != NULL, FALSE); + + _control_acquire_context (transfer, TRUE); strlist = gmyth_string_list_new(); query = g_string_new (GMYTHTV_QUERY_HEADER); - g_string_append_printf (query, "%d", transfer->file_id ); + g_string_append_printf (query, "%d", priv->file_id ); gmyth_string_list_append_string (strlist, query ); - gmyth_string_list_append_char_array( strlist, "IS_OPEN" ); + gmyth_string_list_append_char_array (strlist, "IS_OPEN"); - gmyth_socket_write_stringlist( transfer->control_sock, strlist ); - gmyth_socket_read_stringlist( transfer->control_sock, strlist ); + gmyth_socket_write_stringlist (priv->control_sock, strlist ); + gmyth_socket_read_stringlist (priv->control_sock, strlist ); - myth_control_release_context( transfer ); + _control_release_context (transfer); g_string_free (query, TRUE); g_object_unref (strlist); - return ( strlist != NULL && gmyth_string_list_get_int( strlist, 0 ) == 1 ); + return (strlist != NULL && gmyth_string_list_get_int (strlist, 0) == 1); } /** @@ -475,42 +454,52 @@ * @param transfer The actual File Transfer instance. */ void -gmyth_file_transfer_close( GMythFileTransfer *transfer ) +gmyth_file_transfer_close (GMythFileTransfer *transfer ) { - GMythStringList *strlist; - GString *query; + GMythStringList *strlist; + GMythFileTransferPrivate *priv; + GString *query; - g_return_if_fail (transfer->control_sock != NULL); - - myth_control_acquire_context( transfer, TRUE ); + g_return_val_if_fail (transfer != NULL, FALSE); - strlist = gmyth_string_list_new( ); - query = g_string_new (GMYTHTV_QUERY_HEADER); - g_string_append_printf( query, "%d", transfer->file_id); + priv = GMYTH_FILE_TRANSFER_GET_PRIVATE (transfer); - gmyth_string_list_append_string( strlist, query ); - gmyth_string_list_append_char_array( strlist, "DONE" ); + if (priv->control_sock == NULL) + return; - if ( gmyth_socket_sendreceive_stringlist(transfer->control_sock, strlist) <= 0 ) { - // fixme: time out??? - gmyth_debug ( "Remote file timeout.\n" ); - } + _control_acquire_context (transfer, TRUE); - g_string_free (query, TRUE); - g_object_unref (strlist); + strlist = gmyth_string_list_new (); + query = g_string_new (GMYTHTV_QUERY_HEADER); + g_string_append_printf (query, "%d", priv->file_id); - if (transfer->sock) { - g_object_unref( transfer->sock ); - transfer->sock = NULL; - } + gmyth_string_list_append_string (strlist, query); + gmyth_string_list_append_char_array (strlist, "DONE"); - if (transfer->control_sock) { - g_object_unref( transfer->control_sock ); - transfer->control_sock = NULL; - } + if (gmyth_socket_sendreceive_stringlist (priv->control_sock, strlist) <= 0 ) { + // fixme: time out??? + gmyth_debug ( "Remote file timeout.\n" ); + } - myth_control_release_context( transfer ); + g_string_free (query, TRUE); + g_object_unref (strlist); + if (priv->sock) { + g_object_unref (priv->sock ); + priv->sock = NULL; + } + + if (priv->control_sock) { + g_object_unref (priv->control_sock ); + priv->control_sock = NULL; + } + + if (priv->filename) { + g_free (priv->filename); + priv->filename = NULL; + } + + _control_release_context (transfer); } /** @@ -523,44 +512,48 @@ * @return The actual position on the remote file (after seek has been done). */ gint64 -gmyth_file_transfer_seek(GMythFileTransfer *transfer, guint64 pos, gint whence) +gmyth_file_transfer_seek (GMythFileTransfer *transfer, guint64 pos, gint whence) { - GMythStringList *strlist = gmyth_string_list_new(); - GString *query; + GMythStringList *strlist = gmyth_string_list_new(); + GMythFileTransferPrivate *priv; + GString *query; - g_return_val_if_fail (transfer->sock != NULL, -1); - g_return_val_if_fail (transfer->control_sock != NULL, -1); + g_return_val_if_fail (transfer != NULL, FALSE); + priv = GMYTH_FILE_TRANSFER_GET_PRIVATE (transfer); - strlist = gmyth_string_list_new(); - query = g_string_new (GMYTHTV_QUERY_HEADER); - g_string_append_printf (query, "%d", transfer->file_id); - - /* myth_control_acquire_context( transfer, TRUE ); */ + g_return_val_if_fail (priv->sock != NULL, -1); + g_return_val_if_fail (priv->control_sock != NULL, -1); - gmyth_string_list_append_string( strlist, query ); - gmyth_string_list_append_char_array( strlist, "SEEK" ); - gmyth_string_list_append_uint64( strlist, pos ); - - gmyth_string_list_append_int( strlist, whence ); + strlist = gmyth_string_list_new(); + query = g_string_new (GMYTHTV_QUERY_HEADER); + g_string_append_printf (query, "%d", priv->file_id); - if (pos > 0 ) - gmyth_string_list_append_uint64( strlist, pos ); - else - gmyth_string_list_append_uint64( strlist, transfer->readposition ); - - gmyth_socket_sendreceive_stringlist( transfer->control_sock, strlist ); + /* myth_control_acquire_context( transfer, TRUE ); */ - gint64 retval = gmyth_string_list_get_int64(strlist, 0); - transfer->readposition = retval; - gmyth_debug ( "[%s] got reading position pointer from the streaming = %lld\n", - __FUNCTION__, retval ); + gmyth_string_list_append_string (strlist, query); + gmyth_string_list_append_char_array (strlist, "SEEK"); + gmyth_string_list_append_uint64 (strlist, pos); - g_object_unref (strlist); - g_string_free (query, TRUE); + gmyth_string_list_append_int (strlist, whence); - /* myth_control_release_context( transfer ); */ + if (pos > 0 ) + gmyth_string_list_append_uint64 (strlist, pos); + else + gmyth_string_list_append_uint64 (strlist, priv->offset); - return retval; + gmyth_socket_sendreceive_stringlist (priv->control_sock, strlist); + + gint64 retval = gmyth_string_list_get_int64 (strlist, 0); + priv->offset = retval; + gmyth_debug ( "[%s] got reading position pointer from the streaming = %lld\n", + __FUNCTION__, retval ); + + g_object_unref (strlist); + g_string_free (query, TRUE); + + /* myth_control_release_context( transfer ); */ + + return retval; } /** @@ -572,31 +565,16 @@ * @return true, if the acquire had been got. */ static gboolean -myth_control_acquire_context( GMythFileTransfer *transfer, gboolean do_wait ) +_control_acquire_context( GMythFileTransfer *transfer, gboolean do_wait ) { gboolean ret = TRUE; - //guint max_iter = 50; - - g_mutex_lock( transfer->mutex ); - - //while ( !has_io_access ) - // g_cond_wait( io_watcher_cond, mutex ); - - //has_io_access = FALSE; - - //myth_control_acquire_context (FALSE); - - /* - if ( do_wait ) { - while ( --max_iter > 0 && !g_main_context_wait( io_watcher_context, io_watcher_cond, mutex ) ) - ret = FALSE; - } else if ( !g_main_context_acquire( io_watcher_context ) ) - ret = FALSE; - */ - - //g_static_mutex_lock( &st_mutex ); - - return ret; + GMythFileTransferPrivate *priv; + + g_return_val_if_fail (transfer != NULL, FALSE); + priv = GMYTH_FILE_TRANSFER_GET_PRIVATE (transfer); + + g_mutex_lock (priv->mutex); + return ret; } /** @@ -607,23 +585,17 @@ * @return true, if the socket read/write permissions had been releaseds. */ static gboolean -myth_control_release_context( GMythFileTransfer *transfer ) +_control_release_context( GMythFileTransfer *transfer ) { gboolean ret = TRUE; - - //g_static_mutex_unlock( &st_mutex ); - - //g_main_context_release( io_watcher_context ); - - //g_main_context_wakeup( io_watcher_context ); - - //has_io_access = TRUE; + GMythFileTransferPrivate *priv; - //g_cond_broadcast( io_watcher_cond ); - - g_mutex_unlock( transfer->mutex ); + g_return_val_if_fail (transfer != NULL, FALSE); + priv = GMYTH_FILE_TRANSFER_GET_PRIVATE (transfer); + + g_mutex_unlock (priv->mutex ); - return ret; + return ret; } /** @@ -639,70 +611,74 @@ * @return The actual block size (in bytes) returned by REQUEST_BLOCK message, * or the error code. */ -gint64 +GMythFileTransferReadResult gmyth_file_transfer_read(GMythFileTransfer *transfer, GByteArray *data, gint size, gboolean read_unlimited) { - gint bytes_sent = 0; - gsize bytes_read = 0; - gint64 total_read = 0; - - GError *error = NULL; - - GIOChannel *io_channel; - GIOChannel *io_channel_control; + gint bytes_sent = 0; + gsize bytes_read = 0; + gint64 total_read = 0; + GMythFileTransferReadResult retval = GMYTH_FILE_TRANSFER_READ_OK; + GMythFileTransferPrivate *priv; - GIOCondition io_cond; - GIOCondition io_cond_control; - GIOStatus io_status = G_IO_STATUS_NORMAL; - GIOStatus io_status_control = G_IO_STATUS_NORMAL; - - gboolean ret = TRUE; + GError *error = NULL; - GString *query; - - g_return_val_if_fail ( data != NULL, -2 ); + GIOChannel *io_channel; + GIOChannel *io_channel_control; - io_channel = transfer->sock->sd_io_ch; - io_channel_control = transfer->control_sock->sd_io_ch; + GIOCondition io_cond; + GIOCondition io_cond_control; + GIOStatus io_status = G_IO_STATUS_NORMAL; + GIOStatus io_status_control = G_IO_STATUS_NORMAL; - io_status = g_io_channel_set_encoding( io_channel, NULL, &error ); - if ( io_status == G_IO_STATUS_NORMAL ) - gmyth_debug ( "[%s] Setting encoding to binary data socket).\n", __FUNCTION__ ); + GMythStringList *strlist; + gboolean ret = TRUE; + GString *query; - io_cond = g_io_channel_get_buffer_condition( io_channel ); + g_return_val_if_fail (transfer != NULL, FALSE); + g_return_val_if_fail (data != NULL, GMYTH_FILE_TRANSFER_READ_ERROR); - io_cond_control = g_io_channel_get_buffer_condition( io_channel ); - if ( transfer->sock == NULL || ( io_status == G_IO_STATUS_ERROR ) ) { - g_printerr( "gmyth_file_transfer_read(): Called with no raw socket.\n" ); - return -1; - } + priv = GMYTH_FILE_TRANSFER_GET_PRIVATE (transfer); - if ( transfer->control_sock == NULL || ( io_status_control == G_IO_STATUS_ERROR ) ) { - g_printerr( "gmyth_file_transfer_read(): Called with no control socket.\n" ); - return -1; - } + strlist = gmyth_string_list_new(); - query = g_string_new (GMYTHTV_QUERY_HEADER); - g_string_append_printf ( query, "%d", transfer->file_id ); - gmyth_debug ("[%s] Transfer_query = %s\n", __FUNCTION__, query->str ); - - //myth_control_acquire_context( transfer, TRUE ); - - while (total_read != size) { - GMythStringList *strlist = gmyth_string_list_new(); + io_channel = priv->sock->sd_io_ch; + io_channel_control = priv->control_sock->sd_io_ch; - gmyth_string_list_append_char_array( strlist, query->str ); - gmyth_string_list_append_char_array( strlist, "REQUEST_BLOCK" ); - gmyth_string_list_append_int( strlist, size - total_read); + io_status = g_io_channel_set_encoding( io_channel, NULL, &error ); + if ( io_status == G_IO_STATUS_NORMAL ) + gmyth_debug ( "[%s] Setting encoding to binary data socket).\n", __FUNCTION__ ); + + io_cond = g_io_channel_get_buffer_condition( io_channel ); + + io_cond_control = g_io_channel_get_buffer_condition( io_channel ); + if (priv->sock == NULL || ( io_status == G_IO_STATUS_ERROR ) ) { + g_printerr( "gmyth_file_transfer_read(): Called with no raw socket.\n" ); + return GMYTH_FILE_TRANSFER_READ_ERROR; + } + + if (priv->control_sock == NULL || ( io_status_control == G_IO_STATUS_ERROR ) ) { + g_printerr( "gmyth_file_transfer_read(): Called with no control socket.\n" ); + return GMYTH_FILE_TRANSFER_READ_ERROR; + } + + query = g_string_new (GMYTHTV_QUERY_HEADER); + g_string_append_printf ( query, "%d", priv->file_id ); + gmyth_debug ("[%s] Transfer_query = %s\n", __FUNCTION__, query->str ); + + _control_acquire_context (transfer, TRUE ); + //Do Read + gmyth_string_list_append_char_array (strlist, query->str ); + gmyth_string_list_append_char_array (strlist, "REQUEST_BLOCK" ); + gmyth_string_list_append_int (strlist, size - total_read); // Request the block to the backend - gmyth_socket_write_stringlist (transfer->control_sock, strlist); + gmyth_socket_write_stringlist (priv->control_sock, strlist); // Receives the backand answer - gmyth_socket_read_stringlist (transfer->control_sock, strlist); + gmyth_socket_read_stringlist (priv->control_sock, strlist); if (strlist != NULL && gmyth_string_list_length (strlist) > 0) { - bytes_sent = gmyth_string_list_get_int (strlist, 0); // -1 on backend error + bytes_sent = gmyth_string_list_get_int (strlist, 0); // -1 on backend error gmyth_debug ( "[%s] got SENT buffer message = %d\n", __FUNCTION__, bytes_sent ); if (bytes_sent > 0) { @@ -716,103 +692,96 @@ if (io_status != G_IO_STATUS_NORMAL) { gmyth_debug ("Error on io_channel"); g_free (data_buffer); - total_read = GMYTHTV_FILE_TRANSFER_READ_ERROR; g_object_unref (strlist); - break; + retval = GMYTH_FILE_TRANSFER_READ_ERROR; + goto error; } - total_read += bytes_read; - /* append new data to the increasing byte array */ data = g_byte_array_append (data, (const guint8*)data_buffer, bytes_read); - gmyth_debug ("Total transfer data read: %"G_GINT64_FORMAT"\n", total_read); + gmyth_debug ("Total transfer data read: %"G_GINT64_FORMAT"\n", bytes_read); + priv->offset += bytes_read; + + if ((priv->filesize > 0) && (priv->offset == priv->filesize)) { + retval = GMYTH_FILE_TRANSFER_READ_EOF; + goto error; + } g_free (data_buffer); } else if (!read_unlimited) { - total_read = GMYTHTV_FILE_TRANSFER_READ_ERROR; g_object_unref (strlist); strlist = NULL; - break; + retval = GMYTH_FILE_TRANSFER_READ_ERROR; + goto error; } } else { - /*if (!(transfer->priv != NULL && transfer->priv->recorder != NULL && - transfer->priv->do_next_program_chain) ) { - */ - total_read = GMYTHTV_FILE_TRANSFER_READ_ERROR; + retval = GMYTH_FILE_TRANSFER_READ_ERROR; if (strlist != NULL) { g_object_unref (strlist); strlist = NULL; } - break; } + if ( strlist!=NULL ) { g_object_unref (strlist); strlist = NULL; } - if ((total_read < size) && read_unlimited) { - /* wait for more data */ - g_usleep (3 * G_USEC_PER_SEC); - } else if (total_read < size) { - gmyth_debug ("EOF"); - break; - } - - } /* while - iterates through bytes until reaches the end of stream */ - - if (read_unlimited && (bytes_sent == 0)) { + if (read_unlimited && (bytes_sent == 0)) { gmyth_debug( "Trying to move to the next program chain..." ); - transfer->priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer); - - if ( transfer->priv != NULL && transfer->priv->recorder != NULL && - transfer->priv->do_next_program_chain ) + if (priv->recorder != NULL && + priv->do_next_program_chain) { - total_read = GMYTHTV_FILE_TRANSFER_NEXT_PROG_CHAIN; - //g_mutex_lock( transfer->mutex ); - //ret = gmyth_livetv_next_program_chain( transfer->priv->recorder ); - GMythProgramInfo *prog_info = gmyth_recorder_get_current_program_info( transfer->priv->recorder ); + retval = GMYTH_FILE_TRANSFER_READ_NEXT_PROG_CHAIN; + GMythProgramInfo *prog_info = gmyth_recorder_get_current_program_info (priv->recorder); - if ( prog_info != NULL && prog_info->pathname != NULL && strlen( prog_info->pathname->str ) > 0 && - g_ascii_strcasecmp( prog_info->pathname->str, transfer->filename ) != 0 ) - ret = gmyth_file_transfer_open ( transfer, g_strrstr( prog_info->pathname->str, "/" ) ); + if (prog_info != NULL && prog_info->pathname != NULL && strlen( prog_info->pathname->str ) > 0 && + g_ascii_strcasecmp( prog_info->pathname->str, priv->filename ) != 0 ) + ret = gmyth_file_transfer_open (transfer, g_strrstr( prog_info->pathname->str, "/" ) ); - if ( prog_info != NULL ) + if (prog_info != NULL ) g_object_unref( prog_info ); - //g_mutex_unlock( transfer->mutex ); - if ( !ret ) gmyth_debug( "Cannot change to the next program info!" ); else gmyth_debug( "OK!!! MOVED to the next program info [%s]!", - transfer->filename ); + priv->filename ); } - } /* if */ + } /* if */ + +error: - //myth_control_release_context( transfer ); - g_string_free (query, TRUE); + _control_release_context (transfer); + g_string_free (query, TRUE); - if ( error != NULL ) { - gmyth_debug ("Cleaning-up ERROR: %s [msg = %s, code = %d]\n", __FUNCTION__, error->message, - error->code); - g_error_free (error); - } + if ( error != NULL ) { + gmyth_debug ("Cleaning-up ERROR: %s [msg = %s, code = %d]\n", __FUNCTION__, error->message, + error->code); + g_error_free (error); + } - if ( total_read > 0 ) - transfer->readposition += total_read; + if ( total_read > 0 ) + priv->offset += total_read; - return total_read; + return retval; } static void -gmyth_file_transfer_program_info_changed( GMythFileTransfer *transfer, - gint msg_code, gpointer livetv_recorder ) +_file_transfer_program_info_changed( GMythFileTransfer *transfer, + gint msg_code, gpointer livetv_recorder ) { - GMythRecorder *recorder = GMYTH_RECORDER( livetv_recorder ); - + GMythRecorder *recorder; + GMythFileTransferPrivate *priv; + + g_return_val_if_fail (transfer != NULL, FALSE); + + priv = GMYTH_FILE_TRANSFER_GET_PRIVATE (transfer); + + recorder = GMYTH_RECORDER( livetv_recorder ); gmyth_debug( "Program info changed! ( file transfer orig. = %p, ptr. = [%s] )", transfer, livetv_recorder != NULL ? "[NOT NULL]" : "[NULL]"); @@ -821,13 +790,10 @@ gmyth_debug( "YES, the requested program info movement on the LiveTV transfer is authentical!" ); } - transfer->priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer); - + priv = GMYTH_FILE_TRANSFER_GET_PRIVATE(transfer); g_object_ref(recorder); - - transfer->priv->recorder = recorder; - - transfer->priv->do_next_program_chain = TRUE; + priv->recorder = recorder; + priv->do_next_program_chain = TRUE; } /** @@ -842,20 +808,24 @@ gboolean gmyth_file_transfer_settimeout( GMythFileTransfer *transfer, gboolean fast ) { - + GMythFileTransferPrivate *priv; GMythStringList *strlist = NULL; - g_return_val_if_fail (transfer->sock != NULL, FALSE); - g_return_val_if_fail (transfer->control_sock != NULL, FALSE); + g_return_val_if_fail (transfer != NULL, FALSE); + + priv = GMYTH_FILE_TRANSFER_GET_PRIVATE (transfer); + + g_return_val_if_fail (priv->sock != NULL, FALSE); + g_return_val_if_fail (priv->control_sock != NULL, FALSE); - myth_control_acquire_context( transfer, TRUE ); + _control_acquire_context (transfer, TRUE ); strlist = gmyth_string_list_new(); gmyth_string_list_append_char_array( strlist, GMYTHTV_QUERY_HEADER ); gmyth_string_list_append_char_array( strlist, "SET_TIMEOUT" ); gmyth_string_list_append_int( strlist, fast ); - gint strlist_len = gmyth_socket_sendreceive_stringlist( transfer->control_sock, + gint strlist_len = gmyth_socket_sendreceive_stringlist (priv->control_sock, strlist ); if ( strlist_len > 0 ) @@ -863,7 +833,7 @@ else gmyth_debug( "Timeout cannot be changed!" ); - myth_control_release_context( transfer ); + _control_release_context (transfer); gmyth_debug ( "%s setting timeout flag of this file transfer = %s\n", strlist_len > 0 ? "Yes," : "NOT", fast ? "FAST" : "NOT FAST" ); @@ -883,6 +853,10 @@ guint64 gmyth_file_transfer_get_filesize (GMythFileTransfer *transfer) { + GMythFileTransferPrivate *priv; + g_return_val_if_fail (transfer != NULL, 0); - return transfer->filesize; + + priv = GMYTH_FILE_TRANSFER_GET_PRIVATE (transfer); + return priv->filesize; } diff -r 9900800a8dd6 -r f92a59c9a9a5 gmyth/src/gmyth_file_transfer.h --- a/gmyth/src/gmyth_file_transfer.h Wed Apr 04 21:18:43 2007 +0100 +++ b/gmyth/src/gmyth_file_transfer.h Wed Apr 04 21:36:07 2007 +0100 @@ -52,13 +52,24 @@ #define IS_GMYTH_FILE_TRANSFER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GMYTH_FILE_TRANSFER_TYPE)) #define GMYTH_FILE_TRANSFER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GMYTH_FILE_TRANSFER_TYPE, GMythFileTransferClass)) -#define GMYTHTV_FILE_TRANSFER_READ_ERROR -314 -#define GMYTHTV_FILE_TRANSFER_NEXT_PROG_CHAIN -315 +typedef enum { + GMYTH_FILE_TRANSFER_READ_OK = 0, + GMYTH_FILE_TRANSFER_READ_NEXT_PROG_CHAIN = 1, + GMYTH_FILE_TRANSFER_READ_ERROR = 2, + GMYTH_FILE_TRANSFER_READ_EOF = 3 +} GMythFileTransferReadResult; + typedef struct _GMythFileTransfer GMythFileTransfer; typedef struct _GMythFileTransferClass GMythFileTransferClass; typedef struct _GMythFileTransferPrivate GMythFileTransferPrivate; +struct _GMythFileTransfer +{ + GObject parent; +}; + + struct _GMythFileTransferClass { GObjectClass parent_class; @@ -66,43 +77,21 @@ /* callbacks */ guint program_info_changed_handler_signal_id; - /* signal default handlers */ - void (*program_info_changed_handler) ( GMythFileTransfer *transfer, + /* signal default handlers */ + void (*program_info_changed_handler) ( GMythFileTransfer *transfer, gint msg_code, gpointer livetv_recorder ); }; -struct _GMythFileTransfer -{ - GObject parent; - - /* Myth URI structure */ - gchar *filename; - GMythBackendInfo *backend_info; - - /* MythTV version number */ - gint mythtv_version; - - /* socket descriptors */ - GMythSocket *control_sock; - GMythSocket *sock; - - GMutex *mutex; - - gint64 readposition; - guint64 filesize; - gint file_id; - - GMythFileTransferPrivate *priv; - -}; GType gmyth_file_transfer_get_type (void); GMythFileTransfer* gmyth_file_transfer_new (GMythBackendInfo *backend_info); +gchar* gmyth_file_transfer_get_file_name (GMythFileTransfer *transfer); gboolean gmyth_file_transfer_open (GMythFileTransfer *transfer, const gchar* filename); void gmyth_file_transfer_close (GMythFileTransfer *transfer); gboolean gmyth_file_transfer_is_open (GMythFileTransfer *transfer); -gint64 gmyth_file_transfer_read (GMythFileTransfer *transfer, +GMythFileTransferReadResult + gmyth_file_transfer_read (GMythFileTransfer *transfer, GByteArray *data, gint size, gboolean read_unlimited); diff -r 9900800a8dd6 -r f92a59c9a9a5 gmyth/src/gmyth_recorder.c --- a/gmyth/src/gmyth_recorder.c Wed Apr 04 21:18:43 2007 +0100 +++ b/gmyth/src/gmyth_recorder.c Wed Apr 04 21:36:07 2007 +0100 @@ -1174,7 +1174,8 @@ * @return The framerate (double value) of the current video. */ gdouble -gmyth_recorder_get_framerate( GMythRecorder *recorder ) { +gmyth_recorder_get_framerate (GMythRecorder *recorder ) +{ gdouble fr = 0.0f; GString *query = g_string_new( GMYTHTV_RECORDER_HEADER); @@ -1209,4 +1210,5 @@ g_string_free (query, TRUE); return fr; -} \ No newline at end of file +} +