There is possibility to register more then one player,so this patch
allow to change active player to the freely chosen previously registered
player.
---
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
Hi Michal,
On Wed, Apr 11, 2012, Michal Labedzki wrote:
> Add missing capability for TrackReachedEnd.
> ---
> audio/avrcp.c | 5 +++--
> 1 files changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/audio/avrcp.c b/audio/avrcp.c
> index 8eba046..6eb4bb1 100644
> --- a/audio/avrcp.c
> +++ b/audio/avrcp.c
> @@ -557,12 +557,13 @@ static uint8_t avrcp_handle_get_capabilities(struct avrcp_player *player,
>
> return AVC_CTYPE_STABLE;
> case CAP_EVENTS_SUPPORTED:
> - pdu->params_len = htons(5);
> - pdu->params[1] = 3;
> + pdu->params[1] = 4;
> pdu->params[2] = AVRCP_EVENT_STATUS_CHANGED;
> pdu->params[3] = AVRCP_EVENT_TRACK_CHANGED;
> pdu->params[4] = AVRCP_EVENT_TRACK_REACHED_START;
> + pdu->params[5] = AVRCP_EVENT_TRACK_REACHED_END;
>
> + pdu->params_len = htons(2 + pdu->params[1]);
> return AVC_CTYPE_STABLE;
> }
This patch has been applied. Thanks.
Johan
Hi Michal,
On Wed, Apr 11, 2012 at 12:12 PM, Michal Labedzki
<[email protected]> wrote:
> Remove unused "audio_device" field in player structure.
> ---
> ?audio/avrcp.c | ? ?1 -
> ?1 files changed, 0 insertions(+), 1 deletions(-)
>
> diff --git a/audio/avrcp.c b/audio/avrcp.c
> index d456023..f0c9665 100644
> --- a/audio/avrcp.c
> +++ b/audio/avrcp.c
> @@ -146,7 +146,6 @@ struct pending_pdu {
> ?struct avrcp_player {
> ? ? ? ?struct avrcp_server *server;
> ? ? ? ?struct avctp *session;
> - ? ? ? struct audio_device *dev;
>
> ? ? ? ?unsigned int handler;
> ? ? ? ?uint16_t registered_events;
> --
> on behalf of ST-Ericsson
>
Instead of removing it we can make use of it to set which device is
addressing the player which is going to be useful when implementing
1.4.
--
Luiz Augusto von Dentz
Hi Michal,
On Wed, Apr 11, 2012 at 2:05 PM, Michal Labedzki
<[email protected]> wrote:
> Add missing capability for TrackReachedEnd.
> ---
> ?audio/avrcp.c | ? ?5 +++--
> ?1 files changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/audio/avrcp.c b/audio/avrcp.c
> index 8eba046..6eb4bb1 100644
> --- a/audio/avrcp.c
> +++ b/audio/avrcp.c
> @@ -557,12 +557,13 @@ static uint8_t avrcp_handle_get_capabilities(struct avrcp_player *player,
>
> ? ? ? ? ? ? ? ?return AVC_CTYPE_STABLE;
> ? ? ? ?case CAP_EVENTS_SUPPORTED:
> - ? ? ? ? ? ? ? pdu->params_len = htons(5);
> - ? ? ? ? ? ? ? pdu->params[1] = 3;
> + ? ? ? ? ? ? ? pdu->params[1] = 4;
> ? ? ? ? ? ? ? ?pdu->params[2] = AVRCP_EVENT_STATUS_CHANGED;
> ? ? ? ? ? ? ? ?pdu->params[3] = AVRCP_EVENT_TRACK_CHANGED;
> ? ? ? ? ? ? ? ?pdu->params[4] = AVRCP_EVENT_TRACK_REACHED_START;
> + ? ? ? ? ? ? ? pdu->params[5] = AVRCP_EVENT_TRACK_REACHED_END;
>
> + ? ? ? ? ? ? ? pdu->params_len = htons(2 + pdu->params[1]);
> ? ? ? ? ? ? ? ?return AVC_CTYPE_STABLE;
> ? ? ? ?}
>
> --
> on behalf of ST-Ericsson
>
Ack.
--
Luiz Augusto von Dentz
Hi Michal,
On Wed, Apr 11, 2012 at 12:12 PM, Michal Labedzki
<[email protected]> wrote:
> ?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.
> +
The use case here seems to be incorrect or Im missing something, I
remember commenting that such method is not really desirable since the
controlling point, at least for the current role, is the remote device
so having the players or a external component to control that will
only complicate things. Also this creates a limitation since only one
player can be marked as active at time, IMO the Active property should
only tell if the player can be addressed by the remote device so the
application can keep itself registered but idle (player out of
focus/minimized).
> ?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.
> +
I would make it a boolean property called Active, 2 signal is a pretty
bad since you actually have to emit both everytime.
--
Luiz Augusto von Dentz
Add missing capability for TrackReachedEnd.
---
audio/avrcp.c | 5 +++--
1 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/audio/avrcp.c b/audio/avrcp.c
index 8eba046..6eb4bb1 100644
--- a/audio/avrcp.c
+++ b/audio/avrcp.c
@@ -557,12 +557,13 @@ static uint8_t avrcp_handle_get_capabilities(struct avrcp_player *player,
return AVC_CTYPE_STABLE;
case CAP_EVENTS_SUPPORTED:
- pdu->params_len = htons(5);
- pdu->params[1] = 3;
+ pdu->params[1] = 4;
pdu->params[2] = AVRCP_EVENT_STATUS_CHANGED;
pdu->params[3] = AVRCP_EVENT_TRACK_CHANGED;
pdu->params[4] = AVRCP_EVENT_TRACK_REACHED_START;
+ pdu->params[5] = AVRCP_EVENT_TRACK_REACHED_END;
+ pdu->params_len = htons(2 + pdu->params[1]);
return AVC_CTYPE_STABLE;
}
--
on behalf of ST-Ericsson
Hi Michal,
On Wed, Apr 11, 2012 at 12:12 PM, Michal Labedzki
<[email protected]> wrote:
> Add missing capability for TrackReachedEnd.
> ---
> ?audio/avrcp.c | ? ?5 +++--
> ?1 files changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/audio/avrcp.c b/audio/avrcp.c
> index 8eba046..d456023 100644
> --- a/audio/avrcp.c
> +++ b/audio/avrcp.c
> @@ -557,11 +557,12 @@ static uint8_t avrcp_handle_get_capabilities(struct avrcp_player *player,
>
> ? ? ? ? ? ? ? ?return AVC_CTYPE_STABLE;
> ? ? ? ?case CAP_EVENTS_SUPPORTED:
> - ? ? ? ? ? ? ? pdu->params_len = htons(5);
> - ? ? ? ? ? ? ? pdu->params[1] = 3;
> + ? ? ? ? ? ? ? pdu->params_len = htons(2 + 4);
I think we could have params_lens done latter using params[1] e.g
pdu->params_len = htons(2 + pdu->params[1]) to make it simpler to add
new events.
> + ? ? ? ? ? ? ? pdu->params[1] = 4;
> ? ? ? ? ? ? ? ?pdu->params[2] = AVRCP_EVENT_STATUS_CHANGED;
> ? ? ? ? ? ? ? ?pdu->params[3] = AVRCP_EVENT_TRACK_CHANGED;
> ? ? ? ? ? ? ? ?pdu->params[4] = AVRCP_EVENT_TRACK_REACHED_START;
> + ? ? ? ? ? ? ? pdu->params[5] = AVRCP_EVENT_TRACK_REACHED_END;
>
> ? ? ? ? ? ? ? ?return AVC_CTYPE_STABLE;
> ? ? ? ?}
> --
> on behalf of ST-Ericsson
The rest looks good.
--
Luiz Augusto von Dentz
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
Remove unused "audio_device" field in player structure.
---
audio/avrcp.c | 1 -
1 files changed, 0 insertions(+), 1 deletions(-)
diff --git a/audio/avrcp.c b/audio/avrcp.c
index d456023..f0c9665 100644
--- a/audio/avrcp.c
+++ b/audio/avrcp.c
@@ -146,7 +146,6 @@ struct pending_pdu {
struct avrcp_player {
struct avrcp_server *server;
struct avctp *session;
- struct audio_device *dev;
unsigned int handler;
uint16_t registered_events;
--
on behalf of ST-Ericsson
Add missing capability for TrackReachedEnd.
---
audio/avrcp.c | 5 +++--
1 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/audio/avrcp.c b/audio/avrcp.c
index 8eba046..d456023 100644
--- a/audio/avrcp.c
+++ b/audio/avrcp.c
@@ -557,11 +557,12 @@ static uint8_t avrcp_handle_get_capabilities(struct avrcp_player *player,
return AVC_CTYPE_STABLE;
case CAP_EVENTS_SUPPORTED:
- pdu->params_len = htons(5);
- pdu->params[1] = 3;
+ pdu->params_len = htons(2 + 4);
+ pdu->params[1] = 4;
pdu->params[2] = AVRCP_EVENT_STATUS_CHANGED;
pdu->params[3] = AVRCP_EVENT_TRACK_CHANGED;
pdu->params[4] = AVRCP_EVENT_TRACK_REACHED_START;
+ pdu->params[5] = AVRCP_EVENT_TRACK_REACHED_END;
return AVC_CTYPE_STABLE;
}
--
on behalf of ST-Ericsson