1 // Copyright © 2017-2018 Mozilla Foundation
2 //
3 // This program is made available under an ISC-style license.  See the
4 // accompanying file LICENSE for details.
5 
6 use ffi;
7 
8 bitflags! {
9     /// Some common layout definitions
10     pub struct ChannelLayout: ffi::cubeb_channel_layout {
11         ///
12         const FRONT_LEFT = ffi::CHANNEL_FRONT_LEFT;
13         const FRONT_RIGHT = ffi::CHANNEL_FRONT_RIGHT;
14         const FRONT_CENTER = ffi::CHANNEL_FRONT_CENTER;
15         const LOW_FREQUENCY = ffi::CHANNEL_LOW_FREQUENCY;
16         const BACK_LEFT = ffi::CHANNEL_BACK_LEFT;
17         const BACK_RIGHT = ffi::CHANNEL_BACK_RIGHT;
18         const FRONT_LEFT_OF_CENTER = ffi::CHANNEL_FRONT_LEFT_OF_CENTER;
19         const FRONT_RIGHT_OF_CENTER = ffi::CHANNEL_FRONT_RIGHT_OF_CENTER;
20         const BACK_CENTER = ffi::CHANNEL_BACK_CENTER;
21         const SIDE_LEFT = ffi::CHANNEL_SIDE_LEFT;
22         const SIDE_RIGHT = ffi::CHANNEL_SIDE_RIGHT;
23         const TOP_CENTER = ffi::CHANNEL_TOP_CENTER;
24         const TOP_FRONT_LEFT = ffi::CHANNEL_TOP_FRONT_LEFT;
25         const TOP_FRONT_CENTER = ffi::CHANNEL_TOP_FRONT_CENTER;
26         const TOP_FRONT_RIGHT = ffi::CHANNEL_TOP_FRONT_RIGHT;
27         const TOP_BACK_LEFT = ffi::CHANNEL_TOP_BACK_LEFT;
28         const TOP_BACK_CENTER = ffi::CHANNEL_TOP_BACK_CENTER;
29         const TOP_BACK_RIGHT = ffi::CHANNEL_TOP_BACK_RIGHT;
30     }
31 }
32 
33 macro_rules! bits {
34     ($($x:ident => $y:ident),*) => {
35         $(pub const $x: ChannelLayout = ChannelLayout { bits: ffi::$y };)*
36     }
37 }
38 
39 impl ChannelLayout {
40     bits!(UNDEFINED => CUBEB_LAYOUT_UNDEFINED,
41           MONO => CUBEB_LAYOUT_MONO,
42           MONO_LFE => CUBEB_LAYOUT_MONO_LFE,
43           STEREO => CUBEB_LAYOUT_STEREO,
44           STEREO_LFE => CUBEB_LAYOUT_STEREO_LFE,
45           _3F => CUBEB_LAYOUT_3F,
46           _3F_LFE => CUBEB_LAYOUT_3F_LFE,
47           _2F1 => CUBEB_LAYOUT_2F1,
48           _2F1_LFE => CUBEB_LAYOUT_2F1_LFE,
49           _3F1 => CUBEB_LAYOUT_3F1,
50           _3F1_LFE => CUBEB_LAYOUT_3F1_LFE,
51           _2F2 => CUBEB_LAYOUT_2F2,
52           _2F2_LFE => CUBEB_LAYOUT_2F2_LFE,
53           QUAD => CUBEB_LAYOUT_QUAD,
54           QUAD_LFE => CUBEB_LAYOUT_QUAD_LFE,
55           _3F2 => CUBEB_LAYOUT_3F2,
56           _3F2_LFE => CUBEB_LAYOUT_3F2_LFE,
57           _3F2_BACK => CUBEB_LAYOUT_3F2_BACK,
58           _3F2_LFE_BACK => CUBEB_LAYOUT_3F2_LFE_BACK,
59           _3F3R_LFE => CUBEB_LAYOUT_3F3R_LFE,
60           _3F4_LFE => CUBEB_LAYOUT_3F4_LFE
61     );
62 }
63 
64 impl From<ffi::cubeb_channel> for ChannelLayout {
from(x: ffi::cubeb_channel) -> Self65     fn from(x: ffi::cubeb_channel) -> Self {
66         ChannelLayout::from_bits_truncate(x)
67     }
68 }
69 
70 impl Into<ffi::cubeb_channel> for ChannelLayout {
into(self) -> ffi::cubeb_channel71     fn into(self) -> ffi::cubeb_channel {
72         self.bits()
73     }
74 }
75 
76 impl ChannelLayout {
num_channels(&self) -> u3277     pub fn num_channels(&self) -> u32 {
78         let layout = *self;
79         unsafe { ffi::cubeb_channel_layout_nb_channels(layout.into()) }
80     }
81 }
82 
83 #[cfg(test)]
84 mod test {
85     use ffi;
86 
87     #[test]
channel_layout_from_raw()88     fn channel_layout_from_raw() {
89         macro_rules! check(
90             ($($raw:ident => $real:ident),*) => (
91                 $(let x = super::ChannelLayout::from(ffi::$raw);
92                   assert_eq!(x, super::ChannelLayout::$real);
93                 )*
94             ) );
95 
96         check!(CUBEB_LAYOUT_UNDEFINED => UNDEFINED,
97                CUBEB_LAYOUT_MONO => MONO,
98                CUBEB_LAYOUT_MONO_LFE => MONO_LFE,
99                CUBEB_LAYOUT_STEREO => STEREO,
100                CUBEB_LAYOUT_STEREO_LFE => STEREO_LFE,
101                CUBEB_LAYOUT_3F => _3F,
102                CUBEB_LAYOUT_3F_LFE => _3F_LFE,
103                CUBEB_LAYOUT_2F1 => _2F1,
104                CUBEB_LAYOUT_2F1_LFE => _2F1_LFE,
105                CUBEB_LAYOUT_3F1 => _3F1,
106                CUBEB_LAYOUT_3F1_LFE => _3F1_LFE,
107                CUBEB_LAYOUT_2F2 => _2F2,
108                CUBEB_LAYOUT_2F2_LFE => _2F2_LFE,
109                CUBEB_LAYOUT_QUAD => QUAD,
110                CUBEB_LAYOUT_QUAD_LFE => QUAD_LFE,
111                CUBEB_LAYOUT_3F2 => _3F2,
112                CUBEB_LAYOUT_3F2_LFE => _3F2_LFE,
113                CUBEB_LAYOUT_3F2_BACK => _3F2_BACK,
114                CUBEB_LAYOUT_3F2_LFE_BACK => _3F2_LFE_BACK,
115                CUBEB_LAYOUT_3F3R_LFE => _3F3R_LFE,
116                CUBEB_LAYOUT_3F4_LFE => _3F4_LFE);
117     }
118 
119     #[test]
channel_layout_into_raw()120     fn channel_layout_into_raw() {
121         macro_rules! check(
122             ($($real:ident => $raw:ident),*) => (
123                 $(let x = super::ChannelLayout::$real;
124                   let x: ffi::cubeb_channel_layout = x.into();
125                   assert_eq!(x, ffi::$raw);
126                 )*
127             ) );
128 
129         check!(UNDEFINED => CUBEB_LAYOUT_UNDEFINED,
130                MONO => CUBEB_LAYOUT_MONO,
131                MONO_LFE => CUBEB_LAYOUT_MONO_LFE,
132                STEREO => CUBEB_LAYOUT_STEREO,
133                STEREO_LFE => CUBEB_LAYOUT_STEREO_LFE,
134                _3F => CUBEB_LAYOUT_3F,
135                _3F_LFE => CUBEB_LAYOUT_3F_LFE,
136                _2F1 => CUBEB_LAYOUT_2F1,
137                _2F1_LFE=> CUBEB_LAYOUT_2F1_LFE,
138                _3F1 => CUBEB_LAYOUT_3F1,
139                _3F1_LFE =>  CUBEB_LAYOUT_3F1_LFE,
140                _2F2 => CUBEB_LAYOUT_2F2,
141                _2F2_LFE => CUBEB_LAYOUT_2F2_LFE,
142                QUAD => CUBEB_LAYOUT_QUAD,
143                QUAD_LFE => CUBEB_LAYOUT_QUAD_LFE,
144                _3F2 => CUBEB_LAYOUT_3F2,
145                _3F2_LFE => CUBEB_LAYOUT_3F2_LFE,
146                _3F2_BACK => CUBEB_LAYOUT_3F2_BACK,
147                _3F2_LFE_BACK => CUBEB_LAYOUT_3F2_LFE_BACK,
148                _3F3R_LFE => CUBEB_LAYOUT_3F3R_LFE,
149                _3F4_LFE => CUBEB_LAYOUT_3F4_LFE);
150     }
151 }
152