Bluez.BlueAlsa (bluez v0.1.0)

Copy Markdown View Source

Persistent rebus D-Bus client to org.bluealsa (the bluez-alsa bluealsad daemon), used to learn which A2DP-playback PCMs are ready to open right now. This is the control-plane half of the Bluetooth-headphone audio path; the data plane is sendspin opening the ALSA PCM string directly.

pcms/0 returns, for every connected A2DP headset, what a host needs to open (or surface) its playback PCM:

%{
  mac: "AA:BB:CC:DD:EE:FF",
  pcm_path: "/org/bluealsa/hci0/dev_.../a2dpsrc/sink",
  alsa_string: "bluealsa:DEV=AA:BB:CC:DD:EE:FF,PROFILE=a2dp",
  alias: "WH-1000XM4"   # org.bluez Device1.Alias, falls back to the MAC
}

Connection, not the daemon

This client connects to the system bus (owned by dbus-daemon, the first child of Bluez), not to bluealsad. So it comes up whether or not bluealsad has claimed org.bluealsa yet; the GetManagedObjects call simply errors (→ []) until the daemon is up, and starts returning PCMs once a headset connects. It survives a bluealsad restart without reconnecting.

PCM enumeration (bluez-alsa v4 API)

PCMs are discovered via the freedesktop ObjectManager at /org/bluealsa (each connected A2DP playback PCM is an org.bluealsa.PCM1 object), not the v3 org.bluealsa.Manager1.GetPCMs method — buildroot ships bluez-alsa 4.x, where that method no longer exists (it returns UnknownMethod, which the error path would silently swallow into []).

Inert off-target / when not started

The Bluez subtree only runs on the BT targets, so on host/CI this GenServer isn't started. pcms/0 catches the :exit from calling a non-existent process and returns [], mirroring the exit-safe pattern used elsewhere in the Bluez layer — callers stay inert.

Enrichment with the device Alias is a best-effort org.bluez Properties.Get on the same connection (BlueAlsa already proves D-Bus is reachable); a failed Alias lookup falls back to the MAC, never raises.

Summary

Functions

Returns a specification to start this module under a supervisor.

Connected A2DP-playback PCMs as a list of maps (see the moduledoc). [] when the daemon is down, no headset is connected, or this client isn't running.

PubSub topic broadcast when the BlueALSA PCM set changes.

Functions

child_spec(init_arg)

Returns a specification to start this module under a supervisor.

See Supervisor.

pcms()

@spec pcms() :: [
  %{
    mac: String.t(),
    pcm_path: String.t(),
    alsa_string: String.t(),
    alias: String.t()
  }
]

Connected A2DP-playback PCMs as a list of maps (see the moduledoc). [] when the daemon is down, no headset is connected, or this client isn't running.

pcms_topic()

@spec pcms_topic() :: String.t()

PubSub topic broadcast when the BlueALSA PCM set changes.

start_link(opts \\ [])