version added
[BABOOSHKA.TV] / playlist.sh
1 #!/bin/bash
2
3 if [ $# -lt 1 ]; then
4
5         echo "IM Playlist Player (ver. 0.1.1). 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"
8
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"
15         echo "-s                stop after"
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"
20         exit 1
21 fi
22
23 # BABOOSHKA_HOME=/home/pi       # assigned in start.babooshka.sh
24
25 SAVE_PATH=$BABOOSHKA_HOME
26 DBUS_CTRL_FILE=/tmp/dbuscontrol_command
27 VOLUME=0
28 LEDS_CONTROL=/tmp/bbshk_leds
29 CNT=1
30
31 # ------------------- parse commandline ----------------------
32
33 parserCnt=0
34
35 while [ "$#" -gt 0 ] && [ "$parserCnt" -lt 20 ] ; do
36         case "$1" in
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)
46
47                 -*) echo "unknown option: $1" >&2; exit 1;;
48 #               *) handle_argument "$1"; shift 1;;
49                 *) sleep 0; shift 1;;
50         esac
51         parserCnt=$(( $parserCnt + 1 ))
52 done
53
54 if [ "$SUBTITLES" != "" ]; then SUBTITLES_SET="-t $SUBTITLES"; fi
55
56 if [ -z "$PLAYLIST" ]; then
57         echo "Playlist is not assigned. Please use -p option."
58         exit 0
59 fi
60
61 # -------------------------------------------------------------------
62
63 killCCONTROL() {        # function called by trap (Ctrl-C handler)
64
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..."
70         exit 0
71 }
72
73 trap 'killCCONTROL' 2
74
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)
79 #               echo -n "."
80                 sleep 1
81         done
82 #       echo ''
83 }
84
85 waiting_for_player_start() {
86         echo "waiting for playback starting... "; 
87         while ! ./dbuscontrol.sh status 1>/dev/null 2>/dev/null ; do 
88 #               echo -n "+"
89                 sleep 1
90         done
91 #       echo ''
92 }
93
94 # check for unwatched / not completed video and turn RED LED on
95
96 check_video_complete(){
97
98         if grep -v -P "\tPLAY|\tWATCHED" "$1" | grep "^[^#;]" >/dev/null ; then 
99
100                 lastLedState=$(cat $LEDS_CONTROL)
101                 currentPos=$(cat $SAVE_PATH/currentpos)
102
103                 # make new video current (if previous one has not been paused and all videos has been watched)
104
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"
109                 fi 
110
111 #               echo 'NEWVIDEO'
112                 echo "NEWVIDEO" > "$LEDS_CONTROL"
113         else 
114                 if grep -P "\tPLAY" "$1" | grep "^[^#;]" >/dev/null ; then
115 #                       echo 'VIDEOSTARTED'
116                         echo "VIDEOSTARTED" > "$LEDS_CONTROL"
117                 else 
118 #                       echo 'VIDEOCOMPLETE'
119                         echo "VIDEOCOMPLETE" > "$LEDS_CONTROL"
120                 fi
121         fi
122 }
123
124 # check_video_complete "$PLAYLIST"
125
126 # background checking for external playlist changes
127
128 {       
129         while [ 1 ]; do 
130                 check_video_complete "$PLAYLIST"
131                 sleep 10
132         done
133 } &
134 PLAYLIST_CHANGE_PID=$!
135
136 # ----------------------- crash / reboot handler --------------------
137
138 touch "$DBUS_CTRL_FILE"
139 touch $SAVE_PATH/currenttrack
140 touch $SAVE_PATH/currentpos
141
142 currentTrack=$(cat $SAVE_PATH/currenttrack)
143 currentPos=$(cat $SAVE_PATH/currentpos)
144
145 echo "Saved track: $currentPos, $currentTrack"
146
147 if [ "$START_FROM" == '' ]; then 
148
149         if [ "$currentTrack" != '' ]; then 
150
151                 currentTrackNum=$( cat $PLAYLIST | grep "^[^#;]" | grep -Fn "$currentTrack" | cut -f1 -d: )     # looking for current track in playlist and return number of it
152
153                 if [ "$currentTrackNum" != "" ]; then   # playlist has been updated
154                         CNT=$currentTrackNum; 
155                         echo "Current track number: $CNT"
156                 fi
157
158                 if [ "$currentTrackNum" != '' ] && [ "$currentPos" != '' ]; then 
159
160                         currentPos=$(( $currentPos / 60 ))
161                         echo "restarting from $currentPos min : $CNT : $currentTrack"
162                         POSITION_SET="-s $currentPos"
163
164                         {
165                                 echo "waiting for player start.."
166                                 waiting_for_player_start
167                                 
168                                 # trick to make still picture visible 
169
170                                 ./dbuscontrol.sh pause 
171                                 echo "paused"
172                                 sleep 10
173                                 ./dbuscontrol.sh pause 
174                                 sleep 0.1
175                                 ./dbuscontrol.sh pause
176
177                         } &
178                         WAIT1_PID=$!
179                 else 
180                         waiting_for_press_play
181                 fi
182         else 
183                 waiting_for_press_play
184         fi 
185 else 
186         CNT=$START_FROM
187         waiting_for_press_play
188 fi
189
190 # --------------------- main loop start -----------------------------
191
192 while [ 1 ]; do
193
194         totalLines=$(cat $PLAYLIST | grep "^[^#;]" | wc -l)
195         playlistLine=$(cat $PLAYLIST | grep "^[^#;]" | head -$CNT | tail -1)
196
197         echo "playlistLine: $CNT, $playlistLine"
198
199         if echo $playlistLine | grep "^[^#;]" >/dev/null; then 
200
201                 fileState=$(echo "$playlistLine" | awk '{split($0,a,"\t"); print a[5]}')
202
203                 # show splash 
204
205                 case "$fileState" in 
206                         "PLAY") 
207                                 sudo fbi -T 3 -d /dev/fb0 --once -noverbose splash_loading_pause.png &>/dev/null
208                         ;;
209                         '')
210                                 sudo fbi -T 3 -d /dev/fb0 --once -noverbose splash_loading_new.png &>/dev/null
211                         ;;
212                         *) 
213                                 sudo fbi -T 3 -d /dev/fb0 --once -noverbose splash_loading.png &>/dev/null
214                         ;;
215                 esac
216
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]}')
220
221                 echo "Loading: $CNT/$totalLines : $file"
222                 echo "Commentary: $fileComment"
223                 echo "Additional options: $POSITION_SET $fileOptions"
224
225                 echo $file > $SAVE_PATH/currenttrack
226
227                 if [ "$PREF_LANG" != "" ]; then
228                         {
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 }' )
233
234                                 if [ "$prefAudioTrackNum" != "" ]; then 
235                                         i=1
236                                         while [ "$i" -lt "$prefAudioTrackNum" ] ; do
237                                                 i=$(( $i + 1 ))
238                                                 $BABOOSHKA_HOME/dbuscontrol.sh audiop
239                                         done 
240                                         targetTrackName=$(echo "$audioTracks" | head -$prefAudioTrackNum | tail -1 )
241                                         echo "audio track $prefAudioTrackNum : $targetTrackName"
242                                 else 
243                                         echo "probably single audiotrack detected:"
244                                         echo "$audioTracks"
245                                 fi 
246                         } &
247                         WAIT2_PID=$!
248                 fi
249
250                 {
251                         waiting_for_player_start
252                         sudo fbi -T 3 -d /dev/fb0 --once -noverbose splash.png &>/dev/null
253                 } &
254                 WAIT3_PID=$!
255
256                 # set playlist marker before playing
257
258                 if cat "$PLAYLIST" | grep "^[^#;]" | grep "$file" | grep -v -P "\tWATCHED" >/dev/null; then 
259
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"
263                 fi 
264
265                 # playing
266
267                 echo "VIDEOSTARTED" > "$LEDS_CONTROL"
268                 echo 'playing...'
269
270                 playerOutput=$(./playmovie.sh -i "$file" -v $VOLUME -a 1 -m "$VIDEOMODE" $POSITION_SET $SUBTITLES_SET -r letterbox $fileOptions)
271
272                 # set playlist markers after playing
273
274                 if cat "$PLAYLIST" | grep "^[^#;]" | grep "$file" | grep -v -P "\tWATCHED" >/dev/null; then 
275
276                         playbackPos=$(echo "$playerOutput" | grep "Playback duration" | awk -F: '{print $2}' | xargs)   # whether it was stopped and what time
277
278                         ct=$(echo $playbackPos | awk -F'/' '{print $1}')
279                         tt=$(echo $playbackPos | awk -F'/' '{print $2}')
280
281                         if [ "$ct" -ge "$tt" ]; then watched='WATCHED'; else watched=''; fi
282
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"
285
286                         echo "playlist line updated: $newPlaylistLine"
287                 fi 
288
289                 # check for unwatched / not completed video and turn RED LED on
290                 
291                 check_video_complete "$PLAYLIST"
292
293                 : > $SAVE_PATH/currentpos
294                 POSITION_SET=''
295
296                 DBUS_COMMAND=$(cat "$DBUS_CTRL_FILE")
297
298                 if [ "$PLAYSINGLE" != "" ] && [ "$DBUS_COMMAND" != "NEXT" ]; then 
299                         echo "play single STOP"
300                         echo "STOP" > "$DBUS_CTRL_FILE";
301                         DBUS_COMMAND="STOP"
302                         CNT=$(( $CNT + 1 ));
303                 fi
304
305         else 
306 #               if [ "$DBUS_COMMAND" == "PLAY" ]; then  CNT=$(( $CNT + 1 )); fi 
307                 DBUS_COMMAND="NEXT"
308         fi 
309
310         # check playlist for finishing
311
312         echo "DBus command: $DBUS_COMMAND"
313
314         totalLines=$(cat $PLAYLIST | grep "^[^#;]" | wc -l)
315
316         if [ "$PLAYLISTONCE" != '' ] && [ "$CNT" -ge "$totalLines" ] && [ "$DBUS_COMMAND" != "PREV" ]; then 
317                 echo "play once STOP"
318                 echo "STOP" > "$DBUS_CTRL_FILE"
319                 DBUS_COMMAND="STOP"
320                 CNT=$(( $CNT + 1 ));
321         fi
322
323         # handle and pass dbus command (original or assigned forcibly)
324
325         echo "DBus command: $DBUS_COMMAND"
326
327         if [ "$DBUS_COMMAND" != "" ]; then 
328                 case "$DBUS_COMMAND" in
329                         "NEXT")
330                                 CNT=$(( $CNT + 1 ));
331                         ;;
332                         "STOP")
333                                 waiting_for_press_play
334                                 
335                                 # check for possibly new video in playlist
336
337                                 currentLEDState=$(cat $LEDS_CONTROL)
338
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
342
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"
346                                 fi 
347                                 
348                         ;;
349                         "PREV")
350                                 CNT=$(( $CNT - 1 ));
351                         ;;
352                 esac
353                 : > "$DBUS_CTRL_FILE"
354         else 
355                 CNT=$(( $CNT + 1 ))
356         fi 
357
358         # playlist next line counter
359
360         if [ "$CNT" -gt "$totalLines" ]; then CNT=1; fi
361         if [ "$CNT" -lt "1" ]; then CNT=$totalLines; fi
362 done 
363
364 exit 0
365
Contact me: dev (at) shalnoff (dot) com
PGP fingerprint: A6B8 3B23 6013 F18A 0C71 198B 83D8 C64D 917A 5717