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