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>
24 #include <libgupnp-av/gupnp-didl-lite-contributor.h>
27 #include "interface.h"
32 static const gchar gUPnPContainer[] = "object.container";
33 static const gchar gUPnPAlbum[] = "object.container.album";
34 static const gchar gUPnPPerson[] = "object.container.person";
35 static const gchar gUPnPGenre[] = "object.container.genre";
36 static const gchar gUPnPAudioItem[] = "object.item.audioItem";
37 static const gchar gUPnPVideoItem[] = "object.item.videoItem";
38 static const gchar gUPnPImageItem[] = "object.item.imageItem";
40 static const unsigned int gUPnPContainerLen =
41 (sizeof(gUPnPContainer) / sizeof(gchar)) - 1;
42 static const unsigned int gUPnPAlbumLen =
43 (sizeof(gUPnPAlbum) / sizeof(gchar)) - 1;
44 static const unsigned int gUPnPPersonLen =
45 (sizeof(gUPnPPerson) / sizeof(gchar)) - 1;
46 static const unsigned int gUPnPGenreLen =
47 (sizeof(gUPnPGenre) / sizeof(gchar)) - 1;
48 static const unsigned int gUPnPAudioItemLen =
49 (sizeof(gUPnPAudioItem) / sizeof(gchar)) - 1;
50 static const unsigned int gUPnPVideoItemLen =
51 (sizeof(gUPnPVideoItem) / sizeof(gchar)) - 1;
52 static const unsigned int gUPnPImageItemLen =
53 (sizeof(gUPnPImageItem) / sizeof(gchar)) - 1;
55 static const gchar gUPnPPhotoAlbum[] = "object.container.album.photoAlbum";
56 static const gchar gUPnPMusicAlbum[] = "object.container.album.musicAlbum";
57 static const gchar gUPnPMusicArtist[] = "object.container.person.musicArtist";
58 static const gchar gUPnPMovieGenre[] = "object.container.genre.movieGenre";
59 static const gchar gUPnPMusicGenre[] = "object.container.genre.musicGenre";
60 static const gchar gUPnPMusicTrack[] = "object.item.audioItem.musicTrack";
61 static const gchar gUPnPAudioBroadcast[] =
62 "object.item.audioItem.audioBroadcast";
63 static const gchar gUPnPAudioBook[] = "object.item.audioItem.audioBook";
64 static const gchar gUPnPMovie[] = "object.item.videoItem.movie";
65 static const gchar gUPnPMusicVideoClip[] =
66 "object.item.videoItem.musicVideoClip";
67 static const gchar gUPnPVideoBroadcast[] =
68 "object.item.videoItem.videoBroadcast";
69 static const gchar gUPnPPhoto[] = "object.item.imageItem.photo";
70 static const gchar gMediaSpec2Container[] = "container";
71 static const gchar gMediaSpec2Album[] = "album";
72 static const gchar gMediaSpec2AlbumPhoto[] = "album.photo";
73 static const gchar gMediaSpec2AlbumMusic[] = "album.music";
74 static const gchar gMediaSpec2Person[] = "person";
75 static const gchar gMediaSpec2PersonMusicArtist[] = "person.musicartist";
76 static const gchar gMediaSpec2Genre[] = "genre";
77 static const gchar gMediaSpec2GenreMovie[] = "genre.movie";
78 static const gchar gMediaSpec2GenreMusic[] = "genre.music";
79 static const gchar gMediaSpec2AudioMusic[] = "audio.music";
80 static const gchar gMediaSpec2AudioBroadcast[] = "audio.broadcast";
81 static const gchar gMediaSpec2AudioBook[] = "audio.book";
82 static const gchar gMediaSpec2Audio[] = "audio";
83 static const gchar gMediaSpec2VideoMovie[] = "video.movie";
84 static const gchar gMediaSpec2VideoMusicClip[] = "video.musicclip";
85 static const gchar gMediaSpec2VideoBroadcast[] = "video.broadcast";
86 static const gchar gMediaSpec2Video[] = "video";
87 static const gchar gMediaSpec2ImagePhoto[] = "image.photo";
88 static const gchar gMediaSpec2Image[] = "image";
90 static msu_prop_map_t *prv_msu_prop_map_new(const gchar *prop_name,
91 msu_upnp_prop_mask type,
96 msu_prop_map_t *retval = g_new(msu_prop_map_t, 1);
97 retval->upnp_prop_name = prop_name;
99 retval->filter = filter;
100 retval->searchable = searchable;
101 retval->updateable = updateable;
105 void msu_prop_maps_new(GHashTable **property_map, GHashTable **filter_map)
107 msu_prop_map_t *prop_t;
111 p_map = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL);
112 f_map = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free);
115 prop_t = prv_msu_prop_map_new("@childCount",
116 MSU_UPNP_MASK_PROP_CHILD_COUNT,
118 g_hash_table_insert(f_map, MSU_INTERFACE_PROP_CHILD_COUNT, prop_t);
119 g_hash_table_insert(p_map, "@childCount",
120 MSU_INTERFACE_PROP_CHILD_COUNT);
123 prop_t = prv_msu_prop_map_new("@id",
124 MSU_UPNP_MASK_PROP_PATH,
126 g_hash_table_insert(f_map, MSU_INTERFACE_PROP_PATH, prop_t);
127 g_hash_table_insert(p_map, "@id", MSU_INTERFACE_PROP_PATH);
130 prop_t = prv_msu_prop_map_new("@parentID",
131 MSU_UPNP_MASK_PROP_PARENT,
133 g_hash_table_insert(f_map, MSU_INTERFACE_PROP_PARENT, prop_t);
134 g_hash_table_insert(p_map, "@parentID", MSU_INTERFACE_PROP_PARENT);
137 prop_t = prv_msu_prop_map_new("@refID",
138 MSU_UPNP_MASK_PROP_REFPATH,
140 g_hash_table_insert(f_map, MSU_INTERFACE_PROP_REFPATH, prop_t);
141 g_hash_table_insert(p_map, "@refID", MSU_INTERFACE_PROP_REFPATH);
144 prop_t = prv_msu_prop_map_new("@restricted",
145 MSU_UPNP_MASK_PROP_RESTRICTED,
147 g_hash_table_insert(f_map, MSU_INTERFACE_PROP_RESTRICTED, prop_t);
148 g_hash_table_insert(p_map, "@restricted",
149 MSU_INTERFACE_PROP_RESTRICTED);
152 prop_t = prv_msu_prop_map_new("@searchable",
153 MSU_UPNP_MASK_PROP_SEARCHABLE,
155 g_hash_table_insert(f_map, MSU_INTERFACE_PROP_SEARCHABLE, prop_t);
156 g_hash_table_insert(p_map, "@searchable",
157 MSU_INTERFACE_PROP_SEARCHABLE);
160 prop_t = prv_msu_prop_map_new("dc:creator",
161 MSU_UPNP_MASK_PROP_CREATOR,
163 g_hash_table_insert(f_map, MSU_INTERFACE_PROP_CREATOR, prop_t);
164 g_hash_table_insert(p_map, "dc:creator", MSU_INTERFACE_PROP_CREATOR);
167 prop_t = prv_msu_prop_map_new("dc:date",
168 MSU_UPNP_MASK_PROP_DATE,
170 g_hash_table_insert(f_map, MSU_INTERFACE_PROP_DATE, prop_t);
171 g_hash_table_insert(p_map, "dc:date", MSU_INTERFACE_PROP_DATE);
174 prop_t = prv_msu_prop_map_new("dc:title",
175 MSU_UPNP_MASK_PROP_DISPLAY_NAME,
177 g_hash_table_insert(f_map, MSU_INTERFACE_PROP_DISPLAY_NAME, prop_t);
178 g_hash_table_insert(p_map, "dc:title", MSU_INTERFACE_PROP_DISPLAY_NAME);
180 /* dlna:dlnaManaged */
181 prop_t = prv_msu_prop_map_new("dlna:dlnaManaged",
182 MSU_UPNP_MASK_PROP_DLNA_MANAGED,
184 g_hash_table_insert(f_map, MSU_INTERFACE_PROP_DLNA_MANAGED, prop_t);
185 g_hash_table_insert(p_map, "dlna:dlnaManaged",
186 MSU_INTERFACE_PROP_DLNA_MANAGED);
190 prop_t = prv_msu_prop_map_new("res",
191 MSU_UPNP_MASK_PROP_RESOURCES,
193 g_hash_table_insert(f_map, MSU_INTERFACE_PROP_RESOURCES, prop_t);
196 prop_t = prv_msu_prop_map_new("res",
197 MSU_UPNP_MASK_PROP_URL,
199 g_hash_table_insert(f_map, MSU_INTERFACE_PROP_URL, prop_t);
202 prop_t = prv_msu_prop_map_new("res",
203 MSU_UPNP_MASK_PROP_URLS,
205 g_hash_table_insert(f_map, MSU_INTERFACE_PROP_URLS, prop_t);
208 prop_t = prv_msu_prop_map_new("res@bitrate",
209 MSU_UPNP_MASK_PROP_BITRATE,
211 g_hash_table_insert(f_map, MSU_INTERFACE_PROP_BITRATE, prop_t);
212 g_hash_table_insert(p_map, "res@bitrate", MSU_INTERFACE_PROP_BITRATE);
214 /* res@bitsPerSample */
215 prop_t = prv_msu_prop_map_new("res@bitsPerSample",
216 MSU_UPNP_MASK_PROP_BITS_PER_SAMPLE,
218 g_hash_table_insert(f_map, MSU_INTERFACE_PROP_BITS_PER_SAMPLE, prop_t);
219 g_hash_table_insert(p_map, "res@bitsPerSample",
220 MSU_INTERFACE_PROP_BITS_PER_SAMPLE);
223 prop_t = prv_msu_prop_map_new("res@colorDepth",
224 MSU_UPNP_MASK_PROP_COLOR_DEPTH,
226 g_hash_table_insert(f_map, MSU_INTERFACE_PROP_COLOR_DEPTH, prop_t);
227 g_hash_table_insert(p_map, "res@colorDepth",
228 MSU_INTERFACE_PROP_COLOR_DEPTH);
231 prop_t = prv_msu_prop_map_new("res@duration",
232 MSU_UPNP_MASK_PROP_DURATION,
234 g_hash_table_insert(f_map, MSU_INTERFACE_PROP_DURATION, prop_t);
235 g_hash_table_insert(p_map, "res@duration",
236 MSU_INTERFACE_PROP_DURATION);
238 /* res@protocolInfo */
239 /* res@protocolInfo - DLNA PROFILE*/
240 prop_t = prv_msu_prop_map_new("res@protocolInfo",
241 MSU_UPNP_MASK_PROP_DLNA_PROFILE,
243 g_hash_table_insert(f_map, MSU_INTERFACE_PROP_DLNA_PROFILE, prop_t);
245 /* res@protocolInfo - MIME TYPES*/
246 prop_t = prv_msu_prop_map_new("res@protocolInfo",
247 MSU_UPNP_MASK_PROP_MIME_TYPE,
249 g_hash_table_insert(f_map, MSU_INTERFACE_PROP_MIME_TYPE, prop_t);
252 /* res@resolution - HEIGH */
253 prop_t = prv_msu_prop_map_new("res@resolution",
254 MSU_UPNP_MASK_PROP_HEIGHT,
256 g_hash_table_insert(f_map, MSU_INTERFACE_PROP_HEIGHT, prop_t);
258 /* res@resolution - WIDTH */
259 prop_t = prv_msu_prop_map_new("res@resolution",
260 MSU_UPNP_MASK_PROP_WIDTH,
262 g_hash_table_insert(f_map, MSU_INTERFACE_PROP_WIDTH, prop_t);
264 /* res@sampleFrequency */
265 prop_t = prv_msu_prop_map_new("res@sampleFrequency",
266 MSU_UPNP_MASK_PROP_SAMPLE_RATE,
268 g_hash_table_insert(f_map, MSU_INTERFACE_PROP_SAMPLE_RATE, prop_t);
269 g_hash_table_insert(p_map, "res@sampleFrequency",
270 MSU_INTERFACE_PROP_SAMPLE_RATE);
273 prop_t = prv_msu_prop_map_new("res@size",
274 MSU_UPNP_MASK_PROP_SIZE,
276 g_hash_table_insert(f_map, MSU_INTERFACE_PROP_SIZE, prop_t);
277 g_hash_table_insert(p_map, "res@size", MSU_INTERFACE_PROP_SIZE);
280 prop_t = prv_msu_prop_map_new("upnp:album",
281 MSU_UPNP_MASK_PROP_ALBUM,
283 g_hash_table_insert(f_map, MSU_INTERFACE_PROP_ALBUM, prop_t);
284 g_hash_table_insert(p_map, "upnp:album", MSU_INTERFACE_PROP_ALBUM);
286 /* upnp:albumArtURI */
287 prop_t = prv_msu_prop_map_new("upnp:albumArtURI",
288 MSU_UPNP_MASK_PROP_ALBUM_ART_URL,
290 g_hash_table_insert(f_map, MSU_INTERFACE_PROP_ALBUM_ART_URL, prop_t);
291 g_hash_table_insert(p_map, "upnp:albumArtURI",
292 MSU_INTERFACE_PROP_ALBUM_ART_URL);
295 /* upnp:artist - ARTIST*/
296 prop_t = prv_msu_prop_map_new("upnp:artist",
297 MSU_UPNP_MASK_PROP_ARTIST,
299 g_hash_table_insert(f_map, MSU_INTERFACE_PROP_ARTIST, prop_t);
300 g_hash_table_insert(p_map, "upnp:artist", MSU_INTERFACE_PROP_ARTIST);
302 /* upnp:artist - ARTISTS*/
303 prop_t = prv_msu_prop_map_new("upnp:artist",
304 MSU_UPNP_MASK_PROP_ARTISTS,
306 g_hash_table_insert(f_map, MSU_INTERFACE_PROP_ARTISTS, prop_t);
309 prop_t = prv_msu_prop_map_new("upnp:class",
310 MSU_UPNP_MASK_PROP_TYPE,
312 g_hash_table_insert(f_map, MSU_INTERFACE_PROP_TYPE, prop_t);
313 g_hash_table_insert(p_map, "upnp:class", MSU_INTERFACE_PROP_TYPE);
315 /* upnp:createClass */
316 prop_t = prv_msu_prop_map_new("upnp:createClass",
317 MSU_UPNP_MASK_PROP_CREATE_CLASSES,
319 g_hash_table_insert(f_map, MSU_INTERFACE_PROP_CREATE_CLASSES, prop_t);
322 prop_t = prv_msu_prop_map_new("upnp:genre",
323 MSU_UPNP_MASK_PROP_GENRE,
325 g_hash_table_insert(f_map, MSU_INTERFACE_PROP_GENRE, prop_t);
326 g_hash_table_insert(p_map, "upnp:genre", MSU_INTERFACE_PROP_GENRE);
328 /* upnp:originalTrackNumber */
329 prop_t = prv_msu_prop_map_new("upnp:originalTrackNumber",
330 MSU_UPNP_MASK_PROP_TRACK_NUMBER,
332 g_hash_table_insert(f_map, MSU_INTERFACE_PROP_TRACK_NUMBER, prop_t);
333 g_hash_table_insert(p_map, "upnp:originalTrackNumber",
334 MSU_INTERFACE_PROP_TRACK_NUMBER);
337 *property_map = p_map;
340 static gchar *prv_compute_upnp_filter(GHashTable *upnp_props)
346 str = g_string_new("");
347 g_hash_table_iter_init(&iter, upnp_props);
348 if (g_hash_table_iter_next(&iter, &key, NULL)) {
349 g_string_append(str, (const gchar *) key);
350 while (g_hash_table_iter_next(&iter, &key, NULL)) {
351 g_string_append(str, ",");
352 g_string_append(str, (const gchar *) key);
356 return g_string_free(str, FALSE);
359 static guint32 prv_parse_filter_list(GHashTable *filter_map, GVariant *filter,
364 msu_prop_map_t *prop_map;
365 GHashTable *upnp_props;
368 upnp_props = g_hash_table_new_full(g_str_hash, g_str_equal,
370 (void) g_variant_iter_init(&viter, filter);
372 while (g_variant_iter_next(&viter, "&s", &prop)) {
373 prop_map = g_hash_table_lookup(filter_map, prop);
377 mask |= prop_map->type;
379 if (!prop_map->filter)
382 g_hash_table_insert(upnp_props,
383 (gpointer) prop_map->upnp_prop_name, NULL);
386 *upnp_filter = prv_compute_upnp_filter(upnp_props);
387 g_hash_table_unref(upnp_props);
392 guint32 msu_props_parse_filter(GHashTable *filter_map, GVariant *filter,
396 gboolean parse_filter = TRUE;
399 if (g_variant_n_children(filter) == 1) {
400 g_variant_get_child(filter, 0, "&s", &str);
401 if (!strcmp(str, "*"))
402 parse_filter = FALSE;
406 mask = prv_parse_filter_list(filter_map, filter, upnp_filter);
409 *upnp_filter = g_strdup("*");
415 gboolean msu_props_parse_update_filter(GHashTable *filter_map,
416 GVariant *to_add_update,
417 GVariant *to_delete, guint32 *mask,
423 msu_prop_map_t *prop_map;
424 GHashTable *upnp_props;
425 gboolean retval = FALSE;
429 upnp_props = g_hash_table_new_full(g_str_hash, g_str_equal,
432 (void) g_variant_iter_init(&viter, to_add_update);
434 while (g_variant_iter_next(&viter, "{&sv}", &prop, &value)) {
435 MSU_LOG_DEBUG("to_add_update = %s", prop);
437 prop_map = g_hash_table_lookup(filter_map, prop);
439 if ((!prop_map) || (!prop_map->updateable))
442 *mask |= prop_map->type;
444 if (!prop_map->filter)
447 g_hash_table_insert(upnp_props,
448 (gpointer) prop_map->upnp_prop_name, NULL);
451 (void) g_variant_iter_init(&viter, to_delete);
453 while (g_variant_iter_next(&viter, "&s", &prop)) {
454 MSU_LOG_DEBUG("to_delete = %s", prop);
456 prop_map = g_hash_table_lookup(filter_map, prop);
458 if ((!prop_map) || (!prop_map->updateable) ||
459 (*mask & prop_map->type) != 0)
462 *mask |= prop_map->type;
464 if (!prop_map->filter)
467 g_hash_table_insert(upnp_props,
468 (gpointer) prop_map->upnp_prop_name, NULL);
471 *upnp_filter = prv_compute_upnp_filter(upnp_props);
477 g_hash_table_unref(upnp_props);
482 static void prv_add_string_prop(GVariantBuilder *vb, const gchar *key,
486 MSU_LOG_DEBUG("Prop %s = %s", key, value);
488 g_variant_builder_add(vb, "{sv}", key,
489 g_variant_new_string(value));
493 static void prv_add_strv_prop(GVariantBuilder *vb, const gchar *key,
494 const gchar **value, unsigned int len)
497 g_variant_builder_add(vb, "{sv}", key,
498 g_variant_new_strv(value, len));
501 static void prv_add_path_prop(GVariantBuilder *vb, const gchar *key,
505 MSU_LOG_DEBUG("Prop %s = %s", key, value);
507 g_variant_builder_add(vb, "{sv}", key,
508 g_variant_new_object_path(value));
512 static void prv_add_uint_prop(GVariantBuilder *vb, const gchar *key,
515 MSU_LOG_DEBUG("Prop %s = %u", key, value);
517 g_variant_builder_add(vb, "{sv}", key, g_variant_new_uint32(value));
520 static void prv_add_int_prop(GVariantBuilder *vb, const gchar *key,
524 g_variant_builder_add(vb, "{sv}", key,
525 g_variant_new_int32(value));
528 static void prv_add_variant_prop(GVariantBuilder *vb, const gchar *key,
532 g_variant_builder_add(vb, "{sv}", key, prop);
535 void msu_props_add_child_count(GVariantBuilder *item_vb, gint value)
537 prv_add_int_prop(item_vb, MSU_INTERFACE_PROP_CHILD_COUNT, value);
540 static void prv_add_bool_prop(GVariantBuilder *vb, const gchar *key,
543 MSU_LOG_DEBUG("Prop %s = %u", key, value);
545 g_variant_builder_add(vb, "{sv}", key, g_variant_new_boolean(value));
548 static void prv_add_int64_prop(GVariantBuilder *vb, const gchar *key,
552 MSU_LOG_DEBUG("Prop %s = %"G_GINT64_FORMAT, key, value);
554 g_variant_builder_add(vb, "{sv}", key,
555 g_variant_new_int64(value));
559 static void prv_add_list_dlna_str(gpointer data, gpointer user_data)
561 GVariantBuilder *vb = (GVariantBuilder *) user_data;
562 gchar *cap_str = (gchar *) data;
566 if (g_str_has_prefix(cap_str, "srs-rt-retention-period-")) {
567 str = cap_str + strlen("srs-rt-retention-period-");
568 cap_str = "srs-rt-retention-period";
571 if (!g_strcmp0(str, "infinity"))
578 prv_add_uint_prop(vb, cap_str, value);
581 static GVariant *prv_add_list_dlna_prop(GList* list)
585 g_variant_builder_init(&vb, G_VARIANT_TYPE("a{sv}"));
587 g_list_foreach(list, prv_add_list_dlna_str, &vb);
589 return g_variant_builder_end(&vb);
592 static void prv_add_list_artists_str(gpointer data, gpointer user_data)
594 GVariantBuilder *vb = (GVariantBuilder *) user_data;
595 GUPnPDIDLLiteContributor *contributor = data;
598 str = gupnp_didl_lite_contributor_get_name(contributor);
599 g_variant_builder_add(vb, "s", str);
602 static GVariant *prv_get_artists_prop(GList *list)
606 g_variant_builder_init(&vb, G_VARIANT_TYPE("as"));
607 g_list_foreach(list, prv_add_list_artists_str, &vb);
609 return g_variant_builder_end(&vb);
612 void msu_props_add_device(GUPnPDeviceInfo *proxy,
613 msu_device_t *device,
620 prv_add_string_prop(vb, MSU_INTERFACE_PROP_LOCATION,
621 gupnp_device_info_get_location(proxy));
623 prv_add_string_prop(vb, MSU_INTERFACE_PROP_UDN,
624 gupnp_device_info_get_udn(proxy));
626 prv_add_string_prop(vb, MSU_INTERFACE_PROP_DEVICE_TYPE,
627 gupnp_device_info_get_device_type(proxy));
629 str = gupnp_device_info_get_friendly_name(proxy);
630 prv_add_string_prop(vb, MSU_INTERFACE_PROP_FRIENDLY_NAME, str);
633 str = gupnp_device_info_get_manufacturer(proxy);
634 prv_add_string_prop(vb, MSU_INTERFACE_PROP_MANUFACTURER, str);
637 str = gupnp_device_info_get_manufacturer_url(proxy);
638 prv_add_string_prop(vb, MSU_INTERFACE_PROP_MANUFACTURER_URL, str);
641 str = gupnp_device_info_get_model_description(proxy);
642 prv_add_string_prop(vb, MSU_INTERFACE_PROP_MODEL_DESCRIPTION, str);
645 str = gupnp_device_info_get_model_name(proxy);
646 prv_add_string_prop(vb, MSU_INTERFACE_PROP_MODEL_NAME, str);
649 str = gupnp_device_info_get_model_number(proxy);
650 prv_add_string_prop(vb, MSU_INTERFACE_PROP_MODEL_NUMBER, str);
653 str = gupnp_device_info_get_model_url(proxy);
654 prv_add_string_prop(vb, MSU_INTERFACE_PROP_MODEL_URL, str);
657 str = gupnp_device_info_get_serial_number(proxy);
658 prv_add_string_prop(vb, MSU_INTERFACE_PROP_SERIAL_NUMBER, str);
661 str = gupnp_device_info_get_presentation_url(proxy);
662 prv_add_string_prop(vb, MSU_INTERFACE_PROP_PRESENTATION_URL, str);
665 str = gupnp_device_info_get_icon_url(proxy, NULL, -1, -1, -1, FALSE,
666 NULL, NULL, NULL, NULL);
667 prv_add_string_prop(vb, MSU_INTERFACE_PROP_ICON_URL, str);
670 list = gupnp_device_info_list_dlna_capabilities(proxy);
672 dlna_caps = prv_add_list_dlna_prop(list);
673 g_variant_builder_add(vb, "{sv}",
674 MSU_INTERFACE_PROP_SV_DLNA_CAPABILITIES,
676 g_list_free_full(list, g_free);
679 if (device->search_caps != NULL)
680 g_variant_builder_add(vb, "{sv}",
681 MSU_INTERFACE_PROP_SV_SEARCH_CAPABILITIES,
682 device->search_caps);
684 if (device->sort_caps != NULL)
685 g_variant_builder_add(vb, "{sv}",
686 MSU_INTERFACE_PROP_SV_SORT_CAPABILITIES,
689 if (device->sort_ext_caps != NULL)
690 g_variant_builder_add(vb, "{sv}",
691 MSU_INTERFACE_PROP_SV_SORT_EXT_CAPABILITIES,
692 device->sort_ext_caps);
694 if (device->feature_list != NULL)
695 g_variant_builder_add(vb, "{sv}",
696 MSU_INTERFACE_PROP_SV_FEATURE_LIST,
697 device->feature_list);
700 GVariant *msu_props_get_device_prop(GUPnPDeviceInfo *proxy,
701 msu_device_t *device,
704 GVariant *dlna_caps = NULL;
705 GVariant *retval = NULL;
706 const gchar *str = NULL;
710 if (!strcmp(MSU_INTERFACE_PROP_LOCATION, prop)) {
711 str = gupnp_device_info_get_location(proxy);
712 } else if (!strcmp(MSU_INTERFACE_PROP_UDN, prop)) {
713 str = gupnp_device_info_get_udn(proxy);
714 } else if (!strcmp(MSU_INTERFACE_PROP_DEVICE_TYPE, prop)) {
715 str = gupnp_device_info_get_device_type(proxy);
716 } else if (!strcmp(MSU_INTERFACE_PROP_FRIENDLY_NAME, prop)) {
717 copy = gupnp_device_info_get_friendly_name(proxy);
719 } else if (!strcmp(MSU_INTERFACE_PROP_MANUFACTURER, prop)) {
720 copy = gupnp_device_info_get_manufacturer(proxy);
722 } else if (!strcmp(MSU_INTERFACE_PROP_MANUFACTURER_URL, prop)) {
723 copy = gupnp_device_info_get_manufacturer_url(proxy);
725 } else if (!strcmp(MSU_INTERFACE_PROP_MODEL_DESCRIPTION, prop)) {
726 copy = gupnp_device_info_get_model_description(proxy);
728 } else if (!strcmp(MSU_INTERFACE_PROP_MODEL_NAME, prop)) {
729 copy = gupnp_device_info_get_model_name(proxy);
731 } else if (!strcmp(MSU_INTERFACE_PROP_MODEL_NUMBER, prop)) {
732 copy = gupnp_device_info_get_model_number(proxy);
734 } else if (!strcmp(MSU_INTERFACE_PROP_MODEL_URL, prop)) {
735 copy = gupnp_device_info_get_model_url(proxy);
737 } else if (!strcmp(MSU_INTERFACE_PROP_SERIAL_NUMBER, prop)) {
738 copy = gupnp_device_info_get_serial_number(proxy);
740 } else if (!strcmp(MSU_INTERFACE_PROP_PRESENTATION_URL, prop)) {
741 copy = gupnp_device_info_get_presentation_url(proxy);
743 } else if (!strcmp(MSU_INTERFACE_PROP_ICON_URL, prop)) {
744 copy = gupnp_device_info_get_icon_url(proxy, NULL,
746 NULL, NULL, NULL, NULL);
748 } else if (!strcmp(MSU_INTERFACE_PROP_SV_DLNA_CAPABILITIES, prop)) {
749 list = gupnp_device_info_list_dlna_capabilities(proxy);
751 dlna_caps = prv_add_list_dlna_prop(list);
752 g_list_free_full(list, g_free);
753 retval = g_variant_ref_sink(dlna_caps);
755 #if MSU_LOG_LEVEL & MSU_LOG_LEVEL_DEBUG
756 copy = g_variant_print(dlna_caps, FALSE);
757 MSU_LOG_DEBUG("Prop %s = %s", prop, copy);
760 } else if (!strcmp(MSU_INTERFACE_PROP_SV_SEARCH_CAPABILITIES, prop)) {
761 if (device->search_caps != NULL){
762 retval = g_variant_ref(device->search_caps);
764 #if MSU_LOG_LEVEL & MSU_LOG_LEVEL_DEBUG
765 copy = g_variant_print(device->search_caps, FALSE);
766 MSU_LOG_DEBUG("Prop %s = %s", prop, copy);
769 } else if (!strcmp(MSU_INTERFACE_PROP_SV_SORT_CAPABILITIES, prop)) {
770 if (device->sort_caps != NULL){
771 retval = g_variant_ref(device->sort_caps);
773 #if MSU_LOG_LEVEL & MSU_LOG_LEVEL_DEBUG
774 copy = g_variant_print(device->sort_caps, FALSE);
775 MSU_LOG_DEBUG("Prop %s = %s", prop, copy);
778 } else if (!strcmp(MSU_INTERFACE_PROP_SV_SORT_EXT_CAPABILITIES, prop)) {
779 if (device->sort_ext_caps != NULL){
780 retval = g_variant_ref(device->sort_ext_caps);
782 #if MSU_LOG_LEVEL & MSU_LOG_LEVEL_DEBUG
783 copy = g_variant_print(device->sort_ext_caps, FALSE);
784 MSU_LOG_DEBUG("Prop %s = %s", prop, copy);
787 } else if (!strcmp(MSU_INTERFACE_PROP_SV_FEATURE_LIST, prop)) {
788 if (device->feature_list != NULL){
789 retval = g_variant_ref(device->feature_list);
791 #if MSU_LOG_LEVEL & MSU_LOG_LEVEL_DEBUG
792 copy = g_variant_print(device->feature_list, FALSE);
793 MSU_LOG_DEBUG("Prop %s = %s", prop, copy);
800 MSU_LOG_DEBUG("Prop %s = %s", prop, str);
802 retval = g_variant_ref_sink(g_variant_new_string(str));
804 #if MSU_LOG_LEVEL & MSU_LOG_LEVEL_WARNING
806 MSU_LOG_WARNING("Property %s not defined", prop);
815 static GUPnPDIDLLiteResource *prv_match_resource(GUPnPDIDLLiteResource *res,
816 gchar **pi_str_array)
818 GUPnPDIDLLiteResource *retval = NULL;
819 GUPnPProtocolInfo *res_pi;
820 GUPnPProtocolInfo *pi;
829 res_pi = gupnp_didl_lite_resource_get_protocol_info(res);
833 for (i = 0; pi_str_array[i]; ++i) {
834 pi = gupnp_protocol_info_new_from_string(pi_str_array[i],
838 match = gupnp_protocol_info_is_compatible(pi, res_pi);
850 static GUPnPDIDLLiteResource *prv_get_matching_resource
851 (GUPnPDIDLLiteObject *object, const gchar *protocol_info)
853 GUPnPDIDLLiteResource *retval = NULL;
854 GUPnPDIDLLiteResource *res;
857 gchar **pi_str_array = NULL;
860 pi_str_array = g_strsplit(protocol_info, ",", 0);
862 resources = gupnp_didl_lite_object_get_resources(object);
868 retval = prv_match_resource(res, pi_str_array);
876 g_list_free(resources);
878 g_strfreev(pi_str_array);
883 static void prv_parse_resources(GVariantBuilder *item_vb,
884 GUPnPDIDLLiteResource *res,
887 GUPnPProtocolInfo *protocol_info;
892 if (filter_mask & MSU_UPNP_MASK_PROP_SIZE) {
893 int64_val = gupnp_didl_lite_resource_get_size64(res);
894 prv_add_int64_prop(item_vb, MSU_INTERFACE_PROP_SIZE, int64_val);
897 if (filter_mask & MSU_UPNP_MASK_PROP_BITRATE) {
898 int_val = gupnp_didl_lite_resource_get_bitrate(res);
899 prv_add_int_prop(item_vb, MSU_INTERFACE_PROP_BITRATE, int_val);
902 if (filter_mask & MSU_UPNP_MASK_PROP_SAMPLE_RATE) {
903 int_val = gupnp_didl_lite_resource_get_sample_freq(res);
904 prv_add_int_prop(item_vb, MSU_INTERFACE_PROP_SAMPLE_RATE,
908 if (filter_mask & MSU_UPNP_MASK_PROP_BITS_PER_SAMPLE) {
909 int_val = gupnp_didl_lite_resource_get_bits_per_sample(res);
910 prv_add_int_prop(item_vb, MSU_INTERFACE_PROP_BITS_PER_SAMPLE,
914 if (filter_mask & MSU_UPNP_MASK_PROP_DURATION) {
915 int_val = (int) gupnp_didl_lite_resource_get_duration(res);
916 prv_add_int_prop(item_vb, MSU_INTERFACE_PROP_DURATION, int_val);
919 if (filter_mask & MSU_UPNP_MASK_PROP_WIDTH) {
920 int_val = (int) gupnp_didl_lite_resource_get_width(res);
921 prv_add_int_prop(item_vb, MSU_INTERFACE_PROP_WIDTH, int_val);
924 if (filter_mask & MSU_UPNP_MASK_PROP_HEIGHT) {
925 int_val = (int) gupnp_didl_lite_resource_get_height(res);
926 prv_add_int_prop(item_vb, MSU_INTERFACE_PROP_HEIGHT, int_val);
929 if (filter_mask & MSU_UPNP_MASK_PROP_COLOR_DEPTH) {
930 int_val = (int) gupnp_didl_lite_resource_get_color_depth(res);
931 prv_add_int_prop(item_vb, MSU_INTERFACE_PROP_COLOR_DEPTH,
935 protocol_info = gupnp_didl_lite_resource_get_protocol_info(res);
937 if (filter_mask & MSU_UPNP_MASK_PROP_DLNA_PROFILE) {
938 str_val = gupnp_protocol_info_get_dlna_profile(protocol_info);
939 prv_add_string_prop(item_vb, MSU_INTERFACE_PROP_DLNA_PROFILE,
943 if (filter_mask & MSU_UPNP_MASK_PROP_MIME_TYPE) {
944 str_val = gupnp_protocol_info_get_mime_type(protocol_info);
945 prv_add_string_prop(item_vb, MSU_INTERFACE_PROP_MIME_TYPE,
950 static GVariant *prv_compute_create_classes(GUPnPDIDLLiteContainer *container)
952 GVariantBuilder create_classes_vb;
953 GList *create_classes;
955 GUPnPDIDLLiteCreateClass *create_class;
957 gboolean inc_derived;
959 g_variant_builder_init(&create_classes_vb, G_VARIANT_TYPE("a(sb)"));
961 create_classes = gupnp_didl_lite_container_get_create_classes_full(
963 ptr = create_classes;
965 create_class = ptr->data;
966 content = gupnp_didl_lite_create_class_get_content(
968 inc_derived = gupnp_didl_lite_create_class_get_include_derived(
970 g_variant_builder_add(&create_classes_vb,
971 "(sb)", content, inc_derived);
972 g_object_unref(ptr->data);
973 ptr = g_list_next(ptr);
975 g_list_free(create_classes);
977 return g_variant_builder_end(&create_classes_vb);
980 const gchar *msu_props_media_spec_to_upnp_class(const gchar *m2spec_class)
982 const gchar *retval = NULL;
984 if (!strcmp(m2spec_class, gMediaSpec2AlbumPhoto))
985 retval = gUPnPPhotoAlbum;
986 else if (!strcmp(m2spec_class, gMediaSpec2AlbumMusic))
987 retval = gUPnPMusicAlbum;
988 else if (!strcmp(m2spec_class, gMediaSpec2Album))
990 else if (!strcmp(m2spec_class, gMediaSpec2PersonMusicArtist))
991 retval = gUPnPMusicArtist;
992 else if (!strcmp(m2spec_class, gMediaSpec2Person))
993 retval = gUPnPPerson;
994 else if (!strcmp(m2spec_class, gMediaSpec2GenreMovie))
995 retval = gUPnPMovieGenre;
996 else if (!strcmp(m2spec_class, gMediaSpec2GenreMusic))
997 retval = gUPnPMusicGenre;
998 else if (!strcmp(m2spec_class, gMediaSpec2Genre))
1000 else if (!strcmp(m2spec_class, gMediaSpec2Container))
1001 retval = gUPnPContainer;
1002 else if (!strcmp(m2spec_class, gMediaSpec2AudioMusic))
1003 retval = gUPnPMusicTrack;
1004 else if (!strcmp(m2spec_class, gMediaSpec2AudioBroadcast))
1005 retval = gUPnPAudioBroadcast;
1006 else if (!strcmp(m2spec_class, gMediaSpec2AudioBook))
1007 retval = gUPnPAudioBook;
1008 else if (!strcmp(m2spec_class, gMediaSpec2Audio))
1009 retval = gUPnPAudioItem;
1010 else if (!strcmp(m2spec_class, gMediaSpec2VideoMovie))
1011 retval = gUPnPMovie;
1012 else if (!strcmp(m2spec_class, gMediaSpec2VideoMusicClip))
1013 retval = gUPnPMusicVideoClip;
1014 else if (!strcmp(m2spec_class, gMediaSpec2VideoBroadcast))
1015 retval = gUPnPVideoBroadcast;
1016 else if (!strcmp(m2spec_class, gMediaSpec2Video))
1017 retval = gUPnPVideoItem;
1018 else if (!strcmp(m2spec_class, gMediaSpec2ImagePhoto))
1019 retval = gUPnPPhoto;
1020 else if (!strcmp(m2spec_class, gMediaSpec2Image))
1021 retval = gUPnPImageItem;
1026 const gchar *msu_props_upnp_class_to_media_spec(const gchar *upnp_class)
1028 const gchar *retval = NULL;
1031 if (!strncmp(upnp_class, gUPnPAlbum, gUPnPAlbumLen)) {
1032 ptr = upnp_class + gUPnPAlbumLen;
1033 if (!strcmp(ptr, ".photoAlbum"))
1034 retval = gMediaSpec2AlbumPhoto;
1035 else if (!strcmp(ptr, ".musicAlbum"))
1036 retval = gMediaSpec2AlbumMusic;
1038 retval = gMediaSpec2Album;
1039 } else if (!strncmp(upnp_class, gUPnPPerson, gUPnPPersonLen)) {
1040 ptr = upnp_class + gUPnPPersonLen;
1041 if (!strcmp(ptr, ".musicArtist"))
1042 retval = gMediaSpec2PersonMusicArtist;
1044 retval = gMediaSpec2Person;
1045 } else if (!strncmp(upnp_class, gUPnPGenre, gUPnPGenreLen)) {
1046 ptr = upnp_class + gUPnPGenreLen;
1047 if (!strcmp(ptr, ".movieGenre"))
1048 retval = gMediaSpec2GenreMovie;
1049 else if (!strcmp(ptr, ".musicGenre"))
1050 retval = gMediaSpec2GenreMusic;
1052 retval = gMediaSpec2Genre;
1053 } else if (!strncmp(upnp_class, gUPnPContainer, gUPnPContainerLen)) {
1054 ptr = upnp_class + gUPnPContainerLen;
1055 if (!*ptr || *ptr == '.')
1056 retval = gMediaSpec2Container;
1057 } else if (!strncmp(upnp_class, gUPnPAudioItem, gUPnPAudioItemLen)) {
1058 ptr = upnp_class + gUPnPAudioItemLen;
1059 if (!strcmp(ptr, ".musicTrack"))
1060 retval = gMediaSpec2AudioMusic;
1061 else if (!strcmp(ptr, ".audioBroadcast"))
1062 retval = gMediaSpec2AudioBroadcast;
1063 else if (!strcmp(ptr, ".audioBook"))
1064 retval = gMediaSpec2AudioBook;
1066 retval = gMediaSpec2Audio;
1067 } else if (!strncmp(upnp_class, gUPnPVideoItem, gUPnPVideoItemLen)) {
1068 ptr = upnp_class + gUPnPVideoItemLen;
1069 if (!strcmp(ptr, ".movie"))
1070 retval = gMediaSpec2VideoMovie;
1071 else if (!strcmp(ptr, ".musicVideoClip"))
1072 retval = gMediaSpec2VideoMusicClip;
1073 else if (!strcmp(ptr, ".videoBroadcast"))
1074 retval = gMediaSpec2VideoBroadcast;
1076 retval = gMediaSpec2Video;
1077 } else if (!strncmp(upnp_class, gUPnPImageItem, gUPnPImageItemLen)) {
1078 ptr = upnp_class + gUPnPImageItemLen;
1079 if (!strcmp(ptr, ".photo"))
1080 retval = gMediaSpec2ImagePhoto;
1082 retval = gMediaSpec2Image;
1088 static GVariant *prv_props_get_dlna_managed_dict(GUPnPOCMFlags flags)
1090 GVariantBuilder builder;
1093 g_variant_builder_init(&builder, G_VARIANT_TYPE("a{sb}"));
1095 managed = (flags & GUPNP_OCM_FLAGS_UPLOAD);
1096 g_variant_builder_add(&builder, "{sb}", "Upload", managed);
1098 managed = (flags & GUPNP_OCM_FLAGS_CREATE_CONTAINER);
1099 g_variant_builder_add(&builder, "{sb}", "CreateContainer", managed);
1101 managed = (flags & GUPNP_OCM_FLAGS_DESTROYABLE);
1102 g_variant_builder_add(&builder, "{sb}", "Delete", managed);
1104 managed = (flags & GUPNP_OCM_FLAGS_UPLOAD_DESTROYABLE);
1105 g_variant_builder_add(&builder, "{sb}", "UploadDelete", managed);
1107 managed = (flags & GUPNP_OCM_FLAGS_CHANGE_METADATA);
1108 g_variant_builder_add(&builder, "{sb}", "ChangeMeta", managed);
1110 return g_variant_builder_end(&builder);
1113 gboolean msu_props_add_object(GVariantBuilder *item_vb,
1114 GUPnPDIDLLiteObject *object,
1115 const char *root_path,
1116 const gchar *parent_path,
1117 guint32 filter_mask)
1122 const char *creator;
1123 const char *upnp_class;
1124 const char *media_spec_type;
1125 gboolean retval = FALSE;
1127 GUPnPOCMFlags flags;
1129 id = gupnp_didl_lite_object_get_id(object);
1133 upnp_class = gupnp_didl_lite_object_get_upnp_class(object);
1134 media_spec_type = msu_props_upnp_class_to_media_spec(upnp_class);
1136 if (!media_spec_type)
1139 title = gupnp_didl_lite_object_get_title(object);
1140 creator = gupnp_didl_lite_object_get_creator(object);
1141 rest = gupnp_didl_lite_object_get_restricted(object);
1142 path = msu_path_from_id(root_path, id);
1144 if (filter_mask & MSU_UPNP_MASK_PROP_DISPLAY_NAME)
1145 prv_add_string_prop(item_vb, MSU_INTERFACE_PROP_DISPLAY_NAME,
1148 if (filter_mask & MSU_UPNP_MASK_PROP_CREATOR)
1149 prv_add_string_prop(item_vb, MSU_INTERFACE_PROP_CREATOR,
1152 if (filter_mask & MSU_UPNP_MASK_PROP_PATH)
1153 prv_add_path_prop(item_vb, MSU_INTERFACE_PROP_PATH, path);
1155 if (filter_mask & MSU_UPNP_MASK_PROP_PARENT)
1156 prv_add_path_prop(item_vb, MSU_INTERFACE_PROP_PARENT,
1159 if (filter_mask & MSU_UPNP_MASK_PROP_TYPE)
1160 prv_add_string_prop(item_vb, MSU_INTERFACE_PROP_TYPE,
1163 if (filter_mask & MSU_UPNP_MASK_PROP_RESTRICTED)
1164 prv_add_bool_prop(item_vb, MSU_INTERFACE_PROP_RESTRICTED, rest);
1166 if (filter_mask & MSU_UPNP_MASK_PROP_DLNA_MANAGED) {
1167 flags = gupnp_didl_lite_object_get_dlna_managed(object);
1168 prv_add_variant_prop(item_vb,
1169 MSU_INTERFACE_PROP_DLNA_MANAGED,
1170 prv_props_get_dlna_managed_dict(flags));
1182 void msu_props_add_container(GVariantBuilder *item_vb,
1183 GUPnPDIDLLiteContainer *object,
1184 guint32 filter_mask,
1185 gboolean *have_child_count)
1188 gboolean searchable;
1190 *have_child_count = FALSE;
1191 if (filter_mask & MSU_UPNP_MASK_PROP_CHILD_COUNT) {
1192 child_count = gupnp_didl_lite_container_get_child_count(object);
1193 if (child_count >= 0) {
1194 prv_add_uint_prop(item_vb,
1195 MSU_INTERFACE_PROP_CHILD_COUNT,
1196 (unsigned int) child_count);
1197 *have_child_count = TRUE;
1201 if (filter_mask & MSU_UPNP_MASK_PROP_SEARCHABLE) {
1202 searchable = gupnp_didl_lite_container_get_searchable(object);
1203 prv_add_bool_prop(item_vb, MSU_INTERFACE_PROP_SEARCHABLE,
1207 if (filter_mask & MSU_UPNP_MASK_PROP_CREATE_CLASSES)
1208 prv_add_variant_prop(item_vb,
1209 MSU_INTERFACE_PROP_CREATE_CLASSES,
1210 prv_compute_create_classes(object));
1213 static GVariant *prv_compute_resources(GUPnPDIDLLiteObject *object,
1214 guint32 filter_mask)
1216 GUPnPDIDLLiteResource *res = NULL;
1219 GVariantBuilder *res_array_vb;
1220 GVariantBuilder *res_vb;
1221 const char *str_val;
1224 res_array_vb = g_variant_builder_new(G_VARIANT_TYPE("aa{sv}"));
1226 resources = gupnp_didl_lite_object_get_resources(object);
1231 res_vb = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
1232 if (filter_mask & MSU_UPNP_MASK_PROP_URL) {
1233 str_val = gupnp_didl_lite_resource_get_uri(res);
1235 prv_add_string_prop(res_vb,
1236 MSU_INTERFACE_PROP_URL,
1239 prv_parse_resources(res_vb, res, filter_mask);
1240 g_variant_builder_add(res_array_vb, "@a{sv}",
1241 g_variant_builder_end(res_vb));
1242 g_variant_builder_unref(res_vb);
1243 ptr = g_list_next(ptr);
1245 retval = g_variant_builder_end(res_array_vb);
1246 g_variant_builder_unref(res_array_vb);
1250 g_object_unref(ptr->data);
1253 g_list_free(resources);
1258 static void prv_add_resources(GVariantBuilder *item_vb,
1259 GUPnPDIDLLiteObject *object,
1260 guint32 filter_mask)
1264 val = prv_compute_resources(object, filter_mask);
1265 g_variant_builder_add(item_vb, "{sv}", MSU_INTERFACE_PROP_RESOURCES,
1269 void msu_props_add_item(GVariantBuilder *item_vb,
1270 GUPnPDIDLLiteObject *object,
1271 const gchar *root_path,
1272 guint32 filter_mask,
1273 const gchar *protocol_info)
1276 GUPnPDIDLLiteResource *res;
1277 const char *str_val;
1281 if (filter_mask & MSU_UPNP_MASK_PROP_ARTIST)
1282 prv_add_string_prop(item_vb, MSU_INTERFACE_PROP_ARTIST,
1283 gupnp_didl_lite_object_get_artist(object));
1285 if (filter_mask & MSU_UPNP_MASK_PROP_ARTISTS) {
1286 list = gupnp_didl_lite_object_get_artists(object);
1287 prv_add_variant_prop(item_vb, MSU_INTERFACE_PROP_ARTISTS,
1288 prv_get_artists_prop(list));
1289 g_list_free_full(list, g_object_unref);
1292 if (filter_mask & MSU_UPNP_MASK_PROP_ALBUM)
1293 prv_add_string_prop(item_vb, MSU_INTERFACE_PROP_ALBUM,
1294 gupnp_didl_lite_object_get_album(object));
1296 if (filter_mask & MSU_UPNP_MASK_PROP_DATE)
1297 prv_add_string_prop(item_vb, MSU_INTERFACE_PROP_DATE,
1298 gupnp_didl_lite_object_get_date(object));
1300 if (filter_mask & MSU_UPNP_MASK_PROP_GENRE)
1301 prv_add_string_prop(item_vb, MSU_INTERFACE_PROP_GENRE,
1302 gupnp_didl_lite_object_get_genre(object));
1304 if (filter_mask & MSU_UPNP_MASK_PROP_TRACK_NUMBER) {
1305 track_number = gupnp_didl_lite_object_get_track_number(object);
1306 if (track_number >= 0)
1307 prv_add_int_prop(item_vb,
1308 MSU_INTERFACE_PROP_TRACK_NUMBER,
1312 if (filter_mask & MSU_UPNP_MASK_PROP_ALBUM_ART_URL)
1313 prv_add_string_prop(item_vb, MSU_INTERFACE_PROP_ALBUM_ART_URL,
1314 gupnp_didl_lite_object_get_album_art(
1317 if (filter_mask & MSU_UPNP_MASK_PROP_REFPATH) {
1318 str_val = gupnp_didl_lite_item_get_ref_id(
1319 GUPNP_DIDL_LITE_ITEM(object));
1320 if (str_val != NULL) {
1321 path = msu_path_from_id(root_path, str_val);
1322 prv_add_path_prop(item_vb, MSU_INTERFACE_PROP_REFPATH,
1328 res = prv_get_matching_resource(object, protocol_info);
1330 if (filter_mask & MSU_UPNP_MASK_PROP_URLS) {
1331 str_val = gupnp_didl_lite_resource_get_uri(res);
1333 prv_add_strv_prop(item_vb,
1334 MSU_INTERFACE_PROP_URLS,
1337 prv_parse_resources(item_vb, res, filter_mask);
1338 g_object_unref(res);
1341 if (filter_mask & MSU_UPNP_MASK_PROP_RESOURCES)
1342 prv_add_resources(item_vb, object, filter_mask);
1345 void msu_props_add_resource(GVariantBuilder *item_vb,
1346 GUPnPDIDLLiteObject *object,
1347 guint32 filter_mask,
1348 const gchar *protocol_info)
1350 GUPnPDIDLLiteResource *res;
1351 const char *str_val;
1353 res = prv_get_matching_resource(object, protocol_info);
1355 if (filter_mask & MSU_UPNP_MASK_PROP_URL) {
1356 str_val = gupnp_didl_lite_resource_get_uri(res);
1358 prv_add_string_prop(item_vb,
1359 MSU_INTERFACE_PROP_URL,
1362 prv_parse_resources(item_vb, res, filter_mask);
1363 g_object_unref(res);
1368 static GVariant *prv_get_resource_property(const gchar *prop,
1369 GUPnPDIDLLiteResource *res)
1373 const char *str_val;
1374 GVariant *retval = NULL;
1375 GUPnPProtocolInfo *protocol_info;
1377 if (!strcmp(prop, MSU_INTERFACE_PROP_DLNA_PROFILE)) {
1378 protocol_info = gupnp_didl_lite_resource_get_protocol_info(res);
1381 str_val = gupnp_protocol_info_get_dlna_profile(protocol_info);
1384 retval = g_variant_ref_sink(g_variant_new_string(str_val));
1385 } else if (!strcmp(prop, MSU_INTERFACE_PROP_MIME_TYPE)) {
1386 protocol_info = gupnp_didl_lite_resource_get_protocol_info(res);
1389 str_val = gupnp_protocol_info_get_mime_type(protocol_info);
1392 retval = g_variant_ref_sink(g_variant_new_string(str_val));
1393 } else if (!strcmp(prop, MSU_INTERFACE_PROP_SIZE)) {
1394 int64_val = gupnp_didl_lite_resource_get_size64(res);
1395 if (int64_val == -1)
1397 retval = g_variant_ref_sink(g_variant_new_int64(int64_val));
1398 } else if (!strcmp(prop, MSU_INTERFACE_PROP_DURATION)) {
1399 int_val = (int) gupnp_didl_lite_resource_get_duration(res);
1402 retval = g_variant_ref_sink(g_variant_new_int32(int_val));
1403 } else if (!strcmp(prop, MSU_INTERFACE_PROP_BITRATE)) {
1404 int_val = gupnp_didl_lite_resource_get_bitrate(res);
1407 retval = g_variant_ref_sink(g_variant_new_int32(int_val));
1408 } else if (!strcmp(prop, MSU_INTERFACE_PROP_SAMPLE_RATE)) {
1409 int_val = gupnp_didl_lite_resource_get_sample_freq(res);
1412 retval = g_variant_ref_sink(g_variant_new_int32(int_val));
1413 } else if (!strcmp(prop, MSU_INTERFACE_PROP_BITS_PER_SAMPLE)) {
1414 int_val = gupnp_didl_lite_resource_get_bits_per_sample(res);
1417 retval = g_variant_ref_sink(g_variant_new_int32(int_val));
1418 } else if (!strcmp(prop, MSU_INTERFACE_PROP_WIDTH)) {
1419 int_val = (int) gupnp_didl_lite_resource_get_width(res);
1422 retval = g_variant_ref_sink(g_variant_new_int32(int_val));
1423 } else if (!strcmp(prop, MSU_INTERFACE_PROP_HEIGHT)) {
1424 int_val = (int) gupnp_didl_lite_resource_get_height(res);
1427 retval = g_variant_ref_sink(g_variant_new_int32(int_val));
1428 } else if (!strcmp(prop, MSU_INTERFACE_PROP_COLOR_DEPTH)) {
1429 int_val = (int) gupnp_didl_lite_resource_get_color_depth(res);
1432 retval = g_variant_ref_sink(g_variant_new_int32(int_val));
1433 } else if (!strcmp(prop, MSU_INTERFACE_PROP_URLS)) {
1434 str_val = gupnp_didl_lite_resource_get_uri(res);
1436 retval = g_variant_new_strv(&str_val, 1);
1444 GVariant *msu_props_get_object_prop(const gchar *prop, const gchar *root_path,
1445 GUPnPDIDLLiteObject *object)
1449 const char *upnp_class;
1450 const char *media_spec_type;
1453 GVariant *retval = NULL;
1454 GUPnPOCMFlags dlna_managed;
1456 if (!strcmp(prop, MSU_INTERFACE_PROP_PARENT)) {
1457 id = gupnp_didl_lite_object_get_parent_id(object);
1458 if (!id || !strcmp(id, "-1")) {
1459 MSU_LOG_DEBUG("Prop %s = %s", prop, root_path);
1461 retval = g_variant_ref_sink(g_variant_new_string(
1464 path = msu_path_from_id(root_path, id);
1466 MSU_LOG_DEBUG("Prop %s = %s", prop, path);
1468 retval = g_variant_ref_sink(g_variant_new_string(
1472 } else if (!strcmp(prop, MSU_INTERFACE_PROP_PATH)) {
1473 id = gupnp_didl_lite_object_get_id(object);
1477 path = msu_path_from_id(root_path, id);
1479 MSU_LOG_DEBUG("Prop %s = %s", prop, path);
1481 retval = g_variant_ref_sink(g_variant_new_string(path));
1483 } else if (!strcmp(prop, MSU_INTERFACE_PROP_TYPE)) {
1484 upnp_class = gupnp_didl_lite_object_get_upnp_class(object);
1486 msu_props_upnp_class_to_media_spec(upnp_class);
1487 if (!media_spec_type)
1490 MSU_LOG_DEBUG("Prop %s = %s", prop, media_spec_type);
1492 retval = g_variant_ref_sink(g_variant_new_string(
1494 } else if (!strcmp(prop, MSU_INTERFACE_PROP_DISPLAY_NAME)) {
1495 title = gupnp_didl_lite_object_get_title(object);
1499 MSU_LOG_DEBUG("Prop %s = %s", prop, title);
1501 retval = g_variant_ref_sink(g_variant_new_string(title));
1502 } else if (!strcmp(prop, MSU_INTERFACE_PROP_CREATOR)) {
1503 title = gupnp_didl_lite_object_get_creator(object);
1507 MSU_LOG_DEBUG("Prop %s = %s", prop, title);
1509 retval = g_variant_ref_sink(g_variant_new_string(title));
1510 } else if (!strcmp(prop, MSU_INTERFACE_PROP_RESTRICTED)) {
1511 rest = gupnp_didl_lite_object_get_restricted(object);
1513 MSU_LOG_DEBUG("Prop %s = %d", prop, rest);
1515 retval = g_variant_ref_sink(g_variant_new_boolean(rest));
1516 } else if (!strcmp(prop, MSU_INTERFACE_PROP_DLNA_MANAGED)) {
1517 dlna_managed = gupnp_didl_lite_object_get_dlna_managed(object);
1519 MSU_LOG_DEBUG("Prop %s = %0x", prop, dlna_managed);
1521 retval = g_variant_ref_sink(
1522 prv_props_get_dlna_managed_dict(dlna_managed));
1530 GVariant *msu_props_get_item_prop(const gchar *prop, const gchar *root_path,
1531 GUPnPDIDLLiteObject *object,
1532 const gchar *protocol_info)
1537 GUPnPDIDLLiteResource *res;
1538 GVariant *retval = NULL;
1541 if (GUPNP_IS_DIDL_LITE_CONTAINER(object))
1544 if (!strcmp(prop, MSU_INTERFACE_PROP_ARTIST)) {
1545 str = gupnp_didl_lite_object_get_artist(object);
1549 MSU_LOG_DEBUG("Prop %s = %s", prop, str);
1551 retval = g_variant_ref_sink(g_variant_new_string(str));
1552 } else if (!strcmp(prop, MSU_INTERFACE_PROP_ARTISTS)) {
1553 list = gupnp_didl_lite_object_get_artists(object);
1557 retval = g_variant_ref_sink(prv_get_artists_prop(list));
1558 g_list_free_full(list, g_object_unref);
1560 #if MSU_LOG_LEVEL & MSU_LOG_LEVEL_DEBUG
1561 path = g_variant_print(retval, FALSE);
1562 MSU_LOG_DEBUG("Prop %s = %s", prop, path);
1565 } else if (!strcmp(prop, MSU_INTERFACE_PROP_ALBUM)) {
1566 str = gupnp_didl_lite_object_get_album(object);
1570 MSU_LOG_DEBUG("Prop %s = %s", prop, str);
1572 retval = g_variant_ref_sink(g_variant_new_string(str));
1573 } else if (!strcmp(prop, MSU_INTERFACE_PROP_DATE)) {
1574 str = gupnp_didl_lite_object_get_date(object);
1578 MSU_LOG_DEBUG("Prop %s = %s", prop, str);
1580 retval = g_variant_ref_sink(g_variant_new_string(str));
1581 } else if (!strcmp(prop, MSU_INTERFACE_PROP_GENRE)) {
1582 str = gupnp_didl_lite_object_get_genre(object);
1586 MSU_LOG_DEBUG("Prop %s = %s", prop, str);
1588 retval = g_variant_ref_sink(g_variant_new_string(str));
1589 } else if (!strcmp(prop, MSU_INTERFACE_PROP_TRACK_NUMBER)) {
1590 track_number = gupnp_didl_lite_object_get_track_number(object);
1591 if (track_number < 0)
1594 MSU_LOG_DEBUG("Prop %s = %d", prop, track_number);
1596 retval = g_variant_ref_sink(
1597 g_variant_new_int32(track_number));
1598 } else if (!strcmp(prop, MSU_INTERFACE_PROP_ALBUM_ART_URL)) {
1599 str = gupnp_didl_lite_object_get_album_art(object);
1603 MSU_LOG_DEBUG("Prop %s = %s", prop, str);
1605 retval = g_variant_ref_sink(g_variant_new_string(str));
1606 } else if (!strcmp(prop, MSU_INTERFACE_PROP_REFPATH)) {
1607 str = gupnp_didl_lite_item_get_ref_id(
1608 GUPNP_DIDL_LITE_ITEM(object));
1612 MSU_LOG_DEBUG("Prop %s = %s", prop, str);
1614 path = msu_path_from_id(root_path, str);
1615 retval = g_variant_ref_sink(g_variant_new_string(path));
1617 } else if (!strcmp(prop, MSU_INTERFACE_PROP_RESOURCES)) {
1618 retval = g_variant_ref_sink(
1619 prv_compute_resources(object, 0xffffffff));
1621 res = prv_get_matching_resource(object, protocol_info);
1625 retval = prv_get_resource_property(prop, res);
1627 g_object_unref(res);
1635 GVariant *msu_props_get_container_prop(const gchar *prop,
1636 GUPnPDIDLLiteObject *object)
1639 gboolean searchable;
1640 GUPnPDIDLLiteContainer *container;
1641 GVariant *retval = NULL;
1642 #if MSU_LOG_LEVEL & MSU_LOG_LEVEL_DEBUG
1643 gchar *create_classes;
1645 if (!GUPNP_IS_DIDL_LITE_CONTAINER(object))
1648 container = (GUPnPDIDLLiteContainer *) object;
1649 if (!strcmp(prop, MSU_INTERFACE_PROP_CHILD_COUNT)) {
1651 gupnp_didl_lite_container_get_child_count(container);
1653 MSU_LOG_DEBUG("Prop %s = %d", prop, child_count);
1655 if (child_count >= 0) {
1656 retval = g_variant_new_uint32((guint) child_count);
1657 retval = g_variant_ref_sink(retval);
1659 } else if (!strcmp(prop, MSU_INTERFACE_PROP_SEARCHABLE)) {
1661 gupnp_didl_lite_container_get_searchable(container);
1663 MSU_LOG_DEBUG("Prop %s = %d", prop, searchable);
1665 retval = g_variant_ref_sink(
1666 g_variant_new_boolean(searchable));
1667 } else if (!strcmp(prop, MSU_INTERFACE_PROP_CREATE_CLASSES)) {
1668 retval = g_variant_ref_sink(
1669 prv_compute_create_classes(container));
1670 #if MSU_LOG_LEVEL & MSU_LOG_LEVEL_DEBUG
1671 create_classes = g_variant_print(retval, FALSE);
1672 MSU_LOG_DEBUG("Prop %s = %s", prop, create_classes);
1673 g_free(create_classes);