commit af8af444582ea33ed63a21a78329af59e191db4f from: mtmn date: Tue Jul 14 12:56:54 2026 UTC void: migrate apps to shepherd commit - 8727e48c019cbf81e7b9290bb08459ac5b512d65 commit + af8af444582ea33ed63a21a78329af59e191db4f blob - e39dca1bf2bde6b5093f9678e00a62433ca1f20a blob + dc2adffeb301cdd13645a7daf8bd99bf7ecce2a1 --- flake.lock +++ flake.lock @@ -32,11 +32,11 @@ ] }, "locked": { - "lastModified": 1784030718, - "narHash": "sha256-6EvmUvmyG6ciz71anFi+KbH3JZf8Z0SeI1jVb2u8Rgo=", + "lastModified": 1784049068, + "narHash": "sha256-nvO5rN+SWdpVGY1OIFziAz8JaTl265lgSRlPnQCciIc=", "owner": "~mtmn", "repo": "corpus", - "rev": "2f4f1bb6530a517dd155e2fcf7d2aa93f8343e15", + "rev": "4a464dc7ea2c23ef107e4b2d9f5cc6c840c52e26", "type": "sourcehut" }, "original": { blob - 92754fba4f0c97d4edd1bf914c5bf0492cf02c3c blob + 4b23cbe5c0b76e3801826dbe54d702f724404753 --- hosts/void/overlays/bin/mics +++ hosts/void/overlays/bin/mics @@ -1,12 +1,32 @@ -#!/bin/sh -sw=numid=7 +#!/bin/bash -e -cur=$(amixer -c 1 cget "$sw" | sed -n 's/.*: values=\(on\|off\).*/\1/p' | head -1) +usage() { + echo "Usage: mics mute|unmute [seconds]" + exit 1 +} -if [ "$cur" = off ]; then - amixer -c 1 cset "$sw" on >/dev/null - printf '%s\n' "mic unmuted" +cmd=${1:-mute} + +if [ "$cmd" != "mute" ] && [ "$cmd" != "unmute" ]; then + usage +fi + +indices=$(pactl list short sources | awk '{print $1}') + +if [ "$cmd" = "mute" ]; then + echo "$indices" | xargs -I{} pactl set-source-volume {} 0% else - amixer -c 1 cset "$sw" off >/dev/null - printf '%s\n' "mic muted" + time=$2 + echo "$indices" | xargs -I{} pactl set-source-volume {} 100% + if [ "$time" ]; then + sleep "$time" + echo "$indices" | xargs -I{} pactl set-source-volume {} 0% + fi fi + +echo "Current microphone status:" +echo "$indices" | while read -r idx; do + echo "Source $idx:" + echo " $(pactl get-source-mute "$idx")" + echo " $(pactl get-source-volume "$idx")" +done blob - c75f4db815840fec3f55eaf3a98a25db91c671f9 (mode 644) blob + /dev/null --- hosts/void/overlays/bin/otterb +++ /dev/null @@ -1,216 +0,0 @@ -#!/usr/bin/env ruby -# frozen_string_literal: true - -require "fileutils" -require "open3" -require "etc" - -class Builder - REPO = "https://repo-default.voidlinux.org/current" - DEPS = %w[ - cmake - make - gcc - qt5-devel - qt5-svg-devel - qt5-multimedia-devel - qt5-declarative-devel - qt5-webengine - qt5-webengine-devel - qt5-webkit-devel - qt5-webchannel-devel - qt5-location-devel - hunspell-devel - gstreamer1-devel - libxml2-devel - qt5-tools - ] - .freeze - - def initialize(argv) - @outdir = nil - @chroot = "/var/chroot/otter-build" - @keep = false - @quiet = false - parse(argv) - validate - end - - def run - bootstrap - mount_vfs - prep_chroot - install_deps - build - extract - ensure - unmount_vfs - remove_chroot unless @keep - msg("done.") - end - - private - - def parse(argv) - i = 0 - while i < argv.length - case argv[i] - when "-o" - @outdir = argv[i += 1] - when "-c" - @chroot = argv[i += 1] - when "-k" - @keep = true - when "-q" - @quiet = true - when "-h", "--help" - usage(code: 0) - else - usage - end - - i += 1 - end - end - - def usage_lines - [ - "Usage: #{File.basename($0)} [-o DIR] [-c DIR] [-k] [-q]", - " -o DIR output directory (default: invoking user home)", - " -c DIR chroot directory (default: /var/chroot/otter-build)", - " -k keep chroot after build", - " -q quiet" - ] - end - - def usage(code: 1) - usage_lines.each { |l| puts(l) } - exit(code) - end - - def validate - unless Process.uid.zero? - usage_lines.each { |l| puts(l) } - die("must run as root") - end - - @src = Dir.pwd - die("no CMakeLists.txt in #{@src}") unless File.file?(File.join(@src, "CMakeLists.txt")) - - inv = ENV["SUDO_USER"] || ENV["DOAS_USER"] - if inv - @pw = Etc.getpwnam(inv) rescue nil - die("cannot resolve user #{inv}") unless @pw - @outdir ||= @pw.dir - else - @outdir ||= File.expand_path("~") - end - end - - def msg(s) = puts(s) unless @quiet - - def die(s) - $stderr.puts("#{File.basename($0)}: #{s}") - exit(1) - end - - def run_cmd(cmd, fatal: true) - msg(cmd) - _o, e, st = Open3.capture3(cmd) - die("#{cmd}: #{e.strip}") if !st.success? && fatal - st.success? - end - - def chroot_cmd(script) - msg("chroot #{@chroot} /bin/bash -c '#{script}'") - die("chroot command failed") unless system("chroot #{@chroot} /bin/bash -c '#{script}'") - end - - def bootstrap - FileUtils.mkdir_p(@chroot) - return if File.executable?(File.join(@chroot, "bin/bash")) - - msg("bootstrapping chroot...") - kdir = File.join(@chroot, "var/db/xbps/keys") - FileUtils.mkdir_p(kdir) - Dir.glob("/var/db/xbps/keys/*").each { |f| FileUtils.cp(f, kdir) } - - run_cmd("xbps-install -Syu -R #{REPO} -r #{@chroot} base-voidstrap", fatal: false) - die("bootstrap failed") unless File.executable?(File.join(@chroot, "bin/bash")) - msg("bootstrap ok") - end - - def mount_vfs - mounts = { - File.join(@chroot, "proc") => ["-t", "proc", "proc"], - File.join(@chroot, "sys") => ["-t", "sysfs", "sys"], - File.join(@chroot, "dev") => ["--bind", "/dev"] - } - mounts.each do |dst, opts| - FileUtils.mkdir_p(dst) - next if system("mountpoint -q #{dst} 2>/dev/null") - system("mount #{opts.join(" ")} #{dst}") - end - end - - def unmount_vfs - %w[dev sys proc].each { |n| system("umount #{File.join(@chroot, n)} 2>/dev/null") } - end - - def prep_chroot - FileUtils.cp("/etc/resolv.conf", File.join(@chroot, "etc/resolv.conf")) - kdir = File.join(@chroot, "var/db/xbps/keys") - FileUtils.mkdir_p(kdir) - Dir.glob("/var/db/xbps/keys/*").each { |f| FileUtils.cp(f, kdir) } - end - - def install_deps - chroot_cmd("xbps-install -Syu") - chroot_cmd("xbps-install -S #{DEPS.join(" ")}") - end - - def build - dst = File.join(@chroot, "src/otter-browser") - FileUtils.rm_rf(dst) - FileUtils.mkdir_p(File.dirname(dst)) - system("cp -a #{@src} #{dst}") || die("copy failed") - - cm = File.join(dst, "CMakeLists.txt") - txt = File.read(cm) - unless txt.include?("FATAL_ON_MISSING_REQUIRED_PACKAGES") - die("CMakeLists.txt: FATAL_ON_MISSING_REQUIRED_PACKAGES not found") - end - - txt.gsub!("FATAL_ON_MISSING_REQUIRED_PACKAGES", "") - File.write(cm, txt) - - script = "set -e; cd /src/otter-browser; rm -rf build; mkdir build; cd build; cmake -DENABLE_QT5=ON ../; make -j$(nproc)" - chroot_cmd(script) - end - - def extract - bin = File.join(@chroot, "src/otter-browser/build/otter-browser") - die("binary not found") unless File.file?(bin) - - out = File.join(@outdir, "otter-browser") - system("cp #{bin} #{out}") || die("copy binary failed") - FileUtils.chmod("+x", out) - - if @pw - begin - File.chown(@pw.uid, @pw.gid, out) - rescue => e - msg("chown failed: #{e}") - end - end - - msg("binary: #{out}") - end - - def remove_chroot - msg("removing #{@chroot}...") - FileUtils.rm_rf(@chroot) - end -end - -Builder.new(ARGV).run blob - ee6c7a7b0ffbad97cfc990add38df7b78472982b blob + 48b410ec42d1892bf13c48b3cdb3537815a2fc7b --- hosts/void/overlays/config/river/init +++ hosts/void/overlays/config/river/init @@ -127,20 +127,4 @@ riverctl map normal $alt+Shift Tab send-to-previous-ta riverctl map normal $mod Tab focus-previous-tags riverctl map normal $mod+Shift Tab send-to-previous-tags -swaybg -m fill -c "#0d1612" -i "$HOME/misc/random/wallpapers/curtains.jpg" & -mkfifo "$wobsock" && tail -f "$wobsock" | wob & -wl-paste --watch cliphist store & - -services_to_start=( - battery-notify - fnott - pipewire - kanshi - psi-notify - memcached - nix-daemon -) - -for s in "${services_to_start[@]}"; do - "$s" 2>&1 | vlogger -t "$s" & -done +runsvdir "$HOME/.config/sv" & blob - /dev/null blob + d7890f835d0920aa84eff1ca11382994d8849dfc (mode 644) --- /dev/null +++ hosts/void/overlays/config/shepherd/init.d/battery-notify.scm @@ -0,0 +1,2 @@ +;; -*- mode: scheme; -*- +(exec-service 'battery-notify '("battery-notify")) blob - /dev/null blob + 3dd1f9669954f510716dde7a90b1be4a49957454 (mode 644) --- /dev/null +++ hosts/void/overlays/config/shepherd/init.d/cliphist.scm @@ -0,0 +1,2 @@ +;; -*- mode: scheme; -*- +(exec-service 'cliphist '("wl-paste" "--watch" "cliphist" "store")) blob - /dev/null blob + 0ee7387bd902c2edca98407c2596ae79f521ae0f (mode 644) --- /dev/null +++ hosts/void/overlays/config/shepherd/init.d/fnott.scm @@ -0,0 +1,2 @@ +;; -*- mode: scheme; -*- +(exec-service 'fnott '("fnott")) blob - /dev/null blob + 990f67e1094a6021172cd1b0b715b029df87ab59 (mode 644) --- /dev/null +++ hosts/void/overlays/config/shepherd/init.d/hister.scm @@ -0,0 +1,2 @@ +;; -*- mode: scheme; -*- +(exec-service 'hister '("hister" "listen")) blob - /dev/null blob + a33c316e34352b8463d3eb91564168370a34cac9 (mode 644) --- /dev/null +++ hosts/void/overlays/config/shepherd/init.d/kanshi.scm @@ -0,0 +1,2 @@ +;; -*- mode: scheme; -*- +(exec-service 'kanshi '("kanshi")) blob - /dev/null blob + 09304c6911eff2c72925319adcd8eefc2716e8db (mode 644) --- /dev/null +++ hosts/void/overlays/config/shepherd/init.d/memcached.scm @@ -0,0 +1,2 @@ +;; -*- mode: scheme; -*- +(exec-service 'memcached '("memcached")) blob - /dev/null blob + e339da50cbe82c2f9ce4ef4d7fe2072de8b9c814 (mode 644) --- /dev/null +++ hosts/void/overlays/config/shepherd/init.d/nix-daemon.scm @@ -0,0 +1,2 @@ +;; -*- mode: scheme; -*- +(exec-service 'nix-daemon '("nix-daemon")) blob - /dev/null blob + dc458a7d0d58fdb438904bd22447d4e55c4717a5 (mode 644) --- /dev/null +++ hosts/void/overlays/config/shepherd/init.d/pipewire.scm @@ -0,0 +1,2 @@ +;; -*- mode: scheme; -*- +(exec-service 'pipewire '("pipewire")) blob - /dev/null blob + 7fa8d625de9bdf259ba9d88c1201f98d748e18bd (mode 644) --- /dev/null +++ hosts/void/overlays/config/shepherd/init.d/psi-notify.scm @@ -0,0 +1,2 @@ +;; -*- mode: scheme; -*- +(exec-service 'psi-notify '("psi-notify")) blob - /dev/null blob + 05e9f3832b683dfdfe602e91415e0269e1c42328 (mode 644) --- /dev/null +++ hosts/void/overlays/config/shepherd/init.d/swaybg.scm @@ -0,0 +1,5 @@ +;; -*- mode: scheme; -*- +(exec-service 'swaybg + (list "swaybg" "-m" "fill" "-c" "#0d1612" + "-i" (string-append (getenv "HOME") + "/misc/random/wallpapers/curtains.jpg"))) blob - /dev/null blob + 9bd2f907e28d3de02df2aacf7f787039b2c0c043 (mode 644) --- /dev/null +++ hosts/void/overlays/config/shepherd/init.d/wob.scm @@ -0,0 +1,9 @@ +;; -*- mode: scheme; -*- +;; wob reads volume/brightness levels from a FIFO at $XDG_RUNTIME_DIR/wob.sock +(exec-service + 'wob + (list "sh" "-c" + (string-append + "sock=\"$XDG_RUNTIME_DIR/wob.sock\"; " + "[ -p \"$sock\" ] || mkfifo \"$sock\"; " + "exec sh -c 'tail -f \"$1\" | wob' _ \"$sock\""))) blob - /dev/null blob + 740c3450d99aac3e5b09f96119cfd9ff9f9283e0 (mode 644) --- /dev/null +++ hosts/void/overlays/config/shepherd/init.scm @@ -0,0 +1,33 @@ +;; -*- mode: scheme; -*- +;;; ~/.config/shepherd/init.scm + +(use-modules (shepherd service) + (shepherd support) + ((ice-9 ftw) #:select (scandir))) + +(default-environment-variables (environ)) + +;; Per-service log files live here as .log +(mkdir-p %user-log-dir) + +(define* (exec-service name command #:key (respawn? #t)) + (let ((svc (service (list name) + #:documentation (string-append "Run " (symbol->string name) ".") + #:start (make-forkexec-constructor + command + #:log-file (string-append %user-log-dir "/" + (symbol->string name) ".log")) + #:stop (make-kill-destructor) + #:respawn? respawn?))) + (register-services (list svc)) + (start-service svc))) + +;; Send Shepherd to the background +(perform-service-action root-service 'daemonize) + +;; Load every ~/.config/shepherd/init.d/*.scm file +(let ((init.d (string-append %user-config-dir "/init.d"))) + (for-each (lambda (file) + (load (string-append init.d "/" file))) + (scandir init.d + (lambda (file) (string-suffix? ".scm" file))))) blob - 861b5e9fe5887e520fef1c1ba48ae802cab5470a blob + e4c6eea62d3d66878d16ca5f507223971ef5f0e9 --- hosts/void/overlays/config/volare/config +++ hosts/void/overlays/config/volare/config @@ -158,19 +158,8 @@ mode "resize" { bindsym --locked XF86MonBrightnessUp exec sh -c 'brightnessctl set +5% | sed -En "s/.*\(([0-9]+)%\).*/\1/p" > $wobsock' bindsym --locked XF86MonBrightnessDown exec sh -c 'brightnessctl set 5%- | sed -En "s/.*\(([0-9]+)%\).*/\1/p" > $wobsock' -exec swaybg -m fill -c "#0d1612" -i "$HOME/misc/random/wallpapers/curtains.jpg" -exec sh -c 'mkfifo $wobsock 2>/dev/null; tail -f $wobsock | wob' -exec wl-paste --watch cliphist store +exec shepherd -exec battery-notify -exec fnott -exec pipewire -exec kanshi -exec psi-notify -exec memcached -exec nix-daemon -exec hister listen - font Fragment Mono 10 bar { blob - /dev/null blob + dd170015435b965bf885c4000ff40c694807ed5c (mode 644) --- /dev/null +++ modules/mixins/dotfiles/bin/ffmpeg-cut @@ -0,0 +1,84 @@ +#!/bin/bash -e + +# Takes a file with lines like: +# +# VID_20240630_143147_036.mp4 +# VID_20240630_144842_041.mp4 01:45 +# VID_20240630_145538_042.mp4 01:00 01:50 +# +# ...and extracts them into another folder. +# +# The keyframe seeking is imprecise, but with the Ace Pro it's close enough +# that it doesn't matter. + +while getopts ":i:o:" opt; do + case $opt in + i) input_dir="$OPTARG" + ;; + o) output_dir="$OPTARG" + ;; + \?) echo "Invalid option -$OPTARG" >&2 + exit 1 + ;; + esac +done + +shift $((OPTIND - 1)) +file_list="$1" + +if [[ -z "$input_dir" || -z "$output_dir" || -z "$file_list" ]]; then + echo "Usage: $0 -i input_dir -o output_dir file_list" + exit 1 +fi + +time_to_seconds() { + IFS=: read -r m s <<< "$1" + echo $((10#${m:-0} * 60 + 10#${s:-0})) +} + +while IFS=' ' read -r file start end; do + if [[ -z "$file" ]]; then + echo "File name is empty" >&2 + exit 1 + fi + + + input_file="$input_dir/$file" + + if ! [[ -f "$input_file" ]]; then + echo "$input_file does not exist" >&2 + exit 1 + fi + + base_name=$(basename "$file" .mp4) + if [[ -n "$start" && -n "$end" ]]; then + start_formatted=$(echo "$start" | tr -d ':') + end_formatted=$(echo "$end" | tr -d ':') + output_file="$output_dir/${base_name}_${start_formatted}_${end_formatted}.mp4" + elif [[ -n "$start" ]]; then + start_formatted=$(echo "$start" | tr -d ':') + output_file="$output_dir/${base_name}_${start_formatted}.mp4" + else + output_file="$output_dir/$file" + fi + + cmd=("ffmpeg" "-nostdin") + + if [[ -n "$start" ]]; then + cmd+=("-ss" "$start") + fi + + cmd+=("-i" "$input_file" "-muxpreload" "0" "-muxdelay" "0") + + if [[ -n "$end" ]]; then + start_seconds=$(time_to_seconds "$start") + end_seconds=$(time_to_seconds "$end") + relative_end_seconds=$((end_seconds - start_seconds)) + cmd+=("-to" "$relative_end_seconds") + fi + + cmd+=("-c" "copy" "$output_file") + + echo "${cmd[@]}" + "${cmd[@]}" +done < "$file_list" blob - /dev/null blob + 2fccc51f0d56aa55ae2fb7c7afbaffbed6c5cec1 (mode 644) --- /dev/null +++ modules/mixins/dotfiles/bin/ffmpeg-merge @@ -0,0 +1,8 @@ +#!/bin/bash -ex + +out=${1?} +shift + +# Need to put working directory in or ffmpeg will think it's relative to the +# named pipe in /proc...? +ffmpeg -f concat -safe 0 -i <(printf "file '$PWD/%s'\n" "$@") -c copy "$out" blob - 03e286932f1adbc0b9c082eb822d4d739ced7652 blob + 000de57cf5ecb30b22f75e21bdf4f2257189cf58 --- modules/mixins/dotfiles/bin/isolate +++ modules/mixins/dotfiles/bin/isolate @@ -39,7 +39,6 @@ for p in \ "$HOME/.config" \ "$HOME/.gitconfig" \ "$HOME/.local/bin" \ - "$HOME/.local/share/tools" \ "$HOME/.cache/zig" \ "$HOME/.rustup" \ "$HOME/.nix-profile"; do blob - /dev/null blob + c97eeae4858b91d27cc85a31042595eb9ac9a183 (mode 644) --- /dev/null +++ modules/mixins/dotfiles/bin/plane @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +# Base mp3 is from donation export from https://mynoise.net/NoiseMachines/rainNoiseGenerator.php?c=2&l=2420212127302925252300&m=&d=0 +# This is then cut +10 from beginning/-10 from end to get rid of fades, so it can be looped: +# +# ffmpeg -i myNoise_RAIN_24202121273029252523_0_5.mp3 -vn -acodec copy -ss 00:10 -to 04:10 rain.mp3 +# +# We play with --no-config to avoid normalisation settings that are mostly for video +# You'll also want to go into Audacity or similar and cut off the silence + +exec mpv --quiet --no-config --loop-file --no-audio-display --no-resume-playback ~/plane.mp3 blob - /dev/null blob + 16e6e9e014cee32c35086abe5445f46d054d597b (mode 644) --- /dev/null +++ modules/mixins/dotfiles/bin/sprunge @@ -0,0 +1,4 @@ +#!/bin/bash -e + +curl --data-binary @- https://paste.rs/ +printf "\n" blob - /dev/null blob + 35152ea411a04c5298245af0ed2fccbb0b12e04e (mode 644) --- /dev/null +++ modules/mixins/dotfiles/bin/thunder @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +# Base mp3 is from donation export from https://mynoise.net/NoiseMachines/rainNoiseGenerator.php?c=2&l=2420212127302925252300&m=&d=0 +# This is then cut +10 from beginning/-10 from end to get rid of fades, so it can be looped: +# +# ffmpeg -i myNoise_RAIN_24202121273029252523_0_5.mp3 -vn -acodec copy -ss 00:10 -to 04:10 rain.mp3 +# +# We play with --no-config to avoid normalisation settings that are mostly for video +# You'll also want to go into Audacity or similar and cut off the silence + +exec mpv --quiet --no-config --loop-file --no-audio-display --no-resume-playback ~/misc/thunder.mp3