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