[svn r199] Fixed problem with COxa.
1 /* vim: set sw=2: -*- Mode: C; tab-width: 2; indent-tabs-mode: t; c-basic-offset: 2; c-indent-level: 2-*- */
5 * @file gmyth/gmyth_monitor_handler.c
7 * @brief <p> GMythMonitorHandler deals with the streaming media events remote/local
8 * that are sent to the MythTV frontend.
10 * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
11 * @author Rosfran Lins Borges <rosfran.borges@indt.org.br>
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU Lesser General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
25 * You should have received a copy of the GNU Lesser General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 * GStreamer MythTV plug-in properties:
30 * - location (backend server hostname/URL) [ex.: myth://192.168.1.73:28722/1000_1092091.nuv]
31 * - path (qurl - remote file to be opened)
35 #include "gmyth_uri.h"
36 #include "gmyth_livetv.h"
37 #include "gmyth_util.h"
38 #include "gmyth_socket.h"
39 #include "gmyth_stringlist.h"
40 #include "gmyth_monitor_handler.h"
41 #include "gmyth_debug.h"
46 #include <arpa/inet.h>
47 #include <sys/types.h>
48 #include <sys/socket.h>
54 #define GMYTHTV_QUERY_HEADER "QUERY_FILETRANSFER "
56 #define GMYTHTV_VERSION 30
58 #define GMYTHTV_TRANSFER_MAX_WAITS 700
60 #define GMYTHTV_BUFFER_SIZE 8*1024
62 #ifdef GMYTHTV_ENABLE_DEBUG
63 #define GMYTHTV_ENABLE_DEBUG 1
65 #undef GMYTHTV_ENABLE_DEBUG
68 /* this NDEBUG is to maintain compatibility with GMyth library */
70 #define GMYTHTV_ENABLE_DEBUG 1
73 GMainContext *io_watcher_context = NULL;
75 GThreadPool *monitor_th = NULL;
77 enum myth_sock_types {
78 GMYTH_PLAYBACK_TYPE = 0,
80 GMYTH_FILETRANSFER_TYPE,
84 //static gboolean* myth_control_sock_listener( GIOChannel *io_channel );
85 //static gboolean myth_control_sock_listener( GIOChannel *io_channel, GIOCondition condition,
88 static void myth_control_sock_listener( GIOChannel *io_channel, gboolean* ret );
90 static GMutex* mutex = NULL;
92 static GCond* io_watcher_cond = NULL;
94 static void gmyth_monitor_handler_class_init (GMythMonitorHandlerClass *klass);
95 static void gmyth_monitor_handler_init (GMythMonitorHandler *object);
97 static void gmyth_monitor_handler_dispose (GObject *object);
98 static void gmyth_monitor_handler_finalize (GObject *object);
100 static gboolean gmyth_connect_to_backend_monitor (GMythMonitorHandler *monitor);
102 void gmyth_monitor_handler_close( GMythMonitorHandler *monitor );
104 G_DEFINE_TYPE(GMythMonitorHandler, gmyth_monitor_handler, G_TYPE_OBJECT)
107 gmyth_monitor_handler_class_init (GMythMonitorHandlerClass *klass)
109 GObjectClass *gobject_class;
111 gobject_class = (GObjectClass *) klass;
113 gobject_class->dispose = gmyth_monitor_handler_dispose;
114 gobject_class->finalize = gmyth_monitor_handler_finalize;
118 gmyth_monitor_handler_init (GMythMonitorHandler *monitor)
120 g_return_if_fail( monitor != NULL );
122 monitor->event_sock = NULL;
123 monitor->hostname = NULL;
125 monitor->actual_index = 0;
127 monitor->backend_msgs = g_hash_table_new( g_int_hash, g_int_equal );
129 /* it is used for signalizing the event socket consumer thread */
130 io_watcher_cond = g_cond_new();
132 /* mutex to control access to the event socket consumer thread */
133 mutex = g_mutex_new();
137 gmyth_monitor_handler_dispose (GObject *object)
140 GMythMonitorHandler *monitor = GMYTH_MONITOR_HANDLER (object);
142 if ( monitor->event_sock != NULL )
144 g_object_unref( monitor->event_sock );
145 monitor->event_sock = NULL;
148 if ( monitor->hostname != NULL )
150 g_free( monitor->hostname );
151 monitor->hostname = NULL;
154 if ( monitor->backend_msgs != NULL )
156 g_hash_table_unref( monitor->backend_msgs );
157 monitor->backend_msgs = NULL;
162 g_mutex_free( mutex );
166 if ( io_watcher_cond != NULL )
168 g_cond_free( io_watcher_cond );
169 io_watcher_cond = NULL;
172 if ( monitor_th != NULL )
174 g_thread_pool_free( monitor_th, TRUE, FALSE );
175 //g_object_unref( monitor_th );
179 G_OBJECT_CLASS (gmyth_monitor_handler_parent_class)->dispose (object);
183 gmyth_monitor_handler_finalize (GObject *object)
185 g_signal_handlers_destroy (object);
187 G_OBJECT_CLASS (gmyth_monitor_handler_parent_class)->finalize (object);
190 // fixme: do we need the card_id????
192 gmyth_monitor_handler_new (void)
194 GMythMonitorHandler *monitor = GMYTH_MONITOR_HANDLER ( g_object_new (
195 GMYTH_MONITOR_HANDLER_TYPE, FALSE ));
201 gmyth_monitor_handler_open (GMythMonitorHandler *monitor, gchar *hostname, gint port)
205 if (monitor->hostname != NULL) {
206 g_free (monitor->hostname);
207 monitor->hostname = NULL;
210 monitor->hostname = g_strdup( hostname );
211 monitor->port = port;
213 gmyth_debug ("Monitor event socket --- hostname: %s, port %d\n", monitor->hostname, monitor->port);
215 /* configure the event socket */
216 if (monitor->event_sock == NULL) {
217 if (!gmyth_connect_to_backend_monitor (monitor)) {
218 g_printerr( "Connection to backend failed (Event Socket).\n" );
222 g_warning("Remote monitor event socket already created.\n");
230 //myth_control_sock_listener( GIOChannel *io_channel, GIOCondition condition, gpointer data )
231 myth_control_sock_listener( GIOChannel *io_channel, gboolean* ret )
235 GError *error = NULL;
236 GIOCondition io_cond;
237 GIOCondition condition;
239 GByteArray *byte_array = NULL;
241 ret = g_new0( gboolean, 1 );
243 //gboolean ret = TRUE;
246 static guint count = 0;
249 //GMythMonitorHandler *monitor = (GMythMonitorHandler*)data;
251 //myth_control_acquire_context (TRUE);
253 if ( io_channel == NULL ) {
254 g_debug ("Monitor socket is NULL!\n");
262 gmyth_debug ("%d - Listening on Monitor socket...!\n", count);
264 condition = g_io_channel_get_buffer_condition( io_channel );
265 //while ( !has_io_access )
266 // g_cond_wait( io_watcher_cond, mutex );
268 //myth_control_acquire_context (TRUE);
270 if (condition & G_IO_HUP) {
271 gmyth_debug ("Read end of pipe died!\n");
276 //if ( ( condition & G_IO_IN ) != 0 ) {
277 byte_array = g_byte_array_new();
278 io_status = g_io_channel_set_encoding( io_channel, NULL, &error );
279 guint buffer_size = GMYTHTV_BUFFER_SIZE;
282 trash = g_new0( gchar, buffer_size );
284 io_status = g_io_channel_read_chars( io_channel, trash,
285 buffer_size, &len, &error);
287 gmyth_debug ( "[%s] Received data buffer from IO binary channel... %d bytes gone!\n",
292 byte_array = g_byte_array_append( byte_array, (const guint8*)trash, len );
297 io_cond = g_io_channel_get_buffer_condition( io_channel );
299 } while ( ( io_cond & G_IO_IN ) != 0 );
301 gmyth_debug ("\n\n\n[%s]\tEVENT: Read %d bytes: %s\n\n\n", __FUNCTION__, recv, byte_array != NULL && byte_array->data != NULL ? (gchar*)byte_array->data : "[no event data]" );
305 if ( byte_array != NULL ) {
306 g_byte_array_free( byte_array, TRUE );
314 if ( io_status == G_IO_STATUS_ERROR || error != NULL ) {
315 gmyth_debug ("[%s] Error reading: %s\n", __FUNCTION__, error != NULL ? error->message : "" );
320 //g_hash_table_insert( monitor->backend_msgs, (gpointer)monitor->actual_index,
321 // byte_array->data );
323 //monitor->actual_index += recv;
327 if ( byte_array != NULL ) {
328 g_byte_array_free( byte_array, TRUE );
337 gmyth_connect_to_backend_monitor (GMythMonitorHandler *monitor)
341 /* Creates the event socket */
342 if (monitor->event_sock != NULL) {
343 g_object_unref (monitor->event_sock);
344 monitor->event_sock = NULL;
347 monitor->event_sock = gmyth_socket_new();
349 /* Connects the socket, send Mythtv ANN Monitor and verify Mythtv protocol version */
350 if (!gmyth_socket_connect_to_backend_events ( monitor->event_sock,
351 monitor->hostname, monitor->port, FALSE ) )
353 g_object_unref (monitor->event_sock);
354 monitor->event_sock = NULL;
362 myth_control_sock_setup( GIOChannel *channel )
364 gboolean *ret = g_new0( gboolean, 1 );
369 io_watcher_context = g_main_context_default();
370 GMainLoop *loop = g_main_loop_new( io_watcher_context, TRUE );
374 if ( channel != NULL ) {
375 source = g_io_create_watch( channel, G_IO_IN | G_IO_HUP );
376 //src_id = g_io_add_watch( channel, G_IO_IN | G_IO_HUP,
377 // (GSourceFunc)myth_control_sock_listener, NULL );
383 g_source_set_callback ( source, (GSourceFunc)myth_control_sock_listener, NULL, NULL );
385 g_source_attach( source, io_watcher_context );
388 gmyth_debug( "[%s] Error adding watch listener function to the IO control channel!\n", __FUNCTION__ );
393 g_main_loop_run( loop );
396 if ( source != NULL )
397 g_source_unref( source );
399 //if ( io_watcher_context != NULL )
400 // g_main_context_unref( io_watcher_context );
402 //if ( loop != NULL )
403 // g_main_loop_unref( loop );
410 gmyth_monitor_handler_start (GMythMonitorHandler *monitor)
412 gboolean *ret = g_new0( gboolean, 1 );
415 if (!g_thread_supported () ) g_thread_init (NULL);
417 monitor_th = g_thread_pool_new( (GFunc)myth_control_sock_listener,
418 monitor->event_sock->sd_io_ch, 3, FALSE, NULL );
420 //if ( ( ret = g_thread_join( monitor_th ) ) == FALSE )
421 if ( monitor_th != NULL )
423 gmyth_debug ( "\n[%s]\tOK! Starting listener on the MONITOR event socket...[thread location = %p]\n",
424 __FUNCTION__, g_thread_self( ) );
427 gmyth_debug ( "\n[%s]\tERROR! Coudn't start listener on the MONITOR event socket...[thread location = %p]\n",
428 __FUNCTION__, g_thread_self( ) );
434 gmyth_debug( "[%s] Watch listener function over the IO control channel? %s!!!\n",
435 __FUNCTION__, ( *ret == TRUE ? "YES" : "NO" ) );
441 gmyth_monitor_handler_close( GMythMonitorHandler *monitor )
444 if (monitor->event_sock) {
445 g_object_unref( monitor->event_sock );
446 monitor->event_sock = NULL;
449 if (monitor->hostname) {
450 g_free( monitor->hostname );
451 monitor->hostname = NULL;