2 * renderer-service-upnp
4 * Copyright (C) 2012 Intel Corporation. All rights reserved.
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU Lesser General Public License,
8 * version 2.1, as published by the Free Software Foundation.
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
15 * You should have received a copy of the GNU Lesser General Public License
16 * along with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
19 * Mark Ryan <mark.d.ryan@intel.com>
25 #include <libgupnp/gupnp-context-manager.h>
26 #include <libgupnp/gupnp-error.h>
31 #include "host-service.h"
33 #include "prop-defs.h"
37 GDBusConnection *connection;
38 rsu_interface_info_t *interface_info;
39 rsu_upnp_callback_t found_server;
40 rsu_upnp_callback_t lost_server;
41 GUPnPContextManager *context_manager;
43 GHashTable *server_udn_map;
45 rsu_host_service_t *host_service;
48 static void prv_server_available_cb(GUPnPControlPoint *cp,
49 GUPnPDeviceProxy *proxy,
52 rsu_upnp_t *upnp = user_data;
55 const gchar *ip_address;
56 rsu_device_context_t *context;
59 udn = gupnp_device_info_get_udn((GUPnPDeviceInfo *) proxy);
63 ip_address = gupnp_context_get_host_ip(
64 gupnp_control_point_get_context(cp));
66 device = g_hash_table_lookup(upnp->server_udn_map, udn);
69 if (rsu_device_new(upnp->connection, proxy,
76 g_hash_table_insert(upnp->server_udn_map, g_strdup(udn),
78 upnp->found_server(device->path, upnp->user_data);
81 for (i = 0; i < device->contexts->len; ++i) {
82 context = g_ptr_array_index(device->contexts, i);
84 if (!strcmp(context->ip_address, ip_address))
88 if (i == device->contexts->len)
89 rsu_device_append_new_context(device, ip_address,
98 static gboolean prv_subscribe_to_service_changes(gpointer user_data)
100 rsu_device_t *device = user_data;
102 device->timeout_id = 0;
103 rsu_device_subscribe_to_service_changes(device);
108 static void prv_server_unavailable_cb(GUPnPControlPoint *cp,
109 GUPnPDeviceProxy *proxy,
112 rsu_upnp_t *upnp = user_data;
114 rsu_device_t *device;
115 const gchar *ip_address;
117 rsu_device_context_t *context;
120 udn = gupnp_device_info_get_udn((GUPnPDeviceInfo *) proxy);
124 ip_address = gupnp_context_get_host_ip(
125 gupnp_control_point_get_context(cp));
127 device = g_hash_table_lookup(upnp->server_udn_map, udn);
131 for (i = 0; i < device->contexts->len; ++i) {
132 context = g_ptr_array_index(device->contexts, i);
134 if (!strcmp(context->ip_address, ip_address))
138 if (i < device->contexts->len) {
139 subscribed = (context->subscribed_av || context->subscribed_cm);
141 (void) g_ptr_array_remove_index(device->contexts, i);
143 if (device->contexts->len == 0) {
144 RSU_LOG_DEBUG("Last Context lost. Delete device");
146 if (device->current_task)
147 rsu_async_task_lost_object(
148 device->current_task);
150 upnp->lost_server(device->path, upnp->user_data);
151 g_hash_table_remove(upnp->server_udn_map, udn);
152 } else if (subscribed && !device->timeout_id) {
153 RSU_LOG_DEBUG("Subscribe on new context");
155 device->timeout_id = g_timeout_add_seconds(1,
156 prv_subscribe_to_service_changes,
166 static void prv_on_context_available(GUPnPContextManager *context_manager,
167 GUPnPContext *context,
170 rsu_upnp_t *upnp = user_data;
171 GUPnPControlPoint *cp;
173 cp = gupnp_control_point_new(
175 "urn:schemas-upnp-org:device:MediaRenderer:1");
177 g_signal_connect(cp, "device-proxy-available",
178 G_CALLBACK(prv_server_available_cb), upnp);
180 g_signal_connect(cp, "device-proxy-unavailable",
181 G_CALLBACK(prv_server_unavailable_cb), upnp);
183 gssdp_resource_browser_set_active(GSSDP_RESOURCE_BROWSER(cp), TRUE);
184 gupnp_context_manager_manage_control_point(upnp->context_manager, cp);
188 rsu_upnp_t *rsu_upnp_new(GDBusConnection *connection,
189 rsu_interface_info_t *interface_info,
190 rsu_upnp_callback_t found_server,
191 rsu_upnp_callback_t lost_server,
194 rsu_upnp_t *upnp = g_new0(rsu_upnp_t, 1);
196 upnp->connection = connection;
197 upnp->interface_info = interface_info;
198 upnp->user_data = user_data;
199 upnp->found_server = found_server;
200 upnp->lost_server = lost_server;
202 upnp->server_udn_map = g_hash_table_new_full(g_str_hash, g_str_equal,
205 upnp->context_manager = gupnp_context_manager_create(0);
207 g_signal_connect(upnp->context_manager, "context-available",
208 G_CALLBACK(prv_on_context_available),
211 rsu_host_service_new(&upnp->host_service);
216 void rsu_upnp_delete(rsu_upnp_t *upnp)
219 rsu_host_service_delete(upnp->host_service);
220 g_object_unref(upnp->context_manager);
221 g_hash_table_unref(upnp->server_udn_map);
223 g_free(upnp->interface_info);
228 GVariant *rsu_upnp_get_server_ids(rsu_upnp_t *upnp)
233 rsu_device_t *device;
235 g_variant_builder_init(&vb, G_VARIANT_TYPE("as"));
236 g_hash_table_iter_init(&iter, upnp->server_udn_map);
238 while (g_hash_table_iter_next(&iter, NULL, &value)) {
240 g_variant_builder_add(&vb, "s", device->path);
243 return g_variant_ref_sink(g_variant_builder_end(&vb));
246 void rsu_upnp_get_prop(rsu_upnp_t *upnp, rsu_task_t *task,
247 GCancellable *cancellable,
248 rsu_upnp_task_complete_t cb,
251 rsu_device_t *device;
252 rsu_async_cb_data_t *cb_data;
254 device = rsu_device_from_path(task->path, upnp->server_udn_map);
257 cb_data = rsu_async_cb_data_new(task, cb, user_data, NULL, NULL,
259 cb_data->error = g_error_new(RSU_ERROR,
260 RSU_ERROR_OBJECT_NOT_FOUND,
261 "Cannot locate a device"
262 " for the specified "
264 (void) g_idle_add(rsu_async_complete_task, cb_data);
266 rsu_device_get_prop(device, task, cancellable, cb, user_data);
270 void rsu_upnp_get_all_props(rsu_upnp_t *upnp, rsu_task_t *task,
271 GCancellable *cancellable,
272 rsu_upnp_task_complete_t cb,
275 rsu_device_t *device;
276 rsu_async_cb_data_t *cb_data;
278 device = rsu_device_from_path(task->path, upnp->server_udn_map);
281 cb_data = rsu_async_cb_data_new(task, cb, user_data, NULL, NULL,
283 cb_data->error = g_error_new(RSU_ERROR,
284 RSU_ERROR_OBJECT_NOT_FOUND,
285 "Cannot locate a device"
286 " for the specified "
288 (void) g_idle_add(rsu_async_complete_task, cb_data);
290 rsu_device_get_all_props(device, task, cancellable, cb,
295 void rsu_upnp_play(rsu_upnp_t *upnp, rsu_task_t *task,
296 GCancellable *cancellable,
297 rsu_upnp_task_complete_t cb,
300 rsu_device_t *device;
301 rsu_async_cb_data_t *cb_data;
303 device = rsu_device_from_path(task->path, upnp->server_udn_map);
306 cb_data = rsu_async_cb_data_new(task, cb, user_data, NULL, NULL,
308 cb_data->error = g_error_new(RSU_ERROR,
309 RSU_ERROR_OBJECT_NOT_FOUND,
310 "Cannot locate a device"
311 " for the specified "
313 (void) g_idle_add(rsu_async_complete_task, cb_data);
315 rsu_device_play(device, task, cancellable, cb,
320 void rsu_upnp_pause(rsu_upnp_t *upnp, rsu_task_t *task,
321 GCancellable *cancellable,
322 rsu_upnp_task_complete_t cb,
325 rsu_device_t *device;
326 rsu_async_cb_data_t *cb_data;
328 device = rsu_device_from_path(task->path, upnp->server_udn_map);
331 cb_data = rsu_async_cb_data_new(task, cb, user_data, NULL, NULL,
333 cb_data->error = g_error_new(RSU_ERROR,
334 RSU_ERROR_OBJECT_NOT_FOUND,
335 "Cannot locate a device"
336 " for the specified "
338 (void) g_idle_add(rsu_async_complete_task, cb_data);
340 rsu_device_pause(device, task, cancellable, cb,
345 void rsu_upnp_play_pause(rsu_upnp_t *upnp, rsu_task_t *task,
346 GCancellable *cancellable,
347 rsu_upnp_task_complete_t cb,
350 rsu_device_t *device;
351 rsu_async_cb_data_t *cb_data;
353 device = rsu_device_from_path(task->path, upnp->server_udn_map);
356 cb_data = rsu_async_cb_data_new(task, cb, user_data, NULL, NULL,
358 cb_data->error = g_error_new(RSU_ERROR,
359 RSU_ERROR_OBJECT_NOT_FOUND,
360 "Cannot locate a device"
361 " for the specified "
363 (void) g_idle_add(rsu_async_complete_task, cb_data);
365 rsu_device_play_pause(device, task, cancellable, cb,
370 void rsu_upnp_stop(rsu_upnp_t *upnp, rsu_task_t *task,
371 GCancellable *cancellable,
372 rsu_upnp_task_complete_t cb,
375 rsu_device_t *device;
376 rsu_async_cb_data_t *cb_data;
378 device = rsu_device_from_path(task->path, upnp->server_udn_map);
381 cb_data = rsu_async_cb_data_new(task, cb, user_data, NULL, NULL,
383 cb_data->error = g_error_new(RSU_ERROR,
384 RSU_ERROR_OBJECT_NOT_FOUND,
385 "Cannot locate a device"
386 " for the specified "
388 (void) g_idle_add(rsu_async_complete_task, cb_data);
390 rsu_device_stop(device, task, cancellable, cb,
395 void rsu_upnp_next(rsu_upnp_t *upnp, rsu_task_t *task,
396 GCancellable *cancellable,
397 rsu_upnp_task_complete_t cb,
400 rsu_device_t *device;
401 rsu_async_cb_data_t *cb_data;
403 device = rsu_device_from_path(task->path, upnp->server_udn_map);
406 cb_data = rsu_async_cb_data_new(task, cb, user_data, NULL, NULL,
408 cb_data->error = g_error_new(RSU_ERROR,
409 RSU_ERROR_OBJECT_NOT_FOUND,
410 "Cannot locate a device"
411 " for the specified "
413 (void) g_idle_add(rsu_async_complete_task, cb_data);
415 rsu_device_next(device, task, cancellable, cb,
420 void rsu_upnp_previous(rsu_upnp_t *upnp, rsu_task_t *task,
421 GCancellable *cancellable,
422 rsu_upnp_task_complete_t cb,
425 rsu_device_t *device;
426 rsu_async_cb_data_t *cb_data;
428 device = rsu_device_from_path(task->path, upnp->server_udn_map);
431 cb_data = rsu_async_cb_data_new(task, cb, user_data, NULL, NULL,
433 cb_data->error = g_error_new(RSU_ERROR,
434 RSU_ERROR_OBJECT_NOT_FOUND,
435 "Cannot locate a device"
436 " for the specified "
438 (void) g_idle_add(rsu_async_complete_task, cb_data);
440 rsu_device_previous(device, task, cancellable, cb,
445 void rsu_upnp_open_uri(rsu_upnp_t *upnp, rsu_task_t *task,
446 GCancellable *cancellable,
447 rsu_upnp_task_complete_t cb,
450 rsu_device_t *device;
451 rsu_async_cb_data_t *cb_data;
453 device = rsu_device_from_path(task->path, upnp->server_udn_map);
456 cb_data = rsu_async_cb_data_new(task, cb, user_data, NULL, NULL,
458 cb_data->error = g_error_new(RSU_ERROR,
459 RSU_ERROR_OBJECT_NOT_FOUND,
460 "Cannot locate a device"
461 " for the specified "
463 (void) g_idle_add(rsu_async_complete_task, cb_data);
465 rsu_device_open_uri(device, task, cancellable, cb,
470 void rsu_upnp_seek(rsu_upnp_t *upnp, rsu_task_t *task,
471 GCancellable *cancellable,
472 rsu_upnp_task_complete_t cb,
475 rsu_device_t *device;
476 rsu_async_cb_data_t *cb_data;
478 device = rsu_device_from_path(task->path, upnp->server_udn_map);
481 cb_data = rsu_async_cb_data_new(task, cb, user_data, NULL, NULL,
483 cb_data->error = g_error_new(RSU_ERROR,
484 RSU_ERROR_OBJECT_NOT_FOUND,
485 "Cannot locate a device"
486 " for the specified "
488 (void) g_idle_add(rsu_async_complete_task, cb_data);
490 rsu_device_seek(device, task, cancellable, cb, user_data);
494 void rsu_upnp_set_position(rsu_upnp_t *upnp, rsu_task_t *task,
495 GCancellable *cancellable,
496 rsu_upnp_task_complete_t cb,
499 rsu_device_t *device;
500 rsu_async_cb_data_t *cb_data;
502 device = rsu_device_from_path(task->path, upnp->server_udn_map);
505 cb_data = rsu_async_cb_data_new(task, cb, user_data, NULL, NULL,
507 cb_data->error = g_error_new(RSU_ERROR,
508 RSU_ERROR_OBJECT_NOT_FOUND,
509 "Cannot locate a device"
510 " for the specified "
512 (void) g_idle_add(rsu_async_complete_task, cb_data);
514 rsu_device_set_position(device, task, cancellable, cb,
519 void rsu_upnp_host_uri(rsu_upnp_t *upnp, rsu_task_t *task,
520 GCancellable *cancellable,
521 rsu_upnp_task_complete_t cb,
524 rsu_device_t *device;
525 rsu_async_cb_data_t *cb_data;
527 device = rsu_device_from_path(task->path, upnp->server_udn_map);
530 cb_data = rsu_async_cb_data_new(task, cb, user_data, NULL, NULL,
532 cb_data->error = g_error_new(RSU_ERROR,
533 RSU_ERROR_OBJECT_NOT_FOUND,
534 "Cannot locate a device"
535 " for the specified "
537 (void) g_idle_add(rsu_async_complete_task, cb_data);
539 rsu_device_host_uri(device, task, upnp->host_service,
540 cancellable, cb, user_data);
544 void rsu_upnp_remove_uri(rsu_upnp_t *upnp, rsu_task_t *task,
545 GCancellable *cancellable,
546 rsu_upnp_task_complete_t cb,
549 rsu_device_t *device;
550 rsu_async_cb_data_t *cb_data;
552 device = rsu_device_from_path(task->path, upnp->server_udn_map);
555 cb_data = rsu_async_cb_data_new(task, cb, user_data, NULL, NULL,
557 cb_data->error = g_error_new(RSU_ERROR,
558 RSU_ERROR_OBJECT_NOT_FOUND,
559 "Cannot locate a device"
560 " for the specified "
562 (void) g_idle_add(rsu_async_complete_task, cb_data);
564 rsu_device_remove_uri(device, task, upnp->host_service,
565 cancellable, cb, user_data);
569 void rsu_upnp_lost_client(rsu_upnp_t *upnp, const gchar *client_name)
571 rsu_host_service_lost_client(upnp->host_service, client_name);