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