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
use std::os::raw::c_int;
use std::convert::{From, Into};
use std::result;
use std::fmt;

use ffi;

pub type PortMidiDeviceId = c_int;

/// PortMidi result type.
pub type Result<T> = result::Result<T, Error>;
impl From<ffi::PmError> for Result<()> {
    fn from(err: ffi::PmError) -> Self {
        match err {
            ffi::PmError::PmNoError | ffi::PmError::PmGotData => Ok(()),
            _ => Err(Error::PortMidi(err)),
        }
    }
}

/// PortMidi error type.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Error {
    PortMidi(ffi::PmError),
    Unknown,
    Unimplemented,
    NoDefaultDevice,
    NotAnInputDevice,
    NotAnOutputDevice,
    Invalid,
}
impl From<ffi::PmError> for Error {
    fn from(err: ffi::PmError) -> Self {
        match err {
            err @ _ => Error::PortMidi(err),
        }
    }
}
impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::PortMidi(pm_err) => write!(f, "{}", pm_err),
            err @ _ => write!(f, "{:?}", err),
        }
    }
}


/// Represents a Midi message.
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct MidiMessage {
    pub status: u8,
    pub data1: u8,
    pub data2: u8,
}
impl From<[u8; 3]> for MidiMessage {
    fn from(raw: [u8; 3]) -> Self {
        MidiMessage {
            status: raw[0],
            data1: raw[1],
            data2: raw[2],
        }
    }
}
impl fmt::Display for MidiMessage {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
               "status: {}, data: {}, {}",
               self.status,
               self.data1,
               self.data2)
    }
}
/// Converts a `PmMessage` to a `MidiMessage.
/// This can be used for `c_int` as well as `i32` because these are only type aliases.
impl From<ffi::PmMessage> for MidiMessage {
    fn from(raw: i32) -> Self {
        MidiMessage {
            status: (raw & 0x00_00_00_FF) as u8,
            data1: ((raw & 0x00_00_FF_00) >> 8) as u8,
            data2: ((raw & 0x00_FF_00_00) >> 16) as u8,
        }
    }
}
impl Into<ffi::PmMessage> for MidiMessage {
    fn into(self) -> i32 {
        (((self.data2 as i32) << 16)) | (((self.data1 as i32) << 8)) | self.status as i32
    }
}

/// Represents a time stamped midi event. See also `MidiMessage`
///
/// See the PortMidi documentation for how SysEx and midi realtime messages
/// are handled
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct MidiEvent {
    pub message: MidiMessage,
    pub timestamp: ffi::PmTimestamp,
}
impl From<ffi::PmEvent> for MidiEvent {
    fn from(raw: ffi::PmEvent) -> Self {
        MidiEvent {
            message: MidiMessage::from(raw.message),
            timestamp: raw.timestamp,
        }
    }
}
impl From<MidiMessage> for MidiEvent {
    fn from(msg: MidiMessage) -> Self {
        MidiEvent {
            message: msg,
            timestamp: 0,
        }
    }
}
impl Into<ffi::PmEvent> for MidiEvent {
    fn into(self) -> ffi::PmEvent {
        ffi::PmEvent {
            message: MidiMessage::into(self.message),
            timestamp: self.timestamp,
        }
    }
}