24 #include "JackError.h"    26 #include "JackMidiUtil.h"    27 #include "JackWinMMEInputPort.h"    28 #include "JackMidiWriteQueue.h"    37 JackWinMMEInputPort::HandleMidiInputEvent(HMIDIIN handle, UINT message,
    38                                           DWORD port, DWORD param1,
    48 JackWinMMEInputPort::JackWinMMEInputPort(
const char *alias_name,
    49                                          const char *client_name,
    50                                          const char *driver_name, UINT index,
    51                                          size_t max_bytes, 
size_t max_messages)
    53     thread_queue = 
new JackMidiAsyncQueue(max_bytes, max_messages);
    54     std::auto_ptr<JackMidiAsyncQueue> thread_queue_ptr(thread_queue);
    55     write_queue = 
new JackMidiBufferWriteQueue();
    56     std::auto_ptr<JackMidiBufferWriteQueue> write_queue_ptr(write_queue);
    57     sysex_buffer = 
new jack_midi_data_t[max_bytes];
    58     char error_message[MAXERRORLENGTH];
    59     MMRESULT result = midiInOpen(&handle, index,
    60                                  (DWORD_PTR) HandleMidiInputEvent,
    62                                  CALLBACK_FUNCTION | MIDI_IO_STATUS);
    63     if (result != MMSYSERR_NOERROR) {
    64         GetInErrorString(result, error_message);
    65         goto delete_sysex_buffer;
    67     sysex_header.dwBufferLength = max_bytes;
    68     sysex_header.dwFlags = 0;
    69     sysex_header.lpData = (LPSTR)sysex_buffer;
    70     result = midiInPrepareHeader(handle, &sysex_header, 
sizeof(MIDIHDR));
    71     if (result != MMSYSERR_NOERROR) {
    72         GetInErrorString(result, error_message);
    75     result = midiInAddBuffer(handle, &sysex_header, 
sizeof(MIDIHDR));
    76     if (result != MMSYSERR_NOERROR) {
    77         GetInErrorString(result, error_message);
    78         goto unprepare_header;
    81     MIDIINCAPS capabilities;
    83     result = midiInGetDevCaps(index, &capabilities, 
sizeof(capabilities));
    84     if (result != MMSYSERR_NOERROR) {
    85         WriteInError(
"JackWinMMEInputPort [constructor]", 
"midiInGetDevCaps",
    87         name_tmp = (
char*) driver_name;
    89         name_tmp = capabilities.szPname;
    92     snprintf(alias, 
sizeof(alias) - 1, 
"%s:%s:in%d", alias_name, name_tmp,
    94     snprintf(name, 
sizeof(name) - 1, 
"%s:capture_%d", client_name, index + 1);
    97     write_queue_ptr.release();
    98     thread_queue_ptr.release();
   102     result = midiInUnprepareHeader(handle, &sysex_header, 
sizeof(MIDIHDR));
   103     if (result != MMSYSERR_NOERROR) {
   104         WriteInError(
"JackWinMMEInputPort [constructor]",
   105                      "midiInUnprepareHeader", result);
   108     result = midiInClose(handle);
   109     if (result != MMSYSERR_NOERROR) {
   110         WriteInError(
"JackWinMMEInputPort [constructor]", 
"midiInClose",
   114     delete[] sysex_buffer;
   115     throw std::runtime_error(error_message);
   118 JackWinMMEInputPort::~JackWinMMEInputPort()
   120     MMRESULT result = midiInReset(handle);
   121     if (result != MMSYSERR_NOERROR) {
   122         WriteInError(
"JackWinMMEInputPort [destructor]", 
"midiInReset", result);
   124     result = midiInUnprepareHeader(handle, &sysex_header, 
sizeof(MIDIHDR));
   125     if (result != MMSYSERR_NOERROR) {
   126         WriteInError(
"JackWinMMEInputPort [destructor]",
   127                      "midiInUnprepareHeader", result);
   129     result = midiInClose(handle);
   130     if (result != MMSYSERR_NOERROR) {
   131         WriteInError(
"JackWinMMEInputPort [destructor]", 
"midiInClose", result);
   133     delete[] sysex_buffer;
   139 JackWinMMEInputPort::EnqueueMessage(DWORD timestamp, 
size_t length,
   140                                     jack_midi_data_t *data)
   142     jack_nframes_t frame =
   143         GetFramesFromTime(start_time + (((jack_time_t) timestamp) * 1000));
   146     jack_time_t current_time = GetMicroSeconds();
   147     jack_log(
"JackWinMMEInputPort::EnqueueMessage - enqueueing event at %f "   148              "(frame: %d) with start offset '%d' scheduled for frame '%d'",
   149              ((
double) current_time) / 1000.0, GetFramesFromTime(current_time),
   153     switch (thread_queue->
EnqueueEvent(frame, length, data)) {
   154     case JackMidiWriteQueue::BUFFER_FULL:
   155         jack_error(
"JackWinMMEInputPort::EnqueueMessage - The thread queue "   156                    "cannot currently accept a %d-byte event.  Dropping event.",
   159     case JackMidiWriteQueue::BUFFER_TOO_SMALL:
   160         jack_error(
"JackWinMMEInputPort::EnqueueMessage - The thread queue "   161                    "buffer is too small to enqueue a %d-byte event.  Dropping "   170 JackWinMMEInputPort::GetInErrorString(MMRESULT error, LPTSTR text)
   172     MMRESULT result = midiInGetErrorText(error, text, MAXERRORLENGTH);
   173     if (result != MMSYSERR_NOERROR) {
   174         snprintf(text, MAXERRORLENGTH, 
"Unknown error code '%d'", error);
   179 JackWinMMEInputPort::ProcessJack(JackMidiBuffer *port_buffer,
   180                                  jack_nframes_t frames)
   186     for (; jack_event; jack_event = thread_queue->
DequeueEvent()) {
   187         switch (write_queue->
EnqueueEvent(jack_event, frames)) {
   188         case JackMidiWriteQueue::BUFFER_TOO_SMALL:
   189             jack_error(
"JackWinMMEMidiInputPort::Process - The buffer write "   190                        "queue couldn't enqueue a %d-byte event. Dropping "   191                        "event.", jack_event->
size);
   193         case JackMidiWriteQueue::OK:
   203 JackWinMMEInputPort::ProcessWinMME(UINT message, DWORD param1, DWORD param2)
   205     set_threaded_log_function();
   208         jack_log(
"JackWinMMEInputPort::ProcessWinMME - MIDI device closed.");
   211         jack_log(
"JackWinMMEInputPort::ProcessWinMME - The MIDI input device "   212                   "driver thinks that JACK is not processing messages fast "   216         jack_midi_data_t message_buffer[3];
   217         jack_midi_data_t status = param1 & 0xff;
   218         int length = GetMessageLength(status);
   222              message_buffer[2] = (param1 >> 16)  & 0xff;
   225             message_buffer[1] = (param1 >> 8) & 0xff;
   228             message_buffer[0] = status;
   231             jack_error(
"JackWinMMEInputPort::ProcessWinMME - **BUG** MIDI "   232                        "input driver sent an MIM_DATA message with a sysex "   236             jack_error(
"JackWinMMEInputPort::ProcessWinMME - **BUG** MIDI "   237                        "input driver sent an MIM_DATA message with an invalid "   241         EnqueueMessage(param2, (
size_t) length, message_buffer);
   245         LPMIDIHDR header = (LPMIDIHDR) param1;
   246         size_t byte_count = header->dwBytesRecorded;
   248             jack_log(
"JackWinMMEInputPort::ProcessWinMME - WinMME driver has "   249                       "returned sysex header to us with no bytes.  The JACK "   250                       "driver is probably being stopped.");
   253         jack_midi_data_t *data = (jack_midi_data_t *) header->lpData;
   254         if ((data[0] != 0xf0) || (data[byte_count - 1] != 0xf7)) {
   255             jack_error(
"JackWinMMEInputPort::ProcessWinMME - Discarding "   256                        "%d-byte sysex chunk.", byte_count);
   258             EnqueueMessage(param2, byte_count, data);
   263         MMRESULT result = midiInAddBuffer(handle, &sysex_header,
   265         if (result != MMSYSERR_NOERROR) {
   266             WriteInError(
"JackWinMMEInputPort::ProcessWinMME",
   267                          "midiInAddBuffer", result);
   272         jack_error(
"JackWinMMEInputPort::ProcessWinMME - Invalid or "   273                    "incomplete sysex message received.");
   276         jack_log(
"JackWinMMEInputPort::ProcessWinMME - MIDI device opened.");
   281 JackWinMMEInputPort::Start()
   284         start_time = GetMicroSeconds();
   285         MMRESULT result = midiInStart(handle);
   286         started = result == MMSYSERR_NOERROR;
   288             WriteInError(
"JackWinMMEInputPort::Start", 
"midiInStart", result);
   295 JackWinMMEInputPort::Stop()
   298         MMRESULT result = midiInStop(handle);
   299         started = result != MMSYSERR_NOERROR;
   301             WriteInError(
"JackWinMMEInputPort::Stop", 
"midiInStop", result);
   308 JackWinMMEInputPort::WriteInError(
const char *jack_func, 
const char *mm_func,
   311     char error_message[MAXERRORLENGTH];
   312     GetInErrorString(result, error_message);
   313     jack_error(
"%s - %s: %s", jack_func, mm_func, error_message);
 EnqueueResult EnqueueEvent(jack_nframes_t time, size_t size, jack_midi_data_t *buffer)
SERVER_EXPORT void jack_error(const char *fmt,...)
void ResetMidiBuffer(JackMidiBuffer *buffer, jack_nframes_t frames)
virtual jack_midi_event_t * DequeueEvent()
SERVER_EXPORT void jack_log(const char *fmt,...)
virtual EnqueueResult EnqueueEvent(jack_nframes_t time, size_t size, jack_midi_data_t *buffer)