diff --git a/common/git/config b/common/git/config index 3f4282b..4255836 100644 --- a/common/git/config +++ b/common/git/config @@ -22,3 +22,8 @@ [alias] dft = -c diff.external=difft diff dlog = -c diff.external=difft log -p --ext-diff +[filter "lfs"] + required = true + clean = git-lfs clean -- %f + smudge = git-lfs smudge -- %f + process = git-lfs filter-process diff --git a/common/ncmpcpp/bindings b/common/ncmpcpp/bindings new file mode 100644 index 0000000..a030685 --- /dev/null +++ b/common/ncmpcpp/bindings @@ -0,0 +1,65 @@ +# Vim-style keys. Only overrides are listed; ncmpcpp fills in the rest of its +# defaults (zcat /usr/share/doc/ncmpcpp/bindings.gz). Several actions under one +# key: the first one that can run in the current screen wins. +# ncmpcpp has no multi-key sequences, so gg/dd/yy are g/d/v here. + +def_key "j" + scroll_down +def_key "k" + scroll_up + +def_key "h" + previous_column +def_key "h" + master_screen +def_key "h" + jump_to_parent_directory + +def_key "l" + next_column +def_key "l" + slave_screen +def_key "l" + enter_directory + +def_key "g" + move_home +def_key "G" + move_end + +def_key "ctrl-u" + page_up +def_key "ctrl-d" + page_down + +# / and ? keep their default find; n/N step through matches. +def_key "n" + next_found_item +def_key "N" + previous_found_item + +# n was move-down; moving items goes to J/K. +def_key "J" + move_selected_items_down +def_key "K" + move_selected_items_up + +def_key "d" + delete_playlist_items +def_key "d" + delete_stored_playlist + +def_key "v" + select_item +# With nothing selected this selects everything. +def_key "V" + reverse_selection +# Was update_database, which mopidy does not implement. +def_key "u" + remove_selection + +# Displaced from l, g and t. +def_key "L" + show_lyrics +def_key "t" + jump_to_position_in_song diff --git a/common/ncmpcpp/config b/common/ncmpcpp/config new file mode 100644 index 0000000..5755532 --- /dev/null +++ b/common/ncmpcpp/config @@ -0,0 +1,63 @@ +# ncmpcpp config. Defaults and the full option list: zcat /usr/share/doc/ncmpcpp/config.gz +# +# On sctfw004 the server is mopidy (Mopidy-MPD in front of Mopidy-Subidy), which +# speaks MPD protocol 0.19. Notes that follow from that are marked "mopidy:". + +mpd_host = localhost +mpd_port = 6600 + +lyrics_directory = ~/.local/share/lyrics + +## Media library +# mopidy: `list albumartist` comes back empty from subidy, so album_artist +# gives an empty artist column. Stay on artist. +media_library_primary_tag = artist +# mopidy: splitting by date sends `list ... group date`, which mopidy rejects. +media_library_albums_split_by_date = no +ignore_leading_the = yes + +## Visualizer +# mopidy has no fifo output; its GStreamer pipeline tees PCM to UDP instead +# (see [audio] output in mopidy.conf). +visualizer_data_source = localhost:5555 +visualizer_output_name = Visualizer feed +visualizer_in_stereo = yes +visualizer_type = spectrum +visualizer_look = ●▮ +visualizer_color = 47, 83, 119, 155, 191, 227, 221, 215, 209, 203, 197, 161 +visualizer_spectrum_smooth_look = yes + +## Startup layout +# A startup_slave_screen locks the playlist on the left and every other screen, +# media library included, opens in the leftover width. The visualizer is on 8. +startup_screen = playlist + +## Song change +execute_on_song_change = ~/.config/ncmpcpp/song-notify & + +## Appearance +user_interface = alternative +playlist_display_mode = columns +browser_display_mode = columns +search_engine_display_mode = columns +playlist_editor_display_mode = columns +song_columns_list_format = (25)[blue]{a} (6f)[green]{NE} (45)[white]{t|f:Title} (25)[cyan]{b} (7f)[magenta]{l} +alternative_header_first_line_format = $b$5$aqqu$/a$9 {%t}|{%f} $5$atqq$/a$9$/b +alternative_header_second_line_format = {{$4$b%a$/b$9}{ - $7%b$9}{ ($4%y$9)}}|{%D} +now_playing_prefix = $b +now_playing_suffix = $/b +current_item_prefix = $(blue)$r +current_item_suffix = $/r$(end) +current_item_inactive_column_prefix = $(white)$r +current_item_inactive_column_suffix = $/r$(end) +progressbar_look = ━━─ +progressbar_color = black:b +progressbar_elapsed_color = blue:b +main_window_color = default +statusbar_visibility = yes +titles_visibility = yes +centered_cursor = yes +autocenter_mode = yes +cyclic_scrolling = yes +display_bitrate = yes +enable_window_title = yes diff --git a/common/ncmpcpp/song-notify b/common/ncmpcpp/song-notify new file mode 100755 index 0000000..127e2d7 --- /dev/null +++ b/common/ncmpcpp/song-notify @@ -0,0 +1,57 @@ +#!/usr/bin/env bash +# Desktop notification with cover art on song change. Run by ncmpcpp's +# execute_on_song_change, so it only fires while ncmpcpp is open. +# +# mopidy: Mopidy-MPD has no albumart command, so the cover comes from the +# Subsonic server behind Mopidy-Subidy. url and username are read from +# mopidy.conf, the password from the untracked secrets.conf. +# Usage: song-notify [subidy:song:] (defaults to the current song) + +set -u + +conf=~/.config/mopidy/mopidy.conf +secrets=~/.config/mopidy/secrets.conf +cache=${XDG_CACHE_HOME:-$HOME/.cache}/ncmpcpp/covers + +fmt='%file%\t%artist%\t%title%\t%album%' +if [ $# -gt 0 ]; then + line=$(mpc -f "$fmt" playlist 2>/dev/null | + awk -F'\t' -v u="$1" '$1 == u { print; exit }') +else + line=$(mpc -f "$fmt" current 2>/dev/null) +fi +IFS=$'\t' read -r uri artist title album <<<"$line" +[ -n "$uri" ] || exit 0 + +# Value of key in [subidy] of an ini file. +ini() { + awk -F' *= *' -v k="$2" ' + /^\[/ { s = ($0 == "[subidy]") } + s && $1 == k { print $2; exit }' "$1" +} + +cover= +id=${uri#subidy:song:} +if [ "$id" != "$uri" ] && [ -r "$secrets" ]; then + url=$(ini "$conf" url) + user=$(ini "$conf" username) + pass=$(ini "$secrets" password) + salt=$(head -c 8 /dev/urandom | od -An -tx1 | tr -d ' \n') + token=$(printf '%s%s' "$pass" "$salt" | md5sum | cut -d' ' -f1) + auth="u=$user&t=$token&s=$salt&v=1.16.1&c=ncmpcpp" + + art=$(curl -fsS --max-time 5 "$url/rest/getSong.view?$auth&f=json&id=$id" | + jq -r '."subsonic-response".song.coverArt // empty') + if [ -n "$art" ]; then + cover=$cache/${art////_} + if [ ! -s "$cover" ]; then + mkdir -p "$cache" + curl -fsS --max-time 10 -o "$cover" \ + "$url/rest/getCoverArt.view?$auth&id=$art&size=256" || cover= + fi + fi +fi + +notify-send -a ncmpcpp ${cover:+-i "$cover"} \ + -h string:x-canonical-private-synchronous:ncmpcpp \ + "${title:-$uri}" "${artist:-}${album:+ — $album}" diff --git a/common/ssh/config b/common/ssh/config index 2161252..047714b 100644 --- a/common/ssh/config +++ b/common/ssh/config @@ -25,6 +25,10 @@ Host fw1 HostName 100.100.61.12 User scout-dev +Host fw2 + HostName 100.127.83.76 + User scoutdev + Host sp240 #Hostname 10.8.11.123 Hostname localhost diff --git a/common/zsh/opencode.zsh b/common/zsh/opencode.zsh index 340c0de..1abdcac 100644 --- a/common/zsh/opencode.zsh +++ b/common/zsh/opencode.zsh @@ -131,9 +131,12 @@ _oc_launch() { print -u2 "${colour}┌─ opencode profile: ${(U)profile} ─┐\e[0m" printf '\e]0;opencode [%s]\a' "$profile" + # OpenCode detects its install method with `npm list -g` and upgrades with + # `npm install -g`; both use nvm's prefix unless pointed at this one. LITELLM_KEY="$key" \ OPENCODE_PROFILE="$profile" \ OPENCODE_CONFIG="$cfg" \ + npm_config_prefix="${OPENCODE_BIN:h}" \ command opencode "$@" } diff --git a/common/zsh/zshenv b/common/zsh/zshenv index f756c57..45ac315 100644 --- a/common/zsh/zshenv +++ b/common/zsh/zshenv @@ -13,6 +13,9 @@ export QUTEWAL_DYNAMIC_LOADING=True export NEOVIDE_FORK=1 export RUSTFLAGS="-L/usr/local/lib" +export CPM_SOURCE_CACHE=$HOME/scout/projects/CPM_cache +export CPM_USE_NAMED_CACHE_DIRECTORIES=True + # `col -bx` strips the backspace-overstrike bold that otherwise reaches bat as # literal ^H sequences. MANROFFOPT=-c is required alongside it. export MANPAGER="sh -c 'col -bx | bat -l man -p'" diff --git a/hosts/sctfw004/config/mopidy/mopidy.conf b/hosts/sctfw004/config/mopidy/mopidy.conf new file mode 100644 index 0000000..d54b145 --- /dev/null +++ b/hosts/sctfw004/config/mopidy/mopidy.conf @@ -0,0 +1,27 @@ +# Password lives in ~/.config/mopidy/secrets.conf (untracked, mode 600): +# [subidy] +# password = +# shanty-subsonic is the Subsonic API password; the web login (shanty-connor) +# is rejected on /rest. + +[subidy] +enabled = true +url = https://shanty.rcjohnstone.com +username = connor + +[mpd] +enabled = true +hostname = 127.0.0.1 +port = 6600 + +[file] +enabled = false + +# Second branch of the tee feeds ncmpcpp's visualizer +# (visualizer_data_source = localhost:5555). It expects 44.1 kHz s16le stereo. +[audio] +output = tee name=t ! queue ! autoaudiosink t. ! queue ! audioresample ! audioconvert ! audio/x-raw,rate=44100,channels=2,format=S16LE ! udpsink host=127.0.0.1 port=5555 + +# Exposes mopidy on D-Bus so playerctl (the media keys in hyprland.conf) can drive it. +[mpris] +enabled = true diff --git a/hosts/sctfw004/systemd/mopidy.service b/hosts/sctfw004/systemd/mopidy.service index f1c07cd..6a3f85e 100644 --- a/hosts/sctfw004/systemd/mopidy.service +++ b/hosts/sctfw004/systemd/mopidy.service @@ -1,9 +1,10 @@ [Unit] Description=Mopidy music server -After=network.target sound.target +After=network-online.target sound.target +Wants=network-online.target [Service] -ExecStart=/usr/bin/mopidy --config /etc/mopidy/mopidy.conf +ExecStart=/usr/bin/mopidy --config %h/.config/mopidy/mopidy.conf:%h/.config/mopidy/secrets.conf Restart=on-failure [Install] diff --git a/meta/hosts/sctfw004.conf.yaml b/meta/hosts/sctfw004.conf.yaml index 8e8ed2a..77ca181 100644 --- a/meta/hosts/sctfw004.conf.yaml +++ b/meta/hosts/sctfw004.conf.yaml @@ -20,6 +20,7 @@ ~/.config/fastfetch: common/fastfetch ~/.config/glow: common/glow ~/.config/mpd: common/mpd + ~/.config/mopidy/mopidy.conf: hosts/sctfw004/config/mopidy/mopidy.conf ~/.config/uv: common/uv ~/.config/mpv: common/mpv ~/.config/swayimg: common/swayimg diff --git a/packages/sctfw004.apt b/packages/sctfw004.apt index 0af6f38..4fd0821 100644 --- a/packages/sctfw004.apt +++ b/packages/sctfw004.apt @@ -18,6 +18,7 @@ cppcheck curl dash ddcci-dkms +delta diffutils docker-buildx-plugin docker-ce @@ -47,8 +48,11 @@ gettext-base gh gimp git +git-delta +git-lfs glslang-dev glslang-tools +glslc golang google-chrome-stable gpg @@ -165,6 +169,7 @@ libvulkan-volk-dev libwacom-dev libwayland-client++1 libwayland-dev +libx264-dev libxcb-composite0-dev libxcb-cursor-dev libxcb-cursor0 @@ -200,6 +205,7 @@ libxrandr2 libxrender1 libxtst6 libxxhash-dev +libyaml-dev libzmq3-dev linux-generic-hwe-24.04 linux-modules-extra-6.17.0-20-generic @@ -211,11 +217,13 @@ m17n-db make mopidy mopidy-mpd +mopidy-mpris mousepad mpc mpv mpv-mpris nala +nasm ncal ncmpcpp ncurses-base @@ -265,6 +273,7 @@ ssh swig tailscale thunar +tk-dev tldr ubuntu-desktop-minimal ubuntu-minimal @@ -288,6 +297,7 @@ xdg-desktop-portal-wlr xrdp xterm yad +ydotool zathura zoom zsh diff --git a/packages/sctfw004.flatpak b/packages/sctfw004.flatpak index 0d19255..4343197 100644 --- a/packages/sctfw004.flatpak +++ b/packages/sctfw004.flatpak @@ -1 +1,2 @@ com.moonlight_stream.Moonlight +com.orcaslicer.OrcaSlicer