A collection of scripts
at main 7.4 kB view raw
1#!/bin/sh 2# shellcheck disable=SC1090,SC1091,SC2154 3 4# SC1090 & SC2154 5# The files sourced are user generated files that should contain the needed 6# variables for the script to function correctly. It should be safe to ignore 7# these warnings. 8 9# Required Commands 10# ffmpeg - needed for aud 11# grim - needed for pic 12# mkdir - create missing directories 13# pactl - create loopback devices for multi-device audio recording in wf-recorder 14# slurp - make a selection 15# wf-recorder - needed for rec 16# wl-copy - copy images to clipboard 17 18# This script is intended for use on wayland; however, `scr aud` should work fine without 19# wayland. 20 21# Set required variables if needed 22[ "$SCR_CFG_DIR" ] || SCR_CFG_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/scr" 23[ "$SCR_CACHE_DIR" ] || SCR_CACHE_DIR="${XDG_CACHE_HOME:-$HOME/.cache}/scr" 24 25# Source the configuration file 26# A sample configuration can be found in my dotfiles at: 27# https://github.com/yemouu/setup/blob/master/home/cfg/scr/config.sh 28# TODO: put an example cofiguration in this repo 29. "$SCR_CFG_DIR/config.sh" || { 30 printf '%s\n' "${0##*/}: failed to source $SCR_CFG_DIR/config.sh" 1>&2; exit 1 31} 32 33# Usage statement for the script 34usage() { 35 printf '%b\n' "usage: ${0##*/} action [options]" \ 36 "actions:" \ 37 "\taud - audio" \ 38 "\tpic - picture" \ 39 "\trec - record" \ 40 "options:" \ 41 "\t-a - record desktop audio (aud,rec)" \ 42 "\t-c - copy image to clipboard (pic)" \ 43 "\t-h - display this message" \ 44 "\t-m - record microphone audio (aud,rec)" \ 45 "\t-o - output to use (pic,rec)" \ 46 "\t-d - all displays (pic)" 47} 48 49# Determine the action to run 50case $1 in 51 aud ) action="scr_aud" ;; 52 pic ) action="scr_pic" ;; 53 rec ) action="scr_rec" ;; 54 *h|*help ) usage; exit 0 ;; 55 * ) printf '%s\n' "${0##*/}: $1: invalid action" 1>&2; usage 1>&2; exit 1 ;; 56esac 57shift 58 59# Determine options to run with based on arguments 60# (I need to stop) 61for flag in "$@" 62do 63 # Make sure arguments start with '-' and are atleast 2 characters long 64 case $flag in 65 - ) continue ;; 66 -- ) break ;; 67 -* ) ;; 68 * ) continue;; 69 esac 70 71 # Split arguments to be 1 character long and determine options to use 72 args=${flag#-} 73 74 while [ "$args" ] 75 do 76 a=${args%"${args#?}"} 77 78 case $a in 79 a ) desktop_audio=true ;; 80 c ) copy_clipboard=true ;; 81 d ) output=all ;; # Kinda redundent lol 82 h ) usage; exit 0 ;; 83 m ) microphone=true ;; 84 o ) aargs=$* 85 output=${aargs##*"${flag}"}; output=${output#\ }; output=${output%%\ *} 86 [ "${output}" ] || printf '%s\n' "${0##*/}: -o: missing output" 1>&2 ;; 87 * ) printf '%s\n' "${0##*/}: -$a: invalid argument" 1>&2 88 usage 1>&2; exit 1 ;; 89 esac 90 91 args=${args#?} 92 done 93done 94unset args arg 95 96# Simple function to print out an error message and exit 97die() { 98 printf '%s\n' "${0##*/}: $*" 1>&2 99 exit 1 100} 101 102# Record Audio 103scr_aud() { 104 # Create the directory to store audio recordings if it does not already exist 105 [ -d "$scr_aud_dir" ] || \ 106 { mkdir -p "$scr_aud_dir" || die "failed to make directory: $scr_aud_dir"; } 107 108 # Create the directory to store logs if it does not already exist 109 [ -d "$SCR_CACHE_DIR" ] || \ 110 { mkdir -p "$SCR_CACHE_DIR" || \ 111 die "failed to make directory: $SCR_CACHE_DIR"; } 112 113 filename="$scr_aud_dir/$aud_filename" 114 115 # Require atleast one of the arguments: -a or -m 116 [ "$microphone" ] || [ "$desktop_audio" ] || \ 117 { die "aud: argument -a or -m is required to record audio"; } 118 119 # Set ffmpeg options based on script options 120 [ "$microphone" ] && { args="-f pulse -i $aud_source"; } 121 [ "$desktop_audio" ] && { args="$args -f pulse -i $aud_sink"; } 122 [ "$microphone" ] && [ "$desktop_audio" ] && \ 123 { args="$args -filter_complex amix=inputs=2"; } 124 125 # Pressing Ctrl+C will exit the script instead of just ffmpeg. 126 # Intercept Ctrl+C and do nothing. 127 trap '' INT 128 129 # shellcheck disable=SC2086 130 # Word splitting is favorable here 131 ffmpeg $args "$filename" > "$SCR_CACHE_DIR/aud.log" 2>&1 & 132 aud_pid=$! 133 printf '%s' "Press Ctrl+C to stop recording. " 1>&2 134 wait $aud_pid 135 136 # Reset the trap 137 trap - INT 138 139 printf '\n%s\n' "$filename" 140} 141 142# Take a screenshot 143scr_pic() { 144 # Create directories if they do not already exist 145 [ -d "$scr_pic_dir" ] || \ 146 { mkdir -p "$scr_pic_dir" || die "failed to make directory: $scr_pic_dir"; } 147 148 [ -d "$SCR_CACHE_DIR" ] || \ 149 { mkdir -p "$SCR_CACHE_DIR" || \ 150 die "failed to create directory: $SCR_CACHE_DIR"; } 151 152 filename="$scr_pic_dir/$pic_filename" 153 154 if [ "$output" = "all" ] 155 then 156 # Grim will screenshot all monitors by default 157 grim "$filename" > "$SCR_CACHE_DIR/pic.log" 2>&1 158 else 159 # Get the geometry of the screenshot from the user and take the screenshot 160 # shellcheck disable=SC2086 161 if [ "$output" ]; then set -- -o "$output"; else set -- -g "$(slurp ${SLURP_ARGS})"; fi 162 grim "$@" "$filename" > "$SCR_CACHE_DIR/pic.log" 2>&1 163 fi 164 165 # Copy the image to the system clipboard 166 $copy_clipboard && { wl-copy <"$filename" > "$SCR_CACHE_DIR/copy.log" 2>&1; } 167 168 printf '%s\n' "$filename" 169} 170 171scr_rec() { 172 # Create directories if they do not already exist 173 [ -d "$scr_rec_dir" ] || \ 174 { mkdir -p "$scr_rec_dir" || die "failed to make directory: $scr_pic_dir"; } 175 176 [ -d "$SCR_CACHE_DIR" ] || \ 177 { mkdir -p "$SCR_CACHE_DIR" || \ 178 die "failed to make directory: $SCR_CACHE_DIR"; } 179 180 filename="$scr_rec_dir/$rec_filename" 181 182 # Set wf-recorder arguments based on script options 183 [ "$microphone" ] && args="-a$aud_source" 184 [ "$desktop_audio" ] && args="-a$aud_sink" 185 186 # If both microphone and desktop_audio is set, create a loopback devices pointing to 187 # scr_inputs. wf-record does not support multiple audio devices. This is how they 188 # recomend you record two devices at the same time. 189 [ "$microphone" ] && [ "$desktop_audio" ] && { 190 unload_pulse_modules=true 191 null_sink=$(pactl load-module module-null-sink sink_name=aud_both) 192 lb_desk=$(pactl load-module module-loopback sink=aud_both source="$aud_sink") 193 lb_mic=$(pactl load-module module-loopback sink=aud_both source="$aud_source") 194 args="-aaud_both.monitor" 195 } 196 197 # Pressing Ctrl+C will exit the script instead of just wf-recorder. 198 # Intercept Ctrl+C and exit wf-recorder instead of the script 199 trap '' INT 200 201 # shellcheck disable=SC2086 202 if [ "$output" ]; then set -- -o "$output"; else set -- -g "$(slurp ${SLURP_ARGS})"; fi 203 # Word splitting is favorable here 204 # shellcheck disable=SC2086 205 wf-recorder $args $rec_extraflags "$@" -f "$filename" > "$SCR_CACHE_DIR/rec.log" 2>&1 & 206 rec_pid=$! 207 printf '%s' "Press Ctrl+C to stop recording. " 1>&2 208 wait $rec_pid 209 210 # Reset the trap 211 trap - INT 212 213 # Clean up pulseaudio modules that the script created 214 [ "$unload_pulse_modules" ] && { 215 pactl unload-module "$lb_mic" 216 pactl unload-module "$lb_desk" 217 pactl unload-module "$null_sink" 218 } 219 220 printf '\n%s\n' "$filename" 221} 222 223$action 224 225# Run post scripts 226# Scripts in the directory `$SCR_CFG_DIR/scripts` will 227# take in `$action` as `$1` and `$filename` as `$2`. 228# Sample scripts can be found in my dotfiles at: 229# https://github.com/yemouu/setup/blob/master/home/cfg/scr/scripts 230for i in "$SCR_CFG_DIR/scripts/"* 231do 232 [ -x "$i" ] && { 233 printf '%s\n' "# $i --- START" >> "$SCR_CACHE_DIR/scripts.log" 234 $i "$action" "$filename" > "$SCR_CACHE_DIR/scripts.log" 2>&1 235 printf '%s\n' "# $i --- END" >> "$SCR_CACHE_DIR/scripts.log" 236 } 237done