use convert_case::{Case, Casing};
use std::ffi::CStr;
use std::fmt::Debug;
use std::ops::Range;
#[derive(PartialEq, Eq, Clone, Copy)]
pub struct MediaType(pub spa_sys::spa_media_type);
#[allow(non_upper_case_globals)]
impl MediaType {
pub const Unknown: Self = Self(spa_sys::SPA_MEDIA_TYPE_unknown);
pub const Audio: Self = Self(spa_sys::SPA_MEDIA_TYPE_audio);
pub const Video: Self = Self(spa_sys::SPA_MEDIA_TYPE_video);
pub const Image: Self = Self(spa_sys::SPA_MEDIA_TYPE_image);
pub const Binary: Self = Self(spa_sys::SPA_MEDIA_TYPE_binary);
pub const Stream: Self = Self(spa_sys::SPA_MEDIA_TYPE_stream);
pub const Application: Self = Self(spa_sys::SPA_MEDIA_TYPE_application);
pub fn from_raw(raw: spa_sys::spa_media_type) -> Self {
Self(raw)
}
pub fn as_raw(&self) -> spa_sys::spa_media_type {
self.0
}
}
impl Debug for MediaType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let c_str = unsafe {
let c_buf = spa_sys::spa_debug_type_find_short_name(
spa_sys::spa_type_media_type,
self.as_raw(),
);
if c_buf.is_null() {
return f.write_str("Unsupported media type");
}
CStr::from_ptr(c_buf)
};
let name = format!(
"MediaType::{}",
c_str.to_string_lossy().to_case(Case::Pascal)
);
f.write_str(&name)
}
}
#[derive(PartialEq, PartialOrd, Eq, Clone, Copy)]
pub struct MediaSubtype(pub spa_sys::spa_media_subtype);
#[allow(non_upper_case_globals)]
impl MediaSubtype {
pub const Unknown: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_unknown);
pub const Raw: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_raw);
pub const Dsp: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_dsp);
pub const Iec958: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_iec958);
pub const Dsd: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_dsd);
pub const Mp3: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_mp3);
pub const Aac: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_aac);
pub const Vorbis: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_vorbis);
pub const Wma: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_wma);
pub const Ra: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_ra);
pub const Sbc: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_sbc);
pub const Adpcm: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_adpcm);
pub const G723: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_g723);
pub const G726: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_g726);
pub const G729: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_g729);
pub const Amr: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_amr);
pub const Gsm: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_gsm);
#[cfg(feature = "v0_3_65")]
pub const Alac: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_alac);
#[cfg(feature = "v0_3_65")]
pub const Flac: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_flac);
#[cfg(feature = "v0_3_65")]
pub const Ape: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_ape);
#[cfg(feature = "v0_3_68")]
pub const Opus: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_opus);
pub const H264: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_h264);
pub const Mjpg: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_mjpg);
pub const Dv: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_dv);
pub const Mpegts: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_mpegts);
pub const H263: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_h263);
pub const Mpeg1: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_mpeg1);
pub const Mpeg2: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_mpeg2);
pub const Mpeg4: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_mpeg4);
pub const Xvid: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_xvid);
pub const Vc1: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_vc1);
pub const Vp8: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_vp8);
pub const Vp9: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_vp9);
pub const Bayer: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_bayer);
pub const Jpeg: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_jpeg);
pub const Midi: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_midi);
pub const Control: Self = Self(spa_sys::SPA_MEDIA_SUBTYPE_control);
const AUDIO_RANGE: Range<Self> = Self::Mp3..Self(spa_sys::SPA_MEDIA_SUBTYPE_START_Video);
const VIDEO_RANGE: Range<Self> = Self::H264..Self(spa_sys::SPA_MEDIA_SUBTYPE_START_Image);
const IMAGE_RANGE: Range<Self> = Self::Jpeg..Self(spa_sys::SPA_MEDIA_SUBTYPE_START_Binary);
const BINARY_RANGE: Range<Self> = Self(spa_sys::SPA_MEDIA_SUBTYPE_START_Binary)
..Self(spa_sys::SPA_MEDIA_SUBTYPE_START_Stream);
const STREAM_RANGE: Range<Self> =
Self::Midi..Self(spa_sys::SPA_MEDIA_SUBTYPE_START_Application);
const APPLICATION_RANGE: Range<Self> = Self::Control..Self(spa_sys::spa_media_subtype::MAX);
pub fn is_audio(&self) -> bool {
Self::AUDIO_RANGE.contains(self)
}
pub fn is_video(&self) -> bool {
Self::VIDEO_RANGE.contains(self)
}
pub fn is_image(&self) -> bool {
Self::IMAGE_RANGE.contains(self)
}
pub fn is_binary(&self) -> bool {
Self::BINARY_RANGE.contains(self)
}
pub fn is_stream(&self) -> bool {
Self::STREAM_RANGE.contains(self)
}
pub fn is_application(&self) -> bool {
Self::APPLICATION_RANGE.contains(self)
}
pub fn from_raw(raw: spa_sys::spa_media_subtype) -> Self {
Self(raw)
}
pub fn as_raw(&self) -> spa_sys::spa_media_subtype {
self.0
}
}
impl Debug for MediaSubtype {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let c_str = unsafe {
let c_buf = spa_sys::spa_debug_type_find_short_name(
spa_sys::spa_type_media_subtype,
self.as_raw(),
);
if c_buf.is_null() {
return f.write_str("Unsupported media subtype");
}
CStr::from_ptr(c_buf)
};
let name = format!(
"MediaSubtype::{}",
c_str.to_string_lossy().to_case(Case::Pascal)
);
f.write_str(&name)
}
}
#[derive(PartialEq, PartialOrd, Eq, Clone, Copy)]
pub struct FormatProperties(pub spa_sys::spa_format);
#[allow(non_upper_case_globals)]
impl FormatProperties {
pub const MediaType: Self = Self(spa_sys::SPA_FORMAT_mediaType);
pub const MediaSubtype: Self = Self(spa_sys::SPA_FORMAT_mediaSubtype);
pub const AudioFormat: Self = Self(spa_sys::SPA_FORMAT_AUDIO_format);
pub const AudioFlags: Self = Self(spa_sys::SPA_FORMAT_AUDIO_flags);
pub const AudioRate: Self = Self(spa_sys::SPA_FORMAT_AUDIO_rate);
pub const AudioChannels: Self = Self(spa_sys::SPA_FORMAT_AUDIO_channels);
pub const AudioPosition: Self = Self(spa_sys::SPA_FORMAT_AUDIO_position);
pub const AudioIec958Codec: Self = Self(spa_sys::SPA_FORMAT_AUDIO_iec958Codec);
pub const AudioBitorder: Self = Self(spa_sys::SPA_FORMAT_AUDIO_bitorder);
pub const AudioInterleave: Self = Self(spa_sys::SPA_FORMAT_AUDIO_interleave);
#[cfg(feature = "v0_3_65")]
pub const AudioBitrate: Self = Self(spa_sys::SPA_FORMAT_AUDIO_bitrate);
#[cfg(feature = "v0_3_65")]
pub const AudioBlockAlign: Self = Self(spa_sys::SPA_FORMAT_AUDIO_blockAlign);
#[cfg(feature = "v0_3_65")]
pub const AudioAacStreamFormat: Self = Self(spa_sys::SPA_FORMAT_AUDIO_AAC_streamFormat);
#[cfg(feature = "v0_3_65")]
pub const AudioWmaProfile: Self = Self(spa_sys::SPA_FORMAT_AUDIO_WMA_profile);
#[cfg(feature = "v0_3_65")]
pub const AudioAmrBandMode: Self = Self(spa_sys::SPA_FORMAT_AUDIO_AMR_bandMode);
pub const VideoFormat: Self = Self(spa_sys::SPA_FORMAT_VIDEO_format);
pub const VideoModifier: Self = Self(spa_sys::SPA_FORMAT_VIDEO_modifier);
pub const VideoSize: Self = Self(spa_sys::SPA_FORMAT_VIDEO_size);
pub const VideoFramerate: Self = Self(spa_sys::SPA_FORMAT_VIDEO_framerate);
pub const VideoMaxFramerate: Self = Self(spa_sys::SPA_FORMAT_VIDEO_maxFramerate);
pub const VideoViews: Self = Self(spa_sys::SPA_FORMAT_VIDEO_views);
pub const VideoInterlaceMode: Self = Self(spa_sys::SPA_FORMAT_VIDEO_interlaceMode);
pub const VideoPixelAspectRatio: Self = Self(spa_sys::SPA_FORMAT_VIDEO_pixelAspectRatio);
pub const VideoMultiviewMode: Self = Self(spa_sys::SPA_FORMAT_VIDEO_multiviewMode);
pub const VideoMultiviewFlags: Self = Self(spa_sys::SPA_FORMAT_VIDEO_multiviewFlags);
pub const VideoChromaSite: Self = Self(spa_sys::SPA_FORMAT_VIDEO_chromaSite);
pub const VideoColorRange: Self = Self(spa_sys::SPA_FORMAT_VIDEO_colorRange);
pub const VideoColorMatrix: Self = Self(spa_sys::SPA_FORMAT_VIDEO_colorMatrix);
pub const VideoTransferFunction: Self = Self(spa_sys::SPA_FORMAT_VIDEO_transferFunction);
pub const VideoColorPrimaries: Self = Self(spa_sys::SPA_FORMAT_VIDEO_colorPrimaries);
pub const VideoProfile: Self = Self(spa_sys::SPA_FORMAT_VIDEO_profile);
pub const VideoLevel: Self = Self(spa_sys::SPA_FORMAT_VIDEO_level);
pub const VideoH264StreamFormat: Self = Self(spa_sys::SPA_FORMAT_VIDEO_H264_streamFormat);
pub const VideoH264Alignment: Self = Self(spa_sys::SPA_FORMAT_VIDEO_H264_alignment);
const AUDIO_RANGE: Range<Self> = Self::AudioFormat..Self(spa_sys::SPA_FORMAT_START_Video);
const VIDEO_RANGE: Range<Self> = Self::VideoFormat..Self(spa_sys::SPA_FORMAT_START_Image);
const IMAGE_RANGE: Range<Self> =
Self(spa_sys::SPA_FORMAT_START_Image)..Self(spa_sys::SPA_FORMAT_START_Binary);
const BINARY_RANGE: Range<Self> =
Self(spa_sys::SPA_FORMAT_START_Binary)..Self(spa_sys::SPA_FORMAT_START_Stream);
const STREAM_RANGE: Range<Self> =
Self(spa_sys::SPA_FORMAT_START_Stream)..Self(spa_sys::SPA_FORMAT_START_Application);
const APPLICATION_RANGE: Range<Self> =
Self(spa_sys::SPA_FORMAT_START_Application)..Self(spa_sys::spa_format::MAX);
pub fn is_audio(&self) -> bool {
Self::AUDIO_RANGE.contains(self)
}
pub fn is_video(&self) -> bool {
Self::VIDEO_RANGE.contains(self)
}
pub fn is_image(&self) -> bool {
Self::IMAGE_RANGE.contains(self)
}
pub fn is_binary(&self) -> bool {
Self::BINARY_RANGE.contains(self)
}
pub fn is_stream(&self) -> bool {
Self::STREAM_RANGE.contains(self)
}
pub fn is_application(&self) -> bool {
Self::APPLICATION_RANGE.contains(self)
}
pub fn from_raw(raw: spa_sys::spa_format) -> Self {
Self(raw)
}
pub fn as_raw(&self) -> spa_sys::spa_format {
self.0
}
}
impl Debug for FormatProperties {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let c_str = unsafe {
let c_buf = spa_sys::spa_debug_type_find_name(spa_sys::spa_type_format, self.as_raw());
if c_buf.is_null() {
return f.write_str("Unsupported format");
}
CStr::from_ptr(c_buf)
};
let name = format!(
"FormatProperties::{}",
c_str
.to_string_lossy()
.replace("Spa:Pod:Object:Param:Format:", "")
.replace(':', " ")
.to_case(Case::Pascal)
);
f.write_str(&name)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
#[cfg_attr(miri, ignore)]
fn debug_format() {
assert_eq!("MediaType::Audio", format!("{:?}", MediaType::Audio));
assert_eq!("MediaSubtype::Raw", format!("{:?}", MediaSubtype::Raw));
assert_eq!(
"FormatProperties::VideoTransferFunction",
format!("{:?}", FormatProperties::VideoTransferFunction)
);
}
}