1 use std::ops::Deref;
2 
3 use super::codec::Codec;
4 use ffi::*;
5 use {format, ChannelLayout};
6 
7 #[derive(PartialEq, Eq, Copy, Clone)]
8 pub struct Audio {
9     codec: Codec,
10 }
11 
12 impl Audio {
new(codec: Codec) -> Audio13     pub unsafe fn new(codec: Codec) -> Audio {
14         Audio { codec }
15     }
16 }
17 
18 impl Audio {
rates(&self) -> Option<RateIter>19     pub fn rates(&self) -> Option<RateIter> {
20         unsafe {
21             if (*self.as_ptr()).supported_samplerates.is_null() {
22                 None
23             } else {
24                 Some(RateIter::new((*self.codec.as_ptr()).supported_samplerates))
25             }
26         }
27     }
28 
formats(&self) -> Option<FormatIter>29     pub fn formats(&self) -> Option<FormatIter> {
30         unsafe {
31             if (*self.codec.as_ptr()).sample_fmts.is_null() {
32                 None
33             } else {
34                 Some(FormatIter::new((*self.codec.as_ptr()).sample_fmts))
35             }
36         }
37     }
38 
channel_layouts(&self) -> Option<ChannelLayoutIter>39     pub fn channel_layouts(&self) -> Option<ChannelLayoutIter> {
40         unsafe {
41             if (*self.codec.as_ptr()).channel_layouts.is_null() {
42                 None
43             } else {
44                 Some(ChannelLayoutIter::new(
45                     (*self.codec.as_ptr()).channel_layouts,
46                 ))
47             }
48         }
49     }
50 }
51 
52 impl Deref for Audio {
53     type Target = Codec;
54 
deref(&self) -> &Self::Target55     fn deref(&self) -> &Self::Target {
56         &self.codec
57     }
58 }
59 
60 pub struct RateIter {
61     ptr: *const i32,
62 }
63 
64 impl RateIter {
new(ptr: *const i32) -> Self65     pub fn new(ptr: *const i32) -> Self {
66         RateIter { ptr }
67     }
68 }
69 
70 impl Iterator for RateIter {
71     type Item = i32;
72 
next(&mut self) -> Option<<Self as Iterator>::Item>73     fn next(&mut self) -> Option<<Self as Iterator>::Item> {
74         unsafe {
75             if *self.ptr == 0 {
76                 return None;
77             }
78 
79             let rate = *self.ptr;
80             self.ptr = self.ptr.offset(1);
81 
82             Some(rate)
83         }
84     }
85 }
86 
87 pub struct FormatIter {
88     ptr: *const AVSampleFormat,
89 }
90 
91 impl FormatIter {
new(ptr: *const AVSampleFormat) -> Self92     pub fn new(ptr: *const AVSampleFormat) -> Self {
93         FormatIter { ptr }
94     }
95 }
96 
97 impl Iterator for FormatIter {
98     type Item = format::Sample;
99 
next(&mut self) -> Option<<Self as Iterator>::Item>100     fn next(&mut self) -> Option<<Self as Iterator>::Item> {
101         unsafe {
102             if *self.ptr == AVSampleFormat::AV_SAMPLE_FMT_NONE {
103                 return None;
104             }
105 
106             let format = (*self.ptr).into();
107             self.ptr = self.ptr.offset(1);
108 
109             Some(format)
110         }
111     }
112 }
113 
114 pub struct ChannelLayoutIter {
115     ptr: *const u64,
116 }
117 
118 impl ChannelLayoutIter {
new(ptr: *const u64) -> Self119     pub fn new(ptr: *const u64) -> Self {
120         ChannelLayoutIter { ptr }
121     }
122 
best(self, max: i32) -> ChannelLayout123     pub fn best(self, max: i32) -> ChannelLayout {
124         self.fold(ChannelLayout::MONO, |acc, cur| {
125             if cur.channels() > acc.channels() && cur.channels() <= max {
126                 cur
127             } else {
128                 acc
129             }
130         })
131     }
132 }
133 
134 impl Iterator for ChannelLayoutIter {
135     type Item = ChannelLayout;
136 
next(&mut self) -> Option<<Self as Iterator>::Item>137     fn next(&mut self) -> Option<<Self as Iterator>::Item> {
138         unsafe {
139             if *self.ptr == 0 {
140                 return None;
141             }
142 
143             let layout = ChannelLayout::from_bits_truncate(*self.ptr);
144             self.ptr = self.ptr.offset(1);
145 
146             Some(layout)
147         }
148     }
149 }
150