2 * Copyright (C) 2009 Nokia Corporation.
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., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, 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_ABSTRACT_TYPE (GUPnPContextManager,
48 gupnp_context_manager,
51 struct _GUPnPContextManagerPrivate {
54 GUPnPContextManager *impl;
56 GList *objects; /* control points and root devices */
71 static guint signals[SIGNAL_LAST];
74 on_context_unavailable (GUPnPContextManager *manager,
75 GUPnPContext *context,
80 /* Make sure we don't send anything on now unavailable network */
81 g_object_set (context, "active", FALSE, NULL);
83 /* Unref all associated objects */
84 l = manager->priv->objects;
87 GUPnPContext *obj_context = NULL;
89 if (GUPNP_IS_CONTROL_POINT (l->data)) {
90 GUPnPControlPoint *cp;
92 cp = GUPNP_CONTROL_POINT (l->data);
93 obj_context = gupnp_control_point_get_context (cp);
94 } else if (GUPNP_IS_ROOT_DEVICE (l->data)) {
95 GUPnPDeviceInfo *info;
97 info = GUPNP_DEVICE_INFO (l->data);
98 obj_context = gupnp_device_info_get_context (info);
100 g_assert_not_reached ();
103 if (context == obj_context) {
104 GList *next = l->next;
106 g_object_unref (l->data);
108 manager->priv->objects =
109 g_list_delete_link (manager->priv->objects, l);
118 gupnp_context_manager_init (GUPnPContextManager *manager)
121 G_TYPE_INSTANCE_GET_PRIVATE (manager,
122 GUPNP_TYPE_CONTEXT_MANAGER,
123 GUPnPContextManagerPrivate);
127 gupnp_context_manager_set_property (GObject *object,
132 GUPnPContextManager *manager;
133 GUPnPContextManagerPrivate *priv;
135 manager = GUPNP_CONTEXT_MANAGER (object);
136 priv = manager->priv;
138 switch (property_id) {
140 priv->port = g_value_get_uint (value);
142 case PROP_MAIN_CONTEXT:
143 if (g_value_get_pointer (value) != NULL)
144 g_warning ("GUPnPContextManager:main-context is "
146 "g_main_context_push_thread_default()"
150 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
156 gupnp_context_manager_get_property (GObject *object,
161 GUPnPContextManager *manager;
163 manager = GUPNP_CONTEXT_MANAGER (object);
165 switch (property_id) {
167 g_value_set_uint (value, manager->priv->port);
169 case PROP_MAIN_CONTEXT:
170 g_warning ("GUPnPContextManager:main-context is deprecated. "
171 "Use g_main_context_push_thread_default()"
173 g_value_set_pointer (value,
174 g_main_context_get_thread_default ());
177 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
183 gupnp_context_manager_dispose (GObject *object)
185 GUPnPContextManager *manager;
186 GObjectClass *object_class;
188 manager = GUPNP_CONTEXT_MANAGER (object);
190 g_list_foreach (manager->priv->objects, (GFunc) g_object_unref, NULL);
191 g_list_free (manager->priv->objects);
192 manager->priv->objects = NULL;
195 object_class = G_OBJECT_CLASS (gupnp_context_manager_parent_class);
196 object_class->dispose (object);
200 gupnp_context_manager_class_init (GUPnPContextManagerClass *klass)
202 GObjectClass *object_class;
204 object_class = G_OBJECT_CLASS (klass);
206 object_class->set_property = gupnp_context_manager_set_property;
207 object_class->get_property = gupnp_context_manager_get_property;
208 object_class->dispose = gupnp_context_manager_dispose;
210 g_type_class_add_private (klass, sizeof (GUPnPContextManagerPrivate));
213 * GSSDPClient:main-context:
215 * The #GMainContext to pass to created #GUPnPContext objects. Set to
216 * NULL to use the default.
218 * Deprecated: 0.17.2: Use g_main_context_push_thread_default()
221 g_object_class_install_property
227 "GMainContext to pass to created GUPnPContext"
229 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
230 G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK |
231 G_PARAM_STATIC_BLURB));
234 * GUPnPContextManager:port:
236 * Port the contexts listen on, or 0 if you don't care what
237 * port is used by #GUPnPContext objects created by this object.
239 g_object_class_install_property
242 g_param_spec_uint ("port",
244 "Port to create contexts for",
245 0, G_MAXUINT, SOUP_ADDRESS_ANY_PORT,
247 G_PARAM_CONSTRUCT_ONLY |
248 G_PARAM_STATIC_NAME |
249 G_PARAM_STATIC_NICK |
250 G_PARAM_STATIC_BLURB));
253 * GUPnPContextManager::context-available:
254 * @context_manager: The #GUPnPContextManager that received the signal
255 * @context: The now available #GUPnPContext
257 * Signals the availability of new #GUPnPContext.
260 signals[CONTEXT_AVAILABLE] =
261 g_signal_new ("context-available",
262 GUPNP_TYPE_CONTEXT_MANAGER,
266 g_cclosure_marshal_VOID__OBJECT,
272 * GUPnPContextManager::context-unavailable:
273 * @context_manager: The #GUPnPContextManager that received the signal
274 * @context: The now unavailable #GUPnPContext
276 * Signals the unavailability of a #GUPnPContext.
279 signals[CONTEXT_UNAVAILABLE] =
280 g_signal_new_class_handler
281 ("context-unavailable",
282 GUPNP_TYPE_CONTEXT_MANAGER,
284 G_CALLBACK (on_context_unavailable),
286 g_cclosure_marshal_VOID__OBJECT,
293 * gupnp_context_manager_new:
294 * @main_context: (allow-none): Deprecated: 0.17.2: %NULL. If you want to use
295 * a different main context use
296 * g_main_context_push_thread_default() instead.
297 * @port: Port to create contexts for, or 0 if you don't care what port is used.
299 * Same as gupnp_context_manager_create().
301 * Returns: (transfer full): A new #GUPnPContextManager object.
302 * Deprecated: 0.17.2: Use gupnp_context_manager_create().
304 GUPnPContextManager *
305 gupnp_context_manager_new (GMainContext *main_context,
309 g_warning ("gupnp_context_manager_new::main_context is"
311 " g_main_context_push_thread_default() instead");
313 return gupnp_context_manager_create (port);
316 #ifdef HAVE_LINUX_RTNETLINK_H
317 #include "gupnp-linux-context-manager.h"
321 * gupnp_context_manager_create:
322 * @port: Port to create contexts for, or 0 if you don't care what port is used.
324 * Factory-method to create a new #GUPnPContextManager. The final type of the
325 * #GUPnPContextManager depends on the compile-time selection or - in case of
326 * NetworkManager - on its availability during runtime. If it is not available,
327 * the implementation falls back to the basic Unix context manager instead.
329 * Returns: (transfer full): A new #GUPnPContextManager object.
331 GUPnPContextManager *
332 gupnp_context_manager_create (guint port)
334 #if defined(USE_NETWORK_MANAGER) || defined (USE_CONNMAN)
335 GDBusConnection *system_bus;
337 GUPnPContextManager *impl;
338 GType impl_type = G_TYPE_INVALID;
340 #ifdef USE_NETWORK_MANAGER
341 #include "gupnp-network-manager.h"
342 system_bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL);
344 if (gupnp_network_manager_is_available ())
345 impl_type = GUPNP_TYPE_NETWORK_MANAGER;
347 #include "gupnp-connman-manager.h"
348 system_bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL);
350 if (gupnp_connman_manager_is_available ())
351 impl_type = GUPNP_TYPE_CONNMAN_MANAGER;
354 if (impl_type == G_TYPE_INVALID)
355 /* Either user requested us to use the Linux CM explicitly or we
356 * are using one of the DBus managers but it's not available, so we
357 * fall-back to it. */
358 #if defined (USE_NETLINK) || defined (HAVE_LINUX_RTNETLINK_H)
359 impl_type = GUPNP_TYPE_LINUX_CONTEXT_MANAGER;
361 impl_type = GUPNP_TYPE_UNIX_CONTEXT_MANAGER;
364 impl = g_object_new (impl_type,
368 #if defined(USE_NETWORK_MANAGER) || defined(USE_CONNMAN)
369 g_object_unref (system_bus);
375 * gupnp_context_manager_manage_control_point:
376 * @manager: A #GUPnPContextManager
377 * @control_point: The #GUPnPControlPoint to be taken care of
379 * By calling this function, you are asking @manager to keep a reference to
380 * @control_point until it's associated #GUPnPContext is no longer available.
381 * You usually want to call this function from
382 * #GUPnPContextManager::context-available handler after you create a
383 * #GUPnPControlPoint object for the newly available context.
386 gupnp_context_manager_manage_control_point (GUPnPContextManager *manager,
387 GUPnPControlPoint *control_point)
389 g_return_if_fail (GUPNP_IS_CONTEXT_MANAGER (manager));
390 g_return_if_fail (GUPNP_IS_CONTROL_POINT (control_point));
392 manager->priv->objects = g_list_append (manager->priv->objects,
393 g_object_ref (control_point));
397 * gupnp_context_manager_manage_root_device:
398 * @manager: A #GUPnPContextManager
399 * @root_device: The #GUPnPRootDevice to be taken care of
401 * By calling this function, you are asking @manager to keep a reference to
402 * @root_device when it's associated #GUPnPContext is no longer available. You
403 * usually want to call this function from
404 * #GUPnPContextManager::context-available handler after you create a
405 * #GUPnPRootDevice object for the newly available context.
408 gupnp_context_manager_manage_root_device (GUPnPContextManager *manager,
409 GUPnPRootDevice *root_device)
411 g_return_if_fail (GUPNP_IS_CONTEXT_MANAGER (manager));
412 g_return_if_fail (GUPNP_IS_ROOT_DEVICE (root_device));
414 manager->priv->objects = g_list_append (manager->priv->objects,
415 g_object_ref (root_device));
419 * gupnp_context_manager_get_port:
420 * @manager: A #GUPnPContextManager
422 * Get the network port associated with this context manager.
423 * Returns: The network port asssociated with this context manager.
426 gupnp_context_manager_get_port (GUPnPContextManager *manager)
428 g_return_if_fail (GUPNP_IS_CONTEXT_MANAGER (manager));
430 return manager->priv->port;