Peter Siebel - Practical Common Lisp

Здесь есть возможность читать онлайн «Peter Siebel - Practical Common Lisp» весь текст электронной книги совершенно бесплатно (целиком полную версию без сокращений). В некоторых случаях можно слушать аудио, скачать через торрент в формате fb2 и присутствует краткое содержание. Год выпуска: 2005, ISBN: 2005, Издательство: Apress, Жанр: Программирование, на английском языке. Описание произведения, (предисловие) а так же отзывы посетителей доступны на портале библиотеки ЛибКат.

Practical Common Lisp: краткое содержание, описание и аннотация

Предлагаем к чтению аннотацию, описание, краткое содержание или предисловие (зависит от того, что написал сам автор книги «Practical Common Lisp»). Если вы не нашли необходимую информацию о книге — напишите в комментариях, мы постараемся отыскать её.

Practical Common Lisp — читать онлайн бесплатно полную книгу (весь текст) целиком

Ниже представлен текст книги, разбитый по страницам. Система сохранения места последней прочитанной страницы, позволяет с удобством читать онлайн бесплатно книгу «Practical Common Lisp», без необходимости каждый раз заново искать на чём Вы остановились. Поставьте закладку, и сможете в любой момент перейти на страницу, на которой закончили чтение.

Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

(define-binary-class generic-frame ()

((data (raw-bytes :size (data-bytes (current-binary-object))))))

(defgeneric data-bytes (frame))

(defmethod data-bytes ((frame id3v2.2-frame))

(size frame))

(defmethod data-bytes ((frame id3v2.3-frame))

(let ((flags (flags frame)))

(- (size frame)

(if (frame-compressed-p flags) 4 0)

(if (frame-encrypted-p flags) 1 0)

(if (frame-grouped-p flags) 1 0))))

Then you can define concrete classes that extend one of the version-specific base classes and generic-frameto define version-specific generic frame classes.

(define-binary-class generic-frame-v2.2 (id3v2.2-frame generic-frame) ())

(define-binary-class generic-frame-v2.3 (id3v2.3-frame generic-frame) ())

With these classes defined, you can redefine the find-frame-classfunction to return the right versioned class based on the length of the identifier.

(defun find-frame-class (id)

(ecase (length id)

(3 'generic-frame-v2.2)

(4 'generic-frame-v2.3)))

What 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-id3function.

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

#

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

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

*ID3*

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

ID3V2> (length (frames *id3*))

11

Not too many—let's take a look at what they are.

ID3V2> (frames *id3*)

(# #

# #

# #

# #

# #

#)

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 frames, which you can get with a simple MAPCAR like this:

ID3V2> (mapcar #'id (frames *id3*))

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

If you look up these identifiers in the ID3v2.2 spec, you'll discover that all the frames with identifiers starting with T are text information frames and have a similar structure. And COM is the identifier for comment frames, which have a structure similar to that of text information frames. The particular text information frames identified here turn out to be the frames for representing the song title, artist, album, track, part of set, year, genre, and encoding program.

Of course, this is just one MP3 file. Maybe other frames are used in other files. It's easy enough to discover. First define a function that combines the previous MAPCAR expression with a call to read-id3and wraps the whole thing in a DELETE-DUPLICATES to keep things tidy. You'll have to use a :testargument 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-duplicates (mapcar #'id (frames (read-id3 file))) :test #'string=))

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 use Chapter 15's walk-directoryfunction along with mp3-pto find every MP3 file under a directory and combine the results of calling frame-typeson each file. Recall that NUNION is the recycling version of the UNION function; since frame-typesmakes 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"

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

The four-letter identifiers are the version 2.3 equivalents of the version 2.2 identifiers I discussed previously. Since the information stored in those frames is exactly the information 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.

Text Information Frames

All text information frames consist of two fields: a single byte indicating which string encoding is used in the frame and a string encoded in the remaining bytes of the frame. If the encoding byte is zero, the string is encoded in ISO 8859-1; if the encoding is one, the string is a UCS-2 string.

You've already defined binary types representing the four different kinds of strings—two different encodings each with two different methods of delimiting the string. However, define-binary-classprovides no direct facility for determining the type of value to read based on other values in the object. Instead, you can define a binary type that you pass the value of the encoding byte and that then reads or writes the appropriate kind of string.

As long as you're defining such a type, you can also define it to take two parameters, :lengthand :terminator, and pick the right type of string based on which argument is supplied. To implement this new type, you must first define some helper functions. The first two return the name of the appropriate string type based on the encoding byte.

Читать дальше
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать

Похожие книги на «Practical Common Lisp»

Представляем Вашему вниманию похожие книги на «Practical Common Lisp» списком для выбора. Мы отобрали схожую по названию и смыслу литературу в надежде предоставить читателям больше вариантов отыскать новые, интересные, ещё непрочитанные произведения.


Отзывы о книге «Practical Common Lisp»

Обсуждение, отзывы о книге «Practical Common Lisp» и просто собственные мнения читателей. Оставьте ваши комментарии, напишите, что Вы думаете о произведении, его смысле или главных героях. Укажите что конкретно понравилось, а что нет, и почему Вы так считаете.

x