Mark VandenBrink 12 лет назад
Родитель
Сommit
e831a401b5
12 измененных файлов с 1534 добавлено и 1534 удалено
  1. 132 132
      audio-streams.lisp
  2. 375 375
      id3-frame.lisp
  3. 1 1
      iso-639-2.lisp
  4. 22 22
      logging.lisp
  5. 291 291
      mp3-tag.lisp
  6. 259 259
      mp4-atom.lisp
  7. 51 51
      mp4-tag.lisp
  8. 321 321
      mpeg.lisp
  9. 41 41
      packages.lisp
  10. 28 28
      taglib-tests.lisp
  11. 9 9
      taglib.asd
  12. 4 4
      utils.lisp

+ 132 - 132
audio-streams.lisp

@@ -34,11 +34,11 @@
 (defun make-file-stream (class-name filename &key (read-only t))
   "Convenience function for creating a file stream."
   (let ((new-stream (make-instance (find-class class-name))))
-	(setf (stream new-stream) (if read-only
-								  (open filename :direction :input :element-type 'octet)
-								  (open filename :direction :io :if-exists :overwrite :element-type 'octet)))
-	(setf (stream-filename new-stream) filename)
-	new-stream))
+    (setf (stream new-stream) (if read-only
+                                  (open filename :direction :input :element-type 'octet)
+                                  (open filename :direction :io :if-exists :overwrite :element-type 'octet)))
+    (setf (stream-filename new-stream) filename)
+    new-stream))
 
 ;;;   (:documentation "In-memory stream")))
 (defclass base-mem-stream (base-stream) ())
@@ -46,20 +46,20 @@
 (defun make-mem-stream (vector)
   "Convenience function to turn a vector into a stream."
   (let ((new-stream (make-instance 'base-mem-stream)))
-	(setf (stream new-stream) (ccl:make-vector-input-stream vector))
-	new-stream))
+    (setf (stream new-stream) (ccl:make-vector-input-stream vector))
+    new-stream))
 
 (defmethod stream-close ((in-stream base-file-stream))
   "Close the underlying file."
   (with-slots (stream) in-stream
-	(when stream
-	  (close stream)
-	  (setf stream nil))))
+    (when stream
+      (close stream)
+      (setf stream nil))))
 
 (defmethod stream-close ((in-stream base-mem-stream))
   "'Close' a memory stream by setting it to nil"
   (with-slots (stream) in-stream
-	(setf stream nil)))
+    (setf stream nil)))
 
 (defmethod stream-size ((in-stream base-stream))
   "Returns the length of the underlying stream"
@@ -69,12 +69,12 @@
 (defmethod stream-seek ((in-stream base-stream) offset from)
   "C-like stream positioner.  Takes an offset and a location (one of :start, :end, :current)."
   (with-slots (stream) in-stream
-	(ecase from
-	  (:start (ccl::stream-position stream offset))
-	  (:current (if (zerop offset)
-					(ccl::stream-position stream)
-					(ccl::stream-position stream (+ (ccl::stream-position stream) offset))))
-	  (:end (ccl::stream-position stream (- (ccl::stream-length stream) offset))))))
+    (ecase from
+      (:start (ccl::stream-position stream offset))
+      (:current (if (zerop offset)
+                    (ccl::stream-position stream)
+                    (ccl::stream-position stream (+ (ccl::stream-position stream) offset))))
+      (:end (ccl::stream-position stream (- (ccl::stream-length stream) offset))))))
 
 (defmethod stream-pos ((in-stream base-stream))
   "Short hand for getting current stream read position"
@@ -83,55 +83,55 @@
 (defun stream-read-octets (instream bytes &key (bits-per-byte 8))
   "Used to slurp in octets for the stream-read-* methods"
   (loop with value = 0
-		for low-bit downfrom (* bits-per-byte (1- bytes)) to 0 by bits-per-byte do
-		  (setf (ldb (byte bits-per-byte low-bit) value) (read-byte instream))
-		finally (return value)))
+        for low-bit downfrom (* bits-per-byte (1- bytes)) to 0 by bits-per-byte do
+          (setf (ldb (byte bits-per-byte low-bit) value) (read-byte instream))
+        finally (return value)))
 
 (defmethod stream-read-u8 ((in-stream base-stream) &key (bits-per-byte 8))
   "Read 1 byte from file"
   (with-slots (stream) in-stream
-	(stream-read-octets stream 1 :bits-per-byte bits-per-byte)))
+    (stream-read-octets stream 1 :bits-per-byte bits-per-byte)))
 
 (defmethod stream-read-u16 ((in-stream base-stream) &key (bits-per-byte 8))
   "Read 2 bytes from file"
   (with-slots (stream) in-stream
-	(stream-read-octets stream 2 :bits-per-byte bits-per-byte)))
+    (stream-read-octets stream 2 :bits-per-byte bits-per-byte)))
 
 (defmethod stream-read-u24 ((in-stream base-stream) &key (bits-per-byte 8))
   "Read 3 bytes from file"
   (with-slots (stream) in-stream
-	(stream-read-octets stream 3 :bits-per-byte bits-per-byte)))
+    (stream-read-octets stream 3 :bits-per-byte bits-per-byte)))
 
 (defmethod stream-read-u32 ((in-stream base-stream) &key (bits-per-byte 8))
   "Read 4 bytes from file"
   (with-slots (stream) in-stream
-	(stream-read-octets stream 4 :bits-per-byte bits-per-byte)))
+    (stream-read-octets stream 4 :bits-per-byte bits-per-byte)))
 
 (defmethod stream-read-u64 ((in-stream base-stream) &key (bits-per-byte 8))
   "Read 8 bytes from file"
   (with-slots (stream) in-stream
-	(stream-read-octets stream 8 :bits-per-byte bits-per-byte)))
+    (stream-read-octets stream 8 :bits-per-byte bits-per-byte)))
 
 (defmethod stream-read-sequence ((stream base-stream) size &key (bits-per-byte 8))
   "Read SIZE octets from input-file in BIT-PER-BYTE sizes"
   (log5:with-context "stream-read-sequence"
-	(ecase bits-per-byte
-	  (8
-	   (let ((octets (make-octets size)))
-		 (read-sequence octets (slot-value stream 'stream))
-		 octets))
-	  (7
-	   (let* ((last-byte-was-FF nil)
-			  (byte nil)
-			  (octets (ccl:with-output-to-vector (out)
-						(dotimes (i size)
-						  (setf byte (stream-read-u8 stream))
-						  (if last-byte-was-FF
-							  (if (not (zerop byte))
-								  (write-byte byte out))
-							  (write-byte byte out))
-						  (setf last-byte-was-FF (= byte #xFF))))))
-		 octets)))))
+    (ecase bits-per-byte
+      (8
+       (let ((octets (make-octets size)))
+         (read-sequence octets (slot-value stream 'stream))
+         octets))
+      (7
+       (let* ((last-byte-was-FF nil)
+              (byte nil)
+              (octets (ccl:with-output-to-vector (out)
+                        (dotimes (i size)
+                          (setf byte (stream-read-u8 stream))
+                          (if last-byte-was-FF
+                              (if (not (zerop byte))
+                                  (write-byte byte out))
+                              (write-byte byte out))
+                          (setf last-byte-was-FF (= byte #xFF))))))
+         octets)))))
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; STRINGS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
@@ -146,25 +146,25 @@
 ;;; sometimes encoded as #(00 00))
 (defun stream-decode-ucs-string (octets &key (start 0) (end nil))
   "Decode octets as a UCS string with a BOM (encoding == 1)"
-	(labels ((get-byte-order-mark (octets)
-			   (let ((retval 0))
-				 (setf (ldb (byte 8 0) retval) (aref octets 1))
-				 (setf (ldb (byte 8 8) retval) (aref octets 0))
-				 (when (not (or (= #xfffe retval) (= #xfeff retval)))
-				   (error "got an invalid byte-order mark of ~x" retval))
-				 retval)))
-
-	  ;; special case: empty (and mis-coded) string
-	  (cond ((zerop (length octets))
-			 (make-string 0))
-			(t
-			 ;;
-			 ;; else, we have a (hopefully) properly encoded string
-			 (let ((bom (get-byte-order-mark octets)))
-			   (ecase (the fixnum bom)
-				 (#xfffe (ccl:decode-string-from-octets octets :start (+ 2 start) :end end :external-format :ucs-2le))
-				 (#xfeff (ccl:decode-string-from-octets octets :start (+ 2 start) :end end :external-format :ucs-2be))
-				 (0      (make-string 0))))))))
+    (labels ((get-byte-order-mark (octets)
+               (let ((retval 0))
+                 (setf (ldb (byte 8 0) retval) (aref octets 1))
+                 (setf (ldb (byte 8 8) retval) (aref octets 0))
+                 (when (not (or (= #xfffe retval) (= #xfeff retval)))
+                   (error "got an invalid byte-order mark of ~x" retval))
+                 retval)))
+
+      ;; special case: empty (and mis-coded) string
+      (cond ((zerop (length octets))
+             (make-string 0))
+            (t
+             ;;
+             ;; else, we have a (hopefully) properly encoded string
+             (let ((bom (get-byte-order-mark octets)))
+               (ecase (the fixnum bom)
+                 (#xfffe (ccl:decode-string-from-octets octets :start (+ 2 start) :end end :external-format :ucs-2le))
+                 (#xfeff (ccl:decode-string-from-octets octets :start (+ 2 start) :end end :external-format :ucs-2be))
+                 (0      (make-string 0))))))))
 
 (defun stream-decode-ucs-be-string (octets &key (start 0) (end nil))
   "Decode octets as a UCS-BE string (encoding == 2)"
@@ -177,95 +177,95 @@
 (defun stream-decode-string (octets &key (start 0) (end nil) (encoding 0))
   "Decode octets depending on encoding"
   (ecase encoding
-	(0 (stream-decode-iso-string octets    :start start :end end))
-	(1 (stream-decode-ucs-string octets    :start start :end end))
-	(2 (stream-decode-ucs-be-string octets :start start :end end))
-	(3 (stream-decode-utf-8-string octets  :start start :end end))))
+    (0 (stream-decode-iso-string octets    :start start :end end))
+    (1 (stream-decode-ucs-string octets    :start start :end end))
+    (2 (stream-decode-ucs-be-string octets :start start :end end))
+    (3 (stream-decode-utf-8-string octets  :start start :end end))))
 
 (defmethod stream-read-iso-string-with-len ((instream base-stream) len)
   "Read an iso-8859-1 string of length 'len' (encoding = 0)"
   (let ((octets (stream-read-sequence instream len)))
-	(stream-decode-iso-string octets)))
+    (stream-decode-iso-string octets)))
 
 (defmethod stream-read-ucs-string-with-len ((instream base-stream) len)
   "Read an ucs-2 string of length 'len' (encoding = 1)"
   (let ((octets (stream-read-sequence instream len)))
-	  (stream-decode-ucs-string octets)))
+      (stream-decode-ucs-string octets)))
 
 (defmethod stream-read-ucs-be-string-with-len ((instream base-stream) len)
   "Read an ucs-2-be string of length 'len' (encoding = 2)"
   (let ((octets (stream-read-sequence instream len)))
-	(stream-decode-ucs-be-string octets)))
+    (stream-decode-ucs-be-string octets)))
 
 (defmethod stream-read-utf-8-string-with-len ((instream base-stream) len)
   "Read an utf-8 string of length 'len' (encoding = 3)"
   (let ((octets (stream-read-sequence instream len)))
-	(stream-decode-utf-8-string octets)))
+    (stream-decode-utf-8-string octets)))
 
 (defmethod stream-read-string-with-len ((instream base-stream) len &key (encoding 0))
   "Read in a string of a given encoding of length 'len'"
   (ecase encoding
-	(0 (stream-read-iso-string-with-len instream len))
-	(1 (stream-read-ucs-string-with-len instream len))
-	(2 (stream-read-ucs-be-string-with-len instream len))
-	(3 (stream-read-utf-8-string-with-len instream len))))
+    (0 (stream-read-iso-string-with-len instream len))
+    (1 (stream-read-ucs-string-with-len instream len))
+    (2 (stream-read-ucs-be-string-with-len instream len))
+    (3 (stream-read-utf-8-string-with-len instream len))))
 
 (defmethod stream-read-iso-string ((instream base-stream))
   "Read in a null terminated iso-8859-1 string"
   (let ((octets (ccl:with-output-to-vector (out)
-				  (do ((b (stream-read-u8 instream) (stream-read-u8 instream)))
-					  (nil)
-					(when (zerop b)
-					  (return))			; leave loop w/o writing
-					(write-byte b out)))))
-	(stream-decode-iso-string octets)))
+                  (do ((b (stream-read-u8 instream) (stream-read-u8 instream)))
+                      (nil)
+                    (when (zerop b)
+                      (return))         ; leave loop w/o writing
+                    (write-byte b out)))))
+    (stream-decode-iso-string octets)))
 
 (defmethod stream-read-ucs-string ((instream base-stream))
   "Read in a null terminated UCS string."
   (let ((octets (ccl:with-output-to-vector (out)
-				  (do* ((b0 (stream-read-u8 instream)
-							(stream-read-u8 instream))
-						(b1 (stream-read-u8 instream)
-							(stream-read-u8 instream)))
-					   (nil)
-					(when (and (zerop b0) (zerop b1))
-					  (return))
-					(write-byte b0 out)
-					(write-byte b1 out)))))
-	(stream-decode-ucs-string octets)))
+                  (do* ((b0 (stream-read-u8 instream)
+                            (stream-read-u8 instream))
+                        (b1 (stream-read-u8 instream)
+                            (stream-read-u8 instream)))
+                       (nil)
+                    (when (and (zerop b0) (zerop b1))
+                      (return))
+                    (write-byte b0 out)
+                    (write-byte b1 out)))))
+    (stream-decode-ucs-string octets)))
 
 (defmethod stream-read-ucs-be-string ((instream base-stream))
   "Read in a null terminated UCS-BE string."
   (let ((octets (ccl:with-output-to-vector (out)
-				  (do* ((b0 (stream-read-u8 instream)
-							(stream-read-u8 instream))
-						(b1 (stream-read-u8 instream)
-							(stream-read-u8 instream)))
-					   (nil)
-					(when (and (zerop b0) (zerop b1))
-					  (return))
-					(write-byte b0 out)
-					(write-byte b1 out)))))
-	(stream-decode-ucs-be-string octets)))
+                  (do* ((b0 (stream-read-u8 instream)
+                            (stream-read-u8 instream))
+                        (b1 (stream-read-u8 instream)
+                            (stream-read-u8 instream)))
+                       (nil)
+                    (when (and (zerop b0) (zerop b1))
+                      (return))
+                    (write-byte b0 out)
+                    (write-byte b1 out)))))
+    (stream-decode-ucs-be-string octets)))
 
 (defmethod stream-read-utf-8-string ((instream base-stream))
   "Read in a null terminated utf-8 string (encoding == 3)"
   (let ((octets (ccl:with-output-to-vector (out)
-				  (do ((b (stream-read-u8 instream)
-						  (stream-read-u8 instream)))
-					  (nil)
-					(when (zerop b)
-					  (return))
-					(write-byte b out)))))
-	(stream-decode-utf-8-string octets)))
+                  (do ((b (stream-read-u8 instream)
+                          (stream-read-u8 instream)))
+                      (nil)
+                    (when (zerop b)
+                      (return))
+                    (write-byte b out)))))
+    (stream-decode-utf-8-string octets)))
 
 (defmethod stream-read-string ((instream base-stream) &key (encoding 0))
   "Read in a null terminated string of a given encoding."
   (ecase encoding
-	(0 (stream-read-iso-string    instream))
-	(1 (stream-read-ucs-string    instream))
-	(2 (stream-read-ucs-be-string instream))
-	(3 (stream-read-utf-8-string  instream))))
+    (0 (stream-read-iso-string    instream))
+    (1 (stream-read-ucs-string    instream))
+    (2 (stream-read-ucs-be-string instream))
+    (3 (stream-read-utf-8-string  instream))))
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; FILES ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 (defvar *get-audio-info* t "controls whether the parsing functions also parse audio info like bit-rate, etc")
@@ -273,29 +273,29 @@
 (defun parse-mp4-file (filename &key (get-audio-info *get-audio-info*))
   "Parse an MP4A file by reading it's ATOMS and decoding them."
   (let (stream)
-	(handler-case
-		(progn
-		  (setf stream (make-file-stream 'mp4-file-stream filename))
-		  (mp4-atom:find-mp4-atoms stream)
-		  (when get-audio-info
-			(setf (audio-info stream) (mp4-atom:get-mp4-audio-info stream))))
-	  (mp4-atom:mp4-atom-condition (c)
-		(warn-user "make-mp4-stream got condition: ~a" c)
-		(when stream (stream-close stream))
-		(setf stream nil)))
-	stream))
+    (handler-case
+        (progn
+          (setf stream (make-file-stream 'mp4-file-stream filename))
+          (mp4-atom:find-mp4-atoms stream)
+          (when get-audio-info
+            (setf (audio-info stream) (mp4-atom:get-mp4-audio-info stream))))
+      (mp4-atom:mp4-atom-condition (c)
+        (warn-user "make-mp4-stream got condition: ~a" c)
+        (when stream (stream-close stream))
+        (setf stream nil)))
+    stream))
 
 (defun parse-mp3-file (filename &key (get-audio-info *get-audio-info*))
   "Parse an MP3 file by reading it's FRAMES and decoding them."
   (let (stream)
-	  (handler-case
-		  (progn
-			(setf stream (make-file-stream 'mp3-file-stream filename))
-			(id3-frame:find-id3-frames stream)
-			(when get-audio-info
-			  (setf (audio-info stream) (mpeg:get-mpeg-audio-info stream))))
-		(id3-frame:id3-frame-condition (c)
-		  (warn-user "make-mp3-stream got condition: ~a" c)
-		  (when stream (stream-close stream))
-		  (setf stream nil)))
-	stream))
+      (handler-case
+          (progn
+            (setf stream (make-file-stream 'mp3-file-stream filename))
+            (id3-frame:find-id3-frames stream)
+            (when get-audio-info
+              (setf (audio-info stream) (mpeg:get-mpeg-audio-info stream))))
+        (id3-frame:id3-frame-condition (c)
+          (warn-user "make-mp3-stream got condition: ~a" c)
+          (when stream (stream-close stream))
+          (setf stream nil)))
+    stream))

+ 375 - 375
id3-frame.lisp

@@ -11,8 +11,8 @@
    (object   :initarg :object   :reader object   :initform nil)
    (messsage :initarg :message  :reader message  :initform "Undefined Condition"))
   (:report (lambda (condition stream)
-			 (format stream "id3-frame condition at location: <~a> with object: <~a>: message: <~a>"
-					 (location condition) (object condition) (message condition)))))
+             (format stream "id3-frame condition at location: <~a> with object: <~a>: message: <~a>"
+                     (location condition) (object condition) (message condition)))))
 
 (defmethod print-object ((me id3-frame-condition) stream)
   (format stream "location: <~a>, object: <~a>, message: <~a>" (location me) (object me) (message me)))
@@ -24,7 +24,7 @@
    (flags          :accessor flags          :initarg :flags          :initform 0   :documentation "ID3 header flags")
    (size           :accessor size           :initarg :size           :initform 0   :documentation "size of ID3 info")
    (ext-header     :accessor ext-header     :initarg :ext-header     :initform nil :documentation "holds v2.3/4 extended header")
-   (frames	       :accessor frames	        :initarg :frames		 :initform nil :documentation "holds ID3 frames")
+   (frames         :accessor frames         :initarg :frames         :initform nil :documentation "holds ID3 frames")
    (v21-tag-header :accessor v21-tag-header :initarg :v21-tag-header :initform nil :documentation "old-style v2.1 header (if present)"))
   (:documentation "The ID3 header, found at start of file"))
 
@@ -32,19 +32,19 @@
   "Make sure this is an MP3 file. Look for ID3 header at begining (versions 2, 3, 4)
 and/or end (version 2.1)"
   (log5:with-context "is-valid-mp3-file"
-	(stream-seek mp3-file 0 :start)
-	(let* ((id3 (stream-read-string-with-len mp3-file 3))
-		   (version (stream-read-u8 mp3-file))
-		   (tag))
-	  (stream-seek mp3-file 128 :end)
-	  (setf tag (stream-read-string-with-len mp3-file 3))
-	  (stream-seek mp3-file 0 :start)
+    (stream-seek mp3-file 0 :start)
+    (let* ((id3 (stream-read-string-with-len mp3-file 3))
+           (version (stream-read-u8 mp3-file))
+           (tag))
+      (stream-seek mp3-file 128 :end)
+      (setf tag (stream-read-string-with-len mp3-file 3))
+      (stream-seek mp3-file 0 :start)
 
-	  (log-id3-frame "id3 = ~a, version = ~d" id3 version)
+      (log-id3-frame "id3 = ~a, version = ~d" id3 version)
 
-	  (or (and (string= "ID3" id3)
-			   (or (= 2 version) (= 3 version) (= 4 version)))
-		  (string= tag "TAG")))))
+      (or (and (string= "ID3" id3)
+               (or (= 2 version) (= 3 version) (= 4 version)))
+          (string= tag "TAG")))))
 
 (defclass v21-tag-header ()
   ((title    :accessor title    :initarg :title    :initform nil)
@@ -58,41 +58,41 @@ and/or end (version 2.1)"
 
 (defmethod vpprint ((me v21-tag-header) stream)
   (with-slots (title artist album year comment track genre) me
-	(format stream "title = <~a>, artist = <~a>, album = <~a>, year = <~a>, comment = <~a>, track = <~d>, genre = ~d (~a)"
-			title artist album year comment track genre (mp3-tag:get-id3v1-genre genre))))
+    (format stream "title = <~a>, artist = <~a>, album = <~a>, year = <~a>, comment = <~a>, track = <~d>, genre = ~d (~a)"
+            title artist album year comment track genre (mp3-tag:get-id3v1-genre genre))))
 
 (defmethod initialize-instance ((me v21-tag-header) &key instream)
   "Read in a V2.1 tag.  Caller will have stream-seek'ed file to correct location and ensured that TAG was present"
   (log5:with-context "v21-frame-initializer"
-	(log-id3-frame "reading v2.1 tag")
-	(with-slots      (title artist album year comment genre track) me
-	  (setf track nil)
-	  (setf title    (upto-null (stream-read-string-with-len instream 30)))
-	  (setf artist   (upto-null (stream-read-string-with-len instream 30)))
-	  (setf album    (upto-null (stream-read-string-with-len instream 30)))
-	  (setf year     (upto-null (stream-read-string-with-len instream 4)))
-	  (setf comment  (stream-read-string-with-len instream 30))
-
-	  ;; In V21, a comment can be split into comment and track #
-	  ;; find the first #\Null then check to see if that index < 28.  If so, the check the last two bytes being
-	  ;; non-zero---if so, then track can be set to integer value of last two bytes
-	  (let ((trimmed-comment (upto-null comment))
-			(trck 0))
-		(when (<= (length trimmed-comment) 28)
-		  (setf (ldb (byte 8 8) trck) (char-code (aref comment 28)))
-		  (setf (ldb (byte 8 0) trck) (char-code (aref comment 29)))
-		  (setf comment trimmed-comment)
-		  (if (> trck 0)
-			  (setf track trck)
-			  (setf track nil))))
-	  (setf genre    (stream-read-u8 instream))
-	  (log-id3-frame "v21 tag: ~a" (vpprint me nil)))))
+    (log-id3-frame "reading v2.1 tag")
+    (with-slots      (title artist album year comment genre track) me
+      (setf track nil)
+      (setf title    (upto-null (stream-read-string-with-len instream 30)))
+      (setf artist   (upto-null (stream-read-string-with-len instream 30)))
+      (setf album    (upto-null (stream-read-string-with-len instream 30)))
+      (setf year     (upto-null (stream-read-string-with-len instream 4)))
+      (setf comment  (stream-read-string-with-len instream 30))
+
+      ;; In V21, a comment can be split into comment and track #
+      ;; find the first #\Null then check to see if that index < 28.  If so, the check the last two bytes being
+      ;; non-zero---if so, then track can be set to integer value of last two bytes
+      (let ((trimmed-comment (upto-null comment))
+            (trck 0))
+        (when (<= (length trimmed-comment) 28)
+          (setf (ldb (byte 8 8) trck) (char-code (aref comment 28)))
+          (setf (ldb (byte 8 0) trck) (char-code (aref comment 29)))
+          (setf comment trimmed-comment)
+          (if (> trck 0)
+              (setf track trck)
+              (setf track nil))))
+      (setf genre    (stream-read-u8 instream))
+      (log-id3-frame "v21 tag: ~a" (vpprint me nil)))))
 
 (defclass id3-ext-header ()
   ((size    :accessor size    :initarg :size    :initform 0)
    (flags   :accessor flags   :initarg :flags   :initform 0)
    (padding :accessor padding :initarg :padding :initform 0)
-   (crc	    :accessor crc     :initarg :crc     :initform nil))
+   (crc     :accessor crc     :initarg :crc     :initform nil))
   (:documentation "Class representing a V2.3/4 extended header"))
 
 (defmacro ext-header-crc-p    (flags) `(logbitp 14 ,flags))
@@ -102,77 +102,77 @@ and/or end (version 2.1)"
   "Read in the extended header.  Caller will have stream-seek'ed to correct location in file.
 Note: extended headers are subject to unsynchronization, so make sure that INSTREAM has been made sync-safe."
   (with-slots (size flags padding crc) me
-	(setf size (stream-read-u32 instream))
-	(setf flags (stream-read-u16 instream))
-	(setf padding (stream-read-u32 instream))
-	(when (not (zerop flags))
-
-	  ;; at this point, we have to potentially read in other fields depending on flags.
-	  ;; for now, just error out...
-	  (assert (zerop flags) () "non-zero extended header flags = ~x, check validity")
-	  ;;(when (ext-header-crc-p flags)
-	  ;;  (setf crc (stream-read-u32 instream)))))
-	  )))
+    (setf size (stream-read-u32 instream))
+    (setf flags (stream-read-u16 instream))
+    (setf padding (stream-read-u32 instream))
+    (when (not (zerop flags))
+
+      ;; at this point, we have to potentially read in other fields depending on flags.
+      ;; for now, just error out...
+      (assert (zerop flags) () "non-zero extended header flags = ~x, check validity")
+      ;;(when (ext-header-crc-p flags)
+      ;;  (setf crc (stream-read-u32 instream)))))
+      )))
 
 (defmethod vpprint ((me id3-ext-header) stream)
   (with-slots (size flags padding crc) me
-	(format stream "extended header: size: ~d, flags: ~x, padding ~:d, crc = ~x~%"
-			size flags padding crc)))
+    (format stream "extended header: size: ~d, flags: ~x, padding ~:d, crc = ~x~%"
+            size flags padding crc)))
 
 ;;; NB: v2.2 only really defines bit-7. It does document bit-6 as being the compression flag, but then states
 ;;; that if it is set, the software should "ignore the entire tag if this (bit-6) is set"
 (defmacro header-unsynchronized-p (flags) `(logbitp 7 ,flags)) ; all share this flag
 (defmacro header-extended-p (flags)       `(logbitp 6 ,flags)) ; 2.3/2.4
 (defmacro header-experimental-p (flags)   `(logbitp 5 ,flags)) ; 2.3/2.4
-(defmacro header-footer-p (flags)		  `(logbitp 4 ,flags)) ; 2.4 only
+(defmacro header-footer-p (flags)         `(logbitp 4 ,flags)) ; 2.4 only
 
 (defmacro print-header-flags (stream flags)
   `(format ,stream "0x~2,'0x: ~:[0/~;unsynchronized-frames/~]~:[0/~;extended-header/~]~:[0/~;expermental-tag/~]~:[0~;footer-present~]"
-		   ,flags
-		   (header-unsynchronized-p ,flags)
-		   (header-extended-p ,flags)
-		   (header-experimental-p ,flags)
-		   (header-footer-p ,flags)))
+           ,flags
+           (header-unsynchronized-p ,flags)
+           (header-extended-p ,flags)
+           (header-experimental-p ,flags)
+           (header-footer-p ,flags)))
 
 (defmethod vpprint ((me id3-header) stream)
   (with-slots (version revision flags v21-tag-header size ext-header frames) me
-	(format stream "~a"
-			(with-output-to-string (s)
-			  (format s "Header: version/revision: ~d/~d, flags: ~a, size = ~:d bytes; ~a; ~a"
-					  version revision (print-header-flags nil flags) size
-					  (if (header-extended-p flags)
-						  (concatenate 'string "Extended header: " (vpprint ext-header nil))
-						  "No extended header")
-					  (if v21-tag-header
-						  (concatenate 'string "V21 tag: " (vpprint v21-tag-header nil))
-						  "No V21 tag"))
-			  (when frames
-				(format s "~&~4tFrames[~d]:~%" (length frames))
-				(dolist (f frames)
-				  (format s "~8t~a~%" (vpprint f nil))))))))
+    (format stream "~a"
+            (with-output-to-string (s)
+              (format s "Header: version/revision: ~d/~d, flags: ~a, size = ~:d bytes; ~a; ~a"
+                      version revision (print-header-flags nil flags) size
+                      (if (header-extended-p flags)
+                          (concatenate 'string "Extended header: " (vpprint ext-header nil))
+                          "No extended header")
+                      (if v21-tag-header
+                          (concatenate 'string "V21 tag: " (vpprint v21-tag-header nil))
+                          "No V21 tag"))
+              (when frames
+                (format s "~&~4tFrames[~d]:~%" (length frames))
+                (dolist (f frames)
+                  (format s "~8t~a~%" (vpprint f nil))))))))
 
 (defmethod initialize-instance :after ((me id3-header) &key instream &allow-other-keys)
   "Fill in an mp3-header from INSTREAM."
   (log5:with-context "id3-header-initializer"
-	(with-slots (version revision flags size ext-header frames v21-tag-header) me
-	  (stream-seek instream 128 :end)
-	  (when (string= "TAG" (stream-read-string-with-len instream 3))
-		(log-id3-frame "looking at last 128 bytes at ~:d to try to read id3v21 header" (stream-seek instream 0 :current))
-		(handler-case
-			(setf v21-tag-header (make-instance 'v21-tag-header :instream instream))
-		  (id3-frame-condition (c)
-			(log-id3-frame "reading v21 got condition: ~a" c))))
-
-	  (stream-seek instream 0 :start)
-	  (when (string= "ID3" (stream-read-string-with-len instream 3))
-		(setf version (stream-read-u8 instream))
-		(setf revision (stream-read-u8 instream))
-		(setf flags (stream-read-u8 instream))
-		(setf size (stream-read-u32 instream :bits-per-byte 7))
-		(when (header-unsynchronized-p flags)
-		  (log-id3-frame "header flags indicate unsync"))
-		(assert (not (header-footer-p flags)) () "Can't decode ID3 footer's yet")
-		(log-id3-frame "id3 header = ~a" (vpprint me nil))))))
+    (with-slots (version revision flags size ext-header frames v21-tag-header) me
+      (stream-seek instream 128 :end)
+      (when (string= "TAG" (stream-read-string-with-len instream 3))
+        (log-id3-frame "looking at last 128 bytes at ~:d to try to read id3v21 header" (stream-seek instream 0 :current))
+        (handler-case
+            (setf v21-tag-header (make-instance 'v21-tag-header :instream instream))
+          (id3-frame-condition (c)
+            (log-id3-frame "reading v21 got condition: ~a" c))))
+
+      (stream-seek instream 0 :start)
+      (when (string= "ID3" (stream-read-string-with-len instream 3))
+        (setf version (stream-read-u8 instream))
+        (setf revision (stream-read-u8 instream))
+        (setf flags (stream-read-u8 instream))
+        (setf size (stream-read-u32 instream :bits-per-byte 7))
+        (when (header-unsynchronized-p flags)
+          (log-id3-frame "header flags indicate unsync"))
+        (assert (not (header-footer-p flags)) () "Can't decode ID3 footer's yet")
+        (log-id3-frame "id3 header = ~a" (vpprint me nil))))))
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; frames ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;;
@@ -196,18 +196,18 @@ Note: extended headers are subject to unsynchronization, so make sure that INSTR
 ;;; the bytes an raw octets.
 (defun get-name-value-pair (instream len name-encoding value-encoding)
   (log5:with-context  "get-name-value-pair"
-	(log-id3-frame "reading from ~:d, len ~:d, name-encoding = ~d, value-encoding = ~d" (stream-seek instream 0 :current) len name-encoding value-encoding)
-	(let* ((old-pos (stream-seek instream 0 :current))
-		   (name (stream-read-string instream :encoding name-encoding))
-		   (name-len (- (stream-seek instream 0 :current) old-pos))
-		   (value))
+    (log-id3-frame "reading from ~:d, len ~:d, name-encoding = ~d, value-encoding = ~d" (stream-seek instream 0 :current) len name-encoding value-encoding)
+    (let* ((old-pos (stream-seek instream 0 :current))
+           (name (stream-read-string instream :encoding name-encoding))
+           (name-len (- (stream-seek instream 0 :current) old-pos))
+           (value))
 
-	  (log-id3-frame "name = <~a>, name-len = ~d" name name-len)
-	  (setf value (if (>= value-encoding 0)
-					  (stream-read-string-with-len instream (- len name-len) :encoding value-encoding)
-					  (stream-read-sequence instream (- len name-len)))) ; if < 0, then just read as octets
+      (log-id3-frame "name = <~a>, name-len = ~d" name name-len)
+      (setf value (if (>= value-encoding 0)
+                      (stream-read-string-with-len instream (- len name-len) :encoding value-encoding)
+                      (stream-read-sequence instream (- len name-len)))) ; if < 0, then just read as octets
 
-	  (values name value))))
+      (values name value))))
 
 (defclass id3-frame ()
   ((pos     :accessor pos     :initarg :pos                 :documentation "the offset in the buffer were this frame was found")
@@ -239,40 +239,40 @@ Note: extended headers are subject to unsynchronization, so make sure that INSTR
 ;; NB version 2.2 does NOT have FLAGS field in a frame; hence, the ECASE
 (defun valid-frame-flags (header-version frame-flags)
   (ecase header-version
-	(3 (zerop (logand #b0001111100011111 frame-flags)))
-	(4 (zerop (logand #b1000111110110000 frame-flags)))))
+    (3 (zerop (logand #b0001111100011111 frame-flags)))
+    (4 (zerop (logand #b1000111110110000 frame-flags)))))
 
 (defun print-frame-flags (version flags stream)
   (ecase version
-	(2 (format stream "None, "))
-	(3 (format stream
-			   "flags: 0x~4,'0x: ~:[0/~;tag-alter-preservation/~]~:[0/~;file-alter-preservation/~]~:[0/~;read-only/~]~:[0/~;compress/~]~:[0/~;encypt/~]~:[0~;group~], "
-			   flags
-			   (frame-23-altertag-p flags)
-			   (frame-23-alterfile-p flags)
-			   (frame-23-readonly-p flags)
-			   (frame-23-compress-p flags)
-			   (frame-23-encrypt-p flags)
-			   (frame-23-group-p flags)))
-	(4 (format stream 
-			   "flags: 0x~4,'0x: ~:[0/~;tag-alter-preservation/~]~:[0/~;file-alter-preservation/~]~:[0/~;read-only/~]~:[0/~;group-id/~]~:[0/~;compress/~]~:[0/~;encypt/~]~:[0/~;unsynch/~]~:[0~;datalen~], "
-			   flags
-			   (frame-24-altertag-p flags)
-			   (frame-24-alterfile-p flags)
-			   (frame-24-readonly-p flags)
-			   (frame-24-groupid-p flags)
-			   (frame-24-compress-p flags)
-			   (frame-24-encrypt-p flags)
-			   (frame-24-unsynch-p flags)
-			   (frame-24-datalen-p flags)))))
+    (2 (format stream "None, "))
+    (3 (format stream
+               "flags: 0x~4,'0x: ~:[0/~;tag-alter-preservation/~]~:[0/~;file-alter-preservation/~]~:[0/~;read-only/~]~:[0/~;compress/~]~:[0/~;encypt/~]~:[0~;group~], "
+               flags
+               (frame-23-altertag-p flags)
+               (frame-23-alterfile-p flags)
+               (frame-23-readonly-p flags)
+               (frame-23-compress-p flags)
+               (frame-23-encrypt-p flags)
+               (frame-23-group-p flags)))
+    (4 (format stream
+               "flags: 0x~4,'0x: ~:[0/~;tag-alter-preservation/~]~:[0/~;file-alter-preservation/~]~:[0/~;read-only/~]~:[0/~;group-id/~]~:[0/~;compress/~]~:[0/~;encypt/~]~:[0/~;unsynch/~]~:[0~;datalen~], "
+               flags
+               (frame-24-altertag-p flags)
+               (frame-24-alterfile-p flags)
+               (frame-24-readonly-p flags)
+               (frame-24-groupid-p flags)
+               (frame-24-compress-p flags)
+               (frame-24-encrypt-p flags)
+               (frame-24-unsynch-p flags)
+               (frame-24-datalen-p flags)))))
 
 (defun vpprint-frame-header (id3-frame)
   (with-output-to-string (stream)
-	(with-slots (pos version id len flags) id3-frame
-	  (format stream "offset: ~:d, version = ~d, id: ~a, len: ~:d, ~a" pos version id len
-			  (if flags
-				  (print-frame-flags version flags stream)
-				  "flags: none")))))
+    (with-slots (pos version id len flags) id3-frame
+      (format stream "offset: ~:d, version = ~d, id: ~a, len: ~:d, ~a" pos version id len
+              (if flags
+                  (print-frame-flags version flags stream)
+                  "flags: none")))))
 
 (defclass frame-raw (id3-frame)
   ((octets :accessor octets :initform nil))
@@ -280,15 +280,15 @@ Note: extended headers are subject to unsynchronization, so make sure that INSTR
 
 (defmethod initialize-instance :after ((me frame-raw) &key instream)
   (log5:with-context "frame-raw"
-	(with-slots (pos len octets) me
-	  (log-id3-frame "reading ~:d bytes from position ~:d" len pos)
-	  (setf octets (stream-read-sequence instream len))
-	  (log-id3-frame "frame: ~a" (vpprint me nil)))))
+    (with-slots (pos len octets) me
+      (log-id3-frame "reading ~:d bytes from position ~:d" len pos)
+      (setf octets (stream-read-sequence instream len))
+      (log-id3-frame "frame: ~a" (vpprint me nil)))))
 
 
 (defmethod vpprint ((me frame-raw) stream)
   (with-slots (octets) me
-	(format stream "frame-raw: ~a, ~a" (vpprint-frame-header me) (printable-array octets))))
+    (format stream "frame-raw: ~a, ~a" (vpprint-frame-header me) (printable-array octets))))
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; V2.2 frames ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 (defclass frame-buf (frame-raw) ())
@@ -331,25 +331,25 @@ Note: extended headers are subject to unsynchronization, so make sure that INSTR
 (defclass frame-com (id3-frame)
   ((encoding :accessor encoding)
    (lang     :accessor lang)
-   (desc	 :accessor desc)
-   (val	     :accessor val)))
+   (desc     :accessor desc)
+   (val      :accessor val)))
 
 (defmethod initialize-instance :after ((me frame-com) &key instream)
   (log5:with-context "frame-com"
-	(with-slots (len encoding lang desc val) me
-	  (setf encoding (stream-read-u8 instream))
-	  (setf lang (stream-read-iso-string-with-len instream 3))
-	  (multiple-value-bind (n v) (get-name-value-pair instream (- len 1 3) encoding encoding)
-		(setf desc n)
+    (with-slots (len encoding lang desc val) me
+      (setf encoding (stream-read-u8 instream))
+      (setf lang (stream-read-iso-string-with-len instream 3))
+      (multiple-value-bind (n v) (get-name-value-pair instream (- len 1 3) encoding encoding)
+        (setf desc n)
 
-		;; iTunes broken-ness... for frame-coms, there can be an additional null or two at the end
-		(setf val (upto-null v)))
-	  (log-id3-frame "encoding = ~d, lang = <~a>, desc = <~a>, text = <~a>" encoding lang desc val))))
+        ;; iTunes broken-ness... for frame-coms, there can be an additional null or two at the end
+        (setf val (upto-null v)))
+      (log-id3-frame "encoding = ~d, lang = <~a>, desc = <~a>, text = <~a>" encoding lang desc val))))
 
 (defmethod vpprint ((me frame-com) stream)
   (with-slots (len encoding lang desc val) me
-	(format stream "frame-com: ~a, encoding = ~d, lang = <~a> (~a), desc = <~a>, val = <~a>"
-			(vpprint-frame-header me) encoding lang (get-iso-639-2-language lang) desc val)))
+    (format stream "frame-com: ~a, encoding = ~d, lang = <~a> (~a), desc = <~a>, val = <~a>"
+            (vpprint-frame-header me) encoding lang (get-iso-639-2-language lang) desc val)))
 
 ;;; ULT's are same format as COM's... XXX rewrite this as suggested in comment at bottom of this file
 ;;; V22 unsynced lyrics/text "ULT"
@@ -375,20 +375,20 @@ Note: extended headers are subject to unsynchronization, so make sure that INSTR
 
 (defmethod initialize-instance :after ((me frame-pic) &key instream)
   (log5:with-context "frame-pic"
-	(with-slots (id len encoding img-format type desc data) me
-	  (setf encoding (stream-read-u8 instream))
-	  (setf img-format (stream-read-iso-string-with-len instream 3))
-	  (setf type (stream-read-u8 instream))
-	  (multiple-value-bind (n v) (get-name-value-pair instream (- len 5) encoding -1)
-		(setf desc n)
-		(setf data v)
-		(log-id3-frame "encoding: ~d, img-format = <~a>, type = ~d (~a), desc = <~a>, value = ~a"
-				   encoding img-format type (get-picture-type type) desc (printable-array data))))))
+    (with-slots (id len encoding img-format type desc data) me
+      (setf encoding (stream-read-u8 instream))
+      (setf img-format (stream-read-iso-string-with-len instream 3))
+      (setf type (stream-read-u8 instream))
+      (multiple-value-bind (n v) (get-name-value-pair instream (- len 5) encoding -1)
+        (setf desc n)
+        (setf data v)
+        (log-id3-frame "encoding: ~d, img-format = <~a>, type = ~d (~a), desc = <~a>, value = ~a"
+                   encoding img-format type (get-picture-type type) desc (printable-array data))))))
 
 (defmethod vpprint ((me frame-pic) stream)
   (with-slots (encoding img-format type desc data) me
-	(format stream "frame-pic: ~a,  encoding ~d, img-format type: <~a>, picture type: ~d (~a), description <~a>, data: ~a"
-			(vpprint-frame-header me) encoding img-format type (get-picture-type type) desc (printable-array data))))
+    (format stream "frame-pic: ~a,  encoding ~d, img-format type: <~a>, picture type: ~d (~a), description <~a>, data: ~a"
+            (vpprint-frame-header me) encoding img-format type (get-picture-type type) desc (printable-array data))))
 
 ;; Version 2, 3, or 4 generic text-info frames
 ;; Text information identifier  "T00" - "TZZ", excluding "TXX", or "T000 - TZZZ", excluding "TXXX"
@@ -401,28 +401,28 @@ Note: extended headers are subject to unsynchronization, so make sure that INSTR
 
 (defmethod initialize-instance :after ((me frame-text-info) &key instream)
   (log5:with-context "frame-text-info"
-	(with-slots (version flags len encoding info) me
-	  (let ((read-len len))
+    (with-slots (version flags len encoding info) me
+      (let ((read-len len))
 
-		;; In version 4 frames, each frame may also have an unsync flag.  since we have unsynced already
-		;; the only thing we need to do here is check for the optional DATALEN field.  If it is present
-		;; then it has the actual number of octets to read
-		(when (and (= version 4) (frame-24-unsynch-p flags))
-		  (if (frame-24-datalen-p flags)
-			  (setf read-len (stream-read-u32 instream :bits-per-byte 7))))
+        ;; In version 4 frames, each frame may also have an unsync flag.  since we have unsynced already
+        ;; the only thing we need to do here is check for the optional DATALEN field.  If it is present
+        ;; then it has the actual number of octets to read
+        (when (and (= version 4) (frame-24-unsynch-p flags))
+          (if (frame-24-datalen-p flags)
+              (setf read-len (stream-read-u32 instream :bits-per-byte 7))))
 
-		(setf encoding (stream-read-u8 instream))
-		(setf info (stream-read-string-with-len instream (1- read-len) :encoding encoding)))
+        (setf encoding (stream-read-u8 instream))
+        (setf info (stream-read-string-with-len instream (1- read-len) :encoding encoding)))
 
-	  ;; A null is ok, but according to the "spec", you're supposed to ignore anything after a 'Null'
-	  (log-id3-frame "made text-info-frame: ~a" (vpprint me nil))
-	  (setf info (upto-null info))
+      ;; A null is ok, but according to the "spec", you're supposed to ignore anything after a 'Null'
+      (log-id3-frame "made text-info-frame: ~a" (vpprint me nil))
+      (setf info (upto-null info))
 
-	  (log-id3-frame "encoding = ~d, info = <~a>" encoding info))))
+      (log-id3-frame "encoding = ~d, info = <~a>" encoding info))))
 
 (defmethod vpprint ((me frame-text-info) stream)
   (with-slots (len encoding info) me
-	(format stream "frame-text-info: ~a, encoding = ~d, info = <~a>" (vpprint-frame-header me) encoding info)))
+    (format stream "frame-text-info: ~a, encoding = ~d, info = <~a>" (vpprint-frame-header me) encoding info)))
 
 (defclass frame-tal (frame-text-info) ())
 (defclass frame-tbp (frame-text-info) ())
@@ -473,16 +473,16 @@ Note: extended headers are subject to unsynchronization, so make sure that INSTR
 
 (defmethod initialize-instance :after ((me frame-txx) &key instream)
   (log5:with-context "frame-txx"
-	(with-slots (len encoding desc val) me
-	  (setf encoding (stream-read-u8 instream))
-	  (multiple-value-bind (n v) (get-name-value-pair instream (1- len) encoding encoding)
-		(setf desc n)
-		(setf val v)
-		(log-id3-frame "encoding = ~d, desc = <~a>, val = <~a>" encoding desc val)))))
+    (with-slots (len encoding desc val) me
+      (setf encoding (stream-read-u8 instream))
+      (multiple-value-bind (n v) (get-name-value-pair instream (1- len) encoding encoding)
+        (setf desc n)
+        (setf val v)
+        (log-id3-frame "encoding = ~d, desc = <~a>, val = <~a>" encoding desc val)))))
 
 (defmethod vpprint ((me frame-txx) stream)
   (with-slots (len encoding desc val) me
-	(format stream "frame-txx: ~a, encoding = ~d, desc = <~a>, val = <~a>" (vpprint-frame-header me) encoding desc val)))
+    (format stream "frame-txx: ~a, encoding = ~d, desc = <~a>, val = <~a>" (vpprint-frame-header me) encoding desc val)))
 
 ;;; V22 unique file identifier  "UFI"
 ;;; Owner identifier        <textstring> $00
@@ -494,15 +494,15 @@ Note: extended headers are subject to unsynchronization, so make sure that INSTR
 
 (defmethod initialize-instance :after ((me frame-ufi) &key instream)
   (log5:with-context "frame-ufi"
-	(with-slots (id len name value) me
-	  (multiple-value-bind (n v) (get-name-value-pair instream len 0 -1)
-		(setf name n)
-		(setf value v))
-	  (log-id3-frame "name = <~a>, value = ~a" name (printable-array value)))))
+    (with-slots (id len name value) me
+      (multiple-value-bind (n v) (get-name-value-pair instream len 0 -1)
+        (setf name n)
+        (setf value v))
+      (log-id3-frame "name = <~a>, value = ~a" name (printable-array value)))))
 
 (defmethod vpprint ((me frame-ufi) stream)
   (with-slots (id len name value) me
-	(format stream "frame-ufi: ~a, name: <~a>, value: ~a" (vpprint-frame-header me) name (printable-array value))))
+    (format stream "frame-ufi: ~a, name: <~a>, value: ~a" (vpprint-frame-header me) name (printable-array value))))
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; V23/V24 frames ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 (defclass frame-aenc (frame-raw) ())
@@ -588,32 +588,32 @@ Note: extended headers are subject to unsynchronization, so make sure that INSTR
 
 (defparameter *picture-type*
   '("Other"
-	"32x32 pixels 'file icon' (PNG only)"
-	"Other file icon"
-	"Cover (front)"
-	"Cover (back)"
-	"Leaflet page"
-	"Media (e.g. lable side of CD)"
-	"Lead artist/lead performer/soloist"
-	"Artist/performer"
-	"Conductor"
-	"Band/Orchestra"
-	"Composer"
-	"Lyricist/text writer"
-	"Recording Location"
-	"During recording"
-	"During performance"
-	"Movie/video screen capture"
-	"A bright coloured fish"	; how do you know the fish is intelligent? :)
-	"Illustration"
-	"Band/artist logotype"
-	"Publisher/Studio logotype"))
+    "32x32 pixels 'file icon' (PNG only)"
+    "Other file icon"
+    "Cover (front)"
+    "Cover (back)"
+    "Leaflet page"
+    "Media (e.g. lable side of CD)"
+    "Lead artist/lead performer/soloist"
+    "Artist/performer"
+    "Conductor"
+    "Band/Orchestra"
+    "Composer"
+    "Lyricist/text writer"
+    "Recording Location"
+    "During recording"
+    "During performance"
+    "Movie/video screen capture"
+    "A bright coloured fish"    ; how do you know the fish is intelligent? :)
+    "Illustration"
+    "Band/artist logotype"
+    "Publisher/Studio logotype"))
 
 (defun get-picture-type (n)
   "Function to return picture types for APIC frames"
   (if (and (>= n 0) (< n (length *picture-type*)))
-	  (nth n *picture-type*)
-	  "Unknown"))
+      (nth n *picture-type*)
+      "Unknown"))
 
 ;; V23/V24 APIC frames
 ;; <Header for 'Attached picture', ID: "APIC">
@@ -632,19 +632,19 @@ Note: extended headers are subject to unsynchronization, so make sure that INSTR
 
 (defmethod initialize-instance :after ((me frame-apic) &key instream)
   (log5:with-context "frame-apic"
-	(with-slots (id len encoding mime type desc data) me
-	  (setf encoding (stream-read-u8 instream))
-	  (setf mime (stream-read-iso-string instream))
-	  (setf type (stream-read-u8 instream))
-	  (multiple-value-bind (n v) (get-name-value-pair instream (- len 1 (length mime) 1 1) encoding -1)
-		(setf desc n)
-		(setf data v)
-		(log-id3-frame "enoding = ~d, mime = <~a>, type = ~d (~a), desc = <~a>, data = ~a" encoding mime type (get-picture-type type) desc (printable-array data))))))
+    (with-slots (id len encoding mime type desc data) me
+      (setf encoding (stream-read-u8 instream))
+      (setf mime (stream-read-iso-string instream))
+      (setf type (stream-read-u8 instream))
+      (multiple-value-bind (n v) (get-name-value-pair instream (- len 1 (length mime) 1 1) encoding -1)
+        (setf desc n)
+        (setf data v)
+        (log-id3-frame "enoding = ~d, mime = <~a>, type = ~d (~a), desc = <~a>, data = ~a" encoding mime type (get-picture-type type) desc (printable-array data))))))
 
 (defmethod vpprint ((me frame-apic) stream)
   (with-slots (encoding mime type desc data) me
-	(format stream "frame-apic: ~a, encoding ~d, mime type: ~a, picture type: ~d (~a), description <~a>, data: ~a"
-			(vpprint-frame-header me) encoding mime type (get-picture-type type) desc (printable-array data))))
+    (format stream "frame-apic: ~a, encoding ~d, mime type: ~a, picture type: ~d (~a), description <~a>, data: ~a"
+            (vpprint-frame-header me) encoding mime type (get-picture-type type) desc (printable-array data))))
 
 ;;; V23/V24 COMM frames
 ;;; <Header for 'Comment', ID: "COMM">
@@ -654,27 +654,27 @@ Note: extended headers are subject to unsynchronization, so make sure that INSTR
 ;;; The actual text         <full text string according to encoding>
 (defclass frame-comm (id3-frame)
   ((encoding :accessor encoding)
-   (lang	 :accessor lang)
+   (lang     :accessor lang)
    (desc     :accessor desc)
-   (val		 :accessor val))
+   (val      :accessor val))
   (:documentation "V23/4 Comment frame"))
 
 (defmethod initialize-instance :after ((me frame-comm) &key instream)
   (log5:with-context "frame-comm"
-	(with-slots (encoding lang len desc val) me
-	  (setf encoding (stream-read-u8 instream))
-	  (setf lang (stream-read-iso-string-with-len instream 3))
-	  (multiple-value-bind (n v) (get-name-value-pair instream (- len 1 3) encoding encoding)
-		(setf desc n)
+    (with-slots (encoding lang len desc val) me
+      (setf encoding (stream-read-u8 instream))
+      (setf lang (stream-read-iso-string-with-len instream 3))
+      (multiple-value-bind (n v) (get-name-value-pair instream (- len 1 3) encoding encoding)
+        (setf desc n)
 
-		;; iTunes broken-ness... for frame-coms, there can be an additional null or two at the end
-		(setf val (upto-null v)))
-	  (log-id3-frame "encoding = ~d, lang = <~a>, desc = <~a>, val = <~a>" encoding lang desc val))))
+        ;; iTunes broken-ness... for frame-coms, there can be an additional null or two at the end
+        (setf val (upto-null v)))
+      (log-id3-frame "encoding = ~d, lang = <~a>, desc = <~a>, val = <~a>" encoding lang desc val))))
 
 (defmethod vpprint ((me frame-comm) stream)
   (with-slots (encoding lang desc val) me
-	(format stream "frame-comm: ~a,  encoding: ~d, lang: <~a> (~a), desc = <~a>, val = <~a>"
-			(vpprint-frame-header me) encoding lang (get-iso-639-2-language lang) desc val)))
+    (format stream "frame-comm: ~a,  encoding: ~d, lang: <~a> (~a), desc = <~a>, val = <~a>"
+            (vpprint-frame-header me) encoding lang (get-iso-639-2-language lang) desc val)))
 
 ;;; Unsynchronized lyrics frames look very much like comment frames...
 (defclass frame-uslt (frame-comm) ())
@@ -688,14 +688,14 @@ Note: extended headers are subject to unsynchronization, so make sure that INSTR
 
 (defmethod initialize-instance :after ((me frame-pcnt) &key instream)
   (log5:with-context "frame-pcnt"
-	(with-slots (play-count len) me
-	  (assert (= 4 len) () "Ran into a play count with ~d bytes" len)
-	  (setf play-count (stream-read-u32 instream)) ; probably safe---play count *can* be longer than 4 bytes, but...
-	  (log-id3-frame "play count = <~d>" play-count))))
+    (with-slots (play-count len) me
+      (assert (= 4 len) () "Ran into a play count with ~d bytes" len)
+      (setf play-count (stream-read-u32 instream)) ; probably safe---play count *can* be longer than 4 bytes, but...
+      (log-id3-frame "play count = <~d>" play-count))))
 
 (defmethod vpprint ((me frame-pcnt) stream)
   (with-slots (play-count) me
-	(format stream "frame-pcnt: ~a, count = ~d" (vpprint-frame-header me) play-count)))
+    (format stream "frame-pcnt: ~a, count = ~d" (vpprint-frame-header me) play-count)))
 
 ;;; V23/V24 PRIV frames
 ;;; <Header for 'Private frame', ID: "PRIV">
@@ -708,21 +708,21 @@ Note: extended headers are subject to unsynchronization, so make sure that INSTR
 
 (defmethod initialize-instance :after ((me frame-priv) &key instream)
   (log5:with-context "frame-priv"
-	(with-slots (id len name value) me
-	  (multiple-value-bind (n v) (get-name-value-pair instream len 0 -1)
-		(setf name n)
-		(setf value v)
-		(log-id3-frame "name = <~a>, value = <~a>" name value)))))
+    (with-slots (id len name value) me
+      (multiple-value-bind (n v) (get-name-value-pair instream len 0 -1)
+        (setf name n)
+        (setf value v)
+        (log-id3-frame "name = <~a>, value = <~a>" name value)))))
 
 (defmethod vpprint ((me frame-priv) stream)
   (with-slots (id len name value) me
-	(format stream "frame-priv: ~a, name: <~a>, data: ~a" (vpprint-frame-header me) name (printable-array value))))
+    (format stream "frame-priv: ~a, name: <~a>, data: ~a" (vpprint-frame-header me) name (printable-array value))))
 
 ;; V23/V24 TXXX frames
 ;; <Header for 'User defined text information frame', ID: "TXXX">
 ;; Text encoding    $xx
 ;; Description      <text string according to encoding> $00 (00)
-;; Value    	    <text string according to encoding>
+;; Value            <text string according to encoding>
 (defclass frame-txxx (id3-frame)
   ((encoding :accessor encoding)
    (desc     :accessor desc)
@@ -731,15 +731,15 @@ Note: extended headers are subject to unsynchronization, so make sure that INSTR
 
 (defmethod initialize-instance :after ((me frame-txxx) &key instream)
   (log5:with-context "frame-txxx"
-	(with-slots (encoding len desc val) me
-	  (setf encoding (stream-read-u8 instream))
-	  (multiple-value-bind (n v) (get-name-value-pair instream
-													  (- len 1)
-													  encoding
-													  encoding)
-		(setf desc n)
-		(setf val v))
-	  (log-id3-frame "encoding = ~d, desc = <~a>, value = <~a>" encoding desc val))))
+    (with-slots (encoding len desc val) me
+      (setf encoding (stream-read-u8 instream))
+      (multiple-value-bind (n v) (get-name-value-pair instream
+                                                      (- len 1)
+                                                      encoding
+                                                      encoding)
+        (setf desc n)
+        (setf val v))
+      (log-id3-frame "encoding = ~d, desc = <~a>, value = <~a>" encoding desc val))))
 
 (defmethod vpprint ((me frame-txxx) stream)
   (format stream "frame-txxx: ~a, <~a/~a>" (vpprint-frame-header me) (desc me) (val me)))
@@ -747,7 +747,7 @@ Note: extended headers are subject to unsynchronization, so make sure that INSTR
 ;; V23/V24 UFID frames
 ;; <Header for 'Unique file identifier', ID: "UFID">
 ;; Owner identifier    <text string> $00
-;; Identifier    	   <up to 64 bytes binary data>
+;; Identifier          <up to 64 bytes binary data>
 (defclass frame-ufid (id3-frame)
   ((name  :accessor name)
    (value :accessor value))
@@ -755,15 +755,15 @@ Note: extended headers are subject to unsynchronization, so make sure that INSTR
 
 (defmethod initialize-instance :after ((me frame-ufid) &key instream)
   (log5:with-context "frame-ufid"
-	(with-slots (id len name value) me
-	  (multiple-value-bind (n v) (get-name-value-pair instream len 0 -1)
-		(setf name n)
-		(setf value v))
-	  (log-id3-frame "name = <~a>, value = ~a" name (printable-array value)))))
+    (with-slots (id len name value) me
+      (multiple-value-bind (n v) (get-name-value-pair instream len 0 -1)
+        (setf name n)
+        (setf value v))
+      (log-id3-frame "name = <~a>, value = ~a" name (printable-array value)))))
 
 (defmethod vpprint ((me frame-ufid) stream)
   (with-slots (id len name value) me
-	(format stream "frame-ufid: ~a,  name: <~a>, value: ~a" (vpprint-frame-header me) name (printable-array value))))
+    (format stream "frame-ufid: ~a,  name: <~a>, value: ~a" (vpprint-frame-header me) name (printable-array value))))
 
 ;;; V23/V24 URL frame
 ;;; <Header for 'URL link frame', ID: "W000" - "WZZZ", excluding "WXXX" described in 4.3.2.>
@@ -774,13 +774,13 @@ Note: extended headers are subject to unsynchronization, so make sure that INSTR
 
 (defmethod initialize-instance :after ((me frame-url-link) &key instream)
   (with-slots (id len url) me
-	(log5:with-context "url"
-	  (setf url (stream-read-iso-string-with-len instream len))
-	  (log-id3-frame "url = <~a>" url))))
+    (log5:with-context "url"
+      (setf url (stream-read-iso-string-with-len instream len))
+      (log-id3-frame "url = <~a>" url))))
 
 (defmethod vpprint ((me frame-url-link) stream)
   (with-slots (url) me
-	(format stream "frame-url-link: ~a, url: ~a" (vpprint-frame-header me) url)))
+    (format stream "frame-url-link: ~a, url: ~a" (vpprint-frame-header me) url)))
 
 ;;; V23/V24 frames URL link frames
 (defclass frame-wcom (frame-url-link) ())
@@ -800,140 +800,140 @@ Note: extended headers are subject to unsynchronization, so make sure that INSTR
 (defun possibly-valid-frame-id? (frame-id)
   "test to see if a string is a potentially valid frame id"
   (labels ((numeric-char-p (c)
-			 (let ((code (char-code c)))
-			   (and (>= code (char-code #\0))
-					(<= code (char-code #\9))))))
-
-	;; test each octet to see if it is alphanumeric
-	(dotimes (i (length frame-id))
-	  (let ((c (aref frame-id i)))
-		(when (not (or (numeric-char-p c)
-					   (and (alpha-char-p c) (upper-case-p c))))
-		  (return-from possibly-valid-frame-id? nil))))
-	t))
+             (let ((code (char-code c)))
+               (and (>= code (char-code #\0))
+                    (<= code (char-code #\9))))))
+
+    ;; test each octet to see if it is alphanumeric
+    (dotimes (i (length frame-id))
+      (let ((c (aref frame-id i)))
+        (when (not (or (numeric-char-p c)
+                       (and (alpha-char-p c) (upper-case-p c))))
+          (return-from possibly-valid-frame-id? nil))))
+    t))
 
 (defun find-frame-class (id)
   "Search by concatenating 'frame-' with ID and look for that symbol in this package"
   (log5:with-context "find-frame-class"
-	(log-id3-frame "looking for class <~a>" id)
-	(let ((found-class-symbol (find-symbol (string-upcase (concatenate 'string "frame-" id)) :ID3-FRAME))
-		  found-class)
-
-	  ;; if we found the class name, return the class (to be used for MAKE-INSTANCE)
-	  (when found-class-symbol
-		(setf found-class (find-class found-class-symbol))
-		(log-id3-frame "found class: ~a" found-class)
-		(return-from find-frame-class found-class))
-
-	  (log-id3-frame "didn't find class, checking general cases")
-
-	  ;; if not a "normal" frame-id, look at general cases of
-	  ;; starting with a 'T' or a 'W'
-	  (setf found-class (case (aref id 0)
-						  (#\T (log-id3-frame "assuming text-info") (find-class (find-symbol "FRAME-TEXT-INFO" :ID3-FRAME)))
-						  (#\W (log-id3-frame "assuming url-link")  (find-class (find-symbol "FRAME-URL-LINK"  :ID3-FRAME)))
-						  (t
-						   ;; we don't recognize the frame name.  if it could possibly be a real frame name,
-						   ;; then just read it raw
-						   (when (possibly-valid-frame-id? id)
-							 (log-id3-frame "just reading raw")
-							 (find-class (find-symbol "FRAME-RAW" :ID3-FRAME))))))
-
-	  (log-id3-frame "general case for id <~a> is ~a" id found-class)
-	  found-class)))
+    (log-id3-frame "looking for class <~a>" id)
+    (let ((found-class-symbol (find-symbol (string-upcase (concatenate 'string "frame-" id)) :ID3-FRAME))
+          found-class)
+
+      ;; if we found the class name, return the class (to be used for MAKE-INSTANCE)
+      (when found-class-symbol
+        (setf found-class (find-class found-class-symbol))
+        (log-id3-frame "found class: ~a" found-class)
+        (return-from find-frame-class found-class))
+
+      (log-id3-frame "didn't find class, checking general cases")
+
+      ;; if not a "normal" frame-id, look at general cases of
+      ;; starting with a 'T' or a 'W'
+      (setf found-class (case (aref id 0)
+                          (#\T (log-id3-frame "assuming text-info") (find-class (find-symbol "FRAME-TEXT-INFO" :ID3-FRAME)))
+                          (#\W (log-id3-frame "assuming url-link")  (find-class (find-symbol "FRAME-URL-LINK"  :ID3-FRAME)))
+                          (t
+                           ;; we don't recognize the frame name.  if it could possibly be a real frame name,
+                           ;; then just read it raw
+                           (when (possibly-valid-frame-id? id)
+                             (log-id3-frame "just reading raw")
+                             (find-class (find-symbol "FRAME-RAW" :ID3-FRAME))))))
+
+      (log-id3-frame "general case for id <~a> is ~a" id found-class)
+      found-class)))
 
 (defun make-frame (version instream)
   "Create an appropriate mp3 frame by reading data from INSTREAM."
   (log5:with-context "make-frame"
-	(let* ((pos (stream-seek instream 0 :current))
-		   (byte (stream-read-u8 instream))
-		   frame-name frame-len frame-flags frame-class)
+    (let* ((pos (stream-seek instream 0 :current))
+           (byte (stream-read-u8 instream))
+           frame-name frame-len frame-flags frame-class)
 
-	  (log-id3-frame "reading from position ~:d (size of stream = ~:d)" pos (stream-size instream))
+      (log-id3-frame "reading from position ~:d (size of stream = ~:d)" pos (stream-size instream))
 
-	  (when (zerop byte)				; XXX should this be correlated to PADDING in the extended header???
-		(log-id3-frame "hit padding of size ~:d while making a frame" 9999) ;(- (stream-size instream) pos))
-		(return-from make-frame nil))	; hit padding
+      (when (zerop byte)                ; XXX should this be correlated to PADDING in the extended header???
+        (log-id3-frame "hit padding of size ~:d while making a frame" 9999) ;(- (stream-size instream) pos))
+        (return-from make-frame nil))   ; hit padding
 
-	  (setf frame-name
-			(concatenate 'string (string (code-char byte)) (stream-read-string-with-len instream (ecase version (2 2) (3 3) (4 3)))))
+      (setf frame-name
+            (concatenate 'string (string (code-char byte)) (stream-read-string-with-len instream (ecase version (2 2) (3 3) (4 3)))))
 
-	  (setf frame-len (ecase version
-						(2 (stream-read-u24 instream))
-						(3 (stream-read-u32 instream))
-						(4 (stream-read-u32 instream :bits-per-byte 7))))
+      (setf frame-len (ecase version
+                        (2 (stream-read-u24 instream))
+                        (3 (stream-read-u32 instream))
+                        (4 (stream-read-u32 instream :bits-per-byte 7))))
 
-	  (when (or (= version 3) (= version 4))
-		(setf frame-flags (stream-read-u16 instream))
-		(when (not (valid-frame-flags version frame-flags))
-		  (warn-user "Invalid frame flags found ~a, will ignore" (print-frame-flags version frame-flags nil))))
+      (when (or (= version 3) (= version 4))
+        (setf frame-flags (stream-read-u16 instream))
+        (when (not (valid-frame-flags version frame-flags))
+          (warn-user "Invalid frame flags found ~a, will ignore" (print-frame-flags version frame-flags nil))))
 
-	  (log-id3-frame "making frame: id:~a, version: ~d, len: ~:d, flags: ~a"
-					 frame-name version frame-len
-					 (print-frame-flags version frame-flags nil))
-	  (setf frame-class (find-frame-class frame-name))
+      (log-id3-frame "making frame: id:~a, version: ~d, len: ~:d, flags: ~a"
+                     frame-name version frame-len
+                     (print-frame-flags version frame-flags nil))
+      (setf frame-class (find-frame-class frame-name))
 
-	  ;; edge case where found a frame name, but it is not valid or where making this frame
-	  ;; would blow past the end of the file/buffer
-	  (when (or (> (+ (stream-seek instream 0 :current) frame-len) (stream-size instream))
-				(null frame-class))
-		(error 'id3-frame-condition :message "bad frame found" :object frame-name :location pos))
+      ;; edge case where found a frame name, but it is not valid or where making this frame
+      ;; would blow past the end of the file/buffer
+      (when (or (> (+ (stream-seek instream 0 :current) frame-len) (stream-size instream))
+                (null frame-class))
+        (error 'id3-frame-condition :message "bad frame found" :object frame-name :location pos))
 
-	  (make-instance frame-class :pos pos :version version :id frame-name :len frame-len :flags frame-flags :instream instream))))
+      (make-instance frame-class :pos pos :version version :id frame-name :len frame-len :flags frame-flags :instream instream))))
 
 (defun find-id3-frames (mp3-file)
   "With an open mp3-file, make sure it is in fact an MP3 file, then read it's header and frames"
 
   (labels ((read-loop (version stream)
-			 (log5:with-context "read-loop-in-find-id3-frames"
-			   (log-id3-frame "Starting loop through ~:d bytes" (stream-size stream))
-			   (let (frames this-frame)
-				 (do ()
-					 ((>= (stream-seek stream 0 :current) (stream-size stream)))
-				   (handler-case
-					   (progn
-						 (setf this-frame (make-frame version stream))
-						 (when (null this-frame)
-						   (log-id3-frame "hit padding: returning ~d frames" (length frames))
-						   (return-from read-loop (values t (nreverse frames))))
-
-						 (log-id3-frame "bottom of read-loop: pos = ~:d, size = ~:d" (stream-seek stream 0 :current) (stream-size stream))
-						 (push this-frame frames))
-					 (condition (c)
-					   (log-id3-frame "got condition ~a when making frame" c)
-					   (return-from read-loop (values nil (nreverse frames))))))
-
-				 (log-id3-frame "Succesful read: returning ~d frames" (length frames))
-				 (values t (nreverse frames)))))) ; reverse this so we have frames in "file order"
-
-	(log5:with-context "find-id3-frames"
-	  (when (not (is-valid-mp3-file mp3-file))
-		(log-id3-frame "~a is not an mp3 file" (stream-filename mp3-file))
-		(error 'id3-frame-condition :location "find-id3-frames" :object (stream-filename mp3-file) :message "is not an mp3 file"))
-
-	  (log-id3-frame "~a is a valid mp3 file" (stream-filename mp3-file))
-
-	  (setf (id3-header mp3-file) (make-instance 'id3-header :instream mp3-file))
-	  (with-slots (size ext-header frames flags version) (id3-header mp3-file)
-
-		;; At this point, we switch from reading the file stream and create a memory stream
-		;; rationale: it may need to be unsysnc'ed and it helps prevent run-away reads with
-		;; mis-formed frames
-		(when (not (zerop size))
-		  (let ((mem-stream (make-mem-stream (stream-read-sequence mp3-file size
-																   :bits-per-byte (if (header-unsynchronized-p flags) 7 8)))))
-
-			;; Must make extended header here since it is subject to unsynchronization.
-			(when (header-extended-p flags)
-			  (setf ext-header (make-instance 'id3-extended-header :instream mem-stream)))
-
-			;; Start reading frames from memory stream
-			(multiple-value-bind (_ok _frames) (read-loop version mem-stream)
-			  (if (not _ok)
-				  (warn-user "File ~a had errors finding mp3 frames. potentially missed frames!" (stream-filename mp3-file)))
-			  (log-id3-frame "ok = ~a, returning ~d frames" _ok (length _frames))
-			  (setf frames _frames)
-			  _ok)))))))
+             (log5:with-context "read-loop-in-find-id3-frames"
+               (log-id3-frame "Starting loop through ~:d bytes" (stream-size stream))
+               (let (frames this-frame)
+                 (do ()
+                     ((>= (stream-seek stream 0 :current) (stream-size stream)))
+                   (handler-case
+                       (progn
+                         (setf this-frame (make-frame version stream))
+                         (when (null this-frame)
+                           (log-id3-frame "hit padding: returning ~d frames" (length frames))
+                           (return-from read-loop (values t (nreverse frames))))
+
+                         (log-id3-frame "bottom of read-loop: pos = ~:d, size = ~:d" (stream-seek stream 0 :current) (stream-size stream))
+                         (push this-frame frames))
+                     (condition (c)
+                       (log-id3-frame "got condition ~a when making frame" c)
+                       (return-from read-loop (values nil (nreverse frames))))))
+
+                 (log-id3-frame "Succesful read: returning ~d frames" (length frames))
+                 (values t (nreverse frames)))))) ; reverse this so we have frames in "file order"
+
+    (log5:with-context "find-id3-frames"
+      (when (not (is-valid-mp3-file mp3-file))
+        (log-id3-frame "~a is not an mp3 file" (stream-filename mp3-file))
+        (error 'id3-frame-condition :location "find-id3-frames" :object (stream-filename mp3-file) :message "is not an mp3 file"))
+
+      (log-id3-frame "~a is a valid mp3 file" (stream-filename mp3-file))
+
+      (setf (id3-header mp3-file) (make-instance 'id3-header :instream mp3-file))
+      (with-slots (size ext-header frames flags version) (id3-header mp3-file)
+
+        ;; At this point, we switch from reading the file stream and create a memory stream
+        ;; rationale: it may need to be unsysnc'ed and it helps prevent run-away reads with
+        ;; mis-formed frames
+        (when (not (zerop size))
+          (let ((mem-stream (make-mem-stream (stream-read-sequence mp3-file size
+                                                                   :bits-per-byte (if (header-unsynchronized-p flags) 7 8)))))
+
+            ;; Must make extended header here since it is subject to unsynchronization.
+            (when (header-extended-p flags)
+              (setf ext-header (make-instance 'id3-extended-header :instream mem-stream)))
+
+            ;; Start reading frames from memory stream
+            (multiple-value-bind (_ok _frames) (read-loop version mem-stream)
+              (if (not _ok)
+                  (warn-user "File ~a had errors finding mp3 frames. potentially missed frames!" (stream-filename mp3-file)))
+              (log-id3-frame "ok = ~a, returning ~d frames" _ok (length _frames))
+              (setf frames _frames)
+              _ok)))))))
 
 (defun map-id3-frames (mp3-file &key (func (constantly t)))
   "Iterates through the ID3 frames found in an MP3 file"

+ 1 - 1
iso-639-2.lisp

@@ -492,6 +492,6 @@
 (defun get-iso-639-2-language (l)
   "Convert an ISO-639-2 language tag into a readable language."
   (let* ((lang (getf *langs* (alexandria:make-keyword (string-upcase l)))))
-	(if lang lang "Bad ISO-639-2 language")))
+    (if lang lang "Bad ISO-639-2 language")))
 
 

+ 22 - 22
logging.lisp

@@ -4,33 +4,33 @@
 (in-package #:logging)
 
 (defmacro start-logging ((name spec) &body body)
-  `(unwind-protect 
-		(progn
-		  (log5:start-sender 'trace-log
-			  (log5:stream-sender :location ,name)
-			  :category-spec ,spec
-			  :output-spec '(log5:message log5:context))
-		  ,@body)
-	 (log5:stop-sender 'trace-log)))
+  `(unwind-protect
+        (progn
+          (log5:start-sender 'trace-log
+              (log5:stream-sender :location ,name)
+              :category-spec ,spec
+              :output-spec '(log5:message log5:context))
+          ,@body)
+     (log5:stop-sender 'trace-log)))
 
 
 (defparameter *logging-categories* '(mp4-atom::cat-log-mp4-atom
-									 audio-streams::cat-log-stream
-									 mpeg::cat-log-mpeg-frame
-									 id3-frame::cat-log-id3-frame))
+                                     audio-streams::cat-log-stream
+                                     mpeg::cat-log-mpeg-frame
+                                     id3-frame::cat-log-id3-frame))
 
 
 (defmacro with-logging ((&optional file &key (categories *logging-categories*)) &body body)
   (alexandria:with-gensyms (output-stream)
-	`(let (,output-stream)
-	   (unwind-protect
-			(setf ,output-stream (if ,file
-									 (open ,file :direction :output :if-exists :supersede :if-does-not-exist :create)
-									 *standard-output*))
-			(log5:start-sender 'trace-log (log5:stream-sender :location ,output-stream)
-							   :category-spec ',categories
-							   :output-spec '(log5:message log5:context))
-			,@body)
-	   (if ,file (close ,output-stream))
-	   (log5:stop-sender 'trace-log))))
+    `(let (,output-stream)
+       (unwind-protect
+            (setf ,output-stream (if ,file
+                                     (open ,file :direction :output :if-exists :supersede :if-does-not-exist :create)
+                                     *standard-output*))
+            (log5:start-sender 'trace-log (log5:stream-sender :location ,output-stream)
+                               :category-spec ',categories
+                               :output-spec '(log5:message log5:context))
+            ,@body)
+       (if ,file (close ,output-stream))
+       (log5:stop-sender 'trace-log))))
 

+ 291 - 291
mp3-tag.lisp

@@ -4,385 +4,385 @@
 
 (defparameter *id3v1-genres*
   #("Blues"
-	"Classic Rock"
-	"Country"
-	"Dance"
-	"Disco"
-	"Funk"
-	"Grunge"
-	"Hip-Hop"
-	"Jazz"
-	"Metal"
-	"New Age"
-	"Oldies"
-	"Other"
-	"Pop"
-	"R&B"
-	"Rap"
-	"Reggae"
-	"Rock"
-	"Techno"
-	"Industrial"
-	"Alternative"
-	"Ska"
-	"Death Metal"
-	"Pranks"
-	"Soundtrack"
-	"Euro-Techno"
-	"Ambient"
-	"Trip-Hop"
-	"Vocal"
-	"Jazz+Funk"
-	"Fusion"
-	"Trance"
-	"Classical"
-	"Instrumental"
-	"Acid"
-	"House"
-	"Game"
-	"Sound Clip"
-	"Gospel"
-	"Noise"
-	"Alternative Rock"
-	"Bass"
-	"Soul"
-	"Punk"
-	"Space"
-	"Meditative"
-	"Instrumental Pop"
-	"Instrumental Rock"
-	"Ethnic"
-	"Gothic"
-	"Darkwave"
-	"Techno-Industrial"
-	"Electronic"
-	"Pop-Folk"
-	"Eurodance"
-	"Dream"
-	"Southern Rock"
-	"Comedy"
-	"Cult"
-	"Gangsta"
-	"Top 40"
-	"Christian Rap"
-	"Pop/Funk"
-	"Jungle"
-	"Native American"
-	"Cabaret"
-	"New Wave"
-	"Psychedelic"
-	"Rave"
-	"Showtunes"
-	"Trailer"
-	"Lo-Fi"
-	"Tribal"
-	"Acid Punk"
-	"Acid Jazz"
-	"Polka"
-	"Retro"
-	"Musical"
-	"Rock & Roll"
-	"Hard Rock"
-	"Folk"
-	"Folk/Rock"
-	"National Folk"
-	"Swing"
-	"Fusion"
-	"Bebob"
-	"Latin"
-	"Revival"
-	"Celtic"
-	"Bluegrass"
-	"Avantgarde"
-	"Gothic Rock"
-	"Progressive Rock"
-	"Psychedelic Rock"
-	"Symphonic Rock"
-	"Slow Rock"
-	"Big Band"
-	"Chorus"
-	"Easy Listening"
-	"Acoustic"
-	"Humour"
-	"Speech"
-	"Chanson"
-	"Opera"
-	"Chamber Music"
-	"Sonata"
-	"Symphony"
-	"Booty Bass"
-	"Primus"
-	"Porn Groove"
-	"Satire"
-	"Slow Jam"
-	"Club"
-	"Tango"
-	"Samba"
-	"Folklore"
-	"Ballad"
-	"Power Ballad"
-	"Rhythmic Soul"
-	"Freestyle"
-	"Duet"
-	"Punk Rock"
-	"Drum Solo"
-	"A Cappella"
-	"Euro-House"
-	"Dance Hall"
-	"Goa"
-	"Drum & Bass"
-	"Club-House"
-	"Hardcore"
-	"Terror"
-	"Indie"
-	"BritPop"
-	"Negerpunk"
-	"Polsk Punk"
-	"Beat"
-	"Christian Gangsta Rap"
-	"Heavy Metal"
-	"Black Metal"
-	"Crossover"
-	"Contemporary Christian"
-	"Christian Rock"
-	"Merengue"
-	"Salsa"
-	"Thrash Metal"
-	"Anime"
-	"Jpop"
-	"Synthpop"))
+    "Classic Rock"
+    "Country"
+    "Dance"
+    "Disco"
+    "Funk"
+    "Grunge"
+    "Hip-Hop"
+    "Jazz"
+    "Metal"
+    "New Age"
+    "Oldies"
+    "Other"
+    "Pop"
+    "R&B"
+    "Rap"
+    "Reggae"
+    "Rock"
+    "Techno"
+    "Industrial"
+    "Alternative"
+    "Ska"
+    "Death Metal"
+    "Pranks"
+    "Soundtrack"
+    "Euro-Techno"
+    "Ambient"
+    "Trip-Hop"
+    "Vocal"
+    "Jazz+Funk"
+    "Fusion"
+    "Trance"
+    "Classical"
+    "Instrumental"
+    "Acid"
+    "House"
+    "Game"
+    "Sound Clip"
+    "Gospel"
+    "Noise"
+    "Alternative Rock"
+    "Bass"
+    "Soul"
+    "Punk"
+    "Space"
+    "Meditative"
+    "Instrumental Pop"
+    "Instrumental Rock"
+    "Ethnic"
+    "Gothic"
+    "Darkwave"
+    "Techno-Industrial"
+    "Electronic"
+    "Pop-Folk"
+    "Eurodance"
+    "Dream"
+    "Southern Rock"
+    "Comedy"
+    "Cult"
+    "Gangsta"
+    "Top 40"
+    "Christian Rap"
+    "Pop/Funk"
+    "Jungle"
+    "Native American"
+    "Cabaret"
+    "New Wave"
+    "Psychedelic"
+    "Rave"
+    "Showtunes"
+    "Trailer"
+    "Lo-Fi"
+    "Tribal"
+    "Acid Punk"
+    "Acid Jazz"
+    "Polka"
+    "Retro"
+    "Musical"
+    "Rock & Roll"
+    "Hard Rock"
+    "Folk"
+    "Folk/Rock"
+    "National Folk"
+    "Swing"
+    "Fusion"
+    "Bebob"
+    "Latin"
+    "Revival"
+    "Celtic"
+    "Bluegrass"
+    "Avantgarde"
+    "Gothic Rock"
+    "Progressive Rock"
+    "Psychedelic Rock"
+    "Symphonic Rock"
+    "Slow Rock"
+    "Big Band"
+    "Chorus"
+    "Easy Listening"
+    "Acoustic"
+    "Humour"
+    "Speech"
+    "Chanson"
+    "Opera"
+    "Chamber Music"
+    "Sonata"
+    "Symphony"
+    "Booty Bass"
+    "Primus"
+    "Porn Groove"
+    "Satire"
+    "Slow Jam"
+    "Club"
+    "Tango"
+    "Samba"
+    "Folklore"
+    "Ballad"
+    "Power Ballad"
+    "Rhythmic Soul"
+    "Freestyle"
+    "Duet"
+    "Punk Rock"
+    "Drum Solo"
+    "A Cappella"
+    "Euro-House"
+    "Dance Hall"
+    "Goa"
+    "Drum & Bass"
+    "Club-House"
+    "Hardcore"
+    "Terror"
+    "Indie"
+    "BritPop"
+    "Negerpunk"
+    "Polsk Punk"
+    "Beat"
+    "Christian Gangsta Rap"
+    "Heavy Metal"
+    "Black Metal"
+    "Crossover"
+    "Contemporary Christian"
+    "Christian Rock"
+    "Merengue"
+    "Salsa"
+    "Thrash Metal"
+    "Anime"
+    "Jpop"
+    "Synthpop"))
 
 (defun find-genre (name)
   "For debug purpose only: test function to return index of genre, given a name. ignores case and returns first complete match"
   (let ((i 0)
-		(match-str (string-downcase name)))
-	(loop for s across *id3v1-genres* do
-	  (if (string= (string-downcase s) match-str)
-		  (return-from find-genre i))
-	  (incf i))))
+        (match-str (string-downcase name)))
+    (loop for s across *id3v1-genres* do
+      (if (string= (string-downcase s) match-str)
+          (return-from find-genre i))
+      (incf i))))
 
 (defun get-id3v1-genre (n)
   "Given N, a supposed ID3 genre, range check it to make sure it is > 0 and < (sizeof *ID3V1-GENRES*)"
-  (let ((idx (- n 1)))	; genres are 1-based, arrays 0-based
-	(if (or (> idx (length *id3v1-genres*))
-			(< idx 0))
-		"BAD GENRE"
-	  (aref *id3v1-genres* idx))))
+  (let ((idx (- n 1)))  ; genres are 1-based, arrays 0-based
+    (if (or (> idx (length *id3v1-genres*))
+            (< idx 0))
+        "BAD GENRE"
+      (aref *id3v1-genres* idx))))
 
 (defun get-frames (stream names)
   "Given a MP3-STREAM, search its frames for NAMES.  Return file-order list of matching frames"
   (let (found-frames)
-	(map-id3-frames stream
-					:func (lambda (f)
-							(when (member (id f) names :test #'string=)
-							  (push f found-frames))))
-	(nreverse found-frames)))
+    (map-id3-frames stream
+                    :func (lambda (f)
+                            (when (member (id f) names :test #'string=)
+                              (push f found-frames))))
+    (nreverse found-frames)))
 
 ;;; Abstract TAG interface
 ;;; The following probably should be macro-ized in the future---lots of cut/paste going on...
 (defmethod album ((me mp3-file-stream))
   (let ((frames (get-frames me '("TAL" "TALB"))))
-	(when frames
-	  (assert (= 1 (length frames)) () "There can be only one album tag")
-	  (return-from album (info (first frames)))))
+    (when frames
+      (assert (= 1 (length frames)) () "There can be only one album tag")
+      (return-from album (info (first frames)))))
   (if (v21-tag-header (id3-header me))
-	  (album (v21-tag-header (id3-header me)))
-	  nil))
+      (album (v21-tag-header (id3-header me)))
+      nil))
 
 (defmethod artist ((me mp3-file-stream))
   (let ((frames (get-frames me '("TP1" "TPE1"))))
-	(when frames
-	  (assert (= 1 (length frames)) () "There can be only one artist tag")
-	  (return-from artist (info (first frames)))))
+    (when frames
+      (assert (= 1 (length frames)) () "There can be only one artist tag")
+      (return-from artist (info (first frames)))))
   (if (v21-tag-header (id3-header me))
-	  (artist (v21-tag-header (id3-header me)))
-	  nil))
+      (artist (v21-tag-header (id3-header me)))
+      nil))
 
 (defmethod comment ((me mp3-file-stream))
   (let ((frames (get-frames me '("COM" "COMM"))))
-	(when frames
-	  (let ((new-frames))
-		(dolist (f frames)
-		  (push (list (encoding f) (lang f) (desc f) (val f)) new-frames))
-		;; XXX need to render this into text
-		(return-from comment new-frames))))
+    (when frames
+      (let ((new-frames))
+        (dolist (f frames)
+          (push (list (encoding f) (lang f) (desc f) (val f)) new-frames))
+        ;; XXX need to render this into text
+        (return-from comment new-frames))))
   (if (v21-tag-header (id3-header me))
-	  (comment (v21-tag-header (id3-header me)))
-	  nil))
+      (comment (v21-tag-header (id3-header me)))
+      nil))
 
 (defmethod year ((me mp3-file-stream))
   (let ((frames (get-frames me '("TRD" "TDRC"))))
-	(when frames
-	  (assert (= 1 (length frames)) () "There can be only one year tag")
-	  (return-from year (info (first frames)))))
+    (when frames
+      (assert (= 1 (length frames)) () "There can be only one year tag")
+      (return-from year (info (first frames)))))
   (if (v21-tag-header (id3-header me))
-	  (year (v21-tag-header (id3-header me)))
-	  nil))
+      (year (v21-tag-header (id3-header me)))
+      nil))
 
 (defmethod title ((me mp3-file-stream))
   (let ((frames (get-frames me '("TT2" "TIT2"))))
-	(when frames
-	  (assert (= 1 (length frames)) () "There can be only one title tag")
-	  (return-from title (info (first frames)))))
+    (when frames
+      (assert (= 1 (length frames)) () "There can be only one title tag")
+      (return-from title (info (first frames)))))
   (if (v21-tag-header (id3-header me))
-	  (title (v21-tag-header (id3-header me)))
-	  nil))
+      (title (v21-tag-header (id3-header me)))
+      nil))
 
 (defmethod genre ((me mp3-file-stream))
   (let ((frames (get-frames me '("TCO" "TCON"))))
-	(when frames
-	  (when (> (length frames) 1)
-		(warn-user "file ~a has more than one genre frame, will only use the first" (stream-filename me)))
-	  (let ((count)
-			(end)
-			(str (info (first frames))))
+    (when frames
+      (when (> (length frames) 1)
+        (warn-user "file ~a has more than one genre frame, will only use the first" (stream-filename me)))
+      (let ((count)
+            (end)
+            (str (info (first frames))))
 
-		;; XXX for V23/V24 TCON frames, a genre can be pretty gnarly.
-		;; if the first byte of the TCON INFO field is a '(', this is interpreted 
-		;; as an ID3v2.1 genre number.  These can stack up (called "refinements") too.
-		;; The INFO field can also just be a string.
-		;; We're taking a simplistic approach here: we can hand the '(' case, but
-		;; only allow one (no refinements) or we can handle the simple string case
-		(when (and (>= (length str) 1) (eq #\( (aref str 0)))
-		  (setf count (count #\( str))
-		  (when (> count 1) (warn-user "Don't support genre refinement yet, found ~d genres" count))
-		  (setf end (position #\) str))
-		  (when (null end) (warn-user "Bad format for genre, ending paren is missing"))
-		  (setf str (get-id3v1-genre (parse-integer (subseq str 1 end)))))
-		(return-from genre str))))
+        ;; XXX for V23/V24 TCON frames, a genre can be pretty gnarly.
+        ;; if the first byte of the TCON INFO field is a '(', this is interpreted
+        ;; as an ID3v2.1 genre number.  These can stack up (called "refinements") too.
+        ;; The INFO field can also just be a string.
+        ;; We're taking a simplistic approach here: we can hand the '(' case, but
+        ;; only allow one (no refinements) or we can handle the simple string case
+        (when (and (>= (length str) 1) (eq #\( (aref str 0)))
+          (setf count (count #\( str))
+          (when (> count 1) (warn-user "Don't support genre refinement yet, found ~d genres" count))
+          (setf end (position #\) str))
+          (when (null end) (warn-user "Bad format for genre, ending paren is missing"))
+          (setf str (get-id3v1-genre (parse-integer (subseq str 1 end)))))
+        (return-from genre str))))
 
   (if (v21-tag-header (id3-header me))
-	  (get-id3v1-genre (genre (v21-tag-header (id3-header me))))
-	  nil))
+      (get-id3v1-genre (genre (v21-tag-header (id3-header me))))
+      nil))
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; no V2.1 tags for any of these ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 (defmethod album-artist ((me mp3-file-stream))
   (let ((frames (get-frames me '("TP2" "TPE2"))))
-	(when frames
-	  (assert (= 1 (length frames)) () "There can be only one album-artist tag")
-	  (return-from album-artist (info (first frames)))))
+    (when frames
+      (assert (= 1 (length frames)) () "There can be only one album-artist tag")
+      (return-from album-artist (info (first frames)))))
   nil)
 
 (defmethod composer ((me mp3-file-stream))
   (let ((frames (get-frames me '("TCM" "TCOM"))))
-	(when frames
-	  (assert (= 1 (length frames)) () "There can be only one composer tag")
-	  (return-from composer (info (first frames)))))
+    (when frames
+      (assert (= 1 (length frames)) () "There can be only one composer tag")
+      (return-from composer (info (first frames)))))
   nil)
 
 (defmethod copyright ((me mp3-file-stream))
   (let ((frames (get-frames me '("TCR" "TCOP"))))
-	(when frames
-	  (assert (= 1 (length frames)) () "There can be only one copyright tag")
-	  (return-from copyright (info (first frames)))))
+    (when frames
+      (assert (= 1 (length frames)) () "There can be only one copyright tag")
+      (return-from copyright (info (first frames)))))
   nil)
 
 (defmethod encoder ((me mp3-file-stream))
   (let ((frames (get-frames me '("TEN" "TENC"))))
-	(when frames
-	  (assert (= 1 (length frames)) () "There can be only one encoder tag")
-	  (return-from encoder (info (first frames)))))
+    (when frames
+      (assert (= 1 (length frames)) () "There can be only one encoder tag")
+      (return-from encoder (info (first frames)))))
   nil)
 
 (defmethod groups ((me mp3-file-stream))
   (let ((frames (get-frames me '("TT1" "TTE1"))))
-	(when frames
-	  (assert (= 1 (length frames)) () "There can be only one group tag")
-	  (return-from groups (info (first frames)))))
+    (when frames
+      (assert (= 1 (length frames)) () "There can be only one group tag")
+      (return-from groups (info (first frames)))))
   nil)
 
 (defmethod lyrics ((me mp3-file-stream))
   (let ((frames (get-frames me '("ULT" "USLT"))))
-	(when frames
-	  (assert (= 1 (length frames)) () "There can be only one lyrics tag")
-	  (return-from lyrics (val (first frames)))))
+    (when frames
+      (assert (= 1 (length frames)) () "There can be only one lyrics tag")
+      (return-from lyrics (val (first frames)))))
   nil)
 
 (defmethod writer ((me mp3-file-stream))
   (let ((frames (get-frames me '("TCM" "TCOM"))))
-	(when frames
-	  (assert (= 1 (length frames)) () "There can be only one composer tag")
-	  (return-from writer (info (first frames)))))
+    (when frames
+      (assert (= 1 (length frames)) () "There can be only one composer tag")
+      (return-from writer (info (first frames)))))
   nil)
 
 (defmethod compilation ((me mp3-file-stream))
   (let ((frames (get-frames me '("TCMP"))))
-	(when frames
-	  (assert (= 1 (length frames)) () "There can be only one compilation tag")
-	  (let ((str (info (first frames))))
-		(return-from compilation (if str 1 0)))))
+    (when frames
+      (assert (= 1 (length frames)) () "There can be only one compilation tag")
+      (let ((str (info (first frames))))
+        (return-from compilation (if str 1 0)))))
   nil)
 
 (defmethod disk ((me mp3-file-stream))
   (let ((frames (get-frames me '("TPA" "TPOS"))))
-	(when frames
-	  (assert (= 1 (length frames)) () "There can be only one disk number tag")
-	  (return-from disk (mk-lst (info (first frames))))))
+    (when frames
+      (assert (= 1 (length frames)) () "There can be only one disk number tag")
+      (return-from disk (mk-lst (info (first frames))))))
   nil)
 
 (defmethod tempo ((me mp3-file-stream))
   (let ((frames (get-frames me '("TBP" "TBPM"))))
-	(when frames
-	  (assert (= 1 (length frames)) () "There can be only one tempo tag")
-	  (return-from tempo (info (first frames)))))
+    (when frames
+      (assert (= 1 (length frames)) () "There can be only one tempo tag")
+      (return-from tempo (info (first frames)))))
   nil)
 
 (defun mk-lst (str)
   (let ((pos (position #\/ str)))
-	(if (null pos)
-		(list str)
-		(list (subseq str 0 pos) (subseq str (+ 1 pos))))))
+    (if (null pos)
+        (list str)
+        (list (subseq str 0 pos) (subseq str (+ 1 pos))))))
 
 (defmethod track ((me mp3-file-stream))
   (let ((frames (get-frames me '("TRK" "TRCK"))))
-	(when frames
-	  (assert (= 1 (length frames)) () "There can be only one track number tag")
-	  (return-from track (mk-lst (info (first frames))))))
+    (when frames
+      (assert (= 1 (length frames)) () "There can be only one track number tag")
+      (return-from track (mk-lst (info (first frames))))))
   nil)
 
 (defmethod show-tags ((me mp3-file-stream) &key (raw nil))
   "Show the tags for an mp3-file.  If RAW is non-nil, dump all the frames; else, print out a subset."
   (if raw
-	  (format t "~a: ~a~%" (stream-filename me)
-			  (with-output-to-string (s)
-				(when (audio-info me)
-				  (mpeg::vpprint (audio-info me) s)
-				  (format s "~%"))
-				(vpprint (id3-header me) s)))
-	  (let ((album (album me))
-			(album-artist (album-artist me))
-			(artist (artist me))
-			(comment (comment me))
-			(compilation (compilation me))
-			(composer (composer me))
-			(copyright (copyright me))
-			(disk (disk me))
-			(encoder (encoder me))
-			(genre (genre me))
-			(groups (groups me))
-			(lyrics (lyrics me))
-			(tempo (tempo me))
-			(title (title me))
-			(track (track me))
-			(writer (writer me))
-			(year (year me)))
-		(format t "~a: ~a~%" (stream-filename me) 
-				(if (audio-info me)
-					(mpeg::vpprint (audio-info me) nil) ""))
-		(when album (format t "~4talbum: ~a~%" album))
-		(when album-artist (format t "~4talbum-artist: ~a~%" album-artist))
-		(when artist (format t "~4tartist: ~a~%" artist))
-		(when comment (format t "~4tcomment: ~a~%" comment))
-		(when compilation (format t "~4tcompilation: ~a~%" compilation))
-		(when composer (format t "~4tcomposer: ~a~%" composer))
-		(when copyright (format t "~4tcopyright: ~a~%" copyright))
-		(when disk (format t "~4tdisk: ~a~%" disk))
-		(when encoder (format t "~4tencoder: ~a~%" encoder))
-		(when genre (format t "~4tgenre: ~a~%" genre))
-		(when groups (format t "~4tgroups: ~a~%" groups))
-		(when lyrics (format t "~4tlyrics: ~a~%" lyrics))
-		(when tempo (format t "~4ttempo: ~a~%" tempo))
-		(when title (format t "~4ttitle: ~a~%" title))
-		(when track (format t "~4ttrack: ~a~%" track))
-		(when writer (format t "~4twriter: ~a~%" writer))
-		(when year (format t "~4tyear: ~a~%" year)))))
+      (format t "~a: ~a~%" (stream-filename me)
+              (with-output-to-string (s)
+                (when (audio-info me)
+                  (mpeg::vpprint (audio-info me) s)
+                  (format s "~%"))
+                (vpprint (id3-header me) s)))
+      (let ((album (album me))
+            (album-artist (album-artist me))
+            (artist (artist me))
+            (comment (comment me))
+            (compilation (compilation me))
+            (composer (composer me))
+            (copyright (copyright me))
+            (disk (disk me))
+            (encoder (encoder me))
+            (genre (genre me))
+            (groups (groups me))
+            (lyrics (lyrics me))
+            (tempo (tempo me))
+            (title (title me))
+            (track (track me))
+            (writer (writer me))
+            (year (year me)))
+        (format t "~a: ~a~%" (stream-filename me)
+                (if (audio-info me)
+                    (mpeg::vpprint (audio-info me) nil) ""))
+        (when album (format t "~4talbum: ~a~%" album))
+        (when album-artist (format t "~4talbum-artist: ~a~%" album-artist))
+        (when artist (format t "~4tartist: ~a~%" artist))
+        (when comment (format t "~4tcomment: ~a~%" comment))
+        (when compilation (format t "~4tcompilation: ~a~%" compilation))
+        (when composer (format t "~4tcomposer: ~a~%" composer))
+        (when copyright (format t "~4tcopyright: ~a~%" copyright))
+        (when disk (format t "~4tdisk: ~a~%" disk))
+        (when encoder (format t "~4tencoder: ~a~%" encoder))
+        (when genre (format t "~4tgenre: ~a~%" genre))
+        (when groups (format t "~4tgroups: ~a~%" groups))
+        (when lyrics (format t "~4tlyrics: ~a~%" lyrics))
+        (when tempo (format t "~4ttempo: ~a~%" tempo))
+        (when title (format t "~4ttitle: ~a~%" title))
+        (when track (format t "~4ttrack: ~a~%" track))
+        (when writer (format t "~4twriter: ~a~%" writer))
+        (when year (format t "~4tyear: ~a~%" year)))))

+ 259 - 259
mp4-atom.lisp

@@ -10,8 +10,8 @@
    (object   :initarg :object   :reader object   :initform nil)
    (messsage :initarg :message  :reader message  :initform "Undefined Condition"))
   (:report (lambda (condition stream)
-			 (format stream "mp4-atom condition at location: <~a> with object: <~a>: message: <~a>"
-					 (location condition) (object condition) (message condition)))))
+             (format stream "mp4-atom condition at location: <~a> with object: <~a>: message: <~a>"
+                     (location condition) (object condition) (message condition)))))
 
 (defmethod print-object ((me mp4-atom-condition) stream)
   (format stream "location: <~a>, object: <~a>, message: <~a>" (location me) (object me) (message me)))
@@ -29,36 +29,36 @@
   "Given a 4-byte string, return an integer type equivalent.
 (eg (as-int \"hdlr\" == +audioprop-hdlr+))"
   (let ((int 0))
-	(declare (integer int))
-	(setf (ldb (byte 8 24) int) (char-code (aref str 0)))
-	(setf (ldb (byte 8 16) int) (char-code (aref str 1)))
-	(setf (ldb (byte 8 8) int)  (char-code (aref str 2)))
-	(setf (ldb (byte 8 0) int)  (char-code (aref str 3)))
-	int))
+    (declare (integer int))
+    (setf (ldb (byte 8 24) int) (char-code (aref str 0)))
+    (setf (ldb (byte 8 16) int) (char-code (aref str 1)))
+    (setf (ldb (byte 8 8) int)  (char-code (aref str 2)))
+    (setf (ldb (byte 8 0) int)  (char-code (aref str 3)))
+    int))
 
 (defmethod as-string ((atom-type integer))
   "Given an integer representing an atom type, return the string form"
   (with-output-to-string (s nil)
-	(write-char (code-char (ldb (byte 8 24) atom-type)) s)
-	(write-char (code-char (ldb (byte 8 16) atom-type)) s)
-	(write-char (code-char (ldb (byte 8 8)  atom-type)) s)
-	(write-char (code-char (ldb (byte 8 0)  atom-type)) s)))
+    (write-char (code-char (ldb (byte 8 24) atom-type)) s)
+    (write-char (code-char (ldb (byte 8 16) atom-type)) s)
+    (write-char (code-char (ldb (byte 8 8)  atom-type)) s)
+    (write-char (code-char (ldb (byte 8 0)  atom-type)) s)))
 
 (eval-when (:compile-toplevel :load-toplevel :execute)
   (defun as-octet (c)
-	"Used below so that we can create atom 'types' from char/ints"
-	(cond ((typep c 'standard-char) (coerce (char-code c) '(unsigned-byte 8)))
-		  ((typep c 'integer) (coerce c '(unsigned-byte 8)))
-		  (t (error "can any handle characters and integers"))))
+    "Used below so that we can create atom 'types' from char/ints"
+    (cond ((typep c 'standard-char) (coerce (char-code c) '(unsigned-byte 8)))
+          ((typep c 'integer) (coerce c '(unsigned-byte 8)))
+          (t (error "can any handle characters and integers"))))
 
   (defmacro mk-mp4-atom-type (l1 l2 l3 l4)
-	"Given 4 chars/ints, create a 32-bit word representing an atom 'type' (aka name)"
-	`(let ((retval 0))
-	   (setf (ldb (byte 8 24) retval) ,(as-octet l1))
-	   (setf (ldb (byte 8 16) retval) ,(as-octet l2))
-	   (setf (ldb (byte 8 8) retval)  ,(as-octet l3))
-	   (setf (ldb (byte 8 0) retval)  ,(as-octet l4))
-	   retval)))
+    "Given 4 chars/ints, create a 32-bit word representing an atom 'type' (aka name)"
+    `(let ((retval 0))
+       (setf (ldb (byte 8 24) retval) ,(as-octet l1))
+       (setf (ldb (byte 8 16) retval) ,(as-octet l2))
+       (setf (ldb (byte 8 8) retval)  ,(as-octet l3))
+       (setf (ldb (byte 8 0) retval)  ,(as-octet l4))
+       retval)))
 
 (defconstant +itunes-album+          (mk-mp4-atom-type #xa9 #\a #\l #\b) "text: album name")
 (defconstant +itunes-album-artist+   (mk-mp4-atom-type #\a  #\A #\R #\T) "text: album artist")
@@ -66,12 +66,12 @@
 (defconstant +itunes-comment+        (mk-mp4-atom-type #xa9 #\c #\m #\t) "text: comment, commonly used by iTunes for sound info, etc")
 (defconstant +itunes-compilation+    (mk-mp4-atom-type #\c  #\p #\i #\l) "byte/boolean: is this file part of a compilation?")
 (defconstant +itunes-composer+       (mk-mp4-atom-type #xa9 #\c #\o #\m) "text: composer name")
-(defconstant +itunes-copyright+	     (mk-mp4-atom-type #\c  #\p #\r #\t) "text: copyright info")
+(defconstant +itunes-copyright+      (mk-mp4-atom-type #\c  #\p #\r #\t) "text: copyright info")
 (defconstant +itunes-cover-art+      (mk-mp4-atom-type #\c  #\o #\v #\r) "octets: cover art, PNG, etc")
 (defconstant +itunes-disk+           (mk-mp4-atom-type #\d  #\i #\s #\k) "octets: disk number, can be n of N")
 (defconstant +itunes-encoder+        (mk-mp4-atom-type #xa9 #\e #\n #\c) "text: who encoded")
-(defconstant +itunes-genre+		     (mk-mp4-atom-type #\g  #\n #\r #\e) "octets: genre of file")
-(defconstant +itunes-genre-x+		 (mk-mp4-atom-type #xa9 #\n #\r #\e) "text: yet another genre atom")
+(defconstant +itunes-genre+          (mk-mp4-atom-type #\g  #\n #\r #\e) "octets: genre of file")
+(defconstant +itunes-genre-x+        (mk-mp4-atom-type #xa9 #\n #\r #\e) "text: yet another genre atom")
 (defconstant +itunes-groups+         (mk-mp4-atom-type #xa9 #\g #\r #\p) "text: ???")
 (defconstant +itunes-lyrics+         (mk-mp4-atom-type #xa9 #\l #\y #\r) "text: lyrics tag")
 (defconstant +itunes-purchased-date+ (mk-mp4-atom-type #\p  #\u #\r #\d) "text: when song was purchased")
@@ -105,11 +105,11 @@
   "Loop from start to end through a file and call FUNC for every ATOM we find. Used
 at top-level and also for container ATOMs that need to read their contents."
   (log5:with-context "atom-read-loop"
-	(do ()
-		((>= (stream-seek mp4-file 0 :current) end))
-	  (log-mp4-atom "atom-read-loop: @~:d before dispatch" (stream-seek mp4-file 0 :current))
-	  (funcall func)
-	  (log-mp4-atom "atom-read-loop: @~:d after dispatch" (stream-seek mp4-file 0 :current)))))
+    (do ()
+        ((>= (stream-seek mp4-file 0 :current) end))
+      (log-mp4-atom "atom-read-loop: @~:d before dispatch" (stream-seek mp4-file 0 :current))
+      (funcall func)
+      (log-mp4-atom "atom-read-loop: @~:d after dispatch" (stream-seek mp4-file 0 :current)))))
 
 (defclass mp4-atom ()
   ((atom-file-position :accessor atom-file-position :initarg :atom-file-position)
@@ -121,9 +121,9 @@ at top-level and also for container ATOMs that need to read their contents."
 (defmethod addc ((me mp4-atom) value)
   "Want to add children atoms to end of ATOM-CHILDREN to preserve in-file order."
   (with-slots (atom-children) me
-	(if (null atom-children)
-		(setf atom-children (list value))
-		(nconc atom-children (list value)))))
+    (if (null atom-children)
+        (setf atom-children (list value))
+        (nconc atom-children (list value)))))
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Concreate atoms ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 (defclass atom-skip (mp4-atom) ())
@@ -131,18 +131,18 @@ at top-level and also for container ATOMs that need to read their contents."
   "The 'skip' atom.  Used when we want to capture the header of atom, but don't want/need
 to read the payload of an atom."
   (with-slots (atom-size atom-type) me
-	(stream-seek mp4-file (- atom-size 8) :current)))
+    (stream-seek mp4-file (- atom-size 8) :current)))
 
 (defclass atom-raw-mixin ()
   ((raw-data :accessor raw-data)))
 (defmethod initialize-instance :after ((me atom-raw-mixin) &key (mp4-file nil) &allow-other-keys)
   "The 'don't need to know contents, but want 'blob' of data read in' atom"
   (log5:with-context "atom-raw-mixin"
-	(with-slots (raw-data atom-type atom-size) me
-	  (log-mp4-atom "atom-raw-mixin: reading in ~d raw bytes for ~a" (- atom-size 8) (vpprint me nil))
-	  (setf raw-data (stream-read-sequence mp4-file (- atom-size 8)))
-	  ;;(utils::dump-data "/tmp/o.txt" raw-data)
-	  )))
+    (with-slots (raw-data atom-type atom-size) me
+      (log-mp4-atom "atom-raw-mixin: reading in ~d raw bytes for ~a" (- atom-size 8) (vpprint me nil))
+      (setf raw-data (stream-read-sequence mp4-file (- atom-size 8)))
+      ;;(utils::dump-data "/tmp/o.txt" raw-data)
+      )))
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ILST ATOMS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 (defclass atom-ilst (mp4-atom) ())
@@ -150,14 +150,14 @@ to read the payload of an atom."
   "Construct an ilst atom.  ILST atoms are containers that hold data elements related to tagging.
 Loop through this container and construct constituent atoms"
   (log5:with-context "atom-ilst-initializer"
-	(with-slots (atom-size atom-type atom-children) me
-	  (log-mp4-atom "atom-ilst-init: found ilst atom <~a> @ ~:d, looping for ~:d bytes"
-					(as-string atom-type) (stream-seek mp4-file 0 :current) (- atom-size 8))
-	  (atom-read-loop mp4-file (+ (stream-seek mp4-file 0 :current)  (- atom-size 8))
-					  (lambda ()
-						(let ((child (make-mp4-atom mp4-file atom-type)))
-						  ;(log-mp4-atom "adding new child ~a" (vpprint child nil))
-						  (addc me child))))))
+    (with-slots (atom-size atom-type atom-children) me
+      (log-mp4-atom "atom-ilst-init: found ilst atom <~a> @ ~:d, looping for ~:d bytes"
+                    (as-string atom-type) (stream-seek mp4-file 0 :current) (- atom-size 8))
+      (atom-read-loop mp4-file (+ (stream-seek mp4-file 0 :current)  (- atom-size 8))
+                      (lambda ()
+                        (let ((child (make-mp4-atom mp4-file atom-type)))
+                          ;(log-mp4-atom "adding new child ~a" (vpprint child nil))
+                          (addc me child))))))
   ;(log-mp4-atom "returning ilst atom: ~a" (vpprint me nil))
   )
 
@@ -186,20 +186,20 @@ Loop through this container and construct constituent atoms"
 
 (defclass atom-data (mp4-atom)
    ((atom-version      :accessor atom-version     :initarg :atom-version)
-	(atom-flags        :accessor atom-flags       :initarg :atom-flags)
-	(atom-value        :accessor atom-value       :initarg :atom-value)
-	(atom-parent-type  :accessor atom-parent-type :initarg :atom-parent-type :initform nil))
+    (atom-flags        :accessor atom-flags       :initarg :atom-flags)
+    (atom-value        :accessor atom-value       :initarg :atom-value)
+    (atom-parent-type  :accessor atom-parent-type :initarg :atom-parent-type :initform nil))
    (:documentation "Represents the 'data' portion of ilst data atom"))
 
  (defmethod initialize-instance :after ((me atom-data) &key mp4-file &allow-other-keys)
    (log5:with-context "atom-data-init"
-	 (with-slots (atom-size atom-type atom-version atom-flags atom-value atom-parent-type) me
-	   (setf atom-version (stream-read-u8 mp4-file))
-	   (setf atom-flags (stream-read-u24 mp4-file))
-	   (assert (= 0 (stream-read-u32 mp4-file)) () "a data atom lacks the required null field") ; XXX is this true?
-	   (log-mp4-atom "atom-data-init: size = ~:d, name = ~a, version = ~d, flags = ~x" atom-size (as-string atom-type) atom-version atom-flags)
-	   (setf atom-value (decode-ilst-data-atom atom-type me atom-parent-type mp4-file))
-	   (log-mp4-atom "atom-data-init: made an ilst atom-data: ~a" (vpprint me nil)))))
+     (with-slots (atom-size atom-type atom-version atom-flags atom-value atom-parent-type) me
+       (setf atom-version (stream-read-u8 mp4-file))
+       (setf atom-flags (stream-read-u24 mp4-file))
+       (assert (= 0 (stream-read-u32 mp4-file)) () "a data atom lacks the required null field") ; XXX is this true?
+       (log-mp4-atom "atom-data-init: size = ~:d, name = ~a, version = ~d, flags = ~x" atom-size (as-string atom-type) atom-version atom-flags)
+       (setf atom-value (decode-ilst-data-atom atom-type me atom-parent-type mp4-file))
+       (log-mp4-atom "atom-data-init: made an ilst atom-data: ~a" (vpprint me nil)))))
 
 ;;; the ILST atom decoders.  First, a lot of the decoders do the same thing, so we define a macros
 ;;; and use those for the relevants atoms.
@@ -208,7 +208,7 @@ Loop through this container and construct constituent atoms"
 
 (defmacro simple-text-decode (type)
   `(defmethod decode-ilst-data-atom ((type (eql +itunes-ilst-data+)) atom (atom-parent-type (eql ,type)) mp4-file)
-	 (stream-read-string-with-len mp4-file (- (atom-size atom) 16))))
+     (stream-read-string-with-len mp4-file (- (atom-size atom) 16))))
 
 (simple-text-decode +itunes-album+)
 (simple-text-decode +itunes-album-artist+)
@@ -228,29 +228,29 @@ Loop through this container and construct constituent atoms"
 
 (defmacro simple-a-b-decode (type)
   `(defmethod decode-ilst-data-atom ((type (eql +itunes-ilst-data+)) atom (atom-parent-type (eql ,type)) mp4-file)
-	 (declare (ignore atom))
-	 (stream-read-u16 mp4-file)					; throw away XXX Why?
-	 (let ((a) (b))
-	   (setf a (stream-read-u16 mp4-file))
-	   (setf b (stream-read-u16 mp4-file))
-	   (stream-read-u16 mp4-file)				; throw away XXX Why?
-	   (list a b))))
+     (declare (ignore atom))
+     (stream-read-u16 mp4-file)                 ; throw away XXX Why?
+     (let ((a) (b))
+       (setf a (stream-read-u16 mp4-file))
+       (setf b (stream-read-u16 mp4-file))
+       (stream-read-u16 mp4-file)               ; throw away XXX Why?
+       (list a b))))
 
 (simple-a-b-decode +itunes-track+)
 (simple-a-b-decode +itunes-track-n+)
 
 (defmethod decode-ilst-data-atom ((type (eql +itunes-ilst-data+)) atom (atom-parent-type (eql +itunes-disk+)) mp4-file)
   (declare (ignore atom))
-  (stream-read-u16 mp4-file)					; throw away XXX Why?
+  (stream-read-u16 mp4-file)                    ; throw away XXX Why?
   (let ((a) (b))
-	(setf a (stream-read-u16 mp4-file))
-	(setf b (stream-read-u16 mp4-file))
-	(list a b)))
+    (setf a (stream-read-u16 mp4-file))
+    (setf b (stream-read-u16 mp4-file))
+    (list a b)))
 
 (defmacro simple-u16-decode (type)
   `(defmethod decode-ilst-data-atom ((type (eql +itunes-ilst-data+)) atom (atom-parent-type (eql ,type)) mp4-file)
-	 (declare (ignore atom))
-	 (stream-read-u16 mp4-file)))
+     (declare (ignore atom))
+     (stream-read-u16 mp4-file)))
 
 (simple-u16-decode +itunes-tempo+)
 (simple-u16-decode +itunes-genre+)
@@ -295,14 +295,14 @@ Loop through this container and construct constituent atoms"
 
 (defmethod initialize-instance :after ((me atom-hdlr) &key (mp4-file nil) &allow-other-keys)
   (with-slots (version flags qtype mtype resv rflag rmask mhdlr atom-size) me
-	(setf version  (stream-read-u8 mp4-file))
-	(setf flags    (stream-read-u24 mp4-file))
-	(setf qtype    (stream-read-u32 mp4-file))
-	(setf mtype    (stream-read-u32 mp4-file))
-	(setf resv     (stream-read-u32 mp4-file))
-	(setf rflag    (stream-read-u32 mp4-file))
-	(setf rmask    (stream-read-u32 mp4-file))
-	(setf mhdlr    (stream-read-sequence mp4-file (- atom-size 32))))) ; 32 is 8-bytes of header plus fields above
+    (setf version  (stream-read-u8 mp4-file))
+    (setf flags    (stream-read-u24 mp4-file))
+    (setf qtype    (stream-read-u32 mp4-file))
+    (setf mtype    (stream-read-u32 mp4-file))
+    (setf resv     (stream-read-u32 mp4-file))
+    (setf rflag    (stream-read-u32 mp4-file))
+    (setf rmask    (stream-read-u32 mp4-file))
+    (setf mhdlr    (stream-read-sequence mp4-file (- atom-size 32))))) ; 32 is 8-bytes of header plus fields above
 
 (defclass atom-mdhd (mp4-atom)
   ((version  :accessor version)
@@ -315,21 +315,21 @@ Loop through this container and construct constituent atoms"
    (quality  :accessor quality)))
 (defmethod initialize-instance :after ((me atom-mdhd) &key (mp4-file nil) &allow-other-keys)
   (with-slots (version flags c-time m-time scale duration lang quality) me
-	(setf version  (stream-read-u8 mp4-file))
-	(setf flags    (stream-read-u24 mp4-file))
-	(setf c-time   (stream-read-u32 mp4-file))
-	(setf m-time   (stream-read-u32 mp4-file))
-	(setf scale    (stream-read-u32 mp4-file))
-	(setf duration (if (= 0 version) (stream-read-u32 mp4-file) (stream-read-u64 mp4-file)))
-	(setf lang     (stream-read-u16 mp4-file))
-	(setf quality  (stream-read-u16 mp4-file))))
+    (setf version  (stream-read-u8 mp4-file))
+    (setf flags    (stream-read-u24 mp4-file))
+    (setf c-time   (stream-read-u32 mp4-file))
+    (setf m-time   (stream-read-u32 mp4-file))
+    (setf scale    (stream-read-u32 mp4-file))
+    (setf duration (if (= 0 version) (stream-read-u32 mp4-file) (stream-read-u64 mp4-file)))
+    (setf lang     (stream-read-u16 mp4-file))
+    (setf quality  (stream-read-u16 mp4-file))))
 
 (defclass atom-esds (mp4-atom)
   ((version      :accessor version)      ; 1 byte
-   (flags        :accessor flags)		 ; 3 bytes
-   (esid         :accessor esid)		 ; 2 bytes
-   (s-priority   :accessor s-priority) 	 ; 1 byte
-   (obj-id		 :accessor obj-id)		 ; 1 byte
+   (flags        :accessor flags)        ; 3 bytes
+   (esid         :accessor esid)         ; 2 bytes
+   (s-priority   :accessor s-priority)   ; 1 byte
+   (obj-id       :accessor obj-id)       ; 1 byte
    (s-type       :accessor s-type)       ; 1 byte (1 bit up-stream, 1-but reservered, 6-bits stream type
    (buf-size     :accessor buf-size)     ; 3 bytes
    (max-bit-rate :accessor max-bit-rate) ; 4 bytes
@@ -349,33 +349,33 @@ Loop through this container and construct constituent atoms"
 (defun read-descriptor-len (instream)
   "Get the ES descriptor's length."
   (let* ((tmp (stream-read-u8 instream))
-		 (len (logand tmp #x7f)))
-	(declare (type (unsigned-byte 8) tmp))
-	(while (not (zerop (logand #x80 tmp)))
-	  (setf tmp (stream-read-u8 instream))
-	  (setf len (logior (ash len 7) (logand tmp #x7f))))
-	len))
+         (len (logand tmp #x7f)))
+    (declare (type (unsigned-byte 8) tmp))
+    (while (not (zerop (logand #x80 tmp)))
+      (setf tmp (stream-read-u8 instream))
+      (setf len (logior (ash len 7) (logand tmp #x7f))))
+    len))
 
 (defmethod initialize-instance :after ((me atom-esds) &key (mp4-file nil) &allow-other-keys)
   (with-slots (version flags esid s-priority obj-id s-type buf-size max-bit-rate avg-bit-rate) me
-	(setf version  (stream-read-u8 mp4-file))
-	(setf flags    (stream-read-u24 mp4-file))
-	(assert (= 3 (stream-read-u8 mp4-file)) () "Expected a description tag of 3")
-	(let* ((len1 (read-descriptor-len mp4-file))
-		   (end-of-atom (+ (stream-seek mp4-file 0 :current) len1)))
-	  (setf esid (stream-read-u16 mp4-file))
-	  (setf s-priority (stream-read-u8 mp4-file))
-	  ;; XXX should do some range checking here against LEN1...
-	  (assert (= 4 (stream-read-u8 mp4-file)) () "Expected tag type of 4")
-	  (read-descriptor-len mp4-file) ; eat, but don't store descriptor header len
-	  (setf obj-id (stream-read-u8 mp4-file))
-	  (setf s-type (stream-read-u8 mp4-file))
-	  (setf buf-size (stream-read-u24 mp4-file))
-	  (setf max-bit-rate (stream-read-u32 mp4-file))
-	  (setf avg-bit-rate (stream-read-u32 mp4-file))
-	  ;; XXX should do checking hereand/or read rest of atom,
-	  ;; but for now, we have what we want, so just seek to end of atom
-	  (stream-seek mp4-file end-of-atom :start))))
+    (setf version  (stream-read-u8 mp4-file))
+    (setf flags    (stream-read-u24 mp4-file))
+    (assert (= 3 (stream-read-u8 mp4-file)) () "Expected a description tag of 3")
+    (let* ((len1 (read-descriptor-len mp4-file))
+           (end-of-atom (+ (stream-seek mp4-file 0 :current) len1)))
+      (setf esid (stream-read-u16 mp4-file))
+      (setf s-priority (stream-read-u8 mp4-file))
+      ;; XXX should do some range checking here against LEN1...
+      (assert (= 4 (stream-read-u8 mp4-file)) () "Expected tag type of 4")
+      (read-descriptor-len mp4-file) ; eat, but don't store descriptor header len
+      (setf obj-id (stream-read-u8 mp4-file))
+      (setf s-type (stream-read-u8 mp4-file))
+      (setf buf-size (stream-read-u24 mp4-file))
+      (setf max-bit-rate (stream-read-u32 mp4-file))
+      (setf avg-bit-rate (stream-read-u32 mp4-file))
+      ;; XXX should do checking hereand/or read rest of atom,
+      ;; but for now, we have what we want, so just seek to end of atom
+      (stream-seek mp4-file end-of-atom :start))))
 
 (defclass atom-stsd (mp4-atom)
   ((flags       :accessor flags)
@@ -384,11 +384,11 @@ Loop through this container and construct constituent atoms"
 
 (defmethod initialize-instance :after ((me atom-stsd) &key (mp4-file nil) &allow-other-keys)
   (log5:with-context "atom-stsd"
-	(with-slots (flags version num-entries) me
-	  (setf version (stream-read-u8 mp4-file))
-	  (setf flags (stream-read-u24 mp4-file))
-	  (setf num-entries (stream-read-u32 mp4-file))
-	  (log-mp4-atom "atom-stsd: version = ~d, flags = ~x, num-fields = ~d" version flags num-entries))))
+    (with-slots (flags version num-entries) me
+      (setf version (stream-read-u8 mp4-file))
+      (setf flags (stream-read-u24 mp4-file))
+      (setf num-entries (stream-read-u32 mp4-file))
+      (log-mp4-atom "atom-stsd: version = ~d, flags = ~x, num-fields = ~d" version flags num-entries))))
 
 (defclass atom-mp4a (mp4-atom)
   ((reserved    :accessor reserved)    ; 6 bytes
@@ -404,131 +404,131 @@ Loop through this container and construct constituent atoms"
 
 (defmethod initialize-instance :after ((me atom-mp4a) &key (mp4-file nil) &allow-other-keys)
   (log5:with-context "atom-mp4a"
-	(with-slots (reserved d-ref-idx version revision vendor num-chans samp-size comp-id packet-size samp-rate) me
-	  (setf reserved    (stream-read-sequence mp4-file 6))
-	  (setf d-ref-idx   (stream-read-u16 mp4-file))
-	  (setf version	    (stream-read-u16 mp4-file))
-	  (setf revision    (stream-read-u16 mp4-file))
-	  (setf vendor	    (stream-read-u32 mp4-file))
-	  (setf num-chans   (stream-read-u16 mp4-file))
-	  (setf samp-size   (stream-read-u16 mp4-file))
-	  (setf comp-id	    (stream-read-u16 mp4-file))
-	  (setf packet-size (stream-read-u16 mp4-file))
-	  (setf samp-rate   (stream-read-u32 mp4-file)) ; fixed 16.16 floating point number
+    (with-slots (reserved d-ref-idx version revision vendor num-chans samp-size comp-id packet-size samp-rate) me
+      (setf reserved    (stream-read-sequence mp4-file 6))
+      (setf d-ref-idx   (stream-read-u16 mp4-file))
+      (setf version     (stream-read-u16 mp4-file))
+      (setf revision    (stream-read-u16 mp4-file))
+      (setf vendor      (stream-read-u32 mp4-file))
+      (setf num-chans   (stream-read-u16 mp4-file))
+      (setf samp-size   (stream-read-u16 mp4-file))
+      (setf comp-id     (stream-read-u16 mp4-file))
+      (setf packet-size (stream-read-u16 mp4-file))
+      (setf samp-rate   (stream-read-u32 mp4-file)) ; fixed 16.16 floating point number
 
-	  (read-container-atoms mp4-file me))))
+      (read-container-atoms mp4-file me))))
 
 
 (defun read-container-atoms (mp4-file parent-atom)
   "loop through a container atom and add it's children to it"
   (with-slots (atom-children atom-file-position atom-of-interest atom-size atom-type atom-decoded) parent-atom
-	(atom-read-loop mp4-file (+ atom-file-position atom-size)
-					(lambda ()
-					  (let ((child (make-mp4-atom mp4-file atom-type)))
-						(log-mp4-atom "read-container-atoms: adding new child ~a" (vpprint child nil))
-						(addc parent-atom child))))))
+    (atom-read-loop mp4-file (+ atom-file-position atom-size)
+                    (lambda ()
+                      (let ((child (make-mp4-atom mp4-file atom-type)))
+                        (log-mp4-atom "read-container-atoms: adding new child ~a" (vpprint child nil))
+                        (addc parent-atom child))))))
 
 (defclass atom-meta (mp4-atom)
   ((version  :accessor version)
    (flags    :accessor flags)))
 (defmethod initialize-instance :after ((me atom-meta) &key (mp4-file nil) &allow-other-keys)
    (with-slots (version flags) me
-	 (setf version  (stream-read-u8 mp4-file))
-	 (setf flags    (stream-read-u24 mp4-file))
-	 (read-container-atoms mp4-file me)))
+     (setf version  (stream-read-u8 mp4-file))
+     (setf flags    (stream-read-u24 mp4-file))
+     (read-container-atoms mp4-file me)))
 
 (defun find-atom-class (id)
   "Search by concatenating 'atom-' with ID and look for that symbol in this package"
   (log5:with-context "find-atom-class"
-	(log-mp4-atom "find-atom-class: looking for class <~a>" (as-string id))
-	(let ((found-class-symbol (find-symbol (string-upcase (concatenate 'string "atom-" (as-string id))) :MP4-ATOM))
-		  (found-class))
+    (log-mp4-atom "find-atom-class: looking for class <~a>" (as-string id))
+    (let ((found-class-symbol (find-symbol (string-upcase (concatenate 'string "atom-" (as-string id))) :MP4-ATOM))
+          (found-class))
 
-	  ;; if we found the class name, return the class (to be used for MAKE-INSTANCE)
-	  (when found-class-symbol
-		(setf found-class (find-class found-class-symbol))
-		(log-mp4-atom "find-atom-class: found class: ~a" found-class)
-		(return-from find-atom-class (find-class found-class-symbol))))
+      ;; if we found the class name, return the class (to be used for MAKE-INSTANCE)
+      (when found-class-symbol
+        (setf found-class (find-class found-class-symbol))
+        (log-mp4-atom "find-atom-class: found class: ~a" found-class)
+        (return-from find-atom-class (find-class found-class-symbol))))
 
-	;; didn't find a class, so return ATOM-SKIP class
-	(log-mp4-atom "find-atom-class: class not found")
-	'atom-skip))
+    ;; didn't find a class, so return ATOM-SKIP class
+    (log-mp4-atom "find-atom-class: class not found")
+    'atom-skip))
 
 (defun make-mp4-atom (mp4-file &optional parent-type)
   "Get current file position, read in size/type, then construct the correct atom."
   (log5:with-context "make-mp4-atom"
-	(let* ((pos (stream-seek mp4-file 0 :current))
-		   (siz (stream-read-u32 mp4-file))
-		   (typ (stream-read-u32 mp4-file))
-		   (atom))
-	  (declare (type integer pos siz typ))
+    (let* ((pos (stream-seek mp4-file 0 :current))
+           (siz (stream-read-u32 mp4-file))
+           (typ (stream-read-u32 mp4-file))
+           (atom))
+      (declare (type integer pos siz typ))
 
-	  (log-mp4-atom "make-mp4-atom: @ pos = ~:d of size = ~:d and type = ~a" pos siz (as-string typ))
+      (log-mp4-atom "make-mp4-atom: @ pos = ~:d of size = ~:d and type = ~a" pos siz (as-string typ))
 
-	  (when (= 0 siz)
-		(error "trying to make an atom ~a with size of 0 at offset ~:d in ~a, ammending size to be 8" 
-			   (as-string typ) pos (stream-filename mp4-file)))
+      (when (= 0 siz)
+        (error "trying to make an atom ~a with size of 0 at offset ~:d in ~a, ammending size to be 8"
+               (as-string typ) pos (stream-filename mp4-file)))
 
-	  (setf atom (make-instance (find-atom-class typ) :atom-size siz :atom-type typ :atom-file-position pos :mp4-file mp4-file :atom-parent-type parent-type))
-	  (log-mp4-atom "make-mp4-atom: made ~a" (vpprint atom nil))
-	  atom)))
+      (setf atom (make-instance (find-atom-class typ) :atom-size siz :atom-type typ :atom-file-position pos :mp4-file mp4-file :atom-parent-type parent-type))
+      (log-mp4-atom "make-mp4-atom: made ~a" (vpprint atom nil))
+      atom)))
 
 (defmethod vpprint ((me mp4-atom) stream)
   (format stream "~a" (with-output-to-string (s)
-						(with-slots (atom-children atom-file-position atom-size atom-type) me
-						  (format s "ATOM: type: <~a> @ ~:d of size ~:d and child count of ~d"
-								  (as-string atom-type) atom-file-position atom-size (length atom-children)))
-						(if (typep me 'atom-data)
-							(with-slots (atom-version atom-flags atom-value atom-type atom-parent-type) me
-							  (format s " having ilst fields: atom-parent-type = ~a, verison = ~d, flags = ~x, data = ~x"
-									  (as-string atom-parent-type) atom-version atom-flags 
-									  (if (typep atom-value 'array) (printable-array atom-value) atom-value)))))))
+                        (with-slots (atom-children atom-file-position atom-size atom-type) me
+                          (format s "ATOM: type: <~a> @ ~:d of size ~:d and child count of ~d"
+                                  (as-string atom-type) atom-file-position atom-size (length atom-children)))
+                        (if (typep me 'atom-data)
+                            (with-slots (atom-version atom-flags atom-value atom-type atom-parent-type) me
+                              (format s " having ilst fields: atom-parent-type = ~a, verison = ~d, flags = ~x, data = ~x"
+                                      (as-string atom-parent-type) atom-version atom-flags
+                                      (if (typep atom-value 'array) (printable-array atom-value) atom-value)))))))
 
 (defun is-valid-m4-file (mp4-file)
   "Make sure this is an MP4 file.  Quick check: is first atom (at file-offset 4) == FSTYP?"
   (stream-seek mp4-file 0 :start)
   (let* ((size (stream-read-u32 mp4-file))
-		 (header (stream-read-u32 mp4-file)))
-	(declare (ignore size))
-	(stream-seek mp4-file 0 :start)
-	(= header +m4-ftyp+)))
+         (header (stream-read-u32 mp4-file)))
+    (declare (ignore size))
+    (stream-seek mp4-file 0 :start)
+    (= header +m4-ftyp+)))
 
 (defun find-mp4-atoms (mp4-file)
   "Given a valid MP4 file mp4-file, look for the 'right' atoms and return them."
   (log5:with-context "find-mp4-atoms"
-	(when (not (is-valid-m4-file mp4-file))
-	  (error 'mp4-atom-condition :location "find-mp4-atoms" :object mp4-file :message "is not an mp4-file" ))
+    (when (not (is-valid-m4-file mp4-file))
+      (error 'mp4-atom-condition :location "find-mp4-atoms" :object mp4-file :message "is not an mp4-file" ))
 
-	(log-mp4-atom "find-mp4-atoms: ~a, before read-file loop, file-position = ~:d, end = ~:d"
-				  (stream-filename mp4-file) (stream-seek mp4-file 0 :current) (stream-size mp4-file))
+    (log-mp4-atom "find-mp4-atoms: ~a, before read-file loop, file-position = ~:d, end = ~:d"
+                  (stream-filename mp4-file) (stream-seek mp4-file 0 :current) (stream-size mp4-file))
 
-	(let ((atoms))
-	  (atom-read-loop mp4-file (stream-size mp4-file)
-					  (lambda ()
-						(let ((new-atom (make-mp4-atom mp4-file)))
-						  (when new-atom
-							(push new-atom atoms)))))
-	  (setf (mp4-atoms mp4-file) (nreverse atoms))) ; preserve in-file-order
+    (let ((atoms))
+      (atom-read-loop mp4-file (stream-size mp4-file)
+                      (lambda ()
+                        (let ((new-atom (make-mp4-atom mp4-file)))
+                          (when new-atom
+                            (push new-atom atoms)))))
+      (setf (mp4-atoms mp4-file) (nreverse atoms))) ; preserve in-file-order
 
-	(log-mp4-atom "find-mp4-atoms: returning list of size ~d" (length (mp4-atoms mp4-file)))))
+    (log-mp4-atom "find-mp4-atoms: returning list of size ~d" (length (mp4-atoms mp4-file)))))
 
 (defmethod map-mp4-atom ((atoms list) &key (func nil) (depth nil))
   "Given a list of atoms, call map-mp4-atom for each one"
   (log5:with-context "map-mp4-atom"
-	(dolist (a atoms)
-	  (map-mp4-atom a :func func :depth depth))))
+    (dolist (a atoms)
+      (map-mp4-atom a :func func :depth depth))))
 
 (defmethod map-mp4-atom ((me mp4-atom) &key (func nil) (depth nil))
   "traverse all atoms under a given atom"
   (log5:with-context "map-mp4-atom(single)"
-	(labels ((_indented-atom (atom depth)
-			   (format t "~vt~a~%"  (if (null depth) 0 depth) (vpprint atom nil))))
-	  (with-slots (atom-type atom-children) me
-		(log-mp4-atom "map-mp4-atom: begining traversal with ~a, I have ~d children" (as-string atom-type) (length atom-children))
-		(when (null func)
-		  (setf func #'_indented-atom))
-		(funcall func me depth)
-		(map-mp4-atom atom-children :func func :depth (if (null depth) nil (+ 1 depth)))))))
+    (labels ((_indented-atom (atom depth)
+               (format t "~vt~a~%"  (if (null depth) 0 depth) (vpprint atom nil))))
+      (with-slots (atom-type atom-children) me
+        (log-mp4-atom "map-mp4-atom: begining traversal with ~a, I have ~d children" (as-string atom-type) (length atom-children))
+        (when (null func)
+          (setf func #'_indented-atom))
+        (funcall func me depth)
+        (map-mp4-atom atom-children :func func :depth (if (null depth) nil (+ 1 depth)))))))
 
 (defmethod traverse ((me mp4-atom) path)
   (traverse (atom-children me) path))
@@ -537,63 +537,63 @@ Loop through this container and construct constituent atoms"
   "Used in finding nested atoms. Search MP4-ATOMS and if we find a match with first of path,
 call traverse atom (unless length of path == 1, in which case, we've found our match)"
   (log5:with-context "traverse"
-	(log-mp4-atom "traverse: entering with ~a ~a" me path)
-	(dolist (sibling me)
-	  (with-slots (atom-type atom-children) sibling
-		(log-mp4-atom "traverse: comparing ~a to ~a" (as-string atom-type) (as-string (first path)))
-		(when (= atom-type (first path))
-		  (cond
-			((= 1 (length path))
-			 (log-mp4-atom "traverse: matched: ~a" sibling)
-			 (return-from traverse sibling))
-			(t
-			 (log-mp4-atom "traverse: path matches, recursing")
-			 (let ((found (traverse atom-children (rest path))))
-			   (if found (return-from traverse found))))))))
-	(log-mp4-atom "traverse: ~a not found" path)
-	nil))
+    (log-mp4-atom "traverse: entering with ~a ~a" me path)
+    (dolist (sibling me)
+      (with-slots (atom-type atom-children) sibling
+        (log-mp4-atom "traverse: comparing ~a to ~a" (as-string atom-type) (as-string (first path)))
+        (when (= atom-type (first path))
+          (cond
+            ((= 1 (length path))
+             (log-mp4-atom "traverse: matched: ~a" sibling)
+             (return-from traverse sibling))
+            (t
+             (log-mp4-atom "traverse: path matches, recursing")
+             (let ((found (traverse atom-children (rest path))))
+               (if found (return-from traverse found))))))))
+    (log-mp4-atom "traverse: ~a not found" path)
+    nil))
 
 (defmethod tag-get-value (atoms node)
   "Helper function to extract text from ILST atom's data atom"
   (let ((atom (traverse atoms
-						(list +mp4-atom-moov+ +mp4-atom-udta+ +mp4-atom-meta+ +mp4-atom-ilst+ node +itunes-ilst-data+))))
-	(if atom
-		(atom-value atom)
-		nil)))
+                        (list +mp4-atom-moov+ +mp4-atom-udta+ +mp4-atom-meta+ +mp4-atom-ilst+ node +itunes-ilst-data+))))
+    (if atom
+        (atom-value atom)
+        nil)))
 
 (defun mp4-show-raw-tag-atoms (mp4-file-stream)
   (map-mp4-atom (mp4-atom::traverse (mp4-atoms mp4-file-stream)
-									(list +mp4-atom-moov+ +mp4-atom-udta+ +mp4-atom-meta+ +mp4-atom-ilst+))
-				:depth 0
-				:func (lambda (atom depth)
-						(when (= (atom-type atom) +itunes-ilst-data+)
-						  (format t "~vt~a~%" depth (vpprint atom nil))))))
+                                    (list +mp4-atom-moov+ +mp4-atom-udta+ +mp4-atom-meta+ +mp4-atom-ilst+))
+                :depth 0
+                :func (lambda (atom depth)
+                        (when (= (atom-type atom) +itunes-ilst-data+)
+                          (format t "~vt~a~%" depth (vpprint atom nil))))))
 
 
 (defun find-all (base name)
   "Starting as BASE atom, recursively search for all instances of NAME"
   (let* ((search-name (if (typep name 'string) (as-int name) name))
-		 (found))
+         (found))
 
-	(map-mp4-atom base
-				  :func (lambda (atom depth)
-						  (declare (ignore depth))
-						  (when (= (atom-type atom) search-name)
-							(push atom found))))
-	(nreverse found)))
+    (map-mp4-atom base
+                  :func (lambda (atom depth)
+                          (declare (ignore depth))
+                          (when (= (atom-type atom) search-name)
+                            (push atom found))))
+    (nreverse found)))
 
 (defun get-audio-properties-atoms (mp4-file)
   "First, find all TRAKs under moov. For the one that contains a HDLR atom with DATA of 'soun',
 return trak.mdia.mdhd and trak.mdia.minf.stbl.stsd"
   (dolist (track (find-all (traverse (mp4-atoms mp4-file) (list +mp4-atom-moov+)) "trak"))
-	(let ((hdlr (traverse track (list +mp4-atom-mdia+ +audioprop-hdlr+))))
-	  (when (and (not (null hdlr))
-				 (not (null (mtype hdlr)))
-				 (string= "soun" (as-string (mtype hdlr))))
-		;; we've found the correct track, extract atoms
-		(return-from get-audio-properties-atoms (values (traverse track (list +mp4-atom-mdia+ +audioprop-mdhd+))
-														(traverse track (list +mp4-atom-mdia+ +mp4-atom-minf+ +mp4-atom-stbl+ +audioprop-mp4a+))
-														(traverse track (list +mp4-atom-mdia+ +mp4-atom-minf+ +mp4-atom-stbl+ +audioprop-mp4a+ +audioprop-esds+)))))))
+    (let ((hdlr (traverse track (list +mp4-atom-mdia+ +audioprop-hdlr+))))
+      (when (and (not (null hdlr))
+                 (not (null (mtype hdlr)))
+                 (string= "soun" (as-string (mtype hdlr))))
+        ;; we've found the correct track, extract atoms
+        (return-from get-audio-properties-atoms (values (traverse track (list +mp4-atom-mdia+ +audioprop-mdhd+))
+                                                        (traverse track (list +mp4-atom-mdia+ +mp4-atom-minf+ +mp4-atom-stbl+ +audioprop-mp4a+))
+                                                        (traverse track (list +mp4-atom-mdia+ +mp4-atom-minf+ +mp4-atom-stbl+ +audioprop-mp4a+ +audioprop-esds+)))))))
   nil)
 
 (defclass audio-info ()
@@ -606,29 +606,29 @@ return trak.mdia.mdhd and trak.mdia.minf.stbl.stsd"
 
 (defmethod vpprint ((me audio-info) stream)
   (with-slots (seconds channels bits-per-sample sample-rate max-bit-rate avg-bit-rate) me
-	(format stream "sample rate: ~:d Hz, # channels: ~d, bits-per-sample: ~:d, max bit-rate: ~:d Kbps, avg bit-rate: ~:d Kbps, duration: ~:d:~2,'0d"
-			(if sample-rate sample-rate 0)
-			(if channels channels 0)
-			(if bits-per-sample bits-per-sample 0)
-			(if max-bit-rate (round (/ max-bit-rate 1000)) 0)
-			(if avg-bit-rate (round (/ avg-bit-rate 1000)) 0)
-			(if seconds (floor (/ seconds 60)) 0)
-			(if seconds (round (mod seconds 60)) 0))))
+    (format stream "sample rate: ~:d Hz, # channels: ~d, bits-per-sample: ~:d, max bit-rate: ~:d Kbps, avg bit-rate: ~:d Kbps, duration: ~:d:~2,'0d"
+            (if sample-rate sample-rate 0)
+            (if channels channels 0)
+            (if bits-per-sample bits-per-sample 0)
+            (if max-bit-rate (round (/ max-bit-rate 1000)) 0)
+            (if avg-bit-rate (round (/ avg-bit-rate 1000)) 0)
+            (if seconds (floor (/ seconds 60)) 0)
+            (if seconds (round (mod seconds 60)) 0))))
 
 (defun get-mp4-audio-info (mp4-file)
   "MP4a audio info is held in under the trak.mdia.mdhd/trak.mdia.minf.stbl/trak.mdia.minf.stbl.mp4a atoms."
   (let ((info (make-instance 'audio-info)))
-	(multiple-value-bind (mdhd mp4a esds) (get-audio-properties-atoms mp4-file)
-	  (with-slots (seconds channels bits-per-sample sample-rate max-bit-rate avg-bit-rate) info
-		(when mdhd
-		  (setf seconds (/ (float (duration mdhd)) (float (scale mdhd)))))
-		(when mp4a
-		  (setf channels (num-chans mp4a))
-		  (setf bits-per-sample (samp-size mp4a))
-		  (let* ((upper (ash (samp-rate mp4a) -16))
-				 (lower (logand (samp-rate mp4a) #xffff)))
-			(setf sample-rate (+ (float upper) (/ (float lower) 1000))))
-		(when esds
-		  (setf avg-bit-rate (avg-bit-rate esds))
-		  (setf max-bit-rate (max-bit-rate esds))))))
-	info))
+    (multiple-value-bind (mdhd mp4a esds) (get-audio-properties-atoms mp4-file)
+      (with-slots (seconds channels bits-per-sample sample-rate max-bit-rate avg-bit-rate) info
+        (when mdhd
+          (setf seconds (/ (float (duration mdhd)) (float (scale mdhd)))))
+        (when mp4a
+          (setf channels (num-chans mp4a))
+          (setf bits-per-sample (samp-size mp4a))
+          (let* ((upper (ash (samp-rate mp4a) -16))
+                 (lower (logand (samp-rate mp4a) #xffff)))
+            (setf sample-rate (+ (float upper) (/ (float lower) 1000))))
+        (when esds
+          (setf avg-bit-rate (avg-bit-rate esds))
+          (setf max-bit-rate (max-bit-rate esds))))))
+    info))

+ 51 - 51
mp4-tag.lisp

@@ -20,62 +20,62 @@
 (defmethod tempo ((me mp4-file-stream))          (mp4-atom:tag-get-value (mp4-atoms me) mp4-atom:+itunes-tempo+))
 (defmethod genre ((me mp4-file-stream))
   (let ((genre   (mp4-atom:tag-get-value (mp4-atoms me) mp4-atom:+itunes-genre+))
-		(genre-x (mp4-atom:tag-get-value (mp4-atoms me) mp4-atom:+itunes-genre-x+)))
-	(assert (not (and genre genre-x)))
-	(cond
-	  (genre   (format nil "~d (~a)" genre (mp3-tag:get-id3v1-genre genre)))
-	  (genre-x (format nil "~d (~a)" genre-x (mp3-tag:get-id3v1-genre genre-x)))
-	  (t       "None"))))
+        (genre-x (mp4-atom:tag-get-value (mp4-atoms me) mp4-atom:+itunes-genre-x+)))
+    (assert (not (and genre genre-x)))
+    (cond
+      (genre   (format nil "~d (~a)" genre (mp3-tag:get-id3v1-genre genre)))
+      (genre-x (format nil "~d (~a)" genre-x (mp3-tag:get-id3v1-genre genre-x)))
+      (t       "None"))))
 (defmethod track ((me mp4-file-stream))
   (let ((track   (mp4-atom:tag-get-value (mp4-atoms me) mp4-atom:+itunes-track+))
-		(track-n (mp4-atom:tag-get-value (mp4-atoms me) mp4-atom:+itunes-track-n+)))
-	(assert (not (and track track-n)))
-	(if track
-		track
-		track-n)))
+        (track-n (mp4-atom:tag-get-value (mp4-atoms me) mp4-atom:+itunes-track-n+)))
+    (assert (not (and track track-n)))
+    (if track
+        track
+        track-n)))
 
 (defmethod show-tags ((me mp4-file-stream) &key (raw nil))
   "Show the tags for an MP4-FILE. If RAW is non-nil, dump the DATA atoms; else show subset of DATA atoms"
   (format t "~a~%" (stream-filename me))
   (if raw
-	  (progn
-		(mp4-atom:mp4-show-raw-tag-atoms me)
-		(if (audio-info me)
-		  (mp4-atom:vpprint (audio-info me) t)))
-	  (let ((album (album me))
-			(album-artist (album-artist me))
-			(artist (artist me))
-			(comment (comment me))
-			(compilation (compilation me))
-			(composer (composer me))
-			(copyright (copyright me))
-			(disk (disk me))
-			(encoder (encoder me))
-			(genre (genre me))
-			(groups (groups me))
-			(lyrics (lyrics me))
-			(tempo (tempo me))
-			(title (title me))
-			(track (track me))
-			(writer (writer me))
-			(year (year me)))
+      (progn
+        (mp4-atom:mp4-show-raw-tag-atoms me)
+        (if (audio-info me)
+          (mp4-atom:vpprint (audio-info me) t)))
+      (let ((album (album me))
+            (album-artist (album-artist me))
+            (artist (artist me))
+            (comment (comment me))
+            (compilation (compilation me))
+            (composer (composer me))
+            (copyright (copyright me))
+            (disk (disk me))
+            (encoder (encoder me))
+            (genre (genre me))
+            (groups (groups me))
+            (lyrics (lyrics me))
+            (tempo (tempo me))
+            (title (title me))
+            (track (track me))
+            (writer (writer me))
+            (year (year me)))
 
-		(if (audio-info me)
-		  (mp4-atom:vpprint (audio-info me) t))
-		(when album (format t "~&~4talbum: ~a~%" album))
-		(when album-artist (format t "~4talbum-artist: ~a~%" album-artist))
-		(when artist (format t "~4tartist: ~a~%" artist))
-		(when comment (format t "~4tcomment: ~a~%" comment))
-		(format t "~4tcompilation: ~[no~;yes;unknown~]~%" (if compilation compilation 2))
-		(when composer (format t "~4tcomposer: ~a~%" composer))
-		(when copyright (format t "~4tcopyright: ~a~%" copyright))
-		(when disk (format t "~4tdisk: ~a~%" disk))
-		(when encoder (format t "~4tencoder: ~a~%" encoder))
-		(when genre (format t "~4tgenre: ~a~%" genre))
-		(when groups (format t "~4tgroups: ~a~%" groups))
-		(when lyrics (format t "~4tlyrics: ~a~%" lyrics))
-		(when tempo (format t "~4ttempo: ~a~%" tempo))
-		(when title (format t "~4ttitle: ~a~%" title))
-		(when track (format t "~4ttrack: ~a~%" track))
-		(when writer (format t "~4twriter: ~a~%" writer))
-		(when year (format t "~4tyear: ~a~%" year)))))
+        (if (audio-info me)
+          (mp4-atom:vpprint (audio-info me) t))
+        (when album (format t "~&~4talbum: ~a~%" album))
+        (when album-artist (format t "~4talbum-artist: ~a~%" album-artist))
+        (when artist (format t "~4tartist: ~a~%" artist))
+        (when comment (format t "~4tcomment: ~a~%" comment))
+        (format t "~4tcompilation: ~[no~;yes;unknown~]~%" (if compilation compilation 2))
+        (when composer (format t "~4tcomposer: ~a~%" composer))
+        (when copyright (format t "~4tcopyright: ~a~%" copyright))
+        (when disk (format t "~4tdisk: ~a~%" disk))
+        (when encoder (format t "~4tencoder: ~a~%" encoder))
+        (when genre (format t "~4tgenre: ~a~%" genre))
+        (when groups (format t "~4tgroups: ~a~%" groups))
+        (when lyrics (format t "~4tlyrics: ~a~%" lyrics))
+        (when tempo (format t "~4ttempo: ~a~%" tempo))
+        (when title (format t "~4ttitle: ~a~%" title))
+        (when track (format t "~4ttrack: ~a~%" track))
+        (when writer (format t "~4twriter: ~a~%" writer))
+        (when year (format t "~4tyear: ~a~%" year)))))

+ 321 - 321
mpeg.lisp

@@ -5,13 +5,13 @@
 (log5:defcategory cat-log-mpeg-frame)
 (defmacro log-mpeg-frame (&rest log-stuff) `(log5:log-for (cat-log-mpeg-frame) ,@log-stuff))
 
-(define-condition mpeg-condition () 
+(define-condition mpeg-condition ()
   ((location :initarg :location :reader location :initform nil)
    (object   :initarg :object   :reader object   :initform nil)
    (messsage :initarg :message  :reader message  :initform "Undefined Condition"))
-  (:report (lambda (condition stream) 
-			 (format stream "MP3 condition at location <~a> with object <~a>: message<~a>"
-					 (location condition) (object condition) (message condition)))))
+  (:report (lambda (condition stream)
+             (format stream "MP3 condition at location <~a> with object <~a>: message<~a>"
+                     (location condition) (object condition) (message condition)))))
 
 (define-condition mpeg-bad-header (mpeg-condition) ())
 
@@ -24,20 +24,20 @@
 
 (defun valid-version (version)
   (or ;; can't deal with 2.5's yet (= (the fixnum +mpeg-2.5+) (the fixnum version))
-	  (= (the fixnum +mpeg-2+) (the fixnum version))
-	  (= (the fixnum +mpeg-1+) (the fixnum version))))
+      (= (the fixnum +mpeg-2+) (the fixnum version))
+      (= (the fixnum +mpeg-1+) (the fixnum version))))
 
 (defun get-mpeg-version-string (version) (nth version '("MPEG 2.5" "Reserved" "MPEG 2" "MPEG 1")))
 
 (defconstant +layer-reserved+  0)
 (defconstant +layer-3+         1)
-(defconstant +layer-2+		   2)
-(defconstant +layer-1+		   3)
+(defconstant +layer-2+         2)
+(defconstant +layer-1+         3)
 
 (defun valid-layer (layer)
   (or (= (the fixnum +layer-3+) (the fixnum layer))
-	  (= (the fixnum +layer-2+) (the fixnum layer))
-	  (= (the fixnum +layer-1+) (the fixnum layer))))
+      (= (the fixnum +layer-2+) (the fixnum layer))
+      (= (the fixnum +layer-1+) (the fixnum layer))))
 
 (defun get-layer-string (layer) (nth layer '("Reserved" "Layer III" "Layer II" "Layer I")))
 
@@ -53,8 +53,8 @@
 (defconstant +emphasis-ccit+     3)
 (defun get-emphasis-string (e)   (nth e '("None" "50/15 ms" "Reserved" "CCIT J.17")))
 (defun valid-emphasis (e) (or (= (the fixnum e) (the fixnum +emphasis-none+))
-							  (= (the fixnum e) (the fixnum +emphasis-50-15+))
-							  (= (the fixnum e) (the fixnum +emphasis-ccit+))))
+                              (= (the fixnum e) (the fixnum +emphasis-50-15+))
+                              (= (the fixnum e) (the fixnum +emphasis-ccit+))))
 
 (defconstant +mode-extension-0+ 0)
 (defconstant +mode-extension-1+ 1)
@@ -62,22 +62,22 @@
 (defconstant +mode-extension-3+ 3)
 (defun get-mode-extension-string (channel-mode layer mode-extension)
   (if (not (= channel-mode +channel-mode-joint+))
-	  ""
-	  (if (or (= layer +layer-1+)
-			  (= layer +layer-2+))
-		  (format nil "Bands ~[4~;8~;12~;16~] to 31" mode-extension)
-		  (format nil "Intensity Stereo: ~[off~;on~], MS Stereo: ~[off~;on~]" (ash mode-extension -1) (logand mode-extension 1)))))
-  
+      ""
+      (if (or (= layer +layer-1+)
+              (= layer +layer-2+))
+          (format nil "Bands ~[4~;8~;12~;16~] to 31" mode-extension)
+          (format nil "Intensity Stereo: ~[off~;on~], MS Stereo: ~[off~;on~]" (ash mode-extension -1) (logand mode-extension 1)))))
+
 (defun get-samples-per-frame (version layer)
   (cond ((= (the fixnum layer) (the fixnum +layer-1+)) 384)
-		((= (the fixnum layer) (the fixnum +layer-2+)) 1152)
-		((= (the fixnum layer) (the fixnum +layer-3+))
-		 (cond ((= (the fixnum version) +mpeg-1+) 1152)
-			   ((or (= (the fixnum version) (the fixnum +mpeg-2+))
-					(= (the fixnum version) (the fixnum +mpeg-2.5+))) 576)))))
+        ((= (the fixnum layer) (the fixnum +layer-2+)) 1152)
+        ((= (the fixnum layer) (the fixnum +layer-3+))
+         (cond ((= (the fixnum version) +mpeg-1+) 1152)
+               ((or (= (the fixnum version) (the fixnum +mpeg-2+))
+                    (= (the fixnum version) (the fixnum +mpeg-2.5+))) 576)))))
 
 (defclass frame ()
-  ((pos		       :accessor pos :initarg :pos)
+  ((pos            :accessor pos :initarg :pos)
    (b-array        :accessor b-array :initarg :b-array)
    (samples        :accessor samples :initarg :samples)
    (sync           :accessor sync :initarg :sync)
@@ -94,161 +94,161 @@
    (original       :accessor original :initarg :original)
    (emphasis       :accessor emphasis :initarg :emphasis)
    (size           :accessor size :initarg :size)
-   (vbr	           :accessor vbr :initarg :vbr)
-   (payload	       :accessor payload :initarg :payload))
+   (vbr            :accessor vbr :initarg :vbr)
+   (payload        :accessor payload :initarg :payload))
   (:default-initargs :pos nil :b-array nil :samples 0 :sync 0 :version 0 :layer 0 :protection 0 :bit-rate 0
-					 :sample-rate 0 :padded 0 :private 0 :channel-mode 0 :mode-extension 0
-					 :copyright 0 :original 0 :emphasis 0 :size nil :vbr nil :payload nil))
+                     :sample-rate 0 :padded 0 :private 0 :channel-mode 0 :mode-extension 0
+                     :copyright 0 :original 0 :emphasis 0 :size nil :vbr nil :payload nil))
 
 (defmacro with-frame-slots ((instance) &body body)
-  `(with-slots (pos b-array samples sync version layer protection bit-rate sample-rate 
-					padded private channel-mode mode-extension copyright  
-					original emphasis size vbr payload) ,instance
-	 ,@body))
+  `(with-slots (pos b-array samples sync version layer protection bit-rate sample-rate
+                    padded private channel-mode mode-extension copyright
+                    original emphasis size vbr payload) ,instance
+     ,@body))
 
 (let ((bit-array-table
-	   (make-array '(14 5) :initial-contents
-				   '((32   32  32  32   8)
-					 (64   48  40  48  16)
-					 (96   56  48  56  24)
-					 (128  64  56  64  32)
-					 (160  80  64  80  40)
-					 (192  96  80  96  48)
-					 (224 112  96 112  56)
-					 (256 128 112 128  64)
-					 (288 160 128 144  80)
-					 (320 192 160 160  96)
-					 (352 224 192 176 112)
-					 (384 256 224 192 128)
-					 (416 320 256 224 144)
-					 (448 384 320 256 160)))))
+       (make-array '(14 5) :initial-contents
+                   '((32   32  32  32   8)
+                     (64   48  40  48  16)
+                     (96   56  48  56  24)
+                     (128  64  56  64  32)
+                     (160  80  64  80  40)
+                     (192  96  80  96  48)
+                     (224 112  96 112  56)
+                     (256 128 112 128  64)
+                     (288 160 128 144  80)
+                     (320 192 160 160  96)
+                     (352 224 192 176 112)
+                     (384 256 224 192 128)
+                     (416 320 256 224 144)
+                     (448 384 320 256 160)))))
 
   (defun valid-bit-rate-index (br-index)
-	(and (> (the fixnum br-index) 0) (< (the fixnum br-index) 15)))
+    (and (> (the fixnum br-index) 0) (< (the fixnum br-index) 15)))
 
   (defun get-bit-rate (version layer bit-rate-index)
-	(log5:with-context "get-bit-rate"
-	  (log-mpeg-frame "version = ~d, layer = ~d, bit-rate-index = ~d" version layer bit-rate-index)
-	  (let ((row (1- bit-rate-index))
-			(col (cond ((= (the fixnum version) (the fixnum +mpeg-1+))
-						(cond ((= (the fixnum layer) (the fixnum +layer-1+)) 0)
-							  ((= (the fixnum layer) (the fixnum +layer-2+)) 1)
-							  ((= (the fixnum layer) (the fixnum +layer-3+)) 2)
-							  (t nil)))
-					   ((= (the fixnum version) (the fixnum +mpeg-2+))
-						(cond ((= (the fixnum layer) (the fixnum +layer-1+)) 3)
-							  ((= (the fixnum layer) (the fixnum +layer-2+)) 4)
-							  ((= (the fixnum layer) (the fixnum +layer-3+)) 4)
-							  (t nil)))
-					   (t (error "don't support MPEG 2.5 yet")))))
-
-		(log-mpeg-frame "version = ~d, row = ~d, col = ~d" version row col)
-		(if (or (null col) (< row 0) (> row 14))
-			nil
-			(let ((ret (* 1000 (aref bit-array-table row col))))
-			  (log-mpeg-frame "returning ~:d" ret)
-			  ret))))))
+    (log5:with-context "get-bit-rate"
+      (log-mpeg-frame "version = ~d, layer = ~d, bit-rate-index = ~d" version layer bit-rate-index)
+      (let ((row (1- bit-rate-index))
+            (col (cond ((= (the fixnum version) (the fixnum +mpeg-1+))
+                        (cond ((= (the fixnum layer) (the fixnum +layer-1+)) 0)
+                              ((= (the fixnum layer) (the fixnum +layer-2+)) 1)
+                              ((= (the fixnum layer) (the fixnum +layer-3+)) 2)
+                              (t nil)))
+                       ((= (the fixnum version) (the fixnum +mpeg-2+))
+                        (cond ((= (the fixnum layer) (the fixnum +layer-1+)) 3)
+                              ((= (the fixnum layer) (the fixnum +layer-2+)) 4)
+                              ((= (the fixnum layer) (the fixnum +layer-3+)) 4)
+                              (t nil)))
+                       (t (error "don't support MPEG 2.5 yet")))))
+
+        (log-mpeg-frame "version = ~d, row = ~d, col = ~d" version row col)
+        (if (or (null col) (< row 0) (> row 14))
+            nil
+            (let ((ret (* 1000 (aref bit-array-table row col))))
+              (log-mpeg-frame "returning ~:d" ret)
+              ret))))))
 
 (defun valid-sample-rate-index (sr-index)
   (and (>= (the fixnum sr-index) 0)
-	   (<  (the fixnum sr-index) 3)))
+       (<  (the fixnum sr-index) 3)))
 
 (defun get-sample-rate (version sr-index)
   (cond ((= (the fixnum version) (the fixnum +mpeg-1+))
-		 (case (the fixnum sr-index) (0 44100) (1 48000) (2 32000)))
-		((= (the fixnum version) (the fixnum +mpeg-2+))
-		 (case (the fixnum sr-index) (0 22050) (1 24000) (2 16000)))
-		(t nil)))
+         (case (the fixnum sr-index) (0 44100) (1 48000) (2 32000)))
+        ((= (the fixnum version) (the fixnum +mpeg-2+))
+         (case (the fixnum sr-index) (0 22050) (1 24000) (2 16000)))
+        (t nil)))
 
 (defun get-frame-size (version layer bit-rate sample-rate padded)
   (truncate (float (cond ((= (the fixnum layer) (the fixnum +layer-1+))
-						  (* 4 (+ (/ (* 12 bit-rate) sample-rate) padded)))
-						 ((= (the fixnum layer) (the fixnum +layer-2+))
-						  (+ (* 144 (/ bit-rate sample-rate)) padded))
-						 ((= (the fixnum layer) (the fixnum +layer-3+))
-						  (if (= (the fixnum version) (the fixnum +mpeg-1+))
-							  (+ (* 144 (/ bit-rate sample-rate)) padded)
-							  (+ (* 72  (/ bit-rate sample-rate)) padded)))))))
+                          (* 4 (+ (/ (* 12 bit-rate) sample-rate) padded)))
+                         ((= (the fixnum layer) (the fixnum +layer-2+))
+                          (+ (* 144 (/ bit-rate sample-rate)) padded))
+                         ((= (the fixnum layer) (the fixnum +layer-3+))
+                          (if (= (the fixnum version) (the fixnum +mpeg-1+))
+                              (+ (* 144 (/ bit-rate sample-rate)) padded)
+                              (+ (* 72  (/ bit-rate sample-rate)) padded)))))))
 
 (defmethod load-frame ((me frame) &key instream (read-payload nil))
   (log5:with-context "load-frame"
-	(with-frame-slots (me)
-	  (when (null b-array)				; has header already been read in?
-		(setf pos (stream-seek instream 0 :current))
-		(setf b-array (stream-read-sequence instream 4)))
-
-	  (if (parse-header me)
-		  (progn
-			(log-mpeg-frame "header parsed ok")
-			(setf size (get-frame-size version layer bit-rate sample-rate padded))
-			(when read-payload
-			  (setf payload (stream-read-sequence instream (- size 4))))
-			t)
-		  (progn
-			(log-mpeg-frame "header didn't parse!")
-			nil)))))
+    (with-frame-slots (me)
+      (when (null b-array)              ; has header already been read in?
+        (setf pos (stream-seek instream 0 :current))
+        (setf b-array (stream-read-sequence instream 4)))
+
+      (if (parse-header me)
+          (progn
+            (log-mpeg-frame "header parsed ok")
+            (setf size (get-frame-size version layer bit-rate sample-rate padded))
+            (when read-payload
+              (setf payload (stream-read-sequence instream (- size 4))))
+            t)
+          (progn
+            (log-mpeg-frame "header didn't parse!")
+            nil)))))
 
 (defmethod parse-header ((me frame))
   (log5:with-context "parse-header"
-	(with-frame-slots (me)
-
-	  (setf (ldb (byte 8 8) sync) (aref b-array 0))
-	  (setf (ldb (byte 3 5) sync) (ldb (byte 3 5) (aref b-array 1)))
-	  (when (not (= sync +sync-word+))
-		(return-from parse-header nil))
-
-	  (setf version (ldb (byte 2 3) (aref b-array 1)))
-	  (when (not (valid-version version))
-		(log-mpeg-frame "bad version ~d" version)
-		(return-from parse-header nil))
-
-	  (setf layer (ldb (byte 2 1) (aref b-array 1)))
-	  (when (not (valid-layer layer))
-		(log-mpeg-frame "bad layer ~d" layer)
-		(return-from parse-header nil))
-
-	  (setf protection (ldb (byte 1 0) (aref b-array 1)))
-	  (setf samples (get-samples-per-frame version layer))
-
-	  (let ((br-index (the fixnum (ldb (byte 4 4) (aref b-array 2)))))
-		(when (not (valid-bit-rate-index br-index))
-		  (log-mpeg-frame "bad bit-rate index ~d" br-index)
-		  (return-from parse-header nil))
-		(setf bit-rate (get-bit-rate version layer br-index)))
-
-	  (let ((sr-index (the fixnum (ldb (byte 2 2) (aref b-array 2)))))
-		(when (not (valid-sample-rate-index sr-index))
-		  (log-mpeg-frame "bad sample-rate index ~d" sr-index)
-		  (return-from parse-header nil))
-		(setf sample-rate (get-sample-rate version sr-index)))
-
-	  (setf padded (ldb (byte 1 1) (aref b-array 2)))
-	  (setf private (ldb (byte 1 0) (aref b-array 2)))
-
-	  (setf channel-mode (ldb (byte 2 6) (aref b-array 3)))
-	  (setf mode-extension (ldb (byte 2 4) (aref b-array 3)))
-	  (setf copyright (ldb (byte 1 3) (aref b-array 3)))
-	  (setf original (ldb (byte 1 2) (aref b-array 3)))
-	  (setf emphasis (ldb (byte 2 0) (aref b-array 3)))
-	  (when (not (valid-emphasis emphasis))
-		(log-mpeg-frame "bad emphasis ~d" emphasis)
-		(return-from parse-header nil))
-
-	  (log-mpeg-frame "good parse: ~a" me)
-	  t)))
+    (with-frame-slots (me)
+
+      (setf (ldb (byte 8 8) sync) (aref b-array 0))
+      (setf (ldb (byte 3 5) sync) (ldb (byte 3 5) (aref b-array 1)))
+      (when (not (= sync +sync-word+))
+        (return-from parse-header nil))
+
+      (setf version (ldb (byte 2 3) (aref b-array 1)))
+      (when (not (valid-version version))
+        (log-mpeg-frame "bad version ~d" version)
+        (return-from parse-header nil))
+
+      (setf layer (ldb (byte 2 1) (aref b-array 1)))
+      (when (not (valid-layer layer))
+        (log-mpeg-frame "bad layer ~d" layer)
+        (return-from parse-header nil))
+
+      (setf protection (ldb (byte 1 0) (aref b-array 1)))
+      (setf samples (get-samples-per-frame version layer))
+
+      (let ((br-index (the fixnum (ldb (byte 4 4) (aref b-array 2)))))
+        (when (not (valid-bit-rate-index br-index))
+          (log-mpeg-frame "bad bit-rate index ~d" br-index)
+          (return-from parse-header nil))
+        (setf bit-rate (get-bit-rate version layer br-index)))
+
+      (let ((sr-index (the fixnum (ldb (byte 2 2) (aref b-array 2)))))
+        (when (not (valid-sample-rate-index sr-index))
+          (log-mpeg-frame "bad sample-rate index ~d" sr-index)
+          (return-from parse-header nil))
+        (setf sample-rate (get-sample-rate version sr-index)))
+
+      (setf padded (ldb (byte 1 1) (aref b-array 2)))
+      (setf private (ldb (byte 1 0) (aref b-array 2)))
+
+      (setf channel-mode (ldb (byte 2 6) (aref b-array 3)))
+      (setf mode-extension (ldb (byte 2 4) (aref b-array 3)))
+      (setf copyright (ldb (byte 1 3) (aref b-array 3)))
+      (setf original (ldb (byte 1 2) (aref b-array 3)))
+      (setf emphasis (ldb (byte 2 0) (aref b-array 3)))
+      (when (not (valid-emphasis emphasis))
+        (log-mpeg-frame "bad emphasis ~d" emphasis)
+        (return-from parse-header nil))
+
+      (log-mpeg-frame "good parse: ~a" me)
+      t)))
 
 (defmethod vpprint ((me frame) stream)
   (with-frame-slots (me)
-	(format stream "MPEG Frame: position in file = ~:d, header in (hex) bytes = ~x, size = ~d, sync word = ~x, " pos b-array size sync)
-	(when vbr
-	  (format stream "~&vbr-info: ~a~%" vbr))
-	(format stream "version = ~a, layer = ~a, crc protected? = ~[yes~;no~], bit-rate = ~:d bps, sampling rate = ~:d bps, padded? = ~[no~;yes~], private bit set? = ~[no~;yes~], channel mode = ~a, "
-			(get-mpeg-version-string version) (get-layer-string layer)
-			protection bit-rate sample-rate padded private (get-channel-mode-string channel-mode))
-	(format stream "mode extension = ~a, copyrighted? = ~[no~;yes~], original? = ~[no~;yes~], emphasis = ~a"
-			(get-mode-extension-string channel-mode layer mode-extension) copyright original (get-emphasis-string emphasis))
-	(when payload
-	  (format stream "~%frame payload[~:d] = ~a~%" (length payload) payload))))
+    (format stream "MPEG Frame: position in file = ~:d, header in (hex) bytes = ~x, size = ~d, sync word = ~x, " pos b-array size sync)
+    (when vbr
+      (format stream "~&vbr-info: ~a~%" vbr))
+    (format stream "version = ~a, layer = ~a, crc protected? = ~[yes~;no~], bit-rate = ~:d bps, sampling rate = ~:d bps, padded? = ~[no~;yes~], private bit set? = ~[no~;yes~], channel mode = ~a, "
+            (get-mpeg-version-string version) (get-layer-string layer)
+            protection bit-rate sample-rate padded private (get-channel-mode-string channel-mode))
+    (format stream "mode extension = ~a, copyrighted? = ~[no~;yes~], original? = ~[no~;yes~], emphasis = ~a"
+            (get-mode-extension-string channel-mode layer mode-extension) copyright original (get-emphasis-string emphasis))
+    (when payload
+      (format stream "~%frame payload[~:d] = ~a~%" (length payload) payload))))
 
 (defclass vbr-info ()
   ((tag    :accessor tag :initarg :tag)
@@ -261,7 +261,7 @@
 
 (defmacro with-vbr-info-slots ((instance) &body body)
   `(with-slots (tag flags frames bytes tocs scale) ,instance
-	 ,@body))
+     ,@body))
 
 (defconstant +vbr-frames+  1)
 (defconstant +vbr-bytes+   2)
@@ -270,147 +270,147 @@
 
 (defun get-side-info-size (version channel-mode)
   (cond ((= (the fixnum version) (the fixnum +mpeg-1+))
-		 (cond ((= (the fixnum channel-mode) (the fixnum +channel-mode-mono+)) 17)
-			   (t 32)))
-		(t (cond ((= (the fixnum channel-mode) (the fixnum +channel-mode-mono+)) 9)
-				 (t 17)))))
+         (cond ((= (the fixnum channel-mode) (the fixnum +channel-mode-mono+)) 17)
+               (t 32)))
+        (t (cond ((= (the fixnum channel-mode) (the fixnum +channel-mode-mono+)) 9)
+                 (t 17)))))
 
 (defmethod check-vbr ((me frame))
   (log5::with-context "check-vbr"
-	(with-frame-slots (me)
-	  (let ((i (get-side-info-size version channel-mode)))
-		(log-mpeg-frame "array index = ~d, payload size = ~d" i (length payload))
-		(when (or (and (= (aref payload (+ i 0)) (char-code #\X))
-					   (= (aref payload (+ i 1)) (char-code #\i))
-					   (= (aref payload (+ i 2)) (char-code #\n))
-					   (= (aref payload (+ i 3)) (char-code #\g)))
-				  (and (= (aref payload (+ i 0)) (char-code #\I))
-					   (= (aref payload (+ i 1)) (char-code #\n))
-					   (= (aref payload (+ i 2)) (char-code #\f))
-					   (= (aref payload (+ i 3)) (char-code #\o))))
-
-		  (log-mpeg-frame "found xing/info: ~c ~c ~c ~c"
-					  (code-char (aref payload (+ i 0)))
-					  (code-char (aref payload (+ i 1)))
-					  (code-char (aref payload (+ i 2)))
-					  (code-char (aref payload (+ i 3))))
-
-		  (setf vbr (make-instance 'vbr-info))
-		  (let ((v (make-mem-stream (payload me))))
-			(stream-seek v i :start)			; seek to xing/info info
-			(setf (tag vbr)   (stream-read-iso-string-with-len v 4))
-			(setf (flags vbr) (stream-read-u32 v))
-			(when (logand (flags vbr) +vbr-frames+)
-			  (setf (frames vbr) (stream-read-u32 v))
-			  (if (= 0 (frames vbr)) (warn-user "warning Xing/Info header flags has FRAMES set, but field is zero")))
-			(when (logand (flags vbr) +vbr-bytes+)
-			  (setf (bytes vbr) (stream-read-u32 v))
-			  (if (= 0 (bytes vbr)) (warn-user "warning Xing/Info header flags has BYTES set, but field is zero")))
-			(when (logand (flags vbr) +vbr-tocs+)
-			  (setf (tocs vbr) (stream-read-sequence v 100)))
-			(when (logand (flags vbr) +vbr-scale+)
-			  (setf (scale vbr) (stream-read-u32 v)))
-			(log-mpeg-frame "vbr-info = ~a" (vpprint vbr nil))))))))
+    (with-frame-slots (me)
+      (let ((i (get-side-info-size version channel-mode)))
+        (log-mpeg-frame "array index = ~d, payload size = ~d" i (length payload))
+        (when (or (and (= (aref payload (+ i 0)) (char-code #\X))
+                       (= (aref payload (+ i 1)) (char-code #\i))
+                       (= (aref payload (+ i 2)) (char-code #\n))
+                       (= (aref payload (+ i 3)) (char-code #\g)))
+                  (and (= (aref payload (+ i 0)) (char-code #\I))
+                       (= (aref payload (+ i 1)) (char-code #\n))
+                       (= (aref payload (+ i 2)) (char-code #\f))
+                       (= (aref payload (+ i 3)) (char-code #\o))))
+
+          (log-mpeg-frame "found xing/info: ~c ~c ~c ~c"
+                      (code-char (aref payload (+ i 0)))
+                      (code-char (aref payload (+ i 1)))
+                      (code-char (aref payload (+ i 2)))
+                      (code-char (aref payload (+ i 3))))
+
+          (setf vbr (make-instance 'vbr-info))
+          (let ((v (make-mem-stream (payload me))))
+            (stream-seek v i :start)            ; seek to xing/info info
+            (setf (tag vbr)   (stream-read-iso-string-with-len v 4))
+            (setf (flags vbr) (stream-read-u32 v))
+            (when (logand (flags vbr) +vbr-frames+)
+              (setf (frames vbr) (stream-read-u32 v))
+              (if (= 0 (frames vbr)) (warn-user "warning Xing/Info header flags has FRAMES set, but field is zero")))
+            (when (logand (flags vbr) +vbr-bytes+)
+              (setf (bytes vbr) (stream-read-u32 v))
+              (if (= 0 (bytes vbr)) (warn-user "warning Xing/Info header flags has BYTES set, but field is zero")))
+            (when (logand (flags vbr) +vbr-tocs+)
+              (setf (tocs vbr) (stream-read-sequence v 100)))
+            (when (logand (flags vbr) +vbr-scale+)
+              (setf (scale vbr) (stream-read-u32 v)))
+            (log-mpeg-frame "vbr-info = ~a" (vpprint vbr nil))))))))
 
 (defmethod vpprint ((me vbr-info) stream)
   (with-vbr-info-slots (me)
-	(format stream "tag = ~a, flags = 0x~x, frames = ~:d, bytes = ~:d, tocs = ~d, scale = ~d, "
-			tag flags frames bytes tocs scale)))
+    (format stream "tag = ~a, flags = 0x~x, frames = ~:d, bytes = ~:d, tocs = ~d, scale = ~d, "
+            tag flags frames bytes tocs scale)))
 
 (defun find-first-sync (in)
   (log5:with-context "find-first-sync"
 
-	(log-mpeg-frame "Looking for first sync, begining at file position ~:d" (stream-seek in 0 :current))
-	(let ((b-array (make-octets 4))
-		  (pos))
-
-	  (handler-case 
-		  ;;
-		  ;; loop through entire file if we have to
-		  ;; XXX question: if we read FF E from the file (two bytes), but the
-		  ;; parse fails (i.e. a false sync), do we skip forward, or try to parse
-		  ;; the second byte as the FF?
-		  (loop 
-			 (setf pos (stream-seek in 0 :current))
-			 (setf (aref b-array 0) (stream-read-u8 in))
-			 (when (= (aref b-array 0) #xff)
-			   (setf (aref b-array 1) (stream-read-u8 in))
-			   (when (= (logand (aref b-array 1) #xe0) #xe0)
-				 (log-mpeg-frame "Potential sync bytes at ~:d: <~x>" pos b-array)
-				 (setf (aref b-array 2) (stream-read-u8 in))
-				 (setf (aref b-array 3) (stream-read-u8 in))
-
-				 (let ((hdr (make-instance 'frame :b-array b-array :pos pos)))
-				   (if (load-frame hdr :instream in :read-payload t)
-					   (progn
-						 (check-vbr hdr)
-						 (log-mpeg-frame "Valid header being returned: ~a" hdr)
-						 (return-from find-first-sync hdr))
-					   (progn
-						 (log-mpeg-frame "hdr wasn't valid: ~a" hdr)))))))
-		(end-of-file (c) (progn 
-						   (log-mpeg-frame "got a condition while looking for first sync: ~a" c)
-						   (error c))))
-	  nil)))
+    (log-mpeg-frame "Looking for first sync, begining at file position ~:d" (stream-seek in 0 :current))
+    (let ((b-array (make-octets 4))
+          (pos))
+
+      (handler-case
+          ;;
+          ;; loop through entire file if we have to
+          ;; XXX question: if we read FF E from the file (two bytes), but the
+          ;; parse fails (i.e. a false sync), do we skip forward, or try to parse
+          ;; the second byte as the FF?
+          (loop
+             (setf pos (stream-seek in 0 :current))
+             (setf (aref b-array 0) (stream-read-u8 in))
+             (when (= (aref b-array 0) #xff)
+               (setf (aref b-array 1) (stream-read-u8 in))
+               (when (= (logand (aref b-array 1) #xe0) #xe0)
+                 (log-mpeg-frame "Potential sync bytes at ~:d: <~x>" pos b-array)
+                 (setf (aref b-array 2) (stream-read-u8 in))
+                 (setf (aref b-array 3) (stream-read-u8 in))
+
+                 (let ((hdr (make-instance 'frame :b-array b-array :pos pos)))
+                   (if (load-frame hdr :instream in :read-payload t)
+                       (progn
+                         (check-vbr hdr)
+                         (log-mpeg-frame "Valid header being returned: ~a" hdr)
+                         (return-from find-first-sync hdr))
+                       (progn
+                         (log-mpeg-frame "hdr wasn't valid: ~a" hdr)))))))
+        (end-of-file (c) (progn
+                           (log-mpeg-frame "got a condition while looking for first sync: ~a" c)
+                           (error c))))
+      nil)))
 
 (defmethod next-frame ((me frame) &key instream read-payload)
   (log5:with-context "next-frame"
-	(let ((nxt-frame (make-instance 'frame)))
-	  (when (not (payload me))
-		(log-mpeg-frame "no payload in current frame, skipping from ~:d forward ~:d bytes"
-						(stream-seek instream 0 :current)
-						(- (size me) 4) :current)
-		(stream-seek instream (- (size me) 4) :current))
+    (let ((nxt-frame (make-instance 'frame)))
+      (when (not (payload me))
+        (log-mpeg-frame "no payload in current frame, skipping from ~:d forward ~:d bytes"
+                        (stream-seek instream 0 :current)
+                        (- (size me) 4) :current)
+        (stream-seek instream (- (size me) 4) :current))
 
-	  (if (load-frame nxt-frame :instream instream :read-payload read-payload)
-		  nxt-frame
-		  nil))))
+      (if (load-frame nxt-frame :instream instream :read-payload read-payload)
+          nxt-frame
+          nil))))
 
 (defun map-frames (in func &key (start-pos nil) (read-payload nil) (max nil))
   (log5:with-context "next-frame"
-	(log-mpeg-frame "mapping frame, start pos ~:d" start-pos)
+    (log-mpeg-frame "mapping frame, start pos ~:d" start-pos)
 
-	(when start-pos
-	  (stream-seek in start-pos :start))
+    (when start-pos
+      (stream-seek in start-pos :start))
 
-	(loop 
-	   for max-frames = (if max max most-positive-fixnum)
-	   for count = 0 then (incf count)
-	   for frame = (find-first-sync in) then (next-frame frame :instream in :read-payload read-payload)
-	    while (and frame (< count max-frames)) do
-		 (log-mpeg-frame "At pos ~:d, dispatching function" (pos frame))
-		 (funcall func frame))))
+    (loop
+       for max-frames = (if max max most-positive-fixnum)
+       for count = 0 then (incf count)
+       for frame = (find-first-sync in) then (next-frame frame :instream in :read-payload read-payload)
+        while (and frame (< count max-frames)) do
+         (log-mpeg-frame "At pos ~:d, dispatching function" (pos frame))
+         (funcall func frame))))
 
 (defun get-mpeg-bit-rate-exhaustive (in)
   (let ((n-frames 0)
-		(total-len 0)
-		(last-bit-rate nil)
-		(bit-rate-total 0)
-		(vbr nil))
-	(map-frames in (lambda (f)
-					 (incf n-frames)
-					 (incf total-len (float (/ (samples f) (sample-rate f))))
-					 (incf bit-rate-total (bit-rate f))
-					 (if (null last-bit-rate)
-						 (setf last-bit-rate (bit-rate f))
-						 (progn
-						   (when (not (= last-bit-rate (bit-rate f)))
-							 (setf vbr t))
-						   (setf last-bit-rate (bit-rate f)))))
-				:read-payload nil)
-	(if (or (zerop n-frames) (zerop bit-rate-total))
-		(values nil nil nil)
-		(values vbr (float (/ bit-rate-total n-frames)) total-len))))
+        (total-len 0)
+        (last-bit-rate nil)
+        (bit-rate-total 0)
+        (vbr nil))
+    (map-frames in (lambda (f)
+                     (incf n-frames)
+                     (incf total-len (float (/ (samples f) (sample-rate f))))
+                     (incf bit-rate-total (bit-rate f))
+                     (if (null last-bit-rate)
+                         (setf last-bit-rate (bit-rate f))
+                         (progn
+                           (when (not (= last-bit-rate (bit-rate f)))
+                             (setf vbr t))
+                           (setf last-bit-rate (bit-rate f)))))
+                :read-payload nil)
+    (if (or (zerop n-frames) (zerop bit-rate-total))
+        (values nil nil nil)
+        (values vbr (float (/ bit-rate-total n-frames)) total-len))))
 
 (defun get-mpeg-bit-rate-ff (in)
   (let ((ff (find-first-sync in)))
-	(if (not ff)
-		(return-from get-mpeg-bit-rate-ff (values nil nil)))
-	(if (vbr ff)
-		(let* ((len (float (* (frames (vbr ff)) (/ (samples ff) (sample-rate ff)))))
-			   (br (float (/ (* 8 (bytes (vbr ff)) ) len))))
-		  (values t br len))
-		(values nil nil nil))))
+    (if (not ff)
+        (return-from get-mpeg-bit-rate-ff (values nil nil)))
+    (if (vbr ff)
+        (let* ((len (float (* (frames (vbr ff)) (/ (samples ff) (sample-rate ff)))))
+               (br (float (/ (* 8 (bytes (vbr ff)) ) len))))
+          (values t br len))
+        (values nil nil nil))))
 
 (defclass mpeg-audio-info ()
   ((is-vbr      :accessor is-vbr :initarg :is-vbr :initform nil)
@@ -422,62 +422,62 @@
 
 (defmethod vpprint ((me mpeg-audio-info) stream)
   (with-slots (is-vbr sample-rate  bit-rate len version layer) me
-	(format stream "~a, ~a, ~:[CBR,~;VBR,~] sample rate: ~:d Hz, bit rate: ~:d Kbps, duration: ~:d:~2,'0d"
-			(get-mpeg-version-string version)
-			(get-layer-string layer)
-			is-vbr
-			sample-rate
-			(round (/ bit-rate 1000))
-			(floor (/ len 60)) (round (mod len 60)))))
+    (format stream "~a, ~a, ~:[CBR,~;VBR,~] sample rate: ~:d Hz, bit rate: ~:d Kbps, duration: ~:d:~2,'0d"
+            (get-mpeg-version-string version)
+            (get-layer-string layer)
+            is-vbr
+            sample-rate
+            (round (/ bit-rate 1000))
+            (floor (/ len 60)) (round (mod len 60)))))
 
 (defun get-mpeg-audio-info (in &key (max-frames nil))
   "Get MPEG Layer 3 audio information."
   (log5:with-context "get-mpeg-audio-info"
-	(let ((pos (stream-seek in 0 :current))
-		  (first-frame (find-first-sync in))
-		  (info (make-instance 'mpeg-audio-info)))
-
-	  (log-mpeg-frame "search for first frame yielded ~a" first-frame)
-	  (when (null first-frame)
-		(return-from get-mpeg-audio-info nil))
-
-	  (with-slots (is-vbr sample-rate bit-rate len version layer) info
-		(setf version (version first-frame))
-		(setf layer (layer first-frame))
-		(setf sample-rate (sample-rate first-frame))
-		(if (vbr first-frame)
-			(progn
-			  (log-mpeg-frame "found Xing/Info header")
-			  (setf is-vbr t)
-			  (setf len (float (* (frames (vbr first-frame)) (/ (samples first-frame) (sample-rate first-frame)))))
-			  (setf bit-rate  (float (/ (* 8 (bytes (vbr first-frame)) ) len))))
-			(let ((n-frames 0)
-				  (total-len 0)
-				  (last-bit-rate nil)
-				  (bit-rate-total 0)
-				  (vbr nil))
-			  (stream-seek in pos :start)
-			  (log-mpeg-frame "no Xing/Info, so mapping frames")
-			  (map-frames in (lambda (f)
-							   (incf n-frames)
-							   (incf total-len (float (/ (samples f) (sample-rate f))))
-							   (incf bit-rate-total (bit-rate f))
-							   (if (null last-bit-rate)
-								   (setf last-bit-rate (bit-rate f))
-								   (progn
-									 (when (not (= last-bit-rate (bit-rate f)))
-									   (setf vbr t))
-									 (setf last-bit-rate (bit-rate f)))))
-						  :read-payload nil :max max-frames)
-			  (if (or (< n-frames 10) (zerop bit-rate-total))
-				  (progn
-					(log-mpeg-frame "couldn't get audio-info: only got ~d frames" n-frames)
-					(return-from get-mpeg-audio-info nil))
-				  (progn
-					(setf is-vbr vbr)
-					(setf len total-len)
-					(setf bit-rate (float (/ bit-rate-total n-frames))))))))
-	  info)))
+    (let ((pos (stream-seek in 0 :current))
+          (first-frame (find-first-sync in))
+          (info (make-instance 'mpeg-audio-info)))
+
+      (log-mpeg-frame "search for first frame yielded ~a" first-frame)
+      (when (null first-frame)
+        (return-from get-mpeg-audio-info nil))
+
+      (with-slots (is-vbr sample-rate bit-rate len version layer) info
+        (setf version (version first-frame))
+        (setf layer (layer first-frame))
+        (setf sample-rate (sample-rate first-frame))
+        (if (vbr first-frame)
+            (progn
+              (log-mpeg-frame "found Xing/Info header")
+              (setf is-vbr t)
+              (setf len (float (* (frames (vbr first-frame)) (/ (samples first-frame) (sample-rate first-frame)))))
+              (setf bit-rate  (float (/ (* 8 (bytes (vbr first-frame)) ) len))))
+            (let ((n-frames 0)
+                  (total-len 0)
+                  (last-bit-rate nil)
+                  (bit-rate-total 0)
+                  (vbr nil))
+              (stream-seek in pos :start)
+              (log-mpeg-frame "no Xing/Info, so mapping frames")
+              (map-frames in (lambda (f)
+                               (incf n-frames)
+                               (incf total-len (float (/ (samples f) (sample-rate f))))
+                               (incf bit-rate-total (bit-rate f))
+                               (if (null last-bit-rate)
+                                   (setf last-bit-rate (bit-rate f))
+                                   (progn
+                                     (when (not (= last-bit-rate (bit-rate f)))
+                                       (setf vbr t))
+                                     (setf last-bit-rate (bit-rate f)))))
+                          :read-payload nil :max max-frames)
+              (if (or (< n-frames 10) (zerop bit-rate-total))
+                  (progn
+                    (log-mpeg-frame "couldn't get audio-info: only got ~d frames" n-frames)
+                    (return-from get-mpeg-audio-info nil))
+                  (progn
+                    (setf is-vbr vbr)
+                    (setf len total-len)
+                    (setf bit-rate (float (/ bit-rate-total n-frames))))))))
+      info)))
 
 
 #|

+ 41 - 41
packages.lisp

@@ -12,55 +12,55 @@
 
 (defpackage #:audio-streams
   (:export #:octets #:make-octets *get-mpeg-audio-info*
-		   #:mp3-file-stream #:mp4-file-stream #:base-mem-stream
-		   #:id3-header #:audio-info #:mp4-atoms
-		   #:parse-mp3-file #:parse-mp4-file
-		   #:make-mem-stream #:stream-filename
-		   #:stream-read-u8 #:stream-read-u16 #:stream-read-u24 #:stream-read-u32 #:stream-read-u64 #:stream-read-octets
-		   #:stream-decode-iso-string #:stream-deocode-ucs-string #:stream-decode-ucs-be-string
-		   #:stream-decode-utf-8-string #:stream-decode-string #:stream-read-iso-string-with-len
-		   #:stream-read-ucs-string-with-len #:stream-read-ucs-be-string-with-len
-		   #:stream-read-utf-8-string-with-len #:stream-read-string-with-len
-		   #:stream-read-iso-string #:stream-read-ucs-string #:stream-read-ucs-be-string
-		   #:stream-read-utf-8-string #:stream-read-string
-		   #:stream-read-string #:stream-read-sequence #:stream-size
-		   #:stream-seek #:stream-close)
+           #:mp3-file-stream #:mp4-file-stream #:base-mem-stream
+           #:id3-header #:audio-info #:mp4-atoms
+           #:parse-mp3-file #:parse-mp4-file
+           #:make-mem-stream #:stream-filename
+           #:stream-read-u8 #:stream-read-u16 #:stream-read-u24 #:stream-read-u32 #:stream-read-u64 #:stream-read-octets
+           #:stream-decode-iso-string #:stream-deocode-ucs-string #:stream-decode-ucs-be-string
+           #:stream-decode-utf-8-string #:stream-decode-string #:stream-read-iso-string-with-len
+           #:stream-read-ucs-string-with-len #:stream-read-ucs-be-string-with-len
+           #:stream-read-utf-8-string-with-len #:stream-read-string-with-len
+           #:stream-read-iso-string #:stream-read-ucs-string #:stream-read-ucs-be-string
+           #:stream-read-utf-8-string #:stream-read-string
+           #:stream-read-string #:stream-read-sequence #:stream-size
+           #:stream-seek #:stream-close)
   (:use #:common-lisp #:utils))
 
 (defpackage #:mp4-atom
   (:export #:mp4-atom #:map-mp4-atom #:find-mp4-atoms #:traverse #:mp4-atom-condition
-		   #:atom-file-position #:atom-children #:atom-size #:atom-of-interest #:atom-decoded
-		   #:atom-type #:vpprint #:*tag-path* #:tag-get-value #:mp4-atom-condition
-		   #:mp4-show-raw-tag-atoms #:get-mp4-audio-info
-		   #:+itunes-album+
-		   #:+itunes-album-artist+
-		   #:+itunes-artist+
-		   #:+itunes-comment+
-		   #:+itunes-composer+
-		   #:+itunes-copyright+
-		   #:+itunes-year+
-		   #:+itunes-encoder+
-		   #:+itunes-groups+
-		   #:+itunes-lyrics+
-		   #:+itunes-purchased-date+
-		   #:+itunes-title+
-		   #:+itunes-tool+
-		   #:+itunes-writer+
-		   #:+itunes-compilation+
-		   #:+itunes-cover-art+
-		   #:+itunes-disk+
-		   #:+itunes-genre+
-		   #:+itunes-genre-x+
-		   #:+itunes-tempo+
-		   #:+itunes-track+
-		   #:+itunes-track-n+)
+           #:atom-file-position #:atom-children #:atom-size #:atom-of-interest #:atom-decoded
+           #:atom-type #:vpprint #:*tag-path* #:tag-get-value #:mp4-atom-condition
+           #:mp4-show-raw-tag-atoms #:get-mp4-audio-info
+           #:+itunes-album+
+           #:+itunes-album-artist+
+           #:+itunes-artist+
+           #:+itunes-comment+
+           #:+itunes-composer+
+           #:+itunes-copyright+
+           #:+itunes-year+
+           #:+itunes-encoder+
+           #:+itunes-groups+
+           #:+itunes-lyrics+
+           #:+itunes-purchased-date+
+           #:+itunes-title+
+           #:+itunes-tool+
+           #:+itunes-writer+
+           #:+itunes-compilation+
+           #:+itunes-cover-art+
+           #:+itunes-disk+
+           #:+itunes-genre+
+           #:+itunes-genre-x+
+           #:+itunes-tempo+
+           #:+itunes-track+
+           #:+itunes-track-n+)
   (:use #:common-lisp #:audio-streams #:utils))
 
 
 (defpackage #:id3-frame
   (:export #:id3-frame #:find-id3-frames #:id3-frame-condition #:vpprint #:header #:get-frame-info
-		   #:encoding #:lang #:desc #:val #:comment #:artist #:album #:year #:comment #:year
-		   #:map-id3-frames #:frames #:year #:title #:genre #:id #:v21-tag-header #:info #:version)
+           #:encoding #:lang #:desc #:val #:comment #:artist #:album #:year #:comment #:year
+           #:map-id3-frames #:frames #:year #:title #:genre #:id #:v21-tag-header #:info #:version)
   (:use #:common-lisp #:audio-streams #:utils #:iso-639-2))
 
 (defpackage #:mp3-tag
@@ -69,7 +69,7 @@
 
 (defpackage #:mp4-tag
   (:export #:show-tags #:album #:album-artist #:artist #:comment #:composer #:copyright #:created
-		   #:encoder #:groups #:lyrics #:purd #:title #:tool #:writer)
+           #:encoder #:groups #:lyrics #:purd #:title #:tool #:writer)
   (:use #:common-lisp #:audio-streams #:utils))
 
 (defpackage #:logging

+ 28 - 28
taglib-tests.lisp

@@ -22,26 +22,26 @@
 
 (defmethod has-extension ((p pathname) ext)
   (let ((e (pathname-type p)))
-	(if e
-	  (string= (string-downcase e) (string-downcase ext))
-	  nil)))
+    (if e
+      (string= (string-downcase e) (string-downcase ext))
+      nil)))
 
 (defmacro redirect (filename &rest body)
   `(let ((*standard-output* (open ,filename :direction :output :if-does-not-exist :create :if-exists :supersede)))
-	 ,@body
-	 (finish-output *standard-output*)))
+     ,@body
+     (finish-output *standard-output*)))
 
 ;;; A note re filesystem encoding: my music collection is housed on a Mac and shared via SAMBA.
-;;; In order to make sure we get valid pathnames, we need to set CCL's filesystem encoding to 
+;;; In order to make sure we get valid pathnames, we need to set CCL's filesystem encoding to
 ;;; :UTF-8
 
 ;;;;;;;;;;;;;;;;;;;; MP4 Tests ;;;;;;;;;;;;;;;;;;;;
 (defun mp4-test0 (file)
   (let (foo)
-	(unwind-protect
-		 (setf foo (parse-mp4-file file))
-	  (when foo (stream-close foo)))
-	foo))
+    (unwind-protect
+         (setf foo (parse-mp4-file file))
+      (when foo (stream-close foo)))
+    foo))
 
 (defun mp4-test1 ()
   (mp4-test0 *song-m4a*))
@@ -49,19 +49,19 @@
 (defun mp4-test2 (&key (dir "Queen") (raw nil) (file-system-encoding :utf-8))
   (set-pathname-encoding file-system-encoding)
   (osicat:walk-directory dir (lambda (f)
-							   (when (has-extension f "m4a")
-								 (let ((file (mp4-test0 f)))
-								   (when file 
-									 (mp4-tag:show-tags file :raw raw)
-									 (mp4-atom::get-mp4-audio-info file)))))))
+                               (when (has-extension f "m4a")
+                                 (let ((file (mp4-test0 f)))
+                                   (when file
+                                     (mp4-tag:show-tags file :raw raw)
+                                     (mp4-atom::get-mp4-audio-info file)))))))
 
 ;;;;;;;;;;;;;;;;;;;; MP3 Tests ;;;;;;;;;;;;;;;;;;;;
 (defun mp3-test0 (file)
   (let (foo)
-	(unwind-protect 
-		 (setf foo (parse-mp3-file file))
-	  (when foo (stream-close foo)))
-	foo))
+    (unwind-protect
+         (setf foo (parse-mp3-file file))
+      (when foo (stream-close foo)))
+    foo))
 
 (defun mp3-test1 ()
   (mp3-test0 *song-mp3*))
@@ -69,17 +69,17 @@
 (defun mp3-test2 (&key (dir "Queen") (raw nil) (file-system-encoding :utf-8))
   (set-pathname-encoding file-system-encoding)
   (osicat:walk-directory dir (lambda (f)
-							   (when (has-extension f "mp3")
-								 (let ((file (mp3-test0 f)))
-								   (when file (mp3-tag:show-tags file :raw raw)))))))
+                               (when (has-extension f "mp3")
+                                 (let ((file (mp3-test0 f)))
+                                   (when file (mp3-tag:show-tags file :raw raw)))))))
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 (defun test2 (&key (dir "Queen") (raw nil) (file-system-encoding :utf-8))
   (set-pathname-encoding file-system-encoding)
   (osicat:walk-directory dir (lambda (f)
-							   (if (has-extension f "mp3")
-								   (let ((file (mp3-test0 f)))
-									 (when file (mp3-tag:show-tags file :raw raw)))
-								   (if (has-extension f "m4a")
-									   (let ((file (mp4-test0 f)))
-										 (when file (mp4-tag:show-tags file :raw raw))))))))
+                               (if (has-extension f "mp3")
+                                   (let ((file (mp3-test0 f)))
+                                     (when file (mp3-tag:show-tags file :raw raw)))
+                                   (if (has-extension f "m4a")
+                                       (let ((file (mp4-test0 f)))
+                                         (when file (mp4-tag:show-tags file :raw raw))))))))

+ 9 - 9
taglib.asd

@@ -11,14 +11,14 @@
   :license "Public Domain"
   :depends-on (#:log5 #:alexandria)
   :components ((:file "packages")
-			   (:file "utils"         :depends-on ("packages"))
-			   (:file "audio-streams" :depends-on ("packages" "utils"))
-			   (:file "mpeg"          :depends-on ("packages" "audio-streams" "utils"))
-			   (:file "iso-639-2"     :depends-on ("packages" "utils"))
-			   (:file "id3-frame"     :depends-on ("packages" "utils"))
-			   (:file "mp3-tag"       :depends-on ("packages" "id3-frame" "audio-streams" "utils"))
-			   (:file "logging"       :depends-on ("packages" "mp4-atom" "audio-streams" "utils"))
-			   (:file "mp4-atom"      :depends-on ("packages" "utils"))
-			   (:file "mp4-tag"       :depends-on ("packages" "utils"))))
+               (:file "utils"         :depends-on ("packages"))
+               (:file "audio-streams" :depends-on ("packages" "utils"))
+               (:file "mpeg"          :depends-on ("packages" "audio-streams" "utils"))
+               (:file "iso-639-2"     :depends-on ("packages" "utils"))
+               (:file "id3-frame"     :depends-on ("packages" "utils"))
+               (:file "mp3-tag"       :depends-on ("packages" "id3-frame" "audio-streams" "utils"))
+               (:file "logging"       :depends-on ("packages" "mp4-atom" "audio-streams" "utils"))
+               (:file "mp4-atom"      :depends-on ("packages" "utils"))
+               (:file "mp4-tag"       :depends-on ("packages" "utils"))))
 
 

+ 4 - 4
utils.lisp

@@ -14,9 +14,9 @@
 (defun printable-array (array)
   "given an array, return a string of the first *MAX-RAW-BYTES-PRINT-LEN* bytes"
   (let* ((len (length array))
-		 (print-len (min len *max-raw-bytes-print-len*))
-		 (printable-array (make-array print-len :displaced-to array)))
-	(format nil "[~:d of ~:d bytes] <~x>" print-len len printable-array)))
+         (print-len (min len *max-raw-bytes-print-len*))
+         (printable-array (make-array print-len :displaced-to array)))
+    (format nil "[~:d of ~:d bytes] <~x>" print-len len printable-array)))
 
 (defun upto-null (string)
   "Trim STRING to end at first NULL found"
@@ -24,4 +24,4 @@
 
 (defun dump-data (file-name data)
   (with-open-file (f file-name :direction :output :if-exists :supersede :element-type '(unsigned-byte 8))
-	(write-sequence data f)))
+    (write-sequence data f)))