Can you please integrate exceptions from the Android database? https://android.googlesource.com/platform/system/bt/+/master/device/include/interop_database.h Ones with INTEROP_DISABLE_ABSOLUTE_VOLUME On 03/10/2018 16:12, EHfive wrote: > On 10/3/18 8:37 PM, EHfive wrote: >> Require bluez-tools/mpris-proxy running. (No hurt if dosen't) >> >> If you need play/pause/next... controls , add configurations below to /etc/dbus-1/system.d/ >> >> ------------------------ mpris.conf >> >> <!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN" >> "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd"> >> <busconfig> >> <policy context="default"> >> <allow send_interface="org.mpris.MediaPlayer2.Player"/> >> </policy> >> </busconfig> >> >> ------------------------ >> > An alternative > > https://gist.github.com/EHfive/e2a28d0279a6247fab4bac93d73b8571 > > A python script which implement org.mpris.MediaPlayer2.Player and register mpris player object by calling org.bluez.Media1.RegisterPlayer. > >> =================== >> >> diff --git a/src/modules/bluetooth/bluez5-util.c b/src/modules/bluetooth/bluez5-util.c >> index 2d83373..72cd05a 100644 >> --- a/src/modules/bluetooth/bluez5-util.c >> +++ b/src/modules/bluetooth/bluez5-util.c >> @@ -348,6 +348,50 @@ void pa_bluetooth_transport_free(pa_bluetooth_transport *t) { >> pa_xfree(t); >> } >> >> +static int bluez5_transport_set_property(pa_bluetooth_transport *t, const char *prop_name, int prop_type, void *prop_value){ >> + DBusMessage *m, *r; >> + DBusError err; >> + DBusMessageIter i; >> + const char * interface = BLUEZ_MEDIA_TRANSPORT_INTERFACE; >> + >> + pa_log_debug("Setting property, Owner: %s; Path: %s; Property: %s",t->owner, t->path, prop_name); >> + >> + pa_assert(t); >> + pa_assert(t->device); >> + pa_assert(t->device->discovery); >> + >> + dbus_error_init(&err); >> + >> + pa_assert_se(m = dbus_message_new_method_call(t->owner, t->path, "org.freedesktop.DBus.Properties", "Set")); >> + >> + dbus_message_iter_init_append(m, &i); >> + >> + pa_assert_se(dbus_message_iter_append_basic(&i, DBUS_TYPE_STRING, &interface)); >> + pa_assert_se(dbus_message_iter_append_basic(&i, DBUS_TYPE_STRING, &prop_name)); >> + pa_dbus_append_basic_variant(&i, prop_type, prop_value); >> + >> + r = dbus_connection_send_with_reply_and_block(pa_dbus_connection_get(t->device->discovery->connection), m, -1, &err); >> + dbus_message_unref(m); >> + m = NULL; >> + if(r) { >> + dbus_message_unref(r); >> + r = NULL; >> + } >> + >> + if(dbus_error_is_set(&err)) { >> + pa_log_debug("Failed to set property \"%s.%s\"", interface, prop_name); >> + return -1; >> + } >> + >> + return 0; >> +} >> + >> +static int bluez5_transport_set_volume(pa_bluetooth_transport *t, uint16_t volume){ >> + if(t->a2dp_gain == volume) >> + return 0; >> + return bluez5_transport_set_property(t, "Volume", DBUS_TYPE_UINT16, &volume); >> +} >> + >> static int bluez5_transport_acquire_cb(pa_bluetooth_transport *t, bool optional, size_t *imtu, size_t *omtu) { >> DBusMessage *m, *r; >> DBusError err; >> @@ -441,6 +485,14 @@ bool pa_bluetooth_device_any_transport_connected(const pa_bluetooth_device *d) { >> return false; >> } >> >> +void pa_transport_set_a2dp_gain(pa_bluetooth_transport *t, uint16_t a2dp_gain){ >> + if(t->a2dp_gain == a2dp_gain) >> + return; >> + t->a2dp_gain = a2dp_gain; >> + pa_hook_fire(pa_bluetooth_discovery_hook(t->device->discovery, PA_BLUETOOTH_HOOK_TRANSPORT_A2DP_GAIN_CHANGED), t); >> +} >> + >> + >> static int transport_state_from_string(const char* value, pa_bluetooth_transport_state_t *state) { >> pa_assert(value); >> pa_assert(state); >> @@ -483,6 +535,18 @@ static void parse_transport_property(pa_bluetooth_transport *t, DBusMessageIter >> pa_bluetooth_transport_set_state(t, state); >> } >> >> + break; >> + } >> + case DBUS_TYPE_UINT16: { >> + >> + uint16_t value; >> + dbus_message_iter_get_basic(&variant_i, &value); >> + >> + if (pa_streq(key, "Volume")) { >> + pa_log_debug("Transport Volume Changed to %u ", value); >> + pa_transport_set_a2dp_gain(t, value); >> + } >> + >> break; >> } >> } >> @@ -1468,6 +1532,7 @@ static DBusMessage *endpoint_set_configuration(DBusConnection *conn, DBusMessage >> t = pa_bluetooth_transport_new(d, sender, path, p, config, size); >> t->acquire = bluez5_transport_acquire_cb; >> t->release = bluez5_transport_release_cb; >> + t->set_volume = bluez5_transport_set_volume; >> pa_bluetooth_transport_put(t); >> >> pa_log_debug("Transport %s available for profile %s", t->path, pa_bluetooth_profile_to_string(t->profile)); >> diff --git a/src/modules/bluetooth/bluez5-util.h b/src/modules/bluetooth/bluez5-util.h >> index ad30708..5b8149d 100644 >> --- a/src/modules/bluetooth/bluez5-util.h >> +++ b/src/modules/bluetooth/bluez5-util.h >> @@ -47,6 +47,7 @@ typedef enum pa_bluetooth_hook { >> PA_BLUETOOTH_HOOK_TRANSPORT_STATE_CHANGED, /* Call data: pa_bluetooth_transport */ >> PA_BLUETOOTH_HOOK_TRANSPORT_MICROPHONE_GAIN_CHANGED, /* Call data: pa_bluetooth_transport */ >> PA_BLUETOOTH_HOOK_TRANSPORT_SPEAKER_GAIN_CHANGED, /* Call data: pa_bluetooth_transport */ >> + PA_BLUETOOTH_HOOK_TRANSPORT_A2DP_GAIN_CHANGED, /* Call data: pa_bluetooth_transport */ >> PA_BLUETOOTH_HOOK_MAX >> } pa_bluetooth_hook_t; >> >> @@ -70,6 +71,7 @@ typedef void (*pa_bluetooth_transport_release_cb)(pa_bluetooth_transport *t); >> typedef void (*pa_bluetooth_transport_destroy_cb)(pa_bluetooth_transport *t); >> typedef void (*pa_bluetooth_transport_set_speaker_gain_cb)(pa_bluetooth_transport *t, uint16_t gain); >> typedef void (*pa_bluetooth_transport_set_microphone_gain_cb)(pa_bluetooth_transport *t, uint16_t gain); >> +typedef int (*pa_bluetooth_transport_set_volume_cb)(pa_bluetooth_transport *t, uint16_t volume); >> >> struct pa_bluetooth_transport { >> pa_bluetooth_device *device; >> @@ -84,6 +86,7 @@ struct pa_bluetooth_transport { >> >> uint16_t microphone_gain; >> uint16_t speaker_gain; >> + uint16_t a2dp_gain; >> >> pa_bluetooth_transport_state_t state; >> >> @@ -92,6 +95,7 @@ struct pa_bluetooth_transport { >> pa_bluetooth_transport_destroy_cb destroy; >> pa_bluetooth_transport_set_speaker_gain_cb set_speaker_gain; >> pa_bluetooth_transport_set_microphone_gain_cb set_microphone_gain; >> + pa_bluetooth_transport_set_volume_cb set_volume; >> void *userdata; >> }; >> >> diff --git a/src/modules/bluetooth/module-bluez5-device.c b/src/modules/bluetooth/module-bluez5-device.c >> index 351ad12..49a6dba 100644 >> --- a/src/modules/bluetooth/module-bluez5-device.c >> +++ b/src/modules/bluetooth/module-bluez5-device.c >> @@ -64,6 +64,7 @@ PA_MODULE_USAGE("path=<device object path>" >> #define BITPOOL_DEC_LIMIT 32 >> #define BITPOOL_DEC_STEP 5 >> #define HSP_MAX_GAIN 15 >> +#define BLUEZ_MAX_GAIN 127 >> >> static const char* const valid_modargs[] = { >> "path", >> @@ -113,6 +114,7 @@ struct userdata { >> pa_hook_slot *transport_state_changed_slot; >> pa_hook_slot *transport_speaker_gain_changed_slot; >> pa_hook_slot *transport_microphone_gain_changed_slot; >> + pa_hook_slot *transport_a2dp_gain_changed_slot; >> >> pa_bluetooth_discovery *discovery; >> pa_bluetooth_device *device; >> @@ -1056,6 +1058,37 @@ static void source_set_volume_cb(pa_source *s) { >> u->transport->set_microphone_gain(u->transport, gain); >> } >> >> +static void source_set_a2dp_volume_cb(pa_source *s) { >> + uint16_t gain; >> + pa_volume_t volume; >> + struct userdata *u; >> + >> + pa_assert(s); >> + pa_assert(s->core); >> + >> + u = s->userdata; >> + >> + pa_assert(u); >> + pa_assert(u->source == s); >> + >> + if (u->transport->set_volume == NULL) >> + return; >> + >> + gain = (uint16_t) ((pa_cvolume_max(&s->real_volume) * BLUEZ_MAX_GAIN) / PA_VOLUME_NORM); >> + >> + pa_log_debug("Real Volume Gain:%u", gain); >> + >> + if (gain > BLUEZ_MAX_GAIN) >> + gain = BLUEZ_MAX_GAIN; >> + >> + volume = (pa_volume_t) (gain * PA_VOLUME_NORM / BLUEZ_MAX_GAIN); >> + >> + pa_cvolume_set(&s->real_volume, u->sample_spec.channels, volume); >> + pa_cvolume_set(&s->soft_volume, u->sample_spec.channels, volume); >> + >> + u->transport->set_volume(u->transport, gain); >> +} >> + >> /* Run from main thread */ >> static int add_source(struct userdata *u) { >> pa_source_new_data data; >> @@ -1109,6 +1142,9 @@ static int add_source(struct userdata *u) { >> if (u->profile == PA_BLUETOOTH_PROFILE_HEADSET_HEAD_UNIT || u->profile == PA_BLUETOOTH_PROFILE_HEADSET_AUDIO_GATEWAY) { >> pa_source_set_set_volume_callback(u->source, source_set_volume_cb); >> u->source->n_volume_steps = 16; >> + } else if (u->profile == PA_BLUETOOTH_PROFILE_A2DP_SOURCE) { >> + pa_source_set_set_volume_callback(u->source, source_set_a2dp_volume_cb); >> + u->source->n_volume_steps = 1; >> } >> return 0; >> } >> @@ -1230,6 +1266,40 @@ static void sink_set_volume_cb(pa_sink *s) { >> u->transport->set_speaker_gain(u->transport, gain); >> } >> >> +static void sink_set_a2dp_volume_cb(pa_sink *s) { >> + uint16_t gain; >> + pa_volume_t volume; >> + struct userdata *u; >> + >> + pa_assert(s); >> + pa_assert(s->core); >> + >> + u = s->userdata; >> + >> + pa_assert(u); >> + pa_assert(u->sink == s); >> + >> + if (u->transport->set_volume == NULL) >> + return; >> + >> + gain = (uint16_t) ((pa_cvolume_max(&s->real_volume) * BLUEZ_MAX_GAIN) / PA_VOLUME_NORM); >> + >> + pa_log_debug("Real Volume Gain:%u", gain); >> + >> + if (gain > BLUEZ_MAX_GAIN) >> + gain = BLUEZ_MAX_GAIN; >> + >> + volume = (pa_volume_t) (gain * PA_VOLUME_NORM / BLUEZ_MAX_GAIN); >> + >> + pa_cvolume_set(&s->real_volume, u->sample_spec.channels, volume); >> + >> + if(u->transport->set_volume(u->transport, gain) < 0) { >> + pa_cvolume_set(&s->soft_volume, u->sample_spec.channels, PA_VOLUME_NORM); >> + pa_sink_set_set_volume_callback(s, NULL); >> + u->transport->a2dp_gain = 0xFFu; >> + } >> +} >> + >> /* Run from main thread */ >> static int add_sink(struct userdata *u) { >> pa_sink_new_data data; >> @@ -1284,6 +1354,9 @@ static int add_sink(struct userdata *u) { >> if (u->profile == PA_BLUETOOTH_PROFILE_HEADSET_HEAD_UNIT || u->profile == PA_BLUETOOTH_PROFILE_HEADSET_AUDIO_GATEWAY) { >> pa_sink_set_set_volume_callback(u->sink, sink_set_volume_cb); >> u->sink->n_volume_steps = 16; >> + } else if (u->profile == PA_BLUETOOTH_PROFILE_A2DP_SINK) { >> + pa_sink_set_set_volume_callback(u->sink, sink_set_a2dp_volume_cb); >> + u->sink->n_volume_steps = 1; >> } >> return 0; >> } >> @@ -2340,6 +2413,53 @@ static pa_hook_result_t transport_microphone_gain_changed_cb(pa_bluetooth_discov >> return PA_HOOK_OK; >> } >> >> +static pa_hook_result_t transport_a2dp_gain_changed_cb(pa_bluetooth_discovery *y, pa_bluetooth_transport *t, struct userdata *u) { >> + pa_volume_t volume; >> + pa_cvolume v; >> + uint16_t gain; >> + >> + pa_assert(t); >> + pa_assert(u); >> + >> + if (t != u->transport) >> + return PA_HOOK_OK; >> + >> + gain = t->a2dp_gain; >> + volume = (pa_volume_t) (gain * PA_VOLUME_NORM / BLUEZ_MAX_GAIN); >> + >> + pa_cvolume_set(&v, u->sample_spec.channels, volume); >> + >> + if(u->profile == PA_BLUETOOTH_PROFILE_A2DP_SINK){ >> + pa_assert(u->sink); >> + >> + if(!u->sink->set_volume){ >> + pa_cvolume_set(&u->sink->soft_volume, u->sample_spec.channels, PA_VOLUME_NORM); >> + pa_sink_set_set_volume_callback(u->sink, sink_set_a2dp_volume_cb); >> + } >> + >> + >> + if (gain == 0) >> + pa_sink_mute_changed(u->sink, true); >> + else if(u->sink->muted) >> + pa_sink_mute_changed(u->sink, false); >> + >> + pa_sink_volume_changed(u->sink, &v); >> + } else if(u->profile == PA_BLUETOOTH_PROFILE_A2DP_SOURCE){ >> + pa_assert(u->source); >> + >> + >> + if (gain == 0) >> + pa_source_mute_changed(u->source, true); >> + else if(u->source->muted) >> + pa_source_mute_changed(u->source, false); >> + >> + pa_source_volume_changed(u->source, &v); >> + } >> + >> + >> + return PA_HOOK_OK; >> +} >> + >> /* Run from main thread context */ >> static int device_process_msg(pa_msgobject *obj, int code, void *data, int64_t offset, pa_memchunk *chunk) { >> struct bluetooth_msg *m = BLUETOOTH_MSG(obj); >> @@ -2430,6 +2550,9 @@ int pa__init(pa_module* m) { >> u->transport_microphone_gain_changed_slot = >> pa_hook_connect(pa_bluetooth_discovery_hook(u->discovery, PA_BLUETOOTH_HOOK_TRANSPORT_MICROPHONE_GAIN_CHANGED), PA_HOOK_NORMAL, (pa_hook_cb_t) transport_microphone_gain_changed_cb, u); >> >> + u->transport_a2dp_gain_changed_slot = >> + pa_hook_connect(pa_bluetooth_discovery_hook(u->discovery, PA_BLUETOOTH_HOOK_TRANSPORT_A2DP_GAIN_CHANGED), PA_HOOK_NORMAL, (pa_hook_cb_t) transport_a2dp_gain_changed_cb, u); >> + >> if (add_card(u) < 0) >> goto fail; >> >> @@ -2491,6 +2614,9 @@ void pa__done(pa_module *m) { >> if (u->transport_microphone_gain_changed_slot) >> pa_hook_slot_free(u->transport_microphone_gain_changed_slot); >> >> + if (u->transport_a2dp_gain_changed_slot) >> + pa_hook_slot_free(u->transport_a2dp_gain_changed_slot); >> + >> if (u->sbc_info.buffer) >> pa_xfree(u->sbc_info.buffer); >> >> >> _______________________________________________ >> pulseaudio-discuss mailing list >> pulseaudio-discuss@xxxxxxxxxxxxxxxxxxxxx >> https://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss > > _______________________________________________ > pulseaudio-discuss mailing list > pulseaudio-discuss@xxxxxxxxxxxxxxxxxxxxx > https://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss >
Attachment:
signature.asc
Description: OpenPGP digital signature
_______________________________________________ pulseaudio-discuss mailing list pulseaudio-discuss@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss