All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH  1/3] audio/avrcp: Get player playlist details
@ 2015-10-20 13:16 Bharat Panda
  2015-10-20 13:16 ` [PATCH 2/3] audio/avrcp: Handle PlaylistChanged signal Bharat Panda
                   ` (2 more replies)
  0 siblings, 3 replies; 10+ messages in thread
From: Bharat Panda @ 2015-10-20 13:16 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: cpgs, Bharat Panda

Support added to read and cache player playlist details after
player registration completes.
---
 profiles/audio/media.c | 164 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 164 insertions(+)

diff --git a/profiles/audio/media.c b/profiles/audio/media.c
index 69070bf..1b5246d 100644
--- a/profiles/audio/media.c
+++ b/profiles/audio/media.c
@@ -58,6 +58,7 @@
 #define MEDIA_INTERFACE "org.bluez.Media1"
 #define MEDIA_ENDPOINT_INTERFACE "org.bluez.MediaEndpoint1"
 #define MEDIA_PLAYER_INTERFACE "org.mpris.MediaPlayer2.Player"
+#define MEDIA_PLAYER_PLAYLIST_INTERFACE "org.mpris.MediaPlayer2.Playlists"
 
 #define REQUEST_TIMEOUT (3 * 1000)		/* 3 seconds */
 
@@ -92,9 +93,19 @@ struct media_endpoint {
 	GSList			*transports;
 };
 
+struct player_request {
+	struct media_player	*mp;
+	DBusMessage		*msg;
+	DBusPendingCall		*call;
+	GDestroyNotify		destroy;
+	void			*user_data;
+};
+
 struct media_player {
 	struct media_adapter	*adapter;
 	struct avrcp_player	*player;
+	GSList			*playlists;
+	GSList			*requests;
 	char			*sender;	/* Player DBus bus id */
 	char			*path;		/* Player object path */
 	GHashTable		*settings;	/* Player settings */
@@ -105,6 +116,7 @@ struct media_player {
 	char			*status;
 	uint32_t		position;
 	uint32_t		duration;
+	uint32_t		total_items;
 	uint8_t			volume;
 	GTimer			*timer;
 	bool			play;
@@ -115,6 +127,13 @@ struct media_player {
 	char			*name;
 };
 
+struct media_playlist {
+	char		*name;
+	char		*id;
+	char		*icon;
+	uint8_t		data[0];
+} __attribute__ ((packed));
+
 static GSList *adapters = NULL;
 
 static void endpoint_request_free(struct endpoint_request *request)
@@ -966,6 +985,7 @@ static void media_player_free(gpointer data)
 	g_free(mp->path);
 	g_free(mp->status);
 	g_free(mp->name);
+	g_free(mp->playlists);
 	g_free(mp);
 }
 
@@ -1271,6 +1291,147 @@ static bool previous(void *user_data)
 	return media_player_send(mp, "Previous");
 }
 
+static void playlist_reply(DBusPendingCall *call, void *user_data)
+{
+	struct player_request *request = user_data;
+	struct media_player *mp = request->mp;
+	DBusMessage *reply;
+	DBusMessageIter array_iter, entry, struct_iter;
+	DBusError derr;
+	int ctype;
+
+	reply = dbus_pending_call_steal_reply(call);
+
+	dbus_error_init(&derr);
+
+	if (dbus_set_error_from_message(&derr, reply)) {
+		error("Error: GetPlayLists method %s, %s", derr.name,
+					derr.message);
+		dbus_error_free(&derr);
+		goto done;
+	}
+
+	dbus_message_iter_init(reply, &array_iter);
+	ctype = dbus_message_iter_get_arg_type(&array_iter);
+
+	if (ctype != DBUS_TYPE_ARRAY)
+		goto done;
+
+	dbus_message_iter_recurse(&array_iter, &struct_iter);
+
+	while ((ctype = dbus_message_iter_get_arg_type(&struct_iter)) !=
+				DBUS_TYPE_INVALID) {
+		struct media_playlist *playlist;
+
+		if (ctype != DBUS_TYPE_STRUCT) {
+			error("Invalid type");
+			goto done;
+		}
+
+		playlist = g_new0(struct media_playlist, 1);
+
+		dbus_message_iter_recurse(&struct_iter, &entry);
+
+		dbus_message_iter_get_basic(&entry, &playlist->id);
+		DBG("Playlists Id %s", playlist->id);
+
+		dbus_message_iter_next(&entry);
+		dbus_message_iter_get_basic(&entry, &playlist->name);
+		DBG("Playlist Name %s", playlist->name);
+
+		dbus_message_iter_next(&entry);
+		dbus_message_iter_get_basic(&entry, &playlist->icon);
+		DBG("Playlist Icon %s", playlist->icon);
+
+		/* TODO: Create Media folder with playlist information */
+
+		mp->playlists = g_slist_append(mp->playlists, playlist);
+
+		g_free(playlist);
+
+		mp->total_items++;
+		dbus_message_iter_next(&struct_iter);
+	}
+
+done:
+	dbus_message_unref(reply);
+
+	mp->requests = g_slist_remove(mp->requests, request);
+
+	if (request->call)
+		dbus_pending_call_unref(request->call);
+
+	if (request->destroy)
+		request->destroy(request->user_data);
+
+	dbus_message_unref(request->msg);
+	g_free(request);
+}
+
+static gboolean media_player_async_call(DBusMessage *msg,
+					struct media_player *mp,
+					GDestroyNotify destroy)
+{
+	struct player_request *request;
+	const char *method = NULL;
+
+	request = g_new0(struct player_request, 1);
+
+	if (!(dbus_connection_send_with_reply(btd_get_dbus_connection(),
+					msg, &request->call, -1))) {
+		error("D-Bus send failed");
+		g_free(request);
+		return FALSE;
+	}
+
+	method = dbus_message_get_member(msg);
+
+	if (g_strcmp0(method, "GetPlaylists") == 0)
+		dbus_pending_call_set_notify(request->call,
+						&playlist_reply, request, NULL);
+
+	request->mp = mp;
+	request->msg = msg;
+	request->destroy = destroy;
+
+	mp->requests = g_slist_append(mp->requests, request);
+
+	DBG("Calling %s: name = %s path = %s", dbus_message_get_member(msg),
+			dbus_message_get_destination(msg),
+			dbus_message_get_path(msg));
+
+	return TRUE;
+}
+static gboolean get_playlists(struct media_player *mp)
+{
+	DBusMessage *msg;
+	gboolean reverse_order = FALSE;
+	uint32_t start_index = 0x0000;
+	uint32_t end_index = 0xFFFF;
+	char *ordering = "Alphabetical";
+	uint32_t max_count = (end_index - start_index);
+
+	msg = dbus_message_new_method_call(mp->sender, mp->path,
+				MEDIA_PLAYER_PLAYLIST_INTERFACE,
+				"GetPlaylists");
+
+	if (msg == NULL) {
+		error("Couldn't allocate D-Bus message");
+		return -ENOMEM;
+	}
+
+	dbus_message_append_args(msg,
+			DBUS_TYPE_UINT32, &start_index,
+			DBUS_TYPE_UINT32, &max_count,
+			DBUS_TYPE_STRING, &ordering,
+			DBUS_TYPE_BOOLEAN, &reverse_order,
+			DBUS_TYPE_INVALID);
+
+	mp->total_items = 0;
+
+	return (media_player_async_call(msg, mp, g_free));
+}
+
 static struct avrcp_player_cb player_cb = {
 	.list_settings = list_settings,
 	.get_setting = get_setting,
@@ -1831,6 +1992,9 @@ static DBusMessage *register_player(DBusConnection *conn, DBusMessage *msg,
 		return btd_error_invalid_args(msg);
 	}
 
+	if (!get_playlists(mp))
+		DBG("Error fetching playlists");
+
 	return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
 }
 
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread
* [PATCH  1/3] aurdio/avrcp: Get player playlist details
@ 2015-10-06 11:53 Bharat Panda
  2015-10-06 11:53 ` [PATCH 3/3] audio/avrcp: Add support for SetBrowsedPlayer Bharat Panda
  0 siblings, 1 reply; 10+ messages in thread
From: Bharat Panda @ 2015-10-06 11:53 UTC (permalink / raw)
  To: linux-bluetooth; +Cc: cpgs, Bharat Panda

Support added to read and cache player playlist details after
player registration completes.
---
 profiles/audio/media.c | 121 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 121 insertions(+)

diff --git a/profiles/audio/media.c b/profiles/audio/media.c
index 69070bf..edeb66f 100644
--- a/profiles/audio/media.c
+++ b/profiles/audio/media.c
@@ -58,6 +58,7 @@
 #define MEDIA_INTERFACE "org.bluez.Media1"
 #define MEDIA_ENDPOINT_INTERFACE "org.bluez.MediaEndpoint1"
 #define MEDIA_PLAYER_INTERFACE "org.mpris.MediaPlayer2.Player"
+#define MEDIA_PLAYER_PLAYLIST_INTERFACE "org.mpris.MediaPlayer2.Playlists"
 
 #define REQUEST_TIMEOUT (3 * 1000)		/* 3 seconds */
 
@@ -95,6 +96,7 @@ struct media_endpoint {
 struct media_player {
 	struct media_adapter	*adapter;
 	struct avrcp_player	*player;
+	GSList			*playlists;
 	char			*sender;	/* Player DBus bus id */
 	char			*path;		/* Player object path */
 	GHashTable		*settings;	/* Player settings */
@@ -105,8 +107,10 @@ struct media_player {
 	char			*status;
 	uint32_t		position;
 	uint32_t		duration;
+	uint32_t		total_items;
 	uint8_t			volume;
 	GTimer			*timer;
+	guint			playlist_id;
 	bool			play;
 	bool			pause;
 	bool			next;
@@ -115,6 +119,13 @@ struct media_player {
 	char			*name;
 };
 
+struct media_playlist {
+	char		*name;
+	char		*id;
+	char		*icon;
+	uint8_t		data[0];
+} __attribute__ ((packed));
+
 static GSList *adapters = NULL;
 
 static void endpoint_request_free(struct endpoint_request *request)
@@ -961,6 +972,9 @@ static void media_player_free(gpointer data)
 	if (mp->settings)
 		g_hash_table_unref(mp->settings);
 
+	if (mp->playlist_id > 0)
+		g_source_remove(mp->playlist_id);
+
 	g_timer_destroy(mp->timer);
 	g_free(mp->sender);
 	g_free(mp->path);
@@ -1271,6 +1285,111 @@ static bool previous(void *user_data)
 	return media_player_send(mp, "Previous");
 }
 
+
+static void playlist_reply(DBusPendingCall *call, void *user_data)
+{
+	struct media_player *mp = user_data;
+	DBusMessage *reply;
+	DBusMessageIter array_iter, entry, struct_iter;
+	DBusError derr;
+	int ctype;
+
+	reply = dbus_pending_call_steal_reply(call);
+
+	dbus_error_init(&derr);
+
+	if (dbus_set_error_from_message(&derr, reply)) {
+		error("Error: GetPlayLists method %s, %s", derr.name,
+					derr.message);
+		dbus_error_free(&derr);
+		goto done;
+	}
+
+	dbus_message_iter_init(reply, &array_iter);
+	ctype = dbus_message_iter_get_arg_type(&array_iter);
+
+	if (ctype != DBUS_TYPE_ARRAY)
+		goto done;
+
+	dbus_message_iter_recurse(&array_iter, &struct_iter);
+
+	while ((ctype = dbus_message_iter_get_arg_type(&struct_iter)) !=
+				DBUS_TYPE_INVALID) {
+		struct media_playlist *playlist;
+
+		if (ctype != DBUS_TYPE_STRUCT) {
+			error("Invalid type");
+			goto done;
+		}
+
+		playlist = g_new0(struct media_playlist, 1);
+
+		dbus_message_iter_recurse(&struct_iter, &entry);
+
+		dbus_message_iter_get_basic(&entry, &playlist->id);
+		DBG("Playlists Id %s", playlist->id);
+
+		dbus_message_iter_next(&entry);
+		dbus_message_iter_get_basic(&entry, &playlist->name);
+		DBG("Playlist Name %s", playlist->name);
+
+		dbus_message_iter_next(&entry);
+		dbus_message_iter_get_basic(&entry, &playlist->icon);
+		DBG("Playlist Icon %s", playlist->icon);
+
+		/* TODO: Create Media folder with playlist information */
+
+		mp->playlists = g_slist_append(mp->playlists, playlist);
+		mp->total_items++;
+
+		dbus_message_iter_next(&struct_iter);
+	}
+
+done:
+	dbus_message_unref(reply);
+}
+
+static gboolean get_playlists(gpointer user_data)
+{
+	struct media_player *mp = user_data;
+	DBusMessage *msg;
+	DBusPendingCall *call;
+	gboolean reverse_order = FALSE;
+	uint32_t start_index = 0x0000;
+	uint32_t end_index = 0xFFFF;
+	char *ordering = "Alphabetical";
+	uint32_t max_count = (end_index - start_index);
+
+	msg = dbus_message_new_method_call(mp->sender, mp->path,
+				MEDIA_PLAYER_PLAYLIST_INTERFACE,
+				"GetPlaylists");
+
+	if (msg == NULL) {
+		error("Couldn't allocate D-Bus message");
+		return -ENOMEM;
+	}
+
+	dbus_message_append_args(msg,
+			DBUS_TYPE_UINT32, &start_index,
+			DBUS_TYPE_UINT32, &max_count,
+			DBUS_TYPE_STRING, &ordering,
+			DBUS_TYPE_BOOLEAN, &reverse_order,
+			DBUS_TYPE_INVALID);
+
+	mp->total_items = 0;
+
+	if ((dbus_connection_send_with_reply(btd_get_dbus_connection(),
+					msg, &call, -1))) {
+		dbus_pending_call_set_notify(call, &playlist_reply, mp, NULL);
+		dbus_pending_call_unref(call);
+		dbus_message_unref(msg);
+	}
+
+	mp->playlist_id = 0;
+
+	return FALSE;
+}
+
 static struct avrcp_player_cb player_cb = {
 	.list_settings = list_settings,
 	.get_setting = get_setting,
@@ -1831,6 +1950,8 @@ static DBusMessage *register_player(DBusConnection *conn, DBusMessage *msg,
 		return btd_error_invalid_args(msg);
 	}
 
+	mp->playlist_id = g_idle_add(get_playlists, mp);
+
 	return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
 }
 
-- 
1.9.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2015-12-02 13:41 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-10-20 13:16 [PATCH 1/3] audio/avrcp: Get player playlist details Bharat Panda
2015-10-20 13:16 ` [PATCH 2/3] audio/avrcp: Handle PlaylistChanged signal Bharat Panda
2015-11-27 11:21   ` Bharat Bhusan Panda
2015-12-02 13:31     ` Luiz Augusto von Dentz
2015-10-20 13:16 ` [PATCH 3/3] audio/avrcp: Add support for SetBrowsedPlayer Bharat Panda
2015-11-27 11:21   ` Bharat Bhusan Panda
2015-12-02 13:41   ` Luiz Augusto von Dentz
2015-10-21 13:04 ` [PATCH 1/3] audio/avrcp: Get player playlist details Luiz Augusto von Dentz
  -- strict thread matches above, loose matches on Subject: below --
2015-10-06 11:53 [PATCH 1/3] aurdio/avrcp: " Bharat Panda
2015-10-06 11:53 ` [PATCH 3/3] audio/avrcp: Add support for SetBrowsedPlayer Bharat Panda
2015-10-19 10:54   ` Luiz Augusto von Dentz

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.