mirror of
				https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
				synced 2025-11-03 09:01:50 -05:00 
			
		
		
		
	bluetooth: Move HSP gain conversions into backend-native
For the upcoming A2DP AVRCP Absolute Volume feature the code in BlueZ5 has to be generic to be reusable. Move this conversion so that it becomes possible to implement A2DP volume - which uses different values - on top without duplicating existing callback functionality. Part-of: <https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/521>
This commit is contained in:
		
							parent
							
								
									cefee393fb
								
							
						
					
					
						commit
						a575006aa8
					
				
					 3 changed files with 82 additions and 87 deletions
				
			
		| 
						 | 
				
			
			@ -36,6 +36,8 @@
 | 
			
		|||
 | 
			
		||||
#include "bluez5-util.h"
 | 
			
		||||
 | 
			
		||||
#define HSP_MAX_GAIN 15
 | 
			
		||||
 | 
			
		||||
struct pa_bluetooth_backend {
 | 
			
		||||
  pa_core *core;
 | 
			
		||||
  pa_dbus_connection *connection;
 | 
			
		||||
| 
						 | 
				
			
			@ -121,6 +123,25 @@ static uint32_t hfp_features =
 | 
			
		|||
    " </interface>"                                                     \
 | 
			
		||||
    "</node>"
 | 
			
		||||
 | 
			
		||||
static pa_volume_t hsp_gain_to_volume(uint16_t gain) {
 | 
			
		||||
    pa_volume_t volume = (pa_volume_t) (gain * PA_VOLUME_NORM / HSP_MAX_GAIN);
 | 
			
		||||
 | 
			
		||||
    /* increment volume by one to correct rounding errors */
 | 
			
		||||
    if (volume < PA_VOLUME_NORM)
 | 
			
		||||
        volume++;
 | 
			
		||||
 | 
			
		||||
    return volume;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static uint16_t volume_to_hsp_gain(pa_volume_t volume) {
 | 
			
		||||
    uint16_t gain = volume * HSP_MAX_GAIN / PA_VOLUME_NORM;
 | 
			
		||||
 | 
			
		||||
    if (gain > HSP_MAX_GAIN)
 | 
			
		||||
        gain = HSP_MAX_GAIN;
 | 
			
		||||
 | 
			
		||||
    return gain;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static pa_dbus_pending* send_and_add_to_pending(pa_bluetooth_backend *backend, DBusMessage *m,
 | 
			
		||||
        DBusPendingCallNotifyFunction func, void *call_data) {
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -516,13 +537,13 @@ static void rfcomm_io_callback(pa_mainloop_api *io, pa_io_event *e, int fd, pa_i
 | 
			
		|||
         * RING: Sent by AG to HS to notify of an incoming call. It can safely be ignored because
 | 
			
		||||
         * it does not expect a reply. */
 | 
			
		||||
        if (sscanf(buf, "AT+VGS=%d", &gain) == 1 || sscanf(buf, "\r\n+VGM=%d\r\n", &gain) == 1) {
 | 
			
		||||
            t->speaker_gain = gain;
 | 
			
		||||
            pa_hook_fire(pa_bluetooth_discovery_hook(t->device->discovery, PA_BLUETOOTH_HOOK_TRANSPORT_SPEAKER_GAIN_CHANGED), t);
 | 
			
		||||
            t->speaker_volume = hsp_gain_to_volume(gain);
 | 
			
		||||
            pa_hook_fire(pa_bluetooth_discovery_hook(t->device->discovery, PA_BLUETOOTH_HOOK_TRANSPORT_SPEAKER_VOLUME_CHANGED), t);
 | 
			
		||||
            do_reply = true;
 | 
			
		||||
 | 
			
		||||
        } else if (sscanf(buf, "AT+VGM=%d", &gain) == 1 || sscanf(buf, "\r\n+VGS=%d\r\n", &gain) == 1) {
 | 
			
		||||
            t->microphone_gain = gain;
 | 
			
		||||
            pa_hook_fire(pa_bluetooth_discovery_hook(t->device->discovery, PA_BLUETOOTH_HOOK_TRANSPORT_MICROPHONE_GAIN_CHANGED), t);
 | 
			
		||||
            t->microphone_volume = hsp_gain_to_volume(gain);
 | 
			
		||||
            pa_hook_fire(pa_bluetooth_discovery_hook(t->device->discovery, PA_BLUETOOTH_HOOK_TRANSPORT_MICROPHONE_VOLUME_CHANGED), t);
 | 
			
		||||
            do_reply = true;
 | 
			
		||||
        } else if (sscanf(buf, "AT+CKPD=%d", &dummy) == 1) {
 | 
			
		||||
            do_reply = true;
 | 
			
		||||
| 
						 | 
				
			
			@ -559,13 +580,17 @@ static void transport_destroy(pa_bluetooth_transport *t) {
 | 
			
		|||
    pa_xfree(trd);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void set_speaker_gain(pa_bluetooth_transport *t, uint16_t gain) {
 | 
			
		||||
static pa_volume_t set_speaker_volume(pa_bluetooth_transport *t, pa_volume_t volume) {
 | 
			
		||||
    struct transport_data *trd = t->userdata;
 | 
			
		||||
    uint16_t gain = volume_to_hsp_gain(volume);
 | 
			
		||||
 | 
			
		||||
    if (t->speaker_gain == gain)
 | 
			
		||||
      return;
 | 
			
		||||
    /* Propagate rounding and bound checks */
 | 
			
		||||
    volume = hsp_gain_to_volume(gain);
 | 
			
		||||
 | 
			
		||||
    t->speaker_gain = gain;
 | 
			
		||||
    if (t->speaker_volume == volume)
 | 
			
		||||
        return volume;
 | 
			
		||||
 | 
			
		||||
    t->speaker_volume = volume;
 | 
			
		||||
 | 
			
		||||
    /* If we are in the AG role, we send a command to the head set to change
 | 
			
		||||
     * the speaker gain. In the HS role, source and sink are swapped, so
 | 
			
		||||
| 
						 | 
				
			
			@ -575,15 +600,21 @@ static void set_speaker_gain(pa_bluetooth_transport *t, uint16_t gain) {
 | 
			
		|||
    } else {
 | 
			
		||||
        rfcomm_write_command(trd->rfcomm_fd, "AT+VGM=%d", gain);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return volume;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void set_microphone_gain(pa_bluetooth_transport *t, uint16_t gain) {
 | 
			
		||||
static pa_volume_t set_microphone_volume(pa_bluetooth_transport *t, pa_volume_t volume) {
 | 
			
		||||
    struct transport_data *trd = t->userdata;
 | 
			
		||||
    uint16_t gain = volume_to_hsp_gain(volume);
 | 
			
		||||
 | 
			
		||||
    if (t->microphone_gain == gain)
 | 
			
		||||
      return;
 | 
			
		||||
    /* Propagate rounding and bound checks */
 | 
			
		||||
    volume = hsp_gain_to_volume(gain);
 | 
			
		||||
 | 
			
		||||
    t->microphone_gain = gain;
 | 
			
		||||
    if (t->microphone_volume == volume)
 | 
			
		||||
        return volume;
 | 
			
		||||
 | 
			
		||||
    t->microphone_volume = volume;
 | 
			
		||||
 | 
			
		||||
    /* If we are in the AG role, we send a command to the head set to change
 | 
			
		||||
     * the microphone gain. In the HS role, source and sink are swapped, so
 | 
			
		||||
| 
						 | 
				
			
			@ -593,6 +624,8 @@ static void set_microphone_gain(pa_bluetooth_transport *t, uint16_t gain) {
 | 
			
		|||
    } else {
 | 
			
		||||
        rfcomm_write_command(trd->rfcomm_fd, "AT+VGS=%d", gain);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return volume;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static DBusMessage *profile_new_connection(DBusConnection *conn, DBusMessage *m, void *userdata) {
 | 
			
		||||
| 
						 | 
				
			
			@ -662,8 +695,8 @@ static DBusMessage *profile_new_connection(DBusConnection *conn, DBusMessage *m,
 | 
			
		|||
    t->acquire = sco_acquire_cb;
 | 
			
		||||
    t->release = sco_release_cb;
 | 
			
		||||
    t->destroy = transport_destroy;
 | 
			
		||||
    t->set_speaker_gain = set_speaker_gain;
 | 
			
		||||
    t->set_microphone_gain = set_microphone_gain;
 | 
			
		||||
    t->set_speaker_volume = set_speaker_volume;
 | 
			
		||||
    t->set_microphone_volume = set_microphone_volume;
 | 
			
		||||
 | 
			
		||||
    trd = pa_xnew0(struct transport_data, 1);
 | 
			
		||||
    trd->rfcomm_fd = fd;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue