Add gobject introspection
[profile/ivi/GUPnP.git] / libgupnp / gupnp-resource-factory.c
1 /*
2  * Copyright (C) 2007 Zeeshan Ali (Khattak) <zeeshanak@gnome.org>
3  * Copyright (C) 2006, 2007 OpenedHand Ltd.
4  *
5  * Author: Zeeshan Ali (Khattak) <zeeshanak@gnome.org>
6  *         Jorn Baayen <jorn@openedhand.com>
7  *
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.
12  *
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.
17  *
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.
22  */
23
24 /**
25  * SECTION:gupnp-resource-factory
26  * @short_description: Class for resource and resource proxy object creation.
27  *
28  * #GUPnPResourceFactory objects are used by #GUPnPControlPoint,
29  * #GUPnPDeviceProxy and #GUPnPDevice to create resource proxy and resource
30  * objects. Register UPnP type - #GType pairs to have resource or resource proxy
31  * objects created with the specified #GType whenever an object for a resource
32  * of the specified UPnP type is requested. The #GType<!-- -->s need
33  * to be derived from the relevant resource or resource proxy type (e.g.
34  * a device proxy type needs to be derived from #GUPnPDeviceProxy).
35  */
36
37 #include <string.h>
38
39 #include "gupnp-resource-factory-private.h"
40 #include "gupnp-root-device.h"
41
42 G_DEFINE_TYPE (GUPnPResourceFactory,
43                gupnp_resource_factory,
44                G_TYPE_OBJECT);
45
46 struct _GUPnPResourceFactoryPrivate {
47         GHashTable *resource_type_hash;
48         GHashTable *proxy_type_hash;
49 };
50
51 static void
52 gupnp_resource_factory_init (GUPnPResourceFactory *factory)
53 {
54         factory->priv =
55                 G_TYPE_INSTANCE_GET_PRIVATE (factory,
56                                              GUPNP_TYPE_RESOURCE_FACTORY,
57                                              GUPnPResourceFactoryPrivate);
58
59         factory->priv->resource_type_hash =
60                         g_hash_table_new_full (g_str_hash,
61                                                g_str_equal,
62                                                g_free,
63                                                NULL);
64         factory->priv->proxy_type_hash =
65                         g_hash_table_new_full (g_str_hash,
66                                                g_str_equal,
67                                                g_free,
68                                                NULL);
69 }
70
71 static void
72 gupnp_resource_factory_finalize (GObject *object)
73 {
74         GUPnPResourceFactory *self;
75         GObjectClass *object_class;
76
77         self = GUPNP_RESOURCE_FACTORY (object);
78
79         if (self->priv->resource_type_hash) {
80                 g_hash_table_destroy (self->priv->resource_type_hash);
81                 self->priv->resource_type_hash = NULL;
82         }
83
84         if (self->priv->proxy_type_hash) {
85                 g_hash_table_destroy (self->priv->proxy_type_hash);
86                 self->priv->proxy_type_hash = NULL;
87         }
88
89         object_class = G_OBJECT_CLASS (gupnp_resource_factory_parent_class);
90         object_class->finalize (object);
91 }
92
93 static void
94 gupnp_resource_factory_class_init (GUPnPResourceFactoryClass *klass)
95 {
96         GObjectClass *object_class;
97
98         object_class = G_OBJECT_CLASS (klass);
99
100         object_class->finalize = gupnp_resource_factory_finalize;
101
102         g_type_class_add_private (klass, sizeof (GUPnPResourceFactoryPrivate));
103 }
104
105 /**
106  * gupnp_resource_factory_new:
107  *
108  * Create a new #GUPnPResourceFactory object.
109  *
110  * Return value: A #GUPnPResourceFactory object.
111  **/
112 GUPnPResourceFactory *
113 gupnp_resource_factory_new (void)
114 {
115         return g_object_new (GUPNP_TYPE_RESOURCE_FACTORY, NULL);
116 }
117
118 /**
119  * gupnp_resource_factory_get_default:
120  *
121  * Get the default singleton #GUPnPResourceFactory object.
122  *
123  * Returns: (transfer none): A @GUPnPResourceFactory object.
124  **/
125 GUPnPResourceFactory *
126 gupnp_resource_factory_get_default (void)
127 {
128         static GUPnPResourceFactory *default_factory = NULL;
129
130         if (G_UNLIKELY (default_factory == NULL)) {
131                 default_factory = g_object_new (GUPNP_TYPE_RESOURCE_FACTORY,
132                                                 NULL);
133         }
134
135         return default_factory;
136 }
137
138 /**
139  * gupnp_resource_factory_create_device_proxy:
140  * @factory: A #GUPnPResourceFactory
141  * @context: A #GUPnPContext
142  * @doc: A #GUPnPXMLDoc
143  * @element: The #xmlNode ponting to the right device element
144  * @udn: The UDN of the device to create a proxy for
145  * @location: The location of the device description file
146  * @url_base: The URL base for this device, or %NULL if none
147  *
148  *
149  * Create a #GUPnPDeviceProxy for the device with element @element, as
150  * read from the device description file specified by @location.
151  *
152  * Return value: A new #GUPnPDeviceProxy.
153  **/
154 GUPnPDeviceProxy *
155 gupnp_resource_factory_create_device_proxy
156                                 (GUPnPResourceFactory *factory,
157                                  GUPnPContext         *context,
158                                  GUPnPXMLDoc          *doc,
159                                  xmlNode              *element,
160                                  const char           *udn,
161                                  const char           *location,
162                                  const SoupURI        *url_base)
163 {
164         GUPnPDeviceProxy *proxy;
165         char             *upnp_type;
166         GType             proxy_type = GUPNP_TYPE_DEVICE_PROXY;
167
168         g_return_val_if_fail (GUPNP_IS_RESOURCE_FACTORY (factory), NULL);
169         g_return_val_if_fail (GUPNP_IS_CONTEXT (context), NULL);
170         g_return_val_if_fail (GUPNP_IS_XML_DOC (doc), NULL);
171         g_return_val_if_fail (element != NULL, NULL);
172         g_return_val_if_fail (location != NULL, NULL);
173         g_return_val_if_fail (url_base != NULL, NULL);
174
175         upnp_type = xml_util_get_child_element_content_glib (element,
176                                                              "deviceType");
177         if (upnp_type) {
178                 gpointer value;
179
180                 value = g_hash_table_lookup (factory->priv->proxy_type_hash,
181                                              upnp_type);
182                 if (value)
183                         proxy_type = GPOINTER_TO_SIZE (value);
184
185                 g_free (upnp_type);
186         }
187
188         proxy = g_object_new (proxy_type,
189                               "resource-factory", factory,
190                               "context", context,
191                               "location", location,
192                               "udn", udn,
193                               "url-base", url_base,
194                               "document", doc,
195                               "element", element,
196                               NULL);
197
198         return proxy;
199 }
200
201 /**
202  * gupnp_resource_factory_create_service_proxy:
203  * @factory: A #GUPnPResourceFactory
204  * @context: A #GUPnPContext
205  * @doc: A #GUPnPXMLDoc
206  * @element: The #xmlNode ponting to the right service element
207  * @location: The location of the service description file
208  * @udn: The UDN of the device the service is contained in
209  * @service_type: The service type
210  * @url_base: The URL base for this service, or %NULL if none
211  *
212  * Create a #GUPnPServiceProxy for the service with element @element, as
213  * read from the service description file specified by @location.
214  *
215  * Return value: A new #GUPnPServiceProxy.
216  **/
217 GUPnPServiceProxy *
218 gupnp_resource_factory_create_service_proxy
219                                 (GUPnPResourceFactory *factory,
220                                  GUPnPContext         *context,
221                                  GUPnPXMLDoc          *doc,
222                                  xmlNode              *element,
223                                  const char           *udn,
224                                  const char           *service_type,
225                                  const char           *location,
226                                  const SoupURI        *url_base)
227 {
228         GUPnPServiceProxy *proxy;
229         GType              proxy_type = GUPNP_TYPE_SERVICE_PROXY;
230
231         g_return_val_if_fail (GUPNP_IS_RESOURCE_FACTORY (factory), NULL);
232         g_return_val_if_fail (GUPNP_IS_CONTEXT (context), NULL);
233         g_return_val_if_fail (GUPNP_IS_XML_DOC (doc), NULL);
234         g_return_val_if_fail (element != NULL, NULL);
235         g_return_val_if_fail (location != NULL, NULL);
236         g_return_val_if_fail (url_base != NULL, NULL);
237
238         if (service_type) {
239                 gpointer value;
240
241                 value = g_hash_table_lookup (factory->priv->proxy_type_hash,
242                                              service_type);
243                 if (value)
244                         proxy_type = GPOINTER_TO_SIZE (value);
245         }
246
247         proxy = g_object_new (proxy_type,
248                               "context", context,
249                               "location", location,
250                               "udn", udn,
251                               "service-type", service_type,
252                               "url-base", url_base,
253                               "document", doc,
254                               "element", element,
255                               NULL);
256
257         return proxy;
258 }
259
260 /**
261  * gupnp_resource_factory_create_device:
262  * @factory: A #GUPnPResourceFactory
263  * @context: A #GUPnPContext
264  * @root_device: The #GUPnPRootDevice
265  * @element: The #xmlNode ponting to the right device element
266  * @udn: The UDN of the device to create a device for
267  * @location: The location of the device description file
268  * @url_base: The URL base for this device
269  *
270  * Create a #GUPnPDevice for the device with element @element, as
271  * read from the device description file specified by @location.
272  *
273  * Return value: A new #GUPnPDevice.
274  **/
275 GUPnPDevice *
276 gupnp_resource_factory_create_device
277                                 (GUPnPResourceFactory *factory,
278                                  GUPnPContext         *context,
279                                  GUPnPDevice          *root_device,
280                                  xmlNode              *element,
281                                  const char           *udn,
282                                  const char           *location,
283                                  const SoupURI        *url_base)
284 {
285         GUPnPDevice *device;
286         char        *upnp_type;
287         GType        device_type = GUPNP_TYPE_DEVICE;
288
289         g_return_val_if_fail (GUPNP_IS_RESOURCE_FACTORY (factory), NULL);
290         g_return_val_if_fail (GUPNP_IS_CONTEXT (context), NULL);
291         g_return_val_if_fail (GUPNP_IS_ROOT_DEVICE (root_device), NULL);
292         g_return_val_if_fail (element != NULL, NULL);
293         g_return_val_if_fail (url_base != NULL, NULL);
294
295         upnp_type = xml_util_get_child_element_content_glib (element,
296                                                              "deviceType");
297         if (upnp_type) {
298                 gpointer value;
299
300                 value = g_hash_table_lookup (factory->priv->resource_type_hash,
301                                              upnp_type);
302                 if (value)
303                         device_type = GPOINTER_TO_SIZE (value);
304
305                 g_free (upnp_type);
306         }
307
308         device = g_object_new (device_type,
309                                "resource-factory", factory,
310                                "context", context,
311                                "root-device", root_device,
312                                "location", location,
313                                "udn", udn,
314                                "url-base", url_base,
315                                "element", element,
316                                NULL);
317
318         return device;
319 }
320
321 /**
322  * gupnp_resource_factory_create_service:
323  * @factory: A #GUPnPResourceFactory
324  * @context: A #GUPnPContext
325  * @root_device: The #GUPnPRootDevice
326  * @element: The #xmlNode ponting to the right service element
327  * @udn: The UDN of the device the service is contained in
328  * @location: The location of the service description file
329  * @url_base: The URL base for this service
330  *
331  * Create a #GUPnPService for the service with element @element, as
332  * read from the service description file specified by @location.
333  *
334  * Return value: A new #GUPnPService.
335  **/
336 GUPnPService *
337 gupnp_resource_factory_create_service
338                                 (GUPnPResourceFactory *factory,
339                                  GUPnPContext         *context,
340                                  GUPnPDevice          *root_device,
341                                  xmlNode              *element,
342                                  const char           *udn,
343                                  const char           *location,
344                                  const SoupURI        *url_base)
345 {
346         GUPnPService *service;
347         char         *upnp_type;
348         GType         service_type = GUPNP_TYPE_SERVICE;
349
350         g_return_val_if_fail (GUPNP_IS_RESOURCE_FACTORY (factory), NULL);
351         g_return_val_if_fail (GUPNP_IS_CONTEXT (context), NULL);
352         g_return_val_if_fail (GUPNP_IS_ROOT_DEVICE (root_device), NULL);
353         g_return_val_if_fail (element != NULL, NULL);
354         g_return_val_if_fail (location != NULL, NULL);
355         g_return_val_if_fail (url_base != NULL, NULL);
356
357         upnp_type = xml_util_get_child_element_content_glib (element,
358                                                              "serviceType");
359         if (upnp_type) {
360                 gpointer value;
361
362                 value = g_hash_table_lookup (factory->priv->resource_type_hash,
363                                              upnp_type);
364                 if (value)
365                         service_type = GPOINTER_TO_SIZE (value);
366
367                 g_free (upnp_type);
368         }
369
370         service = g_object_new (service_type,
371                                 "context", context,
372                                 "root-device", root_device,
373                                 "location", location,
374                                 "udn", udn,
375                                 "url-base", url_base,
376                                 "element", element,
377                                 NULL);
378
379         return service;
380 }
381
382 /**
383  * gupnp_resource_factory_register_resource_type:
384  * @factory: A #GUPnPResourceFactory.
385  * @upnp_type: The UPnP type name of the resource.
386  * @type: The requested GType assignment for the resource.
387  *
388  * Registers the GType @type for the resource of UPnP type @upnp_type. After
389  * this call, the factory @factory will create object of GType @type each time
390  * it is asked to create a resource object for UPnP type @upnp_type.
391  *
392  * Note: GType @type must be a derived type of #GUPNP_TYPE_DEVICE if resource is
393  * a device or #GUPNP_TYPE_SERVICE if its a service.
394  **/
395 void
396 gupnp_resource_factory_register_resource_type (GUPnPResourceFactory *factory,
397                                                const char           *upnp_type,
398                                                GType                 type)
399 {
400         g_hash_table_insert (factory->priv->resource_type_hash,
401                              g_strdup (upnp_type),
402                              GSIZE_TO_POINTER (type));
403 }
404
405 /**
406  * gupnp_resource_factory_unregister_resource_type:
407  * @factory: A #GUPnPResourceFactory.
408  * @upnp_type: The UPnP type name of the resource.
409  *
410  * Unregisters the GType assignment for the resource of UPnP type @upnp_type.
411  *
412  * Return value: %TRUE if GType assignment was removed successfully, %FALSE
413  * otherwise.
414  **/
415 gboolean
416 gupnp_resource_factory_unregister_resource_type
417                                 (GUPnPResourceFactory *factory,
418                                  const char           *upnp_type)
419 {
420         return g_hash_table_remove (factory->priv->resource_type_hash,
421                                     upnp_type);
422 }
423
424 /**
425  * gupnp_resource_factory_register_resource_proxy_type:
426  * @factory: A #GUPnPResourceFactory.
427  * @upnp_type: The UPnP type name of the resource.
428  * @type: The requested GType assignment for the resource proxy.
429  *
430  * Registers the GType @type for the proxy of resource of UPnP type @upnp_type.
431  * After this call, the factory @factory will create object of GType @type each
432  * time it is asked to create a resource proxy object for UPnP type @upnp_type.
433  *
434  * Note: GType @type must be a derived type of #GUPNP_TYPE_DEVICE_PROXY if
435  * resource is a device or #GUPNP_TYPE_SERVICE_PROXY if its a service.
436  **/
437 void
438 gupnp_resource_factory_register_resource_proxy_type
439                                 (GUPnPResourceFactory *factory,
440                                  const char           *upnp_type,
441                                  GType                 type)
442 {
443         g_hash_table_insert (factory->priv->proxy_type_hash,
444                              g_strdup (upnp_type),
445                              GSIZE_TO_POINTER (type));
446 }
447
448 /**
449  * gupnp_resource_factory_unregister_resource_proxy_type:
450  * @factory: A #GUPnPResourceFactory.
451  * @upnp_type: The UPnP type name of the resource.
452  *
453  * Unregisters the GType assignment for the proxy of resource of UPnP type
454  * @upnp_type.
455  *
456  * Return value: %TRUE if GType assignment was removed successfully, %FALSE
457  * otherwise.
458  **/
459 gboolean
460 gupnp_resource_factory_unregister_resource_proxy_type
461                                 (GUPnPResourceFactory *factory,
462                                  const char           *upnp_type)
463 {
464         return g_hash_table_remove (factory->priv->proxy_type_hash, upnp_type);
465 }