audio/transport: supply volume on transport init
authorArchie Pusaka <apusaka@chromium.org>
Thu, 23 Jul 2020 07:23:40 +0000 (15:23 +0800)
committerAyush Garg <ayush.garg@samsung.com>
Mon, 12 Apr 2021 09:00:50 +0000 (14:30 +0530)
Sometimes the response of RegisterNotification for volume change
event came before we create the transport for the corresponding
device. If that happens, the volume will be stuck to an
uninitialized invalid value. The property Volume of
MediaTransport1 will also be left unaccessible.

This patch supplies the initial volume when creating a new
transport. The value is obtained from the media_player object.
However, since the avrcp session might not be created by the time
the transport is created, we also try to initialize the volume
when creating avrcp session.

Signed-off-by: Anuj Jain <anuj01.jain@samsung.com>
Signed-off-by: Ayush Garg <ayush.garg@samsung.com>
profiles/audio/avrcp.c
profiles/audio/avrcp.h
profiles/audio/media.c
profiles/audio/media.h
profiles/audio/transport.c

index a81b46e020f84da89c4792f2641cbe64fbc3982b..d9d8ba6e201417229d2dea727e9ec36f53a19e68 100644 (file)
@@ -63,6 +63,7 @@
 #include "avctp.h"
 #include "avrcp.h"
 #include "control.h"
+#include "media.h"
 #include "player.h"
 #include "transport.h"
 
@@ -1897,7 +1898,6 @@ static uint8_t avrcp_handle_request_continuing(struct avrcp *session,
        if (pending->pdu_id != pdu->params[0])
                goto err;
 
-
        len = 0;
        pending->attr_ids = player_fill_media_attribute(player,
                                                        pending->attr_ids,
@@ -4532,8 +4532,12 @@ static void target_init(struct avrcp *session)
 
        player = g_slist_nth_data(server->players, 0);
        if (player != NULL) {
+               int8_t init_volume;
                target->player = player;
                player->sessions = g_slist_prepend(player->sessions, session);
+
+               init_volume = media_player_get_device_volume(session->dev);
+               media_transport_update_device_volume(session->dev, init_volume);
        }
 
        session->supported_events |= (1 << AVRCP_EVENT_STATUS_CHANGED) |
@@ -5006,6 +5010,27 @@ int avrcp_set_volume(struct btd_device *dev, int8_t volume, bool notify)
                                        avrcp_handle_set_volume, session);
 }
 
+struct avrcp_player *avrcp_get_target_player_by_device(struct btd_device *dev)
+{
+       struct avrcp_server *server;
+       struct avrcp *session;
+       struct avrcp_data *target;
+
+       server = find_server(servers, device_get_adapter(dev));
+       if (server == NULL)
+               return NULL;
+
+       session = find_session(server->sessions, dev);
+       if (session == NULL)
+               return NULL;
+
+       target = session->target;
+       if (target == NULL)
+               return NULL;
+
+       return target->player;
+}
+
 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
 int avrcp_get_target_volume(struct btd_device *dev, uint8_t* volume)
 {
index e186da9bac86b58c93e8c43b466d0da7011ef6ce..842382a8c371a7a08e5ef0e83788464edfd5c237 100644 (file)
@@ -127,3 +127,5 @@ void avrcp_player_event(struct avrcp_player *player, uint8_t id,
 
 size_t avrcp_handle_vendor_reject(uint8_t *code, uint8_t *operands);
 size_t avrcp_browsing_general_reject(uint8_t *operands);
+
+struct avrcp_player *avrcp_get_target_player_by_device(struct btd_device *dev);
index 847a99febda499f9782e24a2425dd9f61f7fa01d..c1030c07cee209ad435da031820d58056eb540fd 100644 (file)
@@ -283,6 +283,20 @@ static void media_endpoint_exit(DBusConnection *connection, void *user_data)
        media_endpoint_remove(endpoint);
 }
 
+static struct media_adapter *find_adapter(struct btd_device *device)
+{
+       GSList *l;
+
+       for (l = adapters; l; l = l->next) {
+               struct media_adapter *adapter = l->data;
+
+               if (adapter->btd_adapter == device_get_adapter(device))
+                       return adapter;
+       }
+
+       return NULL;
+}
+
 static void clear_configuration(struct media_endpoint *endpoint,
                                        struct media_transport *transport)
 {
@@ -616,6 +630,33 @@ struct a2dp_config_data {
        a2dp_endpoint_config_t cb;
 };
 
+int8_t media_player_get_device_volume(struct btd_device *device)
+{
+       struct avrcp_player *target_player;
+       struct media_adapter *adapter;
+       GSList *l;
+
+       if (!device)
+               return -1;
+
+       target_player = avrcp_get_target_player_by_device(device);
+       if (!target_player)
+               return -1;
+
+       adapter = find_adapter(device);
+       if (!adapter)
+               return -1;
+
+       for (l = adapter->players; l; l = l->next) {
+               struct media_player *mp = l->data;
+
+               if (mp->player == target_player)
+                       return mp->volume;
+       }
+
+       return -1;
+}
+
 static gboolean set_configuration(struct media_endpoint *endpoint,
                                        uint8_t *configuration, size_t size,
                                        media_endpoint_cb_t cb,
@@ -629,6 +670,7 @@ static gboolean set_configuration(struct media_endpoint *endpoint,
        const char *path;
        DBusMessageIter iter;
        struct media_transport *transport;
+       int8_t init_volume;
 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
        struct media_adapter *adapter;
        struct media_player *mp;
@@ -645,6 +687,9 @@ static gboolean set_configuration(struct media_endpoint *endpoint,
        if (transport == NULL)
                return FALSE;
 
+       init_volume = media_player_get_device_volume(device);
+       media_transport_update_volume(transport, init_volume);
+
        msg = dbus_message_new_method_call(endpoint->sender, endpoint->path,
                                                MEDIA_ENDPOINT_INTERFACE,
                                                "SetConfiguration");
@@ -861,20 +906,6 @@ static gboolean endpoint_init_a2dp_sink(struct media_endpoint *endpoint,
        return TRUE;
 }
 
-static struct media_adapter *find_adapter(struct btd_device *device)
-{
-       GSList *l;
-
-       for (l = adapters; l; l = l->next) {
-               struct media_adapter *adapter = l->data;
-
-               if (adapter->btd_adapter == device_get_adapter(device))
-                       return adapter;
-       }
-
-       return NULL;
-}
-
 static bool endpoint_properties_exists(const char *uuid,
                                                struct btd_device *dev,
                                                void *user_data)
@@ -2195,6 +2226,7 @@ static struct media_player *media_player_create(struct media_adapter *adapter,
        mp->sender = g_strdup(sender);
        mp->path = g_strdup(path);
        mp->timer = g_timer_new();
+       mp->volume = -1;
 
        mp->watch = g_dbus_add_disconnect_watch(conn, sender,
                                                media_player_exit, mp,
index dd630d4327ff75ba7648dc8e698d53c42ecc5108..53694f4c6955d69023789a2d575034a760da96d1 100755 (executable)
@@ -33,3 +33,5 @@ void media_unregister(struct btd_adapter *btd_adapter);
 struct a2dp_sep *media_endpoint_get_sep(struct media_endpoint *endpoint);
 const char *media_endpoint_get_uuid(struct media_endpoint *endpoint);
 uint8_t media_endpoint_get_codec(struct media_endpoint *endpoint);
+
+int8_t media_player_get_device_volume(struct btd_device *device);
index d0f986d0e0b97a06130e5e9969060a1e5c5a0f83..bb5354c4f7d68d306863e9d977f7fc904bc51866 100644 (file)
@@ -1117,7 +1117,7 @@ void media_transport_update_device_volume(struct btd_device *dev,
 {
        GSList *l;
 
-       if (dev == NULL)
+       if (dev == NULL || volume < 0)
                return;
 
        for (l = transports; l; l = l->next) {