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
use crate::{MidiInputDeviceId, TryFromRawError};
use helgoboss_midi::Channel;
use std::convert::TryInto;
/// Recording input of a track.
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
pub enum RecordingInput {
/// Index refers to a single mono channel.
Mono(u32),
/// Index refers to a single ReaRoute mono channel.
MonoReaRoute(u32),
/// Index refers to the first of two channels in a stereo channel pair.
Stereo(u32),
/// Index refers to the first of two channels in a ReaRoute stereo channel pair.
StereoReaRoute(u32),
Midi {
device_id: Option<MidiInputDeviceId>,
channel: Option<Channel>,
},
}
impl RecordingInput {
/// Converts an integer as returned by the low-level API to a recording input.
///
/// # Errors
///
/// Fails if the given integer is not a valid recording input index.
pub fn try_from_raw(rec_input_index: i32) -> Result<RecordingInput, TryFromRawError<i32>> {
use RecordingInput::*;
let v: u32 = rec_input_index.try_into().map_err(|_| {
TryFromRawError::new("couldn't convert to recording input", rec_input_index)
})?;
match v {
0..=511 => Ok(Mono(v)),
512..=1023 => Ok(MonoReaRoute(v - 512)),
1024..=1535 => Ok(Stereo(v - 1024)),
1536..=2047 => Ok(StereoReaRoute(v - 1536)),
2048..=4095 => Err(TryFromRawError::new(
"couldn't convert to recording input",
rec_input_index,
)),
4096..=6128 => {
let midi_index = v - 4096;
Ok(Midi {
device_id: {
let raw_device_id = midi_index / 32;
if raw_device_id == ALL_MIDI_DEVICES_FACTOR {
None
} else {
Some(MidiInputDeviceId::new(raw_device_id as u8))
}
},
channel: {
let channel_id = midi_index % 32;
if channel_id == 0 {
None
} else {
let ch = channel_id - 1;
ch.try_into().ok()
}
},
})
}
_ => Err(TryFromRawError::new(
"couldn't convert to recording input",
rec_input_index,
)),
}
}
/// Converts this value to an integer as expected by the low-level API.
pub fn to_raw(&self) -> i32 {
use RecordingInput::*;
let result = match *self {
Mono(i) => i,
MonoReaRoute(i) => 512 + i,
Stereo(i) => 1024 + i,
StereoReaRoute(i) => 1536 + i,
Midi { device_id, channel } => {
let device_high = match device_id {
None => ALL_MIDI_DEVICES_FACTOR,
Some(id) => id.get() as u32,
};
let channel_low = match channel {
None => 0,
Some(ch) => u32::from(ch) + 1,
};
4096 + (device_high * 32 + channel_low)
}
};
result as i32
}
}
const ALL_MIDI_DEVICES_FACTOR: u32 = 63;