[PATCH v2 3/3] AVRCP: Add support to changing active player

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



There is possibility to register more then one player,so this patch
allow to change active player to the freely chosen previously registered
player. It is working in compatibility of AVRCP 1.3.
---
 audio/avrcp.c     |   37 +++++++++++++++++++++++++++++
 audio/avrcp.h     |    1 +
 audio/media.c     |   66 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 doc/media-api.txt |   14 +++++++++++
 4 files changed, 118 insertions(+), 0 deletions(-)

diff --git a/audio/avrcp.c b/audio/avrcp.c
index f0c9665..12016b3 100644
--- a/audio/avrcp.c
+++ b/audio/avrcp.c
@@ -1327,3 +1327,40 @@ void avrcp_unregister_player(struct avrcp_player *player)
 
 	player_destroy(player);
 }
+
+void avrcp_set_active_player(struct avrcp_player *player)
+{
+	struct avrcp_server *server = player->server;
+	uint8_t status;
+	uint64_t uid;
+
+	status = player->cb->get_status(player->user_data);
+	uid = player->cb->get_uid(player->user_data);
+
+	player_abort_pending_pdu(server->active_player);
+
+	if (status !=
+		server->active_player->cb->get_status(server->active_player->user_data))
+		avrcp_player_event(server->active_player, AVRCP_EVENT_STATUS_CHANGED,
+								&status);
+	avrcp_player_event(server->active_player, AVRCP_EVENT_TRACK_CHANGED,
+						&uid);
+
+	player->registered_events = server->active_player->registered_events;
+	server->active_player->registered_events = 0;
+	memcpy(player->transaction_events,
+				server->active_player->transaction_events, AVRCP_EVENT_LAST);
+
+	player->session = server->active_player->session;
+	server->active_player->session = NULL;
+
+	if (server->active_player->handler) {
+		avctp_unregister_pdu_handler(server->active_player->handler);
+		server->active_player->handler = 0;
+	}
+
+	player->handler = avctp_register_pdu_handler(AVC_OP_VENDORDEP,
+						handle_vendordep_pdu, player);
+
+	server->active_player = player;
+}
diff --git a/audio/avrcp.h b/audio/avrcp.h
index 8a09546..f2041a7 100644
--- a/audio/avrcp.h
+++ b/audio/avrcp.h
@@ -96,6 +96,7 @@ struct avrcp_player *avrcp_register_player(const bdaddr_t *src,
 						void *user_data,
 						GDestroyNotify destroy);
 void avrcp_unregister_player(struct avrcp_player *player);
+void avrcp_set_active_player(struct avrcp_player *player);
 
 int avrcp_player_event(struct avrcp_player *player, uint8_t id, void *data);
 
diff --git a/audio/media.c b/audio/media.c
index c0fd0c3..99f1a9a 100644
--- a/audio/media.c
+++ b/audio/media.c
@@ -1705,11 +1705,77 @@ static DBusMessage *unregister_player(DBusConnection *conn, DBusMessage *msg,
 	return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
 }
 
+static DBusMessage *set_active_player(DBusConnection *conn, DBusMessage *msg,
+					void *data)
+{
+	struct media_adapter *adapter = data;
+	struct media_player *player;
+	const char *sender, *path;
+	DBusMessage *signal_msg;
+	GSList *l;
+
+	if (!dbus_message_get_args(msg, NULL,
+				DBUS_TYPE_OBJECT_PATH, &path,
+				DBUS_TYPE_INVALID))
+		return NULL;
+
+	sender = dbus_message_get_sender(msg);
+
+	player = media_adapter_find_player(adapter, sender, path);
+	if (player == NULL)
+		return btd_error_does_not_exist(msg);
+
+	avrcp_set_active_player(player->player);
+
+	for (l = adapter->players; l; l = l->next) {
+		struct media_player *mp = l->data;
+
+		if (path && g_strcmp0(mp->path, path) == 0) {
+			DBG("Activate player: %s", mp->path);
+
+			signal_msg = dbus_message_new_signal(mp->path,
+					MEDIA_PLAYER_INTERFACE,
+					"Activated");
+
+			if (signal_msg == NULL) {
+				DBG("Message null");
+				return NULL;
+			}
+
+			if (!dbus_connection_send(conn, signal_msg, NULL)) {
+				DBG("Out of memory");
+				return NULL;
+			}
+
+			dbus_message_unref(signal_msg);
+		} else {
+			signal_msg = dbus_message_new_signal(mp->path,
+					MEDIA_PLAYER_INTERFACE,
+					"Deactivated");
+
+			if (signal_msg == NULL) {
+				DBG("Message null");
+				return NULL;
+			}
+
+			if (!dbus_connection_send(conn, signal_msg, NULL)) {
+				DBG("Out of memory");
+				return NULL;
+			}
+
+			dbus_message_unref(signal_msg);
+		}
+	}
+
+	return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+}
+
 static GDBusMethodTable media_methods[] = {
 	{ "RegisterEndpoint",	"oa{sv}",	"",	register_endpoint },
 	{ "UnregisterEndpoint",	"o",		"",	unregister_endpoint },
 	{ "RegisterPlayer",	"oa{sv}a{sv}","",	register_player },
 	{ "UnregisterPlayer",	"o",		"",	unregister_player },
+	{ "SetActivePlayer",	"o",		"",	set_active_player },
 	{ },
 };
 
diff --git a/doc/media-api.txt b/doc/media-api.txt
index c53ab7b..c64d1f5 100644
--- a/doc/media-api.txt
+++ b/doc/media-api.txt
@@ -123,6 +123,11 @@ Methods		void RegisterEndpoint(object endpoint, dict properties)
 
 			Unregister sender media player.
 
+		void SetActivePlayer(object player)
+
+			Set active media player. Only one active player may be used
+			by remote controller.
+
 MediaPlayer hierarchy
 =====================
 
@@ -188,6 +193,15 @@ Signals		PropertyChanged(string setting, variant value)
 
 					Track duration in milliseconds
 
+		Activated()
+
+			This signal indicates one player to be currently used.
+
+		Deactivated()
+
+			This signal sends to all non-active players and indicates that
+			player lose focus.
+
 Properties	string Equalizer [readwrite]
 
 			Possible values: "off" or "on"
-- 
on behalf of ST-Ericsson

--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux