From: Eluminae <Eluminae@users.noreply.github.com>
To: ml@inbox.vuxu.org
Subject: [PR PATCH] New package: bluez-alsa-bmix-1.0.0
Date: Sat, 10 Oct 2020 13:21:05 +0200 [thread overview]
Message-ID: <gh-mailinglist-notifications-41a7ca26-5023-4802-975b-f1789d68868e-void-packages-25489@inbox.vuxu.org> (raw)
[-- Attachment #1: Type: text/plain, Size: 329 bytes --]
There is a new pull request by Eluminae against master on the void-packages repository
https://github.com/Eluminae/void-packages bluez-alsa-bmix
https://github.com/void-linux/void-packages/pull/25489
New package: bluez-alsa-bmix-1.0.0
A patch file from https://github.com/void-linux/void-packages/pull/25489.patch is attached
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: github-pr-bluez-alsa-bmix-25489.patch --]
[-- Type: text/x-diff, Size: 14998 bytes --]
From aeeba9729b463a54dee8ab083903d5fa1d969824 Mon Sep 17 00:00:00 2001
From: Reed Wade <reedwade@misterbanal.net>
Date: Sat, 10 Oct 2020 13:03:48 +0200
Subject: [PATCH] New package: bluez-alsa-bmix-1.0.0
---
srcpkgs/bluez-alsa-bmix/INSTALL | 10 +
srcpkgs/bluez-alsa-bmix/REMOVE | 4 +
srcpkgs/bluez-alsa-bmix/files/21-bmix.conf | 130 ++++++++
srcpkgs/bluez-alsa-bmix/files/bluez-bmix/run | 5 +
srcpkgs/bluez-alsa-bmix/files/bmix.conf | 15 +
srcpkgs/bluez-alsa-bmix/files/bmixd.bash | 329 +++++++++++++++++++
srcpkgs/bluez-alsa-bmix/template | 20 ++
7 files changed, 513 insertions(+)
create mode 100644 srcpkgs/bluez-alsa-bmix/INSTALL
create mode 100644 srcpkgs/bluez-alsa-bmix/REMOVE
create mode 100644 srcpkgs/bluez-alsa-bmix/files/21-bmix.conf
create mode 100755 srcpkgs/bluez-alsa-bmix/files/bluez-bmix/run
create mode 100644 srcpkgs/bluez-alsa-bmix/files/bmix.conf
create mode 100644 srcpkgs/bluez-alsa-bmix/files/bmixd.bash
create mode 100644 srcpkgs/bluez-alsa-bmix/template
diff --git a/srcpkgs/bluez-alsa-bmix/INSTALL b/srcpkgs/bluez-alsa-bmix/INSTALL
new file mode 100644
index 00000000000..2427aba1848
--- /dev/null
+++ b/srcpkgs/bluez-alsa-bmix/INSTALL
@@ -0,0 +1,10 @@
+# INSTALL
+case "$ACTION" in
+post)
+ if [ ! -d "/var/lib/bmix" ]; then
+ mkdir "/var/lib/bmix"
+ touch "/var/lib/bmix/bmix.conf"
+ chmod 660 "/var/lib/bmix/bmix.conf"
+ chown -R _bluez_bmix:audio "/var/lib/bmix"
+ fi
+esac
diff --git a/srcpkgs/bluez-alsa-bmix/REMOVE b/srcpkgs/bluez-alsa-bmix/REMOVE
new file mode 100644
index 00000000000..532ccd92661
--- /dev/null
+++ b/srcpkgs/bluez-alsa-bmix/REMOVE
@@ -0,0 +1,4 @@
+# REMOVE
+if [ -d "/var/lib/bmix" ]; then
+ rm -r "/var/lib/bmix"
+fi
diff --git a/srcpkgs/bluez-alsa-bmix/files/21-bmix.conf b/srcpkgs/bluez-alsa-bmix/files/21-bmix.conf
new file mode 100644
index 00000000000..bf75f9b5155
--- /dev/null
+++ b/srcpkgs/bluez-alsa-bmix/files/21-bmix.conf
@@ -0,0 +1,130 @@
+pcm.bluealsa_raw {
+ @args [ DEV PROFILE DELAY SRV ]
+ @args.DEV {
+ type string
+ default {
+ @func refer
+ name defaults.bluealsa.device
+ }
+ }
+ @args.PROFILE {
+ type string
+ default {
+ @func refer
+ name defaults.bluealsa.profile
+ }
+ }
+ @args.DELAY {
+ type integer
+ default {
+ @func refer
+ name defaults.bluealsa.delay
+ }
+ }
+ @args.SRV {
+ type string
+ default {
+ @func refer
+ name defaults.bluealsa.service
+ }
+ }
+ type bluealsa
+ device $DEV
+ profile $PROFILE
+ delay $DELAY
+ service $SRV
+}
+
+defaults.bmix {
+ loop 0
+ channels 2
+ rate 48000
+ period 20000
+}
+
+pcm.bmix {
+ @args [ IPC_KEY LOOP CHANNELS RATE PERIOD ]
+ @args.IPC_KEY {
+ type integer
+ }
+ @args.LOOP {
+ type integer
+ default {
+ @func refer
+ name defaults.bmix.loop
+ }
+ }
+ @args.CHANNELS {
+ type integer
+ default {
+ @func refer
+ name defaults.bmix.channels
+ }
+ }
+ @args.RATE {
+ type integer
+ default {
+ @func refer
+ name defaults.bmix.rate
+ }
+ }
+ @args.PERIOD {
+ type integer
+ default {
+ @func refer
+ name defaults.bmix.period
+ }
+ }
+ type plug
+ slave {
+ pcm {
+ type dmix
+ ipc_key $IPC_KEY
+ ipc_perm 0660
+ ipc_gid audio
+ slave {
+ channels $CHANNELS
+ pcm {
+ type hw
+ card "Loopback"
+ device 0
+ subdevice $LOOP
+ format "s16_le"
+ rate $RATE
+ }
+ period_time $PERIOD
+ }
+ }
+ }
+ hint {
+ show {
+ @func refer
+ name defaults.namehint.basic
+ }
+ description "Bluetooth Audio - Mix Multiple Streams"
+ }
+}
+
+ctl.bmix {
+ @args [ SRV BAT ]
+ @args.SRV {
+ type string
+ default {
+ @func refer
+ name defaults.bluealsa.service
+ }
+ }
+ @args.BAT {
+ type string
+ default {
+ @func refer
+ name defaults.bluealsa.battery
+ }
+ }
+ type bluealsa
+ service $SRV
+ battery $BAT
+}
+
+</var/lib/bmix/bmix.conf>
+
diff --git a/srcpkgs/bluez-alsa-bmix/files/bluez-bmix/run b/srcpkgs/bluez-alsa-bmix/files/bluez-bmix/run
new file mode 100755
index 00000000000..42b12f908dd
--- /dev/null
+++ b/srcpkgs/bluez-alsa-bmix/files/bluez-bmix/run
@@ -0,0 +1,5 @@
+#!/bin/sh
+[ -r ./conf ] && . ./conf
+
+exec chpst -u _bluez_bmix:audio /bin/bmixd
+
diff --git a/srcpkgs/bluez-alsa-bmix/files/bmix.conf b/srcpkgs/bluez-alsa-bmix/files/bmix.conf
new file mode 100644
index 00000000000..4aa3b79f35c
--- /dev/null
+++ b/srcpkgs/bluez-alsa-bmix/files/bmix.conf
@@ -0,0 +1,15 @@
+<!-- This configuration file specifies the required security policies
+ for bmix bluealsa helper daemon to work. -->
+
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+<busconfig>
+
+ <!-- ../system.conf have denied everything, so we just punch some holes -->
+
+ <policy user="bmix">
+ <allow send_destination="org.bluez"/>
+ </policy>
+
+</busconfig>
+
diff --git a/srcpkgs/bluez-alsa-bmix/files/bmixd.bash b/srcpkgs/bluez-alsa-bmix/files/bmixd.bash
new file mode 100644
index 00000000000..bc4d2130653
--- /dev/null
+++ b/srcpkgs/bluez-alsa-bmix/files/bmixd.bash
@@ -0,0 +1,329 @@
+#!/bin/bash
+
+# revision 0.2
+
+
+# select which profile types to use: "a2dp", "sco", or "all"
+profiles="${BMIX_PROFILE:-all}"
+
+# d-bus service name for bluealsa
+servicename="${BMIX_BLUEALSA_SRV:-org.bluealsa}"
+
+# experiment with higher latency if you experience underruns/overruns
+latency="${BMIX_LATENCY:-50000}"
+
+# location of dynamic alsa configuration file
+conffile="${BMIX_ALSA_CONF:-/var/lib/bmix/bmix.conf}"
+
+# dmix ipc will use 8 consecutive ipc key numbers starting with this value
+ipc_key_start=${BMIX_IPC_KEY:-30000}
+
+# to reserve some Loopback substreams for other applications, set the lowest
+# substream to use here:
+lowest_loop_substream=${BMIX_LOOPBACK:-0}
+
+# name to use for default bluetooth pcm
+default_pcm_name="${BMIX_DEFAULT_PCM_NAME:-bluetooth}"
+
+# extra arguments to apply to alsaloop
+alsaloop_args="${BMIX_ALSALOOP_ARGS:---sync=none}"
+
+
+ALSALOOP="alsaloop $alsaloop_args"
+
+
+awk_parse_dbus_message='
+ /member=PCMAdded/ { added = 1; next; }
+ /member=PCMRemoved/ { removed = 1; next; }
+ /member=NameOwnerChanged/ { printf("ServiceStopped\n"); fflush(); next; }
+ !/variant/ && /object path/ {
+ match($0, /dev_([[:xdigit:]_]+)\/(a2dp|hfp|hsp)(.*)/, arr)
+ if (RSTART > 0) {
+ brackets = 0
+ addr = arr[1]
+ if (removed) {
+ if (arr[2] ~ /hfp|hsp/)
+ profile = "SCO"
+ else if (arr[2] ~ a2dp)
+ profile = "A2DP"
+ else
+ next
+ if (arr[3] ~ /source/)
+ printf("PCMRemoved %s %s %s\n", addr, profile, "source")
+ else if (arr[3] ~ /sink/)
+ printf("PCMRemoved %s %s %s\n", addr, profile, "sink")
+ else
+ next
+ fflush()
+ removed = 0
+ next
+ }
+ profile = ""
+ mode = ""
+ format = ""
+ channels = ""
+ sampling = ""
+ next
+ }
+ }
+ /string "Transport"/ { t = 1; next; }
+ /string "Mode/ { m = 1; next; }
+ /string "Format"/ { f = 1; next; }
+ /string "Channels"/ { c = 1; next; }
+ /string "Sampling"/ { s = 1; next; }
+ t && /A2DP/ { profile = "A2DP"; t = 0; next; }
+ t && /HFP|HSP/ { profile = "SCO"; t = 0; next; }
+ m && /string/ {
+ sub(/^.*string /,"")
+ gsub("\"","")
+ mode = $0
+ next
+ }
+ f && /uint16/ { format = $NF; f = 0; next; }
+ c && /byte/ { channels = $NF; c = 0; next; }
+ s && /uint32/ { sampling = $NF; s = 0; next; }
+ m && /)/ { m = 0; next; }
+ t && /)/ { t = 0; next; }
+ f && /)/ { f = 0; next; }
+ c && /)/ { c = 0; next; }
+ s && /)/ { s = 0; next; }
+ /\[/ { brackets++; next; }
+ addr && /]/ && (--brackets == 0) {
+ if (addr && profile && mode && format && channels && sampling) {
+ if (added)
+ printf("PCMAdded ")
+ printf("%s %s %s %s %s %s\n", addr, profile, mode, format, channels, sampling)
+ fflush()
+ added = 0
+ }
+ }
+'
+
+declare -A formats
+formats[264]=U8
+formats[33296]=S16_LE
+formats[33560]=S24_3LE
+formats[33816]=S24_LE
+formats[33824]=S32_LE
+formats[8]=U8 # pre bluealsa v3.0.0
+formats[32784]=S16_LE # pre bluealsa v3.0.0
+formats[32792]=S24_LE # pre bluealsa v3.0.0
+
+declare -A select_profile
+select_profile[A2DP]=yes
+select_profile[SCO]=yes
+
+profiles=${profiles^^?}
+if [[ "$profiles" = SCO ]] ; then
+ select_profile[A2DP]=no
+elif [[ "$profiles" = A2DP ]] ; then
+ select_profile[SCO]=no
+fi
+
+declare -A pids
+declare -A loops
+declare -A name
+
+declare default_devid=""
+
+declare -i first_loop="$lowest_loop_substream"
+declare -i num_loops=$(grep -c substream /proc/asound/Loopback/cable\#0)
+
+get_loop_by_devid() {
+ declare -n result=$1
+ declare devid="$2"
+ declare i
+ result=""
+ for i in "${!loops[@]}" ; do
+ if [[ "$i" = "$devid" ]] ; then
+ result=${loops[$i]}
+ break
+ fi
+ done
+ if [[ -z "$result" ]] ; then
+ declare -i next_loop=$((first_loop + ${#loops[@]}))
+ if [[ $next_loop -lt $num_loops ]] ; then
+ loops["$devid"]=$next_loop
+ result=$next_loop
+ fi
+ fi
+}
+
+launch_alsaloop() {
+ # arg1 devid
+ # arg2 loop
+ # arg3 addr
+ # arg4 profile
+ # arg5 format
+ # arg6 channels
+ # arg7 sample rate
+ declare devid="$1" loop=$2 addr="$3" profile="$4" format="$5" channels=$6 rate=$7 pid
+
+ $ALSALOOP -f "$format" -c "$channels" -r "$rate" -C hw:Loopback,1,$loop -P bluealsa_raw:SRV="$servicename",DEV="$addr",PROFILE="$profile",DELAY=0 -t "$latency" >/dev/null 2>&1 &
+ pid=$!
+ sleep 1
+ if ! kill -0 $pid >/dev/null 2>&1; then
+ echo "failed to start alsaloop for $addr ($profile)" >&2
+ return 1
+ fi
+ pids["$devid"]=$pid
+}
+
+create_alsa_config() {
+ # arg1 device id
+ # arg2 device alias
+ # arg3 profile
+ # arg4 channels
+ # arg5 rate
+ declare devid="$1" dev_alias="$2" profile="$3"
+ declare -i channels=$4 rate=$5
+ declare -i ipc_key=$((ipc_key_start + loops[$devid]))
+ declare loop
+
+ cat >> "$conffile" <<-EOF
+ pcm."${name[$devid]}".type empty
+ pcm."${name[$devid]}".slave.pcm "bmix:IPC_KEY=${ipc_key},LOOP=${loops[$devid]},CHANNELS=${channels},RATE=${rate},PERIOD=$(($latency / 2))"
+ pcm."${name[$devid]}".hint.show.@func refer
+ pcm."${name[$devid]}".hint.show.name defaults.namehint.basic
+ pcm."${name[$devid]}".hint.description "$dev_alias ($profile) Bluetooth Audio Playback"
+ EOF
+}
+
+# get device alias from Bluez
+get_alias() {
+ # arg1 name of variable to store result
+ # arg2 addr (underscored)
+ declare -n result="$1"
+ result=$(dbus-send --print-reply=literal --system --dest=org.bluez \
+ /org/bluez/hci0/dev_$2 \
+ org.freedesktop.DBus.Properties.Get string:"org.bluez.Device1" string:"Alias")
+ result=${result# variant }
+}
+
+add_pcm() {
+ # arg1 addr (underscored)
+ # arg2 profile
+ # arg3 format
+ # arg4 channels
+ # arg5 sample rate
+ declare devid="$1,$2" profile="$2" format=${formats["$3"]} addr="${1//_/:}"
+ declare -i channels=$4 rate=$5
+ declare loop dev_alias
+
+ get_alias dev_alias "$1"
+ [[ -n "$dev_alias" ]] || return 1
+
+ get_loop_by_devid loop $devid
+
+ if [[ -z "$loop" ]] ; then
+ echo "No free Loopback substreams" >&2
+ return 1
+ fi
+ launch_alsaloop "$devid" "$loop" "$addr" "$profile" "$format" "$channels" "$rate" \
+ || return 1
+ name["$devid"]="$dev_alias - $profile"
+ create_alsa_config "$devid" "$dev_alias" "$profile" "$channels" "$rate"
+}
+
+remove_pcm() {
+ #arg1 devid
+ declare devid="$1"
+ sed -i '/^pcm."'"${name["$devid"]}"'/d' "$conffile"
+ kill "${pids["$devid"]}" 2>/dev/null
+ unset pids["$devid"]
+ unset name["$devid"]
+}
+
+# make sure default name is alias for pcm that is currently connected
+update_default() {
+ for devid in "${!name[@]}" ; do
+ [[ "$devid" = "$default_devid" ]] && return
+ done
+ declare -a arr=("${!name[@]}")
+ default_devid="${arr[0]}"
+ sed -i -e '/^pcm."'"$default_pcm_name"'/d' "$conffile" 2>/dev/null
+ if [[ -n "$default_devid" ]] ; then
+ cat >> "$conffile" <<-EOF
+ pcm."$default_pcm_name".type empty
+ pcm."$default_pcm_name".slave.pcm "${name[$default_devid]}"
+ pcm."$default_pcm_name".hint.show.@func refer
+ pcm."$default_pcm_name".hint.show.name defaults.namehint.basic
+ pcm."$default_pcm_name".hint.description "Default bluetooth playback"
+ EOF
+ fi
+}
+
+# get list of connected devices
+get_devices() {
+ dbus-send --print-reply --system --dest=org.bluealsa \
+ /org/bluealsa org.bluealsa.Manager1.GetPCMs 2>/dev/null | gawk "$awk_parse_dbus_message"
+}
+
+handle_device_added_event() {
+ if [[ "$4" = sink && "${select_profile["$3"]}" = yes ]] ; then
+ add_pcm "$2" "$3" "$5" "$6" "$7"
+ update_default
+ fi
+}
+
+handle_device_removed_event() {
+ if [[ "$4" = sink ]] ; then
+ remove_pcm "$2,$3"
+ update_default
+ fi
+}
+
+add_initial_devices() {
+ readarray -t devices < <(get_devices)
+ for device in "${devices[@]}" ; do
+ params=($device)
+ if [[ "${params[2]}" = sink && "${select_profile["${params[1]}"]}" = yes ]] ; then
+ add_pcm "${params[0]}" "${params[1]}" "${params[3]}" "${params[4]}" "${params[5]}"
+ fi
+ done
+ update_default
+}
+
+# remove all pcms if bluealsa service terminates
+handle_service_stopped_event() {
+ for pcm in "${!name[@]}" ; do
+ remove_pcm "$pcm"
+ done
+ update_default
+}
+
+# delete all stale entries from alsa config file
+echo "# DO NOT DELETE, DO NOT EDIT - automatically managed by bmixd" > "$conffile"
+
+# create a temporary named pipe to communicate with dbus monitor
+PIPE=$(mktemp -u)
+mkfifo $PIPE
+# attach it to unused file descriptor FD
+exec {FD}<>$PIPE
+# unlink the named pipe
+rm $PIPE
+
+# make sure the pipeline is shut down if this script interrupted
+trap "kill %1; exec {FD}>&-; handle_service_stopped_event; exit 0" INT TERM
+
+# start dbus monitor in background
+dbus-monitor --system "type='signal',sender='org.bluealsa',interface='org.bluealsa.Manager1'" "sender='org.freedesktop.DBus',member='NameOwnerChanged',arg0='org.bluealsa',arg2=''" 2>/dev/null | gawk "$awk_parse_dbus_message" >&$FD &
+
+# load initial set of connected devices
+add_initial_devices
+
+# now listen for dbus signals
+while read
+do
+ case "$REPLY" in
+ PCMAdded*)
+ handle_device_added_event $REPLY
+ ;;
+ PCMRemoved*)
+ handle_device_removed_event $REPLY
+ ;;
+ ServiceStopped*)
+ handle_service_stopped_event
+ ;;
+ esac
+done <&$FD
diff --git a/srcpkgs/bluez-alsa-bmix/template b/srcpkgs/bluez-alsa-bmix/template
new file mode 100644
index 00000000000..97f6c6231cc
--- /dev/null
+++ b/srcpkgs/bluez-alsa-bmix/template
@@ -0,0 +1,20 @@
+# Template file for 'bluez-alsa-bmix'
+pkgname=bluez-alsa-bmix
+version=1.0.0
+revision=1
+build_style=meta
+short_desc="Bluetooth Audio ALSA Backend - bmix daemon"
+depends="bluez-alsa"
+maintainer="Stacy Harper <conctact@stacyharper.net>"
+license="MIT"
+homepage="https://github.com/Arkq/bluez-alsa/wiki/Using-bluealsa-with-dmix"
+system_accounts="_bluez_bmix"
+_bluez_bmix_groups="audio"
+_bluez_bmix_homedir="/var/lib/bmix/"
+
+do_install() {
+ vinstall ${FILESDIR}/21-bmix.conf 644 /etc/alsa/conf.d
+ vinstall ${FILESDIR}/bmix.conf 644 /etc/dbus-1/system.d
+ vbin ${FILESDIR}/bmixd.bash bmixd
+ vsv bluez-bmix
+}
next reply other threads:[~2020-10-10 11:21 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-10-10 11:21 Eluminae [this message]
2020-10-10 11:22 ` Eluminae
2020-10-10 11:25 ` [PR PATCH] [Updated] " Eluminae
2022-04-20 2:15 ` github-actions
2022-05-04 2:15 ` [PR PATCH] [Closed]: " github-actions
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=gh-mailinglist-notifications-41a7ca26-5023-4802-975b-f1789d68868e-void-packages-25489@inbox.vuxu.org \
--to=eluminae@users.noreply.github.com \
--cc=ml@inbox.vuxu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).