| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375 |
- ;;; -*- Mode: Lisp; show-trailing-whitespace: t; Base: 10; indent-tabs: nil; Syntax: ANSI-Common-Lisp; Package: MP3-TAG; -*-
- ;;; Copyright (c) 2013, Mark VandenBrink. All rights reserved.
- (in-package #:mp3-tag)
- (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"))
- (defun get-id3v1-genre (n)
- (let ((idx (- n 1))) ; arrays are zero-based
- (if (or (> idx (length *id3v1-genres*))
- (< idx 0))
- "BAD GENRE!?!?!?"
- (aref *id3v1-genres* idx))))
- (defun get-frames (stream names)
- (let (found-frames)
- (map-id3-frames stream
- :func (lambda (f)
- (when (member (id f) names :test #'string=)
- (push f found-frames))))
- (nreverse found-frames)))
- (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)))))
- (if (v21-tag-header (id3-header me))
- (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)))))
- (if (v21-tag-header (id3-header me))
- (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))
- (return-from comment new-frames))))
- (if (v21-tag-header (id3-header me))
- (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)))))
- (if (v21-tag-header (id3-header me))
- (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)))))
- (if (v21-tag-header (id3-header me))
- (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 "file ~a has more than one genre frame, will only use the first" (stream-filename me)))
- (let ((count)
- (end)
- (str (info (first frames))))
- (when (and (>= (length str) 1) (eq #\( (aref str 0)))
- (setf count (count #\( str))
- (when (> count 1) (warn "Don't support genre refinement yet, found ~d genres" count))
- (setf end (position #\) str))
- (when (null end) (warn "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))
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 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)))))
- 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)))))
- 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)))))
- 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)))))
- 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)))))
- 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)))))
- nil)
- (defmethod purchased-date ((me mp3-file-stream)) "NIY")
- (defmethod tool ((me mp3-file-stream)) "NIY")
- (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)))))
- 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)))))
- 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))))))
- 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)))))
- nil)
- (defun mk-lst (str)
- (let ((pos (position #\/ str)))
- (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))))))
- 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 (mpeg-info me)
- (vpprint (mpeg-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))
- (purchased-date (purchased-date me))
- (tempo (tempo me))
- (title (title me))
- (tool (tool me))
- (track (track me))
- (writer (writer me))
- (year (year me)))
- (format t "~a: ~a~%" (stream-filename me)
- (if (mpeg-info me)
- (vpprint (mpeg-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 purchased-date (format t "~4tpurchased date: ~a~%" purchased-date))
- (when tempo (format t "~4ttempo: ~a~%" tempo))
- (when title (format t "~4ttitle: ~a~%" title))
- (when tool (format t "~4ttool: ~a~%" tool))
- (when track (format t "~4ttrack: ~a~%" track))
- (when writer (format t "~4twriter: ~a~%" writer))
- (when year (format t "~4tyear: ~a~%" year)))))
|