Skip to content

Commit 8dbd03a

Browse files
committed
Update volume when changing soft-volume property
1 parent 61adf95 commit 8dbd03a

File tree

4 files changed

+64
-15
lines changed

4 files changed

+64
-15
lines changed

src/ba-rfcomm.c

+8-8
Original file line numberDiff line numberDiff line change
@@ -440,14 +440,14 @@ static int rfcomm_handler_vgm_set_cb(struct ba_rfcomm *r, const struct bt_at *at
440440

441441
struct ba_transport * const t_sco = r->sco;
442442
struct ba_transport_pcm *pcm = &t_sco->sco.pcm_mic;
443+
const int gain = r->gain_mic = atoi(at->value);
443444
const int fd = r->fd;
444445

445446
/* skip update in case of software volume */
446447
if (pcm->soft_volume)
447448
return rfcomm_write_at(fd, AT_TYPE_RESP, NULL, "OK");
448449

449-
r->gain_mic = atoi(at->value);
450-
int level = ba_transport_pcm_volume_range_to_level(r->gain_mic, HFP_VOLUME_GAIN_MAX);
450+
int level = ba_transport_pcm_volume_range_to_level(gain, HFP_VOLUME_GAIN_MAX);
451451

452452
pthread_mutex_lock(&pcm->mutex);
453453
ba_transport_pcm_volume_set(&pcm->volume[0], &level, NULL, NULL);
@@ -467,8 +467,8 @@ static int rfcomm_handler_vgm_resp_cb(struct ba_rfcomm *r, const struct bt_at *a
467467
struct ba_transport * const t_sco = r->sco;
468468
struct ba_transport_pcm *pcm = &t_sco->sco.pcm_mic;
469469

470-
r->gain_mic = atoi(at->value);
471-
int level = ba_transport_pcm_volume_range_to_level(r->gain_mic, HFP_VOLUME_GAIN_MAX);
470+
int gain = r->gain_mic = atoi(at->value);
471+
int level = ba_transport_pcm_volume_range_to_level(gain, HFP_VOLUME_GAIN_MAX);
472472

473473
pthread_mutex_lock(&pcm->mutex);
474474
ba_transport_pcm_volume_set(&pcm->volume[0], &level, NULL, NULL);
@@ -485,14 +485,14 @@ static int rfcomm_handler_vgs_set_cb(struct ba_rfcomm *r, const struct bt_at *at
485485

486486
struct ba_transport * const t_sco = r->sco;
487487
struct ba_transport_pcm *pcm = &t_sco->sco.pcm_spk;
488+
const int gain = r->gain_spk = atoi(at->value);
488489
const int fd = r->fd;
489490

490491
/* skip update in case of software volume */
491492
if (pcm->soft_volume)
492493
return rfcomm_write_at(fd, AT_TYPE_RESP, NULL, "OK");
493494

494-
r->gain_spk = atoi(at->value);
495-
int level = ba_transport_pcm_volume_range_to_level(r->gain_spk, HFP_VOLUME_GAIN_MAX);
495+
int level = ba_transport_pcm_volume_range_to_level(gain, HFP_VOLUME_GAIN_MAX);
496496

497497
pthread_mutex_lock(&pcm->mutex);
498498
ba_transport_pcm_volume_set(&pcm->volume[0], &level, NULL, NULL);
@@ -512,8 +512,8 @@ static int rfcomm_handler_vgs_resp_cb(struct ba_rfcomm *r, const struct bt_at *a
512512
struct ba_transport * const t_sco = r->sco;
513513
struct ba_transport_pcm *pcm = &t_sco->sco.pcm_spk;
514514

515-
r->gain_spk = atoi(at->value);
516-
int level = ba_transport_pcm_volume_range_to_level(r->gain_spk, HFP_VOLUME_GAIN_MAX);
515+
int gain = r->gain_spk = atoi(at->value);
516+
int level = ba_transport_pcm_volume_range_to_level(gain, HFP_VOLUME_GAIN_MAX);
517517

518518
pthread_mutex_lock(&pcm->mutex);
519519
ba_transport_pcm_volume_set(&pcm->volume[0], &level, NULL, NULL);

src/ba-transport-pcm.c

+27
Original file line numberDiff line numberDiff line change
@@ -693,6 +693,33 @@ int ba_transport_pcm_volume_update(struct ba_transport_pcm *pcm) {
693693
return 0;
694694
}
695695

696+
/**
697+
* Get non-software PCM volume level if available. */
698+
int ba_transport_pcm_get_hardware_volume(
699+
const struct ba_transport_pcm *pcm) {
700+
701+
const struct ba_transport *t = pcm->t;
702+
703+
if (t->profile & BA_TRANSPORT_PROFILE_MASK_A2DP)
704+
return t->a2dp.volume;
705+
706+
if (t->profile & BA_TRANSPORT_PROFILE_MASK_SCO) {
707+
708+
if (t->sco.rfcomm == NULL)
709+
/* TODO: Cache volume level for oFono-based SCO */
710+
return HFP_VOLUME_GAIN_MAX;
711+
712+
if (pcm == &t->sco.pcm_spk)
713+
return t->sco.rfcomm->gain_spk;
714+
if (pcm == &t->sco.pcm_mic)
715+
return t->sco.rfcomm->gain_mic;
716+
717+
}
718+
719+
g_assert_not_reached();
720+
return 0;
721+
}
722+
696723
int ba_transport_pcm_get_delay(const struct ba_transport_pcm *pcm) {
697724

698725
const struct ba_transport *t = pcm->t;

src/ba-transport-pcm.h

+3
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,9 @@ void ba_transport_pcm_volume_set(
250250
int ba_transport_pcm_volume_update(
251251
struct ba_transport_pcm *pcm);
252252

253+
int ba_transport_pcm_get_hardware_volume(
254+
const struct ba_transport_pcm *pcm);
255+
253256
int ba_transport_pcm_get_delay(
254257
const struct ba_transport_pcm *pcm);
255258

src/bluealsa-dbus.c

+26-7
Original file line numberDiff line numberDiff line change
@@ -1023,18 +1023,38 @@ static bool bluealsa_pcm_set_property(const char *property, GVariant *value,
10231023
GError **error, void *userdata) {
10241024

10251025
struct ba_transport_pcm *pcm = userdata;
1026+
struct ba_transport *t = pcm->t;
1027+
1028+
const bool is_sco = t->profile & BA_TRANSPORT_PROFILE_MASK_SCO;
1029+
const int volume_max = is_sco ? HFP_VOLUME_GAIN_MAX : BLUEZ_A2DP_VOLUME_MAX;
10261030

10271031
if (strcmp(property, "SoftVolume") == 0) {
1028-
pcm->soft_volume = g_variant_get_boolean(value);
1029-
bluealsa_dbus_pcm_update(pcm, BA_DBUS_PCM_UPDATE_SOFT_VOLUME);
1032+
1033+
const bool soft_volume = g_variant_get_boolean(value);
1034+
1035+
/* Im case when the software volume was just enabled, set the volume level
1036+
* to the maximum. This will prevent volume change during the transition.
1037+
* In case of disabling the software volume, we will restore the hardware
1038+
* volume level, so the volume control will indicate the correct level. */
1039+
const int volume = soft_volume ? volume_max : ba_transport_pcm_get_hardware_volume(pcm);
1040+
const int level = ba_transport_pcm_volume_range_to_level(volume, volume_max);
1041+
1042+
pthread_mutex_lock(&pcm->mutex);
1043+
1044+
debug("Setting software volume: %s", soft_volume ? "true" : "false");
1045+
pcm->soft_volume = soft_volume;
1046+
1047+
for (size_t i = 0; i < pcm->channels; i++)
1048+
ba_transport_pcm_volume_set(&pcm->volume[i], &level, NULL, NULL);
1049+
1050+
pthread_mutex_unlock(&pcm->mutex);
1051+
1052+
bluealsa_dbus_pcm_update(pcm, BA_DBUS_PCM_UPDATE_SOFT_VOLUME | BA_DBUS_PCM_UPDATE_VOLUME);
10301053
return true;
10311054
}
10321055

10331056
if (strcmp(property, "Volume") == 0) {
10341057

1035-
const bool is_sco = pcm->t->profile & BA_TRANSPORT_PROFILE_MASK_SCO;
1036-
const int max = is_sco ? HFP_VOLUME_GAIN_MAX : BLUEZ_A2DP_VOLUME_MAX;
1037-
10381058
size_t channels = 0;
10391059
const uint8_t *volume = g_variant_get_fixed_array(value, &channels, sizeof(uint8_t));
10401060

@@ -1049,11 +1069,10 @@ static bool bluealsa_pcm_set_property(const char *property, GVariant *value,
10491069
for (size_t i = 0; i < channels; i++) {
10501070

10511071
const bool muted = !!(volume[i] & 0x80);
1052-
const int level = ba_transport_pcm_volume_range_to_level(volume[i] & 0x7F, max);
1072+
const int level = ba_transport_pcm_volume_range_to_level(volume[i] & 0x7F, volume_max);
10531073

10541074
debug("Setting volume [ch=%zu]: %u [%.2f dB] [%c]",
10551075
i, volume[i] & 0x7F, 0.01 * level, muted ? 'x' : ' ');
1056-
10571076
ba_transport_pcm_volume_set(&pcm->volume[i], &level, &muted, NULL);
10581077

10591078
}

0 commit comments

Comments
 (0)