I have tested with this benchmark, find three problem:
Maybe emms-info-native should ignore errors and use message to tell user which file can not be handle properly.
1. if mp3 file can't be readed for control access. info-native will error.
2.
------------------------
Debugger entered--Lisp error: (args-out-of-range "" 0)
bindat--unpack-u8()
bindat--unpack-item(u8 1 nil)
bindat--unpack-item(vec 3 nil)
bindat--unpack-group(((file-identifier vec 3) (eval (unless (equal last emms-info-native--id3v2-magic-array) (error "id3v2 framing mismatch: expected ‘%s’, got ‘%s’" emms-info-native--id3v2-magic-array last))) (version u8) (eval (setq emms-info-native--id3v2-version last)) (revision u8) (flags bits 1) (size-bytes vec 4) (size eval (emms-info-native--checked-id3v2-size 'tag last))))
bindat-unpack(((file-identifier vec 3) (eval (unless (equal last emms-info-native--id3v2-magic-array) (error "id3v2 framing mismatch: expected ‘%s’, got ‘%s’" emms-info-native--id3v2-magic-array last))) (version u8) (eval (setq emms-info-native--id3v2-version last)) (revision u8) (flags bits 1) (size-bytes vec 4) (size eval (emms-info-native--checked-id3v2-size 'tag last))) "")
(progn (set-buffer-multibyte nil) (insert-file-contents-literally filename nil 0 10) (bindat-unpack emms-info-native--id3v2-header-bindat-spec (buffer-string)))
(unwind-protect (progn (set-buffer-multibyte nil) (insert-file-contents-literally filename nil 0 10) (bindat-unpack emms-info-native--id3v2-header-bindat-spec (buffer-string))) (and (buffer-name temp-buffer) (kill-buffer temp-buffer)))
(save-current-buffer (set-buffer temp-buffer) (unwind-protect (progn (set-buffer-multibyte nil) (insert-file-contents-literally filename nil 0 10) (bindat-unpack emms-info-native--id3v2-header-bindat-spec (buffer-string))) (and (buffer-name temp-buffer) (kill-buffer temp-buffer))))
(let ((temp-buffer (generate-new-buffer " *temp*" t))) (save-current-buffer (set-buffer temp-buffer) (unwind-protect (progn (set-buffer-multibyte nil) (insert-file-contents-literally filename nil 0 10) (bindat-unpack emms-info-native--id3v2-header-bindat-spec (buffer-string))) (and (buffer-name temp-buffer) (kill-buffer temp-buffer)))))
emms-info-native--decode-id3v2-header("/home/feng/音乐/李玉刚/逐梦令 四美图/月光.mp3")
(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)) (if (memq 6 (bindat-get-field header 'flags)) (progn (setq offset (+ offset (emms-info-native--decode-id3v2-ext-header-size filename))))) (emms-info-native--decode-id3v2-frames filename offset (+ tag-size 10) unsync))
emms-info-native--decode-id3v2("/home/feng/音乐/李玉刚/逐梦令 四美图/月光.mp3")
(cond ((or (eq stream-type 'vorbis) (eq stream-type 'opus)) (emms-info-native--decode-ogg-comments filename stream-type)) ((eq stream-type 'flac) (emms-info-native--decode-flac-comments filename)) ((eq stream-type 'mp3) (emms-info-native--decode-id3v2 filename)) (t nil))
(let ((stream-type (emms-info-native--find-stream-type filename))) (cond ((or (eq stream-type 'vorbis) (eq stream-type 'opus)) (emms-info-native--decode-ogg-comments filename stream-type)) ((eq stream-type 'flac) (emms-info-native--decode-flac-comments filename)) ((eq stream-type 'mp3) (emms-info-native--decode-id3v2 filename)) (t nil)))
emms-info-native--decode-info-fields("/home/feng/音乐/李玉刚/逐梦令 四美图/月光.mp3")
eval((emms-info-native--decode-info-fields "/home/feng/音乐/李玉刚/逐梦令 四美图/月光.mp3") nil)
elisp--eval-last-sexp(nil)
#f(compiled-function (eval-last-sexp-arg-internal) "Evaluate sexp before point; print value in the echo area.\nInteractively, with a non `-' prefix argument, print output into\ncurrent buffer.\n\nThis commands handles `defvar', `defcustom' and `defface' the\nsame way that `eval-defun' does. See the doc string of that\nfunction for details.\n\nNormally, this function truncates long output according to the\nvalue of the variables `eval-expression-print-length' and\n`eval-expression-print-level'. With a prefix argument of zero,\nhowever, there is no such truncation.\nInteger values are printed in several formats (decimal, octal,\nand hexadecimal). When the prefix argument is -1 or the value\ndoesn't exceed `eval-expression-print-maximum-character', an\ninteger value is also printed as a character of that codepoint.\n\nIf `eval-expression-debug-on-error' is non-nil, which is the default,\nthis command arranges for all errors to enter the debugger." (interactive "P") #<bytecode 0x1d1337931c73bf61>)(nil)
apply(#f(compiled-function (eval-last-sexp-arg-internal) "Evaluate sexp before point; print value in the echo area.\nInteractively, with a non `-' prefix argument, print output into\ncurrent buffer.\n\nThis commands handles `defvar', `defcustom' and `defface' the\nsame way that `eval-defun' does. See the doc string of that\nfunction for details.\n\nNormally, this function truncates long output according to the\nvalue of the variables `eval-expression-print-length' and\n`eval-expression-print-level'. With a prefix argument of zero,\nhowever, there is no such truncation.\nInteger values are printed in several formats (decimal, octal,\nand hexadecimal). When the prefix argument is -1 or the value\ndoesn't exceed `eval-expression-print-maximum-character', an\ninteger value is also printed as a character of that codepoint.\n\nIf `eval-expression-debug-on-error' is non-nil, which is the default,\nthis command arranges for all errors to enter the debugger." (interactive "P") #<bytecode 0x1d1337931c73bf61>) nil)
eval-last-sexp(nil)
funcall-interactively(eval-last-sexp nil)
command-execute(eval-last-sexp)
--------------------------
3.
--------------------------------------------------------------------------------------------------------------------------------------
Debugger entered--Lisp error: (error "id3v2 framing mismatch: expected ‘[73 68 51]’, got...")
error("id3v2 framing mismatch: expected ‘%s’, got ‘%s’" [73 68 51] [255 251 224])
(if (equal last emms-info-native--id3v2-magic-array) nil (error "id3v2 framing mismatch: expected ‘%s’, got ‘%s’" emms-info-native--id3v2-magic-array last))
(unless (equal last emms-info-native--id3v2-magic-array) (error "id3v2 framing mismatch: expected ‘%s’, got ‘%s’" emms-info-native--id3v2-magic-array last))
bindat--unpack-group(((file-identifier vec 3) (eval (unless (equal last emms-info-native--id3v2-magic-array) (error "id3v2 framing mismatch: expected ‘%s’, got ‘%s’" emms-info-native--id3v2-magic-array last))) (version u8) (eval (setq emms-info-native--id3v2-version last)) (revision u8) (flags bits 1) (size-bytes vec 4) (size eval (emms-info-native--checked-id3v2-size 'tag last))))
bindat-unpack(((file-identifier vec 3) (eval (unless (equal last emms-info-native--id3v2-magic-array) (error "id3v2 framing mismatch: expected ‘%s’, got ‘%s’" emms-info-native--id3v2-magic-array last))) (version u8) (eval (setq emms-info-native--id3v2-version last)) (revision u8) (flags bits 1) (size-bytes vec 4) (size eval (emms-info-native--checked-id3v2-size 'tag last))) "\377\373\340\4\0\0\0\0\0\0")
(progn (set-buffer-multibyte nil) (insert-file-contents-literally filename nil 0 10) (bindat-unpack emms-info-native--id3v2-header-bindat-spec (buffer-string)))
(unwind-protect (progn (set-buffer-multibyte nil) (insert-file-contents-literally filename nil 0 10) (bindat-unpack emms-info-native--id3v2-header-bindat-spec (buffer-string))) (and (buffer-name temp-buffer) (kill-buffer temp-buffer)))
(save-current-buffer (set-buffer temp-buffer) (unwind-protect (progn (set-buffer-multibyte nil) (insert-file-contents-literally filename nil 0 10) (bindat-unpack emms-info-native--id3v2-header-bindat-spec (buffer-string))) (and (buffer-name temp-buffer) (kill-buffer temp-buffer))))
(let ((temp-buffer (generate-new-buffer " *temp*" t))) (save-current-buffer (set-buffer temp-buffer) (unwind-protect (progn (set-buffer-multibyte nil) (insert-file-contents-literally filename nil 0 10) (bindat-unpack emms-info-native--id3v2-header-bindat-spec (buffer-string))) (and (buffer-name temp-buffer) (kill-buffer temp-buffer)))))
emms-info-native--decode-id3v2-header("/home/feng/音乐/未整理/Jambalaya (On The Bayou).mp3")
(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)) (if (memq 6 (bindat-get-field header 'flags)) (progn (setq offset (+ offset (emms-info-native--decode-id3v2-ext-header-size filename))))) (emms-info-native--decode-id3v2-frames filename offset (+ tag-size 10) unsync))
emms-info-native--decode-id3v2("/home/feng/音乐/未整理/Jambalaya (On The Bayou).mp3")
(cond ((or (eq stream-type 'vorbis) (eq stream-type 'opus)) (emms-info-native--decode-ogg-comments filename stream-type)) ((eq stream-type 'flac) (emms-info-native--decode-flac-comments filename)) ((eq stream-type 'mp3) (emms-info-native--decode-id3v2 filename)) (t nil))
(let ((stream-type (emms-info-native--find-stream-type filename))) (cond ((or (eq stream-type 'vorbis) (eq stream-type 'opus)) (emms-info-native--decode-ogg-comments filename stream-type)) ((eq stream-type 'flac) (emms-info-native--decode-flac-comments filename)) ((eq stream-type 'mp3) (emms-info-native--decode-id3v2 filename)) (t nil)))
emms-info-native--decode-info-fields("/home/feng/音乐/未整理/Jambalaya (On The Bayou).mp3")
eval((emms-info-native--decode-info-fields "/home/feng/音乐/未整理/Jambalaya (On The Bayou).mp3") nil)
elisp--eval-last-sexp(nil)
#f(compiled-function (eval-last-sexp-arg-internal) "Evaluate sexp before point; print value in the echo area.\nInteractively, with a non `-' prefix argument, print output into\ncurrent buffer.\n\nThis commands handles `defvar', `defcustom' and `defface' the\nsame way that `eval-defun' does. See the doc string of that\nfunction for details.\n\nNormally, this function truncates long output according to the\nvalue of the variables `eval-expression-print-length' and\n`eval-expression-print-level'. With a prefix argument of zero,\nhowever, there is no such truncation.\nInteger values are printed in several formats (decimal, octal,\nand hexadecimal). When the prefix argument is -1 or the value\ndoesn't exceed `eval-expression-print-maximum-character', an\ninteger value is also printed as a character of that codepoint.\n\nIf `eval-expression-debug-on-error' is non-nil, which is the default,\nthis command arranges for all errors to enter the debugger." (interactive "P") #<bytecode 0x1d1337931c73bf61>)(nil)
apply(#f(compiled-function (eval-last-sexp-arg-internal) "Evaluate sexp before point; print value in the echo area.\nInteractively, with a non `-' prefix argument, print output into\ncurrent buffer.\n\nThis commands handles `defvar', `defcustom' and `defface' the\nsame way that `eval-defun' does. See the doc string of that\nfunction for details.\n\nNormally, this function truncates long output according to the\nvalue of the variables `eval-expression-print-length' and\n`eval-expression-print-level'. With a prefix argument of zero,\nhowever, there is no such truncation.\nInteger values are printed in several formats (decimal, octal,\nand hexadecimal). When the prefix argument is -1 or the value\ndoesn't exceed `eval-expression-print-maximum-character', an\ninteger value is also printed as a character of that codepoint.\n\nIf `eval-expression-debug-on-error' is non-nil, which is the default,\nthis command arranges for all errors to enter the debugger." (interactive "P") #<bytecode 0x1d1337931c73bf61>) nil)
eval-last-sexp(nil)
funcall-interactively(eval-last-sexp nil)
command-execute(eval-last-sexp)
-----------------------------------------------------------
At 2021-02-18 05:16:06, "Fran Burstall (Gmail)" <
[hidden email]> wrote:
Hi,
I did
(benchmark-run
(dolist (filename (map-keys emms-cache-db))
(condition-case nil
(emms-info-native--decode-info-fields filename)
(error (message "Error while processing %s" filename)))))
which read tags from 14051 files (mostly mp3 with some flac and ogg) in 710 seconds and only errored out on 75 files. Not too bad!
The errors were of the form
id3v2 tag or frame size 3832965 is invalid
Let me know what more data I can provide to help debug...
---Fran
On Wed, 17 Feb 2021 at 17:31, Petteri Hintsanen <
[hidden email]> wrote:
Yoni Rabkin <
[hidden email]> writes:
> Can you please merge this so that people living with the main branch of
> the git repo can give it a go?
Merged and pushed.
Thanks,
Petteri