From 974858253b233d34be3d61097c398fcfcfeb48fe Mon Sep 17 00:00:00 2001 From: Frank Zechert Date: Sat, 15 Aug 2026 21:51:35 +0200 Subject: [PATCH] configuration merge with laptop and pc --- user/.chezmoi.yaml.tmpl | 3 +- user/.chezmoidata/packages.yaml | 11 +- user/.chezmoiexternal.yaml | 10 + user/.chezmoiignore | 124 ++-- .../run_after_dms-shell.sh.tmpl | 10 + ...ange_after_install-spicetify-theme.sh.tmpl | 37 +- ... => run_onchange_before_AAAA_firs.sh.tmpl} | 5 + user/dot_bashrc.tmpl | 4 +- user/dot_config/accels/nemo | 1 + user/dot_config/btop/btop.conf | 6 +- user/dot_config/gtk-3.0/bookmarks | 2 + .../hypr/hyprland-autostart.lua.tmpl | 7 + user/dot_config/hypr/hyprland-monitors.lua | 23 +- .../hypr/scripts/executable_autostart.sh | 8 +- user/dot_config/mimeapps.list | 75 -- user/dot_config/mimeapps.list.tmpl | 99 +++ user/dot_config/mpv/encoding.rst | 155 +++++ user/dot_config/mpv/input.conf | 246 +++++++ user/dot_config/mpv/mplayer-input.conf | 93 +++ user/dot_config/mpv/mpv.conf | 42 ++ user/dot_config/mpv/restore-old-bindings.conf | 59 ++ user/dot_config/mpv/restore-osc-bindings.conf | 41 ++ user/dot_config/mpv/tech-overview.txt | 656 ++++++++++++++++++ user/dot_config/qt5ct/qt5ct.conf | 30 + user/dot_config/qt6ct/qt6ct.conf | 33 +- .../scripts/executable_action_menu.sh | 12 + .../scripts/executable_restart_network.sh | 6 + user/dot_config/uwsm/env | 1 + user/dot_config/uwsm/env-hyprland | 1 + .../51-disable-suspension.conf | 41 ++ user/dot_config/wofi/config | 32 + user/dot_config/wofi/style.css | 132 ++++ 32 files changed, 1861 insertions(+), 144 deletions(-) create mode 100644 user/.chezmoiscripts/run_after_dms-shell.sh.tmpl rename user/.chezmoiscripts/{run_onchange_before_install-packages.sh.tmpl => run_onchange_before_AAAA_firs.sh.tmpl} (89%) create mode 100644 user/dot_config/accels/nemo delete mode 100644 user/dot_config/mimeapps.list create mode 100644 user/dot_config/mimeapps.list.tmpl create mode 100644 user/dot_config/mpv/encoding.rst create mode 100644 user/dot_config/mpv/input.conf create mode 100644 user/dot_config/mpv/mplayer-input.conf create mode 100644 user/dot_config/mpv/mpv.conf create mode 100644 user/dot_config/mpv/restore-old-bindings.conf create mode 100644 user/dot_config/mpv/restore-osc-bindings.conf create mode 100644 user/dot_config/mpv/tech-overview.txt create mode 100644 user/dot_config/scripts/executable_action_menu.sh create mode 100644 user/dot_config/scripts/executable_restart_network.sh create mode 100644 user/dot_config/wireplumber/wireplumber.conf.d/51-disable-suspension.conf create mode 100644 user/dot_config/wofi/config create mode 100644 user/dot_config/wofi/style.css diff --git a/user/.chezmoi.yaml.tmpl b/user/.chezmoi.yaml.tmpl index 8df5484..115d535 100644 --- a/user/.chezmoi.yaml.tmpl +++ b/user/.chezmoi.yaml.tmpl @@ -3,6 +3,7 @@ {{- $git_signingkey := promptStringOnce . "git.signingkey" "Git Signing Key" -}} {{- $gpg_recipient := promptStringOnce . "gpg.recipient" "GPG Recipient Address" -}} {{- $is_intel_cpu := promptBoolOnce . "cpu.intel" "Is this a Intel CPU?" -}} +{{- $is_amd_cpu := promptBoolOnce . "cpu.amd" "Is this a AMD CPU?" -}} {{- $is_intel_i915_gpu := promptBoolOnce . "gpu.intel_i915" "Is this a Intel i915 GPU?" -}} {{- $is_work_env := promptBoolOnce . "work_env" "Install work environment?" -}} @@ -15,6 +16,7 @@ data: recipient: {{ $gpg_recipient | quote }} cpu: intel: {{ $is_intel_cpu }} + amd: {{ $is_amd_cpu }} gpu: intel_i915: {{ $is_intel_i915_gpu }} work_env: {{ $is_work_env }} @@ -25,7 +27,6 @@ edit: merge: command: meld args: - - {{ printf "%q" "{{ .Target }}" }} - {{ printf "%q" "{{ .Source }}" }} - {{ printf "%q" "{{ .Destination }}" }} diff --git a/user/.chezmoidata/packages.yaml b/user/.chezmoidata/packages.yaml index 28fa148..137b3cf 100644 --- a/user/.chezmoidata/packages.yaml +++ b/user/.chezmoidata/packages.yaml @@ -25,6 +25,8 @@ packages: - texinfo - unzip - usbutils + - cups + - cups-pk-helper # Display - brightnessctl - ddcutil @@ -100,12 +102,13 @@ packages: - papirus-icon-theme # Themes - colloid-catppuccin-gtk-theme-git + - darkly-bin # Software - bat - btop - bitwarden - chezmoi - - chromium + - ungoogled-chromium-bin - evince - fastfetch - figlet @@ -114,7 +117,7 @@ packages: - github-cli - go - grim - - jre-openjdk + - jdk-openjdk - jq - kdeconnect - kitty @@ -147,6 +150,7 @@ packages: - hunspell-en_gb - hunspell-en_us - qalculate-gtk + - wofi # VIM - lua-language-server intel_graphics_i915: @@ -161,6 +165,9 @@ packages: intel_cpu: yay: - intel-ucode + amd_cpu: + yay: + - amd-ucode work_env: yay: - teams-for-linux-bin diff --git a/user/.chezmoiexternal.yaml b/user/.chezmoiexternal.yaml index 2dc1655..19292e5 100644 --- a/user/.chezmoiexternal.yaml +++ b/user/.chezmoiexternal.yaml @@ -32,3 +32,13 @@ type: git-repo url: https://github.com/catppuccin/spicetify.git refreshPeriod: 168h + +# Theme for QT +.config/qt5ct/colors/catppuccin-mocha-blue.conf: + type: file + url: https://raw.githubusercontent.com/catppuccin/qt5ct/refs/heads/main/themes/catppuccin-mocha-blue.conf + refreshPeriod: 168h +.config/qt6ct/colors/catppuccin-mocha-blue.conf: + type: file + url: https://raw.githubusercontent.com/catppuccin/qt5ct/refs/heads/main/themes/catppuccin-mocha-blue.conf + refreshPeriod: 168h diff --git a/user/.chezmoiignore b/user/.chezmoiignore index 1f387dd..4104d41 100644 --- a/user/.chezmoiignore +++ b/user/.chezmoiignore @@ -1,74 +1,108 @@ -Desktop -Documents -Downloads -Music -Pictures -Projects -Public -Templates -Videos -thunderbird -.cache -.lesshst -.thunderbird +.azure .bash_history +.cache .camera_driver +.cargo .claude .claude.json .claude.json.backup +.gradle +.ideavimrc .java .jbr +.jdks .junie +.lesshst +.librewolf +.local +.local/share/* +.local/share/** +.local/state/** +.local/state/** +.mozilla +.MakeMKV .node_repl_history +.npm +.nvm +.pki +.python_history +.rustup +.ssh +.thunderbird -.config/Signal +.config/autostart +.config/Bitwarden +.config/bruno .config/chezmoi +.config/chromium +.config/Claude +.config/cura .config/dconf +.config/draw.io +.config/filezilla .config/fontforge +.config/FreeCAD +.config/gh +.config/GIMP .config/go +.config/google-chrome +.config/icedtea-web +.config/inkscape +.config/isyncrc +.config/JetBrains +.config/kdeconnect +.config/lftp +.config/libaccounts-glib +.config/libreoffice .config/librewolf .config/mozilla .config/nemo +.config/Nextcloud +.config/nvim/lazy-lock.json .config/nvm +.config/nvtop +.config/okularpartrc +.config/okularrc +.config/OpenSCAD +.config/openttd .config/pavucontrol.ini .config/pulse -.config/spotify -.config/systemd -.config/yay -.config/Bitwarden -.config/autostart -.config/teams-for-linux -.config/Claude -.config/chromium -.config/filezilla -.config/kdeconnect -.config/kitty/kitty.conf.bak -.config/lftp +.config/qalculate +.config/qt5ct/qss +.config/qt6ct/qss +.config/QtProject.conf +.config/rustdesk +.config/Signal .config/spicetify +.config/spotify +.config/spotify-launcher.conf +.config/systemd +.config/teams-for-linux +.config/yay +.gnupg .gnupg/crls.d +!.gnupg/dirmngr.conf +!.gnupg/gpg-agent.conf +!.gnupg/gpg.conf .gnupg/openpgp-revocs.d .gnupg/private-keys-v1.d .gnupg/public-keys.d .gnupg/sshcontrol .gnupg/trustdb.gpg -.local -.local/state/** -.local/share/** - - -.npm -.nvm -.ssh -.pki -.python_history -.azure -.config/JetBrains -.config/bruno -.config/draw.io -.config/gh -.config/qalculate -.gradle -.ideavimrc -.jdks +Desktop +Documents +dotfiles +Downloads +isyncrc +maildir +maintenance +Music +nextcloud +Pictures +Projects +Public +Templates +thunderbird +Videos diff --git a/user/.chezmoiscripts/run_after_dms-shell.sh.tmpl b/user/.chezmoiscripts/run_after_dms-shell.sh.tmpl new file mode 100644 index 0000000..42110cc --- /dev/null +++ b/user/.chezmoiscripts/run_after_dms-shell.sh.tmpl @@ -0,0 +1,10 @@ +{{- if eq .chezmoi.os "linux" -}} +#!/usr/bin/env bash +set -e +[ "${CHEZMOI}" -eq 1 ] || exit 1 + + +systemctl --user enable --now dms + +# vim: syntax=bash ft=template +{{- end -}} diff --git a/user/.chezmoiscripts/run_onchange_after_install-spicetify-theme.sh.tmpl b/user/.chezmoiscripts/run_onchange_after_install-spicetify-theme.sh.tmpl index bfa80a7..39df875 100644 --- a/user/.chezmoiscripts/run_onchange_after_install-spicetify-theme.sh.tmpl +++ b/user/.chezmoiscripts/run_onchange_after_install-spicetify-theme.sh.tmpl @@ -3,27 +3,43 @@ # This script is skipped if no spicetify-cli is available or no spotify is installed if ! command -v spicetify > /dev/null; then - echo "Skipping Spotify Theming, no spicetify-cli available" - exit 0 + echo "Skipping Spotify Theming, no spicetify-cli available" + exit 0 fi if [ ! -d "/opt/spotify" ]; then - echo "Skipping Spotify Theming, no spotify found at /opt/spotify" - exit 0 + echo "Skipping Spotify Theming, no spotify found at /opt/spotify" + exit 0 fi + # Apply theme to spotify if either the spotify binary has changed, or the theme was updated in github -# spotify hash: {{ include "/opt/spotify/spotify" | sha256sum }} -# catppuccin hash: {{ joinPath .chezmoi.homeDir ".config/spicetify-catppuccin-theme/catppuccin/app.scss" | include | sha256sum }} + +{{ $spotifyPath := "/opt/spotify/spotify" }} +{{ $s := stat $spotifyPath }} +{{ if and $s (hasKey $s "Exists") $s.Exists }} +# spotify hash: {{ include $spotifyPath | sha256sum }} +{{ else }} +# spotify hash: +{{ end }} + +{{ $catppuccinPath := joinPath .chezmoi.homeDir ".config/spicetify-catppuccin-theme/catppuccin/app.scss" }} +{{ $c := stat $catppuccinPath }} +{{ if and $c (hasKey $c "Exists") $c.Exists }} +# catppuccin hash: {{ include $catppuccinPath | sha256sum }} +{{ else }} +# catppuccin hash: +{{ end }} + mkdir -p ~/.config/spicetify/Themes cp -r ~/.config/spicetify-catppuccin-theme/catppuccin ~/.config/spicetify/Themes/ getent group spotify > /dev/null || { - echo "System group spotify is missing" - echo "Please create it with groupadd -r spotify" - echo "Then re-login and try again" - exit 1 + echo "System group spotify is missing" + echo "Please create it with groupadd -r spotify" + echo "Then re-login and try again" + exit 1 } sudo chgrp spotify /opt/spotify sudo chgrp -R spotify /opt/spotify/Apps @@ -35,3 +51,4 @@ spicetify config current_theme catppuccin spicetify config color_scheme mocha spicetify config inject_css 1 inject_theme_js 1 replace_colors 1 overwrite_assets 1 spicetify apply + diff --git a/user/.chezmoiscripts/run_onchange_before_install-packages.sh.tmpl b/user/.chezmoiscripts/run_onchange_before_AAAA_firs.sh.tmpl similarity index 89% rename from user/.chezmoiscripts/run_onchange_before_install-packages.sh.tmpl rename to user/.chezmoiscripts/run_onchange_before_AAAA_firs.sh.tmpl index 04be2fc..99c22c1 100644 --- a/user/.chezmoiscripts/run_onchange_before_install-packages.sh.tmpl +++ b/user/.chezmoiscripts/run_onchange_before_AAAA_firs.sh.tmpl @@ -25,6 +25,11 @@ declare -a yay_packages yay_packages+=({{ . | quote}}) {{ end -}} {{ end -}} + {{ if eq .cpu.amd true -}} + {{ range .packages.arch.amd_cpu.yay -}} + yay_packages+=({{ . | quote}}) + {{ end -}} + {{ end -}} {{ if eq .gpu.intel_i915 true -}} {{ range .packages.arch.intel_graphics_i915.yay -}} yay_packages+=({{ . | quote}}) diff --git a/user/dot_bashrc.tmpl b/user/dot_bashrc.tmpl index e0fdc09..07dc37d 100644 --- a/user/dot_bashrc.tmpl +++ b/user/dot_bashrc.tmpl @@ -12,10 +12,10 @@ HISTTIMEFORMAT="[%F %T] " HISTCONTROL="ignoredups" HISTSIZE="200" HISTFILESIZE="2000" -shopt -s histappend +shopt -s histappend # append new entries to the histry instead of overwriting # --- Bash Options --- -set -o vi +set -o vi # mandated by POSIX shopt -s checkwinsize # --- Pager --- diff --git a/user/dot_config/accels/nemo b/user/dot_config/accels/nemo new file mode 100644 index 0000000..2188306 --- /dev/null +++ b/user/dot_config/accels/nemo @@ -0,0 +1 @@ +(gtk_accel_path "/DirViewActions/OpenInTerminal" "F4") diff --git a/user/dot_config/btop/btop.conf b/user/dot_config/btop/btop.conf index 4726c85..c3bedb6 100644 --- a/user/dot_config/btop/btop.conf +++ b/user/dot_config/btop/btop.conf @@ -5,7 +5,7 @@ color_theme = "/home/frank/.config/btop/themes/catppuccin_mocha.theme" #* If the theme set background should be shown, set to False if you want terminal background transparency. -theme_background = true +theme_background = false #* Sets if 24-bit truecolor should be used, will convert 24-bit colors to 256 color (6x6x6 color cube) if false. truecolor = true @@ -27,13 +27,13 @@ presets = "cpu:1:default,proc:0:default cpu:0:default,mem:0:default,net:0:defaul #* Set to True to enable "h,j,k,l,g,G" keys for directional control in lists. #* Conflicting keys for h:"help" and k:"kill" is accessible while holding shift. -vim_keys = false +vim_keys = true #* Disable all mouse events. disable_mouse = false #* Rounded corners on boxes, is ignored if TTY mode is ON. -rounded_corners = true +rounded_corners = false #* Use terminal synchronized output sequences to reduce flickering on supported terminals. terminal_sync = true diff --git a/user/dot_config/gtk-3.0/bookmarks b/user/dot_config/gtk-3.0/bookmarks index a867c60..2ba4836 100644 --- a/user/dot_config/gtk-3.0/bookmarks +++ b/user/dot_config/gtk-3.0/bookmarks @@ -3,4 +3,6 @@ file:///home/frank/Downloads Downloads file:///home/frank/Pictures Pictures file:///home/frank/Projects Projects file:///home/frank/Projects/inso-automation inso-automation +file:///home/frank/Documents/3d-printing 3d-printing +file:///home/frank/nextcloud nextcloud smb://10.10.10.5/ HOMESERVER diff --git a/user/dot_config/hypr/hyprland-autostart.lua.tmpl b/user/dot_config/hypr/hyprland-autostart.lua.tmpl index c901411..4f20c2f 100644 --- a/user/dot_config/hypr/hyprland-autostart.lua.tmpl +++ b/user/dot_config/hypr/hyprland-autostart.lua.tmpl @@ -9,3 +9,10 @@ hl.on("hyprland.start", function() hl.exec_cmd("~/.config/hypr/scripts/autostart.sh") end) +-- old stuff, probably not needed anymore +-- exec-once = gnome-keyring-daemon --start --components=secrets +-- exec-once = systemctl --user start gcr-ssh-agent.socket +-- +-- Polkit Daemon +-- exec-once = /usr/lib/polkit-gnome/polkit-gnome-authentication-agent-1 +-- diff --git a/user/dot_config/hypr/hyprland-monitors.lua b/user/dot_config/hypr/hyprland-monitors.lua index a71d3fd..aac52a0 100644 --- a/user/dot_config/hypr/hyprland-monitors.lua +++ b/user/dot_config/hypr/hyprland-monitors.lua @@ -9,7 +9,7 @@ hl.monitor({ -- if no profile match at all, the fallback_profile will be applied anyways. local fallback_profile="laptop" local profiles = { - home = { + home_docked = { priority = 10, monitors = { "desc:GIGA-BYTE TECHNOLOGY CO. LTD. M34WQ 0x00000B52", @@ -25,6 +25,25 @@ local profiles = { workspace_rules = { }, }, + home_pc = { + priority = 20, + monitors = { + "desc:GIGA-BYTE TECHNOLOGY CO. LTD. M34WQ 0x00000B52", + "desc:Dell Inc. DELL U2724D DL7R834", + "desc:Dell Inc. DELL U2414H 292K475V26JL", + }, + disable_other_monitors = true, + monitor_config = { + ["desc:GIGA-BYTE TECHNOLOGY CO. LTD. M34WQ 0x00000B52"] = {disabled=false, scale=1, position="0x0", mode="3440x1440@120"}, + ["desc:Dell Inc. DELL U2414H 292K475V26JL"] = {disabled=false, scale=1, position="760x-1080", mode="1920x1080@60"}, + ["desc:Dell Inc. DELL U2724D DL7R834"] = {disabled=false, scale=1, position="3440x0", mode="2560x1440@120"}, + }, + workspace_rules = { + { workspace = "1", monitor = "desc:GIGA-BYTE TECHNOLOGY CO. LTD. M34WQ 0x00000B52", default = true, persistent = true}, + { workspace = "9", monitor = "desc:Dell Inc. DELL U2724D DL7R834", default = true, persistent = true}, + { workspace = "10", monitor = "desc:Dell Inc. DELL U2414H 292K475V26JL", default = true, persistent = true}, + } + }, work = { priority = 10, monitors = { @@ -162,7 +181,7 @@ local function apply_monitor_profile() end local monitor_profile_timer = nil -local function request_apply_monitor_profile(data) +function request_apply_monitor_profile(data) debug_notify("requested monitor profile update") table.insert(apply_monitor_request_queue, data or {}) if monitor_profile_timer == nil or not monitor_profile_timer:is_enabled() then diff --git a/user/dot_config/hypr/scripts/executable_autostart.sh b/user/dot_config/hypr/scripts/executable_autostart.sh index c0ccaa0..0abcbdd 100644 --- a/user/dot_config/hypr/scripts/executable_autostart.sh +++ b/user/dot_config/hypr/scripts/executable_autostart.sh @@ -1,10 +1,16 @@ #!/usr/bin/env bash +(sleep 5 ; hyprctl eval 'request_apply_monitor_profile()') & + hyprctl dispatch 'hl.dsp.exec_cmd("uwsm app -- thunderbird", {workspace = 10})' +{{ if eq .work_env true -}} hyprctl dispatch 'hl.dsp.exec_cmd("uwsm app -- /home/frank/.local/share/applications/librewolf.webapp-e7db0a1c-02e9-42cc-a5da-8fdc222e89dc.desktop", {workspace = 9})' hyprctl dispatch 'hl.dsp.exec_cmd("uwsm app -- jetbrains-toolbox.desktop")' +{{ end -}} +hyprctl dispatch 'hl.dsp.exec_cmd("uwsm app -- nextcloud")' sleep 3 hyprctl dispatch 'hl.dsp.exec_cmd("uwsm app -- Telegram --ozone-platform=wayland", {workspace = 10})' hyprctl dispatch 'hl.dsp.exec_cmd("uwsm app -- signal-desktop --ozone-platform=wayland", {workspace = 10})' +{{ if eq .work_env true -}} hyprctl dispatch 'hl.dsp.exec_cmd("uwsm app -- /home/frank/.local/share/applications/librewolf.webapp-daf88433-cdaa-4a10-9bfb-af0a20fb7b71.desktop", {workspace = 9})' - +{{ end -}} diff --git a/user/dot_config/mimeapps.list b/user/dot_config/mimeapps.list deleted file mode 100644 index 5b9f0e0..0000000 --- a/user/dot_config/mimeapps.list +++ /dev/null @@ -1,75 +0,0 @@ -[Default Applications] -application/pdf=librewolf.desktop -application/rss+xml=userapp-Thunderbird-WTV1S3.desktop -application/vnd.comicbook+zip=librewolf.desktop -application/vnd.comicbook-rar=librewolf.desktop -application/x-bzpdf=librewolf.desktop -application/x-ext-pdf=librewolf.desktop -application/x-extension-ics=userapp-Thunderbird-X7G9S3.desktop -application/x-extension-rss=userapp-Thunderbird-WTV1S3.desktop -application/x-gzpdf=librewolf.desktop -image/avif=dms-open.desktop -image/bmp=dms-open.desktop -image/gif=dms-open.desktop -image/jpeg=dms-open.desktop -image/png=dms-open.desktop -image/svg+xml=dms-open.desktop -image/webp=dms-open.desktop -inode/directory=nemo.desktop -message/rfc822=userapp-Thunderbird-3QI0S3.desktop -text/calendar=userapp-Thunderbird-X7G9S3.desktop -text/html=librewolf.desktop -text/plain=nvim.desktop -x-directory/normal=nemo.desktop -x-scheme-handler/about=librewolf.desktop -x-scheme-handler/calendar=dms-open.desktop -x-scheme-handler/feed=userapp-Thunderbird-WTV1S3.desktop -x-scheme-handler/http=librewolf.desktop -x-scheme-handler/https=librewolf.desktop -x-scheme-handler/mailto=userapp-Thunderbird-3QI0S3.desktop -x-scheme-handler/mid=userapp-Thunderbird-3QI0S3.desktop -x-scheme-handler/net.thunderbird=userapp-Thunderbird-U229S3.desktop -x-scheme-handler/news=userapp-Thunderbird-AH40S3.desktop -x-scheme-handler/nntp=userapp-Thunderbird-AH40S3.desktop -x-scheme-handler/snews=userapp-Thunderbird-AH40S3.desktop -x-scheme-handler/unknown=librewolf.desktop -x-scheme-handler/webcal=userapp-Thunderbird-X7G9S3.desktop -x-scheme-handler/webcals=userapp-Thunderbird-X7G9S3.desktop -x-scheme-handler/claude=claude-desktop.desktop -x-scheme-handler/jetbrains=jetbrainsd.desktop -x-scheme-handler/claude-cli=claude-code-url-handler.desktop -application/xhtml+xml=librewolf.desktop -x-scheme-handler/bruno=bruno.desktop - -[Added Associations] -application/pdf=librewolf.desktop; -application/rss+xml=userapp-Thunderbird-WTV1S3.desktop; -application/vnd.comicbook+zip=librewolf.desktop; -application/vnd.comicbook-rar=librewolf.desktop; -application/x-bzpdf=librewolf.desktop; -application/x-ext-pdf=librewolf.desktop; -application/x-extension-ics=userapp-Thunderbird-X7G9S3.desktop; -application/x-extension-rss=userapp-Thunderbird-WTV1S3.desktop; -application/x-gzpdf=librewolf.desktop; -image/avif=dms-open.desktop; -image/bmp=dms-open.desktop; -image/gif=dms-open.desktop; -image/jpeg=dms-open.desktop; -image/png=dms-open.desktop; -image/svg+xml=dms-open.desktop; -image/webp=dms-open.desktop; -message/rfc822=userapp-Thunderbird-3QI0S3.desktop; -text/calendar=userapp-Thunderbird-X7G9S3.desktop; -x-scheme-handler/calendar=dms-open.desktop; -x-scheme-handler/feed=userapp-Thunderbird-WTV1S3.desktop; -x-scheme-handler/mailto=userapp-Thunderbird-3QI0S3.desktop; -x-scheme-handler/mid=userapp-Thunderbird-3QI0S3.desktop; -x-scheme-handler/net.thunderbird=userapp-Thunderbird-U229S3.desktop; -x-scheme-handler/news=userapp-Thunderbird-AH40S3.desktop; -x-scheme-handler/nntp=userapp-Thunderbird-AH40S3.desktop; -x-scheme-handler/snews=userapp-Thunderbird-AH40S3.desktop; -x-scheme-handler/webcal=userapp-Thunderbird-X7G9S3.desktop; -x-scheme-handler/webcals=userapp-Thunderbird-X7G9S3.desktop; -application/xhtml+xml=librewolf.desktop; - -[Removed Associations] diff --git a/user/dot_config/mimeapps.list.tmpl b/user/dot_config/mimeapps.list.tmpl new file mode 100644 index 0000000..485a6e6 --- /dev/null +++ b/user/dot_config/mimeapps.list.tmpl @@ -0,0 +1,99 @@ +{{ $rss := "x" }} +{{ $cal := "x" }} +{{ $mail := "x" }} +{{ $tb := "x" }} +{{ $news := "x" }} + +{{- if eq .chezmoi.hostname "arch-next" -}} + +{{- $rss = "userapp-Thunderbird-Y886T3.desktop" -}} +{{- $cal = "userapp-Thunderbird-NA25T3.desktop" -}} +{{- $mail = "userapp-Thunderbird-Q3N5T3.desktop" -}} +{{- $tb = "userapp-Thunderbird-SIG6T3.desktop" }} +{{- $news = "userapp-Thunderbird-A0Q6T3.desktop" }} + +{{- else if eq .chezmoi.hostname "xps13-ia" -}} + +{{- $rss = "userapp-Thunderbird-WTV1S3.desktop" -}} +{{- $cal = "userapp-Thunderbird-X7G9S3.desktop" -}} +{{- $mail = "userapp-Thunderbird-3QI0S3.desktop" -}} +{{- $tb = "userapp-Thunderbird-U229S3.desktop" -}} +{{- $news = "userapp-Thunderbird-AH40S3.desktop" -}} + +{{- end -}} + +[Default Applications] +application/pdf=librewolf.desktop +application/rss+xml={{ $rss }} +application/vnd.comicbook+zip=librewolf.desktop +application/vnd.comicbook-rar=librewolf.desktop +application/x-bzpdf=librewolf.desktop +application/x-ext-pdf=librewolf.desktop +application/x-extension-ics={{ $cal}} +application/x-extension-rss={{ $rss }} +application/x-gzpdf=librewolf.desktop +image/avif=dms-open.desktop +image/bmp=dms-open.desktop +image/gif=dms-open.desktop +image/jpeg=dms-open.desktop +image/png=dms-open.desktop +image/svg+xml=dms-open.desktop +image/webp=dms-open.desktop +inode/directory=nemo.desktop +message/rfc822={{ $mail }} +text/calendar={{ $cal }} +text/html=librewolf.desktop +text/plain=nvim.desktop +x-directory/normal=nemo.desktop +x-scheme-handler/about=librewolf.desktop +x-scheme-handler/calendar=dms-open.desktop +x-scheme-handler/feed={{ $rss }} +x-scheme-handler/http=librewolf.desktop +x-scheme-handler/https=librewolf.desktop +x-scheme-handler/mailto={{ $mail }} +x-scheme-handler/mid={{ $mail }} +x-scheme-handler/net.thunderbird={{ $tb }} +x-scheme-handler/news={{ $news }} +x-scheme-handler/nntp={{ $news }} +x-scheme-handler/snews={{ $news }} +x-scheme-handler/unknown=librewolf.desktop +x-scheme-handler/webcal={{ $cal }} +x-scheme-handler/webcals={{ $cal }} +x-scheme-handler/claude=claude-desktop.desktop +x-scheme-handler/jetbrains=jetbrainsd.desktop +x-scheme-handler/claude-cli=claude-code-url-handler.desktop +application/xhtml+xml=librewolf.desktop +x-scheme-handler/bruno=bruno.desktop + +[Added Associations] +application/pdf=librewolf.desktop; +application/rss+xml={{ $rss }}; +application/vnd.comicbook+zip=librewolf.desktop; +application/vnd.comicbook-rar=librewolf.desktop; +application/x-bzpdf=librewolf.desktop; +application/x-ext-pdf=librewolf.desktop; +application/x-extension-ics={{ $cal }}; +application/x-extension-rss={{ $rss }}; +application/x-gzpdf=librewolf.desktop; +image/avif=dms-open.desktop; +image/bmp=dms-open.desktop; +image/gif=dms-open.desktop; +image/jpeg=dms-open.desktop; +image/png=dms-open.desktop; +image/svg+xml=dms-open.desktop; +image/webp=dms-open.desktop; +message/rfc822={{ $mail }}; +text/calendar={{ $cal }}; +x-scheme-handler/calendar=dms-open.desktop; +x-scheme-handler/feed={{ $rss }}; +x-scheme-handler/mailto={{ $mail }}; +x-scheme-handler/mid={{ $mail }}; +x-scheme-handler/net.thunderbird={{ $tb }}; +x-scheme-handler/news={{ $rss }}; +x-scheme-handler/nntp={{ $rss }}; +x-scheme-handler/snews={{ $rss }}; +x-scheme-handler/webcal={{ $cal }}; +x-scheme-handler/webcals={{ $cal }}; +application/xhtml+xml=librewolf.desktop; + +[Removed Associations] diff --git a/user/dot_config/mpv/encoding.rst b/user/dot_config/mpv/encoding.rst new file mode 100644 index 0000000..9c6c067 --- /dev/null +++ b/user/dot_config/mpv/encoding.rst @@ -0,0 +1,155 @@ +General usage +============= + +:: + + mpv infile --o=outfile [--of=outfileformat] [--ofopts=formatoptions] [--orawts] \ + [(any other mpv options)] \ + --ovc=outvideocodec [--ovcopts=outvideocodecoptions] \ + --oac=outaudiocodec [--oacopts=outaudiocodecoptions] + +Help for these options is provided if giving help as parameter, as in:: + + mpv --ovc=help + +The suboptions of these generally are identical to ffmpeg's (as option parsing +is simply delegated to ffmpeg). The option --ocopyts enables copying timestamps +from the source as-is, instead of fixing them to match audio playback time +(note: this doesn't work with all output container formats); --orawts even turns +off discontinuity fixing. + +Note that if neither --ofps nor --oautofps is specified, VFR encoding is assumed +and the time base is 24000fps. --oautofps sets --ofps to a guessed fps number +from the input video. Note that not all codecs and not all formats support VFR +encoding, and some which do have bugs when a target bitrate is specified - use +--ofps or --oautofps to force CFR encoding in these cases. + +Of course, the options can be stored in a profile, like this .config/mpv/mpv.conf +section:: + + [myencprofile] + vf-add = scale=480:-2 + ovc = libx264 + ovcopts-add = preset=medium + ovcopts-add = tune=fastdecode + ovcopts-add = crf=23 + ovcopts-add = maxrate=1500k + ovcopts-add = bufsize=1000k + ovcopts-add = rc_init_occupancy=900k + ovcopts-add = refs=2 + ovcopts-add = profile=baseline + oac = aac + oacopts-add = b=96k + +It's also possible to define default encoding options by putting them into +the section named ``[encoding]``. (This behavior changed after mpv 0.3.x. In +mpv 0.3.x, config options in the default section / no section were applied +to encoding. This is not the case anymore.) + +One can then encode using this profile using the command:: + + mpv infile --o=outfile.mp4 --profile=myencprofile + +Some example profiles are provided in a file +etc/encoding-profiles.conf; as for this, see below. + + +Encoding examples +================= + +These are some examples of encoding targets this code has been used and tested +for. + +Typical MPEG-4 Part 2 ("ASP", "DivX") encoding, AVI container:: + + mpv infile --o=outfile.avi \ + --vf=fps=25 \ + --ovc=mpeg4 --ovcopts=qscale=4 \ + --oac=libmp3lame --oacopts=b=128k + +Note: AVI does not support variable frame rate, so the fps filter must be used. +The frame rate should ideally match the input (25 for PAL, 24000/1001 or +30000/1001 for NTSC) + +Typical MPEG-4 Part 10 ("AVC", "H.264") encoding, Matroska (MKV) container:: + + mpv infile --o=outfile.mkv \ + --ovc=libx264 --ovcopts=preset=medium,crf=23,profile=baseline \ + --oac=libopus --oacopts=qscale=3 + +Typical MPEG-4 Part 10 ("AVC", "H.264") encoding, MPEG-4 (MP4) container:: + + mpv infile --o=outfile.mp4 \ + --ovc=libx264 --ovcopts=preset=medium,crf=23,profile=baseline \ + --oac=aac --oacopts=b=128k + +Typical VP8 encoding, WebM (restricted Matroska) container:: + + mpv infile -o outfile.mkv \ + --of=webm \ + --ovc=libvpx --ovcopts=qmin=6,b=1000000k \ + --oac=libopus --oacopts=qscale=3 + + +Device targets +============== + +As the options for various devices can get complex, profiles can be used. + +An example profile file for encoding is provided in +etc/encoding-profiles.conf in the source tree. This file is installed and loaded +by default. If you want to modify it, you can replace and it with your own copy +by doing:: + + mkdir -p ~/.mpv + cp /etc/mpv/encoding-profiles.conf ~/.mpv/encoding-profiles.conf + +Keep in mind that the default profile is the playback one. If you want to add +options that apply only in encoding mode, put them into a ``[encoding]`` +section. + +Refer to the top of that file for more comments - in a nutshell, the following +options are added by it:: + + --profile=enc-to-dvdpal # DVD-Video PAL, use dvdauthor -v pal+4:3 -a ac3+en + --profile=enc-to-dvdntsc # DVD-Video NTSC, use dvdauthor -v ntsc+4:3 -a ac3+en + --profile=enc-to-bb-9000 # MP4 for Blackberry Bold 9000 + --profile=enc-to-nok-6300 # 3GP for Nokia 6300 + --profile=enc-to-psp # MP4 for PlayStation Portable + --profile=enc-to-iphone # MP4 for iPhone + --profile=enc-to-iphone-4 # MP4 for iPhone 4 (double res) + --profile=enc-to-iphone-5 # MP4 for iPhone 5 (even larger res) + +You can encode using these with a command line like:: + + mpv infile --o=outfile.mp4 --profile=enc-to-bb-9000 + +Of course, you are free to override options set by these profiles by specifying +them after the -profile option. + + +What works +========== + +* Encoding at variable frame rate (default) +* Encoding at constant frame rate using --vf=fps=RATE +* 2-pass encoding (specify flags=+pass1 in the first pass's --ovcopts, specify + flags=+pass2 in the second pass) +* Hardcoding subtitles using vobsub, ass or srt subtitle rendering (just + configure mpv for the subtitles as usual) +* Hardcoding any other mpv OSD (e.g. time codes, using --osdlevel=3 and + --vf=expand=::::1) +* Encoding directly from a DVD, network stream, webcam, or any other source + mpv supports +* Using x264 presets/tunings/profiles (by using profile=, tune=, preset= in the + --ovcopts) +* Deinterlacing/Inverse Telecine with any of mpv's filters for that +* Audio file converting: mpv --o=outfile.m4a infile.flac --no-video + --oac=aac --oacopts=b=320k + +What does not work yet +====================== + +* 3-pass encoding (ensuring constant total size and bitrate constraints while + having VBR audio; mencoder calls this "frameno") +* Direct stream copy diff --git a/user/dot_config/mpv/input.conf b/user/dot_config/mpv/input.conf new file mode 100644 index 0000000..5c723a0 --- /dev/null +++ b/user/dot_config/mpv/input.conf @@ -0,0 +1,246 @@ +# mpv keybindings +# +# Location of user-defined bindings: ~/.config/mpv/input.conf +# +# Lines starting with # are comments. Use SHARP to assign the # key. +# Copy this file and uncomment and edit the bindings you want to change. +# +# List of commands and further details: DOCS/man/input.rst +# List of special keys: --input-keylist +# Keybindings testing mode: mpv --input-test --force-window --idle +# +# Use 'ignore' to unbind a key fully (e.g. 'ctrl+a ignore'). +# +# Strings need to be quoted and escaped: +# KEY show-text "This is a single backslash: \\ and a quote: \" !" +# +# You can use modifier-key combinations like Shift+Left or Ctrl+Alt+x with +# the modifiers Shift, Ctrl, Alt and Meta (may not work on the terminal). +# +# The default keybindings are hardcoded into the mpv binary. +# You can disable them completely with: --no-input-default-bindings + +# Developer note: +# On compilation, this file is baked into the mpv binary, and all lines are +# uncommented (unless '#' is followed by a space) - thus this file defines the +# default key bindings. + +# If this is enabled, treat all the following bindings as default. +#default-bindings start + +#MBTN_LEFT ignore # don't do anything +#MBTN_LEFT_DBL cycle fullscreen # toggle fullscreen +#MBTN_RIGHT cycle pause # toggle pause/playback mode +#MBTN_BACK playlist-prev # skip to the previous file +#MBTN_FORWARD playlist-next # skip to the next file +#Ctrl+MBTN_LEFT script-binding positioning/drag-to-pan # pan around the clicked point + +# Mouse wheels, touchpad or other input devices that have axes +# if the input devices supports precise scrolling it will also scale the +# numeric value accordingly +#WHEEL_UP add volume 2 +#WHEEL_DOWN add volume -2 +#WHEEL_LEFT seek -10 # seek 10 seconds backward +#WHEEL_RIGHT seek 10 # seek 10 seconds forward + +## Seek units are in seconds, but note that these are limited by keyframes +#RIGHT seek 5 # seek 5 seconds forward +#LEFT seek -5 # seek 5 seconds backward +#UP seek 60 # seek 1 minute forward +#DOWN seek -60 # seek 1 minute backward +# Do smaller, always exact (non-keyframe-limited), seeks with shift. +# Don't show them on the OSD (no-osd). +#Shift+RIGHT no-osd seek 1 exact # seek exactly 1 second forward +#Shift+LEFT no-osd seek -1 exact # seek exactly 1 second backward +#Shift+UP no-osd seek 5 exact # seek exactly 5 seconds forward +#Shift+DOWN no-osd seek -5 exact # seek exactly 5 seconds backward +#Ctrl+LEFT no-osd sub-seek -1 # seek to the previous subtitle +#Ctrl+RIGHT no-osd sub-seek 1 # seek to the next subtitle +#Ctrl+Shift+LEFT sub-step -1 # change subtitle timing such that the previous subtitle is displayed +#Ctrl+Shift+RIGHT sub-step 1 # change subtitle timing such that the next subtitle is displayed +#Alt+left add video-pan-x 0.1 # move the video right +#Alt+right add video-pan-x -0.1 # move the video left +#Alt+up add video-pan-y 0.1 # move the video down +#Alt+down add video-pan-y -0.1 # move the video up +#Alt++ add video-zoom 0.1 # zoom in +#ZOOMIN add video-zoom 0.1 # zoom in +#Alt+- add video-zoom -0.1 # zoom out +#ZOOMOUT add video-zoom -0.1 # zoom out +#Alt+KP_ADD add video-zoom 0.1 # zoom in +#Alt+KP_SUBTRACT add video-zoom -0.1 # zoom out +#Ctrl+WHEEL_UP script-binding positioning/cursor-centric-zoom 0.1 # zoom in towards the cursor +#Ctrl+WHEEL_DOWN script-binding positioning/cursor-centric-zoom -0.1 # zoom out towards the cursor +#Alt+BS set video-zoom 0; no-osd set panscan 0; no-osd set video-pan-x 0; no-osd set video-pan-y 0; no-osd set video-align-x 0; no-osd set video-align-y 0 # reset zoom and pan settings +#HOME seek 0 absolute # seek to the start +#PGUP add chapter 1 # seek to the next chapter +#PGDWN add chapter -1 # seek to the previous chapter +#Shift+PGUP seek 600 # seek 10 minutes forward +#Shift+PGDWN seek -600 # seek 10 minutes backward +#[ multiply speed 1/1.1 # decrease the playback speed +#] multiply speed 1.1 # increase the playback speed +#{ multiply speed 0.5 # halve the playback speed +#} multiply speed 2.0 # double the playback speed +#BS set speed 1.0 # reset the speed to normal +#Shift+BS revert-seek # undo the previous (or marked) seek +#Shift+Ctrl+BS revert-seek mark # mark the position for revert-seek +#q quit +#Q quit-watch-later # exit and remember the playback position +#q {encode} quit 4 +#ESC set fullscreen no # leave fullscreen +#ESC {encode} quit 4 +#p cycle pause # toggle pause/playback mode +#. frame-step # advance one frame and pause +#, frame-back-step # go back by one frame and pause +#SPACE cycle pause # toggle pause/playback mode +#> playlist-next # skip to the next file +#ENTER playlist-next # skip to the next file +#< playlist-prev # skip to the previous file +#Shift+HOME no-osd set playlist-pos 0 # skip to the first file +#Shift+END no-osd set playlist-pos-1 ${playlist-count} # skip to the last file +#O no-osd cycle-values osd-level 3 1 # toggle displaying the OSD on user interaction or always +#o show-progress # show playback progress +#P show-progress # show playback progress +#i script-binding stats/display-stats # display information and statistics +#I script-binding stats/display-stats-toggle # toggle displaying information and statistics +#? script-binding stats/display-page-4-toggle # toggle displaying key bindings +#` script-binding commands/open # open the console +#z add sub-delay -0.1 # shift subtitles 100 ms earlier +#Z add sub-delay +0.1 # delay subtitles by 100 ms +#x add sub-delay +0.1 # delay subtitles by 100 ms +#ctrl++ add audio-delay 0.100 # change audio/video sync by delaying the audio +#ctrl+- add audio-delay -0.100 # change audio/video sync by shifting the audio earlier +#ctrl+KP_ADD add audio-delay 0.100 # change audio/video sync by delaying the audio +#ctrl+KP_SUBTRACT add audio-delay -0.100 # change audio/video sync by shifting the audio earlier +#G add sub-scale +0.1 # increase the subtitle font size +#F add sub-scale -0.1 # decrease the subtitle font size +#9 add volume -2 +#/ add volume -2 +#KP_DIVIDE add volume -2 +#0 add volume 2 +#* add volume 2 +#KP_MULTIPLY add volume 2 +#m cycle mute # toggle mute +#1 add contrast -1 +#2 add contrast 1 +#3 add brightness -1 +#4 add brightness 1 +#5 add gamma -1 +#6 add gamma 1 +#7 add saturation -1 +#8 add saturation 1 +#Alt+0 set window-scale 0.5 # halve the window size +#Alt+1 set window-scale 1.0 # reset the window size +#Alt+2 set window-scale 2.0 # double the window size +#b cycle deband # toggle the debanding filter +#d cycle deinterlace # cycle the deinterlacing filter +#r add sub-pos -1 # move subtitles up +#R add sub-pos +1 # move subtitles down +#t add sub-pos +1 # move subtitles down +#v cycle sub-visibility # hide or show the subtitles +#Alt+v cycle secondary-sub-visibility # hide or show the secondary subtitles +#V cycle sub-ass-use-video-data # cycle which video data gets used in ASS rendering to fix broken files +#u cycle-values sub-ass-override "force" "scale" # toggle overriding SSA/ASS subtitle styles with the normal styles +#j cycle sub # switch subtitle track +#J cycle sub down # switch subtitle track backwards +#SHARP cycle audio # switch audio track +#_ cycle video # switch video track +#T cycle ontop # toggle placing the video on top of other windows +#f cycle fullscreen # toggle fullscreen +#s screenshot # take a screenshot of the video in its original resolution with subtitles +#S screenshot video # take a screenshot of the video in its original resolution without subtitles +#Ctrl+s screenshot window # take a screenshot of the window with OSD and subtitles +#Alt+s screenshot each-frame # automatically screenshot every frame; issue this command again to stop taking screenshots +#w add panscan -0.1 # decrease panscan +#W add panscan +0.1 # shrink black bars by cropping the video +#e add panscan +0.1 # shrink black bars by cropping the video +#A cycle-values video-aspect-override "16:9" "4:3" "2.35:1" "no" # cycle the video aspect ratio +#POWER quit +#PLAY cycle pause # toggle pause/playback mode +#PAUSE cycle pause # toggle pause/playback mode +#PLAYPAUSE cycle pause # toggle pause/playback mode +#PLAYONLY set pause no # unpause +#PAUSEONLY set pause yes # pause +#STOP quit +#FORWARD seek 60 # seek 1 minute forward +#REWIND seek -60 # seek 1 minute backward +#NEXT playlist-next # skip to the next file +#PREV playlist-prev # skip to the previous file +#VOLUME_UP add volume 2 +#VOLUME_DOWN add volume -2 +#MUTE cycle mute # toggle mute +#CLOSE_WIN quit +#CLOSE_WIN {encode} quit 4 +#ctrl+w quit +#E cycle edition # switch edition +#l ab-loop # set/clear A-B loop points +#L cycle-values loop-file "inf" "no" # toggle infinite looping +#ctrl+c quit 4 +#Ctrl+v loadfile ${clipboard/text} append-play; show-text '+ ${clipboard/text}' # append the copied path +#DEL script-binding osc/visibility # cycle OSC visibility between never, auto (mouse-move) and always +#ctrl+h cycle-values hwdec "no" "auto" # toggle hardware decoding +#F8 show-text ${playlist} # show the playlist +#F9 show-text ${track-list} # show the list of video, audio and sub tracks +#g ignore +#g-p script-binding select/select-playlist +#g-s script-binding select/select-sid +#g-S script-binding select/select-secondary-sid +#g-a script-binding select/select-aid +#g-v script-binding select/select-vid +#g-t script-binding select/select-track +#g-c script-binding select/select-chapter +#g-e script-binding select/select-edition +#g-l script-binding select/select-subtitle-line +#g-d script-binding select/select-audio-device +#g-h script-binding select/select-watch-history +#g-w script-binding select/select-watch-later +#g-b script-binding select/select-binding +#g-r script-binding select/show-properties +#g-m script-binding select/menu +#MENU script-binding select/menu +#ctrl+p script-binding select/menu + +#Alt+KP1 add video-rotate -1 # rotate video counterclockwise by 1 degree +#Alt+KP5 set video-rotate 0 # reset rotation +#Alt+KP3 add video-rotate 1 # rotate video clockwise by 1 degree + +#KP1 add video-zoom -0.01 # zoom out video +#KP2 add video-scale-y -0.01 # scale down video vertically +#KP4 add video-scale-x -0.01 # scale down video horizontally +#KP5 set video-scale-x 1.00; set video-scale-y 1; set video-zoom 0 # reset video scale +#KP6 add video-scale-x 0.01 # scale up video horizontally +#KP8 add video-scale-y 0.01 # scale up video vertically +#KP9 add video-zoom 0.01 # zoom in video + +#Ctrl+KP1 add video-pan-x -0.01; add video-pan-y 0.01 # move video left and down +#Ctrl+KP2 add video-pan-y 0.01 # move video down +#Ctrl+KP3 add video-pan-x 0.01; add video-pan-y 0.01 # move video right and down +#Ctrl+KP4 add video-pan-x -0.01 # move video left +#Ctrl+KP5 set video-pan-x 0.00; set video-pan-y 0.00 # reset video position +#Ctrl+KP6 add video-pan-x 0.01 # move video right +#Ctrl+KP7 add video-pan-x -0.01; add video-pan-y -0.01 # move video left and up +#Ctrl+KP8 add video-pan-y -0.01 # move video up +#Ctrl+KP9 add video-pan-x 0.01; add video-pan-y -0.01 # move video right and up + +#Ctrl+KP_END add video-align-x -0.01; add video-align-y 0.01 # align video left and down +#Ctrl+KP_DOWN add video-align-y 0.01 # align video down +#Ctrl+KP_PGDWN add video-align-x 0.01; add video-align-y 0.01 # align video right and down +#Ctrl+KP_LEFT add video-align-x -0.01 # align video left +#Ctrl+KP_BEGIN set video-align-x 0.00; set video-align-y 0.00 # reset video alignment +#Ctrl+KP_RIGHT add video-align-x 0.01 # align video right +#Ctrl+KP_HOME add video-align-x -0.01; add video-align-y -0.01 # align video left and up +#Ctrl+KP_UP add video-align-y -0.01 # align video up +#Ctrl+KP_PGUP add video-align-x 0.01; add video-align-y -0.01 # align video right and up + +# +# Legacy bindings (may or may not be removed in the future) +# +#! add chapter -1 # seek to the previous chapter +#@ add chapter 1 # seek to the next chapter + +# +# Not assigned by default +# (not an exhaustive list of unbound commands) +# + +# ? cycle sub-forced-events-only # display only DVD/PGS forced subtitle events +# ? stop # stop playback (quit or enter idle mode) diff --git a/user/dot_config/mpv/mplayer-input.conf b/user/dot_config/mpv/mplayer-input.conf new file mode 100644 index 0000000..389f74d --- /dev/null +++ b/user/dot_config/mpv/mplayer-input.conf @@ -0,0 +1,93 @@ +## +## MPlayer-style key bindings +## +## Save it as ~/.config/mpv/input.conf to use it. +## +## Generally, it's recommended to use this as reference-only. +## + +RIGHT seek +10 +LEFT seek -10 +DOWN seek -60 +UP seek +60 +PGUP seek 600 +PGDWN seek -600 +m cycle mute +SHARP cycle audio # switch audio streams ++ add audio-delay 0.100 += add audio-delay 0.100 +- add audio-delay -0.100 +[ multiply speed 0.9091 # scale playback speed +] multiply speed 1.1 +{ multiply speed 0.5 +} multiply speed 2.0 +BS set speed 1.0 # reset speed to normal +q quit +ESC quit +ENTER playlist-next force # skip to next file +p cycle pause +. frame-step # advance one frame and pause +SPACE cycle pause +HOME set playlist-pos 0 # not the same as MPlayer +#END pt_up_step -1 +> playlist-next # skip to next file +< playlist-prev # previous +#INS alt_src_step 1 +#DEL alt_src_step -1 +o osd +I show-text "${filename}" # display filename in osd +P show-progress +z add sub-delay -0.1 # subtract 100 ms delay from subs +x add sub-delay +0.1 # add +9 add volume -1 +/ add volume -1 +0 add volume 1 +* add volume 1 +1 add contrast -1 +2 add contrast 1 +3 add brightness -1 +4 add brightness 1 +5 add hue -1 +6 add hue 1 +7 add saturation -1 +8 add saturation 1 +( add balance -0.1 # adjust audio balance in favor of left +) add balance +0.1 # right +d cycle framedrop +D cycle deinterlace # toggle deinterlacer (auto-inserted filter) +r add sub-pos -1 # move subtitles up +t add sub-pos +1 # down +#? sub-step +1 # immediately display next subtitle +#? sub-step -1 # previous +#? add sub-scale +0.1 # increase subtitle font size +#? add sub-scale -0.1 # decrease subtitle font size +f cycle fullscreen +T cycle ontop # toggle video window ontop of other windows +w add panscan -0.1 # zoom out with -panscan 0 -fs +e add panscan +0.1 # in +c cycle stream-capture # save (and append) file/stream to stream.dump with -capture +s screenshot # take a screenshot (if you want PNG, use "--screenshot-format=png") +S screenshot - each-frame # S will take a png screenshot of every frame + +h cycle tv-channel 1 +l cycle tv-channel -1 +n cycle tv-norm +#b tv_step_chanlist + +#? add chapter -1 # skip to previous dvd chapter +#? add chapter +1 # next + +## +## Advanced seek +## Uncomment the following lines to be able to seek to n% of the media with +## the Fx keys. +## +#F1 seek 10 absolute-percent +#F2 seek 20 absolute-percent +#F3 seek 30 absolute-percent +#F4 seek 40 absolute-percent +#F5 seek 50 absolute-percent +#F6 seek 60 absolute-percent +#F7 seek 70 absolute-percent +#F8 seek 80 absolute-percent +#F9 seek 90 absolute-percent diff --git a/user/dot_config/mpv/mpv.conf b/user/dot_config/mpv/mpv.conf new file mode 100644 index 0000000..0fc53f1 --- /dev/null +++ b/user/dot_config/mpv/mpv.conf @@ -0,0 +1,42 @@ +################## +# video settings # +################## + +# Start in fullscreen mode by default. +fs=yes +profile=high-quality +video-sync=display-resample +interpolation +hwdec=auto + +################## +# audio settings # +################## + +audio-channels=auto + +################## +# other settings # +################## + +cache=yes +demuxer-max-bytes=500M +demuxer-max-back-bytes=100M +cache-pause=no +cache-on-disk=no + +# Display English subtitles if available. +slang=de,en + +# Play Finnish audio if available, fall back to English otherwise. +alang=de,en + +sub-auto=fuzzy +sub-font="Inter" +sub-bold=yes + + +############ +# Profiles # +############ + diff --git a/user/dot_config/mpv/restore-old-bindings.conf b/user/dot_config/mpv/restore-old-bindings.conf new file mode 100644 index 0000000..d07b37e --- /dev/null +++ b/user/dot_config/mpv/restore-old-bindings.conf @@ -0,0 +1,59 @@ +# This file contains all bindings that were removed or changed +# after a certain release. +# If you want MPlayer bindings, use mplayer-input.conf + +# Pick the bindings you want back and add them to your own input.conf. Append +# this file to your input.conf if you want them all back: +# +# cat restore-old-bindings.conf >> ~/.config/mpv/input.conf +# +# Older installations use ~/.mpv/input.conf instead. + +# changed in mpv 0.37.0 + +WHEEL_UP seek 10 # seek 10 seconds forward +WHEEL_DOWN seek -10 # seek 10 seconds backward +WHEEL_LEFT add volume -2 +WHEEL_RIGHT add volume 2 + +# changed in mpv 0.27.0 (macOS and Wayland only) + +# WHEEL_LEFT seek 5 +# WHEEL_RIGHT seek -5 + +# changed in mpv 0.26.0 + +H cycle dvbin-channel-switch-offset up +K cycle dvbin-channel-switch-offset down + +I show-text "${filename}" # display filename in osd + +# changed in mpv 0.24.0 + +L cycle-values loop-playlist "inf" "no" + +# changed in mpv 0.10.0 + +O osd +D cycle deinterlace +d cycle framedrop + +# changed in mpv 0.7.0 + +ENTER playlist-next force + +# changed in mpv 0.6.0 + +ESC quit + +# changed in mpv 0.5.0 + +PGUP seek 600 +PGDWN seek -600 +RIGHT seek 10 +LEFT seek -10 ++ add audio-delay 0.100 +- add audio-delay -0.100 +F cycle sub-forced-events-only +U stop +o cycle-values osd-level diff --git a/user/dot_config/mpv/restore-osc-bindings.conf b/user/dot_config/mpv/restore-osc-bindings.conf new file mode 100644 index 0000000..7034f52 --- /dev/null +++ b/user/dot_config/mpv/restore-osc-bindings.conf @@ -0,0 +1,41 @@ +# This file contains all bindings that were removed or changed +# after a certain release. + +# Pick the bindings you want back and add them to your own osc.conf. Append +# this file to your osc.conf if you want them all back: +# +# cat restore-osc-bindings.conf >> ~/.config/mpv/script-opts/osc.conf + +# changed in mpv 0.40.0 + +# previously unbound +title_mbtn_mid_command= +play_pause_mbtn_mid_command= +play_pause_mbtn_right_command= +fullscreen_mbtn_right_command= +volume_mbtn_right_command= + +# restore playlist_osd=yes behavior +playlist_prev_mbtn_left_command=playlist-prev; show-text ${playlist} 3000 +playlist_next_mbtn_left_command=playlist-next; show-text ${playlist} 3000 + +# restore chapter_osd=yes behavior +chapter_prev_mbtn_left_command=no-osd add chapter -1; show-text ${chapter-list} 3000 +chapter_next_mbtn_left_command=no-osd add chapter 1; show-text ${chapter-list} 3000 + +# restore behavior before select.lua usage +playlist_prev_mbtn_right_command=show-text ${playlist} 3000 +playlist_next_mbtn_right_command=show-text ${playlist} 3000 + +title=${media-title} +title_mbtn_left_command=show-text "${!playlist-count==1:[${playlist-pos-1}/${playlist-count}] }${media-title}" +title_mbtn_right_command=show-text ${filename} + +chapter_prev_mbtn_right_command=show-text ${chapter-list} 3000 +chapter_next_mbtn_right_command=show-text ${chapter-list} 3000 + +audio_track_mbtn_right_command=cycle audio down +audio_track_mbtn_mid_command=show-text ${track-list/audio} 3000 + +sub_track_mbtn_right_command=cycle sub down +sub_track_mbtn_mid_command=show-text ${track-list/sub} 3000 diff --git a/user/dot_config/mpv/tech-overview.txt b/user/dot_config/mpv/tech-overview.txt new file mode 100644 index 0000000..ca4c648 --- /dev/null +++ b/user/dot_config/mpv/tech-overview.txt @@ -0,0 +1,656 @@ +This file intends to give a big picture overview of how mpv is structured. + +player/*.c: + Essentially makes up the player applications, including the main() function + and the playback loop. + + Generally, it accesses all other subsystems, initializes them, and pushes + data between them during playback. + + The structure is as follows (as of commit e13c05366557cb): + * main(): + * basic initializations (e.g. init_libav() and more) + * pre-parse command line (verbosity level, config file locations) + * load config files (mp_parse_cfgfiles()) + * parse command line, add files from the command line to playlist + (m_config_parse_mp_command_line()) + * check help options etc. (call handle_help_options()), possibly exit + * call mp_play_files() function that works down the playlist: + * run idle loop (idle_loop()), until there are files in the + playlist or an exit command was given (only if --idle it set) + * actually load and play a file in play_current_file(): + * run all the dozens of functions to load the file and + initialize playback + * run a small loop that does normal playback, until the file is + done or a command terminates playback + (on each iteration, run_playloop() is called, which is rather + big and complicated - it decodes some audio and video on + each frame, waits for input, etc.) + * uninitialize playback + * determine next entry on the playlist to play + * loop, or exit if no next file or quit is requested + (see enum stop_play_reason) + * call mp_destroy() + * run_playloop(): + * calls fill_audio_out_buffers() + This checks whether new audio needs to be decoded, and pushes it + to the AO. + * calls write_video() + Decode new video, and push it to the VO. + * determines whether playback of the current file has ended + * determines when to start playback after seeks + * and calls a whole lot of other stuff + (Really, this function does everything.) + + Things worth saying about the playback core: + - most state is in MPContext (core.h), which is not available to the + subsystems (and should not be made available) + - the currently played tracks are in mpctx->current_track, and decoder + state in track.dec/d_sub + - the other subsystems rarely call back into the frontend, and the frontend + polls them instead (probably a good thing) + - one exceptions are wakeup callbacks, which notify a "higher" component + of a changed situation in a subsystem + + I like to call the player/*.c files the "frontend". + +ta.h & ta.c: + Hierarchical memory manager inspired by talloc from Samba. It's like a + malloc() with more features. Most importantly, each talloc allocation can + have a parent, and if the parent is free'd, all children will be free'd as + well. The parent is an arbitrary talloc allocation. It's either set by the + allocation call by passing a talloc parent, usually as first argument to the + allocation function. It can also be set or reset later by other calls (at + least talloc_steal()). A talloc allocation that is used as parent is often + called a talloc context. + + One very useful feature of talloc is fast tracking of memory leaks. ("Fast" + as in it doesn't require valgrind.) You can enable it by setting the + MPV_LEAK_REPORT environment variable to "1": + export MPV_LEAK_REPORT=1 + This will list all unfree'd allocations on exit. + + Documentation can be found here: + http://git.samba.org/?p=samba.git;a=blob;f=lib/talloc/talloc.h;hb=HEAD + + For some reason, we're still using API-compatible wrappers instead of TA + directly. The talloc wrapper has only a subset of the functionality, and + in particular the wrappers abort() on memory allocation failure. + + Note: unlike tcmalloc, jemalloc, etc., talloc() is not actually a malloc + replacement. It works on top of system malloc and provides additional + features that are supposed to make memory management easier. + +player/command.c: + This contains the implementation for client API commands and properties. + Properties are essentially dynamic variables changed by certain commands. + This is basically responsible for all user commands, like initiating + seeking, switching tracks, etc. It calls into other player/*.c files, + where most of the work is done, but also calls other parts of mpv. + +player/core.h: + Data structures and function prototypes for most of player/*.c. They are + usually not accessed by other parts of mpv for the sake of modularization. + +player/client.c: + This implements the client API (mpv/client.h). For the most part, this + just calls into other parts of the player. This also manages a ringbuffer + of events from player to clients. + +options/options.h, options/options.c + options.h contains the global option struct MPOpts. The option declarations + (option names, types, and MPOpts offsets for the option parser) are in + options.c. Most default values for options and MPOpts are in + mp_default_opts at the end of options.c. + + MPOpts is unfortunately quite monolithic, but is being incrementally broken + up into sub-structs. Many components have their own sub-option structs + separate from MPOpts. New options should be bound to the component that uses + them. Add a new option table/struct if needed. + + The global MPOpts still contains the sub-structs as fields, which serves to + link them to the option parser. For example, an entry like this may be + typical: + + {"", OPT_SUBSTRUCT(demux_opts, demux_conf)}, + + This directs the option access code to include all options in demux_conf + into the global option list, with no prefix (""), and as part of the + MPOpts.demux_opts field. The MPOpts.demux_opts field is actually not + accessed anywhere, and instead demux.c does this: + + struct m_config_cache *opts_cache = + m_config_cache_alloc(demuxer, global, &demux_conf); + struct demux_opts *opts = opts_cache->opts; + + ... to get a copy of its options. + + See m_config_core.h (below) how to access options. + + The actual option parser is spread over m_option.c, m_config_frontend.c, + and parse_commandline.c, and uses the option table in options.c. + +options/m_config_*.h & m_config_*.c: + Code for querying and managing options. m_config_frontend.h contains + declarations for the "legacy-ish" global m_config struct, while + m_config_core.h provides ways to access options in a threads-safe way + anywhere, like m_config_cache_alloc(). + + m_config_cache_alloc() lets anyone read, observe, and write options in any + thread. The only state it needs is struct mpv_global, which is an opaque + type that can be passed "down" the component hierarchy. For safety reasons, + you should not pass down any pointers to option structs (like MPOpts), but + instead pass down mpv_global, and use m_config_cache_alloc() (or similar) + to get a synchronized copy of the options. + +input/input.c: + This translates keyboard input coming from VOs and other sources (such + as remote control devices like Apple IR or client API commands) to the + key bindings listed in the user's (or the builtin) input.conf and turns + them into items of type struct mp_cmd. These commands are queued, and read + by playloop.c. They get pushed with run_command() to command.c. + + Note that keyboard input and commands used by the client API are the same. + The client API only uses the command parser though, and has its own queue + of input commands somewhere else. + +common/msg.h: + All terminal output must go through mp_msg(). + +stream/*: + File input is implemented here. stream.h/.c provides a simple stream based + interface (like reading a number of bytes at a given offset). mpv can + also play from http streams and such, which is implemented here. + + E.g. if mpv sees "http://something" on the command line, it will pick + stream_lavf.c based on the prefix, and pass the rest of the filename to it. + + Some stream inputs are quite special: stream_dvdnav.c turns DVDs into mpeg + streams (DVDs are actually a bunch of vob files etc. on a filesystem), + + Some stream inputs are just there to invoke special demuxers, like + stream_mf.c. (Basically to make the prefix "mf://" do something special.) + +demux/: + Demuxers split data streams into audio/video/sub streams, which in turn + are split in packets. Packets (see packet.h) are mostly byte chunks + tagged with a playback time (PTS). These packets are passed to the decoders. + + Most demuxers have been removed from this fork, and the only important and + "actual" demuxers left are demux_mkv.c and demux_lavf.c (uses libavformat). + There are some pseudo demuxers like demux_cue.c. + + The main interface is in demux.h. The stream headers are in stheader.h. + There is a stream header for each audio/video/sub stream, and each of them + holds codec information about the stream and other information. + + demux.c is a bit big, the main reason being that it contains the demuxer + cache, which is implemented as a list of packets. The cache is complex + because it support seeking, multiple ranges, prefetching, and so on. + +filters/: + Filter related code. filter.c contains the generic filtering framework + which converts input frames to output frames (audio, video, or demux + packet data). f_decoder_wrapper.c is a source filter which connects the + frontend with the actual audio and video decoders. f_output_chain.c handles + VO/AO output conversions. f_autoconvert.c automatically inserts the + appropriate conversion filters if format conversion is needed. + +video/: + This contains several things related to audio/video decoding, as well as + video filters. + + mp_image.h and img_format.h define how mpv stores decoded video frames + internally. + +video/decode/: + vd_*.c are video decoders. (There's only vd_lavc.c left.) + +video/filter/: + vf_*.c are video filters. They are fed by the video decoder, and output the + filtered images to the VOs. By default, no video filters are used. + +video/out/: + Video output. They also create GUI windows and handle user input. In most + cases, the windowing code is shared among VOs, like x11_common.c for X11 and + w32_common.c for Windows. The VOs stand between frontend and windowing code. + vo_gpu and vo_gpu_next can pick a windowing system at runtime, e.g. the same + binary can provide both X11 and Cocoa support on macOS. + + VOs can be reconfigured at runtime. A vo_reconfig() call can change the video + resolution and format, without destroying the window. + + vo_gpu should be taken as reference. + +audio/: + format.h/format.c define the uncompressed audio formats. (As well as some + compressed formats used for spdif.) + +audio/decode/: + ad_*.c handle audio decoding. ad_lavc.c is the decoder using ffmpeg. + ad_spdif.c is not really a decoder, but is used for compressed audio + passthrough. + +audio/filter/: + Audio filters. af_scaletempo2 is inserted by default if playback is different + from normal speed. + +audio/out/: + Audio outputs. + + Unlike VOs, AOs can't be reconfigured on a format change. On audio format + changes, the AO will simply be closed and re-opened. + + buffer.c is the wrapper to support for two types of audio APIs: push and + pull. ao.c calls into that. It contains generic code to deal with the data + flow these APIs impose. + + Note that mpv synchronizes the video to the audio. That's the reason + why buggy audio drivers can have a bad influence on playback quality. + +sub/: + Contains subtitle and OSD rendering. + + osd.c/.h is actually the OSD code. It queries dec_sub.c to retrieve + decoded/rendered subtitles. osd_libass.c is the actual implementation of + the OSD text renderer (which uses libass, and takes care of all the tricky + fontconfig/freetype API usage and text layouting). + + The VOs call osd.c to render OSD and subtitle (via e.g. osd_draw()). osd.c + in turn asks dec_sub.c for subtitle overlay bitmaps, which relays the + request to one of the sd_*.c subtitle decoders/renderers. + + Subtitle loading is in demux/. Normally, subtitles are loaded via demux_lavf.c. + + The subtitles are passed to dec_sub.c and the subtitle decoders in sd_*.c + as they are demuxed. All text subtitles are rendered by sd_ass.c. If text + subtitles are not in the ASS format, the libavcodec subtitle converters are + used (lavc_conv.c). + + Text subtitles can be preloaded, in which case they are read fully as soon + as the subtitle is selected. In this case, they are effectively stored in + sd_ass.c's internal state. + +etc/: + The files input.conf and builtin.conf are actually integrated into the mpv + binary by the build system. They contain the default configs and keybindings. + +Best practices and Concepts within mpv +====================================== + +General contribution etc. +------------------------- + +See: DOCS/contribute.md + +Error checking +-------------- + +If an error is relevant, it should be handled. If it's interesting, log the +error. However, mpv often keeps errors silent and reports failures somewhat +coarsely by propagating them upwards the caller chain. This is OK, as long as +the errors are not very interesting, or would require a developer to debug it +anyway (in which case using a debugger would be more convenient, and the +developer would need to add temporary debug printfs to get extremely detailed +information which would not be appropriate during normal operation). + +Basically, keep a balance on error reporting. But always check them, unless you +have a good argument not to. + +Memory allocation errors (OOM) are a special class of errors. Normally such +allocation failures are not handled "properly". Instead, abort() is called. +(New code should use MP_HANDLE_OOM() for this.) This is done out of laziness and +for convenience, and due to the fact that MPlayer/mplayer2 never handled it +correctly. (MPlayer varied between handling it correctly, trying to do so but +failing, and just not caring, while mplayer2 started using abort() for it.) + +This is justifiable in a number of ways. Error handling paths are notoriously +untested and buggy, so merely having them won't make your program more reliable. +Having these error handling paths also complicates non-error code, due to the +need to roll back state at any point after a memory allocation. + +Take any larger body of code, that is supposed to handle OOM, and test whether +the error paths actually work, for example by overriding malloc with a version +that randomly fails. You will find bugs quickly, and often they will be very +annoying to fix (if you can even reproduce them). + +In addition, a clear indication that something went wrong may be missing. On +error your program may exhibit "degraded" behavior by design. Consider a video +encoder dropping frames somewhere in the middle of a video due to temporary +allocation failures, instead of just exiting with an errors. In other cases, it +may open conceptual security holes. Failing fast may be better. + +mpv uses GPU APIs, which may be break on allocation errors (because driver +authors will have the same issues as described here), or don't even have a real +concept for dealing with OOM (OpenGL). + +libmpv is often used by GUIs, which I predict always break if OOM happens. + +Last but not least, OSes like Linux use "overcommit", which basically means that +your program may crash any time OOM happens, even if it doesn't use malloc() at +all! + +But still, don't just assume malloc() always succeeds. Use MP_HANDLE_OOM(). The +ta* APIs do this for you. The reason for this is that dereferencing a NULL +pointer can have security relevant consequences if large offsets are involved. +Also, a clear error message is better than a random segfault. + +Some big memory allocations are checked anyway. For example, all code must +assume that allocating video frames or packets can fail. (The above example +of dropping video frames during encoding is entirely possible in mpv.) + +Undefined behavior +------------------ + +Undefined behavior (UB) is a concept in the C language. C is famous for being a +language that makes it almost impossible to write working code, because +undefined behavior is so easily triggered, compilers will happily abuse it to +generate "faster" code, debugging tools will shout at you, and sometimes it +even means your code doesn't work. + +There is a lot of literature on this topic. Read it. + +(In C's defense, UB exists in other languages too, but since they're not used +for low level infrastructure, and/or these languages are at times not rigorously +defined, simply nobody cares. However, the C standard committee is still guilty +for not addressing this. I'll admit that I can't even tell from the standard's +gibberish whether some specific behavior is UB or not. It's written like tax +law.) + +In mpv, we generally try to avoid undefined behavior. For one, we want portable +and reliable operation. But more importantly, we want clean output from +debugging tools, in order to find real bugs more quickly and effectively. + +Avoid the "works in practice" argument. Once debugging tools come into play, or +simply when "in practice" stops being true, this will all get back to you in a +bad way. + +Global state, library safety +---------------------------- + +Mutable global state is when code uses global variables that are not read-only. +This must be avoided in mpv. Always use context structs that the caller of +your code needs to allocate, and whose pointers are passed to your functions. + +Library safety means that your code (or library) can be used by a library +without causing conflicts with other library users in the same process. To any +piece of code, a "safe" library's API can simply be used, without having to +worry about other API users that may be around somewhere. + +Libraries are often not library safe, because they use global mutable state +or other "global" resources. Typical examples include use of signals, simple +global variables (like hsearch() in libc), or internal caches not protected by +locks. + +A surprisingly high number of libraries are not library safe because they need +global initialization. Typically they provide an API function, which +"initializes" the library, and which must be called before calling any other +API functions. Often, you are to provide global configuration parameters, which +can change the behavior of the library. If two libraries A and B use library C, +but A and B initialize C with different parameters, something "bad" may happen. +In addition, these global initialization functions are often not thread-safe. So +if A and B try to initialize C at the same time (from different threads and +without knowing about each other), it may cause undefined behavior. (libcurl is +a good example of both of these issues. FFmpeg and some TLS libraries used to be +affected, but improved.) + +This is so bad because library A and B from the previous example most likely +have no way to cooperate, because they're from different authors and have no +business knowing each others. They'd need a library D, which wraps library C +in a safe way. Unfortunately, typically something worse happens: libraries get +"infected" by the unsafeness of its sub-libraries, and export a global init API +just to initialize the sub-libraries. In the previous example, libraries A and B +would export global init APIs just to init library C, even though the rest of +A/B are clean and library safe. (Again, libcurl is an example of this, if you +subtract other historic anti-features.) + +The main problem with library safety is that its lack propagates to all +libraries using the library. + +We require libmpv to be library safe. This is not really possible, because some +libraries are not library safe (FFmpeg, Xlib, partially ALSA). However, for +ideological reasons, there is no global init API, and best effort is made to try +to avoid problems. + +libmpv has some features that are not library safe, but which are disabled by +default (such as terminal usage aka stdout, or JSON IPC blocking SIGPIPE for +internal convenience). + +A notable, very disgustingly library unsafe behavior of libmpv is calling +abort() on some memory allocation failure. See error checking section. + +Logging +------- + +All logging and terminal output in mpv goes through the functions and macros +provided in common/msg.h. This is in part for library safety, and in part to +make sure users can silence all output, or to redirect the output elsewhere, +like a log file or the internal console.lua script. + +Locking +------- + +See generally available literature. In mpv, we use mp_thread for this. + +Always keep locking clean. Don't skip locking just because it will work "in +practice". (See undefined behavior section.) If your use case is simple, you may +use C11 atomics, but most likely you will only hurt yourself and others. + +Always make clear which fields in a struct are protected by which lock. If a +field is immutable, or simply not thread-safe (e.g. state for a single worker +thread), document it as well. + +Internal mpv APIs are assumed to be not thread-safe by default. If they have +special guarantees (such as being usable by more than one thread at a time), +these should be explicitly documented. + +All internal mpv APIs must be free of global state. Even if a component is not +thread-safe, multiple threads can use _different_ instances of it without any +locking. + +On a side note, recursive locks may seem convenient at first, but introduce +additional problems with condition variables and locking hierarchies. They +should be avoided. + +Locking hierarchy +----------------- + +A simple way to avoid deadlocks with classic locking is to define a locking +hierarchy or lock order. If all threads acquire locks in the same order, no +deadlocks will happen. + +For example, a "leaf" lock is a lock that is below all other locks in the +hierarchy. You can acquire it any time, as long as you don't acquire other +locks while holding it. + +Unfortunately, C has no way to declare or check the lock order, so you should at +least document it. + +In addition, try to avoid exposing locks to the outside. Making the declaration +of a lock private to a specific .c file (and _not_ exporting accessors or +lock/unlock functions that manipulate the lock) is a good idea. Your component's +API may acquire internal locks, but should release them when returning. Keeping +the entire locking in a single file makes it easy to check it. + +Avoiding callback hell +---------------------- + +mpv code is separated in components, like the "frontend" (i.e. MPContext mpctx), +VOs, AOs, demuxers, and more. The frontend usually calls "down" the usage +hierarchy: mpctx almost on top, then things like vo/ao, and utility code on the +very bottom. + +"Callback hell" is when components call both up and down the hierarchy, +which for example leads to accidentally recursion, reentrancy problems, or +locking nightmares. This is avoided by (mostly) calling only down the hierarchy. +Basically the call graph forms a DAG. The other direction is handled by event +queues, wakeup callbacks, and similar mechanisms. + +Typically, a component provides an API, and does not know anything about its +user. The API user (component higher in the hierarchy) polls the state of the +lower component when needed. + +This also enforces some level of modularization, and with some luck the locking +hierarchy. (Basically, locks of lower components automatically become leaf +locks.) Another positive effect is simpler memory management. + +(Also see e.g.: http://250bpm.com/blog:24) + +Wakeup callbacks +---------------- + +This is a common concept in mpv. Even the public API uses it. It's used when an +API has internal threads (or otherwise triggers asynchronous events), but the +component call hierarchy needs to be kept. The wakeup callback is the only +exception to the call hierarchy, and always calls up. + +For example, vo spawns a thread that the API user (the mpv frontend) does not +need to know about. vo simply provides a single-threaded API (or that looks like +one). This API needs a way to notify the API user of new events. But the vo +event producer is on the vo thread - it can't simply invoke a callback back into +the API user, because then the API user has to deal with locking, despite not +using threads. In addition, this will probably cause problems like mentioned in +the "callback hell" section, especially lock order issues. + +The solution is the wakeup callback. It merely unblocks the API user from +waiting, and the API user then uses the normal vo API to examine whether or +which state changed. As a concept, it documents what a wakeup callback is +allowed to do and what not, to avoid the aforementioned problems. + +Generally, you are not allowed to call any API from the wakeup callback. You +just do whatever is needed to unblock your thread. For example, if it's waiting +on a mutex/condition variable, acquire the mutex, set a change flag, signal +the condition variable, unlock, return. (This mutex must not be held when +calling the API. It must be a leaf lock.) + +Restricting the wakeup callback like this sidesteps any reentrancy issues and +other complexities. The API implementation can simply hold internal (and +non-recursive) locks while invoking the wakeup callback. + +The API user still needs to deal with locking (probably), but there's only the +need to implement a single "receiver", that can handle the entire API of the +used component. (Or multiple APIs - MPContext for example has only 1 wakeup +callback that handles all AOs, VOs, input, demuxers, and more. It simple re-runs +the playloop.) + +You could get something more advanced by turning this into a message queue. The +API would append a message to the queue, and the API user can read it. But then +you still need a way to "wakeup" the API user (unless you force the API user +to block on your API, which will make things inconvenient for the API user). You +also need to worry about what happens if the message queue overruns (you either +lose messages or have unbounded memory usage). In the mpv public API, the +distinction between message queue and wakeup callback is sort of blurry, because +it does provide a message queue, but an additional wakeup callback, so API +users are not required to call mpv_wait_event() with a high timeout. + +mpv itself prefers using wakeup callbacks over a generic event queue, because +most times an event queue is not needed (or complicates things), and it is +better to do it manually. + +(You could still abstract the API user side of wakeup callback handling, and +avoid reimplementing it all the time. Although mp_dispatch_queue already +provides mechanisms for this.) + +Condition variables +------------------- + +They're used whenever a thread needs to wait for something, without nonsense +like sleep calls or busy waiting. mpv uses the mp_thread API for this. +There's a lot of literature on condition variables, threading in general. Read it. + +For initial understanding, it may be helpful to know that condition variables +are not variables that signal a condition. mp_cond does not have any +state per-se. Maybe mp_cond would better be named mp_interrupt, +because its sole purpose is to interrupt a thread waiting via mp_cond_wait() +(or similar). The "something" in "waiting for something" can be called +predicate (to avoid confusing it with "condition"). Consult literature for the +proper terms. + +The very short version is... + +Shared declarations: + + mp_mutex lock; + mp_cond cond_var; + struct something state_var; // protected by lock, changes signaled by cond_var + +Waiter thread: + + mp_mutex_lock(&lock); + + // Wait for a change in state_var. We want to wait until predicate_fulfilled() + // returns true. + // Must be a loop for 2 reasons: + // 1. cond_var may be associated with other conditions too + // 2. mp_cond_wait() can have sporadic wakeups + while (!predicate_fulfilled(&state_var)) { + // This unlocks, waits for cond_var to be signaled, and then locks again. + // The _whole_ point of cond_var is that unlocking and waiting for the + // signal happens atomically. + mp_cond_wait(&cond_var, &lock); + } + + // Here you may react to the state change. The state cannot change + // asynchronously as long as you still hold the lock (and didn't release + // and reacquire it). + // ... + + mp_mutex_unlock(&lock); + +Signaler thread: + + mp_mutex_lock(&lock); + + // Something changed. Update the shared variable with the new state. + update_state(&state_var); + + // Notify that something changed. This will wake up the waiter thread if + // it's blocked in mp_cond_wait(). If not, nothing happens. + mp_cond_broadcast(&cond_var); + + // Fun fact: good implementations wake up the waiter only when the lock is + // released, to reduce kernel scheduling overhead. + mp_mutex_unlock(&lock); + +Some basic rules: + 1. Always access your state under proper locking + 2. Always check your predicate before every call to mp_cond_wait() + (And don't call mp_cond_wait() if the predicate is fulfilled.) + 3. Always call mp_cond_wait() in a loop + (And only if your predicate failed without releasing the lock..) + 4. Always call mp_cond_broadcast()/_signal() inside of its associated + lock + +mpv sometimes violates rule 3, and leaves "retrying" (i.e. looping) to the +caller. + +Common pitfalls: + - Thinking that mp_cond is some kind of semaphore, or holds any + application state or the user predicate (it _only_ wakes up threads + that are at the same time blocking on mp_cond_wait() and friends, + nothing else) + - Changing the predicate, but not updating all mp_cond_broadcast()/ + _signal() calls correctly + - Forgetting that mp_cond_wait() unlocks the lock (other threads can + and must acquire the lock) + - Holding multiple nested locks while trying to wait (=> deadlock, violates + the lock order anyway) + - Waiting for a predicate correctly, but unlocking/relocking before acting + on it (unlocking allows arbitrary state changes) + - Confusing which lock/condition var. is used to manage a bit of state + +Generally available literature probably has better examples and explanations. + +Using condition variables the proper way is generally preferred over using more +messy variants of them. (Just saying because on win32, "SetEvent" exists, and +it's inferior to condition variables. Try to avoid the win32 primitives, even if +you're dealing with Windows-only code.) + +Threads +------- + +Threading should be conservatively used. Normally, mpv code pretends to be +single-threaded, and provides thread-unsafe APIs. Threads are used coarsely, +and if you can avoid messing with threads, you should. For example, VOs and AOs +do not need to deal with threads normally, even though they run on separate +threads. The glue code "isolates" them from any threading issues. diff --git a/user/dot_config/qt5ct/qt5ct.conf b/user/dot_config/qt5ct/qt5ct.conf index 47285a2..2d70a01 100644 --- a/user/dot_config/qt5ct/qt5ct.conf +++ b/user/dot_config/qt5ct/qt5ct.conf @@ -1,2 +1,32 @@ [Appearance] +color_scheme_path=/home/frank/.config/qt5ct/colors/catppuccin-mocha-blue.conf +custom_palette=true icon_theme=Papirus-Dark +standard_dialogs=xdgdesktopportal +style=Darkly + +[Fonts] +fixed="FiraMono Nerd Font,13,-1,5,50,0,0,0,0,0,Regular" +general="Inter,13,-1,5,50,0,0,0,0,0,Regular" + +[Interface] +activate_item_on_single_click=1 +buttonbox_layout=0 +cursor_flash_time=1000 +dialog_buttons_have_icons=2 +double_click_interval=400 +gui_effects=@Invalid() +keyboard_scheme=2 +menus_have_icons=true +show_shortcuts_in_context_menus=true +stylesheets=@Invalid() +toolbutton_style=4 +underline_shortcut=2 +wheel_scroll_lines=3 + +[SettingsWindow] +geometry=@ByteArray(\x1\xd9\xd0\xcb\0\x3\0\0\0\0\0\0\0\0\0\0\0\0\x5?\0\0\x5\x43\0\0\0\0\0\0\0\0\0\0\x6\xb7\0\0\x5\x9f\0\0\0\0\x2\0\0\0\rp\0\0\0\0\0\0\0\0\0\0\x5?\0\0\x5\x43) + +[Troubleshooting] +force_raster_widgets=1 +ignored_applications=@Invalid() diff --git a/user/dot_config/qt6ct/qt6ct.conf b/user/dot_config/qt6ct/qt6ct.conf index 91f561f..f5edea9 100644 --- a/user/dot_config/qt6ct/qt6ct.conf +++ b/user/dot_config/qt6ct/qt6ct.conf @@ -1,5 +1,32 @@ -[SettingsWindow] -geometry=@ByteArray(\x1\xd9\xd0\xcb\0\x3\0\0\0\0\0\0\0\0\0\0\0\0\x4\x13\0\0\x2l\0\0\0\0\0\0\0\0\0\0\x4\x13\0\0\x2l\0\0\0\x1\x2\0\0\0\rp\0\0\0\0\0\0\0\0\0\0\x4\x13\0\0\x2l) - [Appearance] +color_scheme_path=/home/frank/.config/qt6ct/colors/catppuccin-mocha-blue.conf +custom_palette=true icon_theme=Papirus-Dark +standard_dialogs=xdgdesktopportal +style=Darkly + +[Fonts] +fixed="FiraMono Nerd Font,13,-1,5,400,0,0,0,0,0,0,0,0,0,0,1,,0,0" +general="Inter,13,-1,5,400,0,0,0,0,0,0,0,0,0,0,1,,0,0" + +[Interface] +activate_item_on_single_click=1 +buttonbox_layout=2 +cursor_flash_time=1200 +dialog_buttons_have_icons=2 +double_click_interval=400 +gui_effects=@Invalid() +keyboard_scheme=2 +menus_have_icons=true +show_shortcuts_in_context_menus=true +stylesheets=@Invalid() +toolbutton_style=4 +underline_shortcut=2 +wheel_scroll_lines=3 + +[SettingsWindow] +geometry=@ByteArray(\x1\xd9\xd0\xcb\0\x3\0\0\0\0\0\0\0\0\0\0\0\0\x5?\0\0\x5\x43\0\0\0\0\0\0\0\0\0\0\x5?\0\0\x5\x43\0\0\0\0\x2\0\0\0\rp\0\0\0\0\0\0\0\0\0\0\x5?\0\0\x5\x43) + +[Troubleshooting] +force_raster_widgets=1 +ignored_applications=@Invalid() diff --git a/user/dot_config/scripts/executable_action_menu.sh b/user/dot_config/scripts/executable_action_menu.sh new file mode 100644 index 0000000..efd8a38 --- /dev/null +++ b/user/dot_config/scripts/executable_action_menu.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +action=$(wofi --cache-file=/dev/null --dmenu << EOF +󰅛 Restart Network +EOF +) + +case "$action" in + "󰅛 Restart Network") + ~/.config/scripts/restart_network.sh + ;; +esac diff --git a/user/dot_config/scripts/executable_restart_network.sh b/user/dot_config/scripts/executable_restart_network.sh new file mode 100644 index 0000000..a10d7d1 --- /dev/null +++ b/user/dot_config/scripts/executable_restart_network.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +PCIE_ADAPTER_SUFFIX=$(lspci | grep I225 | cut -d' ' -f1) +PCIE_ADAPTER_ADDRESS=$(ls -1 /sys/bus/pci/devices | grep "${PCIE_ADAPTER_SUFFIX}") + +pkexec bash -c "echo 1 > /sys/bus/pci/devices/${PCIE_ADAPTER_ADDRESS}/remove; echo 1 > /sys/bus/pci/rescan" diff --git a/user/dot_config/uwsm/env b/user/dot_config/uwsm/env index 2a5bd0a..9b8e53c 100644 --- a/user/dot_config/uwsm/env +++ b/user/dot_config/uwsm/env @@ -1,2 +1,3 @@ export XCURSOR_THEME="Breeze_Light" export XCURSOR_SIZE="24" +export QT_QPA_PLATFORMTHEME="qt6ct" diff --git a/user/dot_config/uwsm/env-hyprland b/user/dot_config/uwsm/env-hyprland index 48a8006..b6a2b20 100644 --- a/user/dot_config/uwsm/env-hyprland +++ b/user/dot_config/uwsm/env-hyprland @@ -1,2 +1,3 @@ export HYPRCURSOR_THEME="Breeze_Light" export HYPRCURSOR_SIZE="24" +export QT_QPA_PLATFORMTHEME="qt6ct" diff --git a/user/dot_config/wireplumber/wireplumber.conf.d/51-disable-suspension.conf b/user/dot_config/wireplumber/wireplumber.conf.d/51-disable-suspension.conf new file mode 100644 index 0000000..cd77adc --- /dev/null +++ b/user/dot_config/wireplumber/wireplumber.conf.d/51-disable-suspension.conf @@ -0,0 +1,41 @@ +# SPDIF devices +monitor.alsa.rules = [ + { + matches = [ + { + # Matches all sources + node.name = "~alsa_input.*" + }, + { + # Matches all sinks + node.name = "~alsa_output.*" + } + ] + actions = { + update-props = { + session.suspend-timeout-seconds = 0 + } + } + } +] + +# bluetooth devices +monitor.bluez.rules = [ + { + matches = [ + { + # Matches all sources + node.name = "~bluez_input.*" + }, + { + # Matches all sinks + node.name = "~bluez_output.*" + } + ] + actions = { + update-props = { + session.suspend-timeout-seconds = 0 + } + } + } +] diff --git a/user/dot_config/wofi/config b/user/dot_config/wofi/config new file mode 100644 index 0000000..84728e6 --- /dev/null +++ b/user/dot_config/wofi/config @@ -0,0 +1,32 @@ +show=drun +width=600 +height=300 +location=center +columns=1 + +prompt=Application + +allow_images=true +image_size=24 +allow_markup=true +hide_scroll=true +parse_search=true + +term=kitty + +matching=contains +insensitive=true + +dmenu-parse_action=true +run-always_parse_args=true +run-show_all=false +drun-disable_prime=true +drun-display_generic=false + +key_up=Ctrl-k +key_down=Ctrl-j +key_left=Ctrl-h +key_right=Ctrl-l +key_pgup=Ctrl-u +key_pgdown=Ctrl-d +key_expand=Ctrl-e diff --git a/user/dot_config/wofi/style.css b/user/dot_config/wofi/style.css new file mode 100644 index 0000000..72ea177 --- /dev/null +++ b/user/dot_config/wofi/style.css @@ -0,0 +1,132 @@ +/* MACHHIATO */ +@define-color rosewater #f4dbd6; +@define-color flamingo #f0c6c6; +@define-color pink #f5bde6; +@define-color mauve #c6a0f6; +@define-color red #ed8796; +@define-color maroon #ee99a0; +@define-color peach #f5a97f; +@define-color yellow #eed49f; +@define-color green #a6da95; +@define-color teal #8bd5ca; +@define-color sky #91d7e3; +@define-color sapphire #7dc4e4; +@define-color blue #8aadf4; +@define-color lavender #b7bdf8; +@define-color text #cad3f5; +@define-color subtext1 #b8c0e0; +@define-color subtext0 #a5adcb; +@define-color overlay2 #939ab7; +@define-color overlay1 #8087a2; +@define-color overlay0 #6e738d; +@define-color surface2 #5b6078; +@define-color surface1 #494d64; +@define-color surface0 #363a4f; +@define-color base #24273a; +@define-color mantle #1e2030; +@define-color crust #181926; + + +* { + font-family: 'Noto Sans Nerd Font', 'FiraMono Nerd Font', 'FiraCode Nerd Font Mono', 'RobotoMono Nerd Font Propo', monospace; + font-size: 14px; + outline: none; +} + +window { + margin: 0px; + padding: 7px; + border: 2px solid @yellow; + border-radius: 0px; + background-color: @crust; +} + +#outer-box { + margin : 17px; +} + +#input { + background-color : @surface0; + color : @text; + border-radius : 0; + padding: 2px 0px; + margin-bottom : 17px; +} + +#input:focus { + box-shadow: none; +} + +#input image { + color: @yellow; + padding: 0 7px; +} + +#scroll { + border: none; +} + +/* First Level Entries */ +#inner-box > #entry { + border-radius : 0; + border: 1px solid @mantle; + background-color : @mantle; + color: @text; + padding : 7px; + padding-left : 22px; +} + +#inner-box > #entry:nth-child(odd) { + background-color : @base; +} + +#inner-box > #entry:selected { + background-color: @surface1; + color: @blue; + border: 1px solid @yellow; +} + +#inner-box > #entry:selected #text { + color: @blue; +} + +#inner-box > #entry expander #entry { + border-radius : 0; + border: none; + color: @text; + padding : 2px; + background-color : @mantle; + padding-left: 17px; +} + +#inner-box > #entry:nth-child(odd) expander #entry { + background-color : @base; +} + +#inner-box > #entry:selected expander #entry { + background-color : @surface1; +} + +#inner-box > #entry:selected expander #entry #text { + color: @text; +} + +#inner-box > #entry:selected expander #entry:selected { + background-color: @surface2; +} + +#inner-box > #entry:selected expander #entry:selected #text { + color: @yellow; +} + +#text { + border: none; + color: @text; + margin-left : 12px; +} + +#entry arrow { + margin-left : -17px; + color: @text; + margin-right : 2px; +}