gmyth/src/gmyth_monitor_handler.c
author rosfran
Tue Dec 05 21:57:35 2006 +0000 (2006-12-05)
branchtrunk
changeset 198 109630cf20ef
parent 192 b13b1e81f5af
child 199 4bed4ce6b681
permissions -rw-r--r--
[svn r199] Fixed problem with COxa.
rosfran@175
     1
/* vim: set sw=2: -*- Mode: C; tab-width: 2; indent-tabs-mode: t; c-basic-offset: 2; c-indent-level: 2-*- */
rosfran@175
     2
/**
rosfran@175
     3
 * GMyth Library
rosfran@175
     4
 *
rosfran@175
     5
 * @file gmyth/gmyth_monitor_handler.c
rosfran@175
     6
 * 
rosfran@175
     7
 * @brief <p> GMythMonitorHandler deals with the streaming media events remote/local
rosfran@175
     8
 * that are sent to the MythTV frontend.
rosfran@175
     9
 *
rosfran@175
    10
 * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
rosfran@175
    11
 * @author Rosfran Lins Borges <rosfran.borges@indt.org.br>
rosfran@175
    12
 *
rosfran@175
    13
 *//*
rosfran@175
    14
 * 
rosfran@175
    15
 * This program is free software; you can redistribute it and/or modify
rosfran@175
    16
 * it under the terms of the GNU Lesser General Public License as published by
rosfran@175
    17
 * the Free Software Foundation; either version 2 of the License, or
rosfran@175
    18
 * (at your option) any later version.
rosfran@175
    19
 *
rosfran@175
    20
 * This program is distributed in the hope that it will be useful,
rosfran@175
    21
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
rosfran@175
    22
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
rosfran@175
    23
 * GNU General Public License for more details.
rosfran@175
    24
 *
rosfran@175
    25
 * You should have received a copy of the GNU Lesser General Public License
rosfran@175
    26
 * along with this program; if not, write to the Free Software
rosfran@175
    27
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
rosfran@175
    28
 *
rosfran@175
    29
 * GStreamer MythTV plug-in properties:
rosfran@175
    30
 * - location (backend server hostname/URL) [ex.: myth://192.168.1.73:28722/1000_1092091.nuv]
rosfran@175
    31
 * - path (qurl - remote file to be opened)
rosfran@175
    32
 * - port number *   
rosfran@175
    33
 */
rosfran@175
    34
rosfran@175
    35
#include "gmyth_uri.h"
rosfran@175
    36
#include "gmyth_livetv.h"
rosfran@175
    37
#include "gmyth_util.h"
rosfran@175
    38
#include "gmyth_socket.h"
rosfran@175
    39
#include "gmyth_stringlist.h"
rosfran@175
    40
#include "gmyth_monitor_handler.h"
rosfran@175
    41
#include "gmyth_debug.h"
rosfran@175
    42
rosfran@175
    43
#include <unistd.h>
rosfran@175
    44
#include <glib.h>
rosfran@175
    45
rosfran@175
    46
#include <arpa/inet.h>
rosfran@175
    47
#include <sys/types.h>
rosfran@175
    48
#include <sys/socket.h>
rosfran@175
    49
#include <netdb.h>
rosfran@175
    50
#include <errno.h>
rosfran@175
    51
#include <stdlib.h>
rosfran@175
    52
#include <assert.h>
rosfran@175
    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@192
    73
GMainContext *io_watcher_context = NULL;
rosfran@192
    74
rosfran@198
    75
GThreadPool *monitor_th = NULL;
rosfran@175
    76
rosfran@175
    77
enum myth_sock_types {
rosfran@175
    78
  GMYTH_PLAYBACK_TYPE = 0,
rosfran@175
    79
  GMYTH_MONITOR_TYPE,
rosfran@175
    80
  GMYTH_FILETRANSFER_TYPE,
rosfran@175
    81
  GMYTH_RINGBUFFER_TYPE
rosfran@175
    82
};
rosfran@175
    83
rosfran@192
    84
//static gboolean* myth_control_sock_listener( GIOChannel *io_channel );
rosfran@198
    85
//static gboolean myth_control_sock_listener( GIOChannel *io_channel, GIOCondition condition, 
rosfran@198
    86
//				gpointer data );
rosfran@198
    87
rosfran@198
    88
static void myth_control_sock_listener( GIOChannel *io_channel, gboolean* ret );
rosfran@175
    89
rosfran@175
    90
static GMutex*				mutex 					 = NULL;
rosfran@175
    91
rosfran@175
    92
static GCond*					io_watcher_cond  = NULL;
rosfran@175
    93
rosfran@175
    94
static void gmyth_monitor_handler_class_init          (GMythMonitorHandlerClass *klass);
rosfran@175
    95
static void gmyth_monitor_handler_init                (GMythMonitorHandler *object);
rosfran@175
    96
rosfran@175
    97
static void gmyth_monitor_handler_dispose  (GObject *object);
rosfran@175
    98
static void gmyth_monitor_handler_finalize (GObject *object);
rosfran@175
    99
rosfran@175
   100
static gboolean gmyth_connect_to_backend_monitor (GMythMonitorHandler *monitor);
rosfran@175
   101
rosfran@175
   102
void gmyth_monitor_handler_close( GMythMonitorHandler *monitor );
rosfran@175
   103
rosfran@175
   104
G_DEFINE_TYPE(GMythMonitorHandler, gmyth_monitor_handler, G_TYPE_OBJECT)
rosfran@175
   105
rosfran@175
   106
static void
rosfran@175
   107
gmyth_monitor_handler_class_init (GMythMonitorHandlerClass *klass)
rosfran@175
   108
{
rosfran@175
   109
  GObjectClass *gobject_class;
rosfran@175
   110
rosfran@175
   111
  gobject_class = (GObjectClass *) klass;
rosfran@175
   112
rosfran@175
   113
  gobject_class->dispose  = gmyth_monitor_handler_dispose;
rosfran@175
   114
  gobject_class->finalize = gmyth_monitor_handler_finalize;
rosfran@175
   115
}
rosfran@175
   116
rosfran@175
   117
static void
rosfran@175
   118
gmyth_monitor_handler_init (GMythMonitorHandler *monitor)
rosfran@175
   119
{ 
rosfran@175
   120
  g_return_if_fail( monitor != NULL );
rosfran@175
   121
rosfran@175
   122
  monitor->event_sock = NULL;
rosfran@175
   123
  monitor->hostname = NULL;
rosfran@175
   124
  monitor->port = 0;
rosfran@175
   125
  monitor->actual_index = 0;
rosfran@175
   126
  
rosfran@175
   127
  monitor->backend_msgs = g_hash_table_new( g_int_hash, g_int_equal );
rosfran@175
   128
    
rosfran@175
   129
  /* it is used for signalizing the event socket consumer thread */
rosfran@175
   130
  io_watcher_cond = g_cond_new();
rosfran@175
   131
  
rosfran@175
   132
  /* mutex to control access to the event socket consumer thread */
rosfran@175
   133
  mutex = g_mutex_new();
rosfran@175
   134
}
rosfran@175
   135
rosfran@175
   136
static void
rosfran@175
   137
gmyth_monitor_handler_dispose  (GObject *object)
rosfran@175
   138
{
rosfran@192
   139
	
rosfran@192
   140
	GMythMonitorHandler *monitor = GMYTH_MONITOR_HANDLER (object);
rosfran@192
   141
	
rosfran@192
   142
  if ( monitor->event_sock != NULL )  
rosfran@192
   143
  {
rosfran@192
   144
  	g_object_unref( monitor->event_sock );
rosfran@192
   145
  	monitor->event_sock = NULL;
rosfran@192
   146
  }
rosfran@192
   147
  
rosfran@192
   148
  if ( monitor->hostname != NULL )  
rosfran@192
   149
  {
rosfran@192
   150
  	g_free( monitor->hostname );
rosfran@192
   151
  	monitor->hostname = NULL;
rosfran@192
   152
  }
rosfran@192
   153
rosfran@192
   154
  if ( monitor->backend_msgs != NULL )  
rosfran@192
   155
  {
rosfran@192
   156
  	g_hash_table_unref( monitor->backend_msgs );
rosfran@192
   157
  	monitor->backend_msgs = NULL;
rosfran@192
   158
  }
rosfran@192
   159
  
rosfran@192
   160
  if ( mutex != NULL )  
rosfran@192
   161
  {
rosfran@192
   162
  	g_mutex_free( mutex );
rosfran@192
   163
  	mutex = NULL;
rosfran@192
   164
  }
rosfran@192
   165
  
rosfran@192
   166
  if ( io_watcher_cond != NULL )  
rosfran@192
   167
  {
rosfran@192
   168
  	g_cond_free( io_watcher_cond );
rosfran@192
   169
  	io_watcher_cond = NULL;
rosfran@192
   170
  }
rosfran@192
   171
  
rosfran@192
   172
  if ( monitor_th != NULL )  
rosfran@192
   173
  {
rosfran@198
   174
  	g_thread_pool_free( monitor_th, TRUE, FALSE );
rosfran@198
   175
  	//g_object_unref( monitor_th );
rosfran@192
   176
  	monitor_th = NULL;
rosfran@192
   177
  }
rosfran@192
   178
rosfran@175
   179
  G_OBJECT_CLASS (gmyth_monitor_handler_parent_class)->dispose (object);
rosfran@175
   180
}
rosfran@175
   181
rosfran@175
   182
static void
rosfran@175
   183
gmyth_monitor_handler_finalize (GObject *object)
rosfran@175
   184
{
rosfran@175
   185
  g_signal_handlers_destroy (object);
rosfran@175
   186
rosfran@175
   187
  G_OBJECT_CLASS (gmyth_monitor_handler_parent_class)->finalize (object);
rosfran@175
   188
}
rosfran@175
   189
rosfran@175
   190
// fixme: do we need the card_id????
rosfran@175
   191
GMythMonitorHandler*
rosfran@175
   192
gmyth_monitor_handler_new (void)
rosfran@175
   193
{
rosfran@175
   194
  GMythMonitorHandler *monitor = GMYTH_MONITOR_HANDLER ( g_object_new (
rosfran@175
   195
				GMYTH_MONITOR_HANDLER_TYPE, FALSE ));
rosfran@175
   196
rosfran@175
   197
  return monitor;
rosfran@175
   198
}
rosfran@175
   199
rosfran@175
   200
gboolean
rosfran@175
   201
gmyth_monitor_handler_open (GMythMonitorHandler *monitor, gchar *hostname, gint port)
rosfran@175
   202
{
rosfran@175
   203
  gboolean ret = TRUE;
rosfran@175
   204
rosfran@175
   205
  if (monitor->hostname != NULL) {
rosfran@175
   206
    g_free (monitor->hostname);
rosfran@175
   207
    monitor->hostname = NULL;
rosfran@175
   208
  }
rosfran@175
   209
rosfran@175
   210
  monitor->hostname = g_strdup( hostname );
rosfran@175
   211
  monitor->port = port;
rosfran@175
   212
rosfran@175
   213
  gmyth_debug ("Monitor event socket --- hostname: %s, port %d\n", monitor->hostname, monitor->port);
rosfran@175
   214
  
rosfran@175
   215
  /* configure the event socket */
rosfran@175
   216
  if (monitor->event_sock == NULL) { 
rosfran@175
   217
    if (!gmyth_connect_to_backend_monitor (monitor)) {
rosfran@175
   218
      g_printerr( "Connection to backend failed (Event Socket).\n" );
rosfran@175
   219
      ret = FALSE;
rosfran@175
   220
    }
rosfran@175
   221
  } else {
rosfran@175
   222
    g_warning("Remote monitor event socket already created.\n");
rosfran@175
   223
  }
rosfran@175
   224
rosfran@175
   225
  return ret;
rosfran@175
   226
rosfran@175
   227
}
rosfran@175
   228
rosfran@198
   229
static void
rosfran@198
   230
//myth_control_sock_listener( GIOChannel *io_channel, GIOCondition condition, gpointer data )
rosfran@198
   231
myth_control_sock_listener( GIOChannel *io_channel, gboolean* ret )
rosfran@175
   232
{
rosfran@175
   233
rosfran@175
   234
  GIOStatus io_status;
rosfran@175
   235
  GError *error = NULL;
rosfran@175
   236
  GIOCondition io_cond;
rosfran@198
   237
  GIOCondition condition;
rosfran@175
   238
  gchar *trash = NULL;
rosfran@175
   239
  GByteArray *byte_array = NULL;
rosfran@175
   240
  guint recv = 0;
rosfran@198
   241
  ret = g_new0( gboolean, 1 );
rosfran@198
   242
  *ret = TRUE;
rosfran@198
   243
  //gboolean ret = TRUE;
rosfran@175
   244
  gsize len = 0;
rosfran@175
   245
  
rosfran@198
   246
  static guint count = 0;  
rosfran@198
   247
  
rosfran@198
   248
  
rosfran@175
   249
  //GMythMonitorHandler *monitor = (GMythMonitorHandler*)data;
rosfran@175
   250
  
rosfran@175
   251
  //myth_control_acquire_context (TRUE);
rosfran@175
   252
  
rosfran@175
   253
  if ( io_channel == NULL ) {
rosfran@175
   254
  	g_debug ("Monitor socket is NULL!\n");
rosfran@198
   255
  	*ret = FALSE;
rosfran@175
   256
  	goto clean_up;
rosfran@175
   257
  }
rosfran@198
   258
    
rosfran@198
   259
  while (TRUE) {
rosfran@198
   260
  	++count;
rosfran@198
   261
  	
rosfran@198
   262
  	gmyth_debug ("%d - Listening on Monitor socket...!\n", count);
rosfran@175
   263
	  	
rosfran@198
   264
	  condition = g_io_channel_get_buffer_condition( io_channel );	  
rosfran@175
   265
	  //while ( !has_io_access ) 
rosfran@175
   266
	  //	g_cond_wait( io_watcher_cond, mutex );
rosfran@175
   267
	  	
rosfran@175
   268
	  //myth_control_acquire_context (TRUE);  
rosfran@175
   269
	  
rosfran@175
   270
	  if (condition & G_IO_HUP) {
rosfran@175
   271
	    gmyth_debug ("Read end of pipe died!\n");
rosfran@192
   272
	    ret = FALSE;
rosfran@186
   273
	    //goto clean_up;
rosfran@175
   274
	  }
rosfran@175
   275
	    
rosfran@198
   276
	  //if ( ( condition & G_IO_IN ) != 0 ) {
rosfran@175
   277
	  	byte_array = g_byte_array_new();
rosfran@175
   278
	  	io_status = g_io_channel_set_encoding( io_channel, NULL, &error );
rosfran@175
   279
	  	guint buffer_size = GMYTHTV_BUFFER_SIZE;
rosfran@175
   280
	    do 
rosfran@175
   281
	    {
rosfran@175
   282
	      trash = g_new0( gchar, buffer_size );
rosfran@175
   283
	
rosfran@175
   284
	      io_status = g_io_channel_read_chars( io_channel, trash, 
rosfran@175
   285
	      		buffer_size, &len, &error);
rosfran@175
   286
	
rosfran@175
   287
	      gmyth_debug ( "[%s] Received data buffer from IO binary channel... %d bytes gone!\n", 
rosfran@175
   288
	      		__FUNCTION__, len );
rosfran@175
   289
	      		
rosfran@175
   290
	      recv += len;
rosfran@175
   291
	      
rosfran@175
   292
	      byte_array = g_byte_array_append( byte_array, (const guint8*)trash, len );
rosfran@175
   293
	      
rosfran@175
   294
	      if ( trash != NULL )
rosfran@175
   295
	      	g_free( trash );
rosfran@175
   296
	      	
rosfran@175
   297
	      io_cond = g_io_channel_get_buffer_condition( io_channel );
rosfran@175
   298
	
rosfran@175
   299
	    } while ( ( io_cond & G_IO_IN ) != 0 );
rosfran@198
   300
	    
rosfran@192
   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]" );
rosfran@198
   302
	    
rosfran@198
   303
	  //}	  
rosfran@186
   304
	  
rosfran@186
   305
	  if ( byte_array != NULL ) {
rosfran@186
   306
	  	g_byte_array_free( byte_array, TRUE );
rosfran@186
   307
	  	byte_array = NULL;
rosfran@175
   308
	  }
rosfran@175
   309
	  
rosfran@175
   310
	  g_usleep( 300 );
rosfran@175
   311
	  
rosfran@198
   312
  }
rosfran@198
   313
  
rosfran@198
   314
  if ( io_status == G_IO_STATUS_ERROR || error != NULL ) {
rosfran@175
   315
    gmyth_debug ("[%s] Error reading: %s\n", __FUNCTION__, error != NULL ? error->message : "" );
rosfran@198
   316
   	*ret = FALSE;
rosfran@175
   317
   	goto clean_up;   	
rosfran@175
   318
  }
rosfran@175
   319
  
rosfran@175
   320
  //g_hash_table_insert( monitor->backend_msgs, (gpointer)monitor->actual_index,
rosfran@175
   321
  //				  byte_array->data );
rosfran@175
   322
  
rosfran@175
   323
  //monitor->actual_index += recv;
rosfran@175
   324
rosfran@175
   325
clean_up:
rosfran@198
   326
rosfran@198
   327
  if ( byte_array != NULL ) {
rosfran@198
   328
  	g_byte_array_free( byte_array, TRUE );
rosfran@198
   329
  	byte_array = NULL;
rosfran@198
   330
  }
rosfran@175
   331
  
rosfran@198
   332
  //return ret;
rosfran@175
   333
rosfran@175
   334
}
rosfran@175
   335
rosfran@175
   336
static gboolean
rosfran@175
   337
gmyth_connect_to_backend_monitor (GMythMonitorHandler *monitor)
rosfran@175
   338
{
rosfran@175
   339
  gboolean ret = TRUE;
rosfran@175
   340
rosfran@175
   341
  /* Creates the event socket */
rosfran@175
   342
  if (monitor->event_sock != NULL) {
rosfran@175
   343
    g_object_unref (monitor->event_sock);
rosfran@175
   344
    monitor->event_sock = NULL;
rosfran@175
   345
  }
rosfran@175
   346
rosfran@175
   347
  monitor->event_sock = gmyth_socket_new();
rosfran@175
   348
rosfran@175
   349
  /* Connects the socket, send Mythtv ANN Monitor and verify Mythtv protocol version */ 
rosfran@175
   350
  if (!gmyth_socket_connect_to_backend_events ( monitor->event_sock,
rosfran@175
   351
          monitor->hostname, monitor->port, FALSE ) ) 
rosfran@175
   352
  {
rosfran@175
   353
    g_object_unref (monitor->event_sock);
rosfran@175
   354
    monitor->event_sock = NULL;
rosfran@175
   355
    ret = FALSE;
rosfran@175
   356
  }
rosfran@175
   357
  
rosfran@175
   358
  return ret;
rosfran@175
   359
}    
rosfran@175
   360
rosfran@192
   361
static gboolean*
rosfran@192
   362
myth_control_sock_setup( GIOChannel *channel )
rosfran@192
   363
{
rosfran@192
   364
	gboolean *ret = g_new0( gboolean, 1 );
rosfran@198
   365
	//guint src_id = 0;
rosfran@192
   366
	
rosfran@192
   367
	*ret = TRUE;
rosfran@192
   368
	
rosfran@192
   369
  io_watcher_context = g_main_context_default();
rosfran@198
   370
  GMainLoop *loop = g_main_loop_new( io_watcher_context, TRUE );
rosfran@192
   371
rosfran@192
   372
  GSource *source;
rosfran@192
   373
rosfran@192
   374
  if ( channel != NULL ) {
rosfran@192
   375
    source = g_io_create_watch( channel, G_IO_IN | G_IO_HUP );
rosfran@198
   376
    //src_id = g_io_add_watch( channel, G_IO_IN | G_IO_HUP, 
rosfran@198
   377
    //					(GSourceFunc)myth_control_sock_listener, NULL );
rosfran@192
   378
  } else {
rosfran@192
   379
  	*ret = FALSE;
rosfran@192
   380
  	goto cleanup;
rosfran@192
   381
  }
rosfran@192
   382
rosfran@192
   383
  g_source_set_callback ( source, (GSourceFunc)myth_control_sock_listener, NULL, NULL );
rosfran@192
   384
rosfran@192
   385
  g_source_attach( source, io_watcher_context );
rosfran@192
   386
  
rosfran@198
   387
  if (NULL == source){
rosfran@192
   388
    gmyth_debug( "[%s] Error adding watch listener function to the IO control channel!\n", __FUNCTION__ );
rosfran@192
   389
    *ret = FALSE;
rosfran@192
   390
    goto cleanup;
rosfran@192
   391
  }
rosfran@192
   392
  
rosfran@198
   393
  g_main_loop_run( loop );
rosfran@192
   394
  
rosfran@192
   395
cleanup:
rosfran@198
   396
  if ( source != NULL )
rosfran@198
   397
    g_source_unref( source );
rosfran@198
   398
    
rosfran@198
   399
  //if ( io_watcher_context != NULL )
rosfran@198
   400
  //  g_main_context_unref( io_watcher_context );
rosfran@198
   401
rosfran@198
   402
  //if ( loop != NULL )
rosfran@198
   403
  //  g_main_loop_unref( loop );
rosfran@198
   404
    
rosfran@192
   405
  return ret;
rosfran@192
   406
  
rosfran@192
   407
}
rosfran@192
   408
rosfran@175
   409
gboolean 
rosfran@175
   410
gmyth_monitor_handler_start (GMythMonitorHandler *monitor)
rosfran@175
   411
{
rosfran@192
   412
	gboolean *ret = g_new0( gboolean, 1 ); 
rosfran@192
   413
	*ret = TRUE;	
rosfran@192
   414
	
rosfran@198
   415
	if (!g_thread_supported () ) 	g_thread_init (NULL);
rosfran@192
   416
	
rosfran@198
   417
  monitor_th = g_thread_pool_new( (GFunc)myth_control_sock_listener, 
rosfran@198
   418
  					monitor->event_sock->sd_io_ch, 3, FALSE, NULL );
rosfran@192
   419
  					
rosfran@198
   420
  //if ( ( ret = g_thread_join( monitor_th ) ) == FALSE )
rosfran@198
   421
  if ( monitor_th != NULL )
rosfran@192
   422
  {
rosfran@192
   423
  	gmyth_debug ( "\n[%s]\tOK! Starting listener on the MONITOR event socket...[thread location = %p]\n", 
rosfran@192
   424
  				__FUNCTION__, g_thread_self( ) );
rosfran@198
   425
  	*ret = TRUE;  	  	
rosfran@198
   426
  } else {
rosfran@198
   427
  	gmyth_debug ( "\n[%s]\tERROR! Coudn't start listener on the MONITOR event socket...[thread location = %p]\n", 
rosfran@198
   428
  				__FUNCTION__, g_thread_self( ) );
rosfran@198
   429
  	*ret = FALSE;
rosfran@192
   430
  }
rosfran@175
   431
rosfran@198
   432
//cleanup:
rosfran@192
   433
    
rosfran@192
   434
  gmyth_debug( "[%s] Watch listener function over the IO control channel? %s!!!\n", 
rosfran@192
   435
  			__FUNCTION__, ( *ret == TRUE ? "YES" : "NO" ) );
rosfran@175
   436
    
rosfran@198
   437
    return *ret;
rosfran@175
   438
}
rosfran@175
   439
rosfran@175
   440
void
rosfran@175
   441
gmyth_monitor_handler_close( GMythMonitorHandler *monitor )
rosfran@175
   442
{
rosfran@175
   443
	
rosfran@175
   444
  if (monitor->event_sock) {
rosfran@175
   445
    g_object_unref( monitor->event_sock );
rosfran@175
   446
    monitor->event_sock = NULL;
rosfran@175
   447
  }
rosfran@175
   448
rosfran@175
   449
  if (monitor->hostname) {
rosfran@175
   450
    g_free( monitor->hostname );
rosfran@175
   451
    monitor->hostname = NULL;
rosfran@175
   452
  }
rosfran@175
   453
  
rosfran@175
   454
}
rosfran@175
   455