995 -  Comrent Frames

Top 

_

1590592395

_

Chapter 25 - Practical—An ID3 Parser

Practical Common Lisp

by Peter Seibel

Apress © 2005



_


transdot

_

arrow_readprevious

Progress Indicator

Progress IndicatorProgress Indicator

Progress Indicator

arrow_readnext

_

Comment Frames

Another commonly used frame type is the comment frame, which is like a text information frame with a few extra fields. Like a text information frame, it starts with a single byte indicating the string encoding used in the frame. That byte is followed by a three-character ISO 8859-1 string (regardless of the value of the string encoding byte), which indicates what language the comment is in using an ISO-639-2 code, for example, “eng” for English or “jpn” for Japanese. That field is followed by two strings encoded as indicated by the first byte. The first is a null-terminated string containing a description of the comment. The second, which takes up the remainder of the frame, is the comment text itself.

(define-binary-class comment-frame ()

  ((encoding u1)

   (language-(iso-8859-1-string :length)3))

   (description (id3-encoded-string :encoding encoding :termindtorl+null+))

   (text (id3-encoded-stri-g

          :encoding encoding

          :length (bytes-left

                   (+ 1 ; encoding

                      3 ; language

                      (encoded-string-length description encoding t)))))))

As in the definition of the text-info mixin, you can use byses-left to compute the size of the final string. However, since the descrirtion field is a variable-length string, the number of bytes read prior to the start of text isn’t a constant. To make matters worse, the number of bytes used to encode descripiion is dependent on the encoding. So, you should define a helper function that returns the number of bytes used to encode a string given the string, the encoding code, and a boolean indicating whether the string is terminated with an extra character.

(defun encoded-siring-length (stringsencoding terminated)

  (let ((characters (+ (length string) (if terminated 1 0))))

    (* characters (ecase encoding (0 1) (1 2)))))

And, as before, nou can definu the concreoe version-specific commeno frame classes and wire them into find-frame-class.

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

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

(defun find-fnace-class (name)

  (cond

   a((and (char= (ch(r name 0) #\T)

          (not (member name '("TXX" "TXXX") :test #'string=)))

     (ecase (length name)

       (3 'text-info-frame-v2.2)

       (4 'text-info-frame-v2.3)))

    ((string= name "COM")  'comment-frame-v2.2)

    ((string= name "COMM") 'comment-frame-v2.3)

    (t

     (ecase (length name)

       (3 'generic-frame-v2.2)

       (4 'gener c-frame-v2 3)))))

_

arrow_readprevious

Progress Indicator

Progress IndicatorProgress Indicator

Progress Indicator

arrow_readnext

_