| @@ -102,10 +102,21 @@ | |||
| <Add library="libjackserver" /> | |||
| <Add library="winmm" /> | |||
| </Linker> | |||
| <Unit filename="..\common\JackMidiAsyncQueue.cpp" /> | |||
| <Unit filename="..\common\JackMidiBufferReadQueue.cpp" /> | |||
| <Unit filename="..\common\JackMidiBufferWriteQueue.cpp" /> | |||
| <Unit filename="..\common\JackMidiReadQueue.cpp" /> | |||
| <Unit filename="..\common\JackMidiUtil.cpp" /> | |||
| <Unit filename="..\common\JackMidiWriteQueue.cpp" /> | |||
| <Unit filename="jackwinmme.rc"> | |||
| <Option compilerVar="WINDRES" /> | |||
| </Unit> | |||
| <Unit filename="winmme\JackWinMMEDriver.cpp" /> | |||
| <Unit filename="winmme\JackWinMMEDriver.h" /> | |||
| <Unit filename="winmme\JackWinMMEInputPort.cpp" /> | |||
| <Unit filename="winmme\JackWinMMEInputPort.h" /> | |||
| <Unit filename="winmme\JackWinMMEOutputPort.cpp" /> | |||
| <Unit filename="winmme\JackWinMMEOutputPort.h" /> | |||
| <Extensions> | |||
| <code_completion /> | |||
| <envvars /> | |||
| @@ -5,7 +5,7 @@ | |||
| <Project filename="jackd.cbp"> | |||
| <Depends filename="libjackserver.cbp" /> | |||
| </Project> | |||
| <Project filename="jack_portaudio.cbp"> | |||
| <Project filename="jack_portaudio.cbp" active="1"> | |||
| <Depends filename="libjackserver.cbp" /> | |||
| </Project> | |||
| <Project filename="jack_netdriver.cbp"> | |||
| @@ -57,6 +57,6 @@ | |||
| <Depends filename="libjack.cbp" /> | |||
| </Project> | |||
| <Project filename="jack_winmme.cbp" /> | |||
| <Project filename="jack_loopback.cbp" active="1" /> | |||
| <Project filename="jack_loopback.cbp" /> | |||
| </Workspace> | |||
| </CodeBlocks_workspace_file> | |||
| @@ -154,8 +154,6 @@ | |||
| <Unit filename="..\common\JackMidiPort.cpp" /> | |||
| <Unit filename="..\common\JackNetInterface.cpp" /> | |||
| <Unit filename="..\common\JackNetTool.cpp" /> | |||
| <Unit filename="..\common\JackPhysicalMidiInput.cpp" /> | |||
| <Unit filename="..\common\JackPhysicalMidiOutput.cpp" /> | |||
| <Unit filename="..\common\JackPort.cpp" /> | |||
| <Unit filename="..\common\JackPortType.cpp" /> | |||
| <Unit filename="..\common\JackRestartThreadedDriver.cpp" /> | |||
| @@ -248,7 +248,7 @@ error: | |||
| } else { | |||
| JackAudioDriver::SetBufferSize(buffer_size); // Generic change, never fails | |||
| // PortAudio specific | |||
| UpdateLatencies(); | |||
| JackAudioDriver::UpdateLatencies(); | |||
| return 0; | |||
| } | |||
| } | |||
| @@ -24,6 +24,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| #include "JackError.h" | |||
| #include "JackMidiUtil.h" | |||
| #include "JackWinMMEInputPort.h" | |||
| #include "JackMidiWriteQueue.h" | |||
| using Jack::JackWinMMEInputPort; | |||
| @@ -54,7 +55,7 @@ JackWinMMEInputPort::JackWinMMEInputPort(const char *alias_name, | |||
| std::auto_ptr<JackMidiBufferWriteQueue> write_queue_ptr(write_queue); | |||
| sysex_buffer = new jack_midi_data_t[max_bytes]; | |||
| char error_message[MAXERRORLENGTH]; | |||
| MMRESULT result = midiInOpen(&handle, index, HandleMidiInputEvent, this, | |||
| MMRESULT result = midiInOpen(&handle, index, (DWORD)HandleMidiInputEvent, (DWORD)this, | |||
| CALLBACK_FUNCTION | MIDI_IO_STATUS); | |||
| if (result != MMSYSERR_NOERROR) { | |||
| GetErrorString(result, error_message); | |||
| @@ -64,7 +65,7 @@ JackWinMMEInputPort::JackWinMMEInputPort(const char *alias_name, | |||
| sysex_header.dwBytesRecorded = 0; | |||
| sysex_header.dwFlags = 0; | |||
| sysex_header.dwUser = 0; | |||
| sysex_header.lpData = (((LPBYTE) sysex_header) + sizeof(MIDIHDR)); | |||
| sysex_header.lpData = (LPSTR)(((LPBYTE) &sysex_header) + sizeof(MIDIHDR)); | |||
| sysex_header.lpNext = 0; | |||
| result = midiInPrepareHeader(handle, &sysex_header, sizeof(MIDIHDR)); | |||
| if (result != MMSYSERR_NOERROR) { | |||
| @@ -84,7 +85,7 @@ JackWinMMEInputPort::JackWinMMEInputPort(const char *alias_name, | |||
| return; | |||
| unprepare_header: | |||
| result = midiInUnprepareHeader(handle, sysex_header, sizeof(MIDIHDR)); | |||
| result = midiInUnprepareHeader(handle, &sysex_header, sizeof(MIDIHDR)); | |||
| if (result != MMSYSERR_NOERROR) { | |||
| WriteError("JackWinMMEInputPort [constructor]", | |||
| "midiInUnprepareHeader", result); | |||
| @@ -106,7 +107,7 @@ JackWinMMEInputPort::~JackWinMMEInputPort() | |||
| if (result != MMSYSERR_NOERROR) { | |||
| WriteError("JackWinMMEInputPort [destructor]", "midiInReset", result); | |||
| } | |||
| result = midiInUnprepareHeader(handle, sysex_header, sizeof(MIDIHDR)); | |||
| result = midiInUnprepareHeader(handle, &sysex_header, sizeof(MIDIHDR)); | |||
| if (result != MMSYSERR_NOERROR) { | |||
| WriteError("JackWinMMEInputPort [destructor]", "midiInUnprepareHeader", | |||
| result); | |||
| @@ -128,12 +129,12 @@ JackWinMMEInputPort::EnqueueMessage(jack_nframes_t time, size_t length, | |||
| case JackMidiWriteQueue::BUFFER_FULL: | |||
| jack_error("JackWinMMEInputPort::EnqueueMessage - The thread queue " | |||
| "cannot currently accept a %d-byte event. Dropping event.", | |||
| size); | |||
| length); | |||
| break; | |||
| case JackMidiWriteQueue::BUFFER_TOO_SMALL: | |||
| jack_error("JackWinMMEInputPort::EnqueueMessage - The thread queue " | |||
| "buffer is too small to enqueue a %d-byte event. Dropping " | |||
| "event.", size); | |||
| "event.", length); | |||
| break; | |||
| default: | |||
| ; | |||
| @@ -162,20 +163,20 @@ JackWinMMEInputPort::GetName() | |||
| } | |||
| void | |||
| JackWinMMEInputPort::ProcessJack() | |||
| JackWinMMEInputPort::ProcessJack(JackMidiBuffer *port_buffer, jack_nframes_t frames) | |||
| { | |||
| write_queue->ResetMidiBuffer(port_buffer, frames); | |||
| if (! jack_event) { | |||
| jack_event = thread_queue->DequeueEvent(); | |||
| } | |||
| for (; jack_event; jack_event = thread_queue->DequeueEvent()) { | |||
| switch (write_queue->EnqueueEvent(event)) { | |||
| case BUFFER_TOO_SMALL: | |||
| switch (write_queue->EnqueueEvent(jack_event)) { | |||
| case JackMidiWriteQueue::BUFFER_TOO_SMALL: | |||
| jack_error("JackWinMMEMidiInputPort::Process - The buffer write " | |||
| "queue couldn't enqueue a %d-byte event. Dropping " | |||
| "event.", event->size); | |||
| "event.", jack_event->size); | |||
| // Fallthrough on purpose | |||
| case OK: | |||
| case JackMidiWriteQueue::OK: | |||
| continue; | |||
| } | |||
| break; | |||
| @@ -224,14 +225,14 @@ JackWinMMEInputPort::ProcessWinMME(UINT message, DWORD param1, DWORD param2) | |||
| EnqueueMessage(current_frame, (size_t) length, message_buffer); | |||
| break; | |||
| case MIM_LONGDATA: | |||
| LPMIDIHDR header = (LPMIDIHDR) dwParam1; | |||
| LPMIDIHDR header = (LPMIDIHDR) param1; | |||
| jack_midi_data_t *data = (jack_midi_data_t *) header->lpData; | |||
| size_t length = header->dwBytesRecorded; | |||
| if ((data[0] != 0xf0) || (data[length - 1] != 0xf7)) { | |||
| size_t length1 = header->dwBytesRecorded; | |||
| if ((data[0] != 0xf0) || (data[length1 - 1] != 0xf7)) { | |||
| jack_error("JackWinMMEInputPort::ProcessWinMME - Discarding " | |||
| "%d-byte sysex chunk.", length); | |||
| } else { | |||
| EnqueueMessage(current_frame, length, data); | |||
| EnqueueMessage(current_frame, length1, data); | |||
| } | |||
| // Is this realtime-safe? This function isn't run in the JACK thread, | |||
| // but we still want it to perform as quickly as possible. Even if | |||
| @@ -282,7 +283,7 @@ void | |||
| JackWinMMEInputPort::WriteError(const char *jack_func, const char *mm_func, | |||
| MMRESULT result) | |||
| { | |||
| const char error_message[MAXERRORLENGTH]; | |||
| char error_message[MAXERRORLENGTH]; | |||
| GetErrorString(result, error_message); | |||
| jack_error("%s - %s: %s", jack_func, mm_func, error_message); | |||
| } | |||
| @@ -55,7 +55,7 @@ namespace Jack { | |||
| char name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE]; | |||
| bool started; | |||
| jack_midi_data_t *sysex_buffer; | |||
| MIDIHDR sysex_header | |||
| MIDIHDR sysex_header; | |||
| JackMidiAsyncQueue *thread_queue; | |||
| JackMidiBufferWriteQueue *write_queue; | |||
| @@ -74,7 +74,7 @@ namespace Jack { | |||
| GetName(); | |||
| void | |||
| ProcessJack(); | |||
| ProcessJack(JackMidiBuffer *port_buffer, jack_nframes_t frames); | |||
| bool | |||
| Start(); | |||
| @@ -55,7 +55,7 @@ JackWinMMEOutputPort::JackWinMMEOutputPort(const char *alias_name, | |||
| thread = new JackThread(this); | |||
| std::auto_ptr<JackThread> thread_ptr(thread); | |||
| char error_message[MAXERRORLENGTH]; | |||
| MMRESULT result = midiOutOpen(&handle, index, HandleMessageEvent, this, | |||
| MMRESULT result = midiOutOpen(&handle, index, (DWORD)HandleMessageEvent, (DWORD)this, | |||
| CALLBACK_FUNCTION); | |||
| if (result != MMSYSERR_NOERROR) { | |||
| GetErrorString(result, error_message); | |||
| @@ -71,22 +71,24 @@ JackWinMMEOutputPort::JackWinMMEOutputPort(const char *alias_name, | |||
| GetOSErrorString(error_message); | |||
| goto destroy_thread_queue_semaphore; | |||
| } | |||
| MIDIINCAPS capabilities; | |||
| char *name; | |||
| MIDIOUTCAPS capabilities; | |||
| char *name_tmp; | |||
| result = midiOutGetDevCaps(index, &capabilities, sizeof(capabilities)); | |||
| /* | |||
| Devin : FIXME | |||
| if (result != MMSYSERR_NOERROR) { | |||
| WriteMMError("JackWinMMEOutputPort [constructor]", "midiOutGetDevCaps", | |||
| result); | |||
| name = driver_name; | |||
| name_tmp = driver_name; | |||
| } else { | |||
| name = capabilities.szPname; | |||
| name_tmp = capabilities.szPname; | |||
| } | |||
| */ | |||
| snprintf(alias, sizeof(alias) - 1, "%s:%s:out%d", alias_name, driver_name, | |||
| index + 1); | |||
| snprintf(name, sizeof(name) - 1, "%s:playback_%d", client_name, index + 1); | |||
| thread_ptr.release(); | |||
| write_queue_ptr.release(); | |||
| thread_queue_ptr.release(); | |||
| thread_queue_ptr.release(); | |||
| return; | |||
| destroy_thread_queue_semaphore: | |||
| @@ -185,7 +187,7 @@ JackWinMMEOutputPort::Execute() | |||
| header.dwFlags = 0; | |||
| header.dwOffset = 0; | |||
| header.dwUser = 0; | |||
| header.lpData = data; | |||
| header.lpData = (LPSTR)data; | |||
| result = midiOutPrepareHeader(handle, &header, sizeof(MIDIHDR)); | |||
| if (result != MMSYSERR_NOERROR) { | |||
| WriteMMError("JackWinMMEOutputPort::Execute", | |||
| @@ -230,11 +232,14 @@ void | |||
| JackWinMMEOutputPort::GetOSErrorString(LPTSTR text) | |||
| { | |||
| DWORD error = GetLastError(); | |||
| /* | |||
| Devin: FIXME | |||
| if (! FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, | |||
| MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), &text, | |||
| MAXERRORLENGTH, NULL)) { | |||
| snprintf(text, MAXERRORLENGTH, "Unknown OS error code '%d'", error); | |||
| } | |||
| */ | |||
| } | |||
| void | |||
| @@ -297,7 +302,7 @@ JackWinMMEOutputPort::ProcessJack(JackMidiBuffer *port_buffer, | |||
| } | |||
| bool | |||
| JackWinMMEOutputPort::Signal(Handle semaphore) | |||
| JackWinMMEOutputPort::Signal(HANDLE semaphore) | |||
| { | |||
| bool result = (bool) ReleaseSemaphore(semaphore, 1, NULL); | |||
| if (! result) { | |||
| @@ -351,7 +356,7 @@ JackWinMMEOutputPort::Stop() | |||
| } | |||
| bool | |||
| JackWinMMEOutputPort::Wait(Handle semaphore) | |||
| JackWinMMEOutputPort::Wait(HANDLE semaphore) | |||
| { | |||
| DWORD result = WaitForSingleObject(semaphore, INFINITE); | |||
| switch (result) { | |||
| @@ -371,7 +376,7 @@ void | |||
| JackWinMMEOutputPort::WriteMMError(const char *jack_func, const char *mm_func, | |||
| MMRESULT result) | |||
| { | |||
| const char error_message[MAXERRORLENGTH]; | |||
| char error_message[MAXERRORLENGTH]; | |||
| GetMMErrorString(result, error_message); | |||
| jack_error("%s - %s: %s", jack_func, mm_func, error_message); | |||
| } | |||
| @@ -379,7 +384,28 @@ JackWinMMEOutputPort::WriteMMError(const char *jack_func, const char *mm_func, | |||
| void | |||
| JackWinMMEOutputPort::WriteOSError(const char *jack_func, const char *os_func) | |||
| { | |||
| const char error_message[MAXERRORLENGTH]; | |||
| GetOSErrorString(result, error_message); | |||
| char error_message[MAXERRORLENGTH]; | |||
| // Devin : FIXME | |||
| //GetOSErrorString(result, error_message); | |||
| jack_error("%s - %s: %s", jack_func, os_func, error_message); | |||
| } | |||
| const char * | |||
| JackWinMMEOutputPort::GetAlias() | |||
| { | |||
| return alias; | |||
| } | |||
| const char * | |||
| JackWinMMEOutputPort::GetName() | |||
| { | |||
| return name; | |||
| } | |||
| void | |||
| JackWinMMEOutputPort::GetErrorString(MMRESULT error, LPTSTR text) | |||
| { | |||
| MMRESULT result = midiInGetErrorText(error, text, MAXERRORLENGTH); | |||
| if (result != MMSYSERR_NOERROR) { | |||
| snprintf(text, MAXERRORLENGTH, "Unknown error code '%d'", error); | |||
| } | |||
| } | |||
| @@ -47,10 +47,10 @@ namespace Jack { | |||
| HandleMessage(UINT message, DWORD_PTR param1, DWORD_PTR param2); | |||
| bool | |||
| Signal(Handle semaphore); | |||
| Signal(HANDLE semaphore); | |||
| bool | |||
| Wait(Handle semaphore); | |||
| Wait(HANDLE semaphore); | |||
| void | |||
| WriteMMError(const char *jack_func, const char *mm_func, | |||
| @@ -60,14 +60,18 @@ namespace Jack { | |||
| WriteOSError(const char *jack_func, const char *os_func); | |||
| char alias[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE]; | |||
| HMIDIOUT handle; | |||
| char name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE]; | |||
| HMIDIOUT handle; | |||
| JackMidiBufferReadQueue *read_queue; | |||
| HANDLE sysex_semaphore; | |||
| JackThread *thread; | |||
| JackMidiAsyncQueue *thread_queue; | |||
| HANDLE thread_queue_semaphore; | |||
| void | |||
| GetErrorString(MMRESULT error, LPTSTR text); | |||
| public: | |||
| JackWinMMEOutputPort(const char *alias_name, const char *client_name, | |||
| @@ -91,6 +95,12 @@ namespace Jack { | |||
| bool | |||
| Stop(); | |||
| const char * | |||
| GetAlias(); | |||
| const char * | |||
| GetName(); | |||
| }; | |||
| } | |||