acmecert: Handle older versions of the JSON library.
[utils.git] / planime
1 #!/bin/bash
2
3 isnum() {
4     grep -xq '[0-9]\+' <<<"$1"
5 }
6
7 scorefile() {
8     if [ "${1##*.}" = mkv ]; then
9         echo 10
10     elif [ "${1##*.}" = ogm ]; then
11         echo 5
12     else
13         echo 0
14     fi
15 }
16
17 findbase() {
18     if [ -r aliases ]; then
19         while read alias rest; do
20             if [ "$alias" = "$1" ]; then
21                 echo "$rest"
22                 return
23             fi
24         done <aliases
25     fi
26     echo "$1"
27 }
28
29 findfile() {
30     if [ -n "$debug" ]; then echo "finding base='$1', ep='$2', qual='$3'" >&2; fi
31     local base file tail eq eqt m matches max score
32     matches=()
33     base="$(findbase "$1")"
34     for file in "$base"*; do
35         tail="${file#"$base"}"
36         eq="${tail%.*}"
37         m=n
38         if [ "${eq%% *}" -eq "$2" ] 2>/dev/null; then
39             if [[ "$eq" == *\ * ]]; then
40                 eqt="${eq#* }"
41             else
42                 eqt=
43             fi
44             m=y
45         elif [ "${eq:0:${#2}}" = "$2" ]; then
46             eqt="${eq:${#2}}"
47             if [ "${eqt:0:1}" = " " -o -z "$eqt" ]; then
48                 eqt="${eqt# }"
49                 m=y
50             fi
51         fi
52         if [ "$m" = y ]; then
53             if [ "$eqt" = "$3" -o "$eqt" = "($3)" -o "${eqt:0:2}" = "- " ]; then
54                 matches=("${matches[@]}" "$file")
55             fi
56         fi
57     done
58     if [ ${#matches[@]} -lt 1 ]; then return 1; fi
59     max=
60     for m in "${matches[@]}"; do
61         score="$(scorefile "$m")"
62         if [ -n "$debug" ]; then echo "found \`$m': score $score" >&2; fi
63         if [ -z "$max" ] || [ "$score" -gt "$max" ]; then
64             max="$score"
65             file="$m"
66         fi
67     done
68     if [ -n "$debug" ]; then echo "using \`$file'" >&2; fi
69     echo "$file"
70     return 0
71 }
72
73 origargs=("$0" "$@")
74 cmdline=(mpv -fs)
75 debug=
76 log=y
77 unset pretend printfile
78
79 usage() {
80     echo "usage: planime [-fdhtCL] [-A PLAYER-ARGS... ;] [-s PAR=VAL] [--] [NAME-QUAL] [EP|.] [TYPE-QUAL]"
81 }
82
83 while getopts hdtCLA:s:fv opt; do
84     case "$opt" in
85         h)
86             usage
87             exit 0
88             ;;
89         d)
90             debug=y
91             ;;
92         t)
93             cmdline=("${cmdline[@]}" -profile tv)
94             DISPLAY=:1
95             chwp=y
96             ;;
97         C)
98             pretend=y
99             ;;
100         L)
101             log=
102             ;;
103         A)
104             while [ "$OPTARG" != \; ]; do
105                 cmdline+=("$OPTARG")
106                 if [ "$OPTIND" -gt $# ]; then
107                     echo "planime: unterminated argument list" >&2
108                     exit 1
109                 fi
110                 OPTARG="${!OPTIND}"
111                 let OPTIND++
112             done
113             ;;
114         s)
115             p="$(expr index "$OPTARG" =)"
116             if [ "$p" -le 0 ]; then
117                 usage >&2
118                 exit 1
119             fi
120             savepar="${OPTARG:0:p}"
121             let p++
122             saveval="${OPTARG:p}"
123             ;;
124         f)
125             printfile=y
126             ;;
127         v)
128             cmdline+=(-v)
129             ;;
130         *)
131             usage >&2
132             exit 1
133             ;;
134     esac
135 done
136 shift $((OPTIND - 1))
137
138 dirbase="$(basename "$(pwd)")"
139 base=.
140 nextep=n
141 file=
142 tqual=
143 if [ $# -eq 0 ]; then
144     nextep=y
145 elif [ $# -eq 1 ]; then
146     if [ -r "$1" ]; then
147         file="$1"
148     else
149         base=
150         ep="$1"
151     fi
152 elif [ $# -eq 2 ]; then
153     if findfile "$dirbase - " "$1" "$2" >/dev/null; then
154         base=""
155         ep="$1"
156         tqual="$2"
157     else
158         base="$1"
159         ep="$2"
160     fi
161 else
162     base="$1"
163     ep="$2"
164     tqual="$3"
165 fi
166 if [ "$ep" = . ]; then nextep=y; fi
167 if [ "$nextep" = y -a -r nextep ]; then
168     ep="$(<nextep)"
169     if ! isnum "$ep"; then
170         echo "planime: nextep is non-numeric" >&2
171         exit 1
172     fi
173 fi
174 if [ -z "$file" ]; then
175     if [ "$base" = . ]; then
176         if [ -r curser ]; then
177             curser="$(<curser)"
178         else
179             curser=
180         fi
181     else
182         curser="$(findbase "$base")"
183     fi
184     if [ -n "$curser" ]; then
185         file="$(findfile "$dirbase $curser - " "$ep" "$tqual")" || \
186             file="$(findfile "$curser - " "$ep" "$tqual")"
187     else
188         file="$(findfile "$dirbase - " "$ep" "$tqual")"
189     fi
190 fi
191
192 if [ -z "$file" -o ! -r "$file" ]; then
193     echo "planime: no matching file found" >&2
194     exit 1
195 fi
196
197 case "${file##*.}" in
198     ogm)
199         aid=1
200         sid=0
201         ;;
202     mkv)
203         alang=jpn
204         slang=eng
205         ;;
206 esac
207
208 ifile=".${file}.info"
209
210 if [ -n "$savepar" ]; then
211     if [ -r "$ifile" ]; then
212         egrep -v "^${savepar} " "$ifile" >"$ifile.new"
213         mv -f "$ifile.new" "$ifile"
214     fi
215     echo "$savepar $saveval" >>"$ifile"
216     exit 0
217 fi
218
219 unset delay
220
221 if [ -r "$ifile" ]; then
222     exec 3<&0
223     exec 0<"$ifile"
224     while read par arg; do
225         if [ "$par" = delay ]; then
226             cmdline=("${cmdline[@]}" -delay "$arg")
227         elif [ "$par" = aspect ]; then
228             cmdline=("${cmdline[@]}" -aspect "$arg")
229         elif [ "$par" = volmod ]; then
230             cmdline=("${cmdline[@]}" -af volume="$arg")
231         elif [ "$par" = alang ]; then
232             unset alang aid
233             alang="$arg"
234         elif [ "$par" = aid ]; then
235             unset alang aid
236             aid="$arg"
237         elif [ "$par" = slang ]; then
238             unset slang sid
239             slang="$arg"
240         elif [ "$par" = sid ]; then
241             unset slang sid
242             sid="$arg"
243         fi
244     done
245     exec 0<&3
246     exec 3<&-
247 fi
248
249 if [ -n "$alang" ]; then
250     cmdline=("${cmdline[@]}" -alang "$alang")
251 elif [ -n "$aid" ]; then
252     cmdline=("${cmdline[@]}" -aid "$((aid + 1))")
253 fi
254 if [ -n "$slang" ]; then
255     cmdline=("${cmdline[@]}" -slang "$slang")
256 elif [ -n "$sid" ]; then
257     cmdline=("${cmdline[@]}" -sid "$((sid + 1))")
258 fi
259
260 if [ -n "$pretend" ]; then
261     echo "${cmdline[@]}" "$file"
262 elif [ -n "$printfile" ]; then
263     echo "$file"
264 else
265     if [ "$chwp" = y ]; then (sleep 2; randomwp) & fi
266     if [ "$log" = y ]; then
267         if [ -d $HOME/.anime ]; then
268             echo "$(date) $(basename "$file")" >>$HOME/.anime/plog
269         fi
270     fi
271     "${cmdline[@]}" "$file"
272     
273     if [ "$nextep" = y ]; then
274         echo "0. Save and continue (or Space)"
275         echo "1. Continue without saving"
276         echo "2. Save and exit (or Enter)"
277         echo "3. Exit without saving (or any key)"
278         IFS= read -sn1 c
279         save=n
280         cont=n
281         case "$c" in
282             0|" ")
283                 save=y
284                 cont=y
285                 ;;
286             1)
287                 cont=y
288                 ;;
289             2|"")
290                 save=y
291                 ;;
292         esac
293         if [ "$save" = y ]; then
294             let ep++
295             echo "$ep" >nextep
296         fi
297         if [ "$cont" = y ]; then
298             exec "${origargs[@]}"
299         else
300             echo "nextep is $ep"
301         fi
302     fi
303 fi