X-Git-Url: https://git.madduck.net/code/pulserecorder.git/blobdiff_plain/fb1414bb84493438c4404c07172bb15da1d96a7c..refs/heads/master:/pulserecorder?ds=inline diff --git a/pulserecorder b/pulserecorder index 65a40ce..5dad254 100755 --- a/pulserecorder +++ b/pulserecorder @@ -15,11 +15,22 @@ # # The third form waits for a new sink-input to appear, and will record that. # -# Copyright © 2020 martin f. krafft +# Copyright © 2020–2021 martin f. krafft # Released under the teams of the Artistic Licence 2.0 # set -eu +cleanup_commands= +cleanup() { + set +e + eval $cleanup_commands 2>/dev/null + trap - 1 2 3 4 5 6 7 8 10 11 12 13 14 15 +} +trap cleanup 1 2 3 4 5 6 7 8 10 11 12 13 14 15 +cleanup_hook() { + cleanup_commands="$@${cleanup_commands:+; $cleanup_commands}" +} + if [ -z "${TMPDIR:-}" ]; then TMPDIR=/tmp fi @@ -31,17 +42,12 @@ for i in $LOGNAME volatile; do done export TMPDIR TMPDIR=$(mktemp -dp "$TMPDIR" parec.XXXXXXXXXX) +cleanup_hook rm -r $TMPDIR -cleanup_commands="rm -r $TMPDIR" -cleanup() { - set +e - eval $cleanup_commands 2>/dev/null - trap - 1 2 3 4 5 6 7 8 10 11 12 13 14 15 -} -trap cleanup 1 2 3 4 5 6 7 8 10 11 12 13 14 15 -cleanup_hook() { - cleanup_commands="$@${cleanup_commands:+; $cleanup_commands}" -} +if command -v systemd-inhibit >/dev/null; then + systemd-inhibit --who=pulserecorder --why=recording sleep 99d 2>/dev/null & + cleanup_hook kill $! +fi state= outfile= index= clobber=0 for arg in "$@"; do @@ -66,7 +72,7 @@ pa_wait_for_event() { type="${1:-*}" event="${2:-*}" id="${3:-*}" pa_subscribe | ( read pid - #echo >&2 pa_subscribe started with PID $pid + #echo >&2 pa_subscribe started with PID $pid, waiting for $type/$event/$id while read lead xevent on xtype xid; do xid=${xid#\#} #echo >&2 "pa_subscribe: $xtype/$xevent/$xid ($type/$event/$id)" @@ -85,6 +91,28 @@ pa_get_next_index() { } } +uuidgen() { + hascmd() { command -v "$@" >/dev/null;} + if hascmd uuid; then uuid + elif hascmd uuidgen; then uuidgen + elif hascmd python3; then + python3 -c 'import uuid; print(uuid.uuid1())' + elif hascmd python; then + python -c 'import uuid; print(uuid.uuid1())' + else + dd if=/dev/urandom bs=16 count=1 status=none | base64 + fi +} + +if [ -z "$outfile" ]; then + uuid=$(uuidgen) + outfile="${uuid}.ogg" +fi + +if [ -f "$outfile" ] && [ $clobber -eq 0 ]; then + echo >&2 "E: file exists, and -f not given: $outfile" + exit 1 +fi case "$index" in (last) @@ -111,29 +139,7 @@ if [ -z "$index" ]; then exit 1 fi -uuidgen() { - hascmd() { command -v "$@" >/dev/null;} - if hascmd uuid; then uuid - elif hascmd uuidgen; then uuidgen - elif hascmd python3; then - python3 -c 'import uuid; print(uuid.uuid1())' - elif hascmd python; then - python -c 'import uuid; print(uuid.uuid1())' - else - dd if=/dev/urandom bs=16 count=1 status=none | base64 - fi -} - -uuid=$(uuidgen) - -[ -n "$outfile" ] || outfile="${uuid}.ogg" - -if [ -f "$outfile" ] && [ $clobber -eq 0 ]; then - echo >&2 "E: file exists, and -f not given: $outfile" - exit 1 -fi - -devname="record-to-file-${uuid}" +devname="record-to-file-$(echo -n ${outfile%.*} | tr -c '[:alnum:]' '_')" echo >&2 "Recording source $index to $outfile …" @@ -146,13 +152,23 @@ load_module() { } move_source_to_sink() { - local c; + local c d; c=$(pactl list short sink-inputs | sed -rne "s,^${1}[[:space:]]+([[:digit:]]+).+,\1,p") + d="$(pactl list short sinks | sed -rne "s,^${c}[[:space:]]+([^[:space:]]+).+,\1,p")" + case "$d" in + (record-to-file-*) + # Never restore to a record-to-file destination, or it could botch + # another recording + c="@DEFAULT_SINK@" + ;; + (*) :;; + esac + echo >&2 "Moving input $1 to sink $2 (restore to $c) …" cleanup_hook pactl move-sink-input $1 $c pactl move-sink-input $1 $2 } -if false; then +if [ -n "${PAREC_PIPE:-}" ]; then # This would be great, but it does not work. For instance, trying this on # audible meant that audible would play at maximum speed (3h played in 3 # minutes), but the result would be full of skips, making me think that @@ -161,8 +177,11 @@ if false; then load_module module-pipe-sink "$devname" "$devname" file="$TMPDIR/outfifo" move_source_to_sink $index "$devname" - oggenc --raw -q5 -o "$outfile" "$TMPDIR/outfifo" || : - #pv -pterb "$TMPDIR/outfifo" > $TMPDIR/outfile.wav || : + #oggenc --raw -q5 -o "$outfile" "$TMPDIR/outfifo" || : + pv -pterb "$TMPDIR/outfifo" > $TMPDIR/outfile.wav & + pid=$! + pa_wait_for_event sink-input remove $index >/dev/null + kill $pid else # More traditional approach, which just takes 1:1 time.