gmyth-upnp/src/gmyth_upnp.c
author melunko
Thu Feb 28 08:10:55 2008 +0000 (2008-02-28)
branchtrunk
changeset 932 58d43e2186ba
parent 915 e612ba1d16ab
child 938 d2bfa2e06cfa
permissions -rw-r--r--
[svn r941] gmyth-dbus-server mysql connection timeout increased to 10seconds
melunko@250
     1
/**
melunko@250
     2
 * GMyth Library
melunko@250
     3
 *
melunko@250
     4
 * @file gmyth/gmyth_upnp.c
melunko@250
     5
 * 
melunko@250
     6
 * @brief <p> GMythUPnP allows that a MythTV frontend discovers a 
melunko@250
     7
 * MythTV backend, using the UPnP architecture.
melunko@250
     8
 *
melunko@250
     9
 * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia.
melunko@250
    10
 * @author Rosfran Lins Borges <rosfran.borges@indt.org.br>
renatofilho@922
    11
 * @authon Renato Araujo Oliveira Filho <renato.filho@indt.org.br>
melunko@250
    12
 *
renatofilho@922
    13
 * This library is free software; you can redistribute it and/or
renatofilho@922
    14
 * modify it under the terms of the GNU Library General Public
renatofilho@922
    15
 * License as published by the Free Software Foundation; either
renatofilho@922
    16
 * version 2 of the License, or (at your option) any later version.
renatofilho@922
    17
 *
renatofilho@922
    18
 * This library is distributed in the hope that it will be useful,
melunko@250
    19
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
renatofilho@922
    20
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
renatofilho@922
    21
 * Library General Public License for more details.
melunko@250
    22
 *
renatofilho@922
    23
 * You should have received a copy of the GNU Library General Public
renatofilho@922
    24
 * License along with this library; if not, write to the
renatofilho@922
    25
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
renatofilho@922
    26
 * Boston, MA 02111-1307, USA.
melunko@250
    27
 */
melunko@250
    28
melunko@250
    29
#ifdef HAVE_CONFIG_H
melunko@250
    30
#include "config.h"
melunko@250
    31
#endif
melunko@250
    32
melunko@250
    33
#include "gmyth_upnp.h"
melunko@250
    34
renatofilho@909
    35
#include <gmyth/gmyth.h>
renatofilho@909
    36
#include <upnp/upnp.h>
renatofilho@909
    37
#include <string.h>
melunko@250
    38
melunko@250
    39
renatofilho@909
    40
#define UPNP_SEARCH_TIMEOUT 5
renatofilho@909
    41
#define UPNP_SERVICE_FILTER  "urn:schemas-mythtv-org:service:MythTv:1"
renatofilho@909
    42
#define SERVER_ID           "MythTV AV Media Server"
renatofilho@909
    43
renatofilho@909
    44
typedef struct _GMythUPnPPrivate GMythUPnPPrivate;
renatofilho@909
    45
typedef struct _GMythUPnPIdleData GMythUPnPIdleData;
melunko@250
    46
rosfran@696
    47
#define GMYTH_UPNP_GET_PRIVATE(obj) \
rosfran@696
    48
    (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GMYTH_UPNP_TYPE, GMythUPnPPrivate))
rosfran@696
    49
renatofilho@909
    50
enum
renatofilho@909
    51
{
renatofilho@909
    52
    DEVICE_FOUND,
renatofilho@909
    53
    DEVICE_LOST,
renatofilho@909
    54
    LAST_SIGNAL
renatofilho@909
    55
};
renatofilho@909
    56
renatofilho@909
    57
struct _GMythUPnPIdleData
renatofilho@909
    58
{
renatofilho@909
    59
    GMythUPnP *parent;
renatofilho@909
    60
    GMythBackendInfo *server;
renatofilho@909
    61
};
renatofilho@909
    62
rosfran@696
    63
struct _GMythUPnPPrivate {
renatofilho@909
    64
    GHashTable     *servers;
renatofilho@754
    65
    GMythUPnPDeviceStatus last_status;
renatofilho@754
    66
    gboolean        upnp_dev_found;
renatofilho@754
    67
    gchar          *udn;
renatofilho@754
    68
    GMutex         *mutex;
renatofilho@909
    69
    gint            idle_count;
renatofilho@909
    70
renatofilho@909
    71
    /* upnp */
renatofilho@909
    72
    UpnpClient_Handle client_id;
rosfran@696
    73
};
rosfran@696
    74
renatofilho@909
    75
static void     gmyth_upnp_class_init   (GMythUPnPClass* klass);
renatofilho@909
    76
static void     gmyth_upnp_init         (GMythUPnP* object);
renatofilho@909
    77
static void     gmyth_upnp_dispose      (GObject* object);
renatofilho@909
    78
static void     gmyth_upnp_finalize     (GObject* object);
renatofilho@909
    79
static GObject* gmyth_upnp_constructor  (GType type,
renatofilho@909
    80
                                         guint n_construct_params,
renatofilho@909
    81
                                         GObjectConstructParam *construct_params);
melunko@250
    82
melunko@250
    83
renatofilho@909
    84
static int      _upnp_event_handler     (Upnp_EventType e_type,
renatofilho@909
    85
                                         void* e,
renatofilho@909
    86
                                         void* data);
melunko@250
    87
rosfran@696
    88
renatofilho@909
    89
static int signals[LAST_SIGNAL] = {0};
melunko@250
    90
renatofilho@909
    91
static GMythUPnP *singleton = NULL;
melunko@250
    92
renatofilho@909
    93
G_DEFINE_TYPE(GMythUPnP, gmyth_upnp, G_TYPE_OBJECT);
melunko@250
    94
renatofilho@909
    95
static void
renatofilho@909
    96
gmyth_upnp_class_init(GMythUPnPClass * klass)
melunko@250
    97
{
renatofilho@754
    98
    GObjectClass   *gobject_class;
renatofilho@754
    99
    GMythUPnPClass *gupnp_class;
melunko@250
   100
renatofilho@754
   101
    gobject_class = (GObjectClass *) klass;
renatofilho@754
   102
    gupnp_class = (GMythUPnPClass *) gobject_class;
melunko@250
   103
renatofilho@754
   104
    gobject_class->dispose = gmyth_upnp_dispose;
renatofilho@754
   105
    gobject_class->finalize = gmyth_upnp_finalize;
renatofilho@909
   106
    gobject_class->constructor = gmyth_upnp_constructor;
rosfran@696
   107
renatofilho@909
   108
    g_type_class_add_private (gobject_class, sizeof(GMythUPnPPrivate));
rosfran@696
   109
renatofilho@754
   110
renatofilho@909
   111
renatofilho@909
   112
    signals[DEVICE_FOUND] = g_signal_new("device-found",
renatofilho@909
   113
                                         G_TYPE_FROM_CLASS(gupnp_class),
renatofilho@909
   114
                                         G_SIGNAL_RUN_LAST,
renatofilho@909
   115
                                         0, NULL, NULL,
renatofilho@909
   116
                                         g_cclosure_marshal_VOID__OBJECT,
renatofilho@909
   117
                                         G_TYPE_NONE, 1,
renatofilho@909
   118
                                         GMYTH_BACKEND_INFO_TYPE);
renatofilho@909
   119
renatofilho@909
   120
    signals[DEVICE_LOST] = g_signal_new("device-lost",
renatofilho@909
   121
                                         G_TYPE_FROM_CLASS(gupnp_class),
renatofilho@909
   122
                                         G_SIGNAL_RUN_LAST,
renatofilho@909
   123
                                         0, NULL, NULL,
renatofilho@909
   124
                                         g_cclosure_marshal_VOID__OBJECT,
renatofilho@909
   125
                                         G_TYPE_NONE, 1,
renatofilho@909
   126
                                         GMYTH_BACKEND_INFO_TYPE);
rosfran@696
   127
melunko@250
   128
}
melunko@250
   129
melunko@250
   130
static void
renatofilho@909
   131
gmyth_upnp_init(GMythUPnP* self)
melunko@250
   132
{
renatofilho@909
   133
    gint ret;
renatofilho@909
   134
    GMythUPnPPrivate *priv;
rosfran@696
   135
renatofilho@909
   136
    priv = GMYTH_UPNP_GET_PRIVATE (self);
rosfran@696
   137
renatofilho@909
   138
    priv->mutex = g_mutex_new ();
renatofilho@909
   139
    priv->servers = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
rosfran@696
   140
renatofilho@909
   141
    /* initalize upnp client */
renatofilho@909
   142
    ret = UpnpInit (NULL, 0);
renatofilho@909
   143
    if (ret != UPNP_E_SUCCESS)
renatofilho@909
   144
        g_warning ("Fail to inilialize upnp SDK: %d", ret);
renatofilho@909
   145
    else
renatofilho@909
   146
    {
renatofilho@909
   147
        ret = UpnpRegisterClient (_upnp_event_handler,
renatofilho@909
   148
                                  &priv->client_id, &priv->client_id);
rosfran@696
   149
renatofilho@909
   150
        if (ret != UPNP_E_SUCCESS)
renatofilho@909
   151
            g_warning ("Fail to start upnp client: %d", ret);
renatofilho@909
   152
    }
melunko@250
   153
}
melunko@250
   154
renatofilho@909
   155
static GObject*
renatofilho@909
   156
gmyth_upnp_constructor (GType type,
renatofilho@909
   157
                        guint n_construct_params,
renatofilho@909
   158
                        GObjectConstructParam *construct_params)
melunko@250
   159
{
renatofilho@909
   160
    GObject *object;
renatofilho@754
   161
renatofilho@909
   162
    if (!singleton)
renatofilho@909
   163
    {
renatofilho@909
   164
        object = G_OBJECT_CLASS (gmyth_upnp_parent_class)->constructor (type,
renatofilho@909
   165
                                                             n_construct_params,
renatofilho@909
   166
                                                             construct_params);
rosfran@696
   167
renatofilho@909
   168
        singleton = GMYTH_UPNP (object);
renatofilho@909
   169
    }
renatofilho@909
   170
    else
renatofilho@909
   171
        object = g_object_ref (G_OBJECT (singleton));
rosfran@696
   172
renatofilho@909
   173
    return object;
melunko@250
   174
}
melunko@250
   175
melunko@250
   176
static void
renatofilho@754
   177
gmyth_upnp_dispose(GObject * object)
melunko@250
   178
{
renatofilho@909
   179
    /* finalize upnp client */
renatofilho@909
   180
    UpnpFinish ();
renatofilho@754
   181
    G_OBJECT_CLASS(gmyth_upnp_parent_class)->dispose(object);
melunko@250
   182
}
melunko@250
   183
melunko@250
   184
static void
renatofilho@754
   185
gmyth_upnp_finalize(GObject * object)
melunko@250
   186
{
renatofilho@754
   187
    G_OBJECT_CLASS(gmyth_upnp_parent_class)->finalize(object);
renatofilho@909
   188
    singleton = NULL;
melunko@250
   189
}
melunko@250
   190
renatofilho@909
   191
renatofilho@909
   192
GMythUPnP*
renatofilho@909
   193
gmyth_upnp_get_instance (void)
rosfran@706
   194
{
renatofilho@909
   195
    return GMYTH_UPNP(g_object_new(GMYTH_UPNP_TYPE, NULL));
rosfran@696
   196
}
rosfran@696
   197
renatofilho@909
   198
renatofilho@909
   199
void
renatofilho@909
   200
gmyth_upnp_search (GMythUPnP *self)
rosfran@696
   201
{
renatofilho@909
   202
    int ret;
renatofilho@909
   203
    GMythUPnPPrivate *priv;
renatofilho@909
   204
renatofilho@909
   205
    priv = GMYTH_UPNP_GET_PRIVATE (self);
renatofilho@909
   206
renatofilho@909
   207
    ret = UpnpSearchAsync (priv->client_id,
renatofilho@909
   208
                           UPNP_SEARCH_TIMEOUT,
renatofilho@909
   209
                           UPNP_SERVICE_FILTER,
renatofilho@909
   210
                           NULL);
renatofilho@909
   211
renatofilho@909
   212
    if (ret != UPNP_E_SUCCESS)
renatofilho@909
   213
        g_warning ("Fail to start upnp listener: %d", ret);
renatofilho@754
   214
}
renatofilho@754
   215
renatofilho@915
   216
static void
renatofilho@915
   217
_fill_servers_cb (gpointer key,
renatofilho@915
   218
                  gpointer value,
renatofilho@915
   219
                  gpointer user_data)
renatofilho@915
   220
{
renatofilho@915
   221
    GList **lst;
renatofilho@915
   222
renatofilho@915
   223
    lst = (GList **) user_data;
renatofilho@915
   224
renatofilho@915
   225
    *lst = g_list_append (*lst, g_object_ref (value));
renatofilho@915
   226
}
renatofilho@915
   227
renatofilho@915
   228
GList*
renatofilho@915
   229
gmyth_upnp_get_devices (GMythUPnP *self)
renatofilho@915
   230
{
renatofilho@915
   231
    GMythUPnPPrivate *priv;
renatofilho@915
   232
    GList *lst;
renatofilho@915
   233
renatofilho@915
   234
    priv = GMYTH_UPNP_GET_PRIVATE (self);
renatofilho@915
   235
    lst = NULL;
renatofilho@915
   236
    g_hash_table_foreach (priv->servers, (GHFunc) _fill_servers_cb, &lst);
renatofilho@915
   237
renatofilho@915
   238
    return lst;
renatofilho@915
   239
}
renatofilho@915
   240
renatofilho@909
   241
static gboolean
renatofilho@909
   242
_idle_emit_device_found_signal (gpointer data)
renatofilho@754
   243
{
renatofilho@909
   244
    GMythUPnPPrivate *priv;
renatofilho@909
   245
    GMythUPnPIdleData *idle_data;
renatofilho@909
   246
renatofilho@909
   247
    idle_data = (GMythUPnPIdleData *) data;
renatofilho@909
   248
    priv = GMYTH_UPNP_GET_PRIVATE (idle_data->parent);
renatofilho@909
   249
renatofilho@909
   250
    g_signal_emit (idle_data->parent, signals[DEVICE_FOUND], 0, idle_data->server);
renatofilho@909
   251
renatofilho@909
   252
    g_object_unref (idle_data->server);
renatofilho@909
   253
    g_free (idle_data);
renatofilho@909
   254
    priv->idle_count--;
renatofilho@909
   255
renatofilho@909
   256
    return FALSE;
rosfran@696
   257
}
rosfran@696
   258
renatofilho@909
   259
static gboolean
renatofilho@909
   260
_idle_emit_device_lost_signal (gpointer data)
melunko@250
   261
{
renatofilho@909
   262
    GMythUPnPPrivate *priv;
renatofilho@909
   263
    GMythUPnPIdleData *idle_data;
rosfran@696
   264
renatofilho@909
   265
    idle_data = (GMythUPnPIdleData *) data;
renatofilho@909
   266
    priv = GMYTH_UPNP_GET_PRIVATE (idle_data->parent);
rosfran@696
   267
renatofilho@909
   268
    g_signal_emit (idle_data->parent, signals[DEVICE_LOST], 0, idle_data->server);
rosfran@696
   269
renatofilho@909
   270
    g_object_unref (idle_data->server);
renatofilho@909
   271
    g_free (idle_data);
renatofilho@909
   272
    priv->idle_count--;
rosfran@696
   273
renatofilho@909
   274
    return FALSE;
renatofilho@909
   275
}
renatofilho@909
   276
renatofilho@909
   277
static char*
renatofilho@909
   278
_xml_get_first_document_item (IXML_Document * doc,
renatofilho@909
   279
                              const gchar *item )
renatofilho@909
   280
{
renatofilho@909
   281
    IXML_NodeList *node_list = NULL;
renatofilho@909
   282
    IXML_Node *text_node = NULL;
renatofilho@909
   283
    IXML_Node *tmp_node = NULL;
renatofilho@909
   284
renatofilho@909
   285
    gchar *ret = NULL;
renatofilho@909
   286
renatofilho@909
   287
    node_list = ixmlDocument_getElementsByTagName (doc,
renatofilho@909
   288
                                                  (char *) item);
renatofilho@909
   289
renatofilho@909
   290
    if (node_list)
renatofilho@909
   291
    {
renatofilho@909
   292
        if ((tmp_node = ixmlNodeList_item (node_list, 0))) 
renatofilho@909
   293
        {
renatofilho@909
   294
            text_node = ixmlNode_getFirstChild (tmp_node);
renatofilho@909
   295
renatofilho@909
   296
            ret = strdup (ixmlNode_getNodeValue (text_node));
renatofilho@909
   297
        }
renatofilho@754
   298
    }
rosfran@696
   299
renatofilho@909
   300
    if (node_list)
renatofilho@909
   301
        ixmlNodeList_free (node_list);
rosfran@696
   302
renatofilho@754
   303
    return ret;
rosfran@696
   304
}
rosfran@696
   305
renatofilho@909
   306
rosfran@696
   307
static void
renatofilho@909
   308
_append_mythtv_server_from_loation (GMythUPnP *self,
renatofilho@909
   309
                                    const gchar *uuid,
renatofilho@909
   310
                                    const gchar *location)
rosfran@696
   311
{
renatofilho@909
   312
    GMythUPnPPrivate *priv;
renatofilho@909
   313
    gchar *base_url;
renatofilho@909
   314
    gchar *end;
rosfran@696
   315
renatofilho@909
   316
    priv = GMYTH_UPNP_GET_PRIVATE (self);
rosfran@696
   317
renatofilho@909
   318
    base_url = g_strdup (location);
renatofilho@909
   319
    end = g_strrstr (base_url, "/");
renatofilho@909
   320
    if (end)
renatofilho@909
   321
    {
renatofilho@909
   322
        gint ret;
renatofilho@909
   323
        IXML_Document *desc_doc;
renatofilho@909
   324
        gchar *info_url;
rosfran@696
   325
renatofilho@909
   326
        end[0] = '\0';
renatofilho@909
   327
        info_url = g_strconcat (base_url,
renatofilho@909
   328
                                "Myth/GetConnectionInfo",
renatofilho@909
   329
                                NULL);
renatofilho@909
   330
        g_free (base_url);
renatofilho@909
   331
        desc_doc = NULL;
renatofilho@909
   332
        ret = UpnpDownloadXmlDoc (info_url, &desc_doc);
renatofilho@909
   333
        if (ret != UPNP_E_SUCCESS)
renatofilho@909
   334
        {
renatofilho@909
   335
            g_warning ("Error obtaining device desc: %d", ret);
renatofilho@909
   336
        }
renatofilho@909
   337
        else
renatofilho@909
   338
        {
renatofilho@909
   339
            GMythBackendInfo *info;
renatofilho@909
   340
            GMythUPnPIdleData *idle_data;
rosfran@706
   341
renatofilho@909
   342
            info = gmyth_backend_info_new_full (
renatofilho@909
   343
                _xml_get_first_document_item (desc_doc, "Host"),
renatofilho@909
   344
                _xml_get_first_document_item (desc_doc, "UserName"),
renatofilho@909
   345
                _xml_get_first_document_item (desc_doc, "Password"),
renatofilho@909
   346
                _xml_get_first_document_item (desc_doc, "Name"),
renatofilho@909
   347
                // Current mythtv version not export port number
renatofilho@909
   348
                6543);
rosfran@696
   349
renatofilho@909
   350
            if (desc_doc)
renatofilho@909
   351
                ixmlDocument_free (desc_doc);
renatofilho@909
   352
renatofilho@909
   353
            g_mutex_lock (priv->mutex);
renatofilho@909
   354
            g_hash_table_insert (priv->servers, 
renatofilho@909
   355
                                 g_strdup (uuid),
renatofilho@909
   356
                                 g_object_ref (info));
renatofilho@909
   357
            g_mutex_unlock (priv->mutex);
renatofilho@909
   358
            g_free (info_url);
renatofilho@909
   359
renatofilho@909
   360
            idle_data = g_new0 (GMythUPnPIdleData, 1);
renatofilho@909
   361
            idle_data->parent = self;
renatofilho@909
   362
            idle_data->server = g_object_ref (info);
renatofilho@909
   363
renatofilho@909
   364
            priv->idle_count++;
renatofilho@909
   365
            g_idle_add (_idle_emit_device_found_signal, idle_data);
renatofilho@909
   366
        }
renatofilho@754
   367
    }
renatofilho@909
   368
}
renatofilho@909
   369
renatofilho@909
   370
static void
renatofilho@909
   371
_remove_mythtv_server (GMythUPnP *self,
renatofilho@909
   372
                       const gchar *uuid)
renatofilho@909
   373
{
renatofilho@909
   374
    GMythUPnPPrivate *priv;
renatofilho@909
   375
    GMythBackendInfo *info;
renatofilho@909
   376
renatofilho@909
   377
    priv = GMYTH_UPNP_GET_PRIVATE (self);
renatofilho@909
   378
renatofilho@909
   379
    g_mutex_lock (priv->mutex);
renatofilho@909
   380
    info = g_hash_table_lookup (priv->servers, uuid);
renatofilho@909
   381
    if (info)
renatofilho@909
   382
    {
renatofilho@909
   383
        GMythUPnPIdleData *idle_data;
renatofilho@909
   384
renatofilho@909
   385
        idle_data = g_new0 (GMythUPnPIdleData, 1);
renatofilho@909
   386
        idle_data->parent = self;
renatofilho@909
   387
        idle_data->server = g_object_ref (info);
renatofilho@909
   388
renatofilho@909
   389
        g_hash_table_remove (priv->servers, uuid);
renatofilho@909
   390
renatofilho@909
   391
        priv->idle_count++;
renatofilho@909
   392
        g_idle_add (_idle_emit_device_lost_signal, idle_data);
renatofilho@909
   393
    }
renatofilho@909
   394
    g_mutex_unlock (priv->mutex);
rosfran@696
   395
rosfran@696
   396
}
rosfran@696
   397
renatofilho@909
   398
static GMythBackendInfo*
renatofilho@909
   399
_find_service_by_uuid (GMythUPnP *self,
renatofilho@909
   400
                      const gchar *uuid)
rosfran@696
   401
{
renatofilho@909
   402
    GMythUPnPPrivate *priv;
renatofilho@909
   403
    GMythBackendInfo *info;
rosfran@696
   404
renatofilho@909
   405
    priv = GMYTH_UPNP_GET_PRIVATE (self);
renatofilho@909
   406
    info = NULL;
rosfran@696
   407
renatofilho@909
   408
    g_mutex_lock (priv->mutex);
renatofilho@909
   409
    info = g_hash_table_lookup (priv->servers, uuid);
renatofilho@909
   410
    g_mutex_unlock (priv->mutex);
rosfran@696
   411
renatofilho@909
   412
    return info;
melunko@250
   413
}
melunko@250
   414
renatofilho@909
   415
static int
renatofilho@909
   416
_upnp_event_handler (Upnp_EventType e_type,
renatofilho@909
   417
                     void* e,
renatofilho@909
   418
                     void* data)
melunko@250
   419
{
renatofilho@909
   420
    g_return_val_if_fail (singleton != NULL, 0);
rosfran@696
   421
renatofilho@909
   422
    switch (e_type)
renatofilho@909
   423
    {
renatofilho@909
   424
        case UPNP_DISCOVERY_ADVERTISEMENT_ALIVE:
renatofilho@909
   425
        case UPNP_DISCOVERY_SEARCH_RESULT:
renatofilho@909
   426
        {
renatofilho@909
   427
            struct Upnp_Discovery *d_event;
renatofilho@754
   428
renatofilho@909
   429
            d_event = (struct Upnp_Discovery *) e;
renatofilho@754
   430
renatofilho@909
   431
            if (strcmp (d_event->ServiceType, UPNP_SERVICE_FILTER) != 0)
renatofilho@909
   432
            {
renatofilho@915
   433
                g_warning ("invalid device : %s", d_event->DeviceId);
renatofilho@909
   434
                break;
renatofilho@909
   435
            }
renatofilho@754
   436
renatofilho@909
   437
renatofilho@909
   438
            if (d_event->ErrCode != UPNP_E_SUCCESS)
renatofilho@909
   439
            {
renatofilho@909
   440
                g_warning ("Error in Discovery: %d", d_event->ErrCode);
renatofilho@909
   441
                break;
renatofilho@909
   442
            }
renatofilho@909
   443
renatofilho@909
   444
            if (_find_service_by_uuid (GMYTH_UPNP (singleton), d_event->DeviceId) == NULL)
renatofilho@909
   445
                _append_mythtv_server_from_loation (singleton,
renatofilho@909
   446
                                                    d_event->DeviceId,
renatofilho@909
   447
                                                    d_event->Location);
renatofilho@909
   448
renatofilho@909
   449
renatofilho@909
   450
            break;
renatofilho@754
   451
        }
renatofilho@909
   452
        case UPNP_DISCOVERY_ADVERTISEMENT_BYEBYE:
renatofilho@909
   453
        {
renatofilho@909
   454
            GMythUPnPPrivate *priv;
renatofilho@909
   455
            struct Upnp_Discovery *d_event;
renatofilho@909
   456
renatofilho@909
   457
            d_event = (struct Upnp_Discovery *) e;
renatofilho@909
   458
            if (d_event->ErrCode != UPNP_E_SUCCESS)
renatofilho@909
   459
            {
renatofilho@909
   460
                g_warning ("Error in Discovery: %d", d_event->ErrCode);
renatofilho@909
   461
                break;
renatofilho@909
   462
            }
renatofilho@909
   463
renatofilho@909
   464
            priv = GMYTH_UPNP_GET_PRIVATE (singleton);
renatofilho@909
   465
            _remove_mythtv_server (singleton,
renatofilho@909
   466
                                   d_event->DeviceId);
renatofilho@909
   467
renatofilho@909
   468
            break;
renatofilho@909
   469
renatofilho@909
   470
        }
renatofilho@909
   471
        default:
renatofilho@909
   472
            break;
renatofilho@754
   473
    }
renatofilho@754
   474
renatofilho@909
   475
    return 0;
melunko@250
   476
}
melunko@250
   477