From: Ian Kelling Date: Wed, 5 Jun 2024 02:43:02 +0000 (-0400) Subject: mostly improvements, wip X-Git-Url: https://iankelling.org/git/?a=commitdiff_plain;h=e6cd2e555df3af0cf23da016b833529a34ffc84c;p=distro-setup mostly improvements, wip --- diff --git a/brc b/brc index 32a2c66..8e1b327 100644 --- a/brc +++ b/brc @@ -689,10 +689,10 @@ jdo() { fi # -q = quiet journalctl -qn2 -f -u "$cmd_name" & + jr_pid=$! # Trial and error of time needed to avoid missing initial lines. # .5 was not reliable. 1 was not reliable. 2 was not reliable sleep 4 - jr_pid=$! systemd-run --unit "$cmd_name" --wait --collect "$cmd" "$@" || ret=$? # The sleep lets the journal output its last line # before the prompt comes up. @@ -2450,6 +2450,19 @@ serstat() { systemctl -n 40 status "$@" } +# assume last arg is a service and we want to tail its log. +serj() { + local service jr_pid ret + ret=0 + service="${*: -1}" + journalctl -qn2 -f -u "$service" & + sleep 3 + s systemctl "$@" || ret=$? + sleep .5 + kill %% + (( ret == 0 )) || return $ret +} + seru() { systemctl --user "$@"; } # like restart, but do nothing if its not already started srestart() { diff --git a/brc2 b/brc2 index 6ac5183..7699add 100644 --- a/brc2 +++ b/brc2 @@ -1682,11 +1682,9 @@ jdo() { if [[ $cmd != /* ]]; then cmd=$(type -P "$cmd") fi + #note date format for since is date '+%F %T' # -q = quiet - journalctl -qn2 -f -u "$cmd_name" & - # Trial and error of time needed to avoid missing initial lines. - # .5 was not reliable. 1 was not reliable. 2 was not reliable - sleep 4 + journalctl --since=now -qn2 -f -u "$cmd_name" & jr_pid=$! # note, we could have a version that does system --user, but if for example # it does sudo ssh, that will leave a process around that we can't kill @@ -4177,10 +4175,7 @@ vpn() { fi [[ $1 ]] || { echo need arg; return 1; } - journalctl --unit=$vpn_service@$1 -f -n0 & - # sometimes the journal doesnt open until after the vpn output - # has happened. hoping this fixes that. - sleep 1 + journalctl --since=now --unit=$vpn_service@$1 -f -n0 & sudo systemctl start $vpn_service@$1 # sometimes the ask-password agent does not work and needs a delay. sleep .5 @@ -4199,15 +4194,17 @@ fixu() { fi } -# unmute +# unmute desktop output um() { - local sink card + local sink card sedcmd sink=$(pactl get-default-sink) if [[ $sink == auto_null ]]; then # guessing there is just one with an off profile. otherwise we will # need some other solution, like storing the card identifier that we - # muted with nap. - card=$(pacmd list-cards | sed -n '/^[[:space:]]*index:/{s/^[[:space:]]*index://;h};/^[[:space:]]*active profile: $/{g;p;q}') + # muted with nap. Or, we could so some hakery with + # pactl -f json. + sedcmd='/^[[:space:]]*index:/{s/^[[:space:]]*index://;h};/^[[:space:]]*active profile: $/{g;p;q}' + card=$(pacmd list-cards | sed -n "$sedcmd") m pacmd set-card-profile "$card" output:analog-stereo fi @@ -4725,7 +4722,8 @@ ftoc() { units "tempF($1)" tempC } -# requires dns/firewall setup first +# note: requires dns setup of live.iankelling.org, & if i'm home, port +# forwarding in wrt-setup-local. todo: automate that. local-icecast() { web-conf -e ian@iankelling.org -f 8000 - apache2 live.iankelling.org <<'EOF' @@ -4778,17 +4776,24 @@ opensslcertinfo() { # dsh on btrbk hosts dsb() { -: - } + : +} # dsh a file and run it dsa() { local ret file if ! parallel -j 10 scp x {}:/tmp <~/.dsh/group/btrbk; then echo parallel scp failed. dsa returning $ret - fi + fi dsh -g btrbk - } +} + +# temporary +zmqsend() { + /nocow/t/ffmpeg-release/ffmpeg-7.0.1/tools/zmqsend "$@" +} + +ffg() { /nocow/t/ffmpeg-release/ffmpeg-7.0.1/tools/graph2dot -o /tmp/g.tmp && dot -Tpng /tmp/g.tmp -o /tmp/g.png && feh /tmp/g.png; } export BASEFILE_DIR=/a/bin/fai-basefiles diff --git a/dynamic-ip-update b/dynamic-ip-update index 12726ae..44d9ffe 100755 --- a/dynamic-ip-update +++ b/dynamic-ip-update @@ -88,6 +88,11 @@ main() { case $gateway in 10.2.0.1) dyndomain=b8.nz + # This domain is for any case where we want some different + # configuration based on lan vs wan. For right now, the only use + # is for ssh config to use port forwarding ports on the wan + # domain. + dyndomain_internet=i.b8.nz ;; *) return 0 @@ -176,6 +181,8 @@ EOF cat >>$tmpf </tmp/iank-ffmpeg & +# ffmpeg ... /tmp/iank-ffmpeg +# echo "cdrawbox -1 t fill" >/tmp/iank-ffmpeg +# echo "cdrawtext -1 reinit text=''" >/tmp/iank-ffmpeg +# echo "cvolume -1 volume=1" >/tmp/iank-ffmpeg + + +# For testing: to show the number of audio channels in a resulting file +# https://stackoverflow.com/questions/47905083/how-to-check-number-of-channels-in-my-audio-wav-file-using-ffmpeg-command +# +# ffprobe -i /tmp/out.wav -show_entries stream=channels -select_streams a:0 -of compact=p=0:nk=1 -v 0 + +# for a right/left speaker test: +# https://askubuntu.com/questions/148363/which-linux-command-can-i-use-to-test-my-speakers-for-current-talk-radio-output +# p install alsa-utils +# speaker-test -t wav -c 2 -l 1 + +# There are 2 other options for audio, so I wanted to do a little +# performance measurement of this method. +# 1 is to combine the 2 audio sources in pulse, +# https://unix.stackexchange.com/questions/351764/create-combined-source-in-pulseaudio . +# 1 is to record mumble and combine in post processing. + +### benchmark / perf tests: these are pretty inaccurate. +# 29 seconds cpu use. video bitrate 1500k, 8 fps, 2x keyframe interval. +# * 64k vorbis: 69.7% +# * 128k vorbis: 70.1% (used in subsequent tests) +# * 1 audio input: 64.3% +# * 0 audio inputs: 59.2% + +# how I did perf testing: add -to 00:00:30 to ffmpeg opts to +# conveniently exit after measurement. Then run: +# +# ffmpeg "${opts[@]}" & +# pid=$! +# sleep 29 +# ps -p $pid -o %cpu +# kill %% + +# filter for only 1 audio input: +#-filter_complex "[0]azmq,volume=precision=fixed;[1]zmq='b=tcp\://127.0.0.1\:5557',drawbox=color=0x262626,drawtext=fontsize=90: fontcolor=beige: x=40: y=40: text=''" +# filter with 0 audio input: +# -filter_complex "[0]zmq='b=tcp\://127.0.0.1\:5557',drawbox=color=0x262626,drawtext=fontsize=90: fontcolor=beige: x=40: y=40: text=''" + + +# When things weren't working, I did some checking on newer ffmpeg to +# see if that helped. It never did. I compiled the latest ffmpeg release +# tarball, 7.0.1, and tried the version in debian bullseye by schrooting +# before running ffmpeg. Building was just configure; make, but then I +# found some flags that were needed. gpl flags r just because I noticed them. +# ./configure --enable-libzmq --enable-libpulse --enable-libvorbis --enable-gpl --enable-version3 +# + +### end background/development docs ### + if ! test "$BASH_VERSION"; then echo "error: shell is not bash" >&2; exit 1; fi shopt -s inherit_errexit 2>/dev/null ||: # ignore fail in bash < 4.4 @@ -32,12 +131,27 @@ set -eE -o pipefail trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" exit status: $?, PIPESTATUS: ${PIPESTATUS[*]}" >&2' ERR -# 3 mountpoints: fsf-sysops (public), fsf (default, all staff), fsf-tech (tech team) -case $1 in - sysops|tech) - mount_suffix=-$1 - ;; -esac +debug=false +loglevel=fatal + +# 3 mountpoints: fsf-sysops (default, public), fsf (all staff), fsf-tech (tech team) +# # note: duplicated in ffp +mount_suffix=-sysops +while [[ $1 ]]; do + case $1 in + sysops|tech) + mount_suffix=-$1 + ;; + staff) + mount_suffix= + ;; + -d) + debug=true + loglevel=debug + ;; + esac + shift +done host=live.iankelling.org:8000 if [[ $(dig +short @10.2.0.1 -x 10.2.0.2 2>&1 ||:) == kd.b8.nz. ]] \ @@ -66,31 +180,111 @@ else stream_res=$primary_res fi +framerate=8 +keyframe_interval=$((framerate * 2)) + +# Monitor of default sink. +# eg: alsa_output.usb-Audio-gd_Audio-gd-00.analog-stereo +pa_sink=$(pacmd list-sinks | awk '/\*/ {getline; print $2}' | sed 's/^$//').monitor opts=( - # nice to have: be a little less verbose + # global options + # be relatively quiet. switch to debug when testing. + -v $loglevel -hide_banner + -nostats + + # note: ordering of inputs also affects zmqsend commands. + + ## audio input options + + -f pulse + -name ffs + # note: duplicated above + -thread_queue_size 160 + -fragment_size 512 + -i default + + -f pulse + # this is for ffmpeg warnings. doesnt seem to affect latency. + -thread_queue_size 160 + # pulse knows this name somewhere + -name ffsdesktop + # This fixes latency. i haven't tried tuning it, but going too low creates + # choppy output. + -fragment_size 512 + -i "$pa_sink" + + + ## video input options -video_size $stream_res -f x11grab - -framerate 4 - # input options come before -i + -framerate $framerate -i :0.0+$x_offset.0 - -vf drawbox=color=black + + # 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=0 [vol0]; +[1]azmq='b=tcp\://127.0.0.1\:5556',volume=precision=fixed: volume=0 [vol1]; +[vol0][vol1] amerge=inputs=2 [out]; +[2]zmq='b=tcp\://127.0.0.1\:5557',drawbox=color=0x262626,drawtext=fontsize=90: fontcolor=beige: x=40: y=40: text=''" + + # 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]' + + # video output options -vcodec libvpx - -g 8 + -g $keyframe_interval -quality realtime + # for 1080p, default 256k is poor quality. 500 is ok. 1500 is a bit better. + -b:v 1500k -threads 2 + -buffer_duration 10 -error-resilient 1 + + ## audio output options + -c:a libvorbis + -b:a 128k + # afaik, this ensures that the amerge doesn't make 4 channel output if + # our output format supported it. + -ac 2 + -content_type video/webm -f webm icecast://source:$pass@$host/fsf$mount_suffix.webm - ) +rm -f /tmp/iank-ffmpeg-interlude-toggle + +# start muted +pactl set-source-mute @DEFAULT_SOURCE@ true + +#echo executing: ffmpeg ${opts[@]} + +#{ sleep 1; ffp &>/dev/null & } + +if $debug; then + ffmpeg "${opts[@]}" + exit 0 +fi -rm -f /tmp/iank-ffmpeg -mkfifo -m 0600 /tmp/iank-ffmpeg -echo executing: ffmpeg -stdin ${opts[@]} -# ffmpeg sits and waits until we do this. dunno why. whatever. -echo >/tmp/iank-ffmpeg & -ffmpeg ${opts[@]} /dev/null; then i3-msg "move $direction; move $direction" else diff --git a/i3-set-layout b/i3-set-layout new file mode 100755 index 0000000..89780d1 --- /dev/null +++ b/i3-set-layout @@ -0,0 +1,65 @@ +#!/usr/bin/python3 + +import sys +from i3ipc import Connection, Event + + +def find_parent(i3, window_id): + """ + Find the parent of a given window id + """ + + def finder(con, parent): + if con.id == window_id: + return parent + for node in con.nodes: + res = finder(node, con) + if res: + return res + return None + + return finder(i3.get_tree(), None) + + +def set_layout(i3): + """ + Set the layout/split for the currently + focused window to either vertical or + horizontal, depending on its width/height + """ + + + + win = i3.get_tree().find_focused() + parent = find_parent(i3, win.id) + + + # We never want to set the layout of a single window container, + # there are already keys for that. I don't know why i3 even does + # this, it is stupid. So, eliminate single window container if we + # are focused on one. + # + # Alternatively, it could first focus the parent, but I think when + # layout changes, we expect new windows to be created within that + # layout. + if (parent and len(parent.nodes) == 1): + gp = find_parent(i3, parent.id) + if (gp.nodes[0].id == parent.id): + if (gp.layout == 'splitv'): + i3.command('move down') + else: # splith or tabbed + i3.command('move right') + else: + if (gp.layout == 'splitv'): + i3.command('move up') + else: + i3.command('move left') + i3.command('layout ' + sys.argv[1]) + +def main(): + i3 = Connection() + set_layout(i3) + + +if __name__ == "__main__": + main() diff --git a/i3-split-maybe b/i3-split-maybe index 69e42c5..dcb268a 100755 --- a/i3-split-maybe +++ b/i3-split-maybe @@ -29,21 +29,41 @@ set -e; . /usr/local/lib/bash-bear; set +e # just after a window is created, or just before a window is # created. # -# *Doing it after a window is created allows you to move a window into +# * Doing it after a window is created allows you to move a window into # the split that only has 1 window, whereas the other way doesn't. For # my use cases, I think I don't really want to move it into the split if -# it is a tabbed split. +# it is a tabbed split. upon further reflection, I've determined that +# single window containers are inherently confusing because they tend to +# exist and get nested at unexpected times and then it is unclear how to +# get rid of them and what is going on and the benefit is generally not +# worth it. This command helps identify single window containers during +# testing: /a/opt/i3ipc-python/examples/i3-debug-console.py # -# *Doing it just before a windows is created, you need to -# call this script, which means wrapping launch of a program, which I -# have no way to do for all cases, I just do it for the common programs -# I have bound to keys in i3. +# * Doing it just before a windows is created, you need to call this +# script, which means wrapping launch of a program, which I have no way +# to do for all cases, I just do it for the common programs I have bound +# to keys in i3. # # * Doing it after a window is created also leaves that split behind if -# * the window is closed. I partially deal with that below. +# the window is closed. I partially deal with that below. # # I have a keybind which disables both, it runs /b/ds/i3-auto-layout-toggle + +dry_run=false +m() { "$@"; } +d() { + if $dry_run; then + printf "%s\n" "$*" + fi +} +case $1 in + -n) + dry_run=true + m() { printf "%s\n" "$*"; } + ;; +esac + if [[ -e /tmp/iank-i3-no-auto ]]; then exit 0 fi @@ -57,26 +77,27 @@ i3-msg -t get_workspaces | jq ".[]| select(.focused==true) | .rect | .width, .he i3-msg -t get_tree | jq -r ".. | select(.focused? == true).rect | .width, .height" >$tmp -half_w=$(( screen_width / 2 + 100 )) -half_h=$(( screen_height / 2 + 100 )) +half_w=$(( screen_width / 2 )) +half_h=$(( screen_height / 2 )) { read -r w; read -r h; } <$tmp +d w=$w , h=$h , half_w=$half_w , half_h=$half_h if (( screen_width < 1920 )); then # haven't considered this case yet exit 0 fi -if (( w < half_w && h < half_h )); then - i3-msg "split vertical, layout tabbed" + +if (( w <= half_w && h <= half_h )); then + m i3-msg "split vertical, layout tabbed" elif (( w == screen_width )); then - : # if we had 2 windows on screen, made them vertical splits, then # closed one, it stays vertical split, but we want it horizontal at # that point. So, make it horizontal here. - i3-msg "split horizontal" + m i3-msg "split horizontal" fi rm -f $tmp diff --git a/i3-sway/bar.conf b/i3-sway/bar.conf new file mode 100644 index 0000000..d1457be --- /dev/null +++ b/i3-sway/bar.conf @@ -0,0 +1,31 @@ +# need this for kde connect +bar { + +# keep it only on secondary monitor to save space and make for less +# missing pixes in obs live stream. For docs on this, search "output +# primary" in the i3 guide. +output primary + +# the builtin prog +#status_command i3status + +#for faster testing +#status_command /a/bin/ds/myi3status +status_command /usr/local/bin/myi3status +#mode hide +# hidden_state hide +font pango:monospace 18 + +# i have no need for the tray icons so far +tray_output primary + +# I found I didn't need these, but, I'm trying them out again. +# workspace_buttons no +} + +## dont want to see this bar for now +# bar { +# status_command /p/c/myi3life +# tray_output none +# workspace_buttons no +# } diff --git a/i3-sway/common.conf b/i3-sway/common.conf index 017f4bd..2cc2d1c 100644 --- a/i3-sway/common.conf +++ b/i3-sway/common.conf @@ -31,7 +31,7 @@ bindsym $mod+3 $ex "/b/ds/i3-split-maybe"; exec "abrowser" bindsym $mod+4 $ex "/b/ds/i3-split-maybe"; exec "abrowser -no-remote -P firefox-main-profile" # todo: figure out a stream delay & way to cut the stream. # settings, advanced, stream delay -bindsym $mod+5 $ex "/a/bin/ds/obs-i3-interlude" +bindsym $mod+5 $ex "/a/bin/ds/stream-interlude" bindsym $mod+6 $ex "/b/ds/i3-split-maybe"; exec "/usr/local/bin/start-tor-browser" bindsym $mod+7 $ex "/a/bin/ds/laptop-xrandr" #bindsym $mod+6 $ex "/a/bin/redshift.sh" @@ -45,7 +45,7 @@ bindsym $mod+1 focus parent bindsym $mod+shift+1 focus child # undo split: https://github.com/i3/i3/issues/3808 bindsym $mod+grave floating toggle; floating toggle -bindsym $mod+equal $ex "dunstctl close-all" +bindsym $mod+equal $ex "/a/exe/i3-set-layout splith" # move firefox to current workspace. # https://i3wm.org/docs/userguide.html#keybindings # get class with xprop, example output @@ -57,14 +57,24 @@ bindsym $mod+shift+w fullscreen toggle bindsym $mod+e $ex i3-pull emacs bindsym $mod+shift+e unmark emacs; mark emacs bindsym $mod+r $ex "/a/bin/ds/xl" -# todo, in newer i3, make this toggle split tabbed -bindsym $mod+t layout toggle splith splitv tabbed + +# todo, in newer i3, make this toggle split tabbed. +bindsym $mod+t $ex "/a/exe/i3-set-layout splitv" #bindsym $mod+Shift+t move workspace to output up bindsym $mod+Shift+t move workspace to output right -# there's a bug about this. it is not logical that there is no "split -# tabbed", but you accomplish that by doing this. -bindsym $mod+g split horizontal, layout tabbed -bindsym $mod+shift+n layout tabbed + +# todo: consider a command that moves a window, and erases any single +# container window left behind. + +# todo: port /b/ds/i3-maybe-double-move into python. + +# todo: consider a command which alters things as if the current window +# had been created into a single window split. For horizontal split, +# this would be like: focus left, split vertical, focus right, move +# left. With that, we could totally eliminate single window containers. + +bindsym $mod+g $ex "/a/exe/i3-set-layout tabbed" + bindsym $mod+shift+g $ex "/b/ds/i3-auto-layout-toggle" # Use Mouse+$mod to drag floating windows to their wanted position @@ -129,6 +139,7 @@ bindsym $mod+8 workspace 9 bindsym $mod+Shift+9 move container to workspace 10 bindsym $mod+9 workspace 10 +bindsym $mod+m $ex "dunstctl close-all" bindsym $mod+Shift+m border toggle # 65 = space. @@ -149,14 +160,14 @@ bindcode $mod+shift+65 focus mode_toggle # Use Mouse+$mod to drag floating windows to their wanted position floating_modifier $mod -bindsym $mod+shift+h $ex obs-clip hc +bindsym $mod+shift+h $ex /b/ds/stream-clip hc bindsym $mod+j $ex "/b/ds/i3-split-maybe"; exec emacsclient -c -bindsym $mod+shift+j $ex obs-clip up +bindsym $mod+shift+j $ex /b/ds/stream-clip up bindsym $mod+k $ex "/b/ds/i3-split-maybe"; exec konsole -bindsym $mod+shift+k $ex obs-clip intro +bindsym $mod+shift+k $ex /b/ds/stream-clip intro bindsym $mod+l $ex dmenu_run -bindsym $mod+shift+l $ex obs-clip steady -bindsym $mod+shift+semicolon $ex obs-clip sad +bindsym $mod+shift+l $ex /b/ds/stream-clip steady +bindsym $mod+shift+semicolon $ex /b/ds/stream-clip sad # note default is 27% on my system76. not sure if these # keybinds will screw up other laptop brightness keys. bindsym XF86MonBrightnessUp $ex brightnessctl s +5% @@ -166,7 +177,6 @@ bindsym XF86MonBrightnessDown $ex brightnessctl s 5%- # is used in the bar {} block below. font pango:monospace 7 -# todo: only available in newer i3n hide_edge_borders vertical #exec --no-startup-id /usr/lib/x86_64-linux-gnu/libexec/kdeconnectd @@ -176,11 +186,13 @@ hide_edge_borders vertical # shortcut to selection widget (primary) -bindsym $mod+End $ex /a/opt/clipster/clipster -sp +bindsym $mod+End $ex "/b/ds/toggle-mute" # title bars but no borders. i tried this out a bit #default_border normal 0 default_border pixel 4 +# for debugging +default_border normal 10 # I dont see a way to make processing windows act like normal windows, # this does it. @@ -193,6 +205,6 @@ default_border pixel 4 # this is the processing window for my app named focus. for_window [class="focus" instance="focus"] floating disable -client.focused #4c7899 #285577 #ffffff #2e9ef4 #ff4400 -client.focused_inactive #333333 #5f676a #ffffff #484e50 #DBEEF4 -client.unfocused #333333 #222222 #888888 #292d2e #B8C8CD +# client.focused #4c7899 #285577 #ffffff #2e9ef4 #ff4400 +# client.focused_inactive #333333 #5f676a #ffffff #484e50 #DBEEF4 +# client.unfocused #333333 #222222 #888888 #292d2e #B8C8CD diff --git a/i3-sway/gen b/i3-sway/gen index 99e4503..cf262ad 100755 --- a/i3-sway/gen +++ b/i3-sway/gen @@ -32,3 +32,8 @@ cat common.conf sway.conf > $dir/config dir=/a/bin/distro-setup/subdir_files/.config/i3 mkdir -p $dir cat common.conf i3.conf > $dir/config + +monitor_count=$(xrandr|grep -c ' connected') +if [[ $1 == bar ]] || (( monitor_count >= 2 )); then + cat bar.conf >> $dir/config +fi diff --git a/i3-sway/i3.conf b/i3-sway/i3.conf index 265a932..737acc2 100644 --- a/i3-sway/i3.conf +++ b/i3-sway/i3.conf @@ -3,39 +3,9 @@ bindsym $mod+Shift+o exec "i3-nagbar -t warning -m 'You pressed the exit shortcu bindsym $mod+Shift+p restart -# need this for kde connect -# bar { - -# # keep it only on secondary monitor to save space and make for less -# # missing pixes in obs live stream. For docs on this, search "output -# # primary" in the i3 guide. -# output primary - -# # the builtin prog -# #status_command i3status - -# #for faster testing -# #status_command /a/bin/ds/myi3status -# status_command /usr/local/bin/myi3status -# #mode hide -# # hidden_state hide -# font pango:monospace 18 - -# # i have no need for the tray icons so far -# tray_output primary - -# # I found I didn't need these, but, I'm trying them out again. -# # workspace_buttons no -# } - -## dont want to see this bar for now -# bar { -# status_command /p/c/myi3life -# tray_output none -# workspace_buttons no -# } $ex copyq $ex dunst $ex /usr/lib/x86_64-linux-gnu/libexec/kdeconnectd -$ex /a/opt/i3-alternating-layout/alternating_layouts.py +# this dies when we restart i3. +exec_always --no-startup-id alternating_layouts.py diff --git a/myi3status b/myi3status index bd0c634..2df9746 100755 --- a/myi3status +++ b/myi3status @@ -181,6 +181,17 @@ main() { ps_char="$ps_char O" fi + if pgrep -fc '^ffmpeg.*icecast://source.*/fsf' &>/dev/null; then + if [[ -e /tmp/iank-ffmpeg-interlude-toggle ]]; then + ps_char="= BRB = $ps_char" + else + ps_char="=|=|= STREAMING =|=|= $ps_char" + if pactl get-source-mute @DEFAULT_SOURCE@ 2>/dev/null | awk '{print $2}' | grep no &>/dev/null; then + ps_char="! UNMUTED ! $ps_char" + fi + fi + fi + printf '{ "name":"status", "color":"#ED297D", "full_text": "%s' "$ps_char" printf '"},' diff --git a/obs-clip b/obs-clip deleted file mode 100755 index 60bafda..0000000 --- a/obs-clip +++ /dev/null @@ -1,71 +0,0 @@ -#!/bin/bash -# I, Ian Kelling, follow the GNU license recommendations at -# https://www.gnu.org/licenses/license-recommendations.en.html. They -# recommend that small programs, < 300 lines, be licensed under the -# Apache License 2.0. This file contains or is part of one or more small -# programs. If a small program grows beyond 300 lines, I plan to switch -# its license to GPL. - -# Copyright 2024 Ian Kelling - -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -set -e; . /usr/local/lib/bash-bear; set +e - -type=$1 - -cd /a/bin/data/clips/$type - -if pgrep mpv; then - pkill mpv - exit 0 -fi - - -case $type in - up) - if [[ ! -s /tmp/last-up ]]; then - find . -type f -printf '%f\n' | shuf > /tmp/last-up - fi - clip=$(head -n1 /tmp/last-up) - tail -n+2 /tmp/last-up | sponge /tmp/last-up - ;; - *) - clip=$(find . -type f -printf '%f\n' | \ - { if [[ -e /tmp/last-$type ]]; then - sed "/^$(cat /tmp/last-$type)\$/d" - else - cat - fi ; } | \ - shuf | head -n1) - echo $clip >/tmp/last-$type - ;; -esac - -found=false - -p=$(cat /p/obs-ws-pass) -# note, if the desktop audio is already on, this will do the wrong thing. -# obs-cmd needs more commands. But, I don't use desktop audio for anything -# else atm. -if pgrep '^obs$' &>/dev/null; then - # this is so the script keeps working when obs is not running, but - # also doesn't ignore errors. - found=true - obs-cmd -w obsws://localhost:4455/$p toggle-mute 'Desktop Audio' -fi -mpv --profile=a $clip ||: - -if $found; then - obs-cmd -w obsws://localhost:4455/$p toggle-mute 'Desktop Audio' -fi diff --git a/obs-i3-interlude b/obs-i3-interlude deleted file mode 100755 index 03636da..0000000 --- a/obs-i3-interlude +++ /dev/null @@ -1,35 +0,0 @@ -#!/bin/bash -# I, Ian Kelling, follow the GNU license recommendations at -# https://www.gnu.org/licenses/license-recommendations.en.html. They -# recommend that small programs, < 300 lines, be licensed under the -# Apache License 2.0. This file contains or is part of one or more small -# programs. If a small program grows beyond 300 lines, I plan to switch -# its license to GPL. - -# Copyright 2024 Ian Kelling - -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -set -e; . /usr/local/lib/bash-bear; set +e - -if [[ -e /tmp/no-obs-auto-scene-switch ]]; then - rm -f /tmp/no-obs-auto-scene-switch - if [[ -s /tmp/last-obs-i3-mark ]]; then - p=$(cat /p/obs-ws-pass) - mark=$(cat /tmp/last-obs-i3-mark) - obs-cmd -w obsws://localhost:4455/$p scene switch $mark - fi -else - touch /tmp/no-obs-auto-scene-switch - obs-cmd -w obsws://localhost:4455/$p scene switch interlude -fi diff --git a/pkgs b/pkgs index 97e4e9d..8d58447 100644 --- a/pkgs +++ b/pkgs @@ -255,6 +255,8 @@ p3=( pidgin pidgin-otr pixz + # unattended-upgrades.log: Please install powermgmt-base package to check power status + powermgmt-base profanity pry # https://wiki.archlinux.org/title/bluetooth diff --git a/script-files b/script-files index e369ceb..2bc52a0 100644 --- a/script-files +++ b/script-files @@ -46,6 +46,7 @@ my_bin_files=( prof-notify /a/bin/newns/newns /a/bin/fai/fai/config/distro-install-common/ethusb-static + /a/opt/i3-alternating-layout/alternating_layouts.py ) for f in /b/log-quiet/*; do diff --git a/stream-clip b/stream-clip new file mode 100755 index 0000000..267ca31 --- /dev/null +++ b/stream-clip @@ -0,0 +1,99 @@ +#!/bin/bash +# I, Ian Kelling, follow the GNU license recommendations at +# https://www.gnu.org/licenses/license-recommendations.en.html. They +# recommend that small programs, < 300 lines, be licensed under the +# Apache License 2.0. This file contains or is part of one or more small +# programs. If a small program grows beyond 300 lines, I plan to switch +# its license to GPL. + +# Copyright 2024 Ian Kelling + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -e; . /usr/local/lib/bash-bear; set +e + +type=$1 + +cd /a/bin/data/clips/$type + +pregex='^mpv --profile=a [^/]+$' +if pgrep -fc "$pregex" >/dev/null; then + pkill -f "$pregex" + exit 0 +fi + +case $type in + up) + if [[ ! -s /tmp/last-up ]]; then + find . -type f -printf '%f\n' | shuf > /tmp/last-up + fi + clip=$(head -n1 /tmp/last-up) + tail -n+2 /tmp/last-up | sponge /tmp/last-up + ;; + *) + # don't listen to the very last clip, but otherwise we don't mind + # recent repeats. + count=$(find . -type f -printf '%f\n' | wc -l) + if (( count > 1 )); then + clip=$(find . -type f -printf '%f\n' | \ + { if [[ -e /tmp/last-$type ]]; then + sed "/^$(cat /tmp/last-$type)\$/d" + else + cat + fi ; } | \ + shuf | head -n1) + echo $clip >/tmp/last-$type + else + clip=./* + fi + ;; +esac + +found=false + +# When I was using obs. Incorporate if I try it again. +# unmute() { +# p=$(cat /p/obs-ws-pass) +# # note, if the desktop audio is already on, this will do the wrong thing. +# # obs-cmd needs more commands. But, I don't use desktop audio for anything +# # else atm. +# if pgrep '^obs$' &>/dev/null; then +# # this is so the script keeps working when obs is not running, but +# # also doesn't ignore errors. +# found=true +# obs-cmd -w obsws://localhost:4455/$p toggle-mute 'Desktop Audio' +# fi +# } +# mute() { +# if $found; then +# obs-cmd -w obsws://localhost:4455/$p toggle-mute 'Desktop Audio' +# fi +# } + + +# note: condition duplicated in stream-clip, myi3status +if pgrep -fc '^ffmpeg.*icecast://source.*/fsf' >/dev/null; then + found=true + toggle-mute mute + echo Parsed_volume_3 volume 1 | zmqsend -b tcp://127.0.0.1:5556 +fi + +mpv --profile=a $clip ||: + +if $found; then + # I dunno if this is needed, but I think it is theoretically possible + # for us to mute ffmpeg before it finishes processing the mpv + # output. It would probably only need a few miliseconds, but whatever. + sleep 1 + echo Parsed_volume_3 volume 0 | zmqsend -b tcp://127.0.0.1:5556 +fi diff --git a/stream-interlude b/stream-interlude new file mode 100755 index 0000000..ea5812e --- /dev/null +++ b/stream-interlude @@ -0,0 +1,83 @@ +#!/bin/bash +# I, Ian Kelling, follow the GNU license recommendations at +# https://www.gnu.org/licenses/license-recommendations.en.html. They +# recommend that small programs, < 300 lines, be licensed under the +# Apache License 2.0. This file contains or is part of one or more small +# programs. If a small program grows beyond 300 lines, I plan to switch +# its license to GPL. + +# Copyright 2024 Ian Kelling + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -e; . /usr/local/lib/bash-bear; set +e + +obs-interlude() { + p=$(cat /p/obs-ws-pass) + if [[ -e /tmp/no-obs-auto-scene-switch ]]; then + rm -f /tmp/no-obs-auto-scene-switch + if [[ -s /tmp/last-obs-i3-mark ]]; then + mark=$(cat /tmp/last-obs-i3-mark) + obs-cmd -w obsws://localhost:4455/$p scene switch $mark + fi + else + touch /tmp/no-obs-auto-scene-switch + obs-cmd -w obsws://localhost:4455/$p scene switch interlude + fi + +} + +ffmpeg-interlude() { + f=/tmp/iank-ffmpeg-interlude-toggle + + # interlude off + if [[ -e $f ]]; then + + rm -f $f + # note: get _6 from looking for "parsed" ffmpeg debug output. + zsend -b tcp://127.0.0.1:5557 Parsed_drawbox_6 t 0 + zsend -b tcp://127.0.0.1:5557 Parsed_drawtext_7 reinit "text=''" + + else + + # I started an attempt to track if I was muted before an interlude, + # but decided against it. Seems easier to handle unmuting with + # whatever normal process I have for it. + # + # muted=$(pactl get-source-mute @DEFAULT_SOURCE@ | awk '{print $2}') + + zsend Parsed_volume_1 volume 0 + zsend -b tcp://127.0.0.1:5557 Parsed_drawbox_6 t fill + zsend -b tcp://127.0.0.1:5557 Parsed_drawtext_7 reinit "text='$(date "+%H\:%M %Z") - Be right back'" + touch $f + fi +} + +zsend() { + local out + if [[ $1 == -b ]]; then + zmq_args=("$1" "$2") + shift 2 + fi + out=$(printf "%s\n" "$*" | zmqsend ${zmq_args[@]} ||:) + if [[ $out != "0 Success" ]]; then + i3-nagbar -m "FAILED zmqsend: $*" -t error -f "pango:monospace 30" + fi +} + + +if pgrep '^obs$' &>/dev/null; then + obs-interlude +else + ffmpeg-interlude +fi diff --git a/toggle-mute b/toggle-mute new file mode 100755 index 0000000..b50b37e --- /dev/null +++ b/toggle-mute @@ -0,0 +1,66 @@ +#!/bin/bash +# I, Ian Kelling, follow the GNU license recommendations at +# https://www.gnu.org/licenses/license-recommendations.en.html. They +# recommend that small programs, < 300 lines, be licensed under the +# Apache License 2.0. This file contains or is part of one or more small +# programs. If a small program grows beyond 300 lines, I plan to change +# to a recommended GPL license. + +# Copyright 2024 Ian Kelling + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +if ! test "$BASH_VERSION"; then echo "error: shell is not bash" >&2; exit 1; fi +shopt -s inherit_errexit 2>/dev/null ||: # ignore fail in bash < 4.4 +set -eE -o pipefail +trap 'echo "$0:$LINENO:error: \"$BASH_COMMAND\" exit status: $?, PIPESTATUS: ${PIPESTATUS[*]}" >&2' ERR + + +mute=true +volume_level=0 + +# mute / unmute instead of toggle. +if [[ $1 ]]; then + case $1 in + mute) + mute=true + ;; + unmute) + mute=false + ;; + esac +else + + muted=$(pactl get-source-mute @DEFAULT_SOURCE@ | awk '{print $2}' ||:) + case $muted in + no) : ;; + yes) mute=false; volume_level=1 ;; + *) + i3-nagbar -m "FAILED TO GET PULSE MUTE STATE" -t error -f "pango:monospace 30" + ;; + esac +fi + +# we double mute here because it could be useful, and I figured out how +# and feel like using what I know. + +pactl set-source-mute @DEFAULT_SOURCE@ $mute + +# note: condition duplicated in stream-clip, myi3statsus +if pgrep -fc '^ffmpeg.*icecast://source.*/fsf' >/dev/null; then + out=$(echo Parsed_volume_1 volume $volume_level | zmqsend ||:) + if [[ $out != "0 Success" ]]; then + i3-nagbar -m "FAILED to set ffmpeg volume to $volume_level" -t error -f "pango:monospace 30" + fi +fi