# HG changeset patch # User rosfran # Date 1165031177 0 # Node ID 85b47c66a241680da9dcd7df66c395afb18ad027 # Parent 94a7f5399f79f93dfef63ba6772602227658a649 [svn r178] API adding to allow Monitor events' socket listening. diff -r 94a7f5399f79 -r 85b47c66a241 gmyth/src/gmyth_file_transfer.c --- a/gmyth/src/gmyth_file_transfer.c Sat Dec 02 03:41:47 2006 +0000 +++ b/gmyth/src/gmyth_file_transfer.c Sat Dec 02 03:46:17 2006 +0000 @@ -33,6 +33,7 @@ */ #include "gmyth_file_transfer.h" +#include "gmyth_uri.h" #include "gmyth_livetv.h" #include "gmyth_util.h" #include "gmyth_socket.h" @@ -57,7 +58,7 @@ #define GMYTHTV_RETRIES -1 #define GMYTHTV_FILE_SIZE 0 -#define GMYTHTV_BUFFER_SIZE 128*1024 +#define GMYTHTV_BUFFER_SIZE 8*1024 #define GMYTHTV_VERSION 30 @@ -74,8 +75,6 @@ #define GMYTHTV_ENABLE_DEBUG 1 #endif -GThread *monitor_th = NULL; - enum myth_sock_types { GMYTH_PLAYBACK_TYPE = 0, GMYTH_MONITOR_TYPE, @@ -83,6 +82,7 @@ GMYTH_RINGBUFFER_TYPE }; +//static GStaticMutex st_mutex = G_STATIC_MUTEX_INIT; static GMutex* mutex = NULL; @@ -120,9 +120,12 @@ { g_return_if_fail( transfer != NULL ); + //transfer->card_id = num; + //transfer->rec_id = -1; + //transfer->recordernum = num; + transfer->readposition = 0; transfer->filesize = GMYTHTV_FILE_SIZE; - transfer->filename = NULL; //transfer->timeoutisfast = FALSE; //transfer->userreadahead = GMYTHTV_USER_READ_AHEAD; @@ -130,8 +133,8 @@ transfer->control_sock = NULL; transfer->sock = NULL; - - transfer->backend_info = NULL; + + transfer->monitor = NULL; /* it is used for signalizing the event socket consumer thread */ io_watcher_cond = g_cond_new(); @@ -156,49 +159,54 @@ // fixme: do we need the card_id???? GMythFileTransfer* -gmyth_file_transfer_new (GMythBackendInfo *backend_info) +gmyth_file_transfer_new ( const GMythBackendInfo *backend_info) { GMythFileTransfer *transfer = GMYTH_FILE_TRANSFER (g_object_new (GMYTH_FILE_TRANSFER_TYPE, NULL)); + + transfer->backend_info = (GMythBackendInfo *)backend_info; - if (backend_info != NULL) { - g_object_ref (backend_info); - transfer->backend_info = backend_info; - } + return transfer; +} + +GMythFileTransfer* +gmyth_file_transfer_new_with_uri ( const gchar* uri_str ) +{ + GMythFileTransfer *transfer = GMYTH_FILE_TRANSFER (g_object_new (GMYTH_FILE_TRANSFER_TYPE, NULL)); + + transfer->uri = gmyth_uri_new_with_value (uri_str); return transfer; } gboolean -gmyth_file_transfer_open (GMythFileTransfer *transfer, const char *filename) +gmyth_file_transfer_open ( GMythFileTransfer *transfer ) { gboolean ret = TRUE; - - g_assert (transfer); - g_return_val_if_fail (transfer->backend_info != NULL, FALSE); - g_return_val_if_fail (filename != NULL, FALSE); - - // FIXME: Verify if file_transfer has already been opened - if (transfer->filename != NULL) { - g_warning ("[%s] File transfer already opened!", __FUNCTION__); - return FALSE; + + g_return_val_if_fail( transfer != NULL, FALSE ); + + if ( transfer->backend_info != NULL ) + { + transfer->hostname = g_string_new ( gmyth_backend_info_get_hostname(transfer->backend_info) ); + transfer->port = gmyth_backend_info_get_port (transfer->backend_info); + } else { + gmyth_debug ("[%s] URI: %s\n", __FUNCTION__, transfer->uri->uri->str); + transfer->hostname = g_string_new ( gmyth_uri_get_host(transfer->uri) ); + transfer->port = gmyth_uri_get_port (transfer->uri); } - transfer->filename = g_strdup (filename); - - gmyth_debug ("[%s] File name: %s\n", __FUNCTION__, filename); - gmyth_debug ("hostname: %s, port %d\n", transfer->backend_info->hostname, - transfer->backend_info->port); + gmyth_debug ("hostname: %s, port %d\n", transfer->hostname->str, transfer->port); /* configure the control socket */ if (transfer->control_sock == NULL) { if (!gmyth_connect_to_backend (transfer)) { - g_printerr( "Connection to backend failed (Control Socket).\n" ); + gmyth_debug( "Connection to backend failed (Control Socket).\n" ); ret = FALSE; } } else { g_warning("Remote transfer control socket already created.\n"); } - + return ret; } @@ -207,15 +215,18 @@ gmyth_connect_to_backend (GMythFileTransfer *transfer) { GString *base_str = NULL; + GString *hostname = NULL; GMythStringList *strlist = NULL; - GString *hostname = NULL; + gchar *path_dir = NULL; gboolean ret = TRUE; g_return_val_if_fail (transfer != NULL, FALSE ); - g_return_val_if_fail (transfer->filename != NULL, FALSE ); - g_return_val_if_fail (transfer->backend_info != NULL, FALSE); + g_return_val_if_fail (transfer->hostname != NULL, FALSE); + g_return_val_if_fail (transfer->port > 0, FALSE); base_str = g_string_new (""); + path_dir = ( transfer->uri != NULL ? gmyth_uri_get_path (transfer->uri) : + gmyth_backend_info_get_path( transfer->backend_info ) ); /* Creates the control socket */ if (transfer->control_sock != NULL) { @@ -227,7 +238,7 @@ // 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)) { + transfer->hostname->str, transfer->port, TRUE)) { g_object_unref (transfer->control_sock); transfer->control_sock = NULL; @@ -241,7 +252,7 @@ } transfer->sock = gmyth_socket_new (); - gmyth_socket_connect (transfer->sock, transfer->backend_info->hostname, transfer->backend_info->port); + gmyth_socket_connect (transfer->sock, transfer->hostname->str, transfer->port); strlist = gmyth_string_list_new(); hostname = gmyth_socket_get_local_hostname(); @@ -252,7 +263,7 @@ 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_string_list_append_char_array (strlist, path_dir ); gmyth_socket_write_stringlist (transfer->sock, strlist ); gmyth_socket_read_stringlist (transfer->sock, strlist ); @@ -274,7 +285,22 @@ goto cleanup; } - //gmyth_connect_to_backend_monitor( transfer, hostname ); + transfer->monitor = gmyth_monitor_handler_new ( ); + + ret = gmyth_monitor_handler_open ( transfer->monitor, transfer->hostname->str, transfer->port ); + + if ( ret == TRUE ) + { + gmyth_debug("Connect MythTV Monitor event socket! Trying to start the message handler..."); + + ret = gmyth_monitor_handler_start ( transfer->monitor ); + + if (ret) + gmyth_debug("MythTV Monitor event socket connected and listening!"); + else + gmyth_debug("Problems when trying to start MythTV Monitor event socket!"); + } + cleanup: if ( strlist != NULL ) @@ -343,7 +369,12 @@ g_object_unref( transfer->control_sock ); transfer->control_sock = NULL; } - + + if ( transfer->monitor ) { + g_object_unref( transfer->monitor ); + transfer->monitor = NULL; + } + } gint64 @@ -439,7 +470,7 @@ gint gmyth_file_transfer_read(GMythFileTransfer *transfer, GByteArray *data, gint size, gboolean read_unlimited) { - gsize bytes_sent = 0; + gint bytes_sent = 0; gsize bytes_read = 0; gsize total_read = 0; @@ -468,13 +499,13 @@ 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" ); - exit(0); // fixme remove this + //exit(0); // fixme remove this return -1; } if ( transfer->control_sock == NULL || ( io_status_control == G_IO_STATUS_ERROR ) ) { g_printerr( "gmyth_file_transfer_read(): Called with no control socket.\n" ); - exit(0); // fixme remove this + //exit(0); // fixme remove this return -1; } @@ -482,9 +513,12 @@ g_string_append_printf ( query, "%d", transfer->file_id ); gmyth_debug ("[%s] Transfer_query = %s\n", __FUNCTION__, query->str ); + /* send requests to the maximum number of REQUEST_BLOCK messages */ + guint max_tries = 4; + myth_control_acquire_context( TRUE ); - while (total_read == 0) { + while (total_read == 0 && --max_tries > 0) { GMythStringList *strlist = gmyth_string_list_new(); gmyth_string_list_append_char_array( strlist, query->str ); @@ -511,11 +545,18 @@ bytes_sent -= bytes_read; /* append new data to the increasing byte array */ - data = g_byte_array_append (data, data_buffer, bytes_read); + data = g_byte_array_append (data, (const guint8*)data_buffer, bytes_read); gmyth_debug ("Total file transfer data read: %d\n", total_read); } g_free (data_buffer); - } + } else { + + } + } else { + total_read = GMYTHTV_FILE_TRANSFER_READ_ERROR; + g_object_unref (strlist); + strlist = NULL; + break; } g_object_unref (strlist); strlist = NULL; @@ -530,7 +571,9 @@ g_error_free (error); } - transfer->readposition += total_read; + if ( total_read >= 0 ) + transfer->readposition += total_read; + return total_read; } diff -r 94a7f5399f79 -r 85b47c66a241 gmyth/src/gmyth_file_transfer.h --- a/gmyth/src/gmyth_file_transfer.h Sat Dec 02 03:41:47 2006 +0000 +++ b/gmyth/src/gmyth_file_transfer.h Sat Dec 02 03:46:17 2006 +0000 @@ -37,6 +37,7 @@ #include "gmyth_uri.h" #include "gmyth_livetv.h" #include "gmyth_backendinfo.h" +#include "gmyth_monitor_handler.h" #include #include @@ -72,7 +73,9 @@ GObject parent; /* Myth URI structure */ - //const GMythURI *uri; + GMythURI *uri; + GString* hostname; + gint port; gchar* filename; GMythBackendInfo *backend_info; @@ -83,27 +86,34 @@ GMythSocket *control_sock; GMythSocket *event_sock; GMythSocket *sock; + + GMythMonitorHandler *monitor; gint64 readposition; guint64 filesize; - //gboolean timeoutisfast; - //gboolean userreadahead; - //gint retries; gint file_id; }; GType gmyth_file_transfer_get_type (void); -GMythFileTransfer* gmyth_file_transfer_new ( GMythBackendInfo *backend_info ); +GMythFileTransfer* gmyth_file_transfer_new ( const GMythBackendInfo *backend_info ); -gboolean gmyth_file_transfer_open (GMythFileTransfer *transfer, const gchar* filename); +GMythFileTransfer* gmyth_file_transfer_new_with_uri ( const gchar* uri_str ); + +gboolean gmyth_file_transfer_open (GMythFileTransfer *transfer); + void gmyth_file_transfer_close (GMythFileTransfer *transfer); gboolean gmyth_file_transfer_is_open (GMythFileTransfer *transfer); -gint gmyth_file_transfer_read(GMythFileTransfer *transfer, GByteArray *data, gint size, gboolean read_unlimited); + +gint gmyth_file_transfer_read(GMythFileTransfer *transfer, GByteArray *data, + gint size, gboolean read_unlimited); + gint64 gmyth_file_transfer_seek(GMythFileTransfer *transfer, guint64 pos, gint whence); + gboolean gmyth_file_transfer_settimeout( GMythFileTransfer *transfer, gboolean fast); + guint64 gmyth_file_transfer_get_filesize (GMythFileTransfer *transfer); #define G_END_DECLS diff -r 94a7f5399f79 -r 85b47c66a241 gmyth/src/gmyth_socket.c --- a/gmyth/src/gmyth_socket.c Sat Dec 02 03:41:47 2006 +0000 +++ b/gmyth/src/gmyth_socket.c Sat Dec 02 03:46:17 2006 +0000 @@ -73,6 +73,8 @@ static GStaticMutex mutex = G_STATIC_MUTEX_INIT; +static gchar* local_hostname = NULL; + static void gmyth_socket_class_init (GMythSocketClass *klass); static void gmyth_socket_init (GMythSocket *object); @@ -95,6 +97,9 @@ static void gmyth_socket_init (GMythSocket *gmyth_socket) { + + /* gmyth_socket->local_hostname = NULL; */ + } /** Gets the some important address translation info, from the client socket @@ -113,7 +118,7 @@ hints = g_new0 (struct addrinfo, 1); hints->ai_family = AF_INET; hints->ai_socktype = SOCK_STREAM; - hints->ai_flags = AI_NUMERICHOST; + /* hints->ai_flags = AI_NUMERICHOST; */ if ( port != -1 ) portStr = g_strdup_printf ("%d", port); @@ -157,7 +162,7 @@ struct ifaddrs *ifaddr = g_new0( struct ifaddrs, 1 ); struct ifaddrs *i = g_new0( struct ifaddrs, 1 ); - gchar addr[NI_MAXHOST+1]; + gchar *addr = g_new0( gchar, NI_MAXHOST+1 ); gchar *ifname; gint ifIdx; @@ -180,7 +185,14 @@ if ( current_connections == NULL || ( current_connections != NULL && g_list_find_custom( current_connections, (gchar *)addr, (GCompareFunc)gmyth_socket_find_match_address_uri ) == NULL ) ) - local_addrs = g_list_append (local_addrs, addr); + { + local_addrs = g_list_append( local_addrs, g_strdup( addr ) ); + } + + if ( addr != NULL ) { + g_free( addr ); + addr = g_new0( gchar, NI_MAXHOST+1 ); + } } } /* iterates over network interfaces */ @@ -290,6 +302,9 @@ gmyth_socket_get_local_hostname () { GString *str = NULL; + + if ( local_hostname != NULL ) + return g_string_new( local_hostname ); gchar localhostname[1024]; gchar *localaddr = NULL; @@ -338,7 +353,10 @@ } g_static_mutex_unlock (&mutex); - + + if ( str != NULL && str->str != NULL ) + local_hostname = g_strdup( str->str ); + return str; } @@ -678,12 +696,14 @@ * @param gmyth_socket the GMythSocket instance. * @param hostname_backend The backend hostname or IP address. * @param port The backend port to connect. - * @param blocking_client A flag to choose between blocking and non-blocking - * backend connection. + * @param blocking_client A flag to choose between blocking and non-blocking + * @param with_events Sets the connection flag to receive events. + * backend connection. */ -gboolean -gmyth_socket_connect_to_backend (GMythSocket *gmyth_socket, - const gchar *hostname_backend, int port, gboolean blocking_client) +static gboolean +gmyth_socket_connect_to_backend_and_events (GMythSocket *gmyth_socket, + const gchar *hostname_backend, gint port, gboolean blocking_client, + gboolean with_events) { if (!gmyth_socket_connect (gmyth_socket, hostname_backend, port)) { g_warning ("[%s] Could not open socket to backend machine [%s]\n", __FUNCTION__, @@ -699,14 +719,14 @@ hostname = gmyth_socket_get_local_hostname(); - g_string_printf(base_str, "ANN %s %s 0", + g_string_printf(base_str, "ANN %s %s %u", (blocking_client ? "Playback" : "Monitor"), - hostname->str); + hostname->str, with_events); gmyth_debug ("[%s] Connection command sent to backend: %s", __FUNCTION__, base_str->str); gmyth_socket_send_command (gmyth_socket, base_str); - result = gmyth_socket_receive_response(gmyth_socket); + result = gmyth_socket_receive_response (gmyth_socket); if (result != NULL) { gmyth_debug ("[%s] Response received from backend: %s", __FUNCTION__, result->str); @@ -723,6 +743,51 @@ } } +/** Starts Mythtv protocol level connection. Checks Mythtv protocol version + * supported by the backend and send the "ANN" command. + * + * @param gmyth_socket the GMythSocket instance. + * @param hostname_backend The backend hostname or IP address. + * @param port The backend port to connect. + * @param blocking_client A flag to choose between blocking and non-blocking + */ +gboolean +gmyth_socket_connect_to_backend (GMythSocket *gmyth_socket, + const gchar *hostname_backend, gint port, gboolean blocking_client) +{ + if (!gmyth_socket_connect_to_backend_and_events ( gmyth_socket, hostname_backend, port, + blocking_client, FALSE) ) { + gmyth_debug ("[%s] Could not open socket to backend machine [%s]\n", __FUNCTION__, + hostname_backend ); + return FALSE; + } + + return TRUE; + +} + +/** Starts Mythtv protocol level connection. Checks Mythtv protocol version + * supported by the backend and send the "ANN" command. + * + * @param gmyth_socket the GMythSocket instance. + * @param hostname_backend The backend hostname or IP address. + * @param port The backend port to connect. + * @param blocking_client A flag to choose between blocking and non-blocking + */ +gboolean +gmyth_socket_connect_to_backend_events (GMythSocket *gmyth_socket, + const gchar *hostname_backend, gint port, gboolean blocking_client) +{ + if (!gmyth_socket_connect_to_backend_and_events ( gmyth_socket, hostname_backend, port, + blocking_client, TRUE) ) { + gmyth_debug ("[%s] Could not open socket to backend machine in order to receive events [%s]\n", __FUNCTION__, + hostname_backend ); + return FALSE; + } + + return TRUE; +} + /** Closes the socket connection to the backend. * * @param gmyth_socket The GMythSocket instance. diff -r 94a7f5399f79 -r 85b47c66a241 gmyth/src/gmyth_socket.h --- a/gmyth/src/gmyth_socket.h Sat Dec 02 03:41:47 2006 +0000 +++ b/gmyth/src/gmyth_socket.h Sat Dec 02 03:46:17 2006 +0000 @@ -69,7 +69,7 @@ GObject parent; /* socket descriptor */ - int sd; + gint sd; GIOChannel *sd_io_ch; gchar *hostname; @@ -92,13 +92,18 @@ gboolean gmyth_socket_send_command (GMythSocket *gmyth_socket, GString *command); GString * gmyth_socket_receive_response (GMythSocket *gmyth_socket); -int gmyth_socket_sendreceive_stringlist (GMythSocket *gmyth_socket, +gint gmyth_socket_sendreceive_stringlist (GMythSocket *gmyth_socket, GMythStringList *str_list); gboolean gmyth_socket_connect (GMythSocket *gmyth_socket, const gchar *hostname, gint port); gboolean gmyth_socket_connect_to_backend (GMythSocket *gmyth_socket, - const gchar *hostname_backend, int port, gboolean blocking_client); + const gchar *hostname_backend, gint port, + gboolean blocking_client); + +gboolean gmyth_socket_connect_to_backend_events (GMythSocket *gmyth_socket, + const gchar *hostname_backend, gint port, + gboolean blocking_client); GString * gmyth_socket_get_local_hostname (void); @@ -112,7 +117,7 @@ gboolean gmyth_socket_write_stringlist(GMythSocket *gmyth_socket, GMythStringList* str_list); -int gmyth_socket_read_stringlist(GMythSocket *gmyth_socket, +gint gmyth_socket_read_stringlist(GMythSocket *gmyth_socket, GMythStringList* str_list); G_END_DECLS