2 * Copyright (C) 2009 Nokia Corporation, all rights reserved.
3 * Copyright (C) 2006, 2007, 2008 OpenedHand Ltd.
5 * Author: Zeeshan Ali (Khattak) <zeeshanak@gnome.org>
6 * Jorn Baayen <jorn@openedhand.com>
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
18 * You should have received a copy of the GNU Library General Public
19 * License along with this library; if not, write to the
20 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 * Boston, MA 02111-1307, USA.
25 * SECTION:gupnp-context-manager
26 * @short_description: Manages #GUPnPContext objects.
28 * A Utility class that takes care of creation and destruction of
29 * #GUPnPContext objects for all available network interfaces as they go up
30 * (connect) and down (disconnect), respectively.
39 #include <libsoup/soup-address.h>
40 #include <glib/gstdio.h>
43 #include "gupnp-marshal.h"
45 #include "gupnp-unix-context-manager.h"
47 G_DEFINE_TYPE (GUPnPContextManager,
48 gupnp_context_manager,
51 struct _GUPnPContextManagerPrivate {
52 GMainContext *main_context;
56 GUPnPContextManager *impl;
58 GList *objects; /* control points and root devices */
74 static guint signals[SIGNAL_LAST];
77 on_context_available (GUPnPContextManager *impl,
78 GUPnPContext *context,
81 GUPnPContextManager *manager = GUPNP_CONTEXT_MANAGER (user_data);
83 /* Just proxy the signal */
84 g_signal_emit (manager,
85 signals[CONTEXT_AVAILABLE],
91 on_context_unavailable (GUPnPContextManager *impl,
92 GUPnPContext *context,
95 GUPnPContextManager *manager;
98 manager = GUPNP_CONTEXT_MANAGER (user_data);
100 /* Make sure we don't send anything on now unavailable network */
101 g_object_set (context, "active", FALSE, NULL);
103 /* Unref all associated objects */
104 l = manager->priv->objects;
107 GUPnPContext *obj_context = NULL;
109 if (GUPNP_IS_CONTROL_POINT (l->data)) {
110 GUPnPControlPoint *cp;
112 cp = GUPNP_CONTROL_POINT (l->data);
113 obj_context = gupnp_control_point_get_context (cp);
114 } else if (GUPNP_IS_ROOT_DEVICE (l->data)) {
115 GUPnPDeviceInfo *info;
117 info = GUPNP_DEVICE_INFO (l->data);
118 obj_context = gupnp_device_info_get_context (info);
120 g_assert_not_reached ();
123 if (context == obj_context) {
124 GList *next = l->next;
126 g_object_unref (l->data);
128 manager->priv->objects =
129 g_list_delete_link (manager->priv->objects, l);
136 /* Just proxy the signal */
137 g_signal_emit (manager,
138 signals[CONTEXT_UNAVAILABLE],
144 gupnp_context_manager_init (GUPnPContextManager *manager)
147 G_TYPE_INSTANCE_GET_PRIVATE (manager,
148 GUPNP_TYPE_CONTEXT_MANAGER,
149 GUPnPContextManagerPrivate);
153 gupnp_context_manager_set_property (GObject *object,
158 GUPnPContextManager *manager;
159 GUPnPContextManagerPrivate *priv;
161 manager = GUPNP_CONTEXT_MANAGER (object);
162 priv = manager->priv;
164 switch (property_id) {
166 priv->port = g_value_get_uint (value);
168 case PROP_MAIN_CONTEXT:
169 priv->main_context = g_value_get_pointer (value);
171 case PROP_CONTEXT_MANAGER:
172 priv->impl = g_value_get_object (value);
173 if (priv->impl != NULL) {
174 priv->impl = g_object_ref (priv->impl);
176 g_signal_connect (priv->impl,
178 G_CALLBACK (on_context_available),
180 g_signal_connect (priv->impl,
181 "context-unavailable",
182 G_CALLBACK (on_context_unavailable),
187 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
193 gupnp_context_manager_get_property (GObject *object,
198 GUPnPContextManager *manager;
200 manager = GUPNP_CONTEXT_MANAGER (object);
202 switch (property_id) {
204 g_value_set_uint (value, manager->priv->port);
206 case PROP_MAIN_CONTEXT:
207 g_value_set_pointer (value, manager->priv->main_context);
209 case PROP_CONTEXT_MANAGER:
210 g_value_set_object (value, manager->priv->impl);
213 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
219 gupnp_context_manager_dispose (GObject *object)
221 GUPnPContextManager *manager;
222 GObjectClass *object_class;
224 manager = GUPNP_CONTEXT_MANAGER (object);
226 if (manager->priv->impl != NULL) {
227 g_signal_handlers_disconnect_by_func (manager->priv->impl,
228 on_context_available, manager);
229 g_signal_handlers_disconnect_by_func (manager->priv->impl,
230 on_context_unavailable, manager);
231 g_object_unref (manager->priv->impl);
232 manager->priv->impl = NULL;
235 g_list_foreach (manager->priv->objects, (GFunc) g_object_unref, NULL);
236 g_list_free (manager->priv->objects);
237 manager->priv->objects = NULL;
240 object_class = G_OBJECT_CLASS (gupnp_context_manager_parent_class);
241 object_class->dispose (object);
245 gupnp_context_manager_class_init (GUPnPContextManagerClass *klass)
247 GObjectClass *object_class;
249 object_class = G_OBJECT_CLASS (klass);
251 object_class->set_property = gupnp_context_manager_set_property;
252 object_class->get_property = gupnp_context_manager_get_property;
253 object_class->dispose = gupnp_context_manager_dispose;
255 g_type_class_add_private (klass, sizeof (GUPnPContextManagerPrivate));
258 * GSSDPClient:main-context:
260 * The #GMainContext to pass to created #GUPnPContext objects. Set to
261 * NULL to use the default.
263 g_object_class_install_property
269 "GMainContext to pass to created GUPnPContext"
271 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
272 G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK |
273 G_PARAM_STATIC_BLURB));
276 * GUPnPContextManager:port:
278 * @port: Port to create contexts for, or 0 if you don't care what
279 * port is used by #GUPnPContext objects created by this object.
281 g_object_class_install_property
284 g_param_spec_uint ("port",
286 "Port to create contexts for",
287 0, G_MAXUINT, SOUP_ADDRESS_ANY_PORT,
289 G_PARAM_CONSTRUCT_ONLY |
290 G_PARAM_STATIC_NAME |
291 G_PARAM_STATIC_NICK |
292 G_PARAM_STATIC_BLURB));
295 * GUPnPContextManager:context-manager:
297 * The actual GUPnPContextManager implementation used. This is an
298 * internal property and therefore Application developer should just
302 g_object_class_install_property
304 PROP_CONTEXT_MANAGER,
305 g_param_spec_object ("context-manager",
307 "ContextManager implemention",
308 GUPNP_TYPE_CONTEXT_MANAGER,
310 G_PARAM_CONSTRUCT_ONLY |
311 G_PARAM_STATIC_NAME |
312 G_PARAM_STATIC_NICK |
313 G_PARAM_STATIC_BLURB));
316 * GUPnPContextManager::context-available:
317 * @context_manager: The #GUPnPContextManager that received the signal
318 * @context: The now available #GUPnPContext
320 * Signals the availability of new #GUPnPContext.
323 signals[CONTEXT_AVAILABLE] =
324 g_signal_new ("context-available",
325 GUPNP_TYPE_CONTEXT_MANAGER,
329 g_cclosure_marshal_VOID__OBJECT,
335 * GUPnPContextManager::context-unavailable:
336 * @context_manager: The #GUPnPContextManager that received the signal
337 * @context: The now unavailable #GUPnPContext
339 * Signals the unavailability of a #GUPnPContext.
342 signals[CONTEXT_UNAVAILABLE] =
343 g_signal_new ("context-unavailable",
344 GUPNP_TYPE_CONTEXT_MANAGER,
348 g_cclosure_marshal_VOID__OBJECT,
355 * gupnp_context_manager_new:
356 * @port: Port to create contexts for, or 0 if you don't care what port is used.
357 * @main_context: GMainContext to pass to created GUPnPContext objects.
359 * Create a new #GUPnPContextManager.
361 * Return value: A new #GUPnPContextManager object.
363 GUPnPContextManager *
364 gupnp_context_manager_new (GMainContext *main_context,
367 GUPnPContextManager *manager;
368 GUPnPContextManager *impl;
369 GType impl_type = G_TYPE_INVALID;
371 #ifdef USE_NETWORK_MANAGER
372 #include "gupnp-network-manager.h"
374 if (gupnp_network_manager_is_available (main_context))
375 impl_type = GUPNP_TYPE_NETWORK_MANAGER;
378 if (impl_type == G_TYPE_INVALID)
379 impl_type = GUPNP_TYPE_UNIX_CONTEXT_MANAGER;
381 impl = g_object_new (impl_type,
382 "main-context", main_context,
386 manager = g_object_new (GUPNP_TYPE_CONTEXT_MANAGER,
387 "main-context", main_context,
389 "context-manager", impl,
391 g_object_unref (impl);
397 * gupnp_context_manager_manage_control_point:
398 * @manager: A #GUPnPContextManager
399 * @control_point: The #GUPnPControlPoint to be taken care of
401 * By calling this function, you are asking @manager to keep a reference to
402 * @control_point until it's associated #GUPnPContext is no longer available.
403 * You usually want to call this function from
404 * #GUPnPContextManager::context-available handler after you create a
405 * #GUPnPControlPoint object for the newly available context.
408 gupnp_context_manager_manage_control_point (GUPnPContextManager *manager,
409 GUPnPControlPoint *control_point)
411 g_return_if_fail (GUPNP_IS_CONTEXT_MANAGER (manager));
412 g_return_if_fail (GUPNP_IS_CONTROL_POINT (control_point));
414 manager->priv->objects = g_list_append (manager->priv->objects,
415 g_object_ref (control_point));
419 * gupnp_context_manager_manage_root_device:
420 * @manager: A #GUPnPContextManager
421 * @root_device: The #GUPnPRootDevice to be taken care of
423 * By calling this function, you are asking @manager to keep a reference to
424 * @root_device when it's associated #GUPnPContext is no longer available. You
425 * usually want to call this function from
426 * #GUPnPContextManager::context-available handler after you create a
427 * #GUPnPRootDevice object for the newly available context.
430 gupnp_context_manager_manage_root_device (GUPnPContextManager *manager,
431 GUPnPRootDevice *root_device)
433 g_return_if_fail (GUPNP_IS_CONTEXT_MANAGER (manager));
434 g_return_if_fail (GUPNP_IS_ROOT_DEVICE (root_device));
436 manager->priv->objects = g_list_append (manager->priv->objects,
437 g_object_ref (root_device));