r150@frost: data | 2005-08-29 01:41:57 +0300
[clinton/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 unknwon, 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/Unkown 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