1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
extern crate libsoundio_sys as raw;

use super::util::*;

use std::fmt;

/// ChannelId indicates the location or intent of a channel (left, right, LFE, etc.).
///
/// It supports the `Display` trait so that you can convert `ChannelId::FrontLeft` to `"Front Left"` for example.
///
/// # Examples
///
/// ```
/// # use soundio::*;
/// println!("Layout: {}", ChannelId::FrontLeftCenter);
///
/// assert_eq!(format!("{}", ChannelId::MsMid), "Mid/Side Mid");
/// ```
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum ChannelId {
    Invalid,

    /// The more commonly supported ids.
    FrontLeft,
    FrontRight,
    FrontCenter,
    Lfe,
    BackLeft,
    BackRight,
    FrontLeftCenter,
    FrontRightCenter,
    BackCenter,
    SideLeft,
    SideRight,
    TopCenter,
    TopFrontLeft,
    TopFrontCenter,
    TopFrontRight,
    TopBackLeft,
    TopBackCenter,
    TopBackRight,

    /// The less commonly supported ids.
    BackLeftCenter,
    BackRightCenter,
    FrontLeftWide,
    FrontRightWide,
    FrontLeftHigh,
    FrontCenterHigh,
    FrontRightHigh,
    TopFrontLeftCenter,
    TopFrontRightCenter,
    TopSideLeft,
    TopSideRight,
    LeftLfe,
    RightLfe,
    Lfe2,
    BottomCenter,
    BottomLeftCenter,
    BottomRightCenter,

    /// Mid/side recording
    MsMid,
    MsSide,

    /// First order ambisonic channels
    AmbisonicW,
    AmbisonicX,
    AmbisonicY,
    AmbisonicZ,

    /// X-Y Recording
    XyX,
    XyY,

    /// The "other" channel ids
    HeadphonesLeft,
    HeadphonesRight,
    ClickTrack,
    ForeignLanguage,
    HearingImpaired,
    Narration,
    Haptic,
    DialogCentricMix,

    Aux,
    Aux0,
    Aux1,
    Aux2,
    Aux3,
    Aux4,
    Aux5,
    Aux6,
    Aux7,
    Aux8,
    Aux9,
    Aux10,
    Aux11,
    Aux12,
    Aux13,
    Aux14,
    Aux15,
}

impl From<raw::SoundIoChannelId> for ChannelId {
    fn from(channel_id: raw::SoundIoChannelId) -> ChannelId {
        match channel_id {
            raw::SoundIoChannelId::SoundIoChannelIdFrontLeft => ChannelId::FrontLeft,
            raw::SoundIoChannelId::SoundIoChannelIdFrontRight => ChannelId::FrontRight,
            raw::SoundIoChannelId::SoundIoChannelIdFrontCenter => ChannelId::FrontCenter,
            raw::SoundIoChannelId::SoundIoChannelIdLfe => ChannelId::Lfe,
            raw::SoundIoChannelId::SoundIoChannelIdBackLeft => ChannelId::BackLeft,
            raw::SoundIoChannelId::SoundIoChannelIdBackRight => ChannelId::BackRight,
            raw::SoundIoChannelId::SoundIoChannelIdFrontLeftCenter => ChannelId::FrontLeftCenter,
            raw::SoundIoChannelId::SoundIoChannelIdFrontRightCenter => ChannelId::FrontRightCenter,
            raw::SoundIoChannelId::SoundIoChannelIdBackCenter => ChannelId::BackCenter,
            raw::SoundIoChannelId::SoundIoChannelIdSideLeft => ChannelId::SideLeft,
            raw::SoundIoChannelId::SoundIoChannelIdSideRight => ChannelId::SideRight,
            raw::SoundIoChannelId::SoundIoChannelIdTopCenter => ChannelId::TopCenter,
            raw::SoundIoChannelId::SoundIoChannelIdTopFrontLeft => ChannelId::TopFrontLeft,
            raw::SoundIoChannelId::SoundIoChannelIdTopFrontCenter => ChannelId::TopFrontCenter,
            raw::SoundIoChannelId::SoundIoChannelIdTopFrontRight => ChannelId::TopFrontRight,
            raw::SoundIoChannelId::SoundIoChannelIdTopBackLeft => ChannelId::TopBackLeft,
            raw::SoundIoChannelId::SoundIoChannelIdTopBackCenter => ChannelId::TopBackCenter,
            raw::SoundIoChannelId::SoundIoChannelIdTopBackRight => ChannelId::TopBackRight,
            raw::SoundIoChannelId::SoundIoChannelIdBackLeftCenter => ChannelId::BackLeftCenter,
            raw::SoundIoChannelId::SoundIoChannelIdBackRightCenter => ChannelId::BackRightCenter,
            raw::SoundIoChannelId::SoundIoChannelIdFrontLeftWide => ChannelId::FrontLeftWide,
            raw::SoundIoChannelId::SoundIoChannelIdFrontRightWide => ChannelId::FrontRightWide,
            raw::SoundIoChannelId::SoundIoChannelIdFrontLeftHigh => ChannelId::FrontLeftHigh,
            raw::SoundIoChannelId::SoundIoChannelIdFrontCenterHigh => ChannelId::FrontCenterHigh,
            raw::SoundIoChannelId::SoundIoChannelIdFrontRightHigh => ChannelId::FrontRightHigh,
            raw::SoundIoChannelId::SoundIoChannelIdTopFrontLeftCenter => {
                ChannelId::TopFrontLeftCenter
            }
            raw::SoundIoChannelId::SoundIoChannelIdTopFrontRightCenter => {
                ChannelId::TopFrontRightCenter
            }
            raw::SoundIoChannelId::SoundIoChannelIdTopSideLeft => ChannelId::TopSideLeft,
            raw::SoundIoChannelId::SoundIoChannelIdTopSideRight => ChannelId::TopSideRight,
            raw::SoundIoChannelId::SoundIoChannelIdLeftLfe => ChannelId::LeftLfe,
            raw::SoundIoChannelId::SoundIoChannelIdRightLfe => ChannelId::RightLfe,
            raw::SoundIoChannelId::SoundIoChannelIdLfe2 => ChannelId::Lfe2,
            raw::SoundIoChannelId::SoundIoChannelIdBottomCenter => ChannelId::BottomCenter,
            raw::SoundIoChannelId::SoundIoChannelIdBottomLeftCenter => ChannelId::BottomLeftCenter,
            raw::SoundIoChannelId::SoundIoChannelIdBottomRightCenter => {
                ChannelId::BottomRightCenter
            }
            raw::SoundIoChannelId::SoundIoChannelIdMsMid => ChannelId::MsMid,
            raw::SoundIoChannelId::SoundIoChannelIdMsSide => ChannelId::MsSide,
            raw::SoundIoChannelId::SoundIoChannelIdAmbisonicW => ChannelId::AmbisonicW,
            raw::SoundIoChannelId::SoundIoChannelIdAmbisonicX => ChannelId::AmbisonicX,
            raw::SoundIoChannelId::SoundIoChannelIdAmbisonicY => ChannelId::AmbisonicY,
            raw::SoundIoChannelId::SoundIoChannelIdAmbisonicZ => ChannelId::AmbisonicZ,
            raw::SoundIoChannelId::SoundIoChannelIdXyX => ChannelId::XyX,
            raw::SoundIoChannelId::SoundIoChannelIdXyY => ChannelId::XyY,
            raw::SoundIoChannelId::SoundIoChannelIdHeadphonesLeft => ChannelId::HeadphonesLeft,
            raw::SoundIoChannelId::SoundIoChannelIdHeadphonesRight => ChannelId::HeadphonesRight,
            raw::SoundIoChannelId::SoundIoChannelIdClickTrack => ChannelId::ClickTrack,
            raw::SoundIoChannelId::SoundIoChannelIdForeignLanguage => ChannelId::ForeignLanguage,
            raw::SoundIoChannelId::SoundIoChannelIdHearingImpaired => ChannelId::HearingImpaired,
            raw::SoundIoChannelId::SoundIoChannelIdNarration => ChannelId::Narration,
            raw::SoundIoChannelId::SoundIoChannelIdHaptic => ChannelId::Haptic,
            raw::SoundIoChannelId::SoundIoChannelIdDialogCentricMix => ChannelId::DialogCentricMix,
            raw::SoundIoChannelId::SoundIoChannelIdAux => ChannelId::Aux,
            raw::SoundIoChannelId::SoundIoChannelIdAux0 => ChannelId::Aux0,
            raw::SoundIoChannelId::SoundIoChannelIdAux1 => ChannelId::Aux1,
            raw::SoundIoChannelId::SoundIoChannelIdAux2 => ChannelId::Aux2,
            raw::SoundIoChannelId::SoundIoChannelIdAux3 => ChannelId::Aux3,
            raw::SoundIoChannelId::SoundIoChannelIdAux4 => ChannelId::Aux4,
            raw::SoundIoChannelId::SoundIoChannelIdAux5 => ChannelId::Aux5,
            raw::SoundIoChannelId::SoundIoChannelIdAux6 => ChannelId::Aux6,
            raw::SoundIoChannelId::SoundIoChannelIdAux7 => ChannelId::Aux7,
            raw::SoundIoChannelId::SoundIoChannelIdAux8 => ChannelId::Aux8,
            raw::SoundIoChannelId::SoundIoChannelIdAux9 => ChannelId::Aux9,
            raw::SoundIoChannelId::SoundIoChannelIdAux10 => ChannelId::Aux10,
            raw::SoundIoChannelId::SoundIoChannelIdAux11 => ChannelId::Aux11,
            raw::SoundIoChannelId::SoundIoChannelIdAux12 => ChannelId::Aux12,
            raw::SoundIoChannelId::SoundIoChannelIdAux13 => ChannelId::Aux13,
            raw::SoundIoChannelId::SoundIoChannelIdAux14 => ChannelId::Aux14,
            raw::SoundIoChannelId::SoundIoChannelIdAux15 => ChannelId::Aux15,
            _ => ChannelId::Invalid,
        }
    }
}

impl From<ChannelId> for raw::SoundIoChannelId {
    fn from(channel_id: ChannelId) -> raw::SoundIoChannelId {
        match channel_id {
            ChannelId::FrontLeft => raw::SoundIoChannelId::SoundIoChannelIdFrontLeft,
            ChannelId::FrontRight => raw::SoundIoChannelId::SoundIoChannelIdFrontRight,
            ChannelId::FrontCenter => raw::SoundIoChannelId::SoundIoChannelIdFrontCenter,
            ChannelId::Lfe => raw::SoundIoChannelId::SoundIoChannelIdLfe,
            ChannelId::BackLeft => raw::SoundIoChannelId::SoundIoChannelIdBackLeft,
            ChannelId::BackRight => raw::SoundIoChannelId::SoundIoChannelIdBackRight,
            ChannelId::FrontLeftCenter => raw::SoundIoChannelId::SoundIoChannelIdFrontLeftCenter,
            ChannelId::FrontRightCenter => raw::SoundIoChannelId::SoundIoChannelIdFrontRightCenter,
            ChannelId::BackCenter => raw::SoundIoChannelId::SoundIoChannelIdBackCenter,
            ChannelId::SideLeft => raw::SoundIoChannelId::SoundIoChannelIdSideLeft,
            ChannelId::SideRight => raw::SoundIoChannelId::SoundIoChannelIdSideRight,
            ChannelId::TopCenter => raw::SoundIoChannelId::SoundIoChannelIdTopCenter,
            ChannelId::TopFrontLeft => raw::SoundIoChannelId::SoundIoChannelIdTopFrontLeft,
            ChannelId::TopFrontCenter => raw::SoundIoChannelId::SoundIoChannelIdTopFrontCenter,
            ChannelId::TopFrontRight => raw::SoundIoChannelId::SoundIoChannelIdTopFrontRight,
            ChannelId::TopBackLeft => raw::SoundIoChannelId::SoundIoChannelIdTopBackLeft,
            ChannelId::TopBackCenter => raw::SoundIoChannelId::SoundIoChannelIdTopBackCenter,
            ChannelId::TopBackRight => raw::SoundIoChannelId::SoundIoChannelIdTopBackRight,
            ChannelId::BackLeftCenter => raw::SoundIoChannelId::SoundIoChannelIdBackLeftCenter,
            ChannelId::BackRightCenter => raw::SoundIoChannelId::SoundIoChannelIdBackRightCenter,
            ChannelId::FrontLeftWide => raw::SoundIoChannelId::SoundIoChannelIdFrontLeftWide,
            ChannelId::FrontRightWide => raw::SoundIoChannelId::SoundIoChannelIdFrontRightWide,
            ChannelId::FrontLeftHigh => raw::SoundIoChannelId::SoundIoChannelIdFrontLeftHigh,
            ChannelId::FrontCenterHigh => raw::SoundIoChannelId::SoundIoChannelIdFrontCenterHigh,
            ChannelId::FrontRightHigh => raw::SoundIoChannelId::SoundIoChannelIdFrontRightHigh,
            ChannelId::TopFrontLeftCenter => {
                raw::SoundIoChannelId::SoundIoChannelIdTopFrontLeftCenter
            }
            ChannelId::TopFrontRightCenter => {
                raw::SoundIoChannelId::SoundIoChannelIdTopFrontRightCenter
            }
            ChannelId::TopSideLeft => raw::SoundIoChannelId::SoundIoChannelIdTopSideLeft,
            ChannelId::TopSideRight => raw::SoundIoChannelId::SoundIoChannelIdTopSideRight,
            ChannelId::LeftLfe => raw::SoundIoChannelId::SoundIoChannelIdLeftLfe,
            ChannelId::RightLfe => raw::SoundIoChannelId::SoundIoChannelIdRightLfe,
            ChannelId::Lfe2 => raw::SoundIoChannelId::SoundIoChannelIdLfe2,
            ChannelId::BottomCenter => raw::SoundIoChannelId::SoundIoChannelIdBottomCenter,
            ChannelId::BottomLeftCenter => raw::SoundIoChannelId::SoundIoChannelIdBottomLeftCenter,
            ChannelId::BottomRightCenter => {
                raw::SoundIoChannelId::SoundIoChannelIdBottomRightCenter
            }
            ChannelId::MsMid => raw::SoundIoChannelId::SoundIoChannelIdMsMid,
            ChannelId::MsSide => raw::SoundIoChannelId::SoundIoChannelIdMsSide,
            ChannelId::AmbisonicW => raw::SoundIoChannelId::SoundIoChannelIdAmbisonicW,
            ChannelId::AmbisonicX => raw::SoundIoChannelId::SoundIoChannelIdAmbisonicX,
            ChannelId::AmbisonicY => raw::SoundIoChannelId::SoundIoChannelIdAmbisonicY,
            ChannelId::AmbisonicZ => raw::SoundIoChannelId::SoundIoChannelIdAmbisonicZ,
            ChannelId::XyX => raw::SoundIoChannelId::SoundIoChannelIdXyX,
            ChannelId::XyY => raw::SoundIoChannelId::SoundIoChannelIdXyY,
            ChannelId::HeadphonesLeft => raw::SoundIoChannelId::SoundIoChannelIdHeadphonesLeft,
            ChannelId::HeadphonesRight => raw::SoundIoChannelId::SoundIoChannelIdHeadphonesRight,
            ChannelId::ClickTrack => raw::SoundIoChannelId::SoundIoChannelIdClickTrack,
            ChannelId::ForeignLanguage => raw::SoundIoChannelId::SoundIoChannelIdForeignLanguage,
            ChannelId::HearingImpaired => raw::SoundIoChannelId::SoundIoChannelIdHearingImpaired,
            ChannelId::Narration => raw::SoundIoChannelId::SoundIoChannelIdNarration,
            ChannelId::Haptic => raw::SoundIoChannelId::SoundIoChannelIdHaptic,
            ChannelId::DialogCentricMix => raw::SoundIoChannelId::SoundIoChannelIdDialogCentricMix,
            ChannelId::Aux => raw::SoundIoChannelId::SoundIoChannelIdAux,
            ChannelId::Aux0 => raw::SoundIoChannelId::SoundIoChannelIdAux0,
            ChannelId::Aux1 => raw::SoundIoChannelId::SoundIoChannelIdAux1,
            ChannelId::Aux2 => raw::SoundIoChannelId::SoundIoChannelIdAux2,
            ChannelId::Aux3 => raw::SoundIoChannelId::SoundIoChannelIdAux3,
            ChannelId::Aux4 => raw::SoundIoChannelId::SoundIoChannelIdAux4,
            ChannelId::Aux5 => raw::SoundIoChannelId::SoundIoChannelIdAux5,
            ChannelId::Aux6 => raw::SoundIoChannelId::SoundIoChannelIdAux6,
            ChannelId::Aux7 => raw::SoundIoChannelId::SoundIoChannelIdAux7,
            ChannelId::Aux8 => raw::SoundIoChannelId::SoundIoChannelIdAux8,
            ChannelId::Aux9 => raw::SoundIoChannelId::SoundIoChannelIdAux9,
            ChannelId::Aux10 => raw::SoundIoChannelId::SoundIoChannelIdAux10,
            ChannelId::Aux11 => raw::SoundIoChannelId::SoundIoChannelIdAux11,
            ChannelId::Aux12 => raw::SoundIoChannelId::SoundIoChannelIdAux12,
            ChannelId::Aux13 => raw::SoundIoChannelId::SoundIoChannelIdAux13,
            ChannelId::Aux14 => raw::SoundIoChannelId::SoundIoChannelIdAux14,
            ChannelId::Aux15 => raw::SoundIoChannelId::SoundIoChannelIdAux15,
            _ => raw::SoundIoChannelId::SoundIoChannelIdInvalid,
        }
    }
}

impl fmt::Display for ChannelId {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // In the C source these only use ASCII characters so it is technically ambiguous
        // whether this is UTF-8 or Latin1.
        let s = latin1_to_string(unsafe { raw::soundio_get_channel_name((*self).into()) });
        f.write_str(&s)
    }
}

impl ChannelId {
    /// Given UTF-8 encoded text which is the name of a channel such as
    /// "Front Left", "FL", or "front-left", return the corresponding
    /// `ChannelId`. Returns `None` for no match.
    ///
    /// # Examples
    ///
    /// ```
    /// # use soundio::*;
    /// assert_eq!(ChannelId::parse("Front Left Center"), Some(ChannelId::FrontLeftCenter));
    /// assert_eq!(ChannelId::parse("FLC"), Some(ChannelId::FrontLeftCenter));
    /// assert_eq!(ChannelId::parse("front-left-of-center"), Some(ChannelId::FrontLeftCenter));
    /// assert_eq!(ChannelId::parse("Shot is the best!"), None);
    /// ```
    pub fn parse(id: &str) -> Option<ChannelId> {
        match unsafe { raw::soundio_parse_channel_id(id.as_ptr() as _, id.len() as _) } {
            raw::SoundIoChannelId::SoundIoChannelIdInvalid => None,
            x => Some(x.into()),
        }
    }
}