Add resume support in do_getalbumart()
[abcde.git] / examples / autorip.sh
1 #!/bin/bash
2 # TODO:
3 #       Add paranoia.
4 #       Fix logger messages.
5 #       Add periodic/startup file/directory checks.
6 #       Auto check of cd drive perms.
7
8 echo "Autorip 0.1.3 started."
9
10 # Set script local variables
11
12 # FREEMIN
13 # The minimum free space to have on the local TMP directory.
14 FREEMIN="750"
15
16 # TIMEOUT
17 # The timeout, in seconds (approx), for the cd-tray to be sucked back 
18 # in if it's not in already, this isn't exact, as a cycle is a bit more
19 # then a second, but it comes out to about 3 hours.
20 TIMEOUT=21600
21
22
23 # CDROM
24 # The cd-rom device to be used.
25 CDROM="/dev/cdroms/cdrom1"
26
27 # BASE
28 # The folder to be used for all of the actions
29 BASE="`pwd`"
30
31 # DONE
32 # The destination of the encoded files.
33 DONE="$BASE/done"
34
35 # TMP
36 # Defaukt temporary directory.
37 TMP="$BASE/tmp"
38
39 # REMTEMP
40 # Remote temporary directory. (currently unused)
41 REMTEMP="$BASE/remtmp"
42
43 # LOCTEMP
44 # Local temporary directory.
45 LOCTEMP="$BASE/tmp"
46
47 # LOGDEST
48 # The syslog facility to use for logging purposes.
49 LOGDEST="local3"
50
51
52 # Oher variables (Do not set)
53
54 # LASTSTART - Last CD in the drive that was encoded.
55 # LASTDONE - Last CD that was finished encoding.
56 # TIME   - Approximately how many seconds have passed without having a cd in the drive.
57 # CURRCD - This variable obtains the discid of whatever's in the cd drive.
58 # REENC  - The disc-id of an already encoded disc put into the drive.
59 # PROCESS - A short feild of the DISCID that's used for keeping track of running encodes.
60 # PROCDIR - The working directory of a process.
61 # DISCNAME - A process local variable that's just the name of the finished disc.
62 # DONELOCK - A timer for waiting for an add to the DB. Wait no more than 60 seconds.
63
64 LASTSTART=""
65 TIME=0
66 REENC=0
67
68 # Reset the status of running.
69
70 echo 0 > "$BASE/lib/stop"
71
72 rm -r "$TMP"
73 mkdir "$TMP"
74
75 main ()
76 {
77         getcurcd
78         
79         # If the cd in the drive is currently being encoded, don't try to encode it.
80         # Just sleep for 120 seconds and try again later.       
81
82         if [ "$CURCD" != "" ] && [ "$CURCD" = "$LASTSTART" ]
83         then    
84                 sleep 120
85                 TIME=0
86                 return 0
87                 
88         # If the CD isn't the same as the last one started, and cdparanoia is running
89         # Assume shit has hit the fan and kill it to end the current process.
90         # The process will die on it's own.
91         
92         elif [ "$CURCD" != "$LASTSTART" ] && [ "$(ps --no-heading -C cdparanoia)" != "" ]
93         then
94
95                 logger -p $LOGDEST.info "Error ($LASTSTART): Disc removed while encoding!"                                              
96                 killall -KILL cdparanoia
97                 
98                 # Reset the last start, because it wasn't.
99                 
100                 LASTSTART=""
101                 
102                 sleep 10
103                 return 0
104         
105         # If there's nothing in the drive, and there's no timeout yet, increase.
106         # If something was in the drive, the function would return without encoding it.
107         
108         elif [ $TIME -lt $TIMEOUT ] && [ "$CURCD" = "" ]
109         then
110                 TIME=$(($TIME+15))
111                 sleep 15
112                 return 0
113         
114         # If the cd has been sticking out for the timeout period (which is approx three hours).
115         # Suck it back in. This could be used to send a message to the domain, or cause beeping.        
116                 
117         elif [ $TIME -ge $TIMEOUT ]
118         then
119                 timeout
120                 
121                 TIME=0
122                 
123                 return 0
124         fi
125
126         # Eject the CD if the last CD processed is sucked (or put) back in.     
127
128
129         # If there is a cd in the drive
130         # Do not encode the last CD to go through the encoding process.
131         # This would cause the same CD to be re-re-rencoded if left in the drive
132         # for too long.
133
134         if [ "$CURCD" != "" ] && [ "$CURCD" != "$(< "$BASE/lib/LASTDONE")" ] &! [ -d "$TMP/$(echo $CURCD | cut -f 1 -d \ )" ]
135         then
136                 
137                 # If the cd in the drive was already encoded, set reenc to the disc-id. If the user puts the
138                 # disc back in the drive, it will re-encode. If it's different, REENC won't matter.
139                 
140                 if [ "`grep "$CURCD" $BASE/lib/done.db`" = "" ] || [ "$REENC" = "$CURCD" ] 
141                 then
142                         until [ "$(($(stat -f "$TMP" --format=%a)*4096/1024/1024))" -gt "$FREEMIN" ]
143                         do
144                                 sleep 120
145                         done
146                 
147                         LASTSTART=$CURCD
148                         cdenc &
149                         REENC=$CURCD
150                         
151                 else
152                         eject $CDROM
153                         beep -r 3
154                         REENC="$CURCD"
155                         return 0
156                 fi
157         fi
158 }
159
160 getcurcd()
161 {
162         # Check for a cd. If cd-discid exits successfully, then set the variable.
163         # If it exits with a 0 (backwards, I know), then blank it.
164
165         if $(cd-discid $CDROM > /dev/null 2>&1)
166
167         then
168                 CURCD=$(cd-discid $CDROM 2>&1)
169         else
170                 CURCD=""
171         fi
172         return 0
173 }
174
175
176
177 timeout()
178 {
179         eject -t $CDROM && getcurcd
180
181         # If the cd was the last done, assume we timed out.
182
183         if [ "$CURCD" = "$(< "$BASE/lib/LASTDONE")" ] 
184         then
185                 logger -p $LOGDEST.error "CD Left (or put back) in drive."
186                 eject $CDROM
187                 beep -r 4
188                 return 0
189         fi
190
191         return 0
192 }
193
194
195 # CD Encoder function. The workhorse.
196 # Note: Only call when CD is in drive, else exit.
197
198 cdenc ()
199 {       
200         # Check to make sure the cd wasn't changed or removed.
201                 
202         if [ "$(cd-discid $CDROM 2>&1)" != "$CURCD" ]
203         then
204                 return 0
205         fi
206         
207         # Set this process's id.
208         
209         local PROCESS="$(echo $CURCD | cut -f 1 -d \ )"
210         local THISDISC="$CURCD"
211         local PROCDIR="$TMP/$PROCESS"
212         local DONELOCK=0
213
214         # Make a work folder
215         
216         rm -fr "$PROCDIR"
217         mkdir "$PROCDIR"
218         cd "$PROCDIR"
219
220         
221         # Okay, abcde has a bug where it tries to rip data cd's. But the version that fixes it itself has
222         # even more. So instead of trying to install the new version, which doesn't work, we use a command
223         # similar to the one ABCDE uses to determine the number of valid tracks (since it assumes the data
224         # track always occurs at the end, which in some game CD's it doesn't) and pass it to the command
225         # line. Yes, it really is one line.
226         
227         local VALIDTRACKS="$(cdparanoia -d $CDROM -Q 2>&1 | egrep '^[[:space:]]+[[:digit:]]' | awk '{print $1}' | tr -d "." | tr '\n' ' ')"
228         
229         # Do it. Do it. 
230                 
231         logger -p $LOGDEST.info "Info ($PROCESS): Starting encoding."
232         
233         abcde -Nx -d $CDROM $VALIDTRACKS > /dev/null 2>&1
234                 
235
236         # If the disc is unknown, give a warning and unique folder name.
237         
238         if [ -d "$PROCDIR/Unknown Artist - Unknown Album/" ]
239         then
240                 logger -p $LOGDEST.warn "Warning ($PROCESS): Processed successfully, but info unknown."
241                 mv "$PROCDIR/Unknown Artist - Unknown Album" "$PROCDIR/Unknown Disc - ID $PROCESS"
242         
243         fi
244         
245         # If more than one folder is left, or the abcde.process folder is left over,
246         # or if there's nothing in the directory, something has gone WRONG.
247         
248         if [ $(ls -1 "$PROCDIR" | wc -l) -gt 1 ] || [ "$(ls -1 "$PROCDIR")" = "abcde.$PROCESS" ] || [ "$(ls -1 "$PROCDIR")" = "" ]
249         then
250                 logger -p $LOGDEST.error "Error ($PROCESS): More than one folder or something very bad happened."
251                 rm -r "$PROCDIR"
252                 return 0
253         fi
254                 
255         # Note: Don't declare discname until process is finished. Now is fine.
256         
257         local DISCNAME=`ls -1 "$PROCDIR"`
258         
259         # Put the current disc's ID into a file in the disc's folder, JIC
260         
261         echo "$THISDISC" > "$PROCDIR/$DISCNAME/disc_id"
262         
263         
264         logger -p $LOGDEST.info "Info ($PROCESS): Encoding of "$DISCNAME" completed successfully."
265         
266         
267         # Wait for the done database to be ready...
268
269         until ! [ -f "$BASE/lib/done.lock" ] || [ $DONELOCK -ge 60 ]
270         do
271         sleep 10
272         DONELOCK=$(($DONELOCK+10)) 
273         done
274
275         # Then add this disc to it.     
276         if [ "`grep "$CURCD" $BASE/lib/done.db`" = "" ] 
277         then    
278                 touch "$BASE/lib/done.lock"
279                 cat "$BASE/lib/done.db" "$PROCDIR/$DISCNAME/disc_id" > "$BASE/lib/done.new"
280                 mv "$BASE/lib/done.new" "$BASE/lib/done.db"
281                 rm "$BASE/lib/done.lock"
282         else
283                 logger -p $LOGDEST.notice "Not adding $PROCESS to done.db" 
284         fi
285         
286         # Move the process's completed directory into the done folder.
287         
288         if ! [ -d "$DONE/$DISCNAME" ]
289         then
290                 mv -f "$PROCDIR/$DISCNAME" "$DONE/"
291         elif [ -d "$DONE/$DISCNAME" ]
292         then
293                 rm -r "$DONE/$DISCNAME"
294                 mv -f "$PROCDIR/$DISCNAME" "$DONE/"
295         fi
296         
297         # A file must be used here because the variable is lost when the function exits sometimes.      
298
299         echo "$THISDISC" > "$BASE/lib/LASTDONE"
300         
301         # If I was the last disc started, and I'm done, clear the laststart variable so the last disc
302         # encoded can be re-encoded if they really want to.
303         
304         if [ "$THISDISC" = "$LASTSTART" ]
305         then
306                 LASTSTART=""
307         fi
308
309         
310         # Remove the process temp directory and call it a day.
311         
312         rm -r "$PROCDIR"
313         
314 }
315
316 until [[ $(< "$BASE/lib/stop") == 1 ]]
317 do
318         main
319 done