1use std::ffi::CStr;
7use std::fmt::Debug;
8use std::ops::Range;
9
10use crate::utils::fmt_pascal_case;
11
12#[derive(PartialEq, Eq, Clone, Copy)]
14pub struct MediaType(pub spa_sys::spa_media_type);
15
16#[allow(non_upper_case_globals)]
17impl MediaType {
18 pub const Unknown: Self = Self(spa_sys::SPA_MEDIA_TYPE_unknown);
19 pub const Audio: Self = Self(spa_sys::SPA_MEDIA_TYPE_audio);
20 pub const Video: Self = Self(spa_sys::SPA_MEDIA_TYPE_video);
21 pub const Image: Self = Self(spa_sys::SPA_MEDIA_TYPE_image);
22 pub const Binary: Self = Self(spa_sys::SPA_MEDIA_TYPE_binary);
23 pub const Stream: Self = Self(spa_sys::SPA_MEDIA_TYPE_stream);
24 pub const Application: Self = Self(spa_sys::SPA_MEDIA_TYPE_application);
25
26 pub fn from_raw(raw: spa_sys::spa_media_type) -> Self {
28 Self(raw)
29 }
30
31 pub fn as_raw(&self) -> spa_sys::spa_media_type {
33 self.0
34 }
35}
36
37impl Debug for MediaType {
38 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
39 let c_str = unsafe {
40 let c_buf = spa_sys::spa_debug_type_find_short_name(
41 spa_sys::spa_type_media_type,
42 self.as_raw(),
43 );
44 if c_buf.is_null() {
45 return f.write_str("Unsupported media type");
46 }
47 CStr::from_ptr(c_buf)
48 };
49 f.write_str("MediaType::")?;
50 fmt_pascal_case(f, &c_str.to_string_lossy())
51 }
52}
53
54#[derive(PartialEq, PartialOrd, Eq, Clone, Copy)]
56pub struct MediaSubtype(pub spa_sys::spa_media_subtype);
57
58#[allow(non_upper_case_globals)]
59impl MediaSubtype {
60 pub const Unknown: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_unknown);
61 pub const Raw: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_raw);
62 pub const Dsp: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_dsp);
63 pub const Iec958: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_iec958);
65 pub const Dsd: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_dsd);
66
67 pub const Mp3: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_mp3);
68 pub const Aac: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_aac);
69 pub const Vorbis: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_vorbis);
70 pub const Wma: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_wma);
71 pub const Ra: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_ra);
72 pub const Sbc: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_sbc);
73 pub const Adpcm: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_adpcm);
74 pub const G723: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_g723);
75 pub const G726: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_g726);
76 pub const G729: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_g729);
77 pub const Amr: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_amr);
78 pub const Gsm: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_gsm);
79 #[cfg(feature = "v0_3_65")]
80 pub const Alac: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_alac);
81 #[cfg(feature = "v0_3_65")]
82 pub const Flac: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_flac);
83 #[cfg(feature = "v0_3_65")]
84 pub const Ape: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_ape);
85 #[cfg(feature = "v0_3_65")]
86 pub const Opus: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_opus);
87
88 pub const H264: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_h264);
89 pub const Mjpg: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_mjpg);
90 pub const Dv: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_dv);
91 pub const Mpegts: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_mpegts);
92 pub const H263: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_h263);
93 pub const Mpeg1: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_mpeg1);
94 pub const Mpeg2: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_mpeg2);
95 pub const Mpeg4: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_mpeg4);
96 pub const Xvid: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_xvid);
97 pub const Vc1: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_vc1);
98 pub const Vp8: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_vp8);
99 pub const Vp9: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_vp9);
100 pub const Bayer: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_bayer);
101
102 pub const Jpeg: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_jpeg);
103
104 pub const Midi: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_midi);
105
106 pub const Control: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_control);
108
109 const AUDIO_RANGE: Range<Self> = Self::Mp3..Self(spa_sys::SPA_MEDIA_SUBTYPE_START_Video);
110 const VIDEO_RANGE: Range<Self> = Self::H264..Self(spa_sys::SPA_MEDIA_SUBTYPE_START_Image);
111 const IMAGE_RANGE: Range<Self> = Self::Jpeg..Self(spa_sys::SPA_MEDIA_SUBTYPE_START_Binary);
112 const BINARY_RANGE: Range<Self> = Self(spa_sys::SPA_MEDIA_SUBTYPE_START_Binary)
113 ..Self(spa_sys::SPA_MEDIA_SUBTYPE_START_Stream);
114 const STREAM_RANGE: Range<Self> =
115 Self::Midi..Self(spa_sys::SPA_MEDIA_SUBTYPE_START_Application);
116 const APPLICATION_RANGE: Range<Self> = Self::Control..Self(spa_sys::spa_media_subtype::MAX);
117
118 pub fn is_audio(&self) -> bool {
119 Self::AUDIO_RANGE.contains(self)
120 }
121
122 pub fn is_video(&self) -> bool {
123 Self::VIDEO_RANGE.contains(self)
124 }
125
126 pub fn is_image(&self) -> bool {
127 Self::IMAGE_RANGE.contains(self)
128 }
129
130 pub fn is_binary(&self) -> bool {
131 Self::BINARY_RANGE.contains(self)
132 }
133
134 pub fn is_stream(&self) -> bool {
135 Self::STREAM_RANGE.contains(self)
136 }
137
138 pub fn is_application(&self) -> bool {
139 Self::APPLICATION_RANGE.contains(self)
140 }
141
142 pub fn from_raw(raw: spa_sys::spa_media_subtype) -> Self {
144 Self(raw)
145 }
146
147 pub fn as_raw(&self) -> spa_sys::spa_media_subtype {
149 self.0
150 }
151}
152
153impl Debug for MediaSubtype {
154 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
155 let c_str = unsafe {
156 let c_buf = spa_sys::spa_debug_type_find_short_name(
157 spa_sys::spa_type_media_subtype,
158 self.as_raw(),
159 );
160 if c_buf.is_null() {
161 return f.write_str("Unsupported media subtype");
162 }
163 CStr::from_ptr(c_buf)
164 };
165 f.write_str("MediaSubtype::")?;
166 fmt_pascal_case(f, &c_str.to_string_lossy())
167 }
168}
169
170#[derive(PartialEq, PartialOrd, Eq, Clone, Copy)]
171pub struct FormatProperties(pub spa_sys::spa_format);
172
173#[allow(non_upper_case_globals)]
174impl FormatProperties {
175 pub const MediaType: Self = Self(spa_sys::SPA_FORMAT_mediaType);
177 pub const MediaSubtype: Self = Self(spa_sys::SPA_FORMAT_mediaSubtype);
179
180 pub const AudioFormat: Self = Self(spa_sys::SPA_FORMAT_AUDIO_format);
182 pub const AudioFlags: Self = Self(spa_sys::SPA_FORMAT_AUDIO_flags);
184 pub const AudioRate: Self = Self(spa_sys::SPA_FORMAT_AUDIO_rate);
186 pub const AudioChannels: Self = Self(spa_sys::SPA_FORMAT_AUDIO_channels);
188 pub const AudioPosition: Self = Self(spa_sys::SPA_FORMAT_AUDIO_position);
190
191 pub const AudioIec958Codec: Self = Self(spa_sys::SPA_FORMAT_AUDIO_iec958Codec);
193
194 pub const AudioBitorder: Self = Self(spa_sys::SPA_FORMAT_AUDIO_bitorder);
196 pub const AudioInterleave: Self = Self(spa_sys::SPA_FORMAT_AUDIO_interleave);
198 #[cfg(feature = "v0_3_65")]
200 pub const AudioBitrate: Self = Self(spa_sys::SPA_FORMAT_AUDIO_bitrate);
201 #[cfg(feature = "v0_3_65")]
203 pub const AudioBlockAlign: Self = Self(spa_sys::SPA_FORMAT_AUDIO_blockAlign);
204
205 #[cfg(feature = "v0_3_65")]
207 pub const AudioAacStreamFormat: Self = Self(spa_sys::SPA_FORMAT_AUDIO_AAC_streamFormat);
208
209 #[cfg(feature = "v0_3_65")]
211 pub const AudioWmaProfile: Self = Self(spa_sys::SPA_FORMAT_AUDIO_WMA_profile);
212
213 #[cfg(feature = "v0_3_65")]
215 pub const AudioAmrBandMode: Self = Self(spa_sys::SPA_FORMAT_AUDIO_AMR_bandMode);
216
217 pub const VideoFormat: Self = Self(spa_sys::SPA_FORMAT_VIDEO_format);
219 pub const VideoModifier: Self = Self(spa_sys::SPA_FORMAT_VIDEO_modifier);
221 pub const VideoSize: Self = Self(spa_sys::SPA_FORMAT_VIDEO_size);
223 pub const VideoFramerate: Self = Self(spa_sys::SPA_FORMAT_VIDEO_framerate);
225 pub const VideoMaxFramerate: Self = Self(spa_sys::SPA_FORMAT_VIDEO_maxFramerate);
227 pub const VideoViews: Self = Self(spa_sys::SPA_FORMAT_VIDEO_views);
229 pub const VideoInterlaceMode: Self = Self(spa_sys::SPA_FORMAT_VIDEO_interlaceMode);
231 pub const VideoPixelAspectRatio: Self = Self(spa_sys::SPA_FORMAT_VIDEO_pixelAspectRatio);
233 pub const VideoMultiviewMode: Self = Self(spa_sys::SPA_FORMAT_VIDEO_multiviewMode);
235 pub const VideoMultiviewFlags: Self = Self(spa_sys::SPA_FORMAT_VIDEO_multiviewFlags);
237 pub const VideoChromaSite: Self = Self(spa_sys::SPA_FORMAT_VIDEO_chromaSite);
239 pub const VideoColorRange: Self = Self(spa_sys::SPA_FORMAT_VIDEO_colorRange);
241 pub const VideoColorMatrix: Self = Self(spa_sys::SPA_FORMAT_VIDEO_colorMatrix);
243 pub const VideoTransferFunction: Self = Self(spa_sys::SPA_FORMAT_VIDEO_transferFunction);
245 pub const VideoColorPrimaries: Self = Self(spa_sys::SPA_FORMAT_VIDEO_colorPrimaries);
247 pub const VideoProfile: Self = Self(spa_sys::SPA_FORMAT_VIDEO_profile);
249 pub const VideoLevel: Self = Self(spa_sys::SPA_FORMAT_VIDEO_level);
251 pub const VideoH264StreamFormat: Self = Self(spa_sys::SPA_FORMAT_VIDEO_H264_streamFormat);
253 pub const VideoH264Alignment: Self = Self(spa_sys::SPA_FORMAT_VIDEO_H264_alignment);
255
256 const AUDIO_RANGE: Range<Self> = Self::AudioFormat..Self(spa_sys::SPA_FORMAT_START_Video);
257 const VIDEO_RANGE: Range<Self> = Self::VideoFormat..Self(spa_sys::SPA_FORMAT_START_Image);
258 const IMAGE_RANGE: Range<Self> =
259 Self(spa_sys::SPA_FORMAT_START_Image)..Self(spa_sys::SPA_FORMAT_START_Binary);
260 const BINARY_RANGE: Range<Self> =
261 Self(spa_sys::SPA_FORMAT_START_Binary)..Self(spa_sys::SPA_FORMAT_START_Stream);
262 const STREAM_RANGE: Range<Self> =
263 Self(spa_sys::SPA_FORMAT_START_Stream)..Self(spa_sys::SPA_FORMAT_START_Application);
264 const APPLICATION_RANGE: Range<Self> =
265 Self(spa_sys::SPA_FORMAT_START_Application)..Self(spa_sys::spa_format::MAX);
266
267 pub fn is_audio(&self) -> bool {
268 Self::AUDIO_RANGE.contains(self)
269 }
270
271 pub fn is_video(&self) -> bool {
272 Self::VIDEO_RANGE.contains(self)
273 }
274
275 pub fn is_image(&self) -> bool {
276 Self::IMAGE_RANGE.contains(self)
277 }
278
279 pub fn is_binary(&self) -> bool {
280 Self::BINARY_RANGE.contains(self)
281 }
282
283 pub fn is_stream(&self) -> bool {
284 Self::STREAM_RANGE.contains(self)
285 }
286
287 pub fn is_application(&self) -> bool {
288 Self::APPLICATION_RANGE.contains(self)
289 }
290
291 pub fn from_raw(raw: spa_sys::spa_format) -> Self {
293 Self(raw)
294 }
295
296 pub fn as_raw(&self) -> spa_sys::spa_format {
298 self.0
299 }
300}
301
302impl Debug for FormatProperties {
303 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
304 let c_str = unsafe {
305 let c_buf = spa_sys::spa_debug_type_find_name(spa_sys::spa_type_format, self.as_raw());
306 if c_buf.is_null() {
307 return f.write_str("Unsupported format");
308 }
309 CStr::from_ptr(c_buf)
310 };
311 let replaced = c_str
312 .to_string_lossy()
313 .replace("Spa:Pod:Object:Param:Format:", "")
314 .replace(':', " ");
315 f.write_str("FormatProperties::")?;
316 fmt_pascal_case(f, &replaced)
317 }
318}
319
320#[cfg(test)]
321mod tests {
322 use super::*;
323
324 #[test]
325 #[cfg_attr(miri, ignore)]
326 fn debug_format() {
327 assert_eq!("MediaType::Audio", format!("{:?}", MediaType::Audio));
328 assert_eq!("MediaSubtype::Raw", format!("{:?}", MediaSubtype::Raw));
329 assert_eq!(
330 "FormatProperties::VideoTransferFunction",
331 format!("{:?}", FormatProperties::VideoTransferFunction)
332 );
333 }
334}