Skip to content

Several fixes / improvements #18

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 15 commits into from
11 changes: 6 additions & 5 deletions src/backend/winmm/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use winmm_sys::midiInAddBuffer;
use super::HandlerData;
use ::Ignore;

pub extern "C" fn handle_input<T>(_: HMIDIIN,
pub extern "system" fn handle_input<T>(_: HMIDIIN,
input_status: UINT,
instance_ptr: DWORD_PTR,
midi_message: DWORD_PTR,
Expand Down Expand Up @@ -46,15 +46,16 @@ pub extern "C" fn handle_input<T>(_: HMIDIIN,
} else { 1 };

// Copy bytes to our MIDI message.
let ptr = (&midi_message) as *const DWORD_PTR as *const u8;
//let ptr = (&midi_message) as *const u64 as *const u8;
let ptr = (&midi_message) as *const _ as *const u8;
let bytes: &[u8] = unsafe { slice::from_raw_parts(ptr, nbytes as usize) };
data.message.bytes.push_all(bytes);
data.message.bytes.extend_from_slice(bytes);
} else { // Sysex message (MIM_LONGDATA or MIM_LONGERROR)
let sysex = unsafe { &*(midi_message as *const MIDIHDR) };
if !data.ignore_flags.contains(Ignore::Sysex) && input_status != MM_MIM_LONGERROR {
// Sysex message and we're not ignoring it
let bytes: &[u8] = unsafe { slice::from_raw_parts(sysex.lpData as *const u8, sysex.dwBytesRecorded as usize) };
data.message.bytes.push_all(bytes);
data.message.bytes.extend_from_slice(bytes);
// TODO: If sysex messages are longer than RT_SYSEX_BUFFER_SIZE, they
// are split in chunks. We could reassemble a single message.
}
Expand Down Expand Up @@ -84,4 +85,4 @@ pub extern "C" fn handle_input<T>(_: HMIDIIN,

// Clear the vector for the next input message.
data.message.bytes.clear();
}
}
50 changes: 25 additions & 25 deletions src/backend/winmm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ use std::ffi::OsString;
use std::os::windows::ffi::OsStringExt;
use std::sync::{Mutex};
use std::io::{stderr, Write};
use std::thread::sleep_ms;
use std::thread::sleep;
use std::time::Duration;
use alloc::heap;

use winapi::*;
Expand Down Expand Up @@ -88,20 +89,14 @@ impl MidiInput {
}

pub fn port_name(&self, port_number: u32) -> Result<String, PortInfoError> {
use std::fmt::Write;

let mut device_caps: MIDIINCAPSW = unsafe { mem::uninitialized() };
let result = unsafe { midiInGetDevCapsW(port_number as UINT_PTR, &mut device_caps, mem::size_of::<MIDIINCAPSW>() as u32) };
if result == MMSYSERR_BADDEVICEID {
return Err(PortInfoError::PortNumberOutOfRange)
} else if result == MMSYSERR_ERROR {
return Err(PortInfoError::CannotRetrievePortName);
}
assert!(result == MMSYSERR_NOERROR, "could not retrieve Windows MM MIDI input port name");
let mut output = from_wide_ptr(device_caps.szPname.as_ptr(), device_caps.szPname.len()).to_string_lossy().into_owned();

// Next lines added to add the portNumber to the name so that
// the device's names are sure to be listed with individual names
// even when they have the same brand name
let _ = write!(&mut output, " {}", port_number);
let output = from_wide_ptr(device_caps.szPname.as_ptr(), device_caps.szPname.len()).to_string_lossy().into_owned();
Ok(output)
}

Expand Down Expand Up @@ -241,20 +236,14 @@ impl MidiOutput {
}

pub fn port_name(&self, port_number: u32) -> Result<String, PortInfoError> {
use std::fmt::Write;

let mut device_caps: MIDIOUTCAPSW = unsafe { mem::uninitialized() };
let result = unsafe { midiOutGetDevCapsW(port_number as UINT_PTR, &mut device_caps, mem::size_of::<MIDIINCAPSW>() as u32) };
if result == MMSYSERR_BADDEVICEID {
return Err(PortInfoError::PortNumberOutOfRange)
return Err(PortInfoError::PortNumberOutOfRange);
} else if result == MMSYSERR_ERROR {
return Err(PortInfoError::CannotRetrievePortName);
}
assert!(result == MMSYSERR_NOERROR, "could not retrieve Windows MM MIDI output port name");
let mut output = from_wide_ptr(device_caps.szPname.as_ptr(), device_caps.szPname.len()).to_string_lossy().into_owned();

// Next lines added to add the portNumber to the name so that
// the device's names are sure to be listed with individual names
// even when they have the same brand name
let _ = write!(&mut output, " {}", port_number);
let output = from_wide_ptr(device_caps.szPname.as_ptr(), device_caps.szPname.len()).to_string_lossy().into_owned();
Ok(output)
}

Expand Down Expand Up @@ -313,7 +302,7 @@ impl MidiOutputConnection {
loop {
let result = unsafe { midiOutLongMsg(self.out_handle, &mut sysex, mem::size_of::<MIDIHDR>() as u32) };
if result == MIDIERR_NOTREADY {
sleep_ms(1);
sleep(Duration::from_millis(1));
continue;
} else {
if result != MMSYSERR_NOERROR {
Expand All @@ -326,7 +315,7 @@ impl MidiOutputConnection {
loop {
let result = unsafe { midiOutUnprepareHeader(self.out_handle, &mut sysex, mem::size_of::<MIDIHDR>() as u32) };
if result == MIDIERR_STILLPLAYING {
sleep_ms(1);
sleep(Duration::from_millis(1));
continue;
} else { break; }
}
Expand All @@ -347,7 +336,7 @@ impl MidiOutputConnection {
loop {
let result = unsafe { midiOutShortMsg(self.out_handle, packet) };
if result == MIDIERR_NOTREADY {
sleep_ms(1);
sleep(Duration::from_millis(1));
continue;
} else {
if result != MMSYSERR_NOERROR {
Expand All @@ -357,9 +346,20 @@ impl MidiOutputConnection {
}
}
}

Ok(())
}
pub fn send_short_message(&mut self, message: u32) -> Result<(), SendError> {
loop {
let result = unsafe { midiOutShortMsg(self.out_handle, message) };
if result == MMSYSERR_NOERROR {
return Ok(());
} else if result == MIDIERR_NOTREADY {
sleep(Duration::from_millis(1));
} else {
return Err(SendError::Other("sending short message failed"));
}
}
}
}

impl Drop for MidiOutputConnection {
Expand All @@ -369,4 +369,4 @@ impl Drop for MidiOutputConnection {
midiOutClose(self.out_handle);
}
}
}
}
5 changes: 5 additions & 0 deletions src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,4 +125,9 @@ impl MidiOutputConnection {
pub fn send(&mut self, message: &[u8]) -> Result<(), SendError> {
self.imp.send(message)
}

#[cfg(target_os="windows")]
pub fn send_short_message(&mut self, message: u32) -> Result<(), SendError> {
self.imp.send_short_message(message)
}
}
2 changes: 2 additions & 0 deletions src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,14 @@ impl fmt::Display for InitError {
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PortInfoError {
PortNumberOutOfRange,
CannotRetrievePortName,
}

impl Error for PortInfoError {
fn description(&self) -> &str {
match *self {
PortInfoError::PortNumberOutOfRange => PORT_OUT_OF_RANGE_MSG,
PortInfoError::CannotRetrievePortName => "could not retrieve Windows MM MIDI output port name",
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#![cfg_attr(windows, feature(vec_push_all, alloc, heap_api))]
#![cfg_attr(windows, feature(alloc, heap_api))]

#[macro_use]
extern crate bitflags;
Expand Down Expand Up @@ -69,4 +69,4 @@ pub use errors::*;
mod common;
pub use common::*;

mod backend;
mod backend;