use crate::{
error::{ParameterError, RytmError},
object::global::types::{RoutingUsbInOptions, RoutingUsbOutOptions, RoutingUsbToMainDb},
};
use rytm_rs_macro::parameter_range;
use rytm_sys::ar_global_t;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub struct Routing {
route_to_main_flags: u16,
send_to_fx_flags: u16,
usb_in: RoutingUsbInOptions,
usb_out: RoutingUsbOutOptions,
usb_to_main_db: RoutingUsbToMainDb,
}
impl Default for Routing {
fn default() -> Self {
Self {
route_to_main_flags: 0b0000_1111_1111_1111,
send_to_fx_flags: 0b0000_1111_1111_1111,
usb_in: RoutingUsbInOptions::default(),
usb_out: RoutingUsbOutOptions::default(),
usb_to_main_db: RoutingUsbToMainDb::default(),
}
}
}
impl TryFrom<&ar_global_t> for Routing {
type Error = RytmError;
fn try_from(raw_global: &ar_global_t) -> Result<Self, Self::Error> {
Ok(Self {
route_to_main_flags: ((raw_global.route_to_main_msb as u16) << 8)
| raw_global.route_to_main_lsb as u16,
send_to_fx_flags: ((raw_global.send_to_fx_msb as u16) << 8)
| raw_global.send_to_fx_lsb as u16,
usb_in: raw_global.usb_in.try_into()?,
usb_out: raw_global.usb_out.try_into()?,
usb_to_main_db: raw_global.usb_to_main_db.try_into()?,
})
}
}
impl Routing {
pub(crate) fn apply_to_raw_global(&self, raw_global: &mut ar_global_t) {
raw_global.route_to_main_msb = (self.route_to_main_flags >> 8) as u8;
raw_global.route_to_main_lsb = self.route_to_main_flags as u8;
raw_global.send_to_fx_msb = (self.send_to_fx_flags >> 8) as u8;
raw_global.send_to_fx_lsb = self.send_to_fx_flags as u8;
raw_global.usb_in = self.usb_in.into();
raw_global.usb_out = self.usb_out.into();
raw_global.usb_to_main_db = self.usb_to_main_db.into();
}
#[parameter_range(range = "route_to_main_flags:0..=4095")]
pub fn set_route_to_main_flags(&mut self, route_to_main_flags: u16) -> Result<(), RytmError> {
self.route_to_main_flags = route_to_main_flags;
Ok(())
}
#[parameter_range(range = "track_index:0..=11")]
pub fn route_track_to_main(&mut self, track_index: usize) -> Result<(), RytmError> {
self.route_to_main_flags |= 1 << track_index;
Ok(())
}
#[parameter_range(range = "track_index:0..=11")]
pub fn clear_routing_of_a_track_to_main(
&mut self,
track_index: usize,
) -> Result<(), RytmError> {
self.route_to_main_flags &= !(1 << track_index);
Ok(())
}
#[parameter_range(range = "send_to_fx_flags:0..=4095")]
pub fn set_send_to_fx_flags(&mut self, send_to_fx_flags: u16) -> Result<(), RytmError> {
self.send_to_fx_flags = send_to_fx_flags;
Ok(())
}
#[parameter_range(range = "track_index:0..=11")]
pub fn send_track_to_fx(&mut self, track_index: usize) -> Result<(), RytmError> {
self.send_to_fx_flags |= 1 << track_index;
Ok(())
}
#[parameter_range(range = "track_index:0..=11")]
pub fn clear_sending_of_a_track_to_fx(&mut self, track_index: usize) -> Result<(), RytmError> {
self.send_to_fx_flags &= !(1 << track_index);
Ok(())
}
pub fn set_usb_in(&mut self, usb_in: RoutingUsbInOptions) {
self.usb_in = usb_in;
}
pub fn set_usb_out(&mut self, usb_out: RoutingUsbOutOptions) {
self.usb_out = usb_out;
}
pub fn set_usb_to_main_db(&mut self, usb_to_main_db: RoutingUsbToMainDb) {
self.usb_to_main_db = usb_to_main_db;
}
pub const fn raw_route_to_main_flags(&self) -> u16 {
self.route_to_main_flags
}
pub fn track_indexes_routed_to_main(&self) -> Vec<usize> {
let mut routed = Vec::new();
for track_index in 0..=11 {
if self.route_to_main_flags & (1 << track_index) != 0 {
routed.push(track_index);
}
}
routed
}
pub fn track_indexes_not_routed_to_main(&self) -> Vec<usize> {
let mut not_routed = Vec::new();
for track_index in 0..=11 {
if self.route_to_main_flags & (1 << track_index) == 0 {
not_routed.push(track_index);
}
}
not_routed
}
pub const fn is_track_routed_to_main(&self, track_index: usize) -> bool {
self.route_to_main_flags & (1 << track_index) != 0
}
pub const fn raw_send_to_fx_flags(&self) -> u16 {
self.send_to_fx_flags
}
pub fn track_indexes_sent_to_fx(&self) -> Vec<usize> {
let mut sent = Vec::new();
for track_index in 0..=11 {
if self.send_to_fx_flags & (1 << track_index) != 0 {
sent.push(track_index);
}
}
sent
}
pub fn track_indexes_not_sent_to_fx(&self) -> Vec<usize> {
let mut not_sent = Vec::new();
for track_index in 0..=11 {
if self.send_to_fx_flags & (1 << track_index) == 0 {
not_sent.push(track_index);
}
}
not_sent
}
pub const fn is_track_sent_to_fx(&self, track_index: usize) -> bool {
self.send_to_fx_flags & (1 << track_index) != 0
}
pub const fn usb_in(&self) -> RoutingUsbInOptions {
self.usb_in
}
pub const fn usb_out(&self) -> RoutingUsbOutOptions {
self.usb_out
}
pub const fn usb_to_main_db(&self) -> RoutingUsbToMainDb {
self.usb_to_main_db
}
}