5 echo "IM Playlist Player. Created for BABOOSHKA.TV™ project (https://babooshka.tv)"
6 echo "Copyright © 2020 Dmitry Shalnov [interplaymedium.org]"
7 echo "Licensed under the Apache License, Version 2.0"
9 echo "Usage: $0 -p <playlist> [options]"
10 echo "-v <arg> volume amp in dB>"
11 echo "-f <arg> play from Nth file in the playlist"
12 echo "-a <erg> set audio track"
13 echo "-m <arg> video mode in WxH format"
14 echo "-t <arg> subtitle track number"
16 echo "-o play list once (make sence if you're not using -s option)"
17 echo "Dependences: omxplayer, ttf-freefont"
18 echo "Playlist format (using TAB delimiter): <file with path (no escapes)> [comment] [additional options] [position] [state]"
19 echo "Use ';' symbol to comment playlist lines if needed"
23 # BABOOSHKA_HOME=/home/pi # assigned in start.babooshka.sh
25 SAVE_PATH=$BABOOSHKA_HOME
26 DBUS_CTRL_FILE=/tmp/dbuscontrol_command
28 LEDS_CONTROL=/tmp/bbshk_leds
31 # ------------------- parse commandline ----------------------
35 while [ "$#" -gt 0 ] && [ "$parserCnt" -lt 20 ] ; do
37 # -i) MEDIAPATH="$2"; shift 2;; # media file
38 -p) PLAYLIST="$2"; shift 2;; # media file
39 -v) VOLUME="$2"; shift 2;; # volume amp
40 -f) START_FROM="$2"; shift 2;; # from Nth file, 0 is random order
41 -a) PREF_LANG="$2"; shift 2;; # audio track prefered language pattern, e.g. ":ру|:ru"
42 -m) VIDEOMODE="$2"; shift 2;; # video mode
43 -t) SUBTITLES="$2"; shift 2;; # volume amp
44 -s) PLAYSINGLE=1; shift 1;; # play file by file with stops (no parameter required)
45 -o) PLAYLISTONCE=1; shift 1;; # play list once (no parameter required)
47 -*) echo "unknown option: $1" >&2; exit 1;;
48 # *) handle_argument "$1"; shift 1;;
51 parserCnt=$(( $parserCnt + 1 ))
54 if [ "$SUBTITLES" != "" ]; then SUBTITLES_SET="-t $SUBTITLES"; fi
56 if [ -z "$PLAYLIST" ]; then
57 echo "Playlist is not assigned. Please use -p option."
61 # -------------------------------------------------------------------
63 killCCONTROL() { # function called by trap (Ctrl-C handler)
65 kill -9 $WAIT1_PID 2>/dev/null
66 kill -9 $WAIT2_PID 2>/dev/null
67 kill -9 $WAIT3_PID 2>/dev/null
68 kill -9 $PLAYLIST_CHANGE_PID 2>/dev/null
69 echo "Have a nice day..."
75 waiting_for_press_play() {
76 echo "waiting for PLAY button press... ";
77 while [ "$DBUS_COMMAND" != "PLAY" ]; do
78 DBUS_COMMAND=$(cat $DBUS_CTRL_FILE)
85 waiting_for_player_start() {
86 echo "waiting for playback starting... ";
87 while ! ./dbuscontrol.sh status 1>/dev/null 2>/dev/null ; do
94 # check for unwatched / not completed video and turn RED LED on
96 check_video_complete(){
98 if grep -v -P "\tPLAY|\tWATCHED" "$1" | grep "^[^#;]" >/dev/null ; then
100 lastLedState=$(cat $LEDS_CONTROL)
101 currentPos=$(cat $SAVE_PATH/currentpos)
103 # make new video current (if previous one has not been paused and all videos has been watched)
105 if [ "$lastLedState" == "VIDEOCOMPLETE" ] && [ "$currentPos" == '' ]; then
106 newVideo=$(grep -v -P "\tPLAY|\tWATCHED" "$1" | grep "^[^#;]" | head -1 | awk '{split($0,a,"\t"); print a[1]}')
107 echo $newVideo > $SAVE_PATH/currenttrack
108 echo "Playlist changed: $newVideo"
112 echo "NEWVIDEO" > "$LEDS_CONTROL"
114 if grep -P "\tPLAY" "$1" | grep "^[^#;]" >/dev/null ; then
115 # echo 'VIDEOSTARTED'
116 echo "VIDEOSTARTED" > "$LEDS_CONTROL"
118 # echo 'VIDEOCOMPLETE'
119 echo "VIDEOCOMPLETE" > "$LEDS_CONTROL"
124 # check_video_complete "$PLAYLIST"
126 # background checking for external playlist changes
130 check_video_complete "$PLAYLIST"
134 PLAYLIST_CHANGE_PID=$!
136 # ----------------------- crash / reboot handler --------------------
138 touch "$DBUS_CTRL_FILE"
139 touch $SAVE_PATH/currenttrack
140 touch $SAVE_PATH/currentpos
142 currentTrack=$(cat $SAVE_PATH/currenttrack)
143 currentPos=$(cat $SAVE_PATH/currentpos)
145 echo "Saved track: $currentPos, $currentTrack"
147 if [ "$START_FROM" == '' ]; then
149 if [ "$currentTrack" != '' ]; then
151 currentTrackNum=$( cat $PLAYLIST | grep "^[^#;]" | grep -Fn "$currentTrack" | cut -f1 -d: ) # looking for current track in playlist and return number of it
153 if [ "$currentTrackNum" != "" ]; then # playlist has been updated
154 CNT=$currentTrackNum;
155 echo "Current track number: $CNT"
158 if [ "$currentTrackNum" != '' ] && [ "$currentPos" != '' ]; then
160 currentPos=$(( $currentPos / 60 ))
161 echo "restarting from $currentPos min : $CNT : $currentTrack"
162 POSITION_SET="-s $currentPos"
165 echo "waiting for player start.."
166 waiting_for_player_start
168 # trick to make still picture visible
170 ./dbuscontrol.sh pause
173 ./dbuscontrol.sh pause
175 ./dbuscontrol.sh pause
180 waiting_for_press_play
183 waiting_for_press_play
187 waiting_for_press_play
190 # --------------------- main loop start -----------------------------
194 totalLines=$(cat $PLAYLIST | grep "^[^#;]" | wc -l)
195 playlistLine=$(cat $PLAYLIST | grep "^[^#;]" | head -$CNT | tail -1)
197 echo "playlistLine: $CNT, $playlistLine"
199 if echo $playlistLine | grep "^[^#;]" >/dev/null; then
201 fileState=$(echo "$playlistLine" | awk '{split($0,a,"\t"); print a[5]}')
207 sudo fbi -T 3 -d /dev/fb0 --once -noverbose splash_loading_pause.png &>/dev/null
210 sudo fbi -T 3 -d /dev/fb0 --once -noverbose splash_loading_new.png &>/dev/null
213 sudo fbi -T 3 -d /dev/fb0 --once -noverbose splash_loading.png &>/dev/null
217 file=$(echo "$playlistLine" | awk '{split($0,a,"\t"); print a[1]}')
218 fileComment=$(echo "$playlistLine" | awk '{split($0,a,"\t"); print a[2]}')
219 fileOptions=$(echo "$playlistLine" | awk '{split($0,a,"\t"); print a[3]}')
221 echo "Loading: $CNT/$totalLines : $file"
222 echo "Commentary: $fileComment"
223 echo "Additional options: $POSITION_SET $fileOptions"
225 echo $file > $SAVE_PATH/currenttrack
227 if [ "$PREF_LANG" != "" ]; then
229 echo "prefered language (pattern): $PREF_LANG"
230 waiting_for_player_start
231 audioTracks=$( $BABOOSHKA_HOME/dbuscontrol.sh audiolist 2>/dev/null )
232 prefAudioTrackNum=$( echo "$audioTracks" | awk -v var=$PREF_LANG 'tolower($0) ~ var {print NR; exit }' )
234 if [ "$prefAudioTrackNum" != "" ]; then
236 while [ "$i" -lt "$prefAudioTrackNum" ] ; do
238 $BABOOSHKA_HOME/dbuscontrol.sh audiop
240 targetTrackName=$(echo "$audioTracks" | head -$prefAudioTrackNum | tail -1 )
241 echo "audio track $prefAudioTrackNum : $targetTrackName"
243 echo "probably single audiotrack detected:"
251 waiting_for_player_start
252 sudo fbi -T 3 -d /dev/fb0 --once -noverbose splash.png &>/dev/null
256 # set playlist marker before playing
258 if cat "$PLAYLIST" | grep "^[^#;]" | grep "$file" | grep -v -P "\tWATCHED" >/dev/null; then
260 sed -i "s|\tPLAY||g" "$PLAYLIST"
261 newPlaylistLine=$(cat "$PLAYLIST" | grep "^[^#;]" | grep "$file" | awk -F"\t" -v pbState="PLAY" '{print $1"\t"$2"\t"$3"\t"$4"\t"pbState}')
262 sed -i "s|^$file.*|${newPlaylistLine}|g" "$PLAYLIST"
267 echo "VIDEOSTARTED" > "$LEDS_CONTROL"
270 playerOutput=$(./playmovie.sh -i "$file" -v $VOLUME -a 1 -m "$VIDEOMODE" $POSITION_SET $SUBTITLES_SET -r letterbox $fileOptions)
272 # set playlist markers after playing
274 if cat "$PLAYLIST" | grep "^[^#;]" | grep "$file" | grep -v -P "\tWATCHED" >/dev/null; then
276 playbackPos=$(echo "$playerOutput" | grep "Playback duration" | awk -F: '{print $2}' | xargs) # whether it was stopped and what time
278 ct=$(echo $playbackPos | awk -F'/' '{print $1}')
279 tt=$(echo $playbackPos | awk -F'/' '{print $2}')
281 if [ "$ct" -ge "$tt" ]; then watched='WATCHED'; else watched=''; fi
283 newPlaylistLine=$(cat "$PLAYLIST" | grep "^[^#;]" | grep "$file" | awk -v pbPos="$playbackPos" -v pbState="$watched" -F"\t" '{print $1"\t"$2"\t"$3"\t"pbPos"\t"pbState}')
284 sed -i "s|^$file.*|${newPlaylistLine}|g" "$PLAYLIST"
286 echo "playlist line updated: $newPlaylistLine"
289 # check for unwatched / not completed video and turn RED LED on
291 check_video_complete "$PLAYLIST"
293 : > $SAVE_PATH/currentpos
296 DBUS_COMMAND=$(cat "$DBUS_CTRL_FILE")
298 if [ "$PLAYSINGLE" != "" ] && [ "$DBUS_COMMAND" != "NEXT" ]; then
299 echo "play single STOP"
300 echo "STOP" > "$DBUS_CTRL_FILE";
306 # if [ "$DBUS_COMMAND" == "PLAY" ]; then CNT=$(( $CNT + 1 )); fi
310 # check playlist for finishing
312 echo "DBus command: $DBUS_COMMAND"
314 totalLines=$(cat $PLAYLIST | grep "^[^#;]" | wc -l)
316 if [ "$PLAYLISTONCE" != '' ] && [ "$CNT" -ge "$totalLines" ] && [ "$DBUS_COMMAND" != "PREV" ]; then
317 echo "play once STOP"
318 echo "STOP" > "$DBUS_CTRL_FILE"
323 # handle and pass dbus command (original or assigned forcibly)
325 echo "DBus command: $DBUS_COMMAND"
327 if [ "$DBUS_COMMAND" != "" ]; then
328 case "$DBUS_COMMAND" in
333 waiting_for_press_play
335 # check for possibly new video in playlist
337 currentLEDState=$(cat $LEDS_CONTROL)
339 if [ "$currentLEDState" == "NEWVIDEO" ]; then
340 newVideo=$(grep -v -P "\tPLAY|\tWATCHED" "$PLAYLIST" | grep "^[^#;]" | head -1 | awk '{split($0,a,"\t"); print a[1]}')
341 echo $newVideo > $SAVE_PATH/currenttrack
343 CNT=$( cat "$PLAYLIST" | grep "^[^#;]" | grep -Fn "$newVideo" | cut -f1 -d: )
344 totalLines=$(cat "$PLAYLIST" | grep "^[^#;]" | wc -l)
345 echo "New track detected: $CNT, $newVideo"
353 : > "$DBUS_CTRL_FILE"
358 # playlist next line counter
360 if [ "$CNT" -gt "$totalLines" ]; then CNT=1; fi
361 if [ "$CNT" -lt "1" ]; then CNT=$totalLines; fi