Github messages for voidlinux
 help / color / mirror / Atom feed
* [PR PATCH] New package: bluez-alsa-bmix-1.0.0
@ 2020-10-10 11:21 Eluminae
  2020-10-10 11:22 ` Eluminae
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Eluminae @ 2020-10-10 11:21 UTC (permalink / raw)
  To: ml

[-- 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
+}

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: New package: bluez-alsa-bmix-1.0.0
  2020-10-10 11:21 [PR PATCH] New package: bluez-alsa-bmix-1.0.0 Eluminae
@ 2020-10-10 11:22 ` Eluminae
  2020-10-10 11:25 ` [PR PATCH] [Updated] " Eluminae
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Eluminae @ 2020-10-10 11:22 UTC (permalink / raw)
  To: ml

[-- Attachment #1: Type: text/plain, Size: 218 bytes --]

New comment by Eluminae on void-packages repository

https://github.com/void-linux/void-packages/pull/25489#issuecomment-706533334

Comment:
I'm not really sure about the way I packaged this. Feels free to guide me :D

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PR PATCH] [Updated] New package: bluez-alsa-bmix-1.0.0
  2020-10-10 11:21 [PR PATCH] New package: bluez-alsa-bmix-1.0.0 Eluminae
  2020-10-10 11:22 ` Eluminae
@ 2020-10-10 11:25 ` Eluminae
  2022-04-20  2:15 ` github-actions
  2022-05-04  2:15 ` [PR PATCH] [Closed]: " github-actions
  3 siblings, 0 replies; 5+ messages in thread
From: Eluminae @ 2020-10-10 11:25 UTC (permalink / raw)
  To: ml

[-- Attachment #1: Type: text/plain, Size: 334 bytes --]

There is an updated 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: 15008 bytes --]

From 2740007da498faec658f82f6943bd462dc17684f 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     | 330 +++++++++++++++++++
 srcpkgs/bluez-alsa-bmix/template             |  20 ++
 7 files changed, 514 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..7cfc466d20e
--- /dev/null
+++ b/srcpkgs/bluez-alsa-bmix/files/bmixd.bash
@@ -0,0 +1,330 @@
+#!/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
+
+	sleep 2
+	$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
+}

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: New package: bluez-alsa-bmix-1.0.0
  2020-10-10 11:21 [PR PATCH] New package: bluez-alsa-bmix-1.0.0 Eluminae
  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
  3 siblings, 0 replies; 5+ messages in thread
From: github-actions @ 2022-04-20  2:15 UTC (permalink / raw)
  To: ml

[-- Attachment #1: Type: text/plain, Size: 305 bytes --]

New comment by github-actions[bot] on void-packages repository

https://github.com/void-linux/void-packages/pull/25489#issuecomment-1103384992

Comment:
Pull Requests become stale 90 days after last activity and are closed 14 days after that.  If this pull request is still relevant bump it or assign it.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PR PATCH] [Closed]: New package: bluez-alsa-bmix-1.0.0
  2020-10-10 11:21 [PR PATCH] New package: bluez-alsa-bmix-1.0.0 Eluminae
                   ` (2 preceding siblings ...)
  2022-04-20  2:15 ` github-actions
@ 2022-05-04  2:15 ` github-actions
  3 siblings, 0 replies; 5+ messages in thread
From: github-actions @ 2022-05-04  2:15 UTC (permalink / raw)
  To: ml

[-- Attachment #1: Type: text/plain, Size: 168 bytes --]

There's a closed pull request on the void-packages repository

New package: bluez-alsa-bmix-1.0.0
https://github.com/void-linux/void-packages/pull/25489

Description:


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2022-05-04  2:15 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-10-10 11:21 [PR PATCH] New package: bluez-alsa-bmix-1.0.0 Eluminae
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

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).