mpv: sane-sysvol script: init

it's a one-way volume control, but that's a start
This commit is contained in:
Colin 2024-04-07 00:01:29 +00:00
parent 17a3f90825
commit 79c4e2c405
2 changed files with 50 additions and 37 deletions

View File

@ -91,48 +91,23 @@ let
local last_up = cursor.last_event['primary_up'] or { time = 0 }
if cursor.hover_raw or last_down.time >= last_up.time then cursor:move(mouse.x, mouse.y) end"
### patch so that the volume control corresponds to `ao-volume`, i.e. the system-wide volume.
### patch so that uosc volume control is routed to sane-sysvol.
### this is particularly nice for moby, because it avoids the awkwardness that system volume
### is hard to adjust while screen is on.
### note that only under alsa (`-ao=alsa`) does `ao-volume` actually correspond to system volume.
### previously i used ao-volume instead of sane-sysvol: but that forced `ao=alsa`
### and came with heavy perf penalties (especially when adjusting the volume)
substituteInPlace src/uosc/main.lua \
--replace-fail \
"mp.observe_property('volume', 'number', create_state_setter('volume'))" \
"mp.observe_property('volume', 'number', update_ao_volume)"
"mp.observe_property('volume'" \
"mp.observe_property('user-data/sane-sysvol/volume'" \
--replace-fail 'volume = nil' 'volume = 0'
substituteInPlace src/uosc/elements/Volume.lua \
--replace-fail "mp.commandv('set', 'volume'" "mp.commandv('set', 'ao-volume'" \
--replace-fail "mp.set_property_native('volume'" "mp.set_property('ao-volume'"
# `ao-volume` isn't actually an observable property.
# as of 2024/03/02, they *may* be working on that:
# - <https://github.com/mpv-player/mpv/pull/13604#issuecomment-1971665736>
# in the meantime, just query the volume every tick (i.e. frame).
# alternative is mpv's JSON IPC feature, where i could notify its socket whenever pipewire volume changes.
cat <<EOF >> src/uosc/main.lua
function update_ao_volume(_, vol)
if vol == nil then
-- vol will be nil if called manually, instead of via observe_property
vol = mp.get_property('ao-volume')
end
if vol == nil then
vol = 0
else
vol = tonumber(vol)
end
if vol ~= state.volume then
set_state('volume', vol)
request_render()
end
end
-- tick seems to occur on every redraw (even when volume is hidden).
-- in practice: for every new frame of the source, or whenever the cursor is moved.
mp.register_event('tick', update_ao_volume)
-- if paused and cursor isn't moving, then `tick` isn't called. fallback to a timer.
mp.add_periodic_timer(2, update_ao_volume)
-- invoke immediately to ensure state.volume is non-nil
update_ao_volume()
EOF
--replace-fail \
"mp.commandv('set', 'volume'" \
"mp.set_property_native('user-data/sane-sysvol/volume'" \
--replace-fail \
"mp.set_property_native('volume'" \
"mp.set_property_native('user-data/sane-sysvol/volume'"
'';
});
mpv-unwrapped = pkgs.mpv-unwrapped.overrideAttrs (upstream: {
@ -217,6 +192,7 @@ in
".local/state/mpv"
];
fs.".config/mpv/scripts/sane-cast/main.lua".symlink.target = ./sane-cast-main.lua;
fs.".config/mpv/scripts/sane-sysvol/main.lua".symlink.target = ./sane-sysvol-main.lua;
fs.".config/mpv/input.conf".symlink.target = ./input.conf;
fs.".config/mpv/mpv.conf".symlink.target = ./mpv.conf;
fs.".config/mpv/script-opts/osc.conf".symlink.target = ./osc.conf;

View File

@ -0,0 +1,37 @@
msg = require('mp.msg')
msg.trace('sane-sysvol: load: begin')
function subprocess(args)
mp.command_native({
name = "subprocess",
args = args,
-- these arguments below probably don't matter: copied from sane-cast
detach = false,
capture_stdout = false,
capture_stderr = false,
passthrough_stdin = false,
playback_only = false,
})
end
function translate_out(vol)
-- called when mpv wants to set the system-wide volume
local volstr = tostring(vol) .. "%"
msg.trace("setting system-wide volume:", volstr)
if vol == nil then
return
end
subprocess({
"wpctl",
"set-volume",
"@DEFAULT_AUDIO_SINK@",
volstr
})
end
mp.set_property_native('user-data/sane-sysvol/volume', 0)
mp.observe_property('user-data/sane-sysvol/volume', 'native', function(_, val)
translate_out(val)
end)
msg.trace('sane-sysvol: load: complete')