Skip to content

Commit

Permalink
Forward BlueALSA PCM volume to user defined mixer
Browse files Browse the repository at this point in the history
This commit allows to forward PCM volume to ALSA mixer element, but
only if BlueALSA PCM does not use software volume scaling. In case of
hardware PCM for playback, audio scaling might also be performed by a
hardware component which should be more efficient.
  • Loading branch information
arkq committed Jul 27, 2021
1 parent 5bf4148 commit 7050c9a
Show file tree
Hide file tree
Showing 8 changed files with 266 additions and 23 deletions.
1 change: 1 addition & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ unreleased
- optional support for A2DP FastStream codec (music & voice)
- connection keep-alive timeout for all BT profiles
- fix for rapid consecutive SCO link close(2)/connect(2)
- bluealsa-aplay: forward PCM volume to ALSA mixer element

bluez-alsa v3.1.0 (2021-06-01)
==============================
Expand Down
16 changes: 15 additions & 1 deletion doc/bluealsa-aplay.1.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ bluealsa-aplay
a simple bluealsa player
------------------------

:Date: June 2021
:Date: July 2021
:Manual section: 1
:Manual group: General Commands Manual
:Version: $VERSION$
Expand Down Expand Up @@ -85,6 +85,20 @@ OPTIONS
effective rate is too slow). Increase the period time with this option if
this problem occurs.

-M NAME, --mixer=NAME
Select ALSA mixer device to use for controlling audio output mute state
and volume level.
In order to use this feature, BlueALSA PCM can not use software volume.
The default is ``default``.

--mixer-name=NAME
Set the name of the mixer element.
The default is ``Master``.

--mixer-index=NUM
Set the index of the mixer channel.
The default is ``0``.

--profile-a2dp
Use A2DP profile (default).

Expand Down
5 changes: 5 additions & 0 deletions src/shared/dbus-client.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@
#define BA_PCM_MODE_SOURCE (1 << 0)
#define BA_PCM_MODE_SINK (1 << 1)

/**
* Get max volume level for given PCM. */
#define BA_PCM_VOLUME_MAX(pcm) \
((pcm)->transport & BA_PCM_TRANSPORT_MASK_A2DP ? 127 : 15)

/**
* Connection context. */
struct ba_dbus_ctx {
Expand Down
3 changes: 2 additions & 1 deletion utils/aplay/Makefile.am
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# BlueALSA - Makefile.am
# Copyright (c) 2016-2020 Arkadiusz Bokowy
# Copyright (c) 2016-2021 Arkadiusz Bokowy

if ENABLE_APLAY

Expand All @@ -9,6 +9,7 @@ bluealsa_aplay_SOURCES = \
../../src/shared/dbus-client.c \
../../src/shared/ffb.c \
../../src/shared/log.c \
alsa-mixer.c \
alsa-pcm.c \
dbus.c \
aplay.c
Expand Down
62 changes: 62 additions & 0 deletions utils/aplay/alsa-mixer.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* BlueALSA - alsa-mixer.c
* Copyright (c) 2016-2021 Arkadiusz Bokowy
*
* This file is a part of bluez-alsa.
*
* This project is licensed under the terms of the MIT license.
*
*/

#include "alsa-mixer.h"

#include <stdio.h>
#include <string.h>

int alsa_mixer_open(snd_mixer_t **mixer, snd_mixer_elem_t **elem,
const char *dev_name, const char *elem_name, unsigned int elem_idx,
char **msg) {

snd_mixer_t *_mixer = NULL;
snd_mixer_elem_t *_elem;
char buf[256];
int err;

snd_mixer_selem_id_t *id;
snd_mixer_selem_id_alloca(&id);
snd_mixer_selem_id_set_name(id, elem_name);
snd_mixer_selem_id_set_index(id, elem_idx);

if ((err = snd_mixer_open(&_mixer, 0)) != 0) {
snprintf(buf, sizeof(buf), "Open mixer: %s", snd_strerror(err));
goto fail;
}
if ((err = snd_mixer_attach(_mixer, dev_name)) != 0) {
snprintf(buf, sizeof(buf), "Attach mixer: %s", snd_strerror(err));
goto fail;
}
if ((err = snd_mixer_selem_register(_mixer, NULL, NULL)) != 0) {
snprintf(buf, sizeof(buf), "Register mixer class: %s", snd_strerror(err));
goto fail;
}
if ((err = snd_mixer_load(_mixer)) != 0) {
snprintf(buf, sizeof(buf), "Load mixer elements: %s", snd_strerror(err));
goto fail;
}
if ((_elem = snd_mixer_find_selem(_mixer, id)) == NULL) {
snprintf(buf, sizeof(buf), "Mixer element not found");
err = -1;
goto fail;
}

*mixer = _mixer;
*elem = _elem;
return 0;

fail:
if (_mixer != NULL)
snd_mixer_close(_mixer);
if (msg != NULL)
*msg = strdup(buf);
return err;
}
20 changes: 20 additions & 0 deletions utils/aplay/alsa-mixer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* BlueALSA - alsa-mixer.h
* Copyright (c) 2016-2021 Arkadiusz Bokowy
*
* This file is a part of bluez-alsa.
*
* This project is licensed under the terms of the MIT license.
*
*/

#ifndef BLUEALSA_APLAY_ALSAMIXER_H_
#define BLUEALSA_APLAY_ALSAMIXER_H_

#include <alsa/asoundlib.h>

int alsa_mixer_open(snd_mixer_t **mixer, snd_mixer_elem_t **elem,
const char *dev_name, const char *elem_name, unsigned int elem_idx,
char **msg);

#endif
Loading

0 comments on commit 7050c9a

Please sign in to comment.