gmyth/src/gmyth_monitor_handler.c
author rosfran
Wed Mar 28 15:53:29 2007 +0100 (2007-03-28)
branchtrunk
changeset 467 bc13aaf7561d
parent 464 5ef4452c42cc
child 545 7f0a3066f6ab
permissions -rw-r--r--
[svn r472] Changed all the g_debug, g_warning and g_debug calls, to the gmyth_debug status/error printing function.
rosfran@175
     1
/**
rosfran@175
     2
 * GMyth Library
rosfran@175
     3
 *
rosfran@175
     4
 * @file gmyth/gmyth_monitor_handler.c
rosfran@175
     5
 * 
rosfran@175
     6
 * @brief <p> GMythMonitorHandler deals with the streaming media events remote/local
rosfran@175
     7
 * that are sent to the MythTV frontend.
rosfran@175
     8
 *
rosfran@175
     9
 * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
rosfran@175
    10
 * @author Rosfran Lins Borges <rosfran.borges@indt.org.br>
rosfran@175
    11
 *
rosfran@175
    12
 *//*
rosfran@175
    13
 * 
rosfran@175
    14
 * This program is free software; you can redistribute it and/or modify
rosfran@175
    15
 * it under the terms of the GNU Lesser General Public License as published by
rosfran@175
    16
 * the Free Software Foundation; either version 2 of the License, or
rosfran@175
    17
 * (at your option) any later version.
rosfran@175
    18
 *
rosfran@175
    19
 * This program is distributed in the hope that it will be useful,
rosfran@175
    20
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
rosfran@175
    21
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
rosfran@175
    22
 * GNU General Public License for more details.
rosfran@175
    23
 *
rosfran@175
    24
 * You should have received a copy of the GNU Lesser General Public License
rosfran@175
    25
 * along with this program; if not, write to the Free Software
rosfran@175
    26
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
rosfran@175
    27
 *
rosfran@175
    28
 * GStreamer MythTV plug-in properties:
rosfran@175
    29
 * - location (backend server hostname/URL) [ex.: myth://192.168.1.73:28722/1000_1092091.nuv]
rosfran@175
    30
 * - path (qurl - remote file to be opened)
rosfran@175
    31
 * - port number *   
rosfran@175
    32
 */
rosfran@175
    33
rosfran@212
    34
#ifdef HAVE_CONFIG_H
rosfran@212
    35
#include "config.h"
rosfran@212
    36
#endif
rosfran@212
    37
rosfran@175
    38
#include <unistd.h>
rosfran@175
    39
#include <glib.h>
rosfran@175
    40
#include <arpa/inet.h>
rosfran@175
    41
#include <sys/types.h>
rosfran@175
    42
#include <sys/socket.h>
rosfran@175
    43
#include <netdb.h>
rosfran@175
    44
#include <errno.h>
rosfran@175
    45
#include <stdlib.h>
rosfran@175
    46
#include <assert.h>
rosfran@175
    47
leo_sobral@213
    48
#include "gmyth_marshal.h"
rosfran@216
    49
leo_sobral@213
    50
#include "gmyth_monitor_handler.h"
rosfran@216
    51
rosfran@216
    52
#include "gmyth.h"
leo_sobral@213
    53
 
rosfran@175
    54
#define GMYTHTV_QUERY_HEADER		"QUERY_FILETRANSFER "
rosfran@175
    55
rosfran@175
    56
#define GMYTHTV_VERSION							30
rosfran@175
    57
rosfran@175
    58
#define GMYTHTV_TRANSFER_MAX_WAITS	700
rosfran@175
    59
rosfran@175
    60
#define GMYTHTV_BUFFER_SIZE					8*1024
rosfran@175
    61
rosfran@175
    62
#ifdef GMYTHTV_ENABLE_DEBUG
rosfran@175
    63
#define GMYTHTV_ENABLE_DEBUG				1
rosfran@175
    64
#else
rosfran@175
    65
#undef GMYTHTV_ENABLE_DEBUG
rosfran@175
    66
#endif
rosfran@175
    67
rosfran@175
    68
/* this NDEBUG is to maintain compatibility with GMyth library */
rosfran@175
    69
#ifndef NDEBUG
rosfran@175
    70
#define GMYTHTV_ENABLE_DEBUG				1
rosfran@175
    71
#endif
rosfran@175
    72
rosfran@347
    73
gboolean gmyth_monitor_handler_listener( GIOChannel *io_channel, 
rosfran@347
    74
						GIOCondition io_cond, gpointer data );
rosfran@198
    75
rosfran@232
    76
static void gmyth_monitor_handler_default_listener( GMythMonitorHandler *monitor, gint msg_code, gchar* message );
rosfran@175
    77
rosfran@175
    78
static void gmyth_monitor_handler_class_init          (GMythMonitorHandlerClass *klass);
rosfran@175
    79
static void gmyth_monitor_handler_init                (GMythMonitorHandler *object);
rosfran@175
    80
rosfran@175
    81
static void gmyth_monitor_handler_dispose  (GObject *object);
rosfran@175
    82
static void gmyth_monitor_handler_finalize (GObject *object);
rosfran@175
    83
rosfran@175
    84
static gboolean gmyth_connect_to_backend_monitor (GMythMonitorHandler *monitor);
rosfran@175
    85
leo_sobral@446
    86
static gboolean gmyth_monitor_handler_setup( GMythMonitorHandler *monitor,
leo_sobral@446
    87
                                             GIOChannel *channel );
leo_sobral@446
    88
rosfran@175
    89
void gmyth_monitor_handler_close( GMythMonitorHandler *monitor );
rosfran@175
    90
rosfran@175
    91
G_DEFINE_TYPE(GMythMonitorHandler, gmyth_monitor_handler, G_TYPE_OBJECT)
rosfran@175
    92
rosfran@175
    93
static void
rosfran@175
    94
gmyth_monitor_handler_class_init (GMythMonitorHandlerClass *klass)
rosfran@175
    95
{
rosfran@175
    96
  GObjectClass *gobject_class;
rosfran@203
    97
  GMythMonitorHandlerClass *gmonitor_class;
rosfran@175
    98
rosfran@175
    99
  gobject_class = (GObjectClass *) klass;
rosfran@203
   100
  gmonitor_class = (GMythMonitorHandlerClass *) gobject_class;
rosfran@175
   101
rosfran@175
   102
  gobject_class->dispose  = gmyth_monitor_handler_dispose;
rosfran@175
   103
  gobject_class->finalize = gmyth_monitor_handler_finalize;
rosfran@203
   104
  
rosfran@203
   105
	gmonitor_class->backend_events_handler_signal_id = 
rosfran@212
   106
		  g_signal_new ("backend-events-handler",
rosfran@212
   107
		                 G_TYPE_FROM_CLASS (gmonitor_class),
rosfran@212
   108
		                 G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
rosfran@212
   109
		                 0,
rosfran@216
   110
										 NULL,
rosfran@216
   111
										 NULL,
rosfran@232
   112
										 gmyth_marshal_VOID__INT_STRING,
rosfran@216
   113
										 G_TYPE_NONE,
rosfran@232
   114
										 2,
rosfran@216
   115
										 G_TYPE_INT,
rosfran@232
   116
										 G_TYPE_STRING);
rosfran@216
   117
										 
rosfran@216
   118
	gmonitor_class->backend_events_handler = gmyth_monitor_handler_default_listener;
rosfran@203
   119
rosfran@175
   120
}
rosfran@175
   121
rosfran@175
   122
static void
rosfran@175
   123
gmyth_monitor_handler_init (GMythMonitorHandler *monitor)
rosfran@175
   124
{ 
rosfran@175
   125
  g_return_if_fail( monitor != NULL );
rosfran@175
   126
rosfran@175
   127
  monitor->event_sock = NULL;
rosfran@175
   128
  monitor->hostname = NULL;
rosfran@175
   129
  monitor->port = 0;
rosfran@175
   130
  monitor->actual_index = 0;
rosfran@175
   131
  
rosfran@360
   132
  monitor->allow_msgs_listener = FALSE;
rosfran@233
   133
  
rosfran@360
   134
  /* monitor->backend_msgs = g_hash_table_new( g_int_hash, g_int_equal ); */
rosfran@175
   135
    
rosfran@175
   136
  /* it is used for signalizing the event socket consumer thread */
rosfran@360
   137
  monitor->mutex = g_mutex_new();
rosfran@175
   138
  
rosfran@360
   139
  monitor->sid_io_watch = -1;
rosfran@220
   140
  
rosfran@220
   141
  monitor->gmyth_monitor_handler_listener = gmyth_monitor_handler_listener;
rosfran@175
   142
}
rosfran@175
   143
rosfran@175
   144
static void
rosfran@175
   145
gmyth_monitor_handler_dispose  (GObject *object)
rosfran@175
   146
{
rosfran@192
   147
	GMythMonitorHandler *monitor = GMYTH_MONITOR_HANDLER (object);
renatofilho@464
   148
    gmyth_monitor_handler_close(monitor);
rosfran@336
   149
rosfran@233
   150
	monitor->allow_msgs_listener = FALSE;
rosfran@360
   151
renatofilho@464
   152
	if (monitor->sid_io_watch != -1)
rosfran@360
   153
	{
renatofilho@464
   154
        g_source_remove (monitor->sid_io_watch);
rosfran@360
   155
	}
rosfran@360
   156
renatofilho@464
   157
    /* mutex to control access to the event socket consumer thread */
renatofilho@464
   158
    if ( monitor->mutex != NULL )
renatofilho@464
   159
    {
renatofilho@464
   160
    	g_mutex_free( monitor->mutex );
renatofilho@464
   161
  	    monitor->mutex = NULL;
renatofilho@464
   162
    }
rosfran@220
   163
	
renatofilho@464
   164
    if ( monitor->event_sock != NULL )  
renatofilho@464
   165
    {
renatofilho@464
   166
  	    g_object_unref( monitor->event_sock );
renatofilho@464
   167
  	    monitor->event_sock = NULL;
renatofilho@464
   168
    }
rosfran@360
   169
renatofilho@464
   170
    if ( monitor->hostname != NULL )  
renatofilho@464
   171
    {
renatofilho@464
   172
  	    g_free( monitor->hostname );
renatofilho@464
   173
  	    monitor->hostname = NULL;
renatofilho@464
   174
    }
rosfran@192
   175
renatofilho@464
   176
    if ( monitor->backend_msgs != NULL )
renatofilho@464
   177
    {
renatofilho@464
   178
  	    g_hash_table_destroy ( monitor->backend_msgs );
renatofilho@464
   179
  	    monitor->backend_msgs = NULL;
renatofilho@464
   180
    }
rosfran@358
   181
 
renatofilho@464
   182
    /*
renatofilho@464
   183
    if ( io_watcher_cond != NULL )  
renatofilho@464
   184
    {
renatofilho@464
   185
        g_cond_free( io_watcher_cond );
renatofilho@464
   186
        io_watcher_cond = NULL;
renatofilho@464
   187
    }
renatofilho@464
   188
    */
rosfran@192
   189
  
renatofilho@464
   190
    G_OBJECT_CLASS (gmyth_monitor_handler_parent_class)->dispose (object);
rosfran@175
   191
}
rosfran@175
   192
rosfran@175
   193
static void
rosfran@175
   194
gmyth_monitor_handler_finalize (GObject *object)
rosfran@175
   195
{
rosfran@175
   196
  g_signal_handlers_destroy (object);
rosfran@175
   197
rosfran@175
   198
  G_OBJECT_CLASS (gmyth_monitor_handler_parent_class)->finalize (object);
rosfran@175
   199
}
rosfran@175
   200
rosfran@419
   201
/** 
rosfran@419
   202
 * Creates a new instance of GMyth Monitor Handler.
rosfran@419
   203
 * 
rosfran@419
   204
 * @return a new instance of the Monitor Handler. 
rosfran@419
   205
 */
rosfran@175
   206
GMythMonitorHandler*
rosfran@216
   207
gmyth_monitor_handler_new ( void )
rosfran@175
   208
{
rosfran@343
   209
  GMythMonitorHandler *monitor = GMYTH_MONITOR_HANDLER ( 
rosfran@343
   210
  					g_object_new ( GMYTH_MONITOR_HANDLER_TYPE, FALSE ) );
rosfran@358
   211
rosfran@175
   212
  return monitor;
rosfran@175
   213
}
rosfran@175
   214
rosfran@419
   215
/** 
rosfran@419
   216
 * Acquire the mutex to have access to the IO Watcher listener.
rosfran@419
   217
 * 
rosfran@419
   218
 * @param monitor The GMythMonitorHandler instance.
rosfran@419
   219
 * @param do_wait Tells the IO Watcher to wait on the GCond. (obsolete)
rosfran@419
   220
 * 
rosfran@419
   221
 * @return <code>true</code>, if the access to IO Watcher was acquired. 
rosfran@419
   222
 */
rosfran@220
   223
static gboolean 
rosfran@343
   224
myth_control_acquire_context( GMythMonitorHandler *monitor, gboolean do_wait ) 
rosfran@220
   225
{
rosfran@220
   226
	
renatofilho@464
   227
    gboolean ret = TRUE;	
rosfran@220
   228
  	
renatofilho@464
   229
    g_mutex_lock( monitor->mutex );
rosfran@220
   230
  
renatofilho@464
   231
    return ret;
rosfran@220
   232
  
rosfran@220
   233
}
rosfran@220
   234
rosfran@419
   235
/** 
rosfran@419
   236
 * Release the mutex to have access to the IO Watcher listener.
rosfran@419
   237
 * 
rosfran@419
   238
 * @param monitor The GMythMonitorHandler instance.
rosfran@419
   239
 * 
rosfran@419
   240
 * @return <code>true</code>, if the access to IO Watcher was released. 
rosfran@419
   241
 */
rosfran@220
   242
static gboolean 
rosfran@343
   243
myth_control_release_context( GMythMonitorHandler *monitor ) 
rosfran@220
   244
{
rosfran@220
   245
	
rosfran@220
   246
	gboolean ret = TRUE;
rosfran@220
   247
    
renatofilho@464
   248
    g_mutex_unlock( monitor->mutex );
rosfran@220
   249
  
renatofilho@464
   250
    return ret;
rosfran@220
   251
}
rosfran@220
   252
rosfran@336
   253
void
rosfran@336
   254
gmyth_monitor_handler_close (GMythMonitorHandler *monitor)
rosfran@336
   255
{
rosfran@336
   256
	monitor->allow_msgs_listener = FALSE;
rosfran@343
   257
rosfran@343
   258
#if 0	
rosfran@358
   259
	if ( monitor->monitor_th != NULL ) 
rosfran@336
   260
  {
rosfran@336
   261
  	g_thread_pool_free( monitor->monitor_th, TRUE, FALSE );
rosfran@336
   262
  	//g_thread_exit( monitor->monitor_th );
rosfran@336
   263
  	/*if ( monitor->monitor_th != NULL )
rosfran@336
   264
  		g_object_unref( monitor->monitor_th );*/
rosfran@336
   265
  	monitor->monitor_th = NULL;
rosfran@336
   266
  }
rosfran@336
   267
	
rosfran@336
   268
  if ( monitor->event_sock != NULL )  
rosfran@336
   269
  {
rosfran@336
   270
  	gmyth_socket_close_connection( monitor->event_sock );  	
rosfran@336
   271
  }
rosfran@343
   272
#endif
rosfran@343
   273
rosfran@336
   274
}
rosfran@336
   275
rosfran@419
   276
/** 
rosfran@419
   277
 * Opens connection the the Monitor socket on MythTV backend server,
rosfran@419
   278
 * where all status messages are notified to the client.
rosfran@419
   279
 * 
rosfran@419
   280
 * @param monitor The GMythMonitorHandler instance.
rosfran@419
   281
 * @param hostname The remote host name of the MythTV backend server.
rosfran@419
   282
 * @param port The remote port number of the MythTV backend server.
rosfran@419
   283
 * 
rosfran@419
   284
 * @return <code>true</code>, if the connection was successfully opened.
rosfran@419
   285
 */
rosfran@175
   286
gboolean
rosfran@229
   287
gmyth_monitor_handler_open (GMythMonitorHandler *monitor, const gchar *hostname, gint port)
rosfran@175
   288
{
rosfran@175
   289
  gboolean ret = TRUE;
rosfran@229
   290
  
rosfran@229
   291
  g_return_val_if_fail( hostname != NULL, FALSE );
rosfran@175
   292
rosfran@175
   293
  if (monitor->hostname != NULL) {
rosfran@175
   294
    g_free (monitor->hostname);
rosfran@175
   295
    monitor->hostname = NULL;
rosfran@175
   296
  }
rosfran@175
   297
renatofilho@464
   298
  monitor->hostname = g_strdup (hostname);
rosfran@175
   299
  monitor->port = port;
rosfran@175
   300
rosfran@175
   301
  gmyth_debug ("Monitor event socket --- hostname: %s, port %d\n", monitor->hostname, monitor->port);
rosfran@175
   302
  
rosfran@175
   303
  /* configure the event socket */
renatofilho@464
   304
  if ( NULL == monitor->event_sock) { 
leo_sobral@436
   305
      if (!gmyth_connect_to_backend_monitor (monitor)) {
leo_sobral@436
   306
          gmyth_debug( "Connection to backend failed (Event Socket)." );
leo_sobral@436
   307
          ret = FALSE;
leo_sobral@436
   308
      }
leo_sobral@436
   309
      else {
rosfran@467
   310
          gmyth_debug("Remote monitor event socket already created.\n");
leo_sobral@436
   311
      }
rosfran@175
   312
  }
rosfran@175
   313
rosfran@175
   314
  return ret;
rosfran@175
   315
rosfran@175
   316
}
rosfran@175
   317
rosfran@419
   318
/** 
rosfran@419
   319
 * Reads the data got from the connection to the Monitor socket,
rosfran@419
   320
 * and looks for some important status messages.
rosfran@419
   321
 * 
rosfran@419
   322
 * @param monitor The GMythMonitorHandler instance.
rosfran@419
   323
 * @param strlist The GMythStringList instance got from the Monitor remote socket.
rosfran@419
   324
 * @param back_msg_action A string pointer to the status message detailed description.
rosfran@419
   325
 * 
rosfran@419
   326
 * @return The backend status message code ID.
rosfran@419
   327
 */
rosfran@212
   328
static gint
rosfran@212
   329
gmyth_monitor_handler_is_backend_message( GMythMonitorHandler *monitor,
rosfran@212
   330
                        GMythStringList* strlist, gchar **back_msg_action )
rosfran@212
   331
{
rosfran@216
   332
	gint msg_type = GMYTH_BACKEND_NO_MESSAGE;
rosfran@216
   333
	GString *back_msg = NULL;
rosfran@216
   334
	
rosfran@343
   335
	if ( gmyth_string_list_length(strlist) > 0 )
rosfran@216
   336
	{
rosfran@343
   337
		
rosfran@343
   338
		back_msg = gmyth_string_list_get_string( strlist, 0 );
rosfran@343
   339
		if ( back_msg != NULL && back_msg->str != NULL &&
rosfran@343
   340
		                                strstr( back_msg->str, "BACKEND" ) != NULL )
rosfran@343
   341
		{
rosfran@343
   342
			gmyth_debug( "MONITOR HANDLER - Received backend message = %s", back_msg->str );
renatofilho@464
   343
	  	    *back_msg_action = gmyth_string_list_get_char_array( strlist, 1 );
rosfran@343
   344
	  	
rosfran@343
   345
	  	if ( back_msg_action != NULL )
rosfran@343
   346
	  	{	        	
rosfran@343
   347
	  	
rosfran@343
   348
	    	if ( g_strstr_len( *back_msg_action, strlen( *back_msg_action ), "LIVETV_CHAIN" ) ||
rosfran@343
   349
	    			g_strstr_len( *back_msg_action, strlen( *back_msg_action ), "RECORDING_LIST_CHANGE" ) || 
rosfran@343
   350
	    			g_strstr_len( *back_msg_action, strlen( *back_msg_action ), "SCHEDULE_CHANGE" ) ||
rosfran@343
   351
	    			g_strstr_len( *back_msg_action, strlen( *back_msg_action ), "LIVETV_WATCH" ) )
rosfran@343
   352
	    	{
rosfran@343
   353
	    		gmyth_debug( "MONITOR: message type == GMYTH_BACKEND_PROGRAM_INFO_CHANGED, msg = %s", *back_msg_action );
rosfran@343
   354
	    		msg_type = GMYTH_BACKEND_PROGRAM_INFO_CHANGED;
rosfran@343
   355
	    	} else if ( g_strstr_len( *back_msg_action, strlen( *back_msg_action ), "DONE_RECORDING" ) ) {
rosfran@343
   356
	    		gmyth_debug( "MONITOR: message type == GMYTH_BACKEND_DONE_RECORDING, msg = %s", *back_msg_action );
rosfran@343
   357
	    		msg_type = GMYTH_BACKEND_DONE_RECORDING;
rosfran@374
   358
	    	} else if ( g_strstr_len( *back_msg_action, strlen( *back_msg_action ), "QUIT" ) ) {
rosfran@374
   359
	    		gmyth_debug( "MONITOR: message type == GMYTH_BACKEND_STOP_LIVETV, msg = %s", *back_msg_action );
rosfran@374
   360
	    		msg_type = GMYTH_BACKEND_STOP_LIVETV;	    		
rosfran@374
   361
	  		}	    	
rosfran@216
   362
	
rosfran@374
   363
	      /* g_hash_table_insert ( monitor->backend_msgs,
rosfran@374
   364
	                             &(monitor->actual_index), *back_msg_action ); */
rosfran@343
   365
		    
rosfran@360
   366
		  } /*  if  */
rosfran@360
   367
		  
rosfran@360
   368
		} /* if */
rosfran@343
   369
		
rosfran@343
   370
		if ( back_msg != NULL )
rosfran@343
   371
		{
rosfran@343
   372
			g_string_free( back_msg, TRUE );
rosfran@343
   373
			back_msg = NULL;        	
rosfran@343
   374
		}
rosfran@343
   375
		
rosfran@343
   376
	} /* if - Does Monitor got any message from backend? */
rosfran@343
   377
	else {
rosfran@343
   378
		*back_msg_action = g_strdup("");
rosfran@216
   379
	}
rosfran@216
   380
	
rosfran@216
   381
	return msg_type;
rosfran@212
   382
rosfran@212
   383
}
rosfran@212
   384
rosfran@212
   385
static void
rosfran@232
   386
gmyth_monitor_handler_default_listener( GMythMonitorHandler *monitor, gint msg_code, gchar* message )
rosfran@212
   387
{
rosfran@212
   388
	//assert( message!= NULL );  
rosfran@232
   389
	gmyth_debug( "DEFAULT Signal handler ( msg = %s, code = %d )\n", 
rosfran@232
   390
				message, msg_code );
rosfran@212
   391
}
rosfran@212
   392
rosfran@198
   393
static void
rosfran@199
   394
gmyth_monitor_handler_print( GString *str, gpointer ptr )
rosfran@199
   395
{
rosfran@212
   396
	gmyth_debug( "Backend message event: %s --- ", str->str );
rosfran@199
   397
}
rosfran@199
   398
rosfran@419
   399
/** 
rosfran@419
   400
 * Opens connection the the Monitor socket on MythTV backend server,
rosfran@419
   401
 * where all status messages are notified to the client.
rosfran@419
   402
 * 
rosfran@419
   403
 * @param io_channel The GIOChannel instance to the Monitor connection.
rosfran@419
   404
 * @param io_cond The GIOCondition describing the actual status of the IO Channel.
rosfran@419
   405
 * @param data Pointer to the GMythMonitorHandler.
rosfran@419
   406
 * 
rosfran@419
   407
 * @return <code>true</code>, if the data was successfully read.
rosfran@419
   408
 */
rosfran@347
   409
gboolean
rosfran@347
   410
gmyth_monitor_handler_listener( GIOChannel *io_channel, GIOCondition io_cond, gpointer data )
rosfran@175
   411
{
rosfran@347
   412
	GMythMonitorHandler *monitor = (GMythMonitorHandler*)data; 
rosfran@175
   413
  guint recv = 0;
leo_sobral@444
   414
  gboolean ret = TRUE;
rosfran@175
   415
  gsize len = 0;
rosfran@175
   416
  
rosfran@199
   417
  static guint count = 0;
rosfran@362
   418
rosfran@362
   419
  myth_control_acquire_context ( monitor, TRUE );
rosfran@198
   420
  
leo_sobral@444
   421
  if ( ( io_cond & G_IO_HUP ) != 0 ) {
leo_sobral@444
   422
  	ret = FALSE;
rosfran@358
   423
  	goto clean_up;
leo_sobral@444
   424
  }
rosfran@358
   425
  
rosfran@347
   426
  //GIOChannel *io_channel = monitor->event_sock->sd_io_ch;
rosfran@203
   427
  //GIOCondition condition = g_io_channel_get_buffer_condition( io_channel );
rosfran@199
   428
  
rosfran@199
   429
  GMythStringList *strlist = NULL;
rosfran@198
   430
  
rosfran@353
   431
  if ( NULL == io_channel ) {
rosfran@419
   432
  	gmyth_debug ("Monitor socket is NULL! (GIOChannel)");
leo_sobral@444
   433
  	ret = FALSE;
rosfran@175
   434
  	goto clean_up;
rosfran@175
   435
  }
rosfran@198
   436
    
rosfran@353
   437
  if (monitor->allow_msgs_listener) {
rosfran@198
   438
  	++count;
rosfran@198
   439
  	
rosfran@198
   440
  	gmyth_debug ("%d - Listening on Monitor socket...!\n", count);
rosfran@175
   441
	
rosfran@199
   442
    do 
rosfran@199
   443
    {
rosfran@199
   444
    	
rosfran@199
   445
    	gint bytes_sent = 0;
rosfran@199
   446
    	
rosfran@199
   447
    	strlist = gmyth_string_list_new();
rosfran@220
   448
    	
rosfran@220
   449
    	if ( monitor->event_sock != NULL )
rosfran@220
   450
    	{
rosfran@220
   451
    		
rosfran@220
   452
	      len = gmyth_socket_read_stringlist( monitor->event_sock, strlist );
rosfran@199
   453
	      
rosfran@353
   454
		    if ( ( len > 0 ) && strlist != NULL && gmyth_string_list_length( strlist ) > 0 ) 
rosfran@220
   455
		    { 
rosfran@220
   456
			    bytes_sent = gmyth_string_list_get_int( strlist,  0 ); // -1 on backend error
rosfran@220
   457
	
rosfran@220
   458
		      gmyth_debug ( "[%s] MONITOR: received data buffer from IO event channel... %d strings gone!\n", 
rosfran@220
   459
		      		__FUNCTION__, len );
rosfran@220
   460
		      		
rosfran@220
   461
		      recv += len;
rosfran@220
   462
		      
rosfran@220
   463
		      /* debug purpose: prints out all the string list elements */
rosfran@220
   464
		      g_list_foreach( strlist->glist, (GFunc)gmyth_monitor_handler_print, NULL );
rosfran@220
   465
		      
rosfran@220
   466
		      gchar *back_msg_action = g_new0( gchar, 1 );
rosfran@220
   467
		      gint msg_type = gmyth_monitor_handler_is_backend_message( monitor, strlist, 
rosfran@220
   468
		      		&back_msg_action );
rosfran@343
   469
		      		
rosfran@343
   470
		      if (monitor!=NULL)		      
rosfran@353
   471
		        g_signal_emit ( monitor,
rosfran@353
   472
		               GMYTH_MONITOR_HANDLER_GET_CLASS (monitor)->backend_events_handler_signal_id,
rosfran@353
   473
		               0, /* details */
rosfran@353
   474
		               msg_type, back_msg_action );
rosfran@220
   475
	               
rosfran@220
   476
	        if (back_msg_action!= NULL)
rosfran@220
   477
	        	g_free( back_msg_action );
rosfran@220
   478
		      
rosfran@220
   479
		    }
rosfran@220
   480
		    
rosfran@220
   481
    	}
rosfran@199
   482
	    
rosfran@199
   483
	    if (strlist!=NULL)
rosfran@353
   484
	    {
rosfran@199
   485
	    	g_object_unref( strlist );
rosfran@353
   486
	    	strlist = NULL;
rosfran@353
   487
	    }
rosfran@358
   488
renatofilho@464
   489
      io_cond = g_io_channel_get_buffer_condition (io_channel);
rosfran@199
   490
rosfran@358
   491
    } while ( recv <= 0 && ( ( io_cond & G_IO_HUP ) == 0 ) );
rosfran@199
   492
    
rosfran@353
   493
    gmyth_debug ("\tMONITOR EVENT: Read %d bytes\n", recv );
rosfran@203
   494
rosfran@203
   495
  } /* main GThread while */
rosfran@198
   496
  
rosfran@175
   497
clean_up:
rosfran@362
   498
  myth_control_release_context (monitor);
rosfran@220
   499
  	
leo_sobral@444
   500
 	return ret;
rosfran@199
   501
rosfran@175
   502
}
rosfran@175
   503
rosfran@419
   504
/** 
rosfran@419
   505
 * Opens connection events' socket the the Monitor socket on 
rosfran@419
   506
 * MythTV backend server.
rosfran@419
   507
 * 
rosfran@419
   508
 * @param monitor The GMythMonitorHandler instance.
rosfran@419
   509
 * 
rosfran@419
   510
 * @return <code>true</code>, if the socket was successfully opened.
rosfran@419
   511
 */
rosfran@175
   512
static gboolean
rosfran@175
   513
gmyth_connect_to_backend_monitor (GMythMonitorHandler *monitor)
rosfran@175
   514
{
rosfran@175
   515
  gboolean ret = TRUE;
rosfran@175
   516
melunko@276
   517
  monitor->event_sock = gmyth_socket_new();
rosfran@175
   518
rosfran@175
   519
  /* Connects the socket, send Mythtv ANN Monitor and verify Mythtv protocol version */ 
rosfran@175
   520
  if (!gmyth_socket_connect_to_backend_events ( monitor->event_sock,
rosfran@175
   521
          monitor->hostname, monitor->port, FALSE ) ) 
rosfran@175
   522
  {
rosfran@175
   523
    g_object_unref (monitor->event_sock);
rosfran@175
   524
    monitor->event_sock = NULL;
rosfran@175
   525
    ret = FALSE;
rosfran@175
   526
  }
rosfran@175
   527
  
rosfran@175
   528
  return ret;
rosfran@175
   529
}    
rosfran@175
   530
rosfran@419
   531
/** 
rosfran@419
   532
 * Opens connection the the Monitor socket on MythTV backend server,
rosfran@419
   533
 * where all status messages are notified to the client.
rosfran@419
   534
 * 
rosfran@419
   535
 * @param monitor The GMythMonitorHandler instance.
rosfran@419
   536
 * @param channel The GIOChannel instance to the Monitor socket.
rosfran@419
   537
 * 
rosfran@419
   538
 * @return Pointer to the boolean value, and it is <code>true</code> only if the 
rosfran@419
   539
 * 				 GMythMonitorHandler could be configured.
rosfran@419
   540
 */
leo_sobral@446
   541
static gboolean
rosfran@220
   542
gmyth_monitor_handler_setup( GMythMonitorHandler *monitor, GIOChannel *channel )
rosfran@192
   543
{
leo_sobral@446
   544
	gboolean ret = TRUE;
rosfran@192
   545
	
rosfran@192
   546
  if ( channel != NULL ) {
rosfran@360
   547
  	
rosfran@360
   548
  	monitor->allow_msgs_listener = TRUE;
rosfran@449
   549
    
rosfran@449
   550
    monitor->sid_io_watch = -1;
rosfran@360
   551
  	
renatofilho@464
   552
    monitor->sid_io_watch = g_io_add_watch (channel, G_IO_IN | G_IO_HUP, 
rosfran@220
   553
    					(GIOFunc)gmyth_monitor_handler_listener, monitor );
rosfran@192
   554
  } else {
leo_sobral@446
   555
  	ret = FALSE;
rosfran@192
   556
  	goto cleanup;
rosfran@192
   557
  }
rosfran@192
   558
rosfran@360
   559
  if (monitor->sid_io_watch < 0){
rosfran@192
   560
    gmyth_debug( "[%s] Error adding watch listener function to the IO control channel!\n", __FUNCTION__ );
leo_sobral@446
   561
    ret = FALSE;
rosfran@192
   562
    goto cleanup;
rosfran@192
   563
  }
rosfran@192
   564
  
rosfran@192
   565
cleanup:
rosfran@198
   566
    
rosfran@192
   567
  return ret;
rosfran@192
   568
  
rosfran@192
   569
}
rosfran@192
   570
rosfran@419
   571
/** 
rosfran@419
   572
 * Starts the MonitorHandler thread to the GIOWatcher.
rosfran@419
   573
 * 
rosfran@419
   574
 * @param monitor The GMythMonitorHandler instance.
rosfran@419
   575
 * 
rosfran@419
   576
 * @return <code>true</code>, if the MonitorHandler was started.
rosfran@419
   577
 */
rosfran@175
   578
gboolean 
rosfran@175
   579
gmyth_monitor_handler_start (GMythMonitorHandler *monitor)
rosfran@175
   580
{
renatofilho@464
   581
    gboolean ret = TRUE;
rosfran@192
   582
	
renatofilho@464
   583
    ret = gmyth_monitor_handler_setup( monitor, monitor->event_sock->sd_io_ch ); 
renatofilho@464
   584
    if ( ret ) {
renatofilho@464
   585
  	    gmyth_debug ( "\n[%s]\tOK! Starting listener on the MONITOR event socket...[thread location = %p]\n", 
rosfran@192
   586
  				__FUNCTION__, g_thread_self( ) );
renatofilho@464
   587
  	    ret = TRUE;  	  	
renatofilho@464
   588
    } else {
renatofilho@464
   589
  	    gmyth_debug ( "\n[%s]\tERROR! Coudn't start listener on the MONITOR event socket...[thread location = %p]\n", 
rosfran@198
   590
  				__FUNCTION__, g_thread_self( ) );
renatofilho@464
   591
  	    ret = FALSE;
renatofilho@464
   592
    }
rosfran@175
   593
renatofilho@464
   594
    gmyth_debug( "[%s] Watch listener function over the IO control channel? %s!!!\n", 
leo_sobral@446
   595
  			__FUNCTION__, ( ret == TRUE ? "YES" : "NO" ) );
rosfran@175
   596
    
leo_sobral@446
   597
    return ret;
rosfran@175
   598
}