Skip to content

Commit

Permalink
core: refactor to remove modes
Browse files Browse the repository at this point in the history
- Sound modes removed
- Devices will now start in "standalone" mode and upgrade if possible
- Service inter-dependency removed

Change-type: major
Signed-off-by: Tomás Migone <[email protected]>
  • Loading branch information
tmigone committed Jan 26, 2022
1 parent 080e9ab commit 78c6d4f
Show file tree
Hide file tree
Showing 34 changed files with 2,321 additions and 708 deletions.
4 changes: 4 additions & 0 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

cd core/sound-supervisor && npm run pre-commit
14 changes: 6 additions & 8 deletions core/audio/balena-sound.pa
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
# See https://sound.balenalabs.io/docs/architecture for details

# Create balena-sound sinks
# Sinks
load-module module-null-sink sink_name=balena-sound.input
load-module module-null-sink sink_name=balena-sound.output
load-module module-null-sink sink_name=snapcast
load-module module-null-sink sink_name=multi-room.input

# Route audio internally, loopback sinks depend on configuration. See start.sh for details:
# balena-sound.input: For multiroom it's routed to snapcast sink, for standalone directly wired to balena-sound.output
# balena-sound.output: Set to audio sink specified by audio block
load-module module-loopback latency_msec=%INPUT_LATENCY% source="balena-sound.input.monitor" %INPUT_SINK%
load-module module-loopback latency_msec=%OUTPUT_LATENCY% source="balena-sound.output.monitor" %OUTPUT_SINK%
# Routes
load-module module-loopback latency_msec=%INPUT_LATENCY% source=balena-sound.input.monitor sink=balena-sound.output
load-module module-loopback latency_msec=%OUTPUT_LATENCY% source=balena-sound.output.monitor %OUTPUT_SINK%

# Route all plugin input to the default sink
# Defaults
set-default-sink balena-sound.input
37 changes: 1 addition & 36 deletions core/audio/start.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,30 +13,6 @@ function set_loopback_latency() {
sed -i "s/%$LOOPBACK%/$LATENCY/" "$CONFIG_FILE"
}

# Route "balena-sound.input" to the appropriate sink depending on selected mode
# Either "snapcast" fifo sink or "balena-sound.output"
function route_input_sink() {
local MODE="$1"

declare -A options=(
["MULTI_ROOM"]=0
["MULTI_ROOM_CLIENT"]=1
["STANDALONE"]=2
)

case "${options[$MODE]}" in
${options["STANDALONE"]} | ${options["MULTI_ROOM_CLIENT"]})
sed -i "s/%INPUT_SINK%/sink='balena-sound.output'/" "$CONFIG_FILE"
echo "Routing 'balena-sound.input' to 'balena-sound.output'."
;;

${options["MULTI_ROOM"]} | *)
sed -i "s/%INPUT_SINK%/sink=\"snapcast\"/" "$CONFIG_FILE"
echo "Routing 'balena-sound.input' to 'snapcast'."
;;
esac
}

# Route any existing source to the input router ("balena-sound.input")
function route_input_source() {
local INPUT_DEVICE=$(arecord -l | awk '/card [0-9]:/ { print $3 }')
Expand All @@ -46,7 +22,6 @@ function route_input_source() {
echo "Routing audio from '$INPUT_DEVICE_FULLNAME' into 'balena-sound.input sink'"
echo -e "\nload-module module-loopback source='$INPUT_DEVICE_FULLNAME' sink='balena-sound.input'" >> "$CONFIG_FILE"
fi

}

# Route "balena-sound.output" to the appropriate audio hardware
Expand All @@ -60,7 +35,7 @@ function route_output_sink() {
OUTPUT=$(cat "$SINK_FILE")
fi
OUTPUT="${OUTPUT:-0}"
sed -i "s/%OUTPUT_SINK%/sink=\"$OUTPUT\"/" "$CONFIG_FILE"
sed -i "s/%OUTPUT_SINK%/sink=$OUTPUT/" "$CONFIG_FILE"
echo "Routing 'balena-sound.output' to '$OUTPUT'."
}

Expand All @@ -71,23 +46,13 @@ function reset_sound_config() {
cp "$CONFIG_TEMPLATE" "$CONFIG_FILE"
}

SOUND_SUPERVISOR_PORT=${SOUND_SUPERVISOR_PORT:-80}
SOUND_SUPERVISOR="$(ip route | awk '/default / { print $3 }'):$SOUND_SUPERVISOR_PORT"
# Wait for sound supervisor to start
while ! curl --silent --output /dev/null "$SOUND_SUPERVISOR/ping"; do sleep 5; echo "Waiting for sound supervisor to start at $SOUND_SUPERVISOR"; done

# Get mode from sound supervisor.
# mode: default to MULTI_ROOM
MODE=$(curl --silent "$SOUND_SUPERVISOR/mode" || true)

# Get latency values
SOUND_INPUT_LATENCY=${SOUND_INPUT_LATENCY:-200}
SOUND_OUPUT_LATENCY=${SOUND_OUTPUT_LATENCY:-200}

# Audio routing: route intermediate balena-sound input/output sinks
echo "Setting audio routing rules..."
reset_sound_config
route_input_sink "$MODE"
route_output_sink
set_loopback_latency "INPUT_LATENCY" "$SOUND_INPUT_LATENCY"
set_loopback_latency "OUTPUT_LATENCY" "$SOUND_OUPUT_LATENCY"
Expand Down
2 changes: 1 addition & 1 deletion core/multiroom/client/Dockerfile.template
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ FROM balenablocks/multiroom
WORKDIR /usr/src

ENV PULSE_SERVER=tcp:audio:4317
ENV PULSE_SINK=balena-sound.output
ENV PULSE_SINK=multi-room.input

COPY start.sh .

Expand Down
26 changes: 11 additions & 15 deletions core/multiroom/client/start.sh
Original file line number Diff line number Diff line change
@@ -1,23 +1,20 @@
#!/usr/bin/env bash
set -e

# Get mode and snapserver from sound-supervisor.
# If sound-supervisor is not running default to multiroom-server (local) as it will be overriden regardless once sound-supervisor starts.
# TODO: consider adding back the wait on sound-supervisor as multiroom won't work regardless if it doesn't start.
SOUND_SUPERVISOR_PORT=${SOUND_SUPERVISOR_PORT:-80}
SOUND_SUPERVISOR="$(ip route | awk '/default / { print $3 }'):$SOUND_SUPERVISOR_PORT"
# Wait for sound supervisor to start
while ! curl --silent --output /dev/null "$SOUND_SUPERVISOR/ping"; do sleep 5; echo "Waiting for sound supervisor to start at $SOUND_SUPERVISOR"; done

# Get mode and snapserver from sound supervisor
# mode: default to MULTI_ROOM
# snapserver: default to multiroom-server (local)
MODE=$(curl --silent "$SOUND_SUPERVISOR/mode" || true)
SNAPSERVER=$(curl --silent "$SOUND_SUPERVISOR/multiroom/master" || true)
SNAPSERVER=$(curl --silent "$SOUND_SUPERVISOR/device/multiroom" || true)
SNAPSERVER=${SNAPSERVER:-"multiroom-server"}
SNAPSERVER_PORT="1704"

# --- ENV VARS ---
# SOUND_MULTIROOM_LATENCY: latency in milliseconds to compensate for speaker hardware sync issues
LATENCY=${SOUND_MULTIROOM_LATENCY:+"--latency $SOUND_MULTIROOM_LATENCY"}

echo "Starting multi-room client..."
echo "- balenaSound mode: $MODE"
echo "- Target snapcast server: $SNAPSERVER"

# Set the snapcast device name for https://github.com/balenalabs/balena-sound/issues/332
Expand All @@ -29,9 +26,8 @@ else
fi

# Start snapclient
if [[ "$MODE" == "MULTI_ROOM" || "$MODE" == "MULTI_ROOM_CLIENT" ]]; then
/usr/bin/snapclient --host $SNAPSERVER $LATENCY --hostID $SNAPCAST_CLIENT_ID --logfilter *:error
else
echo "Multi-room client disabled. Exiting..."
exit 0
fi
# Polling the snapserver port is less resource intensive than letting the service restart itself if the snapserver is not running
echo "Attempting to connect to snapserver at $SNAPSERVER:$SNAPSERVER_PORT..."
while ! nc -z "$SNAPSERVER:$SNAPSERVER_PORT"; do sleep 5; done
echo "Connection established successfully!"
/usr/bin/snapclient --host $SNAPSERVER $LATENCY --hostID $SNAPCAST_CLIENT_ID --logfilter *:error
2 changes: 1 addition & 1 deletion core/multiroom/server/Dockerfile.template
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ FROM balenablocks/multiroom
WORKDIR /usr/src

ENV PULSE_SERVER=tcp:audio:4317
ENV PULSE_SOURCE=snapcast.monitor
ENV PULSE_SOURCE=balena-sound.input.monitor

COPY snapserver.conf /etc/snapserver.conf
COPY start.sh .
Expand Down
28 changes: 7 additions & 21 deletions core/multiroom/server/start.sh
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
#!/bin/bash
set -e

SOUND_SUPERVISOR_PORT=${SOUND_SUPERVISOR_PORT:-80}
SOUND_SUPERVISOR="$(ip route | awk '/default / { print $3 }'):$SOUND_SUPERVISOR_PORT"
# Wait for sound supervisor to start
while ! curl --silent --output /dev/null "$SOUND_SUPERVISOR/ping"; do sleep 5; echo "Waiting for sound supervisor to start at $SOUND_SUPERVISOR"; done

# Get mode from sound supervisor.
# mode: default to MULTI_ROOM
MODE=$(curl --silent "$SOUND_SUPERVISOR/mode" || true)
if [[ -n "$SOUND_MULTIROOM_DISABLE" ]]; then
echo "Multi-room is disabled, exiting..."
exit 0
fi

# Multi-room server can't run properly in some platforms because of resource constraints, so we disable them
declare -A blacklisted=(
Expand All @@ -17,20 +13,10 @@ declare -A blacklisted=(
)

if [[ -n "${blacklisted[$BALENA_DEVICE_TYPE]}" ]]; then
echo "Multi-room server blacklisted for $BALENA_DEVICE_TYPE. Exiting..."

if [[ "$MODE" == "MULTI_ROOM" ]]; then
echo "Multi-room has been disabled on this device type due to performance constraints."
echo "You should use this device in 'MULTI_ROOM_CLIENT' mode if you have other devices running balenaSound, or 'STANDALONE' mode if this is your only device."
fi
echo "Multi-room server is disabled on $BALENA_DEVICE_TYPE device type due to performance constraints. Exiting..."
exit 0
fi

# Start snapserver
if [[ "$MODE" == "MULTI_ROOM" ]]; then
echo "Starting multi-room server..."
/usr/bin/snapserver
else
echo "Multi-room server disabled. Exiting..."
exit 0
fi
echo "Starting multi-room server..."
/usr/bin/snapserver
5 changes: 5 additions & 0 deletions core/sound-supervisor/.lintstagedrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"*.ts": [
"npm run lint-fix"
],
}
12 changes: 7 additions & 5 deletions core/sound-supervisor/Dockerfile.template
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,25 @@ FROM balenalib/%%BALENA_ARCH%%-node:14 as build

WORKDIR /usr/src
COPY core/sound-supervisor/package*.json ./
RUN npm install
RUN sed -i 's/\"prepare\":.*/\"prepare\": \"echo 1\",/g' /usr/src/package.json
RUN npm ci

#dev-cmd-live=npm run livepush
#dev-cmd-live=DEBUG=main* npm run livepush

COPY core/sound-supervisor/src ./src
COPY core/sound-supervisor/typings ./typings
COPY core/sound-supervisor/tsconfig.json .
RUN npm run build
COPY VERSION .

RUN npm run build && npm ci --production

FROM node:14-alpine3.14

WORKDIR /usr/src

COPY core/sound-supervisor/package*.json ./
COPY --from=build /usr/src/build ./build
COPY --from=build /usr/src/node_modules ./node_modules
COPY VERSION .

RUN npm install --production

CMD [ "npm", "start" ]
Loading

0 comments on commit 78c6d4f

Please sign in to comment.