Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
T
Tidal
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
PLN
Tidal
Commits
446cbe1e
Commit
446cbe1e
authored
Nov 01, 2026
by
PLN (Algolia)
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
tools: music-mode switch arms protection before any bring-up
parent
bdb29c99
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
107 additions
and
13 deletions
+107
-13
gig-up.sh
gig-up.sh
+3
-0
gig-up.sh
tools/gig-up.sh
+3
-0
install-protect.sh
tools/install-protect.sh
+2
-1
music-mode.sh
tools/music-mode.sh
+56
-0
parvagues-protect.sh
tools/parvagues-protect.sh
+43
-12
No files found.
gig-up.sh
View file @
446cbe1e
...
@@ -331,6 +331,9 @@ launch_bin(){ # launch_bin "<label>" <binary names...> — first found, detache
...
@@ -331,6 +331,9 @@ launch_bin(){ # launch_bin "<label>" <binary names...> — first found, detache
# ---------------------------------------------------------------------------
# ---------------------------------------------------------------------------
echo
echo
info
"gig-up — ordered launch from
$DIR
"
info
"gig-up — ordered launch from
$DIR
"
# Arm root protection before any sound process starts. The service itself stays
# parked on work days; a failed arm must fail the launch loudly.
"
$DIR
/tools/music-mode.sh"
on
||
exit
1
ensure_perf
ensure_perf
cut_gpu
cut_gpu
...
...
tools/gig-up.sh
View file @
446cbe1e
...
@@ -192,6 +192,9 @@ read -r SC ARD <<<"$(rig_state)"
...
@@ -192,6 +192,9 @@ read -r SC ARD <<<"$(rig_state)"
# broken. A healthy rig converges to a no-op: nothing restarts, nothing makes a sound,
# broken. A healthy rig converges to a no-op: nothing restarts, nothing makes a sound,
# no MIDI is sent, and CC 77-84 / CC 93 are never touched by anything here.
# no MIDI is sent, and CC 77-84 / CC 93 are never touched by anything here.
if
((
CONVERGE
))
;
then
if
((
CONVERGE
))
;
then
# This older CLI path can still start SuperDirt; arm protection first just as
# the desktop/Bridge launcher does.
tools/music-mode.sh on
||
exit
1
((
QUIET
))
||
{
echo
"
${
D
}
converge — starting what is missing
${
Z
}
"
;
}
((
QUIET
))
||
{
echo
"
${
D
}
converge — starting what is missing
${
Z
}
"
;
}
did
=
0
did
=
0
...
...
tools/install-protect.sh
View file @
446cbe1e
#!/usr/bin/env bash
#!/usr/bin/env bash
# install-protect — put parvagues-protect where root can safely run it.
# install-protect — put parvagues-protect where root can safely run it.
#
#
# sudo tools/install-protect.sh install + enable
+ start
# sudo tools/install-protect.sh install + enable
parked watcher
# sudo tools/install-protect.sh --uninstall
# sudo tools/install-protect.sh --uninstall
#
#
# WHY THE SCRIPT IS COPIED INSTEAD OF SYMLINKED
# WHY THE SCRIPT IS COPIED INSTEAD OF SYMLINKED
...
@@ -46,6 +46,7 @@ systemctl enable parvagues-protect.service
...
@@ -46,6 +46,7 @@ systemctl enable parvagues-protect.service
# Always restart; this daemon holds no ports and makes no sound, so a restart
# Always restart; this daemon holds no ports and makes no sound, so a restart
# costs nothing.
# costs nothing.
systemctl restart parvagues-protect.service
systemctl restart parvagues-protect.service
echo
"Protection watcher installed. It stays parked until tools/music-mode.sh on."
sleep 3
sleep 3
echo
echo
...
...
tools/music-mode.sh
0 → 100755
View file @
446cbe1e
#!/usr/bin/env bash
# The user-owned switch read by the root-owned ParVagues protector.
set
-euo
pipefail
dir
=
"/run/user/
$(
id
-u
)
/parvagues"
flag
=
"
$dir
/protection-on"
installed
=
/usr/local/bin/parvagues-protect
mode_supported
()
{
[[
-r
"
$installed
"
]]
&&
grep
-q
'^MODE_FILE='
"
$installed
"
}
music_running
()
{
local
path name
for
path
in
/proc/[0-9]
*
/comm
;
do
IFS
=
read
-r
name <
"
$path
"
2>/dev/null
||
continue
case
"
$name
"
in
sclang|scsynth|supernova|ardour|ardour[0-9]
*
|
ardour-[0-9]
*
|
ArdourGUI
)
return
0
;;
esac
done
return
1
}
case
"
${
1
:-
status
}
"
in
on
)
if
!
systemctl is-active
--quiet
parvagues-protect.service
;
then
echo
"ParVagues protection is not running; run: sudo tools/install-protect.sh"
>
&2
exit
1
fi
mkdir
-p
-m
700
"
$dir
"
chmod 700
"
$dir
"
:
>
"
$flag
"
echo
"Music mode on: protection armed."
;;
off
)
if
music_running
;
then
echo
"Close SuperCollider/Ardour before leaving music mode."
>
&2
exit
1
fi
rm
-f
"
$flag
"
if
!
mode_supported
;
then
echo
"Mode flag cleared, but the installed protector still scans continuously."
>
&2
echo
"Deploy the mode-aware copy: sudo tools/install-protect.sh"
>
&2
exit
1
fi
echo
"Music mode off: protection parked."
;;
status
)
if
[[
-f
"
$flag
"
]]
;
then
state
=
on
;
else
state
=
off
;
fi
if
mode_supported
;
then
policy
=
mode-aware
;
else
policy
=
legacy-always-on
;
fi
printf
'music mode: %s; protector: %s; policy: %s\n'
"
$state
"
\
"
$(
systemctl is-active parvagues-protect.service 2>/dev/null
||
true
)
"
"
$policy
"
;;
*
)
echo
"Usage: music-mode.sh [on|off|status]"
>
&2
;
exit
2
;;
esac
tools/parvagues-protect.sh
View file @
446cbe1e
...
@@ -73,6 +73,11 @@
...
@@ -73,6 +73,11 @@
set
-uo
pipefail
set
-uo
pipefail
INTERVAL
=
"
${
PARVAGUES_PROTECT_INTERVAL
:-
2
}
"
INTERVAL
=
"
${
PARVAGUES_PROTECT_INTERVAL
:-
2
}
"
# The system service stays installed and enabled, but does no /proc sweep until
# the user explicitly enters music mode. /run/user is cleared at reboot, so a
# work session starts parked even after an unclean shutdown during a gig.
MODE_OWNER
=
"
${
PARVAGUES_MODE_OWNER
:-
pln
}
"
MODE_FILE
=
"/run/user/
$(
id
-u
"
$MODE_OWNER
"
)
/parvagues/protection-on"
# name:rtprio:comm-regex — the priorities perf.sh established and PLN has
# name:rtprio:comm-regex — the priorities perf.sh established and PLN has
# played on. scsynth is the audio server, sclang feeds it, Ardour records the
# played on. scsynth is the audio server, sclang feeds it, Ardour records the
...
@@ -89,7 +94,12 @@ INTERVAL="${PARVAGUES_PROTECT_INTERVAL:-2}"
...
@@ -89,7 +94,12 @@ INTERVAL="${PARVAGUES_PROTECT_INTERVAL:-2}"
TARGETS
=(
TARGETS
=(
"scsynth:90:scsynth"
"scsynth:90:scsynth"
"sclang:85:sclang"
"sclang:85:sclang"
"ardour:80:ardour|ardour[0-9]+|ArdourGUI|ardour-[0-9.]+"
# 0 = OOM shield only, NO realtime promotion. Ardour's AudioEngine thread
# already gets FIFO/83 from the backend; promoting the GUI thread to FIFO/80
# killed Ardour outright via RLIMIT_RTTIME on desktop-icon launches (200ms,
# inherited from gnome-shell) and starved the audio thread via RT bandwidth
# throttling. See tools/fix-ardour-rt.sh for the measurement. 2026-09-24.
"ardour:0:ardour|ardour[0-9]+|ArdourGUI|ardour-[0-9.]+"
)
)
OOM_TARGET
=
-1000
OOM_TARGET
=
-1000
...
@@ -230,12 +240,14 @@ protect_pid() {
...
@@ -230,12 +240,14 @@ protect_pid() {
# Only promote. A process already at a HIGHER realtime priority than we ask
# Only promote. A process already at a HIGHER realtime priority than we ask
# for was tuned by someone who knew more than this script does.
# for was tuned by someone who knew more than this script does.
sched_of
"
$pid
"
||
return
0
# A prio of 0 means OOM shield only. Never promote Ardour's GUI thread.
if
[
"
$S_POL
"
!=
"SCHED_FIFO"
]
||
[
"
${
S_PRIO
:-
0
}
"
-lt
"
$prio
"
]
;
then
if
[
"
${
prio
:-
0
}
"
-gt
0
]
&&
sched_of
"
$pid
"
;
then
if
chrt
-f
-p
"
$prio
"
"
$pid
"
2>/dev/null
;
then
if
[
"
$S_POL
"
!=
"SCHED_FIFO"
]
||
[
"
${
S_PRIO
:-
0
}
"
-lt
"
$prio
"
]
;
then
out+
=
" sched:
${
S_POL
:-
?
}
/
${
S_PRIO
:-
?
}
->FIFO/
${
prio
}
"
if
chrt
-f
-p
"
$prio
"
"
$pid
"
2>/dev/null
;
then
else
out+
=
" sched:
${
S_POL
:-
?
}
/
${
S_PRIO
:-
?
}
->FIFO/
${
prio
}
"
out+
=
" sched:FAILED"
else
out+
=
" sched:FAILED"
fi
fi
fi
fi
fi
...
@@ -282,7 +294,7 @@ sweep() {
...
@@ -282,7 +294,7 @@ sweep() {
# Absent processes are NOT a failure here: "Ardour is not open yet" is a normal
# Absent processes are NOT a failure here: "Ardour is not open yet" is a normal
# state ten minutes before doors, and the gate already checks liveness elsewhere.
# state ten minutes before doors, and the gate already checks liveness elsewhere.
check
()
{
check
()
{
local
bad
=
0
found
=
0 name pid adj pids
local
bad
=
0
found
=
0 name pid adj pids
prio
scan
scan
for
t
in
"
${
TARGETS
[@]
}
"
;
do
for
t
in
"
${
TARGETS
[@]
}
"
;
do
name
=
"
${
t
%%
:
*
}
"
name
=
"
${
t
%%
:
*
}
"
...
@@ -298,9 +310,18 @@ check() {
...
@@ -298,9 +310,18 @@ check() {
found
=
1
found
=
1
read
-r
adj 2>/dev/null <
"/proc/
$pid
/oom_score_adj"
||
adj
=
"?"
read
-r
adj 2>/dev/null <
"/proc/
$pid
/oom_score_adj"
||
adj
=
"?"
sched_of
"
$pid
"
||
S_POL
=
""
sched_of
"
$pid
"
||
S_POL
=
""
if
[
"
$adj
"
!=
"
$OOM_TARGET
"
]
||
[
"
$S_POL
"
!=
"SCHED_FIFO"
]
;
then
# A zero priority means OOM protection only; scheduling is left alone.
echo
"UNPROTECTED
$name
[
$pid
] oom_score_adj=
$adj
sched=
${
S_POL
:-
none
}
(want
$OOM_TARGET
/ SCHED_FIFO)"
prio
=
"
${
t
#*
:
}
"
;
prio
=
"
${
prio
%%
:
*
}
"
if
[
"
$adj
"
!=
"
$OOM_TARGET
"
]
\
||
{
[
"
${
prio
:-
0
}
"
-gt
0
]
&&
[
"
$S_POL
"
!=
"SCHED_FIFO"
]
;
}
;
then
if
[
"
${
prio
:-
0
}
"
-gt
0
]
;
then
echo
"UNPROTECTED
$name
[
$pid
] oom_score_adj=
$adj
sched=
${
S_POL
:-
none
}
(want
$OOM_TARGET
/ SCHED_FIFO)"
else
echo
"UNPROTECTED
$name
[
$pid
] oom_score_adj=
$adj
(want
$OOM_TARGET
; scheduling deliberately left alone)"
fi
bad
=
1
bad
=
1
elif
[
"
${
prio
:-
0
}
"
-eq
0
]
;
then
echo
"ok
$name
[
$pid
] oom_score_adj=
$adj
sched=
${
S_POL
:-
OTHER
}
(oom shield only, by design)"
else
else
echo
"ok
$name
[
$pid
] oom_score_adj=
$adj
sched=
$S_POL
/
${
S_PRIO
}
"
echo
"ok
$name
[
$pid
] oom_score_adj=
$adj
sched=
$S_POL
/
${
S_PRIO
}
"
fi
fi
...
@@ -321,8 +342,18 @@ esac
...
@@ -321,8 +342,18 @@ esac
_names
=
""
_names
=
""
for
t
in
"
${
TARGETS
[@]
}
"
;
do
_p
=
"
${
t
#*
:
}
"
;
_names+
=
"
${
t
%%
:
*
}
/
${
_p
%%
:
*
}
"
;
done
for
t
in
"
${
TARGETS
[@]
}
"
;
do
_p
=
"
${
t
#*
:
}
"
;
_names+
=
"
${
t
%%
:
*
}
/
${
_p
%%
:
*
}
"
;
done
log
"parvagues-protect: watching
${
_names
}
every
${
INTERVAL
}
s (oom=
$OOM_TARGET
)"
log
"parvagues-protect: parked; watching
${
_names
}
when music mode is on (oom=
$OOM_TARGET
)"
armed
=
0
while
:
;
do
while
:
;
do
sweep
if
[[
-f
"
$MODE_FILE
"
]]
;
then
if
[[
"
$armed
"
-eq
0
]]
;
then
log
"music mode on: protecting
${
_names
}
every
${
INTERVAL
}
s"
armed
=
1
fi
sweep
elif
[[
"
$armed
"
-eq
1
]]
;
then
log
"music mode off: protection parked"
armed
=
0
fi
sleep
"
$INTERVAL
"
sleep
"
$INTERVAL
"
done
done
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment