software (svp2.sh)
#!/bin/bash
# Notice, must be run explicitly as "/bin/bash", not "/bin/sh",
# because advanced bash features like arrays are used.
# svp2.sh
# Sheila Video Player
#
# svp2: This is the second version of the player, which now uses
# a few keys on a regular USB computer keyboard instead of the custom
# switches going into Raspberry Pi GPIO inputs. The switch inputs can
# still be provided by custom hardware, but by exploiting a regular keyboard
# interface, the system can run on any Linux host, instead of requiring
# a Raspberry Pi or similar unit with available GPIO inputs.
# You can specify the BASEDIR on cmdline, which should contain the
# subdirectories videos and images (mainly for testing/development).
# Otherwise, /mnt is used (which is expected to be a user-supplied
# USB data stick; see example fstab). There's no error handling if
# the directories or expected files don't exist.
if [ -n "${1}" ]; then
BASEDIR="${1}"
else
BASEDIR="/mnt" # externally-supplied USB data stick
fi
# With a second cmdline param, you can shorten/adjust the startup delay
# (possibly to 0), again mainly for development.
SLEEPTIME=10
if [ -n "${2}" ]; then
SLEEPTIME="${2}"
fi
# Note that videos must have the suffix .mpg, and images must have the
# suffix .jpg, even if they are not really those filetypes.
# The video and image player programs can probably handle many other
# filetypes, but this naming inflexibility makes string processing simpler.
VID_LOCATION="${BASEDIR}/videos"
VID_SUFFIX='.mpg'
IMG_LOCATION="${BASEDIR}/images"
IMG_SUFFIX='.jpg'
IMG_NOTFOUND='notfound.jpg'
#VID_CMD='mpv --fs --ontop --no-resume-playback --audio-device=alsa/hdmi:CARD=vc4hdmi,DEV=0'
#VID_CMD='mpv --fs --ontop --no-resume-playback --no-terminal'
VID_CMD='mpv --fs --ontop --no-resume-playback --vo=vaapi,drm,'
IMG_CMD='fim -N -q'
exec 2> /dev/null
# Find the list of video filenames and store in array VID[], then create
# the associated cover image filenames in array IMG[]. If one of the
# video files does not have an associated cover image, then the
# IMG_NOTFOUND image is displayed instead.
N=0
for F in `ls -1 ${VID_LOCATION}`; do
BN=`basename ${F} ${VID_SUFFIX}`
VID[${N}]="${VID_LOCATION}/${BN}${VID_SUFFIX}"
I="${IMG_LOCATION}/${BN}${IMG_SUFFIX}"
IMG[${N}]="${I}"
if [ ! -r "${I}" ]; then
echo "didn't find image file ${I}"
IMG[${N}]="${IMG_LOCATION}/${IMG_NOTFOUND}"
fi
N=`expr $N + 1`
done
TOP=`expr $N - 1`
echo "found $N videos"
# Delay for 10 seconds after startup before trying to display anything.
# This is a kluge (obviously). The .service file has the
# "WantedBy=multi-user.target" line, which is supposed to pause activity
# until the system is ready, but this doesn't work. Maybe I should be using
# a different .target? Anyway, without the delay here, the first image
# does not get displayed, instead there is just a mess of console text on
# the screen until the first button is pressed, because the initial image
# display occurred before the graphics system was ready.
echo "waiting for video system to initialize..."
sleep "${SLEEPTIME}"
echo
echo "OK, let's try it"
# This is the main running loop. Initially, the first cover image is
# displayed. If forward or back arrows are hit, then the image changes
# accordingly. When the play button is hit, the corresponding video
# for the cover image currently onscreen is played. Any button hits
# during video playback will terminate the playback and return to the
# cover images. (There's no pause/resume capability: videos always
# play from the start until finished or interrupted, because that's
# how Sheila likes it.)
SEL=0
result=0
playing=0
img_active=0
while true; do
if [ ${playing} -eq 0 ]; then
if [ ${img_active} -eq 0 ]; then
( ${IMG_CMD} ${IMG[${SEL}]} ) &
ourpid=$!
img_active=1
fi
fi
stty -echo -icanon time 0 min 0
while true; do
result=0
key=$( dd bs=1 count=1 2> /dev/null; printf "." )
key=${key%.}
case $key in
1) result=1 ;;
2) result=2 ;;
q) result=2 ;;
3) result=3 ;;
esac
if [ ${result} -eq 1 ]; then SEL=`expr $SEL - 1`; break;
elif [ ${result} -eq 2 ]; then break;
elif [ ${result} -eq 3 ]; then SEL=`expr $SEL + 1`; break;
fi
if [ ${playing} -eq 1 ]; then
if kill -0 ${vid_pid}; then
# video is still actually playing
playing=1
else
# video has ended
playing=0
break
fi
fi
done
stty sane
if [ ${SEL} -ge ${N} ]; then
SEL=0
fi
if [ ${SEL} -lt 0 ]; then
SEL=${TOP}
fi
if [ ${img_active} -eq 1 ]; then
kill ${ourpid}
img_active=0
fi
if [ ${result} -eq 2 ]; then
if [ ${playing} -eq 0 ]; then
playing=1
( ${VID_CMD} ${VID[${SEL}]} ) &
vid_pid=$!
else
playing=0
kill ${vid_pid}
fi
else
if [ ${playing} -eq 1 ]; then
playing=0
kill ${vid_pid}
fi
fi
done
exit 0
exit 0
exit 0
## Thanks to "cfajohnson" on unix.com.
#
#stty -echo -icanon time 0 min 0
#while :
#do
# key=$( dd bs=1 count=1 2> /dev/null; printf "." )
# key=${key%.}
# case $key in
# q) break ;;
# ?) printf "%d\n" "'$key" ;;
# esac
#done
#stty sane
# Thanks to Stuart P. Bentley on stackoverflow.com.
#
#You can write a function to close each of Bash's 10 inheritable file descriptors:
#
#fdcloexec () {
# "$@" 0>&- 1>&- 2>&- 3>&- 4>&- 5>&- 6>&- 7>&- 8>&- 9>&-
#}
#
#Then you would call fdcloexec your command here to execute your command without inheriting file descriptors.
#
Comments
Post a Comment