[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/emms 399dd78230 23/42: Use bindat-type in emms-info-ogg
|
From: |
ELPA Syncer |
|
Subject: |
[elpa] externals/emms 399dd78230 23/42: Use bindat-type in emms-info-ogg |
|
Date: |
Wed, 1 Nov 2023 15:58:00 -0400 (EDT) |
branch: externals/emms
commit 399dd782300814c5c70b5039c476cc6f059809f6
Author: Petteri Hintsanen <petterih@iki.fi>
Commit: Petteri Hintsanen <petterih@iki.fi>
Use bindat-type in emms-info-ogg
---
emms-info-ogg.el | 114 +++++++++++++++++++------------------
emms-info-vorbis.el | 9 ++-
emms.el | 22 ++++++++
test/emms-info-ogg-tests.el | 134 ++++++++++++++++++++++----------------------
4 files changed, 155 insertions(+), 124 deletions(-)
diff --git a/emms-info-ogg.el b/emms-info-ogg.el
index c0d3645a23..1c25a16d2d 100644
--- a/emms-info-ogg.el
+++ b/emms-info-ogg.el
@@ -39,10 +39,10 @@
;;; Code:
-(require 'bindat)
(require 'emms)
(require 'emms-info-opus)
(require 'emms-info-vorbis)
+(require 'bindat)
(defconst emms-info-ogg--page-size 65307
"Maximum size for a single Ogg container page.")
@@ -59,29 +59,50 @@ Technically metadata blocks can have almost arbitrary
lengths,
but in practice processing must be constrained to prevent memory
exhaustion in case of garbled or malicious inputs.")
+(defconst emms-info-ogg--magic-pattern "OggS"
+ "Ogg format magic capture pattern.")
+
(defconst emms-info-ogg--page-bindat-spec
- '((capture-pattern vec 4)
- (eval (unless (equal last emms-info-ogg--magic-pattern)
- (error "Ogg framing mismatch: expected `%s', got `%s'"
- emms-info-ogg--magic-pattern
- last)))
- (stream-structure-version u8)
- (eval (unless (= last 0)
- (error "Ogg version mismatch: expected 0, got %s" last)))
- (header-type-flag u8)
- (granule-position vec 8)
- (stream-serial-number u32r)
- (page-sequence-no u32r)
- (page-checksum u32r)
- (page-segments u8)
- (segment-table vec (page-segments))
- (payload str (eval (seq-reduce #'+ last 0))))
+ (if emms--use-bindat-type
+ (bindat-type
+ (capture-pattern str 4)
+ (_ unit (unless (equal capture-pattern emms-info-ogg--magic-pattern)
+ (error "Ogg framing mismatch: expected `%s', got `%s'"
+ emms-info-ogg--magic-pattern
+ capture-pattern)))
+ (stream-structure-version u8)
+ (_ unit (unless (= stream-structure-version 0)
+ (error "Ogg version mismatch: expected 0, got %d"
+ stream-structure-version)))
+ (header-type-flag u8)
+ (granule-position sint 64 'le)
+ (stream-serial-number uint 32 'le)
+ (page-sequence-no uint 32 'le)
+ (page-checksum uint 32 'le)
+ (page-segments u8)
+ (segment-table vec page-segments)
+ (payload str (seq-reduce #'+ segment-table 0)))
+ ;; For Emacsen older than 28
+ '((capture-pattern str 4)
+ (eval (unless (equal last emms-info-ogg--magic-pattern)
+ (error "Ogg framing mismatch: expected `%s', got `%s'"
+ emms-info-ogg--magic-pattern
+ last)))
+ (stream-structure-version u8)
+ (eval (unless (= last 0)
+ (error "Ogg version mismatch: expected 0, got %s" last)))
+ (header-type-flag u8)
+ (granule-position-bytes vec 8)
+ (granule-position eval (emms-from-twos-complement
+ (emms-le-to-int last) 64))
+ (stream-serial-number u32r)
+ (page-sequence-no u32r)
+ (page-checksum u32r)
+ (page-segments u8)
+ (segment-table vec (page-segments))
+ (payload str (eval (seq-reduce #'+ last 0)))))
"Ogg page structure specification.")
-(defconst emms-info-ogg--magic-pattern
- (string-to-vector "OggS")
- "Ogg format magic capture pattern.")
-
(defconst emms-info-ogg--crc-table
[#x00000000 #x04C11DB7 #x09823B6E #x0D4326D9 #x130476DC
#x17C56B6B #x1A864DB2 #x1E475005 #x2608EDB8 #x22C9F00F
@@ -152,22 +173,23 @@ See `emms-info-vorbis--split-comment' for details."
(emms-info-ogg--decode-headers packets stream-type))
(user-comments
(bindat-get-field headers 'comment-header 'user-comments))
+ (comments
+ (emms-info-vorbis-extract-comments user-comments))
(last-page
(emms-info-ogg--read-and-decode-last-page filename))
(granule-pos
(alist-get 'granule-position last-page))
+ (sample-rate
+ (if (eq stream-type 'vorbis)
+ (bindat-get-field headers
+ 'identification-header
+ 'sample-rate)
+ ;; Opus assumes a fixed sample rate of 48 kHz for granule
+ ;; position.
+ 48000))
(playing-time
- (emms-info-ogg--decode-granule-pos
- granule-pos
- (if (eq stream-type 'vorbis)
- (bindat-get-field headers
- 'identification-header
- 'sample-rate)
- ;; Opus assumes a fixed sample rate of 48 kHz for granule
- ;; position.
- 48000)))
- (comments
- (emms-info-vorbis-extract-comments user-comments)))
+ (when (and granule-pos (> granule-pos 0))
+ (/ granule-pos sample-rate))))
(nconc comments
(when playing-time
(list (cons "playing-time" playing-time))))))
@@ -198,7 +220,7 @@ different streams will be mixed together without an error."
(bindat-length
emms-info-ogg--page-bindat-spec page)))
(push (bindat-get-field page 'payload) stream)))
- (reverse (mapconcat #'nreverse stream))))
+ (reverse (mapconcat #'nreverse stream nil))))
(defun emms-info-ogg--read-and-decode-page (filename offset)
"Read and decode a single Ogg page from FILENAME.
@@ -231,16 +253,17 @@ Return a structure that corresponds to either
(bindat-unpack emms-info-vorbis--headers-bindat-spec
packets))
((eq stream-type 'opus)
- (let (emms-info-opus--channel-count)
- (bindat-unpack emms-info-opus--headers-bindat-spec
- packets)))
+ (bindat-unpack emms-info-opus--headers-bindat-spec
+ packets))
(t (error "Unknown stream type %s" stream-type))))
(defun emms-info-ogg--read-and-decode-last-page (filename)
"Read and decode the last Ogg page from FILENAME.
Return the page in bindat type structure."
(with-temp-buffer
- (let* ((length (file-attribute-size (file-attributes filename)))
+ (let* ((length (file-attribute-size
+ (file-attributes
+ (file-truename filename))))
(begin (max 0 (- length emms-info-ogg--page-size))))
(set-buffer-multibyte nil)
(insert-file-contents-literally filename nil begin length)
@@ -255,8 +278,7 @@ Ogg page in the buffer, return nil."
(let (page)
(goto-char (point-max))
(while (and (not page)
- (search-backward
- (concat emms-info-ogg--magic-pattern) nil t))
+ (search-backward emms-info-ogg--magic-pattern nil t))
(setq page (emms-info-ogg--verify-page)))
(when (and page
(> (logand (alist-get 'header-type-flag page) #x04) 0))
@@ -297,20 +319,6 @@ checksum."
(aref bytes n))))))
crc))
-(defun emms-info-ogg--decode-granule-pos (vec rate)
- "Decode Ogg granule position vector VEC for sampling rate RATE.
-Granule position is 64-bit little-endian signed integer counting
-the number of passed PCM samples per channel at the end of a
-packet. For a partial packet granule position is -1 and hence
-invalid.
-
-Return the granule position in seconds, or nil if VEC is nil or
-from a partial packet."
- (when vec
- (let* ((int (emms-le-to-int vec))
- (pos (emms-from-twos-complement int 64)))
- (unless (= pos -1) (/ pos rate)))))
-
(provide 'emms-info-ogg)
;;; emms-info-ogg.el ends here
diff --git a/emms-info-vorbis.el b/emms-info-vorbis.el
index a782c8ea0a..e41f8c0e57 100644
--- a/emms-info-vorbis.el
+++ b/emms-info-vorbis.el
@@ -88,7 +88,7 @@ header.")
(eval (unless (= last 1)
(error "Vorbis header type mismatch: expected 1, got %s"
last)))
- (vorbis vec 6)
+ (vorbis str 6)
(eval (unless (equal last emms-info-vorbis--header-magic-pattern)
(error "Vorbis framing mismatch: expected `%s', got `%s'"
emms-info-vorbis--header-magic-pattern
@@ -109,8 +109,7 @@ header.")
last)))
"Vorbis identification header specification.")
-(defconst emms-info-vorbis--header-magic-pattern
- (string-to-vector "vorbis")
+(defconst emms-info-vorbis--header-magic-pattern "vorbis"
"Header packet magic pattern.")
(defconst emms-info-vorbis--comment-header-bindat-spec
@@ -118,7 +117,7 @@ header.")
(eval (unless (= last 3)
(error "Vorbis header type mismatch: expected 3, got %s"
last)))
- (vorbis vec 6)
+ (vorbis str 6)
(eval (unless (equal last emms-info-vorbis--header-magic-pattern)
(error "Vorbis framing mismatch: expected `%s', got `%s'"
emms-info-vorbis--header-magic-pattern
@@ -126,7 +125,7 @@ header.")
(vendor-length u32r)
(eval (when (> last emms-info-vorbis--max-vendor-length)
(error "Vorbis vendor length %s is too long" last)))
- (vendor-string vec (vendor-length))
+ (vendor-string str (vendor-length))
(user-comments-list-length u32r)
(eval (when (> last emms-info-vorbis--max-comments)
(error "Vorbis user comment list length %s is too long"
diff --git a/emms.el b/emms.el
index 67e1f4dc1c..e0cbba3c0b 100644
--- a/emms.el
+++ b/emms.el
@@ -45,6 +45,10 @@
;;; Code:
(require 'emms-compat)
+(defvar emms--use-bindat-type
+ (eval-when-compile (fboundp 'bindat-type))
+"Use bindat-type macro.")
+
(defvar emms-version "16"
"EMMS version string.")
@@ -1379,6 +1383,24 @@ by FROM positions."
(mask (1- (expt 2 (1+ to)))))
(when (> num-bits 0) (ash (logand int mask) (- from)))))
+(defun emms-equal-lists (x y)
+ "Compare two lists X and Y for equality.
+List elements can be in any order, and Y can have more elements
+than X.
+
+This is a special helper function for tests. It is not meant for
+general use."
+ (cond ((and (not (proper-list-p x))
+ (not (proper-list-p y)))
+ (equal x y))
+ ((and (proper-list-p x)
+ (proper-list-p y))
+ (seq-every-p (lambda (elt-x)
+ (seq-find (lambda (elt-y)
+ (emms-equal-lists elt-x elt-y))
+ y))
+ x))))
+
;;; ------------------------------------------------------------------
;;; Sources
;;; ------------------------------------------------------------------
diff --git a/test/emms-info-ogg-tests.el b/test/emms-info-ogg-tests.el
index d7d1c1bd9e..0f51efeb92 100644
--- a/test/emms-info-ogg-tests.el
+++ b/test/emms-info-ogg-tests.el
@@ -27,7 +27,7 @@
(require 'ert)
(ert-deftest emms-ogg-test-decode-page ()
- (let* ((bytes [79 103 103 83 0 2 0 0 0 0 0 0 0 0 134 209 158 23 0 0 0 0 53
82 251 136 1 30 1 118 111 114 98 105 115 0 0 0 0 1 68 172 0 0 0 0 0 0 128 56 1
0 0 0 0 0 184 1])
+ (let* ((bytes (unibyte-string 79 103 103 83 0 2 0 0 0 0 0 0 0 0 134 209 158
23 0 0 0 0 53 82 251 136 1 30 1 118 111 114 98 105 115 0 0 0 0 1 68 172 0 0 0 0
0 0 128 56 1 0 0 0 0 0 184 1))
(page (bindat-unpack emms-info-ogg--page-bindat-spec bytes)))
(should (= (emms-info-ogg--num-packets page) 1))
(should (= (bindat-length emms-info-ogg--page-bindat-spec page) 58))
@@ -36,56 +36,59 @@
(ert-deftest emms-ogg-test-decode-vorbis-headers ()
"Test `emms-info-ogg--decode-headers' with Vorbis data."
- (let ((bytes [1 118 111 114 98 105 115 0 0 0 0 1 68 172 0 0 0 0 0 0 128 56 1
0 0 0 0 0 184 1 3 118 111 114 98 105 115 52 0 0 0 88 105 112 104 46 79 114 103
32 108 105 98 86 111 114 98 105 115 32 73 32 50 48 50 48 48 55 48 52 32 40 82
101 100 117 99 105 110 103 32 69 110 118 105 114 111 110 109 101 110 116 41 2 0
0 0 7 0 0 0 102 111 111 61 98 97 114 27 0 0 0 75 101 121 61 206 159 225 189 144
207 135 225 189 182 32 206 164 206 177 225 189 144 207 132 225 189 176 1]))
- (should (equal (emms-info-ogg--decode-headers bytes 'vorbis)
- `((comment-header
- (framing-bit . 1)
- (user-comments
- ((user-comment . ,(unibyte-string 102 111 111 61 98 97
114))
- (length . 7))
- ((user-comment . ,(unibyte-string 75 101 121 61 206 159
225 189 144 207 135 225 189 182 32 206 164 206 177 225 189 144 207 132 225 189
176))
- (length . 27)))
- (user-comments-list-length . 2)
- (vendor-string . [88 105 112 104 46 79 114 103 32 108
105 98 86 111 114 98 105 115 32 73 32 50 48 50 48 48 55 48 52 32 40 82 101 100
117 99 105 110 103 32 69 110 118 105 114 111 110 109 101 110 116 41])
- (vendor-length . 52)
- (vorbis . [118 111 114 98 105 115])
- (packet-type . 3))
- (identification-header
- (framing-flag . 1)
- (blocksize . 184)
- (bitrate-minimum . 0)
- (bitrate-nominal . 80000)
- (bitrate-maximum . 0)
- (sample-rate . 44100)
- (channel-count . 1)
- (vorbis-version . 0)
- (vorbis . [118 111 114 98 105 115])
- (packet-type . 1)))))))
+ (let ((bytes (unibyte-string 1 118 111 114 98 105 115 0 0 0 0 1 68 172 0 0 0
0 0 0 128 56 1 0 0 0 0 0 184 1 3 118 111 114 98 105 115 52 0 0 0 88 105 112 104
46 79 114 103 32 108 105 98 86 111 114 98 105 115 32 73 32 50 48 50 48 48 55 48
52 32 40 82 101 100 117 99 105 110 103 32 69 110 118 105 114 111 110 109 101
110 116 41 2 0 0 0 7 0 0 0 102 111 111 61 98 97 114 27 0 0 0 75 101 121 61 206
159 225 189 144 207 135 225 189 182 32 206 164 206 177 225 189 144 207 132 225
189 176 1)))
+ (should
+ (emms-equal-lists
+ (emms-info-ogg--decode-headers bytes 'vorbis)
+ '((identification-header
+ (packet-type . 1)
+ (vorbis . "vorbis")
+ (vorbis-version . 0)
+ (channel-count . 1)
+ (sample-rate . 44100)
+ (bitrate-maximum . 0)
+ (bitrate-nominal . 80000)
+ (bitrate-minimum . 0)
+ (blocksize . 184)
+ (framing-flag . 1))
+ (comment-header
+ (packet-type . 3)
+ (vorbis . "vorbis")
+ (vendor-length . 52)
+ (vendor-string . "Xiph.Org libVorbis I 20200704 (Reducing
Environment)")
+ (user-comments-list-length . 2)
+ (user-comments
+ ((length . 7)
+ (user-comment . "foo=bar"))
+ ((length . 27)
+ (user-comment . "Key=\316\237\341\275\220\317\207\341\275\266
\316\244\316\261\341\275\220\317\204\341\275\260")))
+ (framing-bit . 1)))))))
(ert-deftest emms-ogg-test-decode-opus-headers ()
"Test `emms-info-ogg--decode-headers' with Opus data."
- (let ((bytes [79 112 117 115 72 101 97 100 1 1 56 1 68 172 0 0 0 0 0 79 112
117 115 84 97 103 115 13 0 0 0 108 105 98 111 112 117 115 32 49 46 51 46 49 3 0
0 0 38 0 0 0 69 78 67 79 68 69 82 61 111 112 117 115 101 110 99 32 102 114 111
109 32 111 112 117 115 45 116 111 111 108 115 32 48 46 49 46 49 48 7 0 0 0 102
111 111 61 98 97 114 27 0 0 0 75 101 121 61 206 159 225 189 144 207 135 225 189
182 32 206 164 206 177 225 189 144 207 132 225 189 176]))
- (should (equal (emms-info-ogg--decode-headers bytes 'opus)
- `((comment-header
- (user-comments
- ((user-comment . ,(unibyte-string 69 78 67 79 68 69 82
61 111 112 117 115 101 110 99 32 102 114 111 109 32 111 112 117 115 45 116 111
111 108 115 32 48 46 49 46 49 48))
- (length . 38))
- ((user-comment . ,(unibyte-string 102 111 111 61 98 97
114))
- (length . 7))
- ((user-comment . ,(unibyte-string 75 101 121 61 206 159
225 189 144 207 135 225 189 182 32 206 164 206 177 225 189 144 207 132 225 189
176))
- (length . 27)))
- (user-comments-list-length . 3)
- (vendor-string . [108 105 98 111 112 117 115 32 49 46 51
46 49])
- (vendor-length . 13)
- (opus-tags . [79 112 117 115 84 97 103 115]))
- (identification-header
- (channel-mapping-family . 0)
- (output-gain . 0)
- (sample-rate . 44100)
- (pre-skip . 312)
- (channel-count . 1)
- (opus-version . 1)
- (opus-head . [79 112 117 115 72 101 97 100])))))))
+ (let ((bytes (unibyte-string 79 112 117 115 72 101 97 100 1 1 56 1 68 172 0
0 0 0 0 79 112 117 115 84 97 103 115 13 0 0 0 108 105 98 111 112 117 115 32 49
46 51 46 49 3 0 0 0 38 0 0 0 69 78 67 79 68 69 82 61 111 112 117 115 101 110 99
32 102 114 111 109 32 111 112 117 115 45 116 111 111 108 115 32 48 46 49 46 49
48 7 0 0 0 102 111 111 61 98 97 114 27 0 0 0 75 101 121 61 206 159 225 189 144
207 135 225 189 182 32 206 164 206 177 225 189 144 207 132 225 189 176)))
+ (emms-equal-lists
+ (emms-info-ogg--decode-headers bytes 'opus)
+ '((identification-header
+ (opus-head . "OpusHead")
+ (opus-version . 1)
+ (channel-count . 1)
+ (pre-skip . 312)
+ (sample-rate . 44100)
+ (output-gain . 0)
+ (channel-mapping-family . 0))
+ (comment-header
+ (opus-tags . "OpusTags")
+ (vendor-length . 13)
+ (vendor-string . "libopus 1.3.1")
+ (user-comments-list-length . 3)
+ (user-comments
+ ((length . 38)
+ (user-comment . "ENCODER=opusenc from opus-tools 0.1.10"))
+ ((length . 7)
+ (user-comment . "foo=bar"))
+ ((length . 27)
+ (user-comment . "Key=\316\237\341\275\220\317\207\341\275\266
\316\244\316\261\341\275\220\317\204\341\275\260"))))))))
(defun emms-ogg-test--decode-last-page (bytes)
"Call `emms-info-ogg--decode-last-page' with BYTES input.
@@ -99,18 +102,23 @@ This is a helper function for
`emms-ogg-test-decode-last-page'."
(ert-deftest emms-ogg-test-decode-last-page()
(let ((valid [#x01 #x02 #x03 #x04 #x4f #x67 #x67 #x53 #x00 #x04 #x00 #x24
#x08 #x01 #x00 #x00 #x00 #x00 #x9c #x39 #x6e #x47 #x40 #x08 #x00 #x00 #x19 #x4e
#xac #xa3 #x01 #x0a #x4f #x67 #x67 #x53 #x31 #x32 #x33 #x34 #x35 #x36])
(notlast [#x01 #x02 #x03 #x04 #x4f #x67 #x67 #x53 #x00 #x00 #x00 #x24
#x08 #x01 #x00 #x00 #x00 #x00 #x9c #x39 #x6e #x47 #x40 #x08 #x00 #x00 #x19 #x4e
#xac #xa3 #x01 #x0a #x4f #x67 #x67 #x53 #x31 #x32 #x33 #x34 #x35 #x36])
- (invalid [#x01 #x02 #x03 #x04 #x4f #x67 #x67 #x53 #x00 #x04 #x00 #x24
#x08 #x01 #x00 #x00 #x00 #x00 #x9c #x39 #x6e #x47 #x40 #x08 #x00 #x00 #x01 #x02
#x03 #x04 #x01 #x0a #x4f #x67 #x67 #x53 #x31 #x32 #x33 #x34 #x35 #x36]))
- (should (equal (emms-ogg-test--decode-last-page valid)
- '((payload . "OggS123456")
- (segment-table . [10])
- (page-segments . 1)
- (page-checksum . 2745978393)
- (page-sequence-no . 2112)
- (stream-serial-number . 1198406044)
- (granule-position . [0 36 8 1 0 0 0 0])
- (header-type-flag . 4)
- (stream-structure-version . 0)
- (capture-pattern . [79 103 103 83]))))
+ (invalid [#x01 #x02 #x03 #x04 #x4f #x67 #x67 #x53 #x00 #x04 #x00 #x24
#x08 #x01 #x00 #x00 #x00 #x00 #x9c #x39 #x6e #x47 #x40 #x08 #x00 #x00 #x01 #x02
#x03 #x04 #x01 #x0a #x4f #x67 #x67 #x53 #x31 #x32 #x33 #x34 #x35 #x36])
+ (valid-result
+ (quote
+ ((capture-pattern . "OggS")
+ (stream-structure-version . 0)
+ (header-type-flag . 4)
+ (granule-position . 17310720)
+ (stream-serial-number . 1198406044)
+ (page-sequence-no . 2112)
+ (page-checksum . 2745978393)
+ (page-segments . 1)
+ (segment-table . [10])
+ (payload . "OggS123456")))))
+ (unless emms--use-bindat-type
+ (push (cons 'granule-position-bytes [0 36 8 1 0 0 0 0]) valid-result))
+ (should (emms-equal-lists (emms-ogg-test--decode-last-page valid)
+ valid-result))
(should (equal (emms-ogg-test--decode-last-page notlast) nil))
(should (equal (emms-ogg-test--decode-last-page invalid) nil))))
@@ -118,12 +126,6 @@ This is a helper function for
`emms-ogg-test-decode-last-page'."
(let ((bytes [#x01 #x02 #x03 #x04 #x4f #x67 #x67 #x53 #x00 #x04 #x00 #x24
#x08 #x01 #x00 #x00 #x00 #x00 #x9c #x39 #x6e #x47 #x40 #x08 #x00 #x00 #x19 #x4e
#xac #xa3 #x01 #x0a #x4f #x67 #x67 #x53 #x31 #x32 #x33 #x34 #x35 #x36]))
(should (= (emms-info-ogg--checksum bytes) 445885580))))
-(ert-deftest emms-ogg-test-decode-granule-position ()
- (should (= (emms-info-ogg--decode-granule-pos [0 36 8 1 0 0 0 0] 44100) 392))
- (should (= (emms-info-ogg--decode-granule-pos [40 236 178 11 0 0 0 0] 48000)
4089))
- (should (equal (emms-info-ogg--decode-granule-pos [255 255 255 255 255 255
255 255] nil) nil))
- (should (equal (emms-info-ogg--decode-granule-pos nil nil) nil)))
-
(provide 'emms-info-ogg-tests)
;;; emms-info-ogg-tests.el ends here
- [elpa] externals/emms 9d71a515f7 09/42: Split emms-info-native to several files, (continued)
- [elpa] externals/emms 9d71a515f7 09/42: Split emms-info-native to several files, ELPA Syncer, 2023/11/01
- [elpa] externals/emms 29260a991a 11/42: Replace emms-info-native test files, ELPA Syncer, 2023/11/01
- [elpa] externals/emms fe9b0fffe1 16/42: Use strings instead of vectors for Vorbis comments, ELPA Syncer, 2023/11/01
- [elpa] externals/emms 75f1ee292e 20/42: Add copyright information, ELPA Syncer, 2023/11/01
- [elpa] externals/emms 5014dfa5f3 21/42: Ignore empty tags, ELPA Syncer, 2023/11/01
- [elpa] externals/emms 16f107b583 24/42: Use bindat-type in emms-info-vorbis, ELPA Syncer, 2023/11/01
- [elpa] externals/emms 6c3f1d6ab2 25/42: Use bindat-type in emms-info-opus, ELPA Syncer, 2023/11/01
- [elpa] externals/emms 59e999a259 05/42: Fix error reporting from emms-info-native--ogg-page-bindat-spec, ELPA Syncer, 2023/11/01
- [elpa] externals/emms b512ed7331 03/42: Change magic arrays to patterns, ELPA Syncer, 2023/11/01
- [elpa] externals/emms 5a52c1b129 22/42: Remove dependency on cl-lib, ELPA Syncer, 2023/11/01
- [elpa] externals/emms 399dd78230 23/42: Use bindat-type in emms-info-ogg,
ELPA Syncer <=
- [elpa] externals/emms e18b579e31 27/42: Use bindat-type in emms-info-mp3, ELPA Syncer, 2023/11/01
- [elpa] externals/emms f6bd021bc9 29/42: Compatibility code ert-resource-file, ELPA Syncer, 2023/11/01
- [elpa] externals/emms 9db19a5abd 31/42: Remove emms--use-bindat-type, ELPA Syncer, 2023/11/01
- [elpa] externals/emms c848c18727 33/42: Change to emms-info-native- prefix, ELPA Syncer, 2023/11/01
- [elpa] externals/emms 342c44103a 35/42: Fix multi-channel mapping in Opus identification header, ELPA Syncer, 2023/11/01
- [elpa] externals/emms b3c2f9cf09 39/42: Use uintr for little-endian unsigned integer fields, ELPA Syncer, 2023/11/01
- [elpa] externals/emms c96afb7687 40/42: Use eval-when-compile with subr-x, ELPA Syncer, 2023/11/01
- [elpa] externals/emms 2852a8f61b 10/42: Add tests for emms-info-native, ELPA Syncer, 2023/11/01
- [elpa] externals/emms e1f2810f39 13/42: Use string instead of vector as Ogg page payload type, ELPA Syncer, 2023/11/01
- [elpa] externals/emms dd72caba90 37/42: Doc fixes, ELPA Syncer, 2023/11/01