summaryrefslogtreecommitdiffstats
path: root/third_party/rust/alsa/src/chmap.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/alsa/src/chmap.rs')
-rw-r--r--third_party/rust/alsa/src/chmap.rs148
1 files changed, 148 insertions, 0 deletions
diff --git a/third_party/rust/alsa/src/chmap.rs b/third_party/rust/alsa/src/chmap.rs
new file mode 100644
index 0000000000..b2c75921b3
--- /dev/null
+++ b/third_party/rust/alsa/src/chmap.rs
@@ -0,0 +1,148 @@
+use crate::alsa;
+use std::{fmt, mem, slice};
+use super::error::*;
+
+alsa_enum!(
+ /// [SND_CHMAP_TYPE_xxx](http://www.alsa-project.org/alsa-doc/alsa-lib/group___p_c_m.html) constants
+ ChmapType, ALL_CHMAP_TYPES[4],
+
+ None = SND_CHMAP_TYPE_NONE,
+ Fixed = SND_CHMAP_TYPE_FIXED,
+ Var = SND_CHMAP_TYPE_VAR,
+ Paired = SND_CHMAP_TYPE_PAIRED,
+);
+
+alsa_enum!(
+ /// [SND_CHMAP_xxx](http://www.alsa-project.org/alsa-doc/alsa-lib/group___p_c_m.html) constants
+ ChmapPosition, ALL_CHMAP_POSITIONS[33],
+
+ Unknown = SND_CHMAP_UNKNOWN,
+ NA = SND_CHMAP_NA,
+ Mono = SND_CHMAP_MONO,
+ FL = SND_CHMAP_FL,
+ FR = SND_CHMAP_FR,
+ RL = SND_CHMAP_RL,
+ SR = SND_CHMAP_SR,
+ RC = SND_CHMAP_RC,
+ FLC = SND_CHMAP_FLC,
+ FRC = SND_CHMAP_FRC,
+ RLC = SND_CHMAP_RLC,
+ RRC = SND_CHMAP_RRC,
+ FLW = SND_CHMAP_FLW,
+ FRW = SND_CHMAP_FRW,
+ FLH = SND_CHMAP_FLH,
+ FCH = SND_CHMAP_FCH,
+ FRH = SND_CHMAP_FRH,
+ TC = SND_CHMAP_TC,
+ TFL = SND_CHMAP_TFL,
+ TFR = SND_CHMAP_TFR,
+ TFC = SND_CHMAP_TFC,
+ TRL = SND_CHMAP_TRL,
+ TRR = SND_CHMAP_TRR,
+ TRC = SND_CHMAP_TRC,
+ TFLC = SND_CHMAP_TFLC,
+ TFRC = SND_CHMAP_TFRC,
+ TSL = SND_CHMAP_TSL,
+ TSR = SND_CHMAP_TSR,
+ LLFE = SND_CHMAP_LLFE,
+ RLFE = SND_CHMAP_RLFE,
+ BC = SND_CHMAP_BC,
+ BLC = SND_CHMAP_BLC,
+ BRC = SND_CHMAP_BRC,
+);
+
+impl fmt::Display for ChmapPosition {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ let s = unsafe { alsa::snd_pcm_chmap_long_name(*self as libc::c_uint) };
+ let s = from_const("snd_pcm_chmap_long_name", s)?;
+ write!(f, "{}", s)
+ }
+}
+
+
+/// [snd_pcm_chmap_t](http://www.alsa-project.org/alsa-doc/alsa-lib/group___p_c_m.html) wrapper
+pub struct Chmap(*mut alsa::snd_pcm_chmap_t, bool);
+
+impl Drop for Chmap {
+ fn drop(&mut self) { if self.1 { unsafe { libc::free(self.0 as *mut libc::c_void) }}}
+}
+
+impl Chmap {
+ fn set_channels(&mut self, c: libc::c_uint) { unsafe { (*self.0) .channels = c }}
+ fn as_slice_mut(&mut self) -> &mut [libc::c_uint] {
+ unsafe { slice::from_raw_parts_mut((*self.0).pos.as_mut_ptr(), (*self.0).channels as usize) }
+ }
+ fn as_slice(&self) -> &[libc::c_uint] {
+ unsafe { slice::from_raw_parts((*self.0).pos.as_ptr(), (*self.0).channels as usize) }
+ }
+}
+
+impl fmt::Display for Chmap {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ let mut buf: Vec<libc::c_char> = vec![0; 512];
+ acheck!(snd_pcm_chmap_print(self.0, buf.len() as libc::size_t, buf.as_mut_ptr()))?;
+ let s = from_const("snd_pcm_chmap_print", buf.as_mut_ptr())?;
+ write!(f, "{}", s)
+ }
+}
+
+impl<'a> From<&'a [ChmapPosition]> for Chmap {
+ fn from(a: &'a [ChmapPosition]) -> Chmap {
+ let p = unsafe { libc::malloc((mem::size_of::<alsa::snd_pcm_chmap_t>() + mem::size_of::<libc::c_uint>() * a.len()) as libc::size_t) };
+ if p.is_null() { panic!("Out of memory") }
+ let mut r = Chmap(p as *mut alsa::snd_pcm_chmap_t, true);
+ r.set_channels(a.len() as libc::c_uint);
+ for (i,v) in r.as_slice_mut().iter_mut().enumerate() { *v = a[i] as libc::c_uint }
+ r
+ }
+}
+
+impl<'a> From<&'a Chmap> for Vec<ChmapPosition> {
+ fn from(a: &'a Chmap) -> Vec<ChmapPosition> {
+ a.as_slice().iter().map(|&v| ChmapPosition::from_c_int(v as libc::c_int, "").unwrap()).collect()
+ }
+}
+
+pub fn chmap_new(a: *mut alsa::snd_pcm_chmap_t) -> Chmap { Chmap(a, true) }
+pub fn chmap_handle(a: &Chmap) -> *mut alsa::snd_pcm_chmap_t { a.0 }
+
+
+/// Iterator over available channel maps - see [snd_pcm_chmap_query_t](http://www.alsa-project.org/alsa-doc/alsa-lib/group___p_c_m.html)
+pub struct ChmapsQuery(*mut *mut alsa::snd_pcm_chmap_query_t, isize);
+
+impl Drop for ChmapsQuery {
+ fn drop(&mut self) { unsafe { alsa::snd_pcm_free_chmaps(self.0) }}
+}
+
+pub fn chmaps_query_new(a: *mut *mut alsa::snd_pcm_chmap_query_t) -> ChmapsQuery { ChmapsQuery(a, 0) }
+
+impl Iterator for ChmapsQuery {
+ type Item = (ChmapType, Chmap);
+ fn next(&mut self) -> Option<Self::Item> {
+ if self.0.is_null() { return None; }
+ let p = unsafe { *self.0.offset(self.1) };
+ if p.is_null() { return None; }
+ self.1 += 1;
+ let t = ChmapType::from_c_int(unsafe { (*p).type_ } as libc::c_int, "snd_pcm_query_chmaps").unwrap();
+ let m = Chmap(unsafe { &mut (*p).map }, false);
+ Some((t, m))
+ }
+}
+
+
+#[test]
+fn chmap_for_first_pcm() {
+ use super::*;
+ use std::ffi::CString;
+ use crate::device_name::HintIter;
+ let i = HintIter::new(None, &*CString::new("pcm").unwrap()).unwrap();
+ for p in i.map(|n| n.name.unwrap()) {
+ println!("Chmaps for {:?}:", p);
+ match PCM::open(&CString::new(p).unwrap(), Direction::Playback, false) {
+ Ok(a) => for c in a.query_chmaps() {
+ println!(" {:?}, {}", c.0, c.1);
+ },
+ Err(a) => println!(" {}", a) // It's okay to have entries in the name hint array that can't be opened
+ }
+ }
+}