dvd-info.c: Trigger the easy lookup if explicit chapter bounds aren't given.
[dvdrip] / dvdrip
diff --git a/dvdrip b/dvdrip
index 5c1e72b..9634fe0 100755 (executable)
--- a/dvdrip
+++ b/dvdrip
@@ -5,36 +5,32 @@ dev=${DVDRIP_DEVICE-/dev/dvd}
 tmp=${DVDRIP_TMPDIR-${HOME?}/tmp/dvdrip}
 archive=${DVDRIP_ARCHIVE-jem.distorted.org.uk:/mnt/dvd/archive}
 : ${DVD_SECTOR_COPY=dvd-sector-copy}
+: ${DVD_ID=dvd-id}
 : ${DVDRIP_UPLOAD=dvdrip-upload}
-backup=nil eject=nil force=nil verbose=nil bogus=nil; unset dir sub n label
+backup=nil ding=nil eject=nil force=nil retry=nil verbose=nil bogus=nil
+unset params
 usage () {
   cat <<EOF
-usage: $prog [-befv] [-D DEV] [-a ARCH] [-d DIR]
-       [-l LABEL] [-n N] [-s SUB] [-t TMP] TITLE
+usage: $prog [-defrv] [-D DEV] [-a ARCH] [-t TMP] TITLE
 EOF
 }
-while getopts "hD:a:bd:efl:n:s:t:v" opt; do
+while getopts "hB:D:a:defrt:v" opt; do
   case $opt in
     h) usage; exit 0 ;;
+    B) params=${params+$params,}$OPTARG ;;
     D) dev=$OPTARG ;;
     a) archive=$OPTARG ;;
-    b) backup=t ;;
-    d) dir=$OPTARG ;;
+    d) ding=t ;;
     e) eject=t ;;
     f) force=t ;;
-    l) label=$OPTARG ;;
-    n) n=$OPTARG ;;
-    s) sub=$OPTARG ;;
+    r) retry=t ;;
     t) tmp=$OPTARG ;;
     v) verbose=t ;;
     *) bogus=t ;;
   esac
 done
 shift $(( $OPTIND - 1 ))
-case $# in
-  1) title=$1 ;;
-  *) bogus=t ;;
-esac
+case $# in 1) title=$1 ;; *) bogus=t ;; esac
 case $bogus in t) usage >&2; exit 2 ;; esac
 case $verbose in t) set -x ;; esac
 case $archive in
@@ -72,51 +68,40 @@ archdo () {
 }
 archrun () { archdo run "$@"; }
 
-case ${dir+t},${n+t} in
-  t,t | ,)
-    n=$(printf "%02d" "$n")
-    ;;
-  *)
-    echo >&2 "$prog: must specify both directory and disc number, or neither"
-    exit 2
-    ;;
-esac
-
-hack_label () {
-  tr "[:lower:]" "[:upper:]" |
-    tr -Cs "[:alnum:]_\n" "[-*]" |
-    sed 's/^-//; s/-$//'
-}
-
-case $backup in
-  t)
-    case ${label+t},${dir+t} in
-      t,*) ;;
-      ,) label=$(printf "%s" "$title" | hack_label) ;;
-      ,t) label=$(printf "%s_%s" "$dir" "$n" | hack_label) ;;
-    esac
-    len=$(printf "%s" "$label" | wc -c)
-    if [ $len -gt 32 ]; then echo >&2 "$prog: label too long"; exit 2; fi
-    ;;
-  nil)
-    case ${label+t} in
-      t) echo >&2 "$prog: label only meaningful to \`dvdbackup'"; exit 2 ;;
-    esac
-    ;;
-esac
-
-case ${dir+t} in
-  t) tag="${dir}_${n}_${title}" out="$dir/$n. $title" ;;
-  *) tag=$title out=$title ;;
-esac
-tag=${tag//\//_}
+tag=${title//\//_}
 
-archdo run_setrc test -f "$archpath${sub+/$sub}/$out.iso"
+archdo run_setrc test -f "$archpath/$title.iso"
 case $rc,$force in
   0,nil) fail "output file already exists" ;;
   0,t) warn "output file already exists; will overwrite" ;;
 esac
 
+mkdir -p "$tmp/$tag"
+
+discid=$("$DVD_ID" -I "$dev")
+if [ -f "$tmp/$tag/discid" ]; then
+  read oldid <"$tmp/$tag/discid"
+  case $force,$oldid in
+    t,"$discid" | nil,"$discid")
+      ;;
+    nil,*)
+      fail "discid mismatch: expected \`$oldid' but drive has \`$discid'"
+      ;;
+    t,*)
+      warn "discid mismatch: expected \`$oldid' but drive has \`$discid'; continuing anway"
+      ;;
+  esac
+fi
+info "copying \`$discid'"
+echo "$discid" >"$tmp/$tag/discid.new"
+mv "$tmp/$tag/discid.new" "$tmp/$tag/discid"
+
+if [ -b "$dev" ]; then msz=$(blockdev --getsize64 "$dev")
+else msz=nil; fi
+
+echo "$dev" >"$tmp/$tag/device.new"
+mv "$tmp/$tag/device.new" "$tmp/$tag/device"
+
 accumulate_badblocks () {
   if [ -f "$tmp/$tag/badblocks.new" ]; then
     if [ ! -f "$tmp/$tag/badblocks" ]; then
@@ -127,43 +112,74 @@ accumulate_badblocks () {
   fi
 }
 
-mkdir -p "$tmp/$tag"
-case $backup in
+set --
+any=nil
+for i in "$tmp/$tag/dest.new" "$tmp/$tag/dest" "$tmp/$tag/dest.seen"; do
+  if [ -f "$tmp/$tag/dest.new" ]; then any=t; fi
+done
+case $any in
+  nil) printf "%s\n" "$title.iso" >"$tmp/$tag/dest.new" ;;
+esac
+case $eject in
+  t) touch "$tmp/$tag/eject" ;;
+  nil) rm -f "$tmp/$tag/eject" ;;
+esac
+case $ding in
+  t) touch "$tmp/$tag/ding" ;;
+  nil) rm -f "$tmp/$tag/ding" ;;
+esac
+
+accumulate_badblocks
+case $retry in
   t)
-    if [ ! -d "$tmp/$tag/rip" ]; then
-      rm -rf "$tmp/$tag/rip.new"
-      run dvdbackup -Mp -i"$dev" -o"$tmp/$tag" -n"rip.new"
-      run mv "$tmp/$tag/rip.new" "$tmp/$tag/rip"
+    if [ -f "$tmp/$tag/badblocks.retry" ]; then
+      :
+    elif [ -f "$tmp/$tag/badblocks" ]; then
+      run mv "$tmp/$tag/badblocks" "$tmp/$tag/badblocks.retry"
+    else
+      fail "no blocks to retry"
     fi
-    if [ ! -f "$tmp/$tag/iso" ]; then
-      run genisoimage -quiet -dvd-video -udf -V "$label" \
-         -o "$tmp/$tag/iso.new" "$tmp/$tag/rip"
-      run mv "$tmp/$tag/iso.new" "$tmp/$tag/iso"
+    set -- "$@" -R"$tmp/$tag/badblocks.retry"
+    if [ -f "$tmp/$tag/iso" ]; then
+      mv "$tmp/$tag/iso" "$tmp/$tag/iso.new"
     fi
     ;;
-  nil)
-    if [ ! -f "$tmp/$tag/iso" ]; then
-      accumulate_badblocks
-      run_setrc "$DVD_SECTOR_COPY" -c -b"$tmp/$tag/badblocks.new" \
-               "$dev" "$tmp/$tag/iso.new"
-      accumulate_badblocks
-      case $rc in
-       0)
-         run mv "$tmp/$tag/iso.new" "$tmp/$tag/iso"
-         ;;
-       1)
-         run mv "$tmp/$tag/iso.new" "$tmp/$tag/iso"
-         fail "bad sectors found: check \`$tmp/$tag/iso', run again if ok"
-         ;;
-       *)
-         fail "$DVD_SECTOR_COPY: exit $rc"
-         ;;
+esac
+if [ ! -f "$tmp/$tag/iso" ]; then
+  run "$DVD_SECTOR_COPY" -cs ${params+"-B$params"} \
+      -b"$tmp/$tag/badblocks.new" "$@" "$dev" "$tmp/$tag/iso.new"
+  run mv "$tmp/$tag/iso.new" "$tmp/$tag/iso"
+  accumulate_badblocks
+  rm -f "$tmp/$tag/device"
+  case $retry in t) rm -f "$tmp/$tag/badblocks.retry" ;; esac
+  if [ -f "$tmp/$tag/badblocks" ]; then
+    fail "bad sectors found: check \`$tmp/$tag/iso', run again if ok"
+  fi
+  case $msz in
+    nil) ;;
+    *)
+      newmsz=$(blockdev --getsize64 "$dev")
+      case $newmsz in
+       $msz) ;;
+       *) fail "medium size changed ($msz -> $newmsz): try again" ;;
       esac
+      ;;
+  esac
+fi
+
+rm -f "$tmp/$tag/device"
+run mv "$tmp/$tag/dest.new" "$tmp/$tag/dest"
+if [ -f "$tmp/$tag/eject" ]; then eject=t; else eject=nil; fi
+if [ -f "$tmp/$tag/ding" ]; then ding=t; else ding=nil; fi
+run "$DVDRIP_UPLOAD"
+case $eject in t) run eject "$dev" ;; esac
+case $ding in
+  t)
+    if [ -t 1 ]; then exec 3>&1
+    elif [ -t 2 ]; then exec 3>&2
+    else exec 3>/dev/tty
     fi
+    printf "\a" >&3
+    exec 3>&-
     ;;
 esac
-printf "%s\n" "${sub+$sub/}$out.iso" >"$tmp/$tag/dest.new"
-mv "$tmp/$tag/dest.new" "$tmp/$tag/dest"
-run "$DVDRIP_UPLOAD"
-case $eject in t) run eject "$dev" ;; esac
-printf "\a"