From 0a19796698bfaf42f94cf7a2580422564fbf70a1 Mon Sep 17 00:00:00 2001 From: Sebastian Kiesel Date: Fri, 31 Mar 2023 01:22:50 +0200 Subject: [PATCH] add muxa-vr --- bin/muxsa-vr | 331 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 331 insertions(+) create mode 100755 bin/muxsa-vr diff --git a/bin/muxsa-vr b/bin/muxsa-vr new file mode 100755 index 0000000..bf85495 --- /dev/null +++ b/bin/muxsa-vr @@ -0,0 +1,331 @@ +#!/bin/bash + +# muxsa-vr (voice recorder) +# +# part of muxsa, https://git-nks-public.tik.uni-stuttgart.de/edu/muxsa +# +# this script waits for keystrokes, in particular the typical key sequences +# of a "wireless presenter" device, and controls audacity and geeqie, for +# convenient recording of voiceover for presentation slides. + +# MIT License +# +# Copyright (c) 2023 Sebastian Kiesel +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +# OTHER DEALINGS IN THE SOFTWARE. + +############################################################################ + +echo "This is muxsa-vr." + +show_help () { +cat < "${AUDACITY_PIPE_TO}" + else + echo "muxsa-vr: send_to_audacity: pipe ${AUDACITY_PIPE_TO}"\ + "does not exist. not sending: $1" + fi +} + +receive_from_audacity () { + while true ; do + if [ -p "${AUDACITY_PIPE_FROM}" ] ; then + timeout 10 sed 's/^/muxsa-vr: receive_from_audacity: /' \ + ${AUDACITY_PIPE_FROM} + else + echo "muxsa-vr: receive_from_audacity:"\ + "pipe ${AUDACITY_PIPE_FROM} does not exist."\ + "wait for one second" + sleep 1 + fi + done +} +receive_from_audacity & +RECEIVE_FROM_AUDACITY_PID=$! +echo "muxsa-vr: receive_from_audacity subprocess started"\ + "with PID: ${RECEIVE_FROM_AUDACITY_PID}" +trap 'kill "${RECEIVE_FROM_AUDACITY_PID}"' EXIT + + +##### + +# LABEL is assumed to be a global variable holding an integer value +set_label_text_audacity () { + local L="${LABEL:-"0"}" + local T="$(printf "%04d" ${LABEL:-"0"})" + send_to_audacity "SetLabel: Label=${L} Selected=0 Text=\"${T}\"" +} + +############################################################################ +# interation with geeqie + +send_to_geeqie () { + echo "muxsa-vr: send_to_geeqie: $1" + case "$1" in + back) + geeqie --remote --back + ;; + next) + geeqie --remote --next + ;; + *) + echo "muxsa-vr: send_to_geeqie: ignore unknown command $1" + ;; + esac +} + +############################################################################ +# main + +STATE="uninitialized" +LABEL=0 +CLIPS[0]=0 +echo "muxsa-vr started. press i to initialize or h for help." + +while true ; do + + echo "State: ${STATE} Label: ${LABEL} Clips: ${CLIPS[$LABEL]:=0}" + + ##### read one key stroke, including some special keys + read -s -n1 -p "Press key (h for help): " KEYCODE + while read -t0.001 -s -n1 MORE ; do + KEYCODE="${KEYCODE}${MORE}" + done + case "${KEYCODE}" in + $'\e[6~') + KEYCODE="PGDOWN" + ;; + $'\e[5~') + KEYCODE="PGUP" + ;; + $'\e[15~') + KEYCODE="F5" + ;; + $'\e') + KEYCODE="ESC" + ;; + esac + ##### + echo "muxsa-vr: key pressed: ${KEYCODE}" + + case "${KEYCODE}" in + 'h') + show_help + ;; + 'i') + echo "Initializing muxsa-vr and Audacity." + STATE="STOP" + LABEL=0 + CLIPS[0]=0 + send_to_audacity 'NewMonoTrack' + send_to_audacity 'NewLabelTrack' + send_to_audacity 'AddLabel' + set_label_text_audacity + send_to_audacity 'SelAllTracks' + ;; + + 'PGDOWN') + # pgdown = right big button on the wireless presenter + case "${STATE}" in + 'STOP') + send_to_audacity 'CursTrackEnd' + send_to_audacity 'Record1stChoice' + echo "START RECORDING" + STATE="RECORDING" + ;; + 'RECORDING') + send_to_audacity 'Stop' + send_to_audacity 'CursTrackEnd' + echo "STOP RECORDING" + STATE="STOP" + CLIPS[$LABEL]=$(( ${CLIPS[$LABEL]} + 1 )) + ;; + *) + echo "start/stop: invalid state ${STATE} ... ignore" + ;; + esac + ;; + + 'PGUP') + # pgup = left big button on the wireless presenter + case "${STATE}" in + 'STOP') + echo "Playback last clip" + send_to_audacity 'CursTrackEnd' + send_to_audacity 'CursPrevClipBoundary' + send_to_audacity 'Play' + send_to_audacity 'CursTrackEnd' + ;; + *) + echo "playback: invalid state ${STATE} ... ignore" + ;; + esac + ;; + + $'.') + # dot = right small button on the wireless presenter + case "${STATE}" in + 'STOP') + if [ "${CLIPS[$LABEL]}" -eq 0 ] ; then + echo "Add label: not adding a second label here" + else + echo "Adding label at end while paused" + send_to_audacity 'CursTrackEnd' + send_to_audacity 'AddLabel' + LABEL=$(( ${LABEL} + 1 )) + CLIPS[$LABEL]=0 + set_label_text_audacity + send_to_geeqie 'next' + fi + ;; + 'RECORDING') + send_to_audacity 'AddLabelPlaying' + echo "Adding label while recording" + LABEL=$(( ${LABEL} + 1 )) + CLIPS[$LABEL]=0 + send_to_geeqie 'next' + ;; + *) + echo "add label: invalid state ${STATE} ... ignore" + ;; + esac + + ;; + + 'F5'|'ESC') + # F5/Esc(alternating) = left small button on the wireless presenter + case "${STATE}" in + 'STOP') + case "${CLIPS[$LABEL]}" in + '0') + if [ "${LABEL}" -eq 0 ] ; then + echo "Delete: Nothing recorded ... ignore." + else + echo "Nothing recorded since last label." + echo "Deleting last label." + send_to_audacity 'CursTrackEnd' + send_to_audacity 'Delete' + send_to_geeqie 'back' + LABEL=$(( ${LABEL} - 1 )) + fi + ;; + '1') + echo "Deleting first clip after label." + send_to_audacity 'CursTrackEnd' + send_to_audacity 'SelPrevClipBoundaryToCursor' + send_to_audacity 'Delete' + echo "Re-install deleted label" + send_to_audacity 'AddLabel' + set_label_text_audacity + CLIPS[$LABEL]=0 + ;; + *) + echo "Deleting second or later clip after label." + send_to_audacity 'CursTrackEnd' + send_to_audacity 'SelPrevClipBoundaryToCursor' + send_to_audacity 'Delete' + CLIPS[$LABEL]=$(( ${CLIPS[$LABEL]} - 1 )) + ;; + esac + ;; + *) + echo "Delete: invalid state ${STATE} ... ignore" + ;; + esac + ;; + + + 's') + echo "Setting STATE to STOP" + STATE="STOP" + ;; + 'l') + read -p "Enter current label number: " LABEL + [ "${LABEL}" -gt 0 ] &>/dev/null || LABEL=0 + ;; + 'c') + read -p "Enter current clip number: " CLIPS[$LABEL] + [ "${CLIPS[$LABEL]}" -gt 0 ] &>/dev/null || CLIPS[$LABEL]=0 + ;; + 'u') + send_to_audacity 'Undo' + ;; + 'r') + send_to_audacity 'Redo' + ;; + 'b') + send_to_geeqie 'back' + ;; + 'n') + send_to_geeqie 'next' + ;; + *) + echo "unknown key pressed: ${KEYCODE}" + ;; + esac +done + +# End of muxsa-vr +############################################################################