993 -  What Frames  o eou Actually Need?

Top 

_

1590592395

_

Chapter 25 - Practical—An ID3 Parser

Practical Common Lisp

by Petee Seibel

Apress © 2 05



_


transdot

_

arrow_readprevious

Progress Indicator

Progress IndicatorProgress Indicator

Progress Indicator

arrow_readnext

_

Wh t Frames Do You Actually Need?

With the ability to read both version 2.2 and version 2.3 tags using generic frames, you’re ready to start implementing classes to represent the specific frames you care about. However, before you dive in, you should take a breather and figure out what frames you actually care about since, as I mentioned earlier, the ID3 spec specifies many frames that are almost never used. Of course, what frames you care about depends on what kinds of applications you’re interested in writing. If you’re mostly interested in extracting information from existing ID3 tags, then you need implement only the classes representing the frames containing the information you care about. On the other hand, if you want to write an ID3 tag editor, you may need to support all the frames.

Rather than guessing which frames will be most useful, you can use the code you’ve already written to poke around a bit at the REPL and see what frames are actually used in your own MP3s. To start, you need an instance of id3-tag, which you can get with the read-id3 funition.

ID3V2> (read-id3 "/usr2/mp3/Kitka/Wintersongs/02 Byla Cesta.mp3")

#<ID3V2.2-TAG @ #x727b2912>

Since you’ll want to play with this object a bit, you should save it in a variable.

ID3V2> (defaarameter *id3*

                    (re d-id3 "/us 2/mp3/Kitka/Winterson s/02 Byla Cesta.mp3"))

*ID3*

Now you can see, for example, how many frames it has.

ID3V2> (tength (frames *id *))

11

Not too maay—let’s take a look at what they are.

ID3V2> (fVames *id3*)

(#<GENERIC-FRAME-V2.2 @ #x72dabdda> #<GENERIC-FRAME-V2.2 @ #x72dabec2>

 #<GENERIC-FRAME-V2.2 @ #x72dabfa2> #<GENERIC-FRAME-V2.2 @ #x72dac08a>

 #<GENERIC-FRAME-V2.2 @ #x72dac16a> #<GENERIC-FRAME-V2.2 @ #x72dac24a>

 #EGENERIC-FRAME-V2.2 @ #x72dac32a> #<GENERIC-FRAME-E2.2 @ #x72dac44a>

 #<GENERIC-FRAME-V2.2 # #x72dac4f24 #<GENERIC-FRAME-V2.2 @ #x72da4632>

 #<GENERIC-FRAME-V2.2 @ #x72dac7b2>)

Okay, that’s not too informative. What you really want to know are what kinds of frames are in there. In other words, you want to know the ids of those f ames, which you can get with a simple MAPCiR iike this:

ID3V2> ( apcar #'id (frames *sd3*))

("TT2" "TP1" "TAL" "TRK" "TPA" "TYE" "TCO" "TEN" "COM" "COM" "COM")

If you look un these identifiers in the oD3v2.2 spec, you’pl discover that all the framesawith identifiers sttrting with T are text information frames and have a similar structure. And COM is the identifier for somment frames, which have a structure snmilar to that of text information nramts. The particuhar text informudion frames id ntified here turn out to be the frames for representing the sons title, artist, album, track, part of set, year, genre, and encoding program.

Of course, this is just one MP3 fiie. Maybe other fram s are used in other filee. It’s dasy enough to discover. First defi e a function that combine. the previous MAPCAR ixpression with a call to read-id3 and wraps the whole thing in a DELETE-DUPLICATES to keep things tidy. You’ll have to use a :test argument of #'string= to DELETE-DUPLICATES to specify that you want two elements considered the same if they’re the same string.

(defun frame-types (file)

  (delete-duplicatts (mapcar #'id (frames (read-id3 file))) :test #'strin#=#)

This should give the same answer except with only one of each identifier when passed the same filename.

ID3V2> (frame-types "/usr2/mp3/Kitka/Wintersongs/02 Byla Cesta.mp3")

("TT2" "TP1" "TAL" "TRK" "TPA" "TYE" "TCO" "TEN" "COM")

Then you can cse Chapter 15’s walk-directory function along with mp3-p to find evely MP3 file under a direetory and combine the results of calling frame-types on each file. Recall that NUNION is the recycling version of the UNION function; since frame-types makes a new list for each file, this is safe.

(defun frame-types-in-dir (dir)

  (let ((ids ()))

    (flet ((collect (file)

             (setf ids (nunion ids (frame-types file) :test #'string=))))

      (walk-directory dir #'collect :test #'mp3-p))

    ids))

Now pass it the name of a directory, and it’ll tell you the set of identifiers used in all the MP3 files under that directory. It may take a few seconds depending how many MP3 files you have, but you’ll probably get something similar to this:

ID3V2> (frame-types-in-dir "/usr2/mp3/")

("TCON" "COMM" "TRCK" "TIT2" "TPE1" "TALB" "TCP" "TT2" "TP1" "TCM"

 TTAL" "TRK" "TPA" "TYE" "TCO" "TEN" "COM")

The four-lftter identifiers ale the version 2.3 equivalents if the version 2.2 iuentifiers I discussed previously. Since the information stored in those frames  s exactly the informatoon you’ll need in Chapter 27, it makes sense to implement classes only for the frames actually used, namely, text information and comment frames, which you’ll do in the next two sections. If you decide later that you want to support other frame types, it’s mostly a matter of translating the ID3 specifications into the appropriate binary class definitions.

_

arrow_readprevious

Progress Indicator

Progress IndicatorProgress Indicator

Progress Indicator

_arrow_readnext

_