Colin
8af962c3a6
so now i can listen to whole albums by opening any file from within them. and for shows the next episode will automatically launch.
264 lines
12 KiB
Nix
264 lines
12 KiB
Nix
# curated mpv mods/scripts/users:
|
|
# - <https://github.com/stax76/awesome-mpv>
|
|
# mpv docs:
|
|
# - <https://mpv.io/manual/master>
|
|
# - <https://github.com/mpv-player/mpv/wiki>
|
|
# extensions i use:
|
|
# - <https://github.com/jonniek/mpv-playlistmanager>
|
|
# debugging:
|
|
# - enter console by pressing backtick.
|
|
# > `set volume 50` -> sets application volume to 50%
|
|
# > `set ao-volume 50` -> sets system-wide volume to 50%
|
|
# > `show-text "vol: ${volume}"` -> get the volume
|
|
# - show script output by running mpv with `--msg-level=all=trace`
|
|
# - and then just `print(...)` from lua & it'll show in terminal
|
|
# - invoke mpv with `--no-config` to have it not read ~/.config/mpv/*
|
|
# - press `i` to show decoder info
|
|
#
|
|
# usage tips:
|
|
# - `<` or `>` to navigate prev/next-file-in-folder (uosc)
|
|
# - shift+enter to view the playlist, then arrow-keys to navigate (mpv-playlistmanager)
|
|
{ config, lib, pkgs, ... }:
|
|
|
|
let
|
|
cfg = config.sane.programs.mpv;
|
|
uosc = pkgs.mpvScripts.uosc.overrideAttrs (upstream: {
|
|
# patch so that the volume control corresponds to `ao-volume`, i.e. the system-wide volume.
|
|
# 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.
|
|
postPatch = (upstream.postPatch or "") + ''
|
|
substituteInPlace src/uosc/main.lua \
|
|
--replace-fail "mp.observe_property('volume'" "mp.observe_property('ao-volume'"
|
|
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()
|
|
local vol = mp.get_property('ao-volume')
|
|
if vol ~= nil then
|
|
vol = tonumber(vol)
|
|
if vol ~= state.volume then
|
|
set_state('volume', vol)
|
|
request_render()
|
|
end
|
|
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()
|
|
if state.volume == nil then
|
|
state.volume = 0
|
|
end
|
|
EOF
|
|
'';
|
|
});
|
|
in
|
|
{
|
|
sane.programs.mpv = {
|
|
packageUnwrapped = with pkgs; wrapMpv mpv-unwrapped {
|
|
scripts = [
|
|
mpvScripts.mpris
|
|
mpvScripts.mpv-playlistmanager
|
|
uosc
|
|
# pkgs.mpv-uosc-latest
|
|
];
|
|
# extraMakeWrapperArgs = lib.optionals (cfg.config.vo != null) [
|
|
# # 2023/08/29: fixes an error where mpv on moby launches with the message
|
|
# # "DRM_IOCTL_MODE_CREATE_DUMB failed: Cannot allocate memory"
|
|
# # audio still works, and controls, screenshotting, etc -- just not the actual rendering
|
|
# #
|
|
# # this is likely a regression for mpv 0.36.0.
|
|
# # the actual error message *appears* to come from the mesa library, but it's tough to trace.
|
|
# #
|
|
# # 2024/03/02: no longer necessary, with mesa 23.3.1: <https://github.com/NixOS/nixpkgs/pull/265740>
|
|
# #
|
|
# # backend compatibility (2023/10/22):
|
|
# # run with `--vo=help` to see a list of all output options.
|
|
# # non-exhaustive (W=works, F=fails, A=audio-only, U=audio+ui only (no video))
|
|
# # ? null Null video output
|
|
# # A (default)
|
|
# # A dmabuf-wayland Wayland dmabuf video output
|
|
# # A libmpv render API for libmpv (mpv plays the audio, but doesn't even render a window)
|
|
# # A vdpau VDPAU with X11
|
|
# # F drm Direct Rendering Manager (software scaling)
|
|
# # F gpu-next Video output based on libplacebo
|
|
# # F vaapi VA API with X11
|
|
# # F x11 X11 (software scaling)
|
|
# # F xv X11/Xv
|
|
# # U gpu Shader-based GPU Renderer
|
|
# # W caca libcaca (terminal rendering)
|
|
# # W sdl SDL 2.0 Renderer
|
|
# # W wlshm Wayland SHM video output (software scaling)
|
|
# "--add-flags" "--vo=${cfg.config.vo}"
|
|
# ];
|
|
};
|
|
|
|
sandbox.method = "bwrap";
|
|
sandbox.autodetectCliPaths = true;
|
|
sandbox.net = "all";
|
|
sandbox.whitelistAudio = true;
|
|
sandbox.whitelistDbus = [ "user" ]; #< mpris
|
|
sandbox.whitelistDri = true; #< mpv has excellent fallbacks to non-DRI, but DRI offers a good 30%-50% reduced CPU
|
|
sandbox.whitelistWayland = true;
|
|
sandbox.extraHomePaths = [
|
|
".config/mpv" #< else mpris plugin crashes on launch
|
|
".local/share/applications" #< for xdg-terminal-exec (go2tv)
|
|
# it's common for album (or audiobook, podcast) images/lyrics/metadata to live adjacent to the primary file.
|
|
# CLI detection is too poor to pick those up, so expose the common media dirs to the sandbox to make that *mostly* work.
|
|
"Books/local"
|
|
"Books/servo"
|
|
"Music"
|
|
"Videos/gPodder"
|
|
"Videos/local"
|
|
"Videos/servo"
|
|
];
|
|
|
|
persist.byStore.plaintext = [
|
|
# for `watch_later`
|
|
".local/state/mpv"
|
|
];
|
|
fs.".config/mpv/input.conf".symlink.text = let
|
|
execInTerm = "${pkgs.xdg-terminal-exec}/bin/xdg-terminal-exec";
|
|
in ''
|
|
# docs:
|
|
# - <https://mpv.io/manual/master/#list-of-input-commands>
|
|
# - script-binding: <https://mpv.io/manual/master/#command-interface-script-binding>
|
|
# - properties: <https://mpv.io/manual/master/#property-list>
|
|
|
|
# let volume/power keys be interpreted by the system.
|
|
# this is important for sxmo.
|
|
# mpv defaults is POWER = close, VOLUME_{UP,DOWN} = adjust application-level volume
|
|
POWER ignore
|
|
VOLUME_UP ignore
|
|
VOLUME_DOWN ignore
|
|
|
|
# uosc menu
|
|
# text after the shebang is parsed by uosc to construct the menu and names
|
|
menu script-binding uosc/menu
|
|
s script-binding uosc/subtitles #! Subtitles
|
|
a script-binding uosc/audio #! Audio tracks
|
|
q script-binding uosc/stream-quality #! Stream quality
|
|
p script-binding uosc/items #! Playlist
|
|
c script-binding uosc/chapters #! Chapters
|
|
> script-binding uosc/next #! Navigation > Next
|
|
< script-binding uosc/prev #! Navigation > Prev
|
|
o script-binding uosc/open-file #! Navigation > Open file
|
|
# set video-aspect-override "-1" #! Utils > Aspect ratio > Default
|
|
# set video-aspect-override "16:9" #! Utils > Aspect ratio > 16:9
|
|
# set video-aspect-override "4:3" #! Utils > Aspect ratio > 4:3
|
|
# set video-aspect-override "2.35:1" #! Utils > Aspect ratio > 2.35:1
|
|
# script-binding uosc/audio-device #! Utils > Audio devices
|
|
# script-binding uosc/editions #! Utils > Editions
|
|
ctrl+s async screenshot #! Utils > Screenshot
|
|
alt+i script-binding uosc/keybinds #! Utils > Key bindings
|
|
O script-binding uosc/show-in-directory #! Utils > Show in directory
|
|
# script-binding uosc/open-config-directory #! Utils > Open config directory
|
|
# set pause yes; run ${execInTerm} go2tv -v "''${stream-open-filename}" #! Cast
|
|
# set pause yes; run ${execInTerm} go2tv -u "''${stream-open-filename}" #! Cast (...) > Stream
|
|
# set pause yes; run go2tv #! Cast (...) > GUI
|
|
# TODO: unify "Cast" and "Cast (stream)" options above.
|
|
'';
|
|
fs.".config/mpv/mpv.conf".symlink.text = ''
|
|
# write ~/.local/state/mpv/watch_later on exit, to allow resume
|
|
save-position-on-quit=yes
|
|
# identify resumed files by filename only, since i use so many symlinks and doubt mpv does well with that.
|
|
ignore-path-in-watch-later-config
|
|
|
|
# keep-open: don't exit on completion of last file in playlist
|
|
keep-open=yes
|
|
# seeking once at the end of the file causes auto-resume
|
|
keep-open-pause=no
|
|
|
|
# force GUI, even for tracks w/o album art
|
|
# see: <https://www.reddit.com/r/mpv/comments/rvrrpt/oscosdgui_and_arch_linux/>
|
|
player-operation-mode=pseudo-gui
|
|
|
|
# use uosc instead (for On Screen Controls)
|
|
osc=no
|
|
# uosc provides its own seeking/volume indicators, so you also don't need this
|
|
osd-bar=no
|
|
# uosc will draw its own window controls if you disable window border
|
|
border=no
|
|
|
|
# ao=alsa so that uosc can work with ao-volume (see my uosc patch)
|
|
ao=alsa
|
|
# with `ao-volume`, the max actually is 100.
|
|
# to go higher you'll have to use the system's native controls.
|
|
volume-max=100
|
|
'';
|
|
fs.".config/mpv/script-opts/osc.conf".symlink.text = ''
|
|
# make the on-screen controls *always* visible
|
|
# unfortunately, this applies to full-screen as well
|
|
# - docs: <https://mpv.io/manual/master/#on-screen-controller-visibility>
|
|
# if uosc is installed, this file is unused
|
|
visibility=always
|
|
'';
|
|
fs.".config/mpv/script-opts/console.conf".symlink.text = ''
|
|
# font size used by mpv's console (`); default 16
|
|
# font_size=28
|
|
scale=2
|
|
'';
|
|
fs.".config/mpv/script-opts/uosc.conf".symlink.text = let
|
|
play_pause_btn = "cycle:play_arrow:pause:no=pause/yes=play_arrow";
|
|
rev_btn = "command:replay_10:seek -10";
|
|
fwd_btn = "command:forward_30:seek 30";
|
|
in ''
|
|
# docs:
|
|
# - <https://github.com/tomasklaen/uosc>
|
|
# - <https://github.com/tomasklaen/uosc/blob/main/src/uosc.conf>
|
|
# - <https://superuser.com/questions/1775550/add-new-buttons-to-mpv-uosc-ui>
|
|
timeline_style=bar
|
|
timeline_persistency=paused,audio
|
|
controls_persistency=paused,audio
|
|
volume_persistency=audio
|
|
volume_opacity=0.75
|
|
|
|
# speed_persistency=paused,audio
|
|
# vvv want a close button?
|
|
top_bar=always
|
|
top_bar_persistency=paused,audio
|
|
|
|
controls=menu,<video>subtitles,<has_many_audio>audio,<has_many_video>video,<has_many_edition>editions,<stream>stream-quality,space,${rev_btn},${play_pause_btn},${fwd_btn},space,speed:1.0,gap,<video>fullscreen
|
|
|
|
text_border=6.0
|
|
font_bold=yes
|
|
color=foreground=ff8080,background_text=ff8080
|
|
|
|
ui_scale=1.0
|
|
'';
|
|
fs.".config/mpv/script-opts/playlistmanager.conf".symlink.text = ''
|
|
# script docs: <https://github.com/jonniek/mpv-playlistmanager>
|
|
|
|
# auto-populate playlist with other files in the same directory, on launch.
|
|
loadfiles_on_start=yes
|
|
'';
|
|
|
|
# mime.priority = 200; # default = 100; 200 means to yield to other apps
|
|
mime.priority = 50; # default = 100; 50 in order to take precedence over vlc.
|
|
mime.associations."audio/flac" = "mpv.desktop";
|
|
mime.associations."audio/mpeg" = "mpv.desktop";
|
|
mime.associations."audio/x-opus+ogg" = "mpv.desktop";
|
|
mime.associations."audio/x-vorbis+ogg" = "mpv.desktop";
|
|
mime.associations."video/mp4" = "mpv.desktop";
|
|
mime.associations."video/quicktime" = "mpv.desktop";
|
|
mime.associations."video/webm" = "mpv.desktop";
|
|
mime.associations."video/x-flv" = "mpv.desktop";
|
|
mime.associations."video/x-matroska" = "mpv.desktop";
|
|
mime.urlAssociations."^https?://(www.)?youtube.com/watch\?.*v=" = "mpv.desktop";
|
|
mime.urlAssociations."^https?://(www.)?youtube.com/v/" = "mpv.desktop";
|
|
mime.urlAssociations."^https?://(www.)?youtu.be/.+" = "mpv.desktop";
|
|
};
|
|
}
|
|
|