[pulseaudio-discuss] [PATCH v1 09/18] bluetooth: Support port availability flag

Mikel Astiz mikel.astiz.oss at gmail.com
Mon Aug 27 08:24:04 PDT 2012


From: Mikel Astiz <mikel.astiz at bmw-carit.de>

Use the port availability flag to expose whether a certain profile is
connected and whether it's doing actual audio streaming.

The proposed mapping is the following:
- Profile disconnected: port is unavailable.
- Profile is connected (but not streaming/playing): availability uknown.
- Profile is streaming/playing: port is available.

The availability-unknown is specially interesting: it involves that if
the sink/source exists (corresponding card profile set), it is currently
in suspended state.

For example, for SCO cases (HFGW or HSP), this means the SCO is down. A
policy module would typically not change this, unless someone is really
trying to use the sink/source. This situation would be nicely handled by
module-suspend-on-idle, which would automatically connect SCO.

On the other hand, if the user wants to control the status of the SCO,
it will still be possible by resuming the sink or source (suspend=0).
This works out-of-the-box since most UIs would show to the user ports
whose availability is unknown.
---
 src/modules/bluetooth/module-bluetooth-device.c |   72 +++++++++++++++++++++--
 1 files changed, 67 insertions(+), 5 deletions(-)

diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c
index 2074701..85d8e8e 100644
--- a/src/modules/bluetooth/module-bluetooth-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -1197,6 +1197,15 @@ static pa_bt_audio_state_t parse_state_property_change(DBusMessage *m) {
     return state;
 }
 
+static pa_port_available_t audio_state_to_availability(pa_bt_audio_state_t state) {
+    if (state < PA_BT_AUDIO_STATE_CONNECTED)
+        return PA_PORT_AVAILABLE_NO;
+    else if (state >= PA_BT_AUDIO_STATE_PLAYING)
+        return PA_PORT_AVAILABLE_YES;
+    else
+        return PA_PORT_AVAILABLE_UNKNOWN;
+}
+
 /* Run from main thread */
 static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *m, void *userdata) {
     DBusError err;
@@ -1267,6 +1276,50 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *m, void *us
                 }
                 break;
         }
+
+        if (state != PA_BT_AUDIO_STATE_INVALID) {
+            pa_device_port *port;
+            pa_port_available_t available = audio_state_to_availability(state);
+
+            pa_assert_se(port = pa_hashmap_get(u->card->ports, "hfgw-output"));
+            pa_device_port_set_available(port, available);
+
+            pa_assert_se(port = pa_hashmap_get(u->card->ports, "hfgw-input"));
+            pa_device_port_set_available(port, available);
+        }
+    } else if (dbus_message_is_signal(m, "org.bluez.Headset", "PropertyChanged")) {
+        pa_bt_audio_state_t state = parse_state_property_change(m);
+
+        if (state != PA_BT_AUDIO_STATE_INVALID) {
+            pa_device_port *port;
+            pa_port_available_t available = audio_state_to_availability(state);
+
+            pa_assert_se(port = pa_hashmap_get(u->card->ports, "hsp-output"));
+            pa_device_port_set_available(port, available);
+
+            pa_assert_se(port = pa_hashmap_get(u->card->ports, "hsp-input"));
+            pa_device_port_set_available(port, available);
+        }
+    } else if (dbus_message_is_signal(m, "org.bluez.AudioSource", "PropertyChanged")) {
+        pa_bt_audio_state_t state = parse_state_property_change(m);
+
+        if (state != PA_BT_AUDIO_STATE_INVALID) {
+            pa_device_port *port;
+            pa_port_available_t available = audio_state_to_availability(state);
+
+            pa_assert_se(port = pa_hashmap_get(u->card->ports, "a2dp-input"));
+            pa_device_port_set_available(port, available);
+        }
+    } else if (dbus_message_is_signal(m, "org.bluez.AudioSink", "PropertyChanged")) {
+        pa_bt_audio_state_t state = parse_state_property_change(m);
+
+        if (state != PA_BT_AUDIO_STATE_INVALID) {
+            pa_device_port *port;
+            pa_port_available_t available = audio_state_to_availability(state);
+
+            pa_assert_se(port = pa_hashmap_get(u->card->ports, "a2dp-output"));
+            pa_device_port_set_available(port, available);
+        }
     }
 
 fail:
@@ -2097,7 +2150,7 @@ static int card_set_profile(pa_card *c, pa_card_profile *new_profile) {
     return 0;
 }
 
-static void create_ports_for_profile(struct userdata *u, pa_card_new_data *card_new_data, pa_card_profile *profile) {
+static void create_ports_for_profile(struct userdata *u, const pa_bluetooth_device *device, pa_card_new_data *card_new_data, pa_card_profile *profile) {
     pa_device_port *port;
     enum profile *d;
 
@@ -2110,6 +2163,7 @@ static void create_ports_for_profile(struct userdata *u, pa_card_new_data *card_
             port->is_output = 1;
             port->is_input = 0;
             port->priority = profile->priority * 100;
+            port->available = audio_state_to_availability(device->audio_sink_state);
             pa_hashmap_put(port->profiles, profile->name, profile);
             break;
 
@@ -2119,6 +2173,7 @@ static void create_ports_for_profile(struct userdata *u, pa_card_new_data *card_
             port->is_output = 0;
             port->is_input = 1;
             port->priority = profile->priority * 100;
+            port->available = audio_state_to_availability(device->audio_source_state);
             pa_hashmap_put(port->profiles, profile->name, profile);
             break;
 
@@ -2128,6 +2183,7 @@ static void create_ports_for_profile(struct userdata *u, pa_card_new_data *card_
             port->is_output = 1;
             port->is_input = 0;
             port->priority = profile->priority * 100;
+            port->available = audio_state_to_availability(device->headset_state);
             pa_hashmap_put(port->profiles, profile->name, profile);
 
             pa_assert_se(port = pa_device_port_new(u->core, "hsp-input", _("Bluetooth Telephony (HSP/HFP)"), 0));
@@ -2135,6 +2191,7 @@ static void create_ports_for_profile(struct userdata *u, pa_card_new_data *card_
             port->is_output = 0;
             port->is_input = 1;
             port->priority = profile->priority * 100;
+            port->available = audio_state_to_availability(device->headset_state);
             pa_hashmap_put(port->profiles, profile->name, profile);
             break;
 
@@ -2144,6 +2201,7 @@ static void create_ports_for_profile(struct userdata *u, pa_card_new_data *card_
             port->is_output = 1;
             port->is_input = 0;
             port->priority = profile->priority * 100;
+            port->available = audio_state_to_availability(device->hfgw_state);
             pa_hashmap_put(port->profiles, profile->name, profile);
 
             pa_assert_se(port = pa_device_port_new(u->core, "hfgw-input", _("Bluetooth Handsfree Gateway"), 0));
@@ -2151,6 +2209,7 @@ static void create_ports_for_profile(struct userdata *u, pa_card_new_data *card_
             port->is_output = 0;
             port->is_input = 1;
             port->priority = profile->priority * 100;
+            port->available = audio_state_to_availability(device->hfgw_state);
             pa_hashmap_put(port->profiles, profile->name, profile);
             break;
 
@@ -2212,7 +2271,7 @@ static int add_card(struct userdata *u, const pa_bluetooth_device *device) {
 
         d = PA_CARD_PROFILE_DATA(p);
         *d = PROFILE_A2DP;
-        create_ports_for_profile(u, &data, p);
+        create_ports_for_profile(u, device, &data, p);
 
         pa_hashmap_put(data.profiles, p->name, p);
     }
@@ -2227,7 +2286,7 @@ static int add_card(struct userdata *u, const pa_bluetooth_device *device) {
 
         d = PA_CARD_PROFILE_DATA(p);
         *d = PROFILE_A2DP_SOURCE;
-        create_ports_for_profile(u, &data, p);
+        create_ports_for_profile(u, device, &data, p);
 
         pa_hashmap_put(data.profiles, p->name, p);
     }
@@ -2243,7 +2302,7 @@ static int add_card(struct userdata *u, const pa_bluetooth_device *device) {
 
         d = PA_CARD_PROFILE_DATA(p);
         *d = PROFILE_HSP;
-        create_ports_for_profile(u, &data, p);
+        create_ports_for_profile(u, device, &data, p);
 
         pa_hashmap_put(data.profiles, p->name, p);
     }
@@ -2258,7 +2317,7 @@ static int add_card(struct userdata *u, const pa_bluetooth_device *device) {
 
         d = PA_CARD_PROFILE_DATA(p);
         *d = PROFILE_HFGW;
-        create_ports_for_profile(u, &data, p);
+        create_ports_for_profile(u, device, &data, p);
 
         pa_hashmap_put(data.profiles, p->name, p);
     }
@@ -2457,6 +2516,9 @@ int pa__init(pa_module* m) {
                 mike,
                 "type='signal',sender='org.bluez',interface='org.bluez.MediaTransport',member='PropertyChanged'",
                 "type='signal',sender='org.bluez',interface='org.bluez.HandsfreeGateway',member='PropertyChanged'",
+                "type='signal',sender='org.bluez',interface='org.bluez.Headset',member='PropertyChanged'",
+                "type='signal',sender='org.bluez',interface='org.bluez.AudioSource',member='PropertyChanged'",
+                "type='signal',sender='org.bluez',interface='org.bluez.AudioSink',member='PropertyChanged'",
                 NULL) < 0) {
 
         pa_xfree(speaker);
-- 
1.7.7.6



More information about the pulseaudio-discuss mailing list