diff options
author | Luiz Augusto von Dentz <luiz.von.dentz@intel.com> | 2013-02-15 16:02:50 +0200 |
---|---|---|
committer | Johan Hedberg <johan.hedberg@intel.com> | 2013-02-15 16:35:26 +0200 |
commit | 89f1f6a6299c93b4364b4f6f6ab4e0f035c1c6cc (patch) | |
tree | bbb8638a4cea2f40ed1a391df776916a3d21b65a /profiles/audio/player.c | |
parent | 0eb8474255a5c4e953f573d8a4a9aa651e947906 (diff) | |
download | bluez-89f1f6a6299c93b4364b4f6f6ab4e0f035c1c6cc.tar.gz |
AVRCP: Create folders for /Filesystem and /NowPlaying
If browsing is supported create objects representing /Filesystem and
/NowPlaying, these object implement MediaItem interface and can be
passed to ChangeFolder to change the scope.
Diffstat (limited to 'profiles/audio/player.c')
-rw-r--r-- | profiles/audio/player.c | 233 |
1 files changed, 208 insertions, 25 deletions
diff --git a/profiles/audio/player.c b/profiles/audio/player.c index 07fd45730..466b44a26 100644 --- a/profiles/audio/player.c +++ b/profiles/audio/player.c @@ -45,6 +45,7 @@ #define MEDIA_PLAYER_INTERFACE "org.bluez.MediaPlayer1" #define MEDIA_FOLDER_INTERFACE "org.bluez.MediaFolder1" +#define MEDIA_ITEM_INTERFACE "org.bluez.MediaItem1" struct player_callback { const struct media_player_callback *cbs; @@ -57,9 +58,17 @@ struct pending_req { const char *value; }; +struct media_item { + struct media_player *player; + char *path; /* Item object path */ + char *name; /* Item name */ + bool folder; /* Item folder flag */ + bool playable; /* Item playable flag */ +}; + struct media_folder { - char *name; /* Folder name */ - uint32_t items; /* Number of items */ + struct media_item *item; /* Folder item */ + uint32_t number_of_items;/* Number of items */ }; struct media_player { @@ -79,6 +88,7 @@ struct media_player { guint process_id; struct player_callback *cb; GSList *pending; + GSList *folders; }; static void append_metadata(void *key, void *value, void *user_data) @@ -592,25 +602,27 @@ static gboolean folder_name_exists(const GDBusPropertyTable *property, void *data) { struct media_player *mp = data; + struct media_folder *folder = mp->folder; - if (mp->folder == NULL) + if (folder == NULL || folder->item == NULL) return FALSE; - return mp->folder->name != NULL; + return folder->item->name != NULL; } static gboolean get_folder_name(const GDBusPropertyTable *property, DBusMessageIter *iter, void *data) { struct media_player *mp = data; + struct media_folder *folder = mp->folder; - if (mp->folder == NULL || mp->folder->name == NULL) + if (folder == NULL || folder->item == NULL) return FALSE; - DBG("%s", mp->folder->name); + DBG("%s", folder->item->name); dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, - &mp->folder->name); + &folder->item->name); return TRUE; } @@ -626,14 +638,15 @@ static gboolean get_items(const GDBusPropertyTable *property, DBusMessageIter *iter, void *data) { struct media_player *mp = data; + struct media_folder *folder = mp->folder; - if (mp->folder == NULL) + if (folder == NULL) return FALSE; - DBG("%u", mp->folder->items); + DBG("%u", folder->number_of_items); dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32, - &mp->folder->items); + &folder->number_of_items); return TRUE; } @@ -661,9 +674,22 @@ static const GDBusPropertyTable media_folder_properties[] = { { } }; +static void media_item_destroy(void *data) +{ + struct media_item *item = data; + + DBG("%s", item->path); + + g_dbus_unregister_interface(btd_get_dbus_connection(), item->path, + MEDIA_ITEM_INTERFACE); + + g_free(item->path); + g_free(item->name); + g_free(item); +} + static void media_folder_destroy(struct media_folder *folder) { - g_free(folder->name); g_free(folder); } @@ -691,6 +717,7 @@ void media_player_destroy(struct media_player *mp) } g_slist_free_full(mp->pending, g_free); + g_slist_free_full(mp->folders, media_item_destroy); g_timer_destroy(mp->progress); g_free(mp->cb); @@ -913,31 +940,187 @@ void media_player_set_searchable(struct media_player *mp, bool enabled) mp->searchable = enabled; } -void media_player_set_folder(struct media_player *mp, const char *path, - uint32_t items) +static void media_player_set_folder_item(struct media_player *mp, + struct media_item *item, + uint32_t number_of_items) { struct media_folder *folder; - DBG("%s items %u", path, items); + folder = mp->folder; - if (mp->folder != NULL) - media_folder_destroy(mp->folder); + if (folder == NULL) { + folder = g_new0(struct media_folder, 1); + mp->folder = folder; - folder = g_new0(struct media_folder, 1); - folder->name = g_strdup(path); - folder->items = items; - mp->folder = folder; - - if (!g_dbus_register_interface(btd_get_dbus_connection(), + if (!g_dbus_register_interface(btd_get_dbus_connection(), mp->path, MEDIA_FOLDER_INTERFACE, media_folder_methods, NULL, media_folder_properties, mp, NULL)) { - error("D-Bus failed to register %s on %s path", + error("D-Bus failed to register %s on %s path", MEDIA_FOLDER_INTERFACE, mp->path); - media_folder_destroy(mp->folder); - mp->folder = NULL; + media_folder_destroy(mp->folder); + mp->folder = NULL; + return; + } + } + + folder->item = item; + folder->number_of_items = number_of_items; + + g_dbus_emit_property_changed(btd_get_dbus_connection(), mp->path, + MEDIA_FOLDER_INTERFACE, "Name"); + g_dbus_emit_property_changed(btd_get_dbus_connection(), mp->path, + MEDIA_FOLDER_INTERFACE, "NumberOfItems"); +} + +static struct media_item *media_player_find_folder(struct media_player *mp, + const char *name) +{ + GSList *l; + + for (l = mp->folders; l; l = l->next) { + struct media_item *item = l->data; + + if (!item->folder) + continue; + + if (g_str_equal(item->name, name)) + return item; } + + return NULL; +} + +void media_player_set_folder(struct media_player *mp, const char *name, + uint32_t number_of_items) +{ + struct media_item *item; + + DBG("%s number of items %u", name, number_of_items); + + item = media_player_find_folder(mp, name); + if (item == NULL) { + error("Unknown folder: %s", name); + return; + } + + media_player_set_folder_item(mp, item, number_of_items); +} + +static DBusMessage *media_item_play(DBusConnection *conn, DBusMessage *msg, + void *data) +{ + return btd_error_failed(msg, strerror(ENOTSUP)); +} + +static DBusMessage *media_item_add_to_nowplaying(DBusConnection *conn, + DBusMessage *msg, void *data) +{ + return btd_error_failed(msg, strerror(ENOTSUP)); +} + +static gboolean item_name_exists(const GDBusPropertyTable *property, + void *data) +{ + struct media_item *item = data; + + return item->name != NULL; +} + +static gboolean get_item_name(const GDBusPropertyTable *property, + DBusMessageIter *iter, void *data) +{ + struct media_item *item = data; + + if (item->name == NULL) + return FALSE; + + DBG("%s", item->name); + + dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &item->name); + + return TRUE; +} + +static gboolean get_folder_flag(const GDBusPropertyTable *property, + DBusMessageIter *iter, void *data) +{ + struct media_item *item = data; + dbus_bool_t value; + + DBG("%s", item->folder ? "true" : "false"); + + value = item->folder; + + dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &value); + + return TRUE; +} + +static gboolean get_playable(const GDBusPropertyTable *property, + DBusMessageIter *iter, void *data) +{ + struct media_item *item = data; + dbus_bool_t value; + + DBG("%s", item->playable ? "true" : "false"); + + value = item->playable; + + dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &value); + + return TRUE; +} + +static const GDBusMethodTable media_item_methods[] = { + { GDBUS_EXPERIMENTAL_METHOD("Play", NULL, NULL, + media_item_play) }, + { GDBUS_EXPERIMENTAL_METHOD("AddtoNowPlaying", NULL, NULL, + media_item_add_to_nowplaying) }, + { } +}; + +static const GDBusPropertyTable media_item_properties[] = { + { "Name", "s", get_item_name, NULL, item_name_exists, + G_DBUS_PROPERTY_FLAG_EXPERIMENTAL }, + { "Folder", "b", get_folder_flag, NULL, NULL, + G_DBUS_PROPERTY_FLAG_EXPERIMENTAL }, + { "Playable", "b", get_playable, NULL, NULL, + G_DBUS_PROPERTY_FLAG_EXPERIMENTAL }, + { } +}; + +int media_player_create_folder(struct media_player *mp, const char *name) +{ + struct media_item *item; + + DBG("%s", name); + + item = g_new0(struct media_item, 1); + item->player = mp; + item->path = g_strdup_printf("%s%s", mp->path, name); + item->name = g_strdup(name); + item->folder = true; + item->playable = false; + + if (!g_dbus_register_interface(btd_get_dbus_connection(), + item->path, MEDIA_ITEM_INTERFACE, + media_item_methods, + NULL, + media_item_properties, item, NULL)) { + error("D-Bus failed to register %s on %s path", + MEDIA_ITEM_INTERFACE, item->path); + media_item_destroy(item); + return -EINVAL; + } + + if (mp->folder == NULL) + media_player_set_folder_item(mp, item, 0); + + mp->folders = g_slist_prepend(mp->folders, item); + + return 0; } void media_player_set_callbacks(struct media_player *mp, |