use core_foundation::string::{CFString, CFStringRef};
use core_foundation::base::{TCFType, OSStatus};
use coremidi_sys::*;
use std::mem;
use Object;
pub trait PropertyGetter<T> {
fn value_from(&self, object: &Object) -> Result<T, OSStatus>;
}
pub trait PropertySetter<T> {
fn set_value(&self, object: &Object, value: T) -> Result<(), OSStatus>;
}
pub struct StringProperty(CFStringRef);
impl StringProperty {
pub fn new(name: &str) -> Self {
StringProperty(CFString::new(name).as_concrete_TypeRef())
}
}
impl<T> PropertyGetter<T> for StringProperty where T: From<String> {
fn value_from(&self, object: &Object) -> Result<T, OSStatus> {
unsafe {
let mut string_ref: CFStringRef = mem::uninitialized();
let status = MIDIObjectGetStringProperty(object.0, self.0, &mut string_ref);
if status == 0 {
let string: CFString = TCFType::wrap_under_create_rule(string_ref);
Ok(From::<String>::from(format!("{}", string)))
}
else { Err(status) }
}
}
}
impl<'a, T> PropertySetter<T> for StringProperty where T: Into<String> {
fn set_value(&self, object: &Object, value: T) -> Result<(), OSStatus> {
unsafe {
let value: String = value.into();
let string = CFString::new(&value);
let string_ref = string.as_concrete_TypeRef();
let status = MIDIObjectSetStringProperty(object.0, self.0, string_ref);
if status == 0 { Ok(()) } else { Err(status) }
}
}
}
pub struct IntegerProperty(CFStringRef);
impl IntegerProperty {
pub fn new(name: &str) -> Self {
IntegerProperty(CFString::new(name).as_concrete_TypeRef())
}
}
impl<T> PropertyGetter<T> for IntegerProperty where T: From<SInt32> {
fn value_from(&self, object: &Object) -> Result<T, OSStatus> {
unsafe {
let mut value: SInt32 = mem::uninitialized();
let status = MIDIObjectGetIntegerProperty(object.0, self.0, &mut value);
if status == 0 { Ok(From::from(value)) } else { Err(status) }
}
}
}
impl <T> PropertySetter<T> for IntegerProperty where T: Into<SInt32> {
fn set_value(&self, object: &Object, value: T) -> Result<(), OSStatus> {
unsafe {
let status = MIDIObjectSetIntegerProperty(object.0, self.0, value.into());
if status == 0 { Ok(()) } else { Err(status) }
}
}
}
pub struct BooleanProperty(CFStringRef);
impl BooleanProperty {
pub fn new(name: &str) -> Self {
BooleanProperty(CFString::new(name).as_concrete_TypeRef())
}
}
impl<T> PropertyGetter<T> for BooleanProperty where T: From<bool> {
fn value_from(&self, object: &Object) -> Result<T, OSStatus> {
unsafe {
let mut value: SInt32 = mem::uninitialized();
let status = MIDIObjectGetIntegerProperty(object.0, self.0, &mut value);
if status == 0 { Ok(From::from(value == 1)) } else { Err(status) }
}
}
}
impl<T> PropertySetter<T> for BooleanProperty where T: Into<bool> {
fn set_value(&self, object: &Object, value: T) -> Result<(), OSStatus> {
unsafe {
let value: SInt32 = if value.into() { 1 } else { 0 };
let status = MIDIObjectSetIntegerProperty(object.0, self.0, value);
if status == 0 { Ok(()) } else { Err(status) }
}
}
}
pub struct Properties;
impl Properties {
pub fn name() -> StringProperty { unsafe { StringProperty(kMIDIPropertyName) } }
pub fn manufacturer() -> StringProperty { unsafe { StringProperty(kMIDIPropertyManufacturer) } }
pub fn model() -> StringProperty { unsafe { StringProperty(kMIDIPropertyModel) } }
pub fn unique_id() -> IntegerProperty { unsafe { IntegerProperty(kMIDIPropertyUniqueID) } }
pub fn device_id() -> IntegerProperty { unsafe { IntegerProperty(kMIDIPropertyDeviceID) } }
pub fn receive_channels() -> IntegerProperty { unsafe { IntegerProperty(kMIDIPropertyReceiveChannels) } }
pub fn transmit_channels() -> IntegerProperty { unsafe { IntegerProperty(kMIDIPropertyTransmitChannels) } }
pub fn max_sysex_speed() -> IntegerProperty { unsafe { IntegerProperty(kMIDIPropertyMaxSysExSpeed) } }
pub fn advance_schedule_time_musec() -> IntegerProperty { unsafe { IntegerProperty(kMIDIPropertyAdvanceScheduleTimeMuSec) } }
pub fn is_embedded_entity() -> BooleanProperty { unsafe { BooleanProperty(kMIDIPropertyIsEmbeddedEntity) } }
pub fn is_broadcast() -> BooleanProperty { unsafe { BooleanProperty(kMIDIPropertyIsBroadcast) } }
pub fn single_realtime_entity() -> IntegerProperty { unsafe { IntegerProperty(kMIDIPropertySingleRealtimeEntity) } }
pub fn connection_unique_id() -> IntegerProperty { unsafe { IntegerProperty(kMIDIPropertyConnectionUniqueID) } }
pub fn offline() -> BooleanProperty { unsafe { BooleanProperty(kMIDIPropertyOffline) } }
pub fn private() -> BooleanProperty { unsafe { BooleanProperty(kMIDIPropertyPrivate) } }
pub fn driver_owner() -> StringProperty { unsafe { StringProperty(kMIDIPropertyDriverOwner) } }
pub fn driver_version() -> IntegerProperty { unsafe { IntegerProperty(kMIDIPropertyDriverVersion) } }
pub fn supports_general_midi() -> BooleanProperty { unsafe { BooleanProperty(kMIDIPropertySupportsGeneralMIDI) } }
pub fn supports_mmc() -> BooleanProperty { unsafe { BooleanProperty(kMIDIPropertySupportsMMC) } }
pub fn can_route() -> BooleanProperty { unsafe { BooleanProperty(kMIDIPropertyCanRoute) } }
pub fn receives_clock() -> BooleanProperty { unsafe { BooleanProperty(kMIDIPropertyReceivesClock) } }
pub fn receives_mtc() -> BooleanProperty { unsafe { BooleanProperty(kMIDIPropertyReceivesMTC) } }
pub fn receives_notes() -> BooleanProperty { unsafe { BooleanProperty(kMIDIPropertyReceivesNotes) } }
pub fn receives_program_changes() -> BooleanProperty { unsafe { BooleanProperty(kMIDIPropertyReceivesProgramChanges) } }
pub fn receives_bank_select_msb() -> BooleanProperty { unsafe { BooleanProperty(kMIDIPropertyReceivesBankSelectMSB) } }
pub fn receives_bank_select_lsb() -> BooleanProperty { unsafe { BooleanProperty(kMIDIPropertyReceivesBankSelectLSB) } }
pub fn transmits_bank_select_msb() -> BooleanProperty { unsafe { BooleanProperty(kMIDIPropertyTransmitsBankSelectMSB) } }
pub fn transmits_bank_select_lsb() -> BooleanProperty { unsafe { BooleanProperty(kMIDIPropertyTransmitsBankSelectLSB) } }
pub fn transmits_clock() -> BooleanProperty { unsafe { BooleanProperty(kMIDIPropertyTransmitsClock) } }
pub fn transmits_mtc() -> BooleanProperty { unsafe { BooleanProperty(kMIDIPropertyTransmitsMTC) } }
pub fn transmits_notes() -> BooleanProperty { unsafe { BooleanProperty(kMIDIPropertyTransmitsNotes) } }
pub fn transmits_program_changes() -> BooleanProperty { unsafe { BooleanProperty(kMIDIPropertyTransmitsProgramChanges) } }
pub fn pan_disrupts_stereo() -> BooleanProperty { unsafe { BooleanProperty(kMIDIPropertyPanDisruptsStereo) } }
pub fn is_sampler() -> BooleanProperty { unsafe { BooleanProperty(kMIDIPropertyIsSampler) } }
pub fn is_drum_machine() -> BooleanProperty { unsafe { BooleanProperty(kMIDIPropertyIsDrumMachine) } }
pub fn is_mixer() -> BooleanProperty { unsafe { BooleanProperty(kMIDIPropertyIsMixer) } }
pub fn is_effect_unit() -> BooleanProperty { unsafe { BooleanProperty(kMIDIPropertyIsEffectUnit) } }
pub fn max_receive_channels() -> IntegerProperty { unsafe { IntegerProperty(kMIDIPropertyMaxReceiveChannels) } }
pub fn max_transmit_channels() -> IntegerProperty { unsafe { IntegerProperty(kMIDIPropertyMaxTransmitChannels) } }
pub fn driver_device_editor_app() -> StringProperty { unsafe { StringProperty(kMIDIPropertyDriverDeviceEditorApp) } }
pub fn supports_show_control() -> BooleanProperty { unsafe { BooleanProperty(kMIDIPropertySupportsShowControl) } }
pub fn display_name() -> StringProperty { unsafe { StringProperty(kMIDIPropertyDisplayName) } }
}