Allow module-bluetooth-device to listens to HandsfreeGateway state changes using DBUS signals. When an handsfree connects, module-bluetooth-device is loaded and goes to playing state. When the handsfree disconnect audio, the card profile is set to "off". If the headset connects audio again after that, the card profile should switch to "hfgw" again to match state of audio connection. --- src/modules/bluetooth/bluetooth-util.c | 2 +- src/modules/bluetooth/bluetooth-util.h | 1 + src/modules/bluetooth/module-bluetooth-device.c | 54 ++++++++++++++++++++++- 3 files changed, 55 insertions(+), 2 deletions(-) diff --git a/src/modules/bluetooth/bluetooth-util.c b/src/modules/bluetooth/bluetooth-util.c index 0054954..2e4d93c 100644 --- a/src/modules/bluetooth/bluetooth-util.c +++ b/src/modules/bluetooth/bluetooth-util.c @@ -76,7 +76,7 @@ struct pa_bluetooth_discovery { static void get_properties_reply(DBusPendingCall *pending, void *userdata); static pa_dbus_pending* send_and_add_to_pending(pa_bluetooth_discovery *y, DBusMessage *m, DBusPendingCallNotifyFunction func, void *call_data); -static pa_bt_audio_state_t pa_bt_audio_state_from_string(const char* value) { +pa_bt_audio_state_t pa_bt_audio_state_from_string(const char* value) { pa_assert(value); if (pa_streq(value, "disconnected")) diff --git a/src/modules/bluetooth/bluetooth-util.h b/src/modules/bluetooth/bluetooth-util.h index 248ca47..2752a69 100644 --- a/src/modules/bluetooth/bluetooth-util.h +++ b/src/modules/bluetooth/bluetooth-util.h @@ -138,5 +138,6 @@ const char* pa_bluetooth_get_form_factor(uint32_t class); char *pa_bluetooth_cleanup_name(const char *name); pa_bool_t pa_bluetooth_uuid_has(pa_bluetooth_uuid *uuids, const char *uuid); +pa_bt_audio_state_t pa_bt_audio_state_from_string(const char* value); #endif diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c index d90f779..9dbfc3a 100644 --- a/src/modules/bluetooth/module-bluetooth-device.c +++ b/src/modules/bluetooth/module-bluetooth-device.c @@ -1834,6 +1834,55 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *m, void *us pa_log_debug("dbus: property 'NREC' changed to value '%s'", t->nrec ? "True" : "False"); pa_proplist_sets(u->source->proplist, "bluetooth.nrec", t->nrec ? "1" : "0"); } + } else if (dbus_message_is_signal(m, "org.bluez.HandsfreeGateway", "PropertyChanged")) { + const char *key; + DBusMessageIter iter; + DBusMessageIter variant; + pa_bt_audio_state_t state; + + if (!dbus_message_iter_init(m, &iter)) { + pa_log("Failed to parse PropertyChanged: %s", err.message); + goto fail; + } + + if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) { + pa_log("Property name not a string."); + goto fail; + } + + dbus_message_iter_get_basic(&iter, &key); + + if (!dbus_message_iter_next(&iter)) { + pa_log("Property value missing"); + goto fail; + } + + dbus_message_iter_recurse(&iter, &variant); + + if (dbus_message_iter_get_arg_type(&variant) == DBUS_TYPE_STRING) { + const char *value; + dbus_message_iter_get_basic(&variant, &value); + + if (pa_streq(key, "State")) { + pa_log_debug("dbus: HSHFAG property 'State' changed to value '%s'", value); + state = pa_bt_audio_state_from_string(value); + } + } + + switch(state) { + case PA_BT_AUDIO_STATE_INVALID: + case PA_BT_AUDIO_STATE_DISCONNECTED: + case PA_BT_AUDIO_STATE_CONNECTED: + case PA_BT_AUDIO_STATE_CONNECTING: + goto fail; + case PA_BT_AUDIO_STATE_PLAYING: + if (u->card) { + pa_log_debug("Changing profile to hfgw"); + if (pa_card_set_profile(u->card, "hfgw", FALSE) < 0) + pa_log("Failed to change profile to hfgw"); + } + break; + } } fail: @@ -2935,6 +2984,7 @@ int pa__init(pa_module* m) { speaker, mike, transport, + "type='signal',sender='org.bluez',interface='org.bluez.HandsfreeGateway',member='PropertyChanged'", NULL) < 0) { pa_xfree(speaker); @@ -3008,7 +3058,9 @@ void pa__done(pa_module *m) { speaker = pa_sprintf_malloc("type='signal',sender='org.bluez',interface='org.bluez.Headset',member='SpeakerGainChanged',path='%s'", u->path); mike = pa_sprintf_malloc("type='signal',sender='org.bluez',interface='org.bluez.Headset',member='MicrophoneGainChanged',path='%s'", u->path); - pa_dbus_remove_matches(pa_dbus_connection_get(u->connection), speaker, mike, NULL); + pa_dbus_remove_matches(pa_dbus_connection_get(u->connection), speaker, mike, + "type='signal',sender='org.bluez',interface='org.bluez.HandsfreeGateway',member='PropertyChanged'", + NULL); pa_xfree(speaker); pa_xfree(mike); -- 1.7.4.1