mirror of
				https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
				synced 2025-11-03 09:01:50 -05:00 
			
		
		
		
	bluetooth: Use bluetooth-util for mic/speaker gain control
Use the new abstraction in bluetooth-util to both receive volume updates and request them.
This commit is contained in:
		
							parent
							
								
									0b524c1078
								
							
						
					
					
						commit
						d6d6770a04
					
				
					 1 changed files with 58 additions and 36 deletions
				
			
		| 
						 | 
					@ -147,6 +147,8 @@ struct userdata {
 | 
				
			||||||
    pa_hook_slot *source_state_changed_slot;
 | 
					    pa_hook_slot *source_state_changed_slot;
 | 
				
			||||||
    pa_hook_slot *transport_state_changed_slot;
 | 
					    pa_hook_slot *transport_state_changed_slot;
 | 
				
			||||||
    pa_hook_slot *transport_nrec_changed_slot;
 | 
					    pa_hook_slot *transport_nrec_changed_slot;
 | 
				
			||||||
 | 
					    pa_hook_slot *transport_microphone_changed_slot;
 | 
				
			||||||
 | 
					    pa_hook_slot *transport_speaker_changed_slot;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pa_bluetooth_discovery *discovery;
 | 
					    pa_bluetooth_discovery *discovery;
 | 
				
			||||||
    pa_bool_t auto_connect;
 | 
					    pa_bool_t auto_connect;
 | 
				
			||||||
| 
						 | 
					@ -1299,32 +1301,7 @@ static DBusHandlerResult filter_cb(DBusConnection *bus, DBusMessage *m, void *us
 | 
				
			||||||
    if (!dbus_message_has_path(m, u->path) && (!u->transport || !dbus_message_has_path(m, u->transport->path)))
 | 
					    if (!dbus_message_has_path(m, u->path) && (!u->transport || !dbus_message_has_path(m, u->transport->path)))
 | 
				
			||||||
        goto fail;
 | 
					        goto fail;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (dbus_message_is_signal(m, "org.bluez.Headset", "SpeakerGainChanged") ||
 | 
					    if (dbus_message_is_signal(m, "org.bluez.HandsfreeGateway", "PropertyChanged")) {
 | 
				
			||||||
        dbus_message_is_signal(m, "org.bluez.Headset", "MicrophoneGainChanged")) {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        dbus_uint16_t gain;
 | 
					 | 
				
			||||||
        pa_cvolume v;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (!dbus_message_get_args(m, &err, DBUS_TYPE_UINT16, &gain, DBUS_TYPE_INVALID) || gain > HSP_MAX_GAIN) {
 | 
					 | 
				
			||||||
            pa_log("Failed to parse org.bluez.Headset.{Speaker|Microphone}GainChanged: %s", err.message);
 | 
					 | 
				
			||||||
            goto fail;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (u->profile == PROFILE_HSP) {
 | 
					 | 
				
			||||||
            if (u->sink && dbus_message_is_signal(m, "org.bluez.Headset", "SpeakerGainChanged")) {
 | 
					 | 
				
			||||||
                pa_volume_t volume = (pa_volume_t) round((double) gain * PA_VOLUME_NORM / HSP_MAX_GAIN);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                pa_cvolume_set(&v, u->sample_spec.channels, volume);
 | 
					 | 
				
			||||||
                pa_sink_volume_changed(u->sink, &v);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            } else if (u->source && dbus_message_is_signal(m, "org.bluez.Headset", "MicrophoneGainChanged")) {
 | 
					 | 
				
			||||||
                pa_volume_t volume = (pa_volume_t) round((double) gain * PA_VOLUME_NORM / HSP_MAX_GAIN);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                pa_cvolume_set(&v, u->sample_spec.channels, volume);
 | 
					 | 
				
			||||||
                pa_source_volume_changed(u->source, &v);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    } else if (dbus_message_is_signal(m, "org.bluez.HandsfreeGateway", "PropertyChanged")) {
 | 
					 | 
				
			||||||
        pa_bt_audio_state_t state = parse_state_property_change(m);
 | 
					        pa_bt_audio_state_t state = parse_state_property_change(m);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (state != PA_BT_AUDIO_STATE_INVALID && pa_hashmap_get(u->card->profiles, "hfgw")) {
 | 
					        if (state != PA_BT_AUDIO_STATE_INVALID && pa_hashmap_get(u->card->profiles, "hfgw")) {
 | 
				
			||||||
| 
						 | 
					@ -1433,7 +1410,6 @@ fail:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Run from main thread */
 | 
					/* Run from main thread */
 | 
				
			||||||
static void sink_set_volume_cb(pa_sink *s) {
 | 
					static void sink_set_volume_cb(pa_sink *s) {
 | 
				
			||||||
    DBusMessage *m;
 | 
					 | 
				
			||||||
    dbus_uint16_t gain;
 | 
					    dbus_uint16_t gain;
 | 
				
			||||||
    pa_volume_t volume;
 | 
					    pa_volume_t volume;
 | 
				
			||||||
    struct userdata *u;
 | 
					    struct userdata *u;
 | 
				
			||||||
| 
						 | 
					@ -1449,21 +1425,18 @@ static void sink_set_volume_cb(pa_sink *s) {
 | 
				
			||||||
    pa_assert(u);
 | 
					    pa_assert(u);
 | 
				
			||||||
    pa_assert(u->sink == s);
 | 
					    pa_assert(u->sink == s);
 | 
				
			||||||
    pa_assert(u->profile == PROFILE_HSP);
 | 
					    pa_assert(u->profile == PROFILE_HSP);
 | 
				
			||||||
 | 
					    pa_assert(u->transport);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    gain = (dbus_uint16_t) round((double) pa_cvolume_max(&s->real_volume) * HSP_MAX_GAIN / PA_VOLUME_NORM);
 | 
					    gain = (dbus_uint16_t) round((double) pa_cvolume_max(&s->real_volume) * HSP_MAX_GAIN / PA_VOLUME_NORM);
 | 
				
			||||||
    volume = (pa_volume_t) round((double) gain * PA_VOLUME_NORM / HSP_MAX_GAIN);
 | 
					    volume = (pa_volume_t) round((double) gain * PA_VOLUME_NORM / HSP_MAX_GAIN);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pa_cvolume_set(&s->real_volume, u->sample_spec.channels, volume);
 | 
					    pa_cvolume_set(&s->real_volume, u->sample_spec.channels, volume);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pa_assert_se(m = dbus_message_new_method_call("org.bluez", u->path, "org.bluez.Headset", "SetSpeakerGain"));
 | 
					    pa_bluetooth_transport_set_speaker_gain(u->transport, gain);
 | 
				
			||||||
    pa_assert_se(dbus_message_append_args(m, DBUS_TYPE_UINT16, &gain, DBUS_TYPE_INVALID));
 | 
					 | 
				
			||||||
    pa_assert_se(dbus_connection_send(pa_dbus_connection_get(u->connection), m, NULL));
 | 
					 | 
				
			||||||
    dbus_message_unref(m);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Run from main thread */
 | 
					/* Run from main thread */
 | 
				
			||||||
static void source_set_volume_cb(pa_source *s) {
 | 
					static void source_set_volume_cb(pa_source *s) {
 | 
				
			||||||
    DBusMessage *m;
 | 
					 | 
				
			||||||
    dbus_uint16_t gain;
 | 
					    dbus_uint16_t gain;
 | 
				
			||||||
    pa_volume_t volume;
 | 
					    pa_volume_t volume;
 | 
				
			||||||
    struct userdata *u;
 | 
					    struct userdata *u;
 | 
				
			||||||
| 
						 | 
					@ -1479,16 +1452,14 @@ static void source_set_volume_cb(pa_source *s) {
 | 
				
			||||||
    pa_assert(u);
 | 
					    pa_assert(u);
 | 
				
			||||||
    pa_assert(u->source == s);
 | 
					    pa_assert(u->source == s);
 | 
				
			||||||
    pa_assert(u->profile == PROFILE_HSP);
 | 
					    pa_assert(u->profile == PROFILE_HSP);
 | 
				
			||||||
 | 
					    pa_assert(u->transport);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    gain = (dbus_uint16_t) round((double) pa_cvolume_max(&s->real_volume) * HSP_MAX_GAIN / PA_VOLUME_NORM);
 | 
					    gain = (dbus_uint16_t) round((double) pa_cvolume_max(&s->real_volume) * HSP_MAX_GAIN / PA_VOLUME_NORM);
 | 
				
			||||||
    volume = (pa_volume_t) round((double) gain * PA_VOLUME_NORM / HSP_MAX_GAIN);
 | 
					    volume = (pa_volume_t) round((double) gain * PA_VOLUME_NORM / HSP_MAX_GAIN);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pa_cvolume_set(&s->real_volume, u->sample_spec.channels, volume);
 | 
					    pa_cvolume_set(&s->real_volume, u->sample_spec.channels, volume);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pa_assert_se(m = dbus_message_new_method_call("org.bluez", u->path, "org.bluez.Headset", "SetMicrophoneGain"));
 | 
					    pa_bluetooth_transport_set_microphone_gain(u->transport, gain);
 | 
				
			||||||
    pa_assert_se(dbus_message_append_args(m, DBUS_TYPE_UINT16, &gain, DBUS_TYPE_INVALID));
 | 
					 | 
				
			||||||
    pa_assert_se(dbus_connection_send(pa_dbus_connection_get(u->connection), m, NULL));
 | 
					 | 
				
			||||||
    dbus_message_unref(m);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Run from main thread */
 | 
					/* Run from main thread */
 | 
				
			||||||
| 
						 | 
					@ -1594,6 +1565,43 @@ static pa_hook_result_t transport_nrec_changed_cb(pa_bluetooth_discovery *y, pa_
 | 
				
			||||||
    return PA_HOOK_OK;
 | 
					    return PA_HOOK_OK;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static pa_hook_result_t transport_microphone_gain_changed_cb(pa_bluetooth_discovery *y, pa_bluetooth_transport *t,
 | 
				
			||||||
 | 
					                                                             struct userdata *u) {
 | 
				
			||||||
 | 
					    pa_cvolume v;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pa_assert(t);
 | 
				
			||||||
 | 
					    pa_assert(u);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (t != u->transport)
 | 
				
			||||||
 | 
					        return PA_HOOK_OK;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pa_assert(u->source);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pa_cvolume_set(&v, u->sample_spec.channels,
 | 
				
			||||||
 | 
					                   (pa_volume_t) round((double) t->microphone_gain * PA_VOLUME_NORM / HSP_MAX_GAIN));
 | 
				
			||||||
 | 
					    pa_source_volume_changed(u->source, &v);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return PA_HOOK_OK;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static pa_hook_result_t transport_speaker_gain_changed_cb(pa_bluetooth_discovery *y, pa_bluetooth_transport *t,
 | 
				
			||||||
 | 
					                                                          struct userdata *u) {
 | 
				
			||||||
 | 
					    pa_cvolume v;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pa_assert(t);
 | 
				
			||||||
 | 
					    pa_assert(u);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (t != u->transport)
 | 
				
			||||||
 | 
					        return PA_HOOK_OK;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pa_assert(u->sink);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pa_cvolume_set(&v, u->sample_spec.channels, (pa_volume_t) round((double) t->speaker_gain * PA_VOLUME_NORM / HSP_MAX_GAIN));
 | 
				
			||||||
 | 
					    pa_sink_volume_changed(u->sink, &v);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return PA_HOOK_OK;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void connect_ports(struct userdata *u, void *sink_or_source_new_data, pa_direction_t direction) {
 | 
					static void connect_ports(struct userdata *u, void *sink_or_source_new_data, pa_direction_t direction) {
 | 
				
			||||||
    union {
 | 
					    union {
 | 
				
			||||||
        pa_sink_new_data *sink_new_data;
 | 
					        pa_sink_new_data *sink_new_data;
 | 
				
			||||||
| 
						 | 
					@ -2633,6 +2641,14 @@ int pa__init(pa_module* m) {
 | 
				
			||||||
        pa_hook_connect(pa_bluetooth_discovery_hook(u->discovery, PA_BLUETOOTH_HOOK_TRANSPORT_NREC_CHANGED),
 | 
					        pa_hook_connect(pa_bluetooth_discovery_hook(u->discovery, PA_BLUETOOTH_HOOK_TRANSPORT_NREC_CHANGED),
 | 
				
			||||||
                        PA_HOOK_NORMAL, (pa_hook_cb_t) transport_nrec_changed_cb, u);
 | 
					                        PA_HOOK_NORMAL, (pa_hook_cb_t) transport_nrec_changed_cb, u);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    u->transport_microphone_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_speaker_changed_slot =
 | 
				
			||||||
 | 
					        pa_hook_connect(pa_bluetooth_discovery_hook(u->discovery, PA_BLUETOOTH_HOOK_TRANSPORT_SPEAKER_GAIN_CHANGED),
 | 
				
			||||||
 | 
					                        PA_HOOK_NORMAL, (pa_hook_cb_t) transport_speaker_gain_changed_cb, u);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Add the card structure. This will also initialize the default profile */
 | 
					    /* Add the card structure. This will also initialize the default profile */
 | 
				
			||||||
    if (add_card(u) < 0)
 | 
					    if (add_card(u) < 0)
 | 
				
			||||||
        goto fail;
 | 
					        goto fail;
 | 
				
			||||||
| 
						 | 
					@ -2738,6 +2754,12 @@ void pa__done(pa_module *m) {
 | 
				
			||||||
    if (u->transport_nrec_changed_slot)
 | 
					    if (u->transport_nrec_changed_slot)
 | 
				
			||||||
        pa_hook_slot_free(u->transport_nrec_changed_slot);
 | 
					        pa_hook_slot_free(u->transport_nrec_changed_slot);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (u->transport_microphone_changed_slot)
 | 
				
			||||||
 | 
					        pa_hook_slot_free(u->transport_microphone_changed_slot);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (u->transport_speaker_changed_slot)
 | 
				
			||||||
 | 
					        pa_hook_slot_free(u->transport_speaker_changed_slot);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (USE_SCO_OVER_PCM(u))
 | 
					    if (USE_SCO_OVER_PCM(u))
 | 
				
			||||||
        restore_sco_volume_callbacks(u);
 | 
					        restore_sco_volume_callbacks(u);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue