Skip to content

Instantly share code, notes, and snippets.

@Mohawi
Last active January 7, 2024 09:34
Show Gist options
  • Save Mohawi/9a119dcdfae51514a2bae24975f2de4d to your computer and use it in GitHub Desktop.
Save Mohawi/9a119dcdfae51514a2bae24975f2de4d to your computer and use it in GitHub Desktop.
This script sets up a specific architecture that serves as the central node of a multiroom audio system
#!/bin/bash
############################################################################################################################################################################################################
############################################################################################################################################################################################################
############################################################################################################################################################################################################
# #
# SYSTEM ARCHITECTURE - SOMMS (SNAPCAST - OCTO - MOPIDY - MULTIROOM - STREAMER) #
# #
############################################################################################################################################################################################################
# #
# +------------------------------------------------------------------------------------------------+ #
# | | #
# | RaspberryPi4/2GB + Audio Injector Octo | #
# +--------------------+ | (6ADC / 8DAC) | +-----------------------+ #
# | | | (96kHz/24Bit) | | | #
# | ANALOG_IN1/2 +--+ | | +--+ ANALOG_OUT1/2 | #
# | TV | | | +----------------------------------------------+ | | | Snapclient_Out | #
# | | | | +-----------+ | | +------------+ | | | | #
# +--------------------+ | | | | | JACKd | | | | | +-----------------------+ #
# +--------------------+ ALSA_IN/6 +->+ +->+ ALSA_OUT/8 +------+ #
# +--------------------+ | | | | | 96kHz / 24Bit | | | | | +-----------------------+ #
# | | | | +-----------+ | | +------------+ | | | | #
# | ANALOG_IN2/2 +--+ | +-+------------------------------------------+-+ | +--+ ANALOG_OUT2/2 | #
# | CD | | | | ^ | | | TV_Mirror | #
# | | | | | +------------+ +------------+ | | | | | #
# +--------------------+ | | | | | | | | | | +-----------------------+ #
# | | +->+ ALSA_IN1/2 +-->+ | | | | #
# +--------------------+ | | | | | | | +------+------+ | | +-----------------------+ #
# | | | | | +------------+ | | | | | | | | #
# | ANALOG_IN3/2 +--+ | | | | | ALSA_OUT1/2 | | +--+ ANALOG_OUT3/2 | #
# | Vinyl | | | +------------+ | | | | | | | CD_Mirror | #
# | | | | | | | | +------+------+ | | | | #
# +--------------------+ | +->+ ALSA_IN2/2 +-->+ | ^ | | +-----------------------+ #
# | | | | | | | | | #
# | | +------------+ | | | | | +-----------------------+ #
# | | | | | | | | | #
# | | +------------+ | | +------+------+ | | | ANALOG_OUT4/2 | #
# | | | | | | | | | +--+ Vinyl_Mirror | #
# | +->+ ALSA_IN3/2 +-->+ | | SNAPCLIENT1 | | | | #
# | | | | | | | | +-----------------------+ #
# | +------------+ | SNAPSERVER | +------+------+ | #
# | | | ^ | +------------------------------------+ #
# | +----------------+ | | | LAN | | | #
# | +-------------+ | | | 96kHz +---------+------------------------+ | RaspberryPi Zero W + Hifiberry DAC | #
# | | | +->+ Mopidy_Stream1 +-->+ | | | | | | #
# +------------>+ HASS | | | | | 16Bit | v | | | +-------------+ +------------+ | +--------------+ #
# | | | Backend | | +----------------+ | | +-----+-------+ | | | | | | | | | | #
# | | | | | | | | | | +----->+ SNAPCLIENT2 +->+ ALSA_OUT/2 +------+ ANALOG_OUT/2 | #
# | | +-------------+ | +----------------+ | | | SNAPCLIENT4 | | | | | | | | | | | #
# | | | | | | | | | | | | +-------------+ +------------+ | +--------------+ #
# +-----+------+ | +->+ Mopidy_Stream2 +-->+ | +-----+-------+ | | | | #
# | | | +----------+ | | | | v | | +------------------------------------+ #
# | HASS | | Control | | +----------------+ | | +-----+-------+ | | #
# | Frontend +---------------------+ | | | | | | | +------------------------------------+ #
# | | | +---+ | +----------------+ | | | PULSEAUDIO | | | | | #
# +------------+ | | | | | | | | | | | | RaspberryPi Zero W + Hifiberry DAC | #
# | | +->+ Mopidy_Stream3 +-->+ | +-----+-------+ | | | | #
# | | | | | | v | | | +-------------+ +------------+ | +--------------+ #
# +----------------+ | | +----------------+ +-----+------+ +-----+-------+ | | | | | | | | | | #
# | | | v | | | | +----->+ SNAPCLIENT3 +->+ ALSA_OUT/2 +------+ ANALOG_OUT/2 | #
# | Snapcontrol +-------------------------+------------------------------------+ | BLUEZ +-------+ | | | | | | | | | #
# | | | Snapcontrol | | | | | +-------------+ +------------+ | +--------------+ #
# +----------------+ | +-------------+ | | | | #
# +-------------------------------------------------------------------------------------------|----+ +------------------------------------+ #
# | #
# | +-------------------+ #
# +-----------+ Bluetooth speaker | #
# +-------------------+ #
# #
# #
############################################################################################################################################################################################################
############################################################################################################################################################################################################
############################################################################################################################################################################################################
# This runs fine on a Raspberry Pi 4 with 2GB of RAM. The IP of the central node needs to be statically set to 192.168.2.101 or to the one you choose.
# Also the mopidy plugins youtube, soundcloud and bandcamp need authentication tokens, which you will need to provide manually
#
# NO GUARANTEES GIVEN
# If you observe anything odd, please let me know!
#
# on first start you might need to configure the HASS through the webpage (like setup an user account).
echo 'Downloading and installing packages...'
sudo -i
apt update -y
apt upgrade -y
# install snapserver
wget https://github.com/badaix/snapcast/releases/download/v0.26.0/snapserver_0.27.0-1_armhf.deb
apt install ./snapserver_0.27.0-1_armhf.deb -y
rm snapserver_0.27.0-1_armhf.deb
#install snapclient
wget https://github.com/badaix/snapcast/releases/download/v0.26.0/snapclient_0.27.0-1_without-pulse_armhf.deb
apt install ./snapclient_0.27.0-1_without-pulse_armhf.deb -y
rm snapclient_0.27.0-1_without-pulse_armhf.deb
#install jackd
apt install jackd2 -y
apt install jack-tools -y
echo "Install RT patched kernel"
#install RT patched kernel
wget https://github.com/kdoren/linux/releases/download/rpi_6.1.54-rt15/linux-image-6.1.54-rt15-v8+_6.1.54-1_arm64.deb
# if installing 64-bit kernel on 32-bit system:
dpkg --add-architecture arm64
sed -i 's|^deb http|deb [ arch=armhf ] http|g' /etc/apt/sources.list
sed -i 's|^deb http|deb [ arch=armhf ] http|g' /etc/apt/sources.list.d/raspi.list
apt install ./linux-image-6.1.54-rt15-v8+_6.1.54-1_arm64.deb -y
KERN=6.1.54-rt15-v8+ # 64-bit kernel
mkdir -p /boot/$KERN/overlays/
cp -d /usr/lib/linux-image-$KERN/overlays/* /boot/$KERN/overlays/
cp -dr /usr/lib/linux-image-$KERN/* /boot/$KERN/
[[ -d /usr/lib/linux-image-$KERN/broadcom ]] && cp -d /usr/lib/linux-image-$KERN/broadcom/* /boot/$KERN/
touch /boot/$KERN/overlays/README
mv /boot/vmlinuz-$KERN /boot/$KERN/
mv /boot/initrd.img-$KERN /boot/$KERN/
mv /boot/System.map-$KERN /boot/$KERN/
mv /boot/config-$KERN /boot/$KERN/
cat >> /boot/config.txt << EOF
[all]
kernel=vmlinuz-$KERN
# initramfs initrd.img-$KERN
os_prefix=$KERN/
overlay_prefix=overlays/$(if [[ "$KERN" =~ 'v8' ]]; then echo -e "\narm_64bit=1"; fi)
[all]
EOF
rm /boot/cmdline.txt
cat >> /boot/cmdline.txt << EOF
boot=overlay console=serial0,115200 console=/dev/null root=PARTUUID=28f38267-02 rootfstype=ext4 fsck.repair=yes rootwait quiet splash plymoth.ignore-serial-consoles logo.nologo
EOF
cp /boot/cmdline.txt /boot/$KERN/
echo "Configure Jackd"
#fill jackdsound.conf
cat >> /etc/dbus-1/system.d/jackdsound.conf << EOF
<?xml version="1.0"?> <!--*-nxml-*-->
<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<busconfig>
<policy context="default">
<allow own="org.freedesktop.ReserveDevice1.Audio0"/>
<allow own="org.freedesktop.ReserveDevice1.Audio1"/>
<allow own="org.freedesktop.ReserveDevice1.Audio2"/>
</policy>
</busconfig>
EOF
echo "Setup Audioinjector Octo"
#setup octo
sed -i 's/dtparam=audio=on/#dtparam=audio=on/g' /boot/config.txt
echo "Setup extra boot settings"
cat >> /boot/config.txt << EOF
[all]
dtoverlay=audioinjector-addons,non-stop-clocks=false
EOF
#disable LEDs
cat >> /boot/config.txt << EOF
[all]
#Disable the PWR LED
dtparam=pwr_led_trigger=none
dtparam=pwr_led_activelow=off
#Disable the Activity LED
dtparam=act_led_trigger=none
dtparam=act_led_activelow=off
#rotate lcd display 180deg
lcd_rotate=2
EOF
echo "continue setting up jackd"
#setup asound.conf
cat >> /etc/asound.conf << EOF
pcm.rawjack_snapclient_out {
type jack
playback_ports {
0 system:playback_1
1 system:playback_2
}
}
pcm.rawjack_snapserver_LineIn1 {
type jack
capture_ports {
0 system:capture_1
1 system:capture_2
}
}
pcm.rawjack_snapserver_LineIn2 {
type jack
capture_ports {
0 system:capture_3
1 system:capture_4
}
}
pcm.rawjack_snapserver_LineIn3 {
type jack
capture_ports {
0 system:capture_5
1 system:capture_6
}
}
pcm.plugjack_snapclient_out {
type plug
slave { pcm "rawjack_snapclient_out" }
hint {
description "JACK Audio Connection Kit sink for the snapclient"
}
}
pcm.plugjack_snapserver_LineIn1 {
type plug
slave { pcm "rawjack_snapserver_LineIn1" }
hint {
description "JACK Audio Connection Kit source for the LineIn1 channel"
}
}
pcm.plugjack_snapserver_LineIn2 {
type plug
slave { pcm "rawjack_snapserver_LineIn2" }
hint {
description "JACK Audio Connection Kit source for the LineIn2 channel"
}
}
pcm.plugjack_snapserver_LineIn3 {
type plug
slave { pcm "rawjack_snapserver_LineIn3" }
hint {
description "JACK Audio Connection Kit source for the LineIn3 channel"
}
}
EOF
#setup jack_config
cat >> /etc/jack_config.conf << EOF
JACKD_OPTIONS="-R -P75 -dalsa -dhw:audioinjectoroc -r96000 -p512 -n3"
EOF
cat >> /etc/jack-plumbing << EOF
(disconnect "system:capture_(.*)" "system:playback_(.*)")
(connect "system:capture_1" "system:playback_3")
(connect "system:capture_2" "system:playback_4")
(connect "system:capture_3" "system:playback_5")
(connect "system:capture_4" "system:playback_6")
(connect "system:capture_5" "system:playback_7")
(connect "system:capture_6" "system:playback_8")
EOF
echo "Setup snapcast"
# setup snapclient
sed -i 's/SNAPCLIENT_OPTS=""/SNAPCLIENT_OPTS="--host 127.0.0.1 --port 1710 --soundcard plugjack_snapclient_out"/g' /etc/default/snapclient1
sed -i 's/SNAPCLIENT_OPTS=""/SNAPCLIENT_OPTS="--host 127.0.0.1 --port 1710 --soundcard pulse"/g' /etc/default/snapclient2
#setup snapserver
sed -i 's|^source =.*|source = alsa://?name=TV&device=plugjack_snapserver_LineIn1&sampleformat=96000:16:2&silence_threshold_percent=0.2&idle_threshold=100\nsource = alsa://?name=CD&device=plugjack_snapserver_LineIn2&sampleformat=96000:16:2&silence_threshold_percent=0.1&idle_threshold=100\nsource = alsa://?name=Vinyl&device=plugjack_snapserver_LineIn3&sampleformat=96000:16:2&silence_threshold_percent=1.5&idle_threshold=100\nsource = tcp://127.0.0.1:4953?name=Livingroom(Stream)\nsource = tcp://127.0.0.1:4954?name=Library(Stream)\nsource = tcp://127.0.0.1:4955?name=Office(Stream)\nsource = meta:///Vinyl/CD/Livingroom(Stream)?name=Livingroom_Music\nsource = meta:///Livingroom_Music/TV?name=Livingroom_Music_And_Tv|g' /etc/snapserver.conf
sed -i '/^#sampleformat = 48000:16:2/a sampleformat = 96000:16:2' /etc/snapserver.conf
sed -i '/^#port = 1705/a port = 1711' /etc/snapserver.conf
sed -i '/^#port = 1704/a port = 1710' /etc/snapserver.conf
echo "setup services"
#setup services
cat >> /etc/systemd/system/restartOcto.service << EOF
[Unit]
Description=AudioInjector Octo
After=sound.target time-sync.target
Requires=sound.target
PartOf=audioOcto.target
[Service]
Type=oneshot
#ExecStartPre=sleep 5
ExecStart=/home/pi/restartOcto.sh
RemainAfterExit=yes
[Install]
WantedBy=audioOcto.target
EOF
cat >> /etc/systemd/system/jackd.service << EOF
[Unit]
Description=JACK Audio Connection Kit
After=sound.target ntp.service time-sync.target restartOcto.service
#Wants=restartOcto.service
Requires=restartOcto.service
BindsTo=restartOcto.service
PartOf=audioOcto.target
#StartLimitBurst=4
#StartLimitIntervalSec=60
#StartLimitAction=reboot
[Service]
EnvironmentFile=-/etc/jack_config.conf
LimitRTPRIO=infinity
LimitMEMLOCK=infinity
User=pi
Environment="DBUS_SESSION_BUS_ADDRESS=unix:path=/run/dbus/system_bus_socket"
#ExecStartPre=/bin/sleep 5
ExecStart=/usr/bin/jackd \$JACKD_OPTIONS
RestartSec=5
Restart=on-failure
[Install]
WantedBy=audioOcto.target
EOF
cat >> /etc/systemd/system/snapserver.service << EOF
[Unit]
Description=Snapcast server
Documentation=man:snapserver(1)
Wants=avahi-daemon.service jackd.service
After=network.target time-sync.target avahi-daemon.service jackd.service
Requires=jackd.service
PartOf=audioOcto.target
[Service]
EnvironmentFile=-/etc/default/snapserver
LimitRTPRIO=infinity
LimitMEMLOCK=infinity
Nice=-20
#ExecStartPre=/bin/sleep 5
ExecStart=/usr/bin/snapserver --server.datadir=\${HOME} \$SNAPSERVER_OPTS
User=pi
#Group=snapserver
RestartSec=5
Restart=on-failure
[Install]
WantedBy=audioOcto.target
EOF
cat >> /etc/systemd/system/snapclient.service << EOF
[Unit]
Description=Snapcast client
Documentation=man:snapclient(1)
Wants=avahi-daemon.service jackd.service
After=network-online.target time-sync.target sound.target avahi-daemon.service jackd.service
Requires=jackd.service
PartOf=audioOcto.target
[Service]
EnvironmentFile=-/etc/default/snapclient1
Nice=-15
LimitRTPRIO=infinity
LimitMEMLOCK=infinity
#ExecStartPre=/bin/sleep 10
ExecStart=/usr/bin/snapclient --logsink=null \$SNAPCLIENT_OPTS
User=pi
Group=audio
Restart=on-failure
[Install]
WantedBy=audioOcto.target
EOF
cat >> /etc/systemd/system/audioOcto.target << EOF
[Unit]
Description=This target sums up the services to make the Octo interface work
Requires=sound.target
Requires=network.target
Requires=time-sync.target
PartOf=jackd.service
[Install]
WantedBy=multi-user.target
EOF
cat >> /etc/systemd/system/jackd_connect.service << EOF
[Unit]
Description = connect JACK ports according to /etc/jack-plumbing
Wants=jackd.service
After=jackd.service
Requires=jackd.service
#BindsTo=jackd.service
PartOf=audioOcto.target
[Service]
ExecStartPre=sleep 3
ExecStart=jack-plumbing -d
User=pi
Restart=on-failure
[Install]
WantedBy=audioOcto.target
EOF
echo "Install bluetooth and pulseaudio"
apt install bluetooth pi-bluetooth bluez pulseaudio pulseaudio-module-bluetooth
cat >> /etc/systemd/user/snapclient_pulse.service << EOF
[Unit]
Description=Snapcast client for pulse
Documentation=man:snapclient(1)
[Service]
EnvironmentFile=-/etc/default/snapclient2
Nice=-15
LimitRTPRIO=infinity
LimitMEMLOCK=infinity
ExecStart=/usr/bin/snapclient --logsink=null $SNAPCLIENT_OPTS
Restart=on-failure
[Install]
WantedBy=default.target
EOF
systemctl daemon-reload
systemctl enable restartOcto
systemctl enable jackd
systemctl enable jack_config
systemctl enable snapserver
systemctl enable snapclient
systemctl enable audioOcto.target
sudo -u pi -H -s
systemctl --user daemon-reload
systemctl --user enable snapclient_pulse
exit
cat >> /home/pi/restartOcto.sh << EOF
#!/bin/bash
modprobe -r snd_soc_audioinjector_octo_soundcard
modprobe -r snd_soc_cs42xx8_i2c
modprobe -r snd_soc_cs42xx8
modprobe snd_soc_cs42xx8
modprobe snd_soc_cs42xx8_i2c
modprobe snd_soc_audioinjector_octo_soundcard
EOF
chmod +x /home/pi/restartOcto.sh
cat /var/lib/alsa/asound.state << EOF
state.Headphones {
control.1 {
iface MIXER
name 'Headphone Playback Volume'
value 0
comment {
access 'read write'
type INTEGER
count 1
range '-10239 - 400'
dbmin -9999999
dbmax 400
dbvalue.0 0
}
}
control.2 {
iface MIXER
name 'Headphone Playback Switch'
value true
comment {
access 'read write'
type BOOLEAN
count 1
}
}
}
state.vc4hdmi0 {
control.1 {
iface PCM
name 'Playback Channel Map'
value.0 0
value.1 0
value.2 0
value.3 0
value.4 0
value.5 0
value.6 0
value.7 0
comment {
access read
type INTEGER
count 8
range '0 - 36'
}
}
control.2 {
iface PCM
name 'IEC958 Playback Mask'
value ffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
comment {
access read
type IEC958
count 1
}
}
control.3 {
iface PCM
name 'IEC958 Playback Default'
value '0400000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
comment {
access 'read write'
type IEC958
count 1
}
}
control.4 {
iface PCM
name ELD
value '0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
comment {
access 'read volatile'
type BYTES
count 128
}
}
}
state.vc4hdmi1 {
control.1 {
iface PCM
name 'Playback Channel Map'
value.0 0
value.1 0
value.2 0
value.3 0
value.4 0
value.5 0
value.6 0
value.7 0
comment {
access read
type INTEGER
count 8
range '0 - 36'
}
}
control.2 {
iface PCM
name 'IEC958 Playback Mask'
value ffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
comment {
access read
type IEC958
count 1
}
}
control.3 {
iface PCM
name 'IEC958 Playback Default'
value '0400000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
comment {
access 'read write'
type IEC958
count 1
}
}
control.4 {
iface PCM
name ELD
value '0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
comment {
access 'read volatile'
type BYTES
count 128
}
}
}
state.audioinjectoroc {
control.1 {
iface MIXER
name 'ADC3 Capture Volume'
value.0 129
value.1 129
comment {
access 'read write'
type INTEGER
count 2
range '0 - 176'
dbmin -6400
dbmax 2400
dbvalue.0 50
dbvalue.1 50
}
}
control.2 {
iface MIXER
name 'ADC3 Invert Switch'
value.0 false
value.1 false
comment {
access 'read write'
type BOOLEAN
count 2
}
}
control.3 {
iface MIXER
name 'ADC3 Single Ended Mode Switch'
value Single-Ended
comment {
access 'read write'
type ENUMERATED
count 1
item.0 Differential
item.1 Single-Ended
}
}
control.4 {
iface MIXER
name 'DAC1 Playback Volume'
value.0 255
value.1 255
comment {
access 'read write'
type INTEGER
count 2
range '0 - 255'
dbmin -9999999
dbmax 0
dbvalue.0 0
dbvalue.1 0
}
}
control.5 {
iface MIXER
name 'DAC2 Playback Volume'
value.0 255
value.1 255
comment {
access 'read write'
type INTEGER
count 2
range '0 - 255'
dbmin -9999999
dbmax 0
dbvalue.0 0
dbvalue.1 0
}
}
control.6 {
iface MIXER
name 'DAC3 Playback Volume'
value.0 255
value.1 255
comment {
access 'read write'
type INTEGER
count 2
range '0 - 255'
dbmin -9999999
dbmax 0
dbvalue.0 0
dbvalue.1 0
}
}
control.7 {
iface MIXER
name 'DAC4 Playback Volume'
value.0 255
value.1 255
comment {
access 'read write'
type INTEGER
count 2
range '0 - 255'
dbmin -9999999
dbmax 0
dbvalue.0 0
dbvalue.1 0
}
}
control.8 {
iface MIXER
name 'ADC1 Capture Volume'
value.0 152
value.1 152
comment {
access 'read write'
type INTEGER
count 2
range '0 - 176'
dbmin -6400
dbmax 2400
dbvalue.0 1200
dbvalue.1 1200
}
}
control.9 {
iface MIXER
name 'ADC2 Capture Volume'
value.0 104
value.1 104
comment {
access 'read write'
type INTEGER
count 2
range '0 - 176'
dbmin -6400
dbmax 2400
dbvalue.0 -1200
dbvalue.1 -1200
}
}
control.10 {
iface MIXER
name 'DAC1 Invert Switch'
value.0 false
value.1 false
comment {
access 'read write'
type BOOLEAN
count 2
}
}
control.11 {
iface MIXER
name 'DAC2 Invert Switch'
value.0 false
value.1 false
comment {
access 'read write'
type BOOLEAN
count 2
}
}
control.12 {
iface MIXER
name 'DAC3 Invert Switch'
value.0 false
value.1 false
comment {
access 'read write'
type BOOLEAN
count 2
}
}
control.13 {
iface MIXER
name 'DAC4 Invert Switch'
value.0 false
value.1 false
comment {
access 'read write'
type BOOLEAN
count 2
}
}
control.14 {
iface MIXER
name 'ADC1 Invert Switch'
value.0 false
value.1 false
comment {
access 'read write'
type BOOLEAN
count 2
}
}
control.15 {
iface MIXER
name 'ADC2 Invert Switch'
value.0 false
value.1 false
comment {
access 'read write'
type BOOLEAN
count 2
}
}
control.16 {
iface MIXER
name 'ADC High-Pass Filter Switch'
value true
comment {
access 'read write'
type BOOLEAN
count 1
}
}
control.17 {
iface MIXER
name 'DAC De-emphasis Switch'
value false
comment {
access 'read write'
type BOOLEAN
count 1
}
}
control.18 {
iface MIXER
name 'ADC1 Single Ended Mode Switch'
value Single-Ended
comment {
access 'read write'
type ENUMERATED
count 1
item.0 Differential
item.1 Single-Ended
}
}
control.19 {
iface MIXER
name 'ADC2 Single Ended Mode Switch'
value Single-Ended
comment {
access 'read write'
type ENUMERATED
count 1
item.0 Differential
item.1 Single-Ended
}
}
control.20 {
iface MIXER
name 'DAC Single Volume Control Switch'
value 0
comment {
access 'read write'
type INTEGER
count 1
range '0 - 1'
}
}
control.21 {
iface MIXER
name 'DAC Soft Ramp & Zero Cross Control Switch'
value 'Immediate Change'
comment {
access 'read write'
type ENUMERATED
count 1
item.0 'Immediate Change'
item.1 'Zero Cross'
item.2 'Soft Ramp'
item.3 'Soft Ramp on Zero Cross'
}
}
control.22 {
iface MIXER
name 'DAC Auto Mute Switch'
value true
comment {
access 'read write'
type BOOLEAN
count 1
}
}
control.23 {
iface MIXER
name 'Mute ADC Serial Port Switch'
value false
comment {
access 'read write'
type BOOLEAN
count 1
}
}
control.24 {
iface MIXER
name 'ADC Single Volume Control Switch'
value 0
comment {
access 'read write'
type INTEGER
count 1
range '0 - 1'
}
}
control.25 {
iface MIXER
name 'ADC Soft Ramp & Zero Cross Control Switch'
value 'Immediate Change'
comment {
access 'read write'
type ENUMERATED
count 1
item.0 'Immediate Change'
item.1 'Zero Cross'
item.2 'Soft Ramp'
item.3 'Soft Ramp on Zero Cross'
}
}
}
EOF
echo "Install Mopidy"
apt install mopidy -y
python3 -m pip install mopidy-youtube
python3 -m pip install mopidy-soundcloud
python3 -m pip install mopidy-tunein
python3 -m pip install mopidy-local
python3 -m pip install mopidy-iris
python3 -m pip install mopidy-mpd
python3 -m pip install mopidy-bandcamp
echo "mopidy ALL=NOPASSWD: /usr/local/lib/python3.9/dist-packages/mopidy_iris/system.sh" >> /etc/sudoers
rm /etc/mopidy/mopidy.conf
cat >> /etc/mopidy/mopidy.conf << EOF
\# For information about configuration values that can be set in this file see:
\#
\# https://docs.mopidy.com/en/latest/config/
\#
\# Run `sudo mopidyctl config` to see the current effective config, based on
\# both defaults and this configuration file.
[youtube]
enabled = true
youtube_api_key = <<get your own key>>
api_enabled = true
search_results = 15
playlist_max_videos = 20
autoplay_enabled = true
strict_autoplay = true
max_autoplay_length = 15000
[http]
enabled = true
hostname = 0.0.0.0
default_app = iris
[mpd]
enabled = true
hostname = 0.0.0.0
[soundcloud]
auth_token = <<get your own key>>
[bandcamp]
identity = <<get your own key>>
[local]
media_dir = /home/pi/Music
included_file_extensions = .flac, .mp3, .wma
scan_timeout = 5000
album_art_files = *.jpg
use_artist_sortname = true
[autoplay]
enabled=true
tracklist.uris = auto
tracklist.index = auto
tracklist.consume = auto
tracklist.random = auto
tracklist.repeat = auto
tracklist.single = auto
playback.state = auto
playback.time_position = auto
mixer.volume = auto
mixer.mute = auto
EOF
cat >> /etc/mopidy/mopidy0.conf << EOF
[audio]
output = audioresample ! audioconvert ! audio/x-raw,rate=96000,channels=2,format=S16LE ! wavenc ! tcpclientsink host=127.0.0.1 port=4953
[http]
port=6680
zeroconf = Mopidy
[mpd]
port = 6600
EOF
cat >> /etc/mopidy/mopidy1.conf << EOF
[audio]
output = audioresample ! audioconvert ! audio/x-raw,rate=96000,channels=2,format=S16LE ! wavenc ! tcpclientsink host=127.0.0.1 port=4954
[http]
port=6681
allowed_origins = 192.168.2.112:6680
[mpd]
port = 6601
EOF
cat >> /etc/mopidy/mopidy2.conf << EOF
[audio]
output = audioresample ! audioconvert ! audio/x-raw,rate=96000,channels=2,format=S16LE ! wavenc ! tcpclientsink host=127.0.0.1 port=4955
[http]
port=6682
allowed_origins = 192.168.2.112:6680
[mpd]
port = 6602
EOF
cat >> /etc/systemd/system/mopidy@.service << EOF
[Unit]
Description=Mopidy music server #%i
After=avahi-daemon.service
After=dbus.service
After=network.target
After=nss-lookup.target
After=pulseaudio.service
After=remote-fs.target
After=sound.target
[Service]
User=mopidy
PermissionsStartOnly=true
ExecStartPre=/bin/mkdir -p /var/cache/mopidy
ExecStartPre=/bin/chown mopidy:audio /var/cache/mopidy
Environment=XDG_RUNTIME_DIR=/var/cache/mopidy
ExecStart=/usr/bin/mopidy --config /usr/share/mopidy/conf.d:/etc/mopidy/mopidy.conf:/etc/mopidy/mopidy%i.conf
[Install]
WantedBy=multi-user.target
EOF
systemctl enable mopidy@0
systemctl enable mopidy@1
systemctl enable mopidy@2
cat >> /etc/systemd/system/mountMediaServer.service << EOF
[Unit]
Description=Trigger mounting of media server
After=network-online.target
Requires=network-online.target
[Service]
Type=oneshot
#User=pi
ExecStart=/home/pi/MountMediaServer.sh
[Install]
WantedBy=multi-user.target
EOF
systemctl enable mountMediaServer
cat >> /home/pi/MountMediaServer.sh << EOF
#!/bin/bash
sudo mount -t cifs -o user=mopidy,pass=<<not of interest>>,vers=3.0 //192.168.2.3/mm/music /home/pi/Music
while ! (mountpoint -q /home/pi/Music); do
sleep 5
sudo mount -t cifs -o user=mopidy,pass=<<not of interest>>,vers=3.0 //192.168.2.3/mm/music /home/pi/Music
done
EOF
chmod +x /home/pi/MountMediaServer.sh
echo "install homeassistant"
apt-get install -y python3 python3-dev python3-venv python3-pip libffi-dev libssl-dev libjpeg-dev zlib1g-dev autoconf build-essential libopenjp2-7 libtiff5 libturbojpeg0-dev tzdata
useradd -rm homeassistant -G dialout,gpio,i2c
mkdir /srv/homeassistant
chown homeassistant:homeassistant /srv/homeassistant
sudo -u homeassistant -H -s
cd /srv/homeassistant
python3.9 -m venv .
source bin/activate
python3 -m pip install wheel
pip3 install homeassistant
deactivate
cat >> ~/.homeassistant/configuration.yaml << EOF
panel_iframe:
music1:
title: 'Music - Livingroom (Stream)'
icon: 'mdi:music-box-outline'
url: 'http://192.168.2.101:6680'
music3:
title: 'Music - Library (Stream)'
icon: 'mdi:music-box-outline'
url: 'http://192.168.2.101:6681'
music2:
title: 'Music - Office (Stream)'
icon: 'mdi:music-box-outline'
url: 'http://192.168.2.101:6682'
EOF
exit
cat >> /etc/systemd/system/hassio.service << EOF
[Unit]
Description=Home Assistant
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=homeassistant
WorkingDirectory=/home/homeassistant/.homeassistant
ExecStartPre=/bin/sleep 20
ExecStart=/srv/homeassistant/bin/hass -c "/home/homeassistant/.homeassistant"
Restart=always
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable hassio.service
systemctl start hassio.service
echo "setup autostart of chrome"
cat >> /etc/xdg/autostart/chromium_kiosk.desktop << EOF
[Desktop Entry]
Type=Application
Name=Chromium-Iris
Comment=Chromium in Kiosk mode for iris
NoDisplay=false
Exec=bash -c "sleep 15 && chromium-browser http://localhost:8123/music1 –-start-fullscreen –-kiosk –-noerrdialogs –-no-first-run"
EOF
echo "install virtual keyboard"
apt install -y at-spi2-core
apt install -y onboard
gsettings set org.gnome.desktop.a11y.applications screen-keyboard-enabled true
apt install -y dconf-cli
cat >> ~/onboard.settings << EOF
[/]
current-settings-page=1
layout='/usr/share/onboard/layouts/Small.onboard'
schema-version='2.3'
show-status-icon=false
system-theme-associations={'HighContrast': 'HighContrast', 'HighContrastInverse': 'HighContrastInverse', 'LowContrast': 'LowContrast', 'ContrastHighInverse': 'HighContrastInverse', 'Default': '', 'PiXflat': '/usr/share/onboard/themes/DarkRoom.theme'}
theme='/usr/share/onboard/themes/DarkRoom.theme'
use-system-defaults=false
[auto-show]
enabled=true
hide-on-key-press=false
tablet-mode-detection-enabled=false
[keyboard]
key-press-modifiers=@a{ss} {}
[scanner]
enabled=false
[theme-settings]
color-scheme='/usr/share/onboard/themes/DarkRoom.colors'
key-fill-gradient=5.0
key-gradient-direction=-2.0
key-shadow-size=30.0
key-shadow-strength=50.0
key-size=95.0
key-stroke-gradient=15.0
key-style='gradient'
roundrect-radius=20.0
[window]
docking-enabled=false
docking-shrink-workarea=false
force-to-top=true
transparent-background=false
[window/landscape]
dock-expand=true
width=810
x=0
y=278
EOF
cat onboard.settings | dconf load -f /org/onboard/
sed -i 's/Exec=onboard --not-show-in=GNOME,GNOME-Classic:GNOME --startup-delay=3.0/Exec=onboard --startup-delay=3.0/g' /etc/xdg/autostart/onboard-autostart.desktop
sed -i '/^OnlyShowIn=Unity;MATE;/d' /etc/xdg/autostart/onboard-autostart.desktop
apt install ufw -y
ufw allow ssh
ufw allow 6680
ufw allow 6681
ufw allow 6682
ufw allow 8123
ufw allow 1710
ufw allow 1711
ufw allow 1780
ufw deny from 192.168.2.1 proto tcp to any port 22
ufw deny from 192.168.2.2 proto tcp to any port 22
ufw deny from 192.168.2.3 proto tcp to any port 22
ufw allow proto udp to any port 137 from 192.168.2.0/24
ufw allow proto udp to any port 138 from 192.168.2.0/24
ufw allow proto tcp to any port 139 from 192.168.2.0/24
ufw allow proto tcp to any port 445 from 192.168.2.0/24
ufw enable
apt install unattended-upgrades -y
sed -i 's|^//\(.*}-updates\)| \1|g' /etc/apt/apt.conf.d/50unattended-upgrades
sed -i 's|^//\(.*Remove-Unused-Kernel-Packages\)|\1|g' /etc/apt/apt.conf.d/50unattended-upgrades
sed -i 's|^//\(.*Remove-Unused-Dependencies "\)false\(";\)|\1true\2|g' /etc/apt/apt.conf.d/50unattended-upgrades
sed -i 's|^//\(.*Automatic-Reboot-WithUsers\)|\1|g' /etc/apt/apt.conf.d/50unattended-upgrades
sed -i 's|^//\(.*Automatic-Reboot-Time "\).*\(";\)|\105:00\2|g' /etc/apt/apt.conf.d/50unattended-upgrades
cat >> /etc/apt/apt.conf.d/20auto-upgrades << EOF
APT::Periodic::Download-Upgradeable-Packages "1";
APT::Periodic::AutocleanInterval "7";
EOF
echo "Scan local media for mopidy"
systemctl start mountMediaServer.service
/usr/bin/mopidy --config /usr/share/mopidy/conf.d:/etc/mopidy/mopidy.conf:/etc/mopidy/mopidy0.conf local scan
echo "Setup screen blanking"
cat >> /etc/xdg/lxsession/LXDE/autostart << EOF
@xset s 30
EOF
echo rebooting
reboot
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment