fordon_greeman / voidfiles

Branch: 2079ec5
Switch branches/tags
main
theidioticdev add emacs 2079ec5 21h ago
147 lines · 6 KB Raw Blame History
1 ;;; emms-info-native-opus.el --- EMMS Opus info support -*- lexical-binding: t; -*-
2
3 ;; Copyright (C) 2020-2023 Free Software Foundation, Inc.
4
5 ;; Author: Petteri Hintsanen <petterih@iki.fi>
6
7 ;; This file is part of EMMS.
8
9 ;; EMMS is free software; you can redistribute it and/or modify it
10 ;; under the terms of the GNU General Public License as published by
11 ;; the Free Software Foundation; either version 3, or (at your option)
12 ;; any later version.
13
14 ;; EMMS is distributed in the hope that it will be useful, but WITHOUT
15 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16 ;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
17 ;; License for more details.
18
19 ;; You should have received a copy of the GNU General Public License
20 ;; along with EMMS; see the file COPYING. If not, write to the Free
21 ;; Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
22 ;; MA 02110-1301, USA.
23
24 ;;; Commentary:
25
26 ;; This file contains Opus-specific code for `emms-info-native-ogg'
27 ;; feature.
28
29 ;;; Code:
30
31 (require 'emms-info-native-vorbis)
32 (require 'bindat)
33
34 (defvar bindat-raw)
35
36 (defvar emms-info-native-opus--channel-count 0
37 "Last decoded Opus channel count.")
38
39 (defconst emms-info-native-opus--id-magic-pattern "OpusHead"
40 "Opus identification header magic pattern.")
41
42 (defconst emms-info-native-opus--channel-mapping-bindat-spec
43 (if (eval-when-compile (fboundp 'bindat-type))
44 (bindat-type
45 (stream-count u8)
46 (coupled-count u8)
47 (channel-mapping vec emms-info-native-opus--channel-count))
48 '((stream-count u8)
49 (coupled-count u8)
50 (channel-mapping vec (eval emms-info-native-opus--channel-count))))
51 "Opus channel mapping table specification.")
52
53 (defconst emms-info-native-opus--id-header-bindat-spec
54 (if (eval-when-compile (fboundp 'bindat-type))
55 (bindat-type
56 (opus-head str 8)
57 (_ unit (unless (equal opus-head emms-info-native-opus--id-magic-pattern)
58 (error "Opus framing mismatch: expected `%s', got `%s'"
59 emms-info-native-opus--id-magic-pattern
60 opus-head)))
61 (opus-version u8)
62 (_ unit (unless (< opus-version 16)
63 (error "Opus version mismatch: expected < 16, got %s"
64 opus-version)))
65 (channel-count u8)
66 (_ unit (progn (setq emms-info-native-opus--channel-count channel-count) nil))
67 (pre-skip uintr 16)
68 (sample-rate uintr 32)
69 (output-gain uintr 16)
70 (channel-mapping-family u8)
71 (_ . (if (> channel-mapping-family 0)
72 (type emms-info-native-opus--channel-mapping-bindat-spec)
73 (unit nil))))
74 '((opus-head str 8)
75 (eval (unless (equal last emms-info-native-opus--id-magic-pattern)
76 (error "Opus framing mismatch: expected `%s', got `%s'"
77 emms-info-native-opus--id-magic-pattern
78 last)))
79 (opus-version u8)
80 (eval (unless (< last 16)
81 (error "Opus version mismatch: expected < 16, got %s"
82 last)))
83 (channel-count u8)
84 (eval (setq emms-info-native-opus--channel-count last))
85 (pre-skip u16r)
86 (sample-rate u32r)
87 (output-gain u16r)
88 (channel-mapping-family u8)
89 (union (channel-mapping-family)
90 (0 nil)
91 (t (struct emms-info-native-opus--channel-mapping-bindat-spec)))))
92 "Opus identification header specification.")
93
94 (defconst emms-info-native-opus--tags-magic-pattern "OpusTags"
95 "Opus comment header magic pattern.")
96
97 (defconst emms-info-native-opus--comment-header-bindat-spec
98 (if (eval-when-compile (fboundp 'bindat-type))
99 (bindat-type
100 (opus-tags str 8)
101 (_ unit (unless (equal opus-tags emms-info-native-opus--tags-magic-pattern)
102 (error "Opus framing mismatch: expected `%s', got `%s'"
103 emms-info-native-opus--tags-magic-pattern
104 opus-tags)))
105 (vendor-length uintr 32)
106 (_ unit (when (> vendor-length (length bindat-raw))
107 (error "Opus vendor length %s is too long"
108 vendor-length)))
109 (vendor-string str vendor-length)
110 (user-comments-list-length uintr 32)
111 (_ unit (when (> user-comments-list-length (length bindat-raw))
112 (error "Opus user comment list length %s is too long"
113 user-comments-list-length)))
114 (user-comments repeat user-comments-list-length
115 type emms-info-native-vorbis--comment-field-bindat-spec))
116 '((opus-tags str 8)
117 (eval (unless (equal last emms-info-native-opus--tags-magic-pattern)
118 (error "Opus framing mismatch: expected `%s', got `%s'"
119 emms-info-native-opus--tags-magic-pattern
120 last)))
121 (vendor-length u32r)
122 (eval (when (> last (length bindat-raw))
123 (error "Opus vendor length %s is too long" last)))
124 (vendor-string str (vendor-length))
125 (user-comments-list-length u32r)
126 (eval (when (> last (length bindat-raw))
127 (error "Opus user comment list length %s is too long"
128 last)))
129 (user-comments repeat
130 (user-comments-list-length)
131 (struct emms-info-native-vorbis--comment-field-bindat-spec))))
132 "Opus comment header specification.")
133
134 (defconst emms-info-native-opus--headers-bindat-spec
135 (if (eval-when-compile (fboundp 'bindat-type))
136 (bindat-type
137 (identification-header type emms-info-native-opus--id-header-bindat-spec)
138 (comment-header type emms-info-native-opus--comment-header-bindat-spec))
139 '((identification-header struct emms-info-native-opus--id-header-bindat-spec)
140 (comment-header struct emms-info-native-opus--comment-header-bindat-spec)))
141 "Specification for two first Opus header packets.
142 They are always an identification header followed by a comment
143 header.")
144
145 (provide 'emms-info-native-opus)
146
147 ;;; emms-info-native-opus.el ends here