diff options
-rw-r--r-- | emms-info-native.el | 92 |
1 files changed, 51 insertions, 41 deletions
diff --git a/emms-info-native.el b/emms-info-native.el index ab5b6c0..039738c 100644 --- a/emms-info-native.el +++ b/emms-info-native.el @@ -564,20 +564,26 @@ outside itself.") (defun emms-info-native--decode-id3v2 (filename) "Read and decode id3v2 metadata from FILENAME. -Return metadata in a list of (FIELD . VALUE) cons cells." - (let* (emms-info-native--id3v2-version - (header (emms-info-native--decode-id3v2-header filename)) - (tag-size (bindat-get-field header 'size)) - (unsync (memq 7 (bindat-get-field header 'flags))) - (offset 10)) - (when (memq 6 (bindat-get-field header 'flags)) - ;; Skip the extended header. - (cl-incf offset - (emms-info-native--decode-id3v2-ext-header-size filename))) - (emms-info-native--decode-id3v2-frames filename - offset - (+ tag-size 10) - unsync))) +Return metadata in a list of (FIELD . VALUE) cons cells, or nil +in case of errors or if there were no known fields in FILENAME. + +See ‘emms-info-native--id3v2-frame-to-info’ for recognized +fields." + (condition-case-unless-debug nil + (let* (emms-info-native--id3v2-version + (header (emms-info-native--decode-id3v2-header filename)) + (tag-size (bindat-get-field header 'size)) + (unsync (memq 7 (bindat-get-field header 'flags))) + (offset 10)) + (when (memq 6 (bindat-get-field header 'flags)) + ;; Skip the extended header. + (cl-incf offset + (emms-info-native--decode-id3v2-ext-header-size filename))) + (emms-info-native--decode-id3v2-frames filename + offset + (+ tag-size 10) + unsync)) + (error nil))) (defun emms-info-native--decode-id3v2-header (filename) "Read and decode id3v2 header from FILENAME." @@ -594,7 +600,7 @@ Return the size. Signal an error if the size exceeds (with-temp-buffer (set-buffer-multibyte nil) (insert-file-contents-literally filename nil 10 14) - (emms-info-native--checked-id3v2-size (buffer-string)))) + (emms-info-native--checked-id3v2-size 'frame (buffer-string)))) (defun emms-info-native--checked-id3v2-size (elt bytes) "Calculate id3v2 element ELT size from BYTES. @@ -607,7 +613,7 @@ Return the size." (if (= emms-info-native--id3v2-version 4) (setq size (emms-info-native--decode-id3v2-size bytes t)) (setq size (emms-info-native--decode-id3v2-size bytes nil))))) - (when (or (= size 0) (> size emms-info-native--max-peek-size)) + (when (> size emms-info-native--max-peek-size) (error "id3v2 tag or frame size %s is invalid" size)) size)) @@ -633,30 +639,34 @@ unsynchronization and decoded as such. Return metadata in a list of (FIELD . VALUE) cons cells." (let ((offset begin) + (limit (- end (emms-info-native--id3v2-frame-header-size))) comments) - (condition-case nil - (while (< offset end) - (let* ((header (emms-info-native--decode-id3v2-frame-header filename - offset)) - (info-id (emms-info-native--id3v2-frame-info-id header)) - (decoded-size (bindat-get-field (cdr header) 'size))) - (setq offset (car header)) ;advance to frame data begin - (if (or unsync info-id) - ;; Note that if unsync is t, we have to always read a - ;; frame to gets its true size so that we can adjust - ;; offset correctly. - (let ((data (emms-info-native--read-id3v2-frame-data filename - offset - decoded-size - unsync))) - (setq offset (car data)) - (when info-id - (let ((value (emms-info-native--decode-id3v2-string (cdr data)))) - (push (cons info-id value) comments)))) - ;; Skip the frame. - (cl-incf offset decoded-size)))) - (error nil)) - comments)) + (catch 'eof + (while (< offset limit) + (let* ((header (emms-info-native--decode-id3v2-frame-header filename + offset)) + (info-id (emms-info-native--id3v2-frame-info-id header)) + (decoded-size (bindat-get-field (cdr header) 'size))) + (when (= decoded-size 0) (throw 'eof t)) + (setq offset (car header)) ;advance to frame data begin + (if (or unsync info-id) + ;; Note that if unsync is t, we have to always read a + ;; frame to gets its true size so that we can adjust + ;; offset correctly. + (let ((data (emms-info-native--read-id3v2-frame-data filename + offset + decoded-size + unsync))) + (setq offset (car data)) + (when info-id + (let ((value (emms-info-native--decode-id3v2-string (cdr data)))) + (push (cons info-id value) comments)))) + ;; Skip the frame. + (cl-incf offset decoded-size))))) + comments)) + +(defun emms-info-native--id3v2-frame-header-size () + (if (= emms-info-native--id3v2-version 2) 6 10)) (defun emms-info-native--decode-id3v2-frame-header (filename begin) "Read and decode id3v2 frame header from FILENAME. @@ -666,7 +676,7 @@ Return a cons cell (OFFSET . FRAME), where OFFSET is the byte offset after the frame header, and FRAME is the decoded frame." (with-temp-buffer (set-buffer-multibyte nil) - (let ((end (+ begin (if (= emms-info-native--id3v2-version 2) 6 10)))) + (let ((end (+ begin (emms-info-native--id3v2-frame-header-size)))) (insert-file-contents-literally filename nil begin end) (cons end (bindat-unpack emms-info-native--id3v2-frame-header-bindat-spec (buffer-string)))))) @@ -690,7 +700,7 @@ data." (let ((peek-end (+ begin (* 2 num-bytes))) (end num-bytes)) (insert-file-contents-literally filename nil begin peek-end) - (beginning-of-buffer) + (goto-char (point-min)) (while (and (re-search-forward (string 255 0) nil t) (< (point) end)) (replace-match (string 255)) |