Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
ac3fec2
Add Qobuz Connect renderer: schema, feature bit, installer, system files
PhilipVinc Aug 17, 2026
369850e
Add Qobuz Connect renderer: daemon control and worker integration
PhilipVinc Aug 17, 2026
8a6218c
Add Qobuz Connect renderer: Renderer Config section and settings screen
PhilipVinc Aug 17, 2026
514b059
Add Qobuz Connect renderer: active overlay, metadata display, docs
PhilipVinc Aug 17, 2026
c815c74
Qobuz Connect: replace control API polling with qbzd event hooks
PhilipVinc Aug 20, 2026
c876ede
Qobuz Connect: reflect qbzd local pairing in the config screen
PhilipVinc Aug 20, 2026
f6ab478
Qobuz Connect: local pairing setting + settings-before-start ordering
PhilipVinc Aug 20, 2026
aa5bc23
Qobuz Connect: install qbzd pairing test build from fork releases
PhilipVinc Aug 20, 2026
50bfae1
Qobuz Connect: pairing setting moves to Account, gates the login
PhilipVinc Aug 20, 2026
a7a3500
Qobuz Connect: bump qbzd test build to 2.0.2-pairing.2
PhilipVinc Aug 20, 2026
bb9dfca
Qobuz Connect: bump qbzd test build to 2.0.2-pairing.3 (feeder abort)
PhilipVinc Aug 20, 2026
41c2a99
Qobuz Connect: keep the render across pause (AirPlay parity)
PhilipVinc Aug 20, 2026
23c346d
Qobuz Connect: disable a stray qbzd.service on install; harden the hook
PhilipVinc Aug 20, 2026
6aa979a
Qobuz Connect: bump qbzd test build to 2.0.2-pairing.4 (no redundant …
PhilipVinc Aug 20, 2026
dfba9c2
Qobuz Connect: stop qbzd gracefully so the Connect session is left cl…
PhilipVinc Aug 20, 2026
522730c
Qobuz Connect: bump qbzd test build to 2.0.2-pairing.5 (handoff stop …
PhilipVinc Aug 20, 2026
a9985e2
Qobuz Connect: bump qbzd test build to 2.0.2-pairing.6 (handoff echo …
PhilipVinc Aug 20, 2026
06fda1c
Qobuz Connect: bump qbzd test build to 2.0.2-pairing.7 (buffering rep…
PhilipVinc Aug 20, 2026
d56b565
Qobuz Connect: show the real qbzd build in Renderer Config, link its …
PhilipVinc Aug 20, 2026
cba49af
Qobuz Connect: qbzd 2.0.2.moode8, prefer the binary's self-reported b…
PhilipVinc Aug 20, 2026
872b471
Qobuz Connect: qbzd 2.0.2.moode9 (handoff echo naming another track)
PhilipVinc Aug 20, 2026
216342a
Qobuz Connect: qbzd 2.0.2.moode10 (takeback resumes at peer position)
PhilipVinc Aug 20, 2026
5f91e03
Qobuz Connect: qbzd 2.0.2.moode11 (device audio quality = DAC rate)
PhilipVinc Aug 20, 2026
03d6b7e
Qobuz Connect: qbzd 2.0.2.moode12 (SetActive stale-state fix)
PhilipVinc Aug 20, 2026
c3eb49c
Qobuz Connect: stop nagging about login; add Clear stored credentials
PhilipVinc Aug 20, 2026
31684b5
Qobuz Connect: expose Buffer and Volume control, force headless-sane …
PhilipVinc Aug 20, 2026
6ad7b0d
Qobuz Connect: qbzd 2.0.2.moode14 (loading state during buffering)
PhilipVinc Aug 20, 2026
3089424
Qobuz Connect: qbzd 2.0.2.moode15 (buffering state lasts until audible)
PhilipVinc Aug 20, 2026
b942355
Qobuz Connect: qbzd 2.0.2.moode16 (buffering reports PLAYING)
PhilipVinc Aug 20, 2026
aa68949
Qobuz Connect: document it in the setup and install renderer guides
PhilipVinc Aug 20, 2026
133dc08
Qobuz Connect: pin qbzd 2.0.2.moode17 (buffering/position reporting)
PhilipVinc Aug 20, 2026
b536f5f
Qobuz Connect: pin qbzd 2.0.2.moode18 (loading-state fixes)
PhilipVinc Aug 20, 2026
144ac09
Qobuz Connect: pin qbzd 2.0.2.moode19
PhilipVinc Aug 20, 2026
0684da1
Qobuz Connect: pin qbzd 2.0.2.moode20 (transition report follow-up)
PhilipVinc Aug 20, 2026
7043397
Qobuz Connect: pin qbzd 2.0.2.moode21 (state echo carries a duration)
PhilipVinc Aug 20, 2026
6a708d0
Qobuz Connect: hand playback to the DAC when moOde's chain is empty
PhilipVinc Aug 20, 2026
5a7623f
Qobuz Connect: pin qbzd 2.0.2.moode26 (range requests, dual-rate stat…
PhilipVinc Aug 20, 2026
4389454
Qobuz Connect: cache tracks by default, so gapless works out of the box
PhilipVinc Aug 20, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions etc/alsa/conf.d/qbzd-devices.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#########################################
# This file is managed by moOde
#########################################
# ALSA hints so the qbzd Qobuz Connect renderer can select
# moOde's output chains by name
pcm._audioout.hint.show on
pcm._audioout.hint.description "Moode Audio Output"
pcm.btstream.hint.show on
pcm.btstream.hint.description "Moode Bluetooth Stream"
29 changes: 21 additions & 8 deletions usr/local/bin/moodeutl
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ $features = array(
FEAT_SQUEEZELITE => 'Squeezelite renderer',
FEAT_UPMPDCLI => 'UPnP client for MPD',
FEAT_DEEZER => 'Deezer Connect renderer',
FEAT_QOBUZ => 'Qobuz Connect renderer',
FEAT_ROONBRIDGE => 'RoonBridge renderer',
FEAT_LOCALDISPLAY => 'Local display',
FEAT_INPSOURCE => 'Input source select',
Expand Down Expand Up @@ -163,16 +164,17 @@ switch ($option) {
echo VERSION . "\n";
break;
case '--help':
//[--bluetooth | --airplay | --spotify | --deezer | --upnp | --squeezelite | --plexamp | --roonbridge]
//[--bluetooth | --airplay | --spotify | --deezer | --qobuz | --upnp | --squeezelite | --plexamp | --roonbridge]
$btArg = $featBitmask & FEAT_BLUETOOTH ? '--bluetooth | ' : '';
$apArg = $featBitmask & FEAT_AIRPLAY ? '--airplay | ' : '';
$spArg = $featBitmask & FEAT_SPOTIFY ? '--spotify | ' : '';
$dzArg = $featBitmask & FEAT_DEEZER ? '--deezer | ' : '';
$qbArg = $featBitmask & FEAT_QOBUZ ? '--qobuz | ' : '';
$upArg = $featBitmask & FEAT_UPMPDCLI ? '--upnp | ' : '';
$slArg = $featBitmask & FEAT_SQUEEZELITE ? '--squeezelite | ' : '';
$paArg = $featBitmask & FEAT_PLEXAMP ? '--plexamp | ' : '';
$rbArg = $featBitmask & FEAT_ROONBRIDGE ? '--roonbridge | ' : '';
$rendererList = rtrim($btArg . $apArg . $spArg . $dzArg . $upArg . $slArg . $paArg . $rbArg, ' | ');
$rendererList = rtrim($btArg . $apArg . $spArg . $dzArg . $qbArg . $upArg . $slArg . $paArg . $rbArg, ' | ');
echo
"Usage: moodeutl [OPTION]
Moode utility functions
Expand Down Expand Up @@ -530,6 +532,17 @@ function stopAllRenderers($featBitmask) {
} else {
echo "- deezer connect\tfeature disabled\n";
}
if ($featBitmask & FEAT_QOBUZ) {
$qobuzSvc = trim(sqlQuery("SELECT value FROM cfg_system WHERE param='qobuzsvc'"));
if ($qobuzSvc == '1') {
sysCmd('/var/www/util/restart-renderer.php --qobuz --stop');
echo "- qobuz connect\t\tstopped\n";
} else {
echo "- qobuz connect\t\tnot on\n";
}
} else {
echo "- qobuz connect\t\tfeature disabled\n";
}
if ($featBitmask & FEAT_UPMPDCLI) {
$upSvc = trim(sqlQuery("SELECT value FROM cfg_system WHERE param='upnpsvc'"));
if ($upSvc == '1') {
Expand Down Expand Up @@ -578,8 +591,8 @@ function stopAllRenderers($featBitmask) {

function restartRenderer($argv) {
$renderers = array('--bluetooth' => 'btsvc', '--airplay' => 'airplaysvc', '--spotify' => 'spotifysvc',
'--deezer' => 'deezersvc', '--upnp' => 'upnpsvc', '--squeezelite' => 'slsvc', '--plexamp' => 'pasvc',
'--roonbridge' => 'rbsvc');
'--deezer' => 'deezersvc', '--qobuz' => 'qobuzsvc', '--upnp' => 'upnpsvc', '--squeezelite' => 'slsvc',
'--plexamp' => 'pasvc', '--roonbridge' => 'rbsvc');

if (!isset($argv[2])) {
echo 'Missing 2nd argument [renderer name]' . "\n";
Expand All @@ -593,7 +606,7 @@ function restartRenderer($argv) {
}
} else {
echo 'Invalid renderer name' . "\n";
echo 'Valid names are: --bluetooth, --airplay, --spotify, --deezer, --upnp, --squeezelite, --plexamp, --roonbridge' . "\n";
echo 'Valid names are: --bluetooth, --airplay, --spotify, --deezer, --qobuz, --upnp, --squeezelite, --plexamp, --roonbridge' . "\n";
return;
}

Expand All @@ -603,15 +616,15 @@ function restartRenderer($argv) {

function rendererOnoff($argv) {
$renderers = array('--bluetooth' => 'btsvc', '--airplay' => 'airplaysvc', '--spotify' => 'spotifysvc',
'--deezer' => 'deezersvc', '--upnp' => 'upnpsvc', '--squeezelite' => 'slsvc', '--plexamp' => 'pasvc',
'--roonbridge' => 'rbsvc');
'--deezer' => 'deezersvc', '--qobuz' => 'qobuzsvc', '--upnp' => 'upnpsvc', '--squeezelite' => 'slsvc',
'--plexamp' => 'pasvc', '--roonbridge' => 'rbsvc');

if (!isset($argv[2])) {
echo 'Missing 2nd argument [renderer name]' . "\n";
return;
} else if (!array_key_exists($argv[2], $renderers)) {
echo 'Invalid renderer name' . "\n";
echo 'Valid names are: --bluetooth, --airplay, --spotify, --deezer, --upnp, --squeezelite, --plexamp, --roonbridge' . "\n";
echo 'Valid names are: --bluetooth, --airplay, --spotify, --deezer, --qobuz, --upnp, --squeezelite, --plexamp, --roonbridge' . "\n";
return;
} else if (!isset($argv[3])) {
echo 'Missing 3nd argument [on|off]' . "\n";
Expand Down
247 changes: 247 additions & 0 deletions var/local/www/commandw/qbzevent.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,247 @@
#!/bin/bash
#
# SPDX-License-Identifier: GPL-3.0-or-later
# Copyright 2014 The moOde audio player project / Tim Curtis
#
# Qobuz Connect (qbzd) event hook. qbzd forks this script once per daemon
# event with the event described in QBZ_* environment variables (set via
# QBZD_HOOK, see startQobuz() in inc/renderer.php).
#

LOGFILE="/var/log/moode_qbzevent.log"
DEBUG=$(sudo moodeutl -d -gv debuglog)
SQLDB=/var/local/www/db/moode-sqlite3.db

QBZMETA_CACHE_FILE="/var/local/www/qbzmeta.json"
QBZD_API="http://127.0.0.1:8182"
# Budget for retrying a start that failed because the audio device was still
# busy (e.g. shairport-sync releasing it late). qbzd does not retry on its own.
RETRY_FILE="/tmp/qbzevent-retry-budget"
RETRY_BUDGET=5

debug_log () {
if [[ $DEBUG == '0' ]]; then
return 0
fi
echo "$1"
TIME=$(date +'%Y%m%d %H%M%S')
echo "$TIME $1" >> $LOGFILE
}

PLAYER_EVENTS=(
PlaybackStateChanged
TrackStarted
QconnectSessionChanged
PlaybackError
)

MATCH=0
for MATCH_EVENT in "${PLAYER_EVENTS[@]}"
do
if [[ $QBZ_EVENT == $MATCH_EVENT ]]; then
MATCH=1
debug_log "Process: "$QBZ_EVENT
fi
done
# Exit and log if not a match
if [[ $MATCH == 0 ]]; then
debug_log "Logged: "$QBZ_EVENT
exit 0
fi

# qbzd forks this script once per event without waiting so invocations can
# overlap: serialize them (and their cfg_system updates) to preserve ordering
exec 9> /tmp/qbzevent.lock
flock 9

# cfg_system (rows come back in id order)
RESULT=$(sqlite3 -cmd '.timeout 5000' $SQLDB "SELECT value FROM cfg_system WHERE param IN ('alsavolume_max','alsavolume','amixname','camilladsp_volume_sync','inpactive','multiroom_tx','rsmafterqbz','qbzactive') ORDER BY id")
readarray -t arr <<<"$RESULT"
ALSAVOLUME_MAX=${arr[0]}
ALSAVOLUME=${arr[1]}
AMIXNAME=${arr[2]}
CDSP_VOLSYNC=${arr[3]}
INPACTIVE=${arr[4]}
MULTIROOM_TX=${arr[5]}
RSMAFTERQBZ=${arr[6]}
QBZACTIVE=${arr[7]}
RX_ADDRESSES=$(sudo moodeutl -d -gv rx_addresses)

if [[ $INPACTIVE == '1' ]]; then
exit 1
fi

activate () {
if [[ $QBZACTIVE == '1' ]]; then
return 0
fi
QBZACTIVE='1'
$(sqlite3 -cmd '.timeout 5000' $SQLDB "UPDATE cfg_system SET value='1' WHERE param='qbzactive'")
# Take over the audio device
/usr/bin/mpc stop > /dev/null
# Send to front-end
/var/www/util/send-fecmd.php "qbzactive1"
# Arm the failed-start retry budget, but never replenish it here: a retry
# goes through loading (re-activation) again and would otherwise reset its
# own budget. Only a real start (TrackStarted) replenishes.
if [[ ! -f $RETRY_FILE ]]; then
echo $RETRY_BUDGET > $RETRY_FILE
fi

# Local
if [[ $CDSP_VOLSYNC == "on" ]]; then
# Set 0dB CDSP volume
sed -i '0,/- -.*/s//- 0.0/' /var/lib/cdsp/statefile.yml
elif [[ $ALSAVOLUME != "none" ]]; then
# Set 0dB ALSA volume
/var/www/util/sysutil.sh set-alsavol "$AMIXNAME" $ALSAVOLUME_MAX
fi

# Multiroom receivers
if [[ $MULTIROOM_TX == "On" ]]; then
for IP_ADDR in $RX_ADDRESSES; do
RESULT=$(curl -G -S -s --data-urlencode "cmd=trx_control -set-alsavol" http://$IP_ADDR/command/)
if [[ $RESULT != "" ]]; then
RESULT=$(curl -G -S -s --data-urlencode "cmd=trx_control -set-alsavol" http://$IP_ADDR/command/)
if [[ $RESULT != "" ]]; then
echo $(date +%F" "%T) "Event: trx_control -set-alsavol failed: $IP_ADDR" >> $LOGFILE
fi
fi
done
fi
}

# True while qbzd still owns playback: playing, or paused with a live Connect
# session (the session keeps the audio device across a pause, AirPlay parity).
# Fail-safe: an unreachable control API answers "not active" so a dead daemon
# always releases the UI.
still_active () {
local STATE
STATE=$(curl -s --max-time 2 $QBZD_API/api/status | \
jq -r '"\(.playback.state) \(.qconnect.session_active)"' 2>/dev/null)
case "$STATE" in
"playing true"|"paused true") return 0 ;;
*) return 1 ;;
esac
}

deactivate () {
if [[ $QBZACTIVE == '0' ]]; then
return 0
fi
# Verify against the daemon before tearing the render down. Transient
# stopped/error events fire during normal operation — a gapless track
# transition, a superseded stream being abandoned on track change — and
# acting on them dropped the overlay mid-playback, so every later UI
# rebuild (click, resize, page load) showed the library panel instead.
debug_log "Deact?: from $QBZ_EVENT (state=$QBZ_STATE session_active=$QBZ_SESSION_ACTIVE)"
if still_active; then
debug_log "Keep: render (daemon still active)"
return 0
fi
QBZACTIVE='0'
# Worker picks this up and sends qbzactive0 to front-end
$(sqlite3 -cmd '.timeout 5000' $SQLDB "UPDATE cfg_system SET value='0' WHERE param='qbzactive'")
# NOTE: the retry budget survives deactivation on purpose. A failed start
# arrives as loading -> paused -> PlaybackError, so the budget must still
# be there when the PlaybackError event is processed after the pause.

# Local
/var/www/util/vol.sh -restore

if [[ $CDSP_VOLSYNC == "on" ]]; then
# Restore CDSP volume
systemctl restart mpd2cdspvolume
fi

# Multiroom receivers
if [[ $MULTIROOM_TX == "On" ]]; then
for IP_ADDR in $RX_ADDRESSES; do
RESULT=$(curl -G -S -s --data-urlencode "cmd=set_volume -restore" http://$IP_ADDR/command/)
if [[ $RESULT != "" ]]; then
RESULT=$(curl -G -S -s --data-urlencode "cmd=set_volume -restore" http://$IP_ADDR/command/)
if [[ $RESULT != "" ]]; then
echo $(date +%F" "%T) "Event: set_volume -restore failed: $IP_ADDR" >> $LOGFILE
fi
fi
done
fi
}

if [[ $QBZ_EVENT == "PlaybackStateChanged" ]]; then
if [[ $QBZ_STATE == "playing" || $QBZ_STATE == "loading" ]]; then
activate
elif [[ $QBZ_STATE == "stopped" ]]; then
deactivate
fi
# NOTE: paused KEEPS the render (AirPlay/Spotify parity — their flags are
# session-scoped). The session still owns the audio device while paused,
# and any renderUI rebuild (page load, window resize) reads qbzactive from
# cfg_system — deactivating on pause made the overlay vanish on reload or
# resize whenever playback happened to be paused.
fi

if [[ $QBZ_EVENT == "QconnectSessionChanged" ]]; then
if [[ $QBZ_SESSION_ACTIVE == "false" ]]; then
WAS_ACTIVE=$QBZACTIVE
deactivate
# Session gone: no more start attempts to retry
rm -f $RETRY_FILE
if [[ $WAS_ACTIVE == '1' && $RSMAFTERQBZ == "Yes" ]]; then
/usr/bin/mpc play > /dev/null
fi
fi
fi

# A start attempt can fail because the audio device is still busy: retry
if [[ $QBZ_EVENT == "PlaybackError" ]]; then
debug_log "Error: "$QBZ_MESSAGE
RETRIES_LEFT=$(cat $RETRY_FILE 2> /dev/null || echo 0)
MPD_PLAYING=$(/usr/bin/mpc status | grep playing)
if [[ $RETRIES_LEFT -gt 0 && -z $MPD_PLAYING ]]; then
echo $((RETRIES_LEFT - 1)) > $RETRY_FILE
sleep 1
qbzd play -q
else
# Out of retries (or MPD grabbed the device): since paused no longer
# deactivates, release the render here or a failed start would leave
# the UI locked on a silent session.
deactivate
fi
fi

# Update metadata and send to front-end
if [[ $QBZ_EVENT == "TrackStarted" ]]; then
activate
# Playback started: replenish the failed-start retry budget
echo $RETRY_BUDGET > $RETRY_FILE
SFORMAT="FLAC $QBZ_BIT_DEPTH/$QBZ_SAMPLE_RATE kHz"
# Output format from the control API. /api/status, NOT /api/now-playing: the
# latter is login-gated and the pairing flow never logs in (the casting app
# hands over its own session), so it answers needs_auth and this fell back to
# claiming the OUTPUT was FLAC. /api/status also carries the rate the DEVICE
# runs at (qbzd 2.0.2.moode25+), which is the number that differs from the
# source whenever something in the chain resamples.
AUDIO_JSON=$(curl -s --max-time 2 $QBZD_API/api/status | jq -c '.audio // {}' 2>/dev/null)
OFORMAT=$(jq -rn --argjson a "${AUDIO_JSON:-{\}}" '
(if $a.output_sample_rate != null then $a.output_sample_rate else $a.sample_rate end) as $r
| if $a.bit_depth != null and $r != null then "PCM \($a.bit_depth)/\($r / 1000) kHz" else empty end
' 2>/dev/null)
if [[ -z $OFORMAT ]]; then
# Never fall back to SFORMAT: the decoder always emits PCM, so echoing the
# source container here is the one answer that is certainly wrong.
OFORMAT="PCM $QBZ_BIT_DEPTH/$QBZ_SAMPLE_RATE kHz"
fi
METADATA_JSON=$(jq -n -c \
--arg a "update_qbzmeta" \
--arg b "$QBZ_TITLE" \
--arg c "$QBZ_ARTIST" \
--arg d "$QBZ_ALBUM" \
--arg e "$QBZ_DURATION" \
--arg f "$QBZ_COVER_URL" \
--arg g "$SFORMAT" \
--arg h "$OFORMAT" \
'{fecmd: $a, title: $b, artist: $c, album: $d, duration: $e, cover_url: $f, sformat: $g, oformat: $h}')
echo -e "$METADATA_JSON" > $QBZMETA_CACHE_FILE
/var/www/util/send-fecmd.php "$METADATA_JSON"
fi
19 changes: 18 additions & 1 deletion var/local/www/db/moode-sqlite3.db.sql
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,19 @@ INSERT INTO cfg_plugin (id, component, type, plugin, version) VALUES (3, 'render
INSERT INTO cfg_plugin (id, component, type, plugin, version) VALUES (4, 'renderer', 'spotify-connect', 'v8-librespot', '0.8.0-1moode1');
INSERT INTO cfg_plugin (id, component, type, plugin, version) VALUES (5, 'system', 'nqptp', 'v1-nqptp', '1.2.6-1moode1');

-- Table: cfg_qobuz
CREATE TABLE cfg_qobuz (id INTEGER PRIMARY KEY, param CHAR (32), value CHAR (32));
INSERT INTO cfg_qobuz (id, param, value) VALUES (1, 'quality', 'hires_plus');
INSERT INTO cfg_qobuz (id, param, value) VALUES (2, 'gapless', 'Yes');
INSERT INTO cfg_qobuz (id, param, value) VALUES (3, 'normalize_volume', 'No');
INSERT INTO cfg_qobuz (id, param, value) VALUES (4, 'pairing', 'Yes');
INSERT INTO cfg_qobuz (id, param, value) VALUES (5, 'buffer_seconds', '2');
INSERT INTO cfg_qobuz (id, param, value) VALUES (6, 'volume_mode', 'auto');
INSERT INTO cfg_qobuz (id, param, value) VALUES (7, 'output_mode', 'auto');
INSERT INTO cfg_qobuz (id, param, value) VALUES (8, 'stream_first', 'Yes');
INSERT INTO cfg_qobuz (id, param, value) VALUES (9, 'track_cache', 'Yes');
INSERT INTO cfg_qobuz (id, param, value) VALUES (10, 'quality_fallback', 'fallback');

-- Table: cfg_radio
CREATE TABLE cfg_radio (id INTEGER PRIMARY KEY, station CHAR (128), name CHAR (128), type CHAR (1), logo CHAR (128), genre CHAR (32), broadcaster CHAR (32), language CHAR (32), country CHAR (32), region CHAR (32), bitrate CHAR (32), format CHAR (32), geo_fenced CHAR (3), home_page CHAR (32), monitor CHAR (32));
INSERT INTO cfg_radio (id, station, name, type, logo, genre, broadcaster, language, country, region, bitrate, format, geo_fenced, home_page, monitor) VALUES (1, 'http://strm112.1.fm/blues_mobile_mp3', '1.FM - Blues Radio', 'r', 'local', 'Blues', '1.FM', 'English', 'Switzerland', 'Europe', '192', 'MP3', 'No', '', 'No');
Expand Down Expand Up @@ -907,7 +920,7 @@ INSERT INTO cfg_system (id, param, value) VALUES (77, 'cardnum', '0');
INSERT INTO cfg_system (id, param, value) VALUES (78, 'btsvc', '0');
INSERT INTO cfg_system (id, param, value) VALUES (79, 'btname', 'Moode Bluetooth');
INSERT INTO cfg_system (id, param, value) VALUES (80, 'camilladsp_volume_sync', 'off');
INSERT INTO cfg_system (id, param, value) VALUES (81, 'feat_bitmask', '228279');
INSERT INTO cfg_system (id, param, value) VALUES (81, 'feat_bitmask', '490423');
INSERT INTO cfg_system (id, param, value) VALUES (82, 'library_recently_added', '2592000000');
INSERT INTO cfg_system (id, param, value) VALUES (83, 'btactive', '0');
INSERT INTO cfg_system (id, param, value) VALUES (84, 'deezersvc', '0');
Expand Down Expand Up @@ -1002,6 +1015,10 @@ INSERT INTO cfg_system (id, param, value) VALUES (172, 'library_onetouch_pl', 'S
INSERT INTO cfg_system (id, param, value) VALUES (173, 'scnsaver_mode', 'Cover art');
INSERT INTO cfg_system (id, param, value) VALUES (174, 'scnsaver_layout', 'Default');
INSERT INTO cfg_system (id, param, value) VALUES (175, 'scnsaver_xmeta', 'Yes');
INSERT INTO cfg_system (id, param, value) VALUES (176, 'rsmafterqbz', 'No');
INSERT INTO cfg_system (id, param, value) VALUES (177, 'qbzactive', '0');
INSERT INTO cfg_system (id, param, value) VALUES (178, 'qobuzsvc', '0');
INSERT INTO cfg_system (id, param, value) VALUES (179, 'qobuzname', 'Moode Qobuz');

-- Table: cfg_theme
CREATE TABLE cfg_theme (id INTEGER PRIMARY KEY, theme_name CHAR (32), tx_color CHAR (32), bg_color CHAR (32), mbg_color CHAR (32));
Expand Down
2 changes: 2 additions & 0 deletions www/CONTRIBS.html
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ <h4>Contribs</h4>
<a href="https://github.com/project-owner" target="_blank">https://github.com/project-owner</a><br>
Pleezer by Roderick Van Domburg<br>
<a href="https://github.com/roderickvd/pleezer" target="_blank">https://github.com/roderickvd/pleezer</a><br>
QBZ (qbzd) by vicrodh, forker by Filippo Vicentini<br>
<a href="https://github.com/PhilipVinc/qbz" target="_blank">https://github.com/PhilipVinc/qbz</a><br>
Qix color-convert by Heather Arthur and Josh Junon<br>
<a href="https://github.com/Qix-/color-convert" target="_blank">https://github.com/Qix-/color-convert</a><br>
RPi.GPIO by Ben Croston<br>
Expand Down
Loading