#![allow(
clippy::cast_lossless,
clippy::cast_possible_truncation,
clippy::cast_sign_loss
)]
mod global;
mod kit;
mod pattern;
mod raw;
mod settings;
mod song;
mod sound;
pub use global::GlobalQuery;
pub use kit::KitQuery;
pub use pattern::PatternQuery;
pub use raw::RawQuery;
pub use settings::SettingsQuery;
pub use song::SongQuery;
pub use sound::SoundQuery;
const RYTM_SYSEX_QUERY_SIZE: usize = rytm_sys::AR_SYSEX_REQUEST_MSG_SZ as usize;
use super::error::{RytmError, SysexConversionError};
use crate::{
sysex::{AnySysexType, SysexMeta},
SysexCompatible,
};
pub trait ObjectQuery: SysexCompatible + Send + Sync {
fn sysex_type(&self) -> AnySysexType;
fn device_id(&self) -> u8;
fn obj_nr(&self) -> u16;
fn as_sysex_meta(&self) -> SysexMeta {
SysexMeta {
container_version: 0x0101,
dev_id: self.device_id(),
obj_type: ObjectQuery::sysex_type(self).into(),
obj_nr: self.obj_nr(),
chksum: 0,
data_size: 0,
}
}
fn is_targeting_work_buffer(&self) -> bool {
self.obj_nr() >= 128
}
}
impl<T: ObjectQuery> SysexCompatible for T {
fn sysex_type(&self) -> AnySysexType {
ObjectQuery::sysex_type(self)
}
fn as_sysex(&self) -> Result<Vec<u8>, RytmError> {
let mut buffer = vec![0; RYTM_SYSEX_QUERY_SIZE];
let destination_buffer = buffer.as_mut_slice();
let meta: rytm_sys::ar_sysex_meta_t = self.as_sysex_meta().into();
#[allow(clippy::cast_possible_truncation)]
unsafe {
let return_code = rytm_sys::ar_sysex_request(
destination_buffer.as_mut_ptr(),
std::ptr::addr_of!(meta),
) as u8;
if return_code != 0 {
return Err(SysexConversionError::from(return_code).into());
}
}
Ok(buffer)
}
}