Update gupnp to 0.20.5 (fdeb6f9f)
[profile/ivi/GUPnP.git] / libgupnp / gupnp-simple-context-manager.c
1 /*
2  * Copyright (C) 2009,2011 Nokia Corporation.
3  * Copyright (C) 2006, 2007, 2008 OpenedHand Ltd.
4  *
5  * Author: Jens Georg <mail@jensge.org>
6  *         Zeeshan Ali (Khattak) <zeeshanak@gnome.org>
7  *         Jorn Baayen <jorn@openedhand.com>
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Library General Public
11  * License as published by the Free Software Foundation; either
12  * version 2 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Library General Public License for more details.
18  *
19  * You should have received a copy of the GNU Library General Public
20  * License along with this library; if not, write to the
21  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22  * Boston, MA 02110-1301, USA.
23  */
24
25 /**
26  * SECTION:gupnp-simple-context-manager
27  * @short_description: Abstract implementation of basic #GUPnPContextManager.
28  *
29  */
30
31 #include <config.h>
32 #include <errno.h>
33 #include <gio/gio.h>
34 #include <libgssdp/gssdp-error.h>
35
36 #include "gupnp-simple-context-manager.h"
37 #include "gupnp-context.h"
38
39 G_DEFINE_ABSTRACT_TYPE (GUPnPSimpleContextManager,
40                         gupnp_simple_context_manager,
41                         GUPNP_TYPE_CONTEXT_MANAGER);
42
43 struct _GUPnPSimpleContextManagerPrivate {
44         GList *contexts; /* List of GUPnPContext instances */
45
46         GSource *idle_context_creation_src;
47 };
48
49 static GList*
50 gupnp_simple_context_manager_get_interfaces (GUPnPSimpleContextManager *manager)
51 {
52         GUPnPSimpleContextManagerClass *object_class =
53                               GUPNP_SIMPLE_CONTEXT_MANAGER_GET_CLASS (manager);
54
55         return object_class->get_interfaces (manager);
56 }
57
58 static void
59 create_and_signal_context (const char                *interface,
60                            GUPnPSimpleContextManager *manager)
61 {
62         GUPnPContext *context;
63         guint port;
64
65         GError *error;
66
67         g_object_get (manager,
68                       "port", &port,
69                       NULL);
70
71         error = NULL;
72         context = g_initable_new (GUPNP_TYPE_CONTEXT,
73                                   NULL,
74                                   &error,
75                                   "interface", interface,
76                                   "port", port,
77                                   NULL);
78         if (error != NULL) {
79                 if (!(error->domain == GSSDP_ERROR &&
80                       error->code == GSSDP_ERROR_NO_IP_ADDRESS))
81                         g_warning
82                            ("Failed to create context for interface '%s': %s",
83                             interface,
84                             error->message);
85
86                 g_error_free (error);
87
88                 return;
89         }
90
91         g_signal_emit_by_name (manager,
92                                "context-available",
93                                context);
94
95         manager->priv->contexts = g_list_append (manager->priv->contexts,
96                                                  context);
97 }
98
99 /*
100  * Create a context for all network interfaces that are up.
101  */
102 static gboolean
103 create_contexts (gpointer data)
104 {
105         GUPnPSimpleContextManager *manager = (GUPnPSimpleContextManager *) data;
106         GList *ifaces;
107
108         manager->priv->idle_context_creation_src = NULL;
109
110         if (manager->priv->contexts != NULL)
111                return FALSE;
112
113         ifaces = gupnp_simple_context_manager_get_interfaces (manager);
114         while (ifaces) {
115                 create_and_signal_context ((char *) ifaces->data, manager);
116                 g_free (ifaces->data);
117                 ifaces = g_list_delete_link (ifaces, ifaces);
118         }
119
120         return FALSE;
121 }
122
123 static void
124 destroy_contexts (GUPnPSimpleContextManager *manager)
125 {
126         while (manager->priv->contexts) {
127                 GUPnPContext *context;
128
129                 context = GUPNP_CONTEXT (manager->priv->contexts->data);
130
131                 g_signal_emit_by_name (manager,
132                                        "context-unavailable",
133                                        context);
134                 g_object_unref (context);
135
136                 manager->priv->contexts = g_list_delete_link
137                                         (manager->priv->contexts,
138                                          manager->priv->contexts);
139         }
140 }
141
142 static void
143 schedule_contexts_creation (GUPnPSimpleContextManager *manager)
144 {
145         manager->priv->idle_context_creation_src = NULL;
146
147         /* Create contexts in mainloop so that is happens after user has hooked
148          * to the "context-available" signal.
149          */
150         manager->priv->idle_context_creation_src = g_idle_source_new ();
151         g_source_attach (manager->priv->idle_context_creation_src,
152                          g_main_context_get_thread_default ());
153         g_source_set_callback (manager->priv->idle_context_creation_src,
154                                create_contexts,
155                                manager,
156                                NULL);
157         g_source_unref (manager->priv->idle_context_creation_src);
158 }
159
160 static void
161 gupnp_simple_context_manager_init (GUPnPSimpleContextManager *manager)
162 {
163         manager->priv =
164                 G_TYPE_INSTANCE_GET_PRIVATE (manager,
165                                              GUPNP_TYPE_SIMPLE_CONTEXT_MANAGER,
166                                              GUPnPSimpleContextManagerPrivate);
167 }
168
169 static void
170 gupnp_simple_context_manager_constructed (GObject *object)
171 {
172         GObjectClass *parent_class;
173         GUPnPSimpleContextManager *manager;
174
175         manager = GUPNP_SIMPLE_CONTEXT_MANAGER (object);
176         schedule_contexts_creation (manager);
177
178         /* Chain-up */
179         parent_class = G_OBJECT_CLASS (gupnp_simple_context_manager_parent_class);
180         if (parent_class->constructed != NULL)
181                 parent_class->constructed (object);
182 }
183
184 static void
185 gupnp_simple_context_manager_dispose (GObject *object)
186 {
187         GUPnPSimpleContextManager *manager;
188         GObjectClass *object_class;
189
190         manager = GUPNP_SIMPLE_CONTEXT_MANAGER (object);
191
192         destroy_contexts (manager);
193
194         if (manager->priv->idle_context_creation_src) {
195                 g_source_destroy (manager->priv->idle_context_creation_src);
196                 manager->priv->idle_context_creation_src = NULL;
197         }
198
199
200         /* Call super */
201         object_class = G_OBJECT_CLASS (gupnp_simple_context_manager_parent_class);
202         object_class->dispose (object);
203 }
204
205 static void
206 gupnp_simple_context_manager_class_init (GUPnPSimpleContextManagerClass *klass)
207 {
208         GObjectClass *object_class;
209
210         object_class = G_OBJECT_CLASS (klass);
211
212         object_class->constructed  = gupnp_simple_context_manager_constructed;
213         object_class->dispose      = gupnp_simple_context_manager_dispose;
214
215         g_type_class_add_private (klass,
216                                   sizeof (GUPnPSimpleContextManagerPrivate));
217 }