Skip to content

| ARCHIVE: Using the BlueALSA ALSA pcm plugin

borine edited this page Jul 9, 2022 · 1 revision

This article documents the use of the BlueALSA PCM plugin for BlueALSA release 3.1.0 and earlier. Newer releases have additional features for the plugin, and also include documentation as a manual page (https://github.com/Arkq/bluez-alsa/blob/master/doc/bluealsa-plugins.7.rst).

Introduction

The BlueALSA ALSA PCM plugin communicates directly with the bluealsa service. It is a raw PCM communication without any conversions. It can be used to define ALSA PCMs in your own configuration file (e.g. ~/.asoundrc), or you can use the pre-defined configuration that is included in the bluez-alsa project. This wiki article gives an overview of both approaches.

Simplest usage

Possibly the most common use-case of BlueALSA is to connect one bluetooth A2DP speaker (or headphones) and send audio to it from an ALSA application. A default BlueALSA installation allows you to do this by simply using an ALSA device called bluealsa. For example:

aplay -D bluealsa music.wav

or

vlc --alsa-audio-device=bluealsa

Similarly, if you have one 'phone connected with A2DP profile, you can record from it with:

arecord -D bluealsa -f s16_le -c 2 -r 48000 recording.wav

The need to specify an audio format is a requirement of arecord, otherwise it will convert the stream to mono, 8-bit samples at 8000Hz.

To use the last connected HFP/HSP device, you will need

aplay -D bluealsa:PROFILE=sco music.wav

and similarly for capture.

In the above scenarios the PCM device bluealsa refers to the last connected bluetooth A2DP device. It uses the pre-defined bluealsa PCM, and takes advantage of the default behavior which is to use the most recently connected device. This default was introduced in bluez-alsa release 3.1.0.

If you have more than one device connected, and the one you want to use is not the last one connected (or you are using an older release of bluez-alsa), then you need to specify the device, which you can do by either defining your own PCM or by passing parameters to the predefined bluealsa PCM. See the following sections for details.

Defining bluealsa PCMs

If you need to refer to specific bluetooth devices rather than just the most recently connected, or if your version of bluez-alsa is older than 3.1.0, then you can define your own ALSA PCM. To do this, create an ALSA configuration node defining a pcm with type bluealsa. See below for a predefined parameterized pcm, also called "bluealsa", that can avoid the need for writing ALSA configurations.

The configuration node has the following fields:

pcm.name {
    type bluealsa  # Bluetooth PCM
    device STR     # Device address in format XX:XX:XX:XX:XX:XX
    profile STR    # Profile type (a2dp or sco)
    [delay INT]    # Extra delay (in frames) to be reported to the application (default 0)
    [service STR]  # D-Bus name of bluealsa service (default org.bluealsa)
}

The device and profile fields must be specified so that the plugin can select the correct bluetooth transport; delay and service are optional.

The value for device must be an actual bluetooth MAC address, device names and aliases are not valid. The "special" address 00:00:00:00:00:00 can be used here to select the most recently connected device.

Use profile "a2dp" for A2DP streams, and profile "sco" for HSP or HFP streams.

The delay option specifies a number of frames to be added to the delay value reported by the plugin to the application. It is sometimes needed when trying to synchronize the sound, for example with a video or another sound system. This is because not all bluetooth audio devices accurately report the delay (latency) from the time a frame is sent to the bluetooth controller to the time it is actually played out by the loudspeaker (or vice-versa for capture streams from microphones). The user must determine this delay by experience. Most bluetooth devices do however report a delay that is acceptable in most applications, so normally this option can be omitted - in that case no adjustment will be applied.

The service option specifies the D-Bus name used by the bluealsa service. It defaults to "org.bluealsa", which is the default used by the server, so only needs to be specified in special cases.

A simple, typical, example is to add the following to your ~/.asoundrc file (where 00:11:22:33:44:55 is the example bluetooth device address and bt-headphones is the name you have chosen to use for the pcm)

pcm.bt-headphones {
	type plug
	slave.pcm {
		type bluealsa
		device "00:11:22:33:44:55"
		profile "a2dp"
	}
}

With that definition in your ~/.asoundrc file, you can then play audio to the headphones by sending to device bt-headphones; for example:

aplay -D bt-headphones music.wav

A note on choosing a name for your pcm definition: The name pcm.bluealsa is pre-defined by the bluez-alsa installation (see next section), so should not be used as a name for your own pcm devices as doing so will most likely have unexpected or undesirable results.

The Predefined "bluealsa" PCM

As a convenience for users, the bluez-alsa project also installs a global ALSA configuration file which defines a parameterized pcm device named "bluealsa".

pcm.bluealsa is of type plug, so that it automatically converts the audio stream from/to the format required by the bluetooth device. If we compare the bluealsa plugin type with the hw plugin type, then pcm.bluealsa is analogous to pcm.plughw. You can see the bluealsa ALSA configuration file here: 20-bluealsa.conf

The pcm.bluealsa arguments map to the bluealsa plugin parameters as follows:

plugin parameter pcm.bluealsa argument name default
device DEV defaults.bluealsa.device
profile PROFILE defaults.bluealsa.profile
delay DELAY defaults.bluealsa.delay
service SRV defaults.bluealsa.service

You can refer to a bluealsa pcm without needing to create a configuration in ~/.asoundrc with:

bluealsa:DEV=00:11:22:33:44:55,PROFILE=a2dp,DELAY=0,SRV=org.bluealsa

The pre-defined configuration also provides values for all the defaults in the above table, so the above example could more simply be written as

bluealsa:DEV=00:11:22:33:44:55

The default value for device is "00:00:00:00:00:00" which selects the most recently connected device.

ALSA permits arguments to be given as positional parameters as an alternative to explicitly naming them. When using positional parameters it is important that the values are given in the correct sequence - DEV,PROFILE,DELAY,SRV.

Note - before bluez-alsa release 3.0.0, the sequence of the arguments was SRV,DEV,PROFILE,DELAY so the following positional parameter examples will not work with releases 2.1.0 and earlier.

Using positional parameters, we could also write our example as:

bluealsa:00:11:22:33:44:55,a2dp,0,org.bluealsa

or, taking advantage of the default definitions again:

bluealsa:00:11:22:33:44:55

So, without needing to create a ~/asoundrc file at all, we can send audio to the same headphones as in the example above with:

aplay -D bluealsa:00:11:22:33:44:55 music.wav

The defaults can be overridden by defining the ones you want to change in your own configuration (e.g in ~/.asoundrc.conf) for example:

defaults.bluealsa.device "00:11:22:33:44:55"
defaults.bluealsa.profile "sco"
defaults.bluealsa.delay 50
defaults.bluealsa.service "org.bluealsa"

ALSA Name Hints

Applications that follow ALSA guidelines will obtain the list of defined PCMs by using the alsa-lib "namehints" API. To make bluealsa PCMs visible via that API it is necessary to add a "hint" section to the ALSA configuration. If you have defined a new PCM, then the hint goes into the PCM configuration entry as follows:

pcm.bt-headphones {
	type plug
	slave.pcm {
		type bluealsa
		device "00:11:22:33:44:55"
		profile "a2dp"
	}
	hint {
		show on
		description "My Bluetooth headphones"
	}
}

If you are using the pre-defined bluealsa PCM, then you will need to create a "namehint" entry in your ~/.asoundrc file like this:

namehint.pcm {
	mybluealsadevice "bluealsa:DEV=00:11:22:33:44:55,PROFILE=a2dp|DESCMy Bluetooth headphones"
}

Now using aplay -L will include the following in its output:

# aplay -L
bt-headphones
    My Bluetooth headphones
#

With that hint in place, the pcm will be listed as both a Capture and Playback device. So arecord -L will also list it. That is generally OK for HFP/HSP devices, but an A2DP device most often offers only Capture (e.g. a mobile phone) or only Playback (e.g. a bluetooth speaker). It is possible to use the hint description to limit the listing to only one direction using an undocumented syntax of ALSA config files.

If the hint.description value ends with |IOIDInput the pcm will only show in listings of Capture devices; if it ends with |IOIDOutput the pcm will only show in listings of Playback devices.

So we can modify our example above to:

pcm.bt-headphones {
	type plug
	slave.pcm {
		type bluealsa
		device "00:11:22:33:44:55"
		profile "a2dp"
	}
	hint {
		show on
		description "My Bluetooth headphones|IOIDOutput"
	}
}

or

namehint.pcm {
	mybluealsadevice "bluealsa:DEV=00:11:22:33:44:55,PROFILE=a2dp|DESCMy Bluetooth headphones|IOIDOutput"
}

Now the aplay -L output will be exactly the same as before, but arecord -L will not include bt-headphones in its output.

When using the namehint.pcm method, the key (mybluealsadevice in the above example) must be unique but otherwise is not used. The first part of the value string, up to the pipe | symbol, is the string that is to be passed to ALSA applications to identify the PCM (eg with aplay -D ...). The next section, after the tag |DESC, is the description that will be presented to the user. The optional |IOID section is as described above.