abstract-tag.lisp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483
  1. ;;; -*- Mode: Lisp; show-trailing-whitespace: t; Base: 10; indent-tabs: nil; Syntax: ANSI-Common-Lisp; Package: ABSTRACT-TAG; -*-
  2. ;;; Copyright (c) 2013, Mark VandenBrink. All rights reserved.
  3. (in-package #:abstract-tag)
  4. (defparameter *raw-tags* nil
  5. "Controls whether or not we print 'raw' tags (aka frames) or
  6. textual representation of tags")
  7. (defparameter *id3v1-genres*
  8. #("Blues" "Classic Rock" "Country" "Dance" "Disco" "Funk" "Grunge"
  9. "Hip-Hop" "Jazz" "Metal" "New Age" "Oldies" "Other" "Pop" "R&B" "Rap"
  10. "Reggae" "Rock" "Techno" "Industrial" "Alternative" "Ska" "Death Metal"
  11. "Pranks" "Soundtrack" "Euro-Techno" "Ambient" "Trip-Hop" "Vocal"
  12. "Jazz+Funk" "Fusion" "Trance" "Classical" "Instrumental" "Acid" "House"
  13. "Game" "Sound Clip" "Gospel" "Noise" "Alternative Rock" "Bass" "Soul"
  14. "Punk" "Space" "Meditative" "Instrumental Pop" "Instrumental Rock"
  15. "Ethnic" "Gothic" "Darkwave" "Techno-Industrial" "Electronic"
  16. "Pop-Folk" "Eurodance" "Dream" "Southern Rock" "Comedy" "Cult"
  17. "Gangsta" "Top 40" "Christian Rap" "Pop/Funk" "Jungle" "Native
  18. American" "Cabaret" "New Wave" "Psychedelic" "Rave" "Showtunes"
  19. "Trailer" "Lo-Fi" "Tribal" "Acid Punk" "Acid Jazz" "Polka" "Retro"
  20. "Musical" "Rock & Roll" "Hard Rock" "Folk" "Folk/Rock" "National Folk"
  21. "Swing" "Fusion" "Bebob" "Latin" "Revival" "Celtic" "Bluegrass"
  22. "Avantgarde" "Gothic Rock" "Progressive Rock" "Psychedelic Rock"
  23. "Symphonic Rock" "Slow Rock" "Big Band" "Chorus" "Easy Listening"
  24. "Acoustic" "Humour" "Speech" "Chanson" "Opera" "Chamber Music" "Sonata"
  25. "Symphony" "Booty Bass" "Primus" "Porn Groove" "Satire" "Slow Jam"
  26. "Club" "Tango" "Samba" "Folklore" "Ballad" "Power Ballad" "Rhythmic
  27. Soul" "Freestyle" "Duet" "Punk Rock" "Drum Solo" "A Cappella"
  28. "Euro-House" "Dance Hall" "Goa" "Drum & Bass" "Club-House" "Hardcore"
  29. "Terror" "Indie" "BritPop" "Negerpunk" "Polsk Punk" "Beat" "Christian
  30. Gangsta Rap" "Heavy Metal" "Black Metal" "Crossover" "Contemporary
  31. Christian" "Christian Rock" "Merengue" "Salsa" "Thrash Metal" "Anime"
  32. "Jpop" "Synthpop"))
  33. (defun find-genre (name)
  34. "For debug purpose only: test function to return index of genre, given a name.
  35. Ignores case and returns first complete match"
  36. (let ((i 0)
  37. (match-str (string-downcase name)))
  38. (loop for s across *id3v1-genres* do
  39. (if (string= (string-downcase s) match-str)
  40. (return-from find-genre i))
  41. (incf i))))
  42. (defun get-id3v1-genre (n)
  43. "Given N, a supposed ID3 genre, range check it to make sure it
  44. is > 0 and < (sizeof *ID3V1-GENRES*)"
  45. (declare #.utils:*standard-optimize-settings*)
  46. (if (or (> n (1- (length *id3v1-genres*)))
  47. (< n 0))
  48. "BAD GENRE"
  49. (aref *id3v1-genres* n)))
  50. ;;;; The abstract tag interface
  51. (defgeneric album (stream))
  52. (defgeneric artist (stream))
  53. (defgeneric comment (stream))
  54. (defgeneric composer (stream))
  55. (defgeneric copyright (stream))
  56. (defgeneric cover (stream))
  57. (defgeneric year (stream))
  58. (defgeneric encoder (stream))
  59. (defgeneric groups (stream))
  60. (defgeneric lyrics (stream))
  61. (defgeneric title (stream))
  62. (defgeneric writer (stream))
  63. (defgeneric compilation (stream))
  64. (defgeneric disk (stream))
  65. (defgeneric tempo (stream))
  66. (defgeneric genre (stream))
  67. ;;;; MP3
  68. (defmethod cover ((me id3:mp3-file))
  69. (declare #.utils:*standard-optimize-settings*)
  70. (let ((pictures)
  71. (frames (id3:get-frames me '("PIC" "APIC"))))
  72. (when frames
  73. (dolist (f frames)
  74. (push (id3:picture-info f) pictures)))
  75. pictures))
  76. (defmethod album ((me id3:mp3-file))
  77. (declare #.utils:*standard-optimize-settings*)
  78. (let ((frames (id3:get-frames me '("TAL" "TALB"))))
  79. (when frames
  80. (assert (= 1 (length frames)) () "There can be only one album tag")
  81. (return-from album (id3:info (first frames)))))
  82. (if (id3:v21-tag-header (id3:id3-header me))
  83. (id3:album (id3:v21-tag-header (id3:id3-header me)))
  84. nil))
  85. (defmethod artist ((me id3:mp3-file))
  86. (declare #.utils:*standard-optimize-settings*)
  87. (let ((frames (id3:get-frames me '("TP1" "TPE1"))))
  88. (when frames
  89. (assert (= 1 (length frames)) () "There can be only one artist tag")
  90. (return-from artist (id3:info (first frames)))))
  91. (if (id3:v21-tag-header (id3:id3-header me))
  92. (id3:artist (id3:v21-tag-header (id3:id3-header me)))
  93. nil))
  94. (defmethod comment ((me id3:mp3-file))
  95. (declare #.utils:*standard-optimize-settings*)
  96. (let ((frames (id3:get-frames me '("COM" "COMM"))))
  97. (when frames
  98. (let ((new-frames))
  99. (dolist (f frames)
  100. (push (list (id3:encoding f)
  101. (id3:lang f)
  102. (id3:desc f)
  103. (id3:val f)) new-frames))
  104. (return-from comment new-frames))))
  105. (if (id3:v21-tag-header (id3:id3-header me))
  106. (id3:comment (id3:v21-tag-header (id3:id3-header me)))
  107. nil))
  108. (defmethod year ((me id3:mp3-file))
  109. (declare #.utils:*standard-optimize-settings*)
  110. (let ((frames (id3:get-frames me '("TRD" "TDRC"))))
  111. (when frames
  112. (assert (= 1 (length frames)) () "There can be only one year tag")
  113. (return-from year (id3:info (first frames)))))
  114. (if (id3:v21-tag-header (id3:id3-header me))
  115. (id3:year (id3:v21-tag-header (id3:id3-header me)))
  116. nil))
  117. (defmethod title ((me id3:mp3-file))
  118. (declare #.utils:*standard-optimize-settings*)
  119. (let ((frames (id3:get-frames me '("TT2" "TIT2"))))
  120. (when frames
  121. (assert (= 1 (length frames)) () "There can be only one title tag")
  122. (return-from title (id3:info (first frames)))))
  123. (if (id3:v21-tag-header (id3:id3-header me))
  124. (id3:title (id3:v21-tag-header (id3:id3-header me)))
  125. nil))
  126. (defmethod genre ((me id3:mp3-file))
  127. (declare #.utils:*standard-optimize-settings*)
  128. (let ((frames (id3:get-frames me '("TCO" "TCON"))))
  129. (when frames
  130. (when (> (length frames) 1)
  131. (warn-user "file ~a:~%Has more than one genre frame, will only use the first"
  132. (id3:filename me)))
  133. (let ((count)
  134. (end)
  135. (str (id3:info (first frames))))
  136. ;; For V23/V24 TCON frames, a genre can be pretty gnarly. if the
  137. ;; first byte of the TCON INFO field is a '(', what is between this
  138. ;; '(' and the next ')' is interpreted as an ID3v2.1 genre number.
  139. ;; These can stack up (called "refinements") too. The INFO field
  140. ;; can also just be a string. We're taking a simplistic approach
  141. ;; here: we can handle the '(' case, but only allow one (no
  142. ;; refinements) OR we can handle the simple string case
  143. (when (and (>= (length str) 1) (eq #\( (aref str 0)))
  144. (setf count (count #\( str))
  145. (when (> count 1)
  146. (warn-user "file ~a:~%Don't support genre refinement yet, found ~d genres"
  147. (id3:filename me) count))
  148. (setf end (position #\) str))
  149. (when (null end)
  150. (warn-user "file ~a:~%Bad format for genre, ending paren is missing"
  151. (id3:filename me)))
  152. (setf str (get-id3v1-genre (parse-integer (subseq str 1 end)))))
  153. (return-from genre str))))
  154. (if (id3:v21-tag-header (id3:id3-header me))
  155. (get-id3v1-genre (id3:genre (id3:v21-tag-header (id3:id3-header me))))
  156. nil))
  157. ;;;; No V2.1 tags for any of these
  158. (defmethod album-artist ((me id3:mp3-file))
  159. (declare #.utils:*standard-optimize-settings*)
  160. (let ((frames (id3:get-frames me '("TP2" "TPE2"))))
  161. (when frames
  162. (assert (= 1 (length frames)) () "There can be only one album-artist tag")
  163. (return-from album-artist (id3:info (first frames)))))
  164. nil)
  165. (defmethod composer ((me id3:mp3-file))
  166. (declare #.utils:*standard-optimize-settings*)
  167. (let ((frames (id3:get-frames me '("TCM" "TCOM"))))
  168. (when frames
  169. (assert (= 1 (length frames)) () "There can be only one composer tag")
  170. (return-from composer (id3:info (first frames)))))
  171. nil)
  172. (defmethod copyright ((me id3:mp3-file))
  173. (declare #.utils:*standard-optimize-settings*)
  174. (let ((frames (id3:get-frames me '("TCR" "TCOP"))))
  175. (when frames
  176. (assert (= 1 (length frames)) () "There can be only one copyright tag")
  177. (return-from copyright (id3:info (first frames)))))
  178. nil)
  179. (defmethod encoder ((me id3:mp3-file))
  180. (declare #.utils:*standard-optimize-settings*)
  181. (let ((frames (id3:get-frames me '("TEN" "TENC"))))
  182. (when frames
  183. (assert (= 1 (length frames)) () "There can be only one encoder tag")
  184. (return-from encoder (id3:info (first frames)))))
  185. nil)
  186. (defmethod groups ((me id3:mp3-file))
  187. (declare #.utils:*standard-optimize-settings*)
  188. (let ((frames (id3:get-frames me '("TT1" "TTE1"))))
  189. (when frames
  190. (assert (= 1 (length frames)) () "There can be only one group tag")
  191. (return-from groups (id3:info (first frames)))))
  192. nil)
  193. (defmethod lyrics ((me id3:mp3-file))
  194. (declare #.utils:*standard-optimize-settings*)
  195. (let ((frames (id3:get-frames me '("ULT" "USLT"))))
  196. (when frames
  197. (assert (= 1 (length frames)) () "There can be only one lyrics tag")
  198. (return-from lyrics (id3:val (first frames)))))
  199. nil)
  200. (defmethod writer ((me id3:mp3-file))
  201. (declare #.utils:*standard-optimize-settings*)
  202. (let ((frames (id3:get-frames me '("TCM" "TCOM"))))
  203. (when frames
  204. (assert (= 1 (length frames)) () "There can be only one composer tag")
  205. (return-from writer (id3:info (first frames)))))
  206. nil)
  207. (defmethod compilation ((me id3:mp3-file))
  208. (declare #.utils:*standard-optimize-settings*)
  209. (let ((frames (id3:get-frames me '("TCMP" "TCP"))))
  210. (if frames
  211. (id3:info (first frames))
  212. "no")))
  213. (defmethod disk ((me id3:mp3-file))
  214. (declare #.utils:*standard-optimize-settings*)
  215. (let ((frames (id3:get-frames me '("TPA" "TPOS"))))
  216. (when frames
  217. (assert (= 1 (length frames)) () "There can be only one disk number tag")
  218. (return-from disk (mk-lst (id3:info (first frames))))))
  219. nil)
  220. (defmethod tempo ((me id3:mp3-file))
  221. (declare #.utils:*standard-optimize-settings*)
  222. (let ((frames (id3:get-frames me '("TBP" "TBPM"))))
  223. (when frames
  224. (assert (= 1 (length frames)) () "There can be only one tempo tag")
  225. (return-from tempo (id3:info (first frames)))))
  226. nil)
  227. (defun mk-lst (str)
  228. "Transform 'N/M' to (N M)"
  229. (declare #.utils:*standard-optimize-settings*)
  230. (let ((pos (position #\/ str)))
  231. (if (null pos)
  232. (list str)
  233. (list (subseq str 0 pos) (subseq str (+ 1 pos))))))
  234. (defmethod track ((me id3:mp3-file))
  235. (declare #.utils:*standard-optimize-settings*)
  236. (let ((frames (id3:get-frames me '("TRK" "TRCK"))))
  237. (when frames
  238. (assert (= 1 (length frames)) () "There can be only one track number tag")
  239. (return-from track (mk-lst (id3:info (first frames))))))
  240. nil)
  241. (defmethod show-tags ((me id3:mp3-file) &key (raw *raw-tags*))
  242. "Show the tags for an MP3. If RAW is non-nil, dump all the frames;
  243. else, print out a subset."
  244. (declare #.utils:*standard-optimize-settings*)
  245. (format t "~a~%" (id3:filename me))
  246. (when (id3:audio-info me)
  247. (mpeg:vpprint (id3:audio-info me) t)
  248. (format t "~%"))
  249. (if raw
  250. (id3:vpprint (id3:id3-header me) t)
  251. (let ((album (album me))
  252. (album-artist (album-artist me))
  253. (artist (artist me))
  254. (comment (comment me))
  255. (compilation (compilation me))
  256. (composer (composer me))
  257. (copyright (copyright me))
  258. (cover (cover me))
  259. (disk (disk me))
  260. (encoder (encoder me))
  261. (genre (genre me))
  262. (groups (groups me))
  263. (lyrics (lyrics me))
  264. (tempo (tempo me))
  265. (title (title me))
  266. (track (track me))
  267. (writer (writer me))
  268. (year (year me)))
  269. (when album (format t "~&~4talbum: ~a~%" album))
  270. (when album-artist (format t "~4talbum-artist: ~a~%" album-artist))
  271. (when artist (format t "~4tartist: ~a~%" artist))
  272. (when comment (format t "~4tcomment: ~a~%" comment))
  273. (when compilation (format t "~4tcompilation: ~a~%" compilation))
  274. (when composer (format t "~4tcomposer: ~a~%" composer))
  275. (when copyright (format t "~4tcopyright: ~a~%" copyright))
  276. (when cover (format t "~4tcover: ~a~%" cover))
  277. (when disk (format t "~4tdisk: ~a~%" disk))
  278. (when encoder (format t "~4tencoder: ~a~%" encoder))
  279. (when genre (format t "~4tgenre: ~a~%" genre))
  280. (when groups (format t "~4tgroups: ~a~%" groups))
  281. (when lyrics (format t "~4tlyrics: ~a~%" lyrics))
  282. (when tempo (format t "~4ttempo: ~a~%" tempo))
  283. (when title (format t "~4ttitle: ~a~%" title))
  284. (when track (format t "~4ttrack: ~a~%" track))
  285. (when writer (format t "~4twriter: ~a~%" writer))
  286. (when year (format t "~4tyear: ~a~%" year)))))
  287. ;;;; MP4
  288. (defmethod album ((me m4a:mp4-file)) (m4a:tag-get-value (m4a:mp4-atoms me) m4a:+itunes-album+))
  289. (defmethod album-artist ((me m4a:mp4-file)) (m4a:tag-get-value (m4a:mp4-atoms me) m4a:+itunes-album-artist+))
  290. (defmethod artist ((me m4a:mp4-file)) (m4a:tag-get-value (m4a:mp4-atoms me) m4a:+itunes-artist+))
  291. (defmethod comment ((me m4a:mp4-file)) (m4a:tag-get-value (m4a:mp4-atoms me) m4a:+itunes-comment+))
  292. (defmethod composer ((me m4a:mp4-file)) (m4a:tag-get-value (m4a:mp4-atoms me) m4a:+itunes-composer+))
  293. (defmethod copyright ((me m4a:mp4-file)) (m4a:tag-get-value (m4a:mp4-atoms me) m4a:+itunes-copyright+))
  294. ;;;(defmethod cover ((me m4a:mp4-file)) (m4a:tag-get-value (m4a:mp4-atoms me) m4a:+itunes-cover-art+))
  295. (defmethod year ((me m4a:mp4-file)) (m4a:tag-get-value (m4a:mp4-atoms me) m4a:+itunes-year+))
  296. (defmethod encoder ((me m4a:mp4-file)) (m4a:tag-get-value (m4a:mp4-atoms me) m4a:+itunes-encoder+))
  297. (defmethod groups ((me m4a:mp4-file)) (m4a:tag-get-value (m4a:mp4-atoms me) m4a:+itunes-groups+))
  298. (defmethod lyrics ((me m4a:mp4-file)) (m4a:tag-get-value (m4a:mp4-atoms me) m4a:+itunes-lyrics+))
  299. (defmethod title ((me m4a:mp4-file)) (m4a:tag-get-value (m4a:mp4-atoms me) m4a:+itunes-title+))
  300. (defmethod writer ((me m4a:mp4-file)) (m4a:tag-get-value (m4a:mp4-atoms me) m4a:+itunes-writer+))
  301. (defmethod compilation ((me m4a:mp4-file)) (m4a:tag-get-value (m4a:mp4-atoms me) m4a:+itunes-compilation+))
  302. (defmethod disk ((me m4a:mp4-file)) (m4a:tag-get-value (m4a:mp4-atoms me) m4a:+itunes-disk+))
  303. (defmethod tempo ((me m4a:mp4-file)) (m4a:tag-get-value (m4a:mp4-atoms me) m4a:+itunes-tempo+))
  304. (defmethod genre ((me m4a:mp4-file))
  305. (declare #.utils:*standard-optimize-settings*)
  306. (let ((genre (m4a:tag-get-value (m4a:mp4-atoms me) m4a:+itunes-genre+))
  307. (genre-x (m4a:tag-get-value (m4a:mp4-atoms me) m4a:+itunes-genre-x+)))
  308. (assert (not (and genre genre-x)))
  309. (cond
  310. (genre (format nil "~d (~a)" genre (get-id3v1-genre (1- genre))))
  311. (genre-x genre-x)
  312. (t "not present"))))
  313. (defmethod track ((me m4a:mp4-file))
  314. (declare #.utils:*standard-optimize-settings*)
  315. (let ((track (m4a:tag-get-value (m4a:mp4-atoms me) m4a:+itunes-track+))
  316. (track-n (m4a:tag-get-value (m4a:mp4-atoms me) m4a:+itunes-track-n+)))
  317. (assert (not (and track track-n)))
  318. (if track
  319. track
  320. track-n)))
  321. (defmethod show-tags ((me m4a:mp4-file) &key (raw *raw-tags*))
  322. "Show the tags for an MP4-FILE. If RAW is non-nil, dump the DATA atoms;
  323. else show subset of DATA atoms"
  324. (declare #.utils:*standard-optimize-settings*)
  325. (format t "~a~%" (m4a:filename me))
  326. (when (m4a:audio-info me)
  327. (m4a:vpprint (m4a:audio-info me) t)
  328. (format t "~%"))
  329. (if raw
  330. (m4a:mp4-show-raw-tag-atoms me t)
  331. (let ((album (album me))
  332. (album-artist (album-artist me))
  333. (artist (artist me))
  334. (comment (comment me))
  335. (compilation (compilation me))
  336. (composer (composer me))
  337. (copyright (copyright me))
  338. ;;; (cover (cover me))
  339. (disk (disk me))
  340. (encoder (encoder me))
  341. (genre (genre me))
  342. (groups (groups me))
  343. (lyrics (lyrics me))
  344. (tempo (tempo me))
  345. (title (title me))
  346. (track (track me))
  347. (writer (writer me))
  348. (year (year me)))
  349. (when album (format t "~&~4talbum: ~a~%" album))
  350. (when album-artist (format t "~4talbum-artist: ~a~%" album-artist))
  351. (when artist (format t "~4tartist: ~a~%" artist))
  352. (when comment (format t "~4tcomment: ~a~%" comment))
  353. (format t "~4tcompilation: ~[no~;yes~;unknown~]~%" (if compilation compilation 2))
  354. (when composer (format t "~4tcomposer: ~a~%" composer))
  355. (when copyright (format t "~4tcopyright: ~a~%" copyright))
  356. ;;; (when cover (format t "~4tcover: Number of covers: :~d~%" cover))
  357. (when disk (format t "~4tdisk: ~a~%" disk))
  358. (when encoder (format t "~4tencoder: ~a~%" encoder))
  359. (when genre (format t "~4tgenre: ~a~%" genre))
  360. (when groups (format t "~4tgroups: ~a~%" groups))
  361. (when lyrics (format t "~4tlyrics: ~a~%" lyrics))
  362. (when tempo (format t "~4ttempo: ~a~%" tempo))
  363. (when title (format t "~4ttitle: ~a~%" title))
  364. (when track (format t "~4ttrack: ~a~%" track))
  365. (when writer (format t "~4twriter: ~a~%" writer))
  366. (when year (format t "~4tyear: ~a~%" year)))))
  367. ;;;; FLAC
  368. (defmacro get-flac-tag-info (stream name)
  369. `(flac:flac-get-tag (flac:flac-tags ,stream) ,name))
  370. (defmethod album ((me flac:flac-file)) (get-flac-tag-info me "album"))
  371. (defmethod artist ((me flac:flac-file)) (get-flac-tag-info me "artist"))
  372. (defmethod album-artist ((me flac:flac-file)) (get-flac-tag-info me "album artist"))
  373. (defmethod comment ((me flac:flac-file)) (get-flac-tag-info me "comment"))
  374. (defmethod composer ((me flac:flac-file)) (get-flac-tag-info me "composer"))
  375. (defmethod copyright ((me flac:flac-file)) (get-flac-tag-info me "copyright"))
  376. (defmethod disk ((me flac:flac-file)) (get-flac-tag-info me "disk"))
  377. (defmethod encoder ((me flac:flac-file)) (get-flac-tag-info me "encoder"))
  378. (defmethod year ((me flac:flac-file)) (get-flac-tag-info me "date"))
  379. (defmethod title ((me flac:flac-file)) (get-flac-tag-info me "title"))
  380. (defmethod genre ((me flac:flac-file)) (get-flac-tag-info me "genre"))
  381. (defmethod track ((me flac:flac-file))
  382. (declare #.utils:*standard-optimize-settings*)
  383. (let ((tr (get-flac-tag-info me "tracknumber"))
  384. (tn (get-flac-tag-info me "tracktotal")))
  385. (if tn (list tr tn) tr)))
  386. (defmethod show-tags ((me flac:flac-file) &key (raw *raw-tags*))
  387. "Show the tags for a FLAC-FILE."
  388. (declare #.utils:*standard-optimize-settings*)
  389. (format t "~a~%" (flac:filename me))
  390. (when (flac:audio-info me)
  391. (flac:vpprint (flac:audio-info me) t)
  392. (format t "~%"))
  393. (if raw
  394. (flac:flac-show-raw-tag me t)
  395. (let ((album (album me))
  396. (album-artist (album-artist me))
  397. (artist (artist me))
  398. (copyright (copyright me))
  399. (comment (comment me))
  400. (composer (composer me))
  401. (encoder (encoder me))
  402. (genre (genre me))
  403. (title (title me))
  404. (track (track me))
  405. (year (year me)))
  406. (when album (format t "~&~4talbum: ~a~%" album))
  407. (when album-artist (format t "~4talbum-artist: ~a~%" album-artist))
  408. (when artist (format t "~4tartist: ~a~%" artist))
  409. (when copyright (format t "~4tcopyright: ~a~%" copyright))
  410. (when comment (format t "~4tcomment: ~a~%" comment))
  411. (when composer (format t "~4tcomposer: ~a~%" composer))
  412. (when encoder (format t "~4tencoder: ~a~%" encoder))
  413. (when genre (format t "~4tgenre: ~a~%" genre))
  414. (when title (format t "~4ttitle: ~a~%" title))
  415. (when track (format t "~4ttrack: ~a~%" track))
  416. (when year (format t "~4tyear: ~a~%" year)))))