From: Ian Kelling Date: Fri, 5 Jul 2024 19:15:41 +0000 (-0400) Subject: bunch of improvements X-Git-Url: https://iankelling.org/git/?a=commitdiff_plain;h=eea213085a499afdc1011e747bf05688cf896100;p=distro-setup bunch of improvements --- diff --git a/.gitignore b/.gitignore index 4ebcc92..96e18f7 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,5 @@ /subdir_files/.config/i3/config /subdir_files/.config/sway/config /.mblaze/cur +# bash script for testing things +/ms diff --git a/brc b/brc index 293953d..d73342d 100644 --- a/brc +++ b/brc @@ -367,6 +367,11 @@ mysrc /a/bin/fai/fai/config/distro-install-common/bash-misc-funcs # source /usr/share/doc/fzf/examples/key-bindings.bash # fi +# this looks more interesting for more easily selecting multiple files: +# https://github.com/peco/peco?tab=readme-ov-file#keymaps +# This also looks like it could be customized more than fzf: +# https://github.com/lotabout/skim + # * functions @@ -1315,18 +1320,28 @@ ediff() { # shellcheck disable=SC2120 # we expect to pass arguments in use outside this file etail() { ngset - tail -F /var/log/exim4/mainlog /var/log/exim4/*main /var/log/exim4/paniclog /var/log/exim4/*panic -n 200 "$@" + ta /var/log/exim4/mainlog /var/log/exim4/*main /var/log/exim4/paniclog /var/log/exim4/*panic -n 200 "$@" ngreset } etailm() { - tail -F /var/log/exim4/mainlog -n 200 "$@" + ta /var/log/exim4/mainlog -n 200 "$@" } etail2() { - tail -F /var/log/exim4/nondmain -n 200 "$@" + ta /var/log/exim4/nondmain -n 200 "$@" } -# shortcut for tail -F + +# shortcut for tail -F + highlighting if we have it. +tailf() { + if type -t batcat >/dev/null; then + # note: another useful useful style is "header" + tail -F "$@" | batcat --color always --style plain --theme Coldark-Cold -P + else + tail -F "$@" + fi + } + ta() { - tail -F "$@" + bn ta "$@" } ccomp tail etail etail2 ta @@ -1912,7 +1927,7 @@ pst() { # journalctl with times in the format the --since= and --until= options accept jrt() { journalctl -e -n100000 -o short-full "$@"; } jr() { journalctl -e -n100000 "$@" ; } -jrf() { journalctl -n1000 -f "$@" ; } +jrf() { SYSTEMD_COLORS=true bn journalctl -n1000 -f "$@" ; } jru() { # the invocation id is "assigned each time the unit changes from an inactive # state into an activating or active state" man systemd.exec @@ -2202,6 +2217,143 @@ whatismyip() { pubip; } q() { # start / launch a program in the backround and redir output to null "$@" &> /dev/null & } +# quietly run command and then redisplay prompt on the same line. +qr() { + local ret=0 + "$@" &>/dev/null || ret=$? + # https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797 + # [2K = erase whole line + # [1A = go up one line. aka tput cuu 1 + echo -ne "\e[1A\e[2K" + return $ret +} +# Execute then redo the prompt back at the original spot. +# we = random easy to type command. +# +# Also echoes a block after the end of the output. If we didn't do that, +# it would intermingle with previous output of this command. +# +# I wondered about doing this automatically for every command, +# and I found https://unix.stackexchange.com/questions/562018/run-every-bash-command-through-a-function-or-wrapper +# which gives me the idea that I could rebind enter to first +# prefix the current command with a wrapper. +# We could also use the debug trap to define a function of the about to be executed command, +# but I don't know how to modify an existing function. +# +# todo: consider better handling of when linec > LINES +# +# todo: create a command which deletes the lines beneath the cursor (one probably already exists). +we() { + local ret=0 out linec i tmp cur_line empty_lines clear_lines tmpf + + # for wemode + while [[ $1 == we ]]; do + shift + done + # Give up if our command is part of a pipeline. + if ! test -t 1 || ! test -t 2; then + "$@" || ret=$? + return $ret + fi + + tmpf=$(mktemp) + # note: Another way to do this without redirection would be with tput + # sc and tput rc, but if our command output past the bottom line of + # the terminal, we'd be restoring into the middle of its output. + "$@" &>$tmpf || ret=$? + + # we can't do this because inside the {, some terminal escape sequences don't work right. + #"$@" |& { read -r -d '' out + out=$(cat $tmpf) + rm -- $tmpf + linec=0 + if [[ $out ]]; then + # wc gives us 1 when out is an empty string because $() is not newline terminated. + linec=$(wc -l <<<"$out") + fi + # always clear the very next line after our prompt. + echo -ne "\e[2K" + clear_lines=$(( linec - 1 )) + if (( clear_lines > 0 )); then + # https://stackoverflow.com/questions/2575037/how-to-get-the-cursor-position-in-bash + # note, echoing $tmp at this point wont show anything because it is + # still an escape sequence. + IFS='[;' read -p $'\e[6n' -d R -rs tmp + tmp="${tmp%%;*}" + cur_line="${tmp##*[^0-9]}" + empty_lines=$(( LINES - cur_line )) + if (( empty_lines < linec )); then + clear_lines="$empty_lines" + fi + for (( i=0; i < linec - 1; i++ )); do + # 1B = go down one line + echo -ne "\e[1B\e[2K" + done + echo -ne "\e[${clear_lines}A\e[2K" + fi + + if (( linec > 0 )); then + printf "%s\n█\n" "$out" + else + printf "█\n" + fi + # see qr for escape code explanation + echo -ne "\e[$(( linec + 2 ))A\e[2K" + return $ret +} + +# mode where every command is automatically wrapped in we() +wemode() { + # c-space to set mark, eOH is begining of line (dunno how to press that + # on a keyboard). c-q is jump back to mark. c-j = alternate enter + # + # Another interesting variant of this which would handle pipelines + # would be to take "original | cmd" and make it be: "t() { original | + # cmd; }; we t" + # + # This has an annoying flaw that if we run a command from history that + # already starts with we, it adds another we. Might be able to fix it + # with some readline functionality, or the stackoverflow page has a + # bit about editing the last history entry, which I want to avoid + # saving the history file. It isn't a big deal, I'm just going to + # leave it. One idea is: history is editable, we could press up, + # remove the we, then press down. + bind '"\C-m": "\e \eOHwe \C-q\C-j"' +} +weoff() { + bind '"\C-m": accept-line' +} + +# Run the command in the background and make its output go above our +# prompt so it doesn't interfere with it. Especially useful for tailing +# logs. +# +# The name bn is not special. +# +# Note: colorization will need to be turned on since it captures +# output to a pipe, eg: SYSTEMD_COLORS=true bn journalctl -f +bn() { + local line lwlc i + { + "$@" |& while read -r line; do + # lwlc = line wrapped line count. + lwlc=$(( ${#line} / COLUMNS + 1 )) + # from man terminfo + # tput sc = \e7 = save cursor + # tput rc = \e8 = restore cursor + # tput hpa 0 = \e[1G = move cursor to column 0 + # tput il X = \e[XL = insert X lines + # tput ind = \eD = (according to + # https://superuser.com/questions/1106674/how-to-add-blank-lines-above-the-bottom-in-terminal + # But I can't verify because cannot be captured into a var from tput.) + #\e[XA = up X lines + for (( i=0; i < lwlc; i++ )); do + echo -ne "\eD" + done + echo -ne "\e7\e[${lwlc}A\e[1G\e[${lwlc}L$line\e8" + done + } & +} # shellcheck disable=SC2120 r() { @@ -2911,15 +3063,6 @@ psoff() { PROMPT_COMMAND='trap DEBUG; unset PROMPT_COMMAND; PS1=" \w \$ "' } -pskde() { - # shellcheck disable=SC2178 # intentional - PROMPT_COMMAND='trap DEBUG; unset PROMPT_COMMAND' - PS1='\[\e]133;L\a\]\[\e]133;D;$?\]\[\e]133;A\a\]\w \$ \[\e]133;B\a\]' ; - PS2='\[\e]133;A\a\]'$PS2'\[\e]133;B\a\]' ; - PS0='\[\e]133;C\a\]' - -} - pson() { PROMPT_COMMAND=(prompt-command) if [[ $TERM == *(screen*|xterm*|rxvt*) ]]; then @@ -3264,7 +3407,6 @@ if [[ $- == *i* ]]; then # old enough to no longer condition on $BASH_VERSION anymore shopt -s autocd shopt -s dirspell - PS1='\w' if [[ $- == *i* ]] && [[ ! $LC_INSIDE_EMACS ]]; then PROMPT_DIRTRIM=2 bind -m vi-command B:shell-backward-word @@ -3273,7 +3415,6 @@ if [[ $- == *i* ]]; then if [[ $SSH_CLIENT || $SUDO_USER ]]; then unset PROMPT_DIRTRIM - PS1="\h:$PS1" fi # emacs terminal has problems if this runs slowly, @@ -3281,6 +3422,10 @@ if [[ $- == *i* ]]; then prompt-command() { local return=$? # this MUST COME FIRST + PS1='\w' + if [[ $SSH_CLIENT || $SUDO_USER ]]; then + PS1="\h:$PS1" + fi # all usable colors: # black @@ -3291,7 +3436,11 @@ if [[ $- == *i* ]]; then # red bold pwd different owner & group & writable (pri 2) # yellow - local ps_char ps_color + local ps_char ps_color col tmp + + IFS='[;' read -p $'\e[6n' -d R -rs tmp + col="${tmp##*[^0-9]}" + unset IFS if [[ $HISTFILE ]]; then @@ -3329,7 +3478,7 @@ if [[ $- == *i* ]]; then fi jobs_char= if [[ $(jobs -p) ]]; then - jobs_char="$(jobs -p)"'j\j ' + jobs_char='j\j ' fi @@ -3362,6 +3511,12 @@ if [[ $- == *i* ]]; then fi PS1="${PS1%"${PS1#*[wW]}"} $jobs_char$psudo\[$ps_color\]$ps_char\[$term_nocolor\] " + # If the last command was not newline terminated, add a space (so we + # can more easily copy the output if needed), and an indicator to + # help us not be confused. + if [[ $col != 1 ]]; then + PS1=" \[$term_yellow\]█\[$term_nocolor\]$PS1" + fi # copy of what is automatically added by guix. @@ -3372,18 +3527,34 @@ if [[ $- == *i* ]]; then fi fi + # version 211203 does not have this feature, 230805 does + if [[ $KONSOLE_VERSION && $KONSOLE_VERSION == [3456789]* || $KONSOLE_VERSION == 2[3456789]* ]]; then + # This is from konsole, copied after pressing ctrl-alt-] . + # I figured out what it does from reading git clone https://gitlab.freedesktop.org/Per_Bothner/specifications + # + #proposals/semantic-prompts.md + # + # I tried figuring out what they really do from the konsole source code, + # but I gave up. + # + # \[\e]133;L\a\] This makes it so the last command is always + # newline terminated. That is kind nice, but I also want to know + # when they aren't, and this screws up my we() function, so + # removed. The doc notes that Fish and ZSH both show a specific + # char to indicate that happened, that sounds nice so I figured + # out how to do that on my own. + # + # \[\e]133;D;$?\] + # This is something to try to show the last exit code. I already do that + # and colorize it so removed. + # - # set titlebar. instead, using more advanced - # titelbar below - #echo -ne "$_title_escape $HOSTNAME ${PWD/#$HOME/~} \007" - - # version 211203 does not have this feature. - if [[ $KONSOLE_VERSION && $KONSOLE_VERSION == [3456789]* || $KONSOLE_VERSION == 2[2456789]* ]]; then - # from konsole, output via ctrl-alt-] if [[ ! $PS1 =~ 133 ]] ; then - PS1='\[\e]133;L\a\]\[\e]133;D;$?\]\[\e]133;A\a\]'$PS1'\[\e]133;B\a\]' ; - PS2='\[\e]133;A\a\]'$PS2'\[\e]133;B\a\]' ; - PS0='\[\e]133;C\a\]' ; fi + PS1='\[\e]133;A\a\]'"$PS1"'\[\e]133;B\a\]' + PS2='\[\e]133;A\a\]'"$PS2"'\[\e]133;B\a\]' + # shellcheck disable=SC2034 # false positive + PS0='\[\e]133;C\a\]' + fi fi } @@ -3410,6 +3581,8 @@ if [[ $- == *i* ]]; then if [[ $1 == prompt-command ]]; then return 0 fi + # note: this could be useful to do something interesting. + #_iank_last_cmd="$*" echo -ne "$_title_escape ${PWD/#$HOME/~} " printf "%s" "$*" echo -ne "\007" diff --git a/brc2 b/brc2 index 4c5e423..3236dbc 100644 --- a/brc2 +++ b/brc2 @@ -2414,9 +2414,10 @@ wlog() { /a/opt/timetrap/bin/t d -ftotal -s $day -e $day all -m '^w|lunch$' done } -to() { t out -a "$@"; } -ti() { t in -a "$@"; } -tl() { +to() { we t out -a "$@"; } +ti() { we t in -a "$@"; } + +_tl() { local in_secs to "$*" t s lunch @@ -2425,7 +2426,9 @@ tl() { m t out -a "$(date +%F.%T -d @$(( in_secs + 60*45 )) )" t s w } - +tl() { + we _tl "$@" +} # help me focus. opens 2 windows. focus() { @@ -4233,6 +4236,8 @@ vpn() { [[ $1 ]] || { echo need arg; return 1; } journalctl --since=now --unit=$vpn_service@$1 -f -n0 & + # might be able to go lower than 1 + sleep 1 sudo systemctl start $vpn_service@$1 # sometimes the ask-password agent does not work and needs a delay. sleep .5 @@ -5007,6 +5012,10 @@ ffsencode() { ffmpeg -i "$in" -c:v libsvtav1 -crf 60 -preset 6 -g 60 -svtav1-params tune=0:enable-overlays=1:scd=1:scm=1 -pix_fmt yuv420p10le -c:a copy "$out" } +localai() { + schroot -c bookworm + } + export BASEFILE_DIR=/a/bin/fai-basefiles #export ANDROID_HOME=/a/opt/android-home diff --git a/disabled/docker b/disabled/docker old mode 100644 new mode 100755 index 929f4d6..88df3f9 --- a/disabled/docker +++ b/disabled/docker @@ -1,35 +1,34 @@ +#!/bin/bash + +set -e -### begin docker install #### -if isdeb; then # https://docs.docker.com/engine/install/ubuntu/ -sudo mkdir -p /etc/apt/keyrings +# Add Docker's official GPG key: +sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc +sudo chmod a+r /etc/apt/keyrings/docker.asc + +# Add the repository to Apt sources: +echo \ + "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \ + $(debian-codename-compat) stable" | \ + sudo tee /etc/apt/sources.list.d/docker.list > /dev/null +sudo apt-get update - curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg -# lsb_release -cs -> debian-codename-compat -echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(debian-codename-compat) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null p update - pi software-properties-common apt-transport-https - curl -fsSL https://download.docker.com/linux/$(distro-name-compat)/gpg | sudo apt-key add - - url=https://download.docker.com/linux/$(distro-name-compat) - l="deb [arch=amd64] $url $codename_compat stable" - - if ! grep -xFq "$l" /etc/apt/sources.list{,.d/*.list}; then - sudo add-apt-repository "$l" - p update - fi - # docker eats up a fair amount of cpu when doing nothing, so don't enable it unless - # we really need it. - pi-nostart docker-ce - # and docker is even more crap, it ignores that it shouldnt start - ser stop docker - ser disable docker - case $HOSTNAME in - li|lj) sgo docker ;; - esac -fi +# docker eats up a fair amount of cpu when doing nothing, so don't enable it unless +# we really need it. +pi-nostart docker-ce +# case $HOSTNAME in +# li|lj) sgo docker ;; +# *) +# # and docker is even more crap, it ignores that it shouldnt start +# ser stop docker +# ser disable docker +# ;; +# esac ### end docker install #### diff --git a/distro-end b/distro-end index d8a6cc5..742e4b6 100755 --- a/distro-end +++ b/distro-end @@ -207,11 +207,9 @@ EOF fi if [[ ! -e /usr/share/debootstrap/scripts/noble ]]; then - t=$(mktemp -d) - cd $t - m aptitude download debootstrap/noble - m ex ./* - sudo cp ./usr/share/debootstrap/scripts/* /usr/share/debootstrap/scripts + # noble debootstrap as of 2024-07-05. not going to bother + # adding a whole repo for one package which doesn't seem to generally change within a single distro version. + sudo dpkg -i /a/opt/debootstrap_1.0.134ubuntu1_all.deb fi ;;& diff --git a/ffp b/ffp index f956b06..d0af485 100755 --- a/ffp +++ b/ffp @@ -24,12 +24,18 @@ usage() { cat <&2; exit 1; } +debug=false volume=0 temp=$(getopt -l help hdw "$@") || usage 1 eval set -- "$temp" while true; do case $1 in - -d) volume=100 ;; + -d) + volume=100 + debug=true + ;; -h|--help) usage ;; --) shift; break ;; *) echo "$0: unexpected args: $*" >&2 ; usage 1 ;; @@ -73,7 +83,6 @@ esac ##### end command line parsing ######## - host=https://live.iankelling.org:443 live_host=$(dig +timeout=1 +short @iankelling.org live.iankelling.org) vps_host=$(dig +timeout=1 +short iankelling.org) @@ -82,16 +91,46 @@ if [[ $live_host != "$vps_host" ]] && ip n show 10.2.0.1 | grep . &>/dev/null & host=http://127.0.0.1:8000 fi +url=$host/fsf$mount_suffix.webm + +files=(~/2*.webm) +file=${files[@]} +if [[ -e $file ]]; then + url=$file +fi + opts=( -v error + #-v debug -hide_banner -nostats -volume $volume - -f webm -fast -fflags nobuffer -flags low_delay - -i $host/fsf$mount_suffix.webm + # makes it a floating window in i3 and avoids scaling + -noborder + -f webm + -i $url -autoexit - ) +) +if $debug; then + echo running: ffplay "${opts[@]}" +fi ffplay "${opts[@]}" + +# # working mpv, but still a second or so slower than ffplay. +# mpv_opts=( +# # these seem to have no effect on latency +# #--no-cache +# #--untimed +# --no-demuxer-thread +# --vd-lavc-threads=1 +# --volume=$volume +# --video-unscaled +# $host/fsf$mount_suffix.webm +# ) + +# todo: make more mountpoints for other ppl to stream +# todo: make raw recordings accessible to public, for public streams. +# diff --git a/ffs b/ffs index a8c270b..e23f8ba 100755 --- a/ffs +++ b/ffs @@ -20,11 +20,14 @@ # See the License for the specific language governing permissions and # limitations under the License. -# ffs = ffmpeg stream - -# potential improvement: it might be nice that we could have a tall terminal but only use +# potential feature: it might be nice that we could have a tall terminal but only use # the top half for a 1080p stream, this is how: # https://superuser.com/questions/1106674/how-to-add-blank-lines-above-the-bottom-in-terminal +# Another way to do this is with tput csr 0 $(( LINES - something )) +# as in https://stackoverflow.com/questions/51175911/line-created-with-tput-gets-removed-on-scroll +# however, that makes it so if you run man, it won't start at the top, then you +# move around to see the top and exit, your cursor is in a nonscrolling region +# which we do not want. if ! test "$BASH_VERSION"; then echo "error: shell is not bash" >&2; exit 1; fi @@ -34,18 +37,26 @@ trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" exit status: $?, PIPESTATUS: ${P usage() { cat <&2; exit 1; } ffp_args=() + debug=false delay=true +local=false loglevel=fatal -watch=true +mvv=false +try_accel=true volume=0 +vp9=true +watch=true + fullscreen=false tall=true -mvv=false -temp=$(getopt -l help hdlms:uw "$@") || usage 1 + +temp=$(getopt -l help hd:mrs:uw8 "$@") || usage 1 eval set -- "$temp" while true; do case $1 in -d) debug=true - loglevel=debug loglevel=info ffp_args+=(-d) - ;; - -l) - volume=1 + case $2 in + *a*) + try_accel=false + ;;& + *l*) + volume=1 + ;;& + *v*) + loglevel=debug + ;;& + esac + shift ;; -m) mvv=true ;; + -r) + local=true + ;; -s) case $2 in - tall) + tall|t) fullscreen=false tall=true ;; - quarter) + quarter|q) fullscreen=false tall=false ;; - full) + full|f) fullscreen=true tall=false ;; + *) + echo "unknown split type: $2" >&2 + exit 1 + ;; esac shift ;; @@ -112,6 +148,9 @@ while true; do -u) delay=false ;; + -8) + vp9=false + ;; -h|--help) usage ;; --) shift; break ;; *) echo "$0: unexpected args: $*" >&2 ; usage 1 ;; @@ -147,50 +186,49 @@ fi ##### end command line parsing ######## -host=live.iankelling.org:8443 -live_host=$(dig +timeout=1 +short @iankelling.org live.iankelling.org) -vps_host=$(dig +timeout=1 +short iankelling.org) -if [[ $live_host != "$vps_host" ]] && ip n show 10.2.0.1 | grep . &>/dev/null && \ - [[ $(dig +timeout=1 +short @10.2.0.1 -x 10.2.0.2 2>&1 ||:) == kd.b8.nz. ]]; then - host=127.0.0.1:8000 - if ! pgrep '^icecast2$' >/dev/null; then - sudo systemctl start icecast2 +if ! $local; then + host=live.iankelling.org:8443 + live_host=$(dig +timeout=1 +short @iankelling.org live.iankelling.org) + vps_host=$(dig +timeout=1 +short iankelling.org) + if [[ $live_host != "$vps_host" ]] && ip n show 10.2.0.1 | grep . &>/dev/null && \ + [[ $(dig +timeout=1 +short @10.2.0.1 -x 10.2.0.2 2>&1 ||:) == kd.b8.nz. ]]; then + host=127.0.0.1:8000 + if ! pgrep '^icecast2$' >/dev/null; then + sudo systemctl start icecast2 + fi + else + find_prefix="ssh live.iankelling.org" fi -else - find_prefix="ssh live.iankelling.org" -fi -if $find_prefix find /var/icecast -type f | grep .; then - echo "warning: suggest clearing /var/icecast with icrmr or moving files. sleeping for 4 seconds" - sleep 4 -fi - - -pass=$(sed -n 's/ *\([^<]*\).*/\1/p' /p/c/icecast.xml) + if $find_prefix find /var/icecast -type f | grep .; then + echo "warning: suggest clearing /var/icecast with icrmr or moving files. sleeping for 4 seconds" + sleep 4 + fi + pass=$(sed -n 's/ *\([^<]*\).*/\1/p' /p/c/icecast.xml) +fi -tmpf=$(mktemp) -xrandr >$tmpf +xrandr=$(xrandr) # example xrandr output: 1280x800+0+0 -primary_res=$(awk '$2 == "connected" && $3 == "primary" { print $4 }' $tmpf | sed 's/+.*//') -tmp=$(awk '$2 == "connected" && $3 != "primary" { print $3 }' $tmpf | sed 's/+/ /g') +primary_res=$(awk '$2 == "connected" && $3 == "primary" { print $4 }' <<<"$xrandr" | sed 's/+.*//') +tmp=$(awk '$2 == "connected" && $3 != "primary" { print $3 }' <<<"$xrandr" | sed 's/+/ /g') read -r secondary_res x_offset _ <<<"$tmp" - if [[ $secondary_res ]]; then - secondary_x=${secondary_res%%x*} - secondary_y=${secondary_res##*x} - if $fullscreen; then - stream_res=$secondary_res - elif $tall; then - stream_res=$(( secondary_x / 2 ))x$secondary_y - else - stream_res=$(( secondary_x / 2 ))x$(( secondary_y / 2)) - fi + target_res=$secondary_res else x_offset=0 - stream_res=$primary_res + target_res=$primary_res +fi +target_x=${target_res%%x*} +target_y=${target_res##*x} +if $fullscreen; then + stream_res=$target_res +elif $tall; then + stream_res=$(( target_x / 2 ))x$target_y +else + stream_res=$(( target_x / 2 ))x$(( target_y / 2)) fi stream_x=${stream_res%x*} @@ -200,42 +238,78 @@ stream_y=${stream_res#*x} stream_res=$(( stream_x - 4 ))x$(( stream_y - 4)) -# if hardware acceleration exists, use it to save power & cpu. -if vainfo |& grep -i VAProfileVP9Profile &>/dev/null; then - # 1500 seems almost flawless - bitrate_1080=1500 - - encode_settings=( - -c:v vp9_vaapi - # these options increase compression based on random internet reference. - -bsf:v vp9_raw_reorder,vp9_superframe - ) - # https://trac.ffmpeg.org/wiki/Hardware/VAAPI - global_extra_args=( - -vaapi_device /dev/dri/renderD128 - ) - extra_filter_arg=",format=nv12|vaapi,hwupload" +# 1000 is a bit blury, 1500 is pretty clear, 2000 makes scrolling +# adjust much faster, 2500 has marginal improvement on that. +# +# note https://livekit.io/webrtc/bitrate-guide +if $mvv; then + set-bitrate 1000 else - # 1000 is a bit blury, 1500 is pretty clear, 2000 makes scrolling - # adjust much faster, 2500 has marginal improvement on that. - # - # note https://livekit.io/webrtc/bitrate-guide - if $mvv; then - bitrate_1080=1000 - else - bitrate_1080=2000 - fi - - encode_settings=( - -vcodec libvpx - -quality realtime - -error-resilient 1 - ) + set-bitrate 2000 fi -bitrate=$(( ( stream_x * stream_y ) / ( (1920*1080) / bitrate_1080 ) )) +encode_settings=( + -vcodec libvpx + -quality realtime + -error-resilient 1 + -b:v ${bitrate}k +) +if $vp9; then + # if hardware acceleration exists, use it to save power & cpu. + if $try_accel && vainfo |& grep -i VAProfileVP9Profile &>/dev/null; then + # 1500 seems almost flawless. 1200 still very good. 700k actual of 1080p tall. + set-bitrate 1200 + + encode_settings=( + -vcodec vp9_vaapi + # these options increase compression based on random internet reference. + -bsf:v vp9_raw_reorder,vp9_superframe + -b:v ${bitrate}k + ) + # https://trac.ffmpeg.org/wiki/Hardware/VAAPI + global_extra_args=( + # not documented in man page, only here: + # https://trac.ffmpeg.org/wiki/Hardware/VAAPI + -vaapi_device /dev/dri/renderD128 + ) + extra_filter_arg=",format=nv12|vaapi,hwupload" + else + # https://trac.ffmpeg.org/wiki/Encode/VP9. note, these docs are a bit + # shit because they don't fully explain modes and conflicting options. + encode_settings=( + # https://developers.google.com/media/vp9/live-encoding + -tile-columns 2 + -row-mt 1 + -frame-parallel 1 + -error-resilient 1 + -vcodec vp9 + # default can have wrong color for hardware decoders. + # this is what vp8 uses, It doesn't seem like there any + # functional difference I should care about + -pix_fmt yuv420p + ) + if $mvv; then + encode_settings+=( + -b:v ${bitrate}k + -deadline realtime + -cpu-used 8 + ) + else + encode_settings+=( + + # https://developers.google.com/media/vp9/bitrate-modes use Q mode. + -b:v 0 + -crf 45 + # use the least cpu possible in this mode since it uses a lot + # relatively, bitrate jumps a bit, quality suffers a bit. + -cpu-used 5 + ) + fi + fi +fi + if $mvv; then framerate=5 else @@ -243,6 +317,7 @@ else framerate=10 fi +# todo: decide 2 vs 3. maybe vary between vp8 & vp9 keyframe_interval=$((framerate * 2)) # Monitor of default sink. @@ -252,20 +327,19 @@ pa_sink=$(pactl get-default-sink).monitor # this is for ffmpeg warnings. doesnt seem to affect latency. # 160 was too small. at 300, it occasionally complains, # probably only when we are using delayed output -thread_queue_size_arg="-thread_queue_size 500" +thread_queue_size_arg="-thread_queue_size 800" # hardcoded switch for debugging doaudio=true if $doaudio; then audio_out_args=( - -c:a libvorbis + -acodec libopus -b:a 92k # afaik, this ensures that the amerge doesn't make 4 channel output if # our output format supported it. -ac 2 ) audio_in_args=( - -f pulse -name ffs # note: duplicated @@ -283,36 +357,49 @@ if $doaudio; then -i "$pa_sink" ) filter_args=( - # Video + audio filter. Note: this has only the things we actually need in it. - # - # volume=precision=fixed fixes this error: - # The following filters could not choose their formats: Parsed_amerge_4. - # - # Default volume precision is float. Our input is fixed. maybe ffmpeg - # thinks the input could change and so can't commit to an output. - # The error suggests using aformat, which seems like it would probably - # also fix the error. - # - # man page say zmq url default includes "localhost", but specifying a - # localhost url caused an error for me. - -filter_complex "[0]azmq,volume=precision=fixed: volume=$volume [vol0]; + # Video + audio filter. Note: this has only the things we actually need in it. + # + # volume=precision=fixed fixes this error: + # The following filters could not choose their formats: Parsed_amerge_4. + # + # Default volume precision is float. Our input is fixed. maybe ffmpeg + # thinks the input could change and so can't commit to an output. + # The error suggests using aformat, which seems like it would probably + # also fix the error. + # + # man page say zmq url default includes "localhost", but specifying a + # localhost url caused an error for me. + -filter_complex "[0]azmq,volume=precision=fixed: volume=$volume [vol0]; [1]azmq='b=tcp\://127.0.0.1\:5556',volume=precision=fixed: volume=0 [vol1]; [vol0][vol1] amerge=inputs=2; -[2]zmq='b=tcp\://127.0.0.1\:5557',drawbox=color=0x262626,drawtext=fontsize=90: fontcolor=beige: x=40: y=40: text=''${delay_arg}${extra_filter_arg}[out]" - - # An online source says to match a 5 second vid delay, we can do an - # audio delay filter: "adelay=5000|5000". However, we already get - # a stream delay of about 2 seconds, and having the audio be about - # 2 seconds ahead is fine, they do that intentionally in soccer - # matches. - - # Based on error message and poking around, it seems ffmpeg is not - # smart enough to see that [vol0] and [vol1] are inputs to the amerge - # filter, and thus we would not want them as final outputs. So, we - # have to identify the amerge output and pass it to -out. This - # identifier is called an "output pad" in man ffmpeg-filters, and a - # "link label" in man ffmpeg. - -map '[out]' +[2]zmq='b=tcp\://127.0.0.1\:5557',drawbox=color=0x262626,drawtext=fontsize=90: fontcolor=beige: x=40: y=40: text=''${delay_arg}${extra_filter_arg}[vout]" + + # Based on error message and poking around, it seems ffmpeg is not + # smart enough to see that [vol0] and [vol1] are inputs to the amerge + # filter, and thus we would not want them as final outputs. So, we + # have to identify the amerge output and pass it to -out. This + # identifier is called an "output pad" in man ffmpeg-filters, and a + # "link label" in man ffmpeg. + -map '[vout]' + + # An online source says to match a 5 second vid delay, we can do an + # audio delay filter: "adelay=5000|5000". However, we already get + # a stream delay of about 2 seconds, and having the audio be about + # 2 seconds ahead is fine, they do that intentionally in soccer + # matches. + ) +fi + +if $local; then + out_file_opts=( + "$HOME/$(date +%F_%H_%M_%S%:::z).webm" + ) +else + + out_file_opts=( + -content_type video/webm + -f webm + icecast://source:$pass@$host/fsf$mount_suffix.webm ) fi @@ -347,14 +434,11 @@ opts=( # video output options - -g $keyframe_interval ${encode_settings[@]} - -b:v ${bitrate}k + -g $keyframe_interval + ${out_file_opts[@]} - -content_type video/webm - -f webm - icecast://source:$pass@$host/fsf$mount_suffix.webm ) rm -f /tmp/iank-ffmpeg-interlude-toggle diff --git a/myx b/myx index 2eefc91..f71610d 100755 --- a/myx +++ b/myx @@ -64,34 +64,6 @@ i3() { fi } -move-ws() { - local target_out output tmps - target_out=$1 - shift - - if [[ ! ${ws_out[*]} ]]; then - declare -a ws_out - tmps=$(i3 -t get_workspaces) - if [[ ! $tmps ]]; then - return 0 - fi - tmps=$(jq -r '.[] | .num, .output' <<<"$tmps") - while read -r ws; do - read -r output || break - ws_out["$ws"]=$output - done <<<"$tmps" - fi - - for ws; do - if [[ ${ws_out[$ws]} && ${ws_out[$ws]} != "$target_out" ]]; then - # if the workspace is already there, this will fail. - # if the workspace doesn't exist yet, it fails with: - # ERROR: No output matched - m i3 '[workspace="'$ws'"]' move workspace to output $target_out - fi - done -} - date "+%A, %B %d, %r, %S seconds" @@ -247,11 +219,12 @@ fi ## begin i3 config ## +move_outputs=() +ws_outputs=() if [[ $secondary_out ]]; then ws1_output=$primary_out move_outputs=($primary_out) -else - move_outputs=() +elif $tall || $quarter; then ws1_output=MON-RIGHT fi @@ -259,6 +232,7 @@ ws_outputs=( $ws1_output ) + if $tall; then ws_outputs+=( MON-LEFT @@ -272,52 +246,58 @@ elif $quarter; then MON-RIGHT ) move_outputs+=(MON-BOTTOM-LEFT MON-RIGHT) +elif [[ $secondary_out ]]; then + move_outputs+=($secondary_out) + ws_outputs+=($secondary_out) + fi echo d1 ${ws_outputs[@]} -if (( ${#move_outputs[@]} == 0 )); then - move_outputs=(right) -fi - rm -f ~/i3-myx.conf total_ws_count=10 for (( i=0; i>~/i3-myx.conf done +if [[ $secondary_out ]]; then + cat /a/bin/ds/i3-sway/bar.conf >> ~/i3-myx.conf +fi echo "bindsym \$mod+Shift+t move workspace to output ${move_outputs[*]}" >>~/i3-myx.conf m /a/bin/ds/i3-sway/gen - -# this bit is so that we only move workspaces that need to be moved -# and we don't have to ignore errors. A waste of time, but -# it was fun. -declare -A ws_to_out -tmps=$(i3 -t get_workspaces) -tmps=$(jq -r '.[] | .num, .output' <<<"$tmps") -while read -r ws; do - read -r output || break - ws_to_out["$ws"]=$output -done <<<"$tmps" - -for (( i=0; i = 94; # down = 116; - # todo: right, 114 is unused + # todo: right/rght, 114 is unused = 66; = 97; = 98;