diff options
author | Mark Ryan <mark.d.ryan@intel.com> | 2013-06-17 14:05:14 +0200 |
---|---|---|
committer | Ludovic Ferrandis <ludovic.ferrandis@intel.com> | 2013-06-24 11:11:22 +0200 |
commit | 2beeb7b4ba8b91a255de6213d980ef71824446f6 (patch) | |
tree | 609e6a8330b29933a684068ac1cb89b750d2c67d /libdleyna | |
parent | 961414d2e3e5545e6469427e46ace381748d22fe (diff) | |
download | dleyna-server-2beeb7b4ba8b91a255de6213d980ef71824446f6.tar.gz |
Added the new TypeEx property and fixed Type
The Type property is now almost consistent with the MediaServer2Spec Type
property. This should remove a source of constant confusion and
fix a number of bugs, in for example the download sync controller.
dLeyna-server's implementation of Type differs only from MediaServer2Spec
in one way. dLeyna-server has introduced one new value, item.unclassified,
which is used when the object in question is an item but not one of the
items supported by MediaServer2Spec, i.e., not an audio, video or image
item.
A new property, TypeEx has been introduced. TypeEx contains the
extended type information for an object, i.e., the value Type used
to hold (althought the values have changed), so if applications want
the extended type they can still retrieve it.
Both Type and TypeEx are searchable. The superset of values specified
by TypeEx are permitted when creating a container, both in the type
of the container and it its create classes.
The extended type is exposed in the CreateClasses of a container and in
the LastChange event.
Type is no longer permitted in Update. TypeEx must be used.
From an API point of view there are two breakagaes:
1. Applications that used Type to retrieve extended type information,
need to be updated to use TypeEx. Applications that used Type
in their search queries might also need to be updated.
2. Applications that updated the Type of an object will need to be
updated to use TypeEx instead.
There is one slightly unpleasent hack required to report the correct
values for Search and Sort Caps. A correct solution would require
making the p_map hash table many to many, which would result in a bigger
change. I've left this improvement for another commit.
Signed-off-by: Mark Ryan <mark.d.ryan@intel.com>
Diffstat (limited to 'libdleyna')
-rw-r--r-- | libdleyna/server/device.c | 36 | ||||
-rw-r--r-- | libdleyna/server/interface.h | 1 | ||||
-rw-r--r-- | libdleyna/server/props.c | 270 | ||||
-rw-r--r-- | libdleyna/server/props.h | 5 | ||||
-rw-r--r-- | libdleyna/server/search.c | 13 | ||||
-rw-r--r-- | libdleyna/server/server.c | 2 |
6 files changed, 181 insertions, 146 deletions
diff --git a/libdleyna/server/device.c b/libdleyna/server/device.c index 1c3b6a4..36588b5 100644 --- a/libdleyna/server/device.c +++ b/libdleyna/server/device.c @@ -295,7 +295,7 @@ static void prv_last_change_decode(GUPnPCDSLastChangeEntry *entry, if (!mclass) goto on_error; - media_class = dls_props_upnp_class_to_media_spec(mclass); + media_class = dls_props_upnp_class_to_media_spec_ex(mclass); if (!media_class) goto on_error; @@ -769,9 +769,19 @@ static void prv_get_capabilities_analyze(GHashTable *property_map, while (caps && *caps) { prop_name = g_hash_table_lookup(property_map, *caps); - if (prop_name) + if (prop_name) { g_variant_builder_add(&caps_vb, "s", prop_name); + /* TODO: Okay this is not very nice. A better + way to fix this would be to change the p_map + to be many : many. */ + + if (!strcmp(*caps, "upnp:class")) + g_variant_builder_add( + &caps_vb, "s", + DLS_INTERFACE_PROP_TYPE_EX); + } + caps++; } @@ -2858,11 +2868,11 @@ static gchar *prv_create_new_container_didl(const gchar *parent_id, GUPnPDIDLLiteContainer *container; GVariantIter iter; GVariant *child_type; - const gchar *actual_type; + gchar *actual_type; GUPnPOCMFlags flags; gchar *retval = NULL; - actual_type = dls_props_media_spec_to_upnp_class( + actual_type = dls_props_media_spec_ex_to_upnp_class( task->ut.create_container.type); if (!actual_type) goto on_error; @@ -2878,6 +2888,7 @@ static gchar *prv_create_new_container_didl(const gchar *parent_id, task->ut.create_container.display_name); gupnp_didl_lite_object_set_parent_id(item, parent_id); gupnp_didl_lite_object_set_upnp_class(item, actual_type); + g_free(actual_type); gupnp_didl_lite_object_set_restricted(item, FALSE); flags = GUPNP_OCM_FLAGS_UPLOAD | @@ -2890,11 +2901,13 @@ static gchar *prv_create_new_container_didl(const gchar *parent_id, g_variant_iter_init(&iter, task->ut.create_container.child_types); while ((child_type = g_variant_iter_next_value(&iter))) { - actual_type = dls_props_media_spec_to_upnp_class( + actual_type = dls_props_media_spec_ex_to_upnp_class( g_variant_get_string(child_type, NULL)); - if (actual_type != NULL) + if (actual_type != NULL) { gupnp_didl_lite_container_add_create_class(container, actual_type); + g_free(actual_type); + } g_variant_unref(child_type); } @@ -3785,7 +3798,7 @@ static gchar *prv_get_current_xml_fragment(GUPnPDIDLLiteObject *object, retval = gupnp_didl_lite_object_get_album_xml_string(object); else if (mask & DLS_UPNP_MASK_PROP_DATE) retval = gupnp_didl_lite_object_get_date_xml_string(object); - else if (mask & DLS_UPNP_MASK_PROP_TYPE) + else if (mask & DLS_UPNP_MASK_PROP_TYPE_EX) retval = gupnp_didl_lite_object_get_upnp_class_xml_string( object); else if (mask & DLS_UPNP_MASK_PROP_TRACK_NUMBER) @@ -3803,7 +3816,7 @@ static gchar *prv_get_new_xml_fragment(GUPnPDIDLLiteObject *object, { GUPnPDIDLLiteContributor *artist; const gchar *artist_name; - const gchar *upnp_class; + gchar *upnp_class; GVariantIter viter; gchar *retval = NULL; @@ -3825,13 +3838,14 @@ static gchar *prv_get_new_xml_fragment(GUPnPDIDLLiteObject *object, g_variant_get_string(value, NULL)); retval = gupnp_didl_lite_object_get_date_xml_string(object); - } else if (mask & DLS_UPNP_MASK_PROP_TYPE) { - upnp_class = dls_props_media_spec_to_upnp_class( - g_variant_get_string(value, NULL)); + } else if (mask & DLS_UPNP_MASK_PROP_TYPE_EX) { + upnp_class = dls_props_media_spec_ex_to_upnp_class( + g_variant_get_string(value, NULL)); if (!upnp_class) goto on_error; gupnp_didl_lite_object_set_upnp_class(object, upnp_class); + g_free(upnp_class); retval = gupnp_didl_lite_object_get_upnp_class_xml_string( object); diff --git a/libdleyna/server/interface.h b/libdleyna/server/interface.h index 14a214b..be3b125 100644 --- a/libdleyna/server/interface.h +++ b/libdleyna/server/interface.h @@ -43,6 +43,7 @@ enum dls_interface_type_ { #define DLS_INTERFACE_PROP_RESTRICTED "Restricted" #define DLS_INTERFACE_PROP_DISPLAY_NAME "DisplayName" #define DLS_INTERFACE_PROP_TYPE "Type" +#define DLS_INTERFACE_PROP_TYPE_EX "TypeEx" #define DLS_INTERFACE_PROP_CREATOR "Creator" #define DLS_INTERFACE_PROP_DLNA_MANAGED "DLNAManaged" #define DLS_INTERFACE_PROP_OBJECT_UPDATE_ID "ObjectUpdateID" diff --git a/libdleyna/server/props.c b/libdleyna/server/props.c index ad36174..cd6c30a 100644 --- a/libdleyna/server/props.c +++ b/libdleyna/server/props.c @@ -32,80 +32,46 @@ #include "path.h" #include "props.h" +static const gchar gUPnPObject[] = "object"; static const gchar gUPnPContainer[] = "object.container"; -static const gchar gUPnPAlbum[] = "object.container.album"; -static const gchar gUPnPPerson[] = "object.container.person"; -static const gchar gUPnPGenre[] = "object.container.genre"; -static const gchar gUPnPPlaylist[] = "object.container.playlistContainer"; -static const gchar gUPnPStorage[] = "object.container.storageFolder"; static const gchar gUPnPAudioItem[] = "object.item.audioItem"; static const gchar gUPnPVideoItem[] = "object.item.videoItem"; static const gchar gUPnPImageItem[] = "object.item.imageItem"; -static const gchar gUPnPPlaylistItem[] = "object.item.playlistItem"; static const gchar gUPnPItem[] = "object.item"; +static const unsigned int gUPnPObjectLen = + (sizeof(gUPnPObject) / sizeof(gchar)) - 1; static const unsigned int gUPnPContainerLen = (sizeof(gUPnPContainer) / sizeof(gchar)) - 1; -static const unsigned int gUPnPAlbumLen = - (sizeof(gUPnPAlbum) / sizeof(gchar)) - 1; -static const unsigned int gUPnPPersonLen = - (sizeof(gUPnPPerson) / sizeof(gchar)) - 1; -static const unsigned int gUPnPGenreLen = - (sizeof(gUPnPGenre) / sizeof(gchar)) - 1; -static const unsigned int gUPnPPlaylistLen = - (sizeof(gUPnPPlaylist) / sizeof(gchar)) - 1; -static const unsigned int gUPnPStorageLen = - (sizeof(gUPnPStorage) / sizeof(gchar)) - 1; static const unsigned int gUPnPAudioItemLen = (sizeof(gUPnPAudioItem) / sizeof(gchar)) - 1; static const unsigned int gUPnPVideoItemLen = (sizeof(gUPnPVideoItem) / sizeof(gchar)) - 1; static const unsigned int gUPnPImageItemLen = (sizeof(gUPnPImageItem) / sizeof(gchar)) - 1; -static const unsigned int gUPnPPlaylistItemLen = - (sizeof(gUPnPPlaylistItem) / sizeof(gchar)) - 1; static const unsigned int gUPnPItemLen = (sizeof(gUPnPItem) / sizeof(gchar)) - 1; -static const gchar gUPnPPhotoAlbum[] = "object.container.album.photoAlbum"; -static const gchar gUPnPMusicAlbum[] = "object.container.album.musicAlbum"; -static const gchar gUPnPMusicArtist[] = "object.container.person.musicArtist"; -static const gchar gUPnPMovieGenre[] = "object.container.genre.movieGenre"; -static const gchar gUPnPMusicGenre[] = "object.container.genre.musicGenre"; static const gchar gUPnPMusicTrack[] = "object.item.audioItem.musicTrack"; -static const gchar gUPnPAudioBroadcast[] = - "object.item.audioItem.audioBroadcast"; -static const gchar gUPnPAudioBook[] = "object.item.audioItem.audioBook"; static const gchar gUPnPMovie[] = "object.item.videoItem.movie"; -static const gchar gUPnPMusicVideoClip[] = - "object.item.videoItem.musicVideoClip"; -static const gchar gUPnPVideoBroadcast[] = - "object.item.videoItem.videoBroadcast"; static const gchar gUPnPPhoto[] = "object.item.imageItem.photo"; static const gchar gMediaSpec2Container[] = "container"; -static const gchar gMediaSpec2Album[] = "album"; -static const gchar gMediaSpec2AlbumPhoto[] = "album.photo"; -static const gchar gMediaSpec2AlbumMusic[] = "album.music"; -static const gchar gMediaSpec2Person[] = "person"; -static const gchar gMediaSpec2PersonMusicArtist[] = "person.musicartist"; -static const gchar gMediaSpec2Genre[] = "genre"; -static const gchar gMediaSpec2GenreMovie[] = "genre.movie"; -static const gchar gMediaSpec2GenreMusic[] = "genre.music"; -static const gchar gMediaSpec2AudioMusic[] = "audio.music"; -static const gchar gMediaSpec2AudioBroadcast[] = "audio.broadcast"; +static const gchar gMediaSpec2AudioMusic[] = "music"; static const gchar gMediaSpec2Audio[] = "audio"; -static const gchar gMediaSpec2AudioBook[] = "audio.book"; static const gchar gMediaSpec2Video[] = "video"; static const gchar gMediaSpec2VideoMovie[] = "video.movie"; -static const gchar gMediaSpec2VideoMusicClip[] = "video.musicclip"; -static const gchar gMediaSpec2VideoBroadcast[] = "video.broadcast"; static const gchar gMediaSpec2Image[] = "image"; static const gchar gMediaSpec2ImagePhoto[] = "image.photo"; -static const gchar gMediaSpec2Playlist[] = "playlist"; -static const gchar gMediaSpec2PlaylistItem[] = "item.playlist"; -static const gchar gMediaSpec2Item[] = "item"; -static const gchar gMediaSpec2Storage[] = "storage"; +static const gchar gMediaSpec2ItemUnclassified[] = "item.unclassified"; + +static const gchar gMediaSpec2ExItem[] = "item"; + +static const unsigned int gMediaSpec2ExItemLen = + (sizeof(gMediaSpec2ExItem) / sizeof(gchar)) - 1; + +static const unsigned int gMediaSpec2ContainerLen = + (sizeof(gMediaSpec2Container) / sizeof(gchar)) - 1; typedef struct dls_prop_dlna_t_ dls_prop_dlna_t; struct dls_prop_dlna_t_ { @@ -396,10 +362,15 @@ void dls_prop_maps_new(GHashTable **property_map, GHashTable **filter_map) /* upnp:class */ prop_t = prv_prop_map_new("upnp:class", DLS_UPNP_MASK_PROP_TYPE, - FALSE, TRUE, TRUE); + FALSE, TRUE, FALSE); g_hash_table_insert(f_map, DLS_INTERFACE_PROP_TYPE, prop_t); g_hash_table_insert(p_map, "upnp:class", DLS_INTERFACE_PROP_TYPE); + prop_t = prv_prop_map_new("upnp:class", + DLS_UPNP_MASK_PROP_TYPE_EX, + FALSE, TRUE, TRUE); + g_hash_table_insert(f_map, DLS_INTERFACE_PROP_TYPE_EX, prop_t); + /* upnp:containerUpdateID */ prop_t = prv_prop_map_new("upnp:containerUpdateID", DLS_UPNP_MASK_PROP_CONTAINER_UPDATE_ID, @@ -1147,7 +1118,7 @@ static GVariant *prv_compute_create_classes(GUPnPDIDLLiteContainer *container) create_class = ptr->data; content = gupnp_didl_lite_create_class_get_content( create_class); - ms2_class = dls_props_upnp_class_to_media_spec(content); + ms2_class = dls_props_upnp_class_to_media_spec_ex(content); inc_derived = gupnp_didl_lite_create_class_get_include_derived( create_class); g_variant_builder_add(&create_classes_vb, @@ -1160,66 +1131,75 @@ static GVariant *prv_compute_create_classes(GUPnPDIDLLiteContainer *container) return g_variant_builder_end(&create_classes_vb); } -const gchar *dls_props_media_spec_to_upnp_class(const gchar *m2spec_class) +static const gchar *prv_media_spec_to_upnp_class(const gchar *m2spec_class) { const gchar *retval = NULL; - if (!m2spec_class) - goto on_error; - - if (!strcmp(m2spec_class, gMediaSpec2AlbumPhoto)) - retval = gUPnPPhotoAlbum; - else if (!strcmp(m2spec_class, gMediaSpec2AlbumMusic)) - retval = gUPnPMusicAlbum; - else if (!strcmp(m2spec_class, gMediaSpec2Album)) - retval = gUPnPAlbum; - else if (!strcmp(m2spec_class, gMediaSpec2PersonMusicArtist)) - retval = gUPnPMusicArtist; - else if (!strcmp(m2spec_class, gMediaSpec2Person)) - retval = gUPnPPerson; - else if (!strcmp(m2spec_class, gMediaSpec2GenreMovie)) - retval = gUPnPMovieGenre; - else if (!strcmp(m2spec_class, gMediaSpec2GenreMusic)) - retval = gUPnPMusicGenre; - else if (!strcmp(m2spec_class, gMediaSpec2Genre)) - retval = gUPnPGenre; - else if (!strcmp(m2spec_class, gMediaSpec2Container)) + if (!strcmp(m2spec_class, gMediaSpec2Container)) retval = gUPnPContainer; else if (!strcmp(m2spec_class, gMediaSpec2AudioMusic)) retval = gUPnPMusicTrack; - else if (!strcmp(m2spec_class, gMediaSpec2AudioBroadcast)) - retval = gUPnPAudioBroadcast; - else if (!strcmp(m2spec_class, gMediaSpec2AudioBook)) - retval = gUPnPAudioBook; else if (!strcmp(m2spec_class, gMediaSpec2Audio)) retval = gUPnPAudioItem; else if (!strcmp(m2spec_class, gMediaSpec2VideoMovie)) retval = gUPnPMovie; - else if (!strcmp(m2spec_class, gMediaSpec2VideoMusicClip)) - retval = gUPnPMusicVideoClip; - else if (!strcmp(m2spec_class, gMediaSpec2VideoBroadcast)) - retval = gUPnPVideoBroadcast; else if (!strcmp(m2spec_class, gMediaSpec2Video)) retval = gUPnPVideoItem; else if (!strcmp(m2spec_class, gMediaSpec2ImagePhoto)) retval = gUPnPPhoto; else if (!strcmp(m2spec_class, gMediaSpec2Image)) retval = gUPnPImageItem; - else if (!strcmp(m2spec_class, gMediaSpec2Playlist)) - retval = gUPnPPlaylist; - else if (!strcmp(m2spec_class, gMediaSpec2PlaylistItem)) - retval = gUPnPPlaylistItem; - else if (!strcmp(m2spec_class, gMediaSpec2Item)) + + return retval; +} + +const gchar *dls_props_media_spec_to_upnp_class(const gchar *m2spec_class) +{ + const gchar *retval = NULL; + + if (!m2spec_class) + goto on_error; + + retval = prv_media_spec_to_upnp_class(m2spec_class); + + if (!retval && !strcmp(m2spec_class, gMediaSpec2ItemUnclassified)) retval = gUPnPItem; - else if (!strcmp(m2spec_class, gMediaSpec2Storage)) - retval = gUPnPStorage; on_error: return retval; } -const gchar *dls_props_upnp_class_to_media_spec(const gchar *upnp_class) +gchar *dls_props_media_spec_ex_to_upnp_class(const gchar *m2spec_class) +{ + gchar *retval = NULL; + const gchar *basic_type; + const gchar *ptr = NULL; + + if (!m2spec_class) + goto on_error; + + basic_type = prv_media_spec_to_upnp_class(m2spec_class); + if (basic_type) { + retval = g_strdup(basic_type); + } else { + if (!strncmp(m2spec_class, gMediaSpec2ExItem, + gMediaSpec2ExItemLen)) + ptr = m2spec_class + gMediaSpec2ExItemLen; + else if (!strncmp(m2spec_class, gMediaSpec2Container, + gMediaSpec2ContainerLen)) + ptr = m2spec_class + gMediaSpec2ContainerLen; + if (ptr && (!*ptr || *ptr == '.')) + retval = g_strdup_printf("object.%s", m2spec_class); + } + +on_error: + + return retval; +} + +static const gchar *prv_upnp_class_to_media_spec(const gchar *upnp_class, + gboolean *exact) { const gchar *retval = NULL; const gchar *ptr; @@ -1227,71 +1207,73 @@ const gchar *dls_props_upnp_class_to_media_spec(const gchar *upnp_class) if (!upnp_class) goto on_error; - if (!strncmp(upnp_class, gUPnPAlbum, gUPnPAlbumLen)) { - ptr = upnp_class + gUPnPAlbumLen; - if (!strcmp(ptr, ".photoAlbum")) - retval = gMediaSpec2AlbumPhoto; - else if (!strcmp(ptr, ".musicAlbum")) - retval = gMediaSpec2AlbumMusic; - else - retval = gMediaSpec2Album; - } else if (!strncmp(upnp_class, gUPnPPerson, gUPnPPersonLen)) { - ptr = upnp_class + gUPnPPersonLen; - if (!strcmp(ptr, ".musicArtist")) - retval = gMediaSpec2PersonMusicArtist; - else - retval = gMediaSpec2Person; - } else if (!strncmp(upnp_class, gUPnPGenre, gUPnPGenreLen)) { - ptr = upnp_class + gUPnPGenreLen; - if (!strcmp(ptr, ".movieGenre")) - retval = gMediaSpec2GenreMovie; - else if (!strcmp(ptr, ".musicGenre")) - retval = gMediaSpec2GenreMusic; - else - retval = gMediaSpec2Genre; - } else if (!strncmp(upnp_class, gUPnPContainer, gUPnPContainerLen)) { + if (!strncmp(upnp_class, gUPnPContainer, gUPnPContainerLen)) { ptr = upnp_class + gUPnPContainerLen; - if (!*ptr || *ptr == '.') + if (!*ptr || *ptr == '.') { retval = gMediaSpec2Container; + *exact = *ptr == 0; + } } else if (!strncmp(upnp_class, gUPnPAudioItem, gUPnPAudioItemLen)) { ptr = upnp_class + gUPnPAudioItemLen; - if (!strcmp(ptr, ".musicTrack")) + if (!strcmp(ptr, ".musicTrack")) { retval = gMediaSpec2AudioMusic; - else if (!strcmp(ptr, ".audioBroadcast")) - retval = gMediaSpec2AudioBroadcast; - else if (!strcmp(ptr, ".audioBook")) - retval = gMediaSpec2AudioBook; - else + *exact = TRUE; + } else if (!*ptr || *ptr == '.') { retval = gMediaSpec2Audio; + *exact = *ptr == 0; + } } else if (!strncmp(upnp_class, gUPnPVideoItem, gUPnPVideoItemLen)) { ptr = upnp_class + gUPnPVideoItemLen; - if (!strcmp(ptr, ".movie")) + if (!strcmp(ptr, ".movie")) { retval = gMediaSpec2VideoMovie; - else if (!strcmp(ptr, ".musicVideoClip")) - retval = gMediaSpec2VideoMusicClip; - else if (!strcmp(ptr, ".videoBroadcast")) - retval = gMediaSpec2VideoBroadcast; - else + *exact = TRUE; + } else if (!*ptr || *ptr == '.') { retval = gMediaSpec2Video; + *exact = *ptr == 0; + } } else if (!strncmp(upnp_class, gUPnPImageItem, gUPnPImageItemLen)) { ptr = upnp_class + gUPnPImageItemLen; - if (!strcmp(ptr, ".photo")) + if (!strcmp(ptr, ".photo")) { retval = gMediaSpec2ImagePhoto; - else + *exact = TRUE; + } else if (!*ptr || *ptr == '.') { retval = gMediaSpec2Image; - } else if (!strncmp(upnp_class, gUPnPPlaylist, - gUPnPPlaylistLen)) { - retval = gMediaSpec2Playlist; - } else if (!strncmp(upnp_class, gUPnPPlaylistItem, - gUPnPPlaylistItemLen)) { - retval = gMediaSpec2PlaylistItem; + *exact = *ptr == 0; + } } else if (!strncmp(upnp_class, gUPnPItem, gUPnPItemLen)) { ptr = upnp_class + gUPnPItemLen; - if (!*ptr || *ptr == '.') - retval = gMediaSpec2Item; - } else if (!strncmp(upnp_class, gUPnPStorage, - gUPnPStorageLen)) { - retval = gMediaSpec2Storage; + if (!*ptr || *ptr == '.') { + retval = gMediaSpec2ItemUnclassified; + *exact = *ptr == 0; + } + } + +on_error: + + return retval; +} + +const gchar *dls_props_upnp_class_to_media_spec(const gchar *upnp_class) +{ + gboolean exact; + + return prv_upnp_class_to_media_spec(upnp_class, &exact); +} + +const gchar *dls_props_upnp_class_to_media_spec_ex(const gchar *upnp_class) +{ + const gchar *retval; + gboolean exact; + + retval = prv_upnp_class_to_media_spec(upnp_class, &exact); + if (!retval) + goto on_error; + + if (exact) { + if (retval == gMediaSpec2ItemUnclassified) + retval = gMediaSpec2ExItem; + } else { + retval = upnp_class + gUPnPObjectLen + 1; } on_error: @@ -1368,6 +1350,7 @@ gboolean dls_props_add_object(GVariantBuilder *item_vb, const char *creator; const char *upnp_class; const char *media_spec_type; + const char *media_spec_type_ex; gboolean retval = FALSE; gboolean rest; GUPnPOCMFlags flags; @@ -1383,6 +1366,8 @@ gboolean dls_props_add_object(GVariantBuilder *item_vb, if (!media_spec_type) goto on_error; + media_spec_type_ex = dls_props_upnp_class_to_media_spec_ex(upnp_class); + title = gupnp_didl_lite_object_get_title(object); creator = gupnp_didl_lite_object_get_creator(object); rest = gupnp_didl_lite_object_get_restricted(object); @@ -1407,6 +1392,10 @@ gboolean dls_props_add_object(GVariantBuilder *item_vb, prv_add_string_prop(item_vb, DLS_INTERFACE_PROP_TYPE, media_spec_type); + if (filter_mask & DLS_UPNP_MASK_PROP_TYPE_EX) + prv_add_string_prop(item_vb, DLS_INTERFACE_PROP_TYPE_EX, + media_spec_type_ex); + if (filter_mask & DLS_UPNP_MASK_PROP_RESTRICTED) prv_add_bool_prop(item_vb, DLS_INTERFACE_PROP_RESTRICTED, rest); @@ -1785,6 +1774,17 @@ GVariant *dls_props_get_object_prop(const gchar *prop, const gchar *root_path, retval = g_variant_ref_sink(g_variant_new_string( media_spec_type)); + } else if (!strcmp(prop, DLS_INTERFACE_PROP_TYPE_EX)) { + upnp_class = gupnp_didl_lite_object_get_upnp_class(object); + media_spec_type = + dls_props_upnp_class_to_media_spec_ex(upnp_class); + if (!media_spec_type) + goto on_error; + + DLEYNA_LOG_DEBUG("Prop %s = %s", prop, media_spec_type); + + retval = g_variant_ref_sink(g_variant_new_string( + media_spec_type)); } else if (!strcmp(prop, DLS_INTERFACE_PROP_DISPLAY_NAME)) { title = gupnp_didl_lite_object_get_title(object); if (!title) diff --git a/libdleyna/server/props.h b/libdleyna/server/props.h index f219573..c4628f5 100644 --- a/libdleyna/server/props.h +++ b/libdleyna/server/props.h @@ -64,6 +64,7 @@ #define DLS_UPNP_MASK_PROP_DLNA_CONVERSION (1LL << 35) #define DLS_UPNP_MASK_PROP_DLNA_OPERATION (1LL << 36) #define DLS_UPNP_MASK_PROP_DLNA_FLAGS (1LL << 37) +#define DLS_UPNP_MASK_PROP_TYPE_EX (1LL << 38) #define DLS_UPNP_MASK_ALL_PROPS 0xffffffffffffffff @@ -134,6 +135,10 @@ GVariant *dls_props_get_item_prop(const gchar *prop, const gchar *root_path, const gchar *dls_props_media_spec_to_upnp_class(const gchar *m2spec_class); +gchar *dls_props_media_spec_ex_to_upnp_class(const gchar *m2spec_class); + const gchar *dls_props_upnp_class_to_media_spec(const gchar *upnp_class); +const gchar *dls_props_upnp_class_to_media_spec_ex(const gchar *upnp_class); + #endif /* DLS_PROPS_H__ */ diff --git a/libdleyna/server/search.c b/libdleyna/server/search.c index 264654e..c331ceb 100644 --- a/libdleyna/server/search.c +++ b/libdleyna/server/search.c @@ -37,6 +37,7 @@ gchar *dls_search_translate_search_string(GHashTable *filter_map, gchar *op = NULL; gchar *value = NULL; const gchar *translated_value; + gchar *translated_type_ex; dls_prop_map_t *prop_map; GString *str; gint start_pos; @@ -80,6 +81,18 @@ gchar *dls_search_translate_search_string(GHashTable *filter_map, goto on_error; g_free(value); value = g_strdup_printf("\"%s\"", translated_value); + } else if (!strcmp(prop, DLS_INTERFACE_PROP_TYPE_EX)) { + /* Skip the quotes */ + + value[strlen(value) - 1] = 0; + translated_type_ex = + dls_props_media_spec_ex_to_upnp_class( + value + 1); + if (!translated_type_ex) + goto on_error; + g_free(value); + value = g_strdup_printf("\"%s\"", translated_type_ex); + g_free(translated_type_ex); } else if (!strcmp(prop, DLS_INTERFACE_PROP_PARENT) || !strcmp(prop, DLS_INTERFACE_PROP_PATH)) { value[strlen(value) - 1] = 0; diff --git a/libdleyna/server/server.c b/libdleyna/server/server.c index 4db03e4..caa4701 100644 --- a/libdleyna/server/server.c +++ b/libdleyna/server/server.c @@ -120,6 +120,8 @@ static const gchar g_server_introspection[] = " access='read'/>" " <property type='s' name='"DLS_INTERFACE_PROP_TYPE"'" " access='read'/>" + " <property type='s' name='"DLS_INTERFACE_PROP_TYPE_EX"'" + " access='read'/>" " <property type='o' name='"DLS_INTERFACE_PROP_PATH"'" " access='read'/>" " <property type='s' name='"DLS_INTERFACE_PROP_DISPLAY_NAME"'" |