diff --git a/windows/JackCompilerDeps_os.h b/windows/JackCompilerDeps_os.h index 82fae18e..858cbd8f 100644 --- a/windows/JackCompilerDeps_os.h +++ b/windows/JackCompilerDeps_os.h @@ -18,24 +18,24 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef __JackCompilerDeps_WIN32__ -#define __JackCompilerDeps_WIN32__ +#define __JackCompilerDeps_WIN32__ -#if __GNUC__ - #ifndef POST_PACKED_STRUCTURE - /* POST_PACKED_STRUCTURE needs to be a macro which - expands into a compiler directive. The directive must - tell the compiler to arrange the preceding structure - declaration so that it is packed on byte-boundaries rather - than use the natural alignment of the processor and/or - compiler. - */ - #if (__GNUC__< 4) /* Does not seem to work with GCC 3.XX serie */ - #define POST_PACKED_STRUCTURE - #elif defined(JACK_32_64) - #define POST_PACKED_STRUCTURE __attribute__((__packed__)) - #else - #define POST_PACKED_STRUCTURE - #endif +#if __GNUC__ + #ifndef POST_PACKED_STRUCTURE + /* POST_PACKED_STRUCTURE needs to be a macro which + expands into a compiler directive. The directive must + tell the compiler to arrange the preceding structure + declaration so that it is packed on byte-boundaries rather + than use the natural alignment of the processor and/or + compiler. + */ + #if (__GNUC__< 4) /* Does not seem to work with GCC 3.XX serie */ + #define POST_PACKED_STRUCTURE + #elif defined(JACK_32_64) + #define POST_PACKED_STRUCTURE __attribute__((__packed__)) + #else + #define POST_PACKED_STRUCTURE + #endif #endif #define MEM_ALIGN(x,y) x __attribute__((aligned(y))) #define EXPORT __declspec(dllexport) diff --git a/windows/JackNetWinSocket.cpp b/windows/JackNetWinSocket.cpp index 30420b49..94390b4d 100644 --- a/windows/JackNetWinSocket.cpp +++ b/windows/JackNetWinSocket.cpp @@ -286,12 +286,12 @@ namespace Jack //local loop********************************************************************************************************* int JackNetWinSocket::SetLocalLoop() { - //char disable = 0; - /* - see http://msdn.microsoft.com/en-us/library/aa916098.aspx - Default value is TRUE. When TRUE, data that is sent from the local interface to the multicast group to - which the socket is joined, including data sent from the same socket, will be echoed to its receive buffer. - */ + //char disable = 0; + /* + see http://msdn.microsoft.com/en-us/library/aa916098.aspx + Default value is TRUE. When TRUE, data that is sent from the local interface to the multicast group to + which the socket is joined, including data sent from the same socket, will be echoed to its receive buffer. + */ char disable = 1; return SetOption ( IPPROTO_IP, IP_MULTICAST_LOOP, &disable, sizeof ( disable ) ); } diff --git a/windows/JackTypes_os.h b/windows/JackTypes_os.h index 88a8bd8a..13e67349 100644 --- a/windows/JackTypes_os.h +++ b/windows/JackTypes_os.h @@ -20,7 +20,7 @@ #ifndef __JackTypes_WIN32__ #define __JackTypes_WIN32__ -#include +#include #include "types.h" typedef ULONGLONG UInt64; diff --git a/windows/JackWinProcessSync.cpp b/windows/JackWinProcessSync.cpp index 5dc405b5..56171fba 100644 --- a/windows/JackWinProcessSync.cpp +++ b/windows/JackWinProcessSync.cpp @@ -32,7 +32,7 @@ void JackWinProcessSync::LockedSignal() { WaitForSingleObject(fMutex, INFINITE); SetEvent(fEvent); - ReleaseMutex(fMutex); + ReleaseMutex(fMutex); } void JackWinProcessSync::SignalAll() @@ -44,71 +44,71 @@ void JackWinProcessSync::LockedSignalAll() { WaitForSingleObject(fMutex, INFINITE); SetEvent(fEvent); - ReleaseMutex(fMutex); -} - -void JackWinProcessSync::Wait() -{ - ReleaseMutex(fMutex); - WaitForSingleObject(fEvent, INFINITE); -} - -void JackWinProcessSync::LockedWait() -{ - /* Does it make sense on Windows, use non-locked version for now... */ - Wait(); -} - -bool JackWinProcessSync::TimedWait(long usec) -{ - ReleaseMutex(fMutex); - DWORD res = WaitForSingleObject(fEvent, usec / 1000); - return (res == WAIT_OBJECT_0); -} - -bool JackWinProcessSync::LockedTimedWait(long usec) -{ - /* Does it make sense on Windows, use non-locked version for now...*/ - return TimedWait(usec); -} - -/* -Code from CAGuard.cpp : does ot sees to work as expected.. - -void JackWinProcessSync::Wait() -{ - ReleaseMutex(fMutex); - HANDLE handles[] = { fMutex, fEvent }; - DWORD res = WaitForMultipleObjects(2, handles, true, INFINITE); - if ((res != WAIT_OBJECT_0) && (res != WAIT_TIMEOUT)) - jack_error("Wait error err = %d", GetLastError()); - ResetEvent(fEvent); -} + ReleaseMutex(fMutex); +} + +void JackWinProcessSync::Wait() +{ + ReleaseMutex(fMutex); + WaitForSingleObject(fEvent, INFINITE); +} void JackWinProcessSync::LockedWait() -{ - WaitForSingleObject(fMutex, INFINITE); +{ + /* Does it make sense on Windows, use non-locked version for now... */ + Wait(); +} + +bool JackWinProcessSync::TimedWait(long usec) +{ + ReleaseMutex(fMutex); + DWORD res = WaitForSingleObject(fEvent, usec / 1000); + return (res == WAIT_OBJECT_0); +} + +bool JackWinProcessSync::LockedTimedWait(long usec) +{ + /* Does it make sense on Windows, use non-locked version for now...*/ + return TimedWait(usec); +} + +/* +Code from CAGuard.cpp : does ot sees to work as expected.. + +void JackWinProcessSync::Wait() +{ + ReleaseMutex(fMutex); + HANDLE handles[] = { fMutex, fEvent }; + DWORD res = WaitForMultipleObjects(2, handles, true, INFINITE); + if ((res != WAIT_OBJECT_0) && (res != WAIT_TIMEOUT)) + jack_error("Wait error err = %d", GetLastError()); + ResetEvent(fEvent); +} + +void JackWinProcessSync::LockedWait() +{ + WaitForSingleObject(fMutex, INFINITE); ReleaseMutex(fMutex); HANDLE handles[] = { fMutex, fEvent }; DWORD res = WaitForMultipleObjects(2, handles, true, INFINITE); if ((res != WAIT_OBJECT_0) && (res != WAIT_TIMEOUT)) jack_error("LockedWait error err = %d", GetLastError()); - ResetEvent(fEvent); + ResetEvent(fEvent); } - -bool JackWinProcessSync::TimedWait(long usec) -{ - ReleaseMutex(fMutex); - HANDLE handles[] = { fMutex, fEvent }; - DWORD res = WaitForMultipleObjects(2, handles, true, usec / 1000); - if ((res != WAIT_OBJECT_0) && (res != WAIT_TIMEOUT)) - jack_error("Wait error err = %d", GetLastError()); - ResetEvent(fEvent); + +bool JackWinProcessSync::TimedWait(long usec) +{ + ReleaseMutex(fMutex); + HANDLE handles[] = { fMutex, fEvent }; + DWORD res = WaitForMultipleObjects(2, handles, true, usec / 1000); + if ((res != WAIT_OBJECT_0) && (res != WAIT_TIMEOUT)) + jack_error("Wait error err = %d", GetLastError()); + ResetEvent(fEvent); } bool JackWinProcessSync::LockedTimedWait(long usec) -{ - WaitForSingleObject(fMutex, INFINITE); +{ + WaitForSingleObject(fMutex, INFINITE); ReleaseMutex(fMutex); HANDLE handles[] = { fMutex, fEvent }; DWORD res = WaitForMultipleObjects(2, handles, true, usec / 1000); diff --git a/windows/JackWinServerLaunch.cpp b/windows/JackWinServerLaunch.cpp index eeda81a8..895c9bdf 100644 --- a/windows/JackWinServerLaunch.cpp +++ b/windows/JackWinServerLaunch.cpp @@ -1,26 +1,26 @@ -/* -Copyright (C) 2001-2003 Paul Davis -Copyright (C) 2004-2008 Grame - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation; either version 2.1 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -*/ - -#include "JackServerLaunch.h" - -int try_start_server(jack_varargs_t* va, jack_options_t options, jack_status_t* status) -{ - return 0; -} +/* +Copyright (C) 2001-2003 Paul Davis +Copyright (C) 2004-2008 Grame + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "JackServerLaunch.h" + +int try_start_server(jack_varargs_t* va, jack_options_t options, jack_status_t* status) +{ + return 0; +} diff --git a/windows/portaudio/JackPortAudioDevices.cpp b/windows/portaudio/JackPortAudioDevices.cpp index 2adb35e0..d12cfca3 100644 --- a/windows/portaudio/JackPortAudioDevices.cpp +++ b/windows/portaudio/JackPortAudioDevices.cpp @@ -43,9 +43,9 @@ PortAudioDevices::PortAudioDevices() } PortAudioDevices::~PortAudioDevices() -{ +{ // Desactivate for now: crash the server.. - //Pa_Terminate(); + //Pa_Terminate(); delete[] fDeviceInfo; delete[] fHostName; diff --git a/windows/portaudio/JackPortAudioDevices.h b/windows/portaudio/JackPortAudioDevices.h index 92b8603e..c8ab656b 100644 --- a/windows/portaudio/JackPortAudioDevices.h +++ b/windows/portaudio/JackPortAudioDevices.h @@ -1,59 +1,59 @@ -/* -Copyright (C) 2008 Romain Moret at Grame - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#ifndef __PortAudioDevices__ -#define __PortAudioDevices__ - -#include -#include - -#include "portaudio.h" -#include "pa_asio.h" - -/*! -\brief A PortAudio Devices manager. -*/ - -class PortAudioDevices -{ - private: - PaHostApiIndex fNumHostApi; //number of hosts - PaDeviceIndex fNumDevice; //number of devices - PaDeviceInfo** fDeviceInfo; //array of device info - std::string* fHostName; //array of host names (matched with host id's) - public: - PortAudioDevices(); - ~PortAudioDevices(); - - PaDeviceIndex GetNumDevice(); - PaDeviceInfo* GetDeviceInfo(PaDeviceIndex id); - std::string GetDeviceName(PaDeviceIndex id); - std::string GetHostFromDevice(PaDeviceInfo* device); - std::string GetHostFromDevice(PaDeviceIndex id); - std::string GetFullName(PaDeviceIndex id); - std::string GetFullName(std::string hostname, std::string devicename); - PaDeviceInfo* GetDeviceFromFullName(std::string fullname, PaDeviceIndex& id, bool isInput ); - void PrintSupportedStandardSampleRates(const PaStreamParameters* inputParameters, const PaStreamParameters* outputParameters); - int GetInputDeviceFromName(const char* name, PaDeviceIndex& device, int& in_max); - int GetOutputDeviceFromName(const char* name, PaDeviceIndex& device, int& out_max); - void DisplayDevicesNames(); - bool IsDuplex ( PaDeviceIndex id ); -}; - -#endif +/* +Copyright (C) 2008 Romain Moret at Grame + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef __PortAudioDevices__ +#define __PortAudioDevices__ + +#include +#include + +#include "portaudio.h" +#include "pa_asio.h" + +/*! +\brief A PortAudio Devices manager. +*/ + +class PortAudioDevices +{ + private: + PaHostApiIndex fNumHostApi; //number of hosts + PaDeviceIndex fNumDevice; //number of devices + PaDeviceInfo** fDeviceInfo; //array of device info + std::string* fHostName; //array of host names (matched with host id's) + public: + PortAudioDevices(); + ~PortAudioDevices(); + + PaDeviceIndex GetNumDevice(); + PaDeviceInfo* GetDeviceInfo(PaDeviceIndex id); + std::string GetDeviceName(PaDeviceIndex id); + std::string GetHostFromDevice(PaDeviceInfo* device); + std::string GetHostFromDevice(PaDeviceIndex id); + std::string GetFullName(PaDeviceIndex id); + std::string GetFullName(std::string hostname, std::string devicename); + PaDeviceInfo* GetDeviceFromFullName(std::string fullname, PaDeviceIndex& id, bool isInput ); + void PrintSupportedStandardSampleRates(const PaStreamParameters* inputParameters, const PaStreamParameters* outputParameters); + int GetInputDeviceFromName(const char* name, PaDeviceIndex& device, int& in_max); + int GetOutputDeviceFromName(const char* name, PaDeviceIndex& device, int& out_max); + void DisplayDevicesNames(); + bool IsDuplex ( PaDeviceIndex id ); +}; + +#endif diff --git a/windows/resource_vc.h b/windows/resource_vc.h index 673206e6..9916ed38 100644 --- a/windows/resource_vc.h +++ b/windows/resource_vc.h @@ -1,15 +1,15 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Developer Studio generated include file. -// Used by resource.rc -// - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 102 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1000 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by resource.rc +// + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/windows/winmme/JackWinMMEDriver.cpp b/windows/winmme/JackWinMMEDriver.cpp index 87b1e44e..6ddf5667 100644 --- a/windows/winmme/JackWinMMEDriver.cpp +++ b/windows/winmme/JackWinMMEDriver.cpp @@ -1,501 +1,501 @@ -/* -Copyright (C) 2009 Grame - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program; if not, write to the Free Software -Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#include "JackWinMMEDriver.h" -#include "JackGraphManager.h" -#include "JackEngineControl.h" -#include "JackDriverLoader.h" - -#include -#include -#include -#include - -#include -#include -#include - -namespace Jack -{ - -static bool InitHeaders(MidiSlot* slot) -{ - slot->fHeader = (LPMIDIHDR)GlobalAllocPtr(GMEM_MOVEABLE|GMEM_SHARE|GMEM_ZEROINIT, sizeof(MIDIHDR) + kBuffSize); - if (!slot->fHeader) - return false; - - slot->fHeader->lpData = (LPSTR)((LPBYTE)slot->fHeader + sizeof(MIDIHDR)); - slot->fHeader->dwBufferLength = kBuffSize; - slot->fHeader->dwFlags = 0; - slot->fHeader->dwUser = 0; - slot->fHeader->lpNext = 0; - slot->fHeader->dwBytesRecorded = 0; - return true; -} - -void CALLBACK JackWinMMEDriver::MidiInProc(HMIDIIN hMidiIn, UINT wMsg, DWORD userData, DWORD dwParam1, DWORD dwParam2) -{ - jack_ringbuffer_t* ringbuffer = (jack_ringbuffer_t*)userData; - //jack_info("JackWinMMEDriver::MidiInProc 0\n"); - - switch (wMsg) { - case MIM_OPEN: - break; - - case MIM_ERROR: - case MIM_DATA: { - - //jack_info("JackWinMMEDriver::MidiInProc"); - - // One event - unsigned int num_packet = 1; - jack_ringbuffer_write(ringbuffer, (char*)&num_packet, sizeof(unsigned int)); - - // Write event actual data - jack_ringbuffer_write(ringbuffer, (char*)&dwParam1, 3); - break; - } - - case MIM_LONGERROR: - case MIM_LONGDATA: - /* - Nothing for now - */ - break; - } -} - -JackWinMMEDriver::JackWinMMEDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table) - : JackMidiDriver(name, alias, engine, table), - fRealCaptureChannels(0), - fRealPlaybackChannels(0), - fMidiSource(NULL), - fMidiDestination(NULL) -{} - -JackWinMMEDriver::~JackWinMMEDriver() -{} - -int JackWinMMEDriver::Open(bool capturing, - bool playing, - int inchannels, - int outchannels, - bool monitor, - const char* capture_driver_name, - const char* playback_driver_name, - jack_nframes_t capture_latency, - jack_nframes_t playback_latency) -{ - - jack_log("JackWinMMEDriver::Open"); - - fRealCaptureChannels = midiInGetNumDevs(); - fRealPlaybackChannels = midiOutGetNumDevs(); - - // Generic JackMidiDriver Open - if (JackMidiDriver::Open(capturing, playing, fRealCaptureChannels, fRealPlaybackChannels, monitor, capture_driver_name, playback_driver_name, capture_latency, playback_latency) != 0) - return -1; - - fMidiDestination = new MidiSlot[fRealCaptureChannels]; - assert(fMidiDestination); - - // Real input - for (int i = 0; i < fRealCaptureChannels; i++) { - - HMIDIIN handle; - fMidiDestination[i].fIndex = i; - MMRESULT ret = midiInOpen(&handle, fMidiDestination[i].fIndex, (DWORD)MidiInProc, (DWORD)fRingBuffer[i], CALLBACK_FUNCTION); - - if (ret == MMSYSERR_NOERROR) { - fMidiDestination[i].fHandle = handle; - if (!InitHeaders(&fMidiDestination[i])) { - jack_error("memory allocation failed"); - midiInClose(handle); - goto error; - //continue; - } - ret = midiInPrepareHeader(handle, fMidiDestination[i].fHeader, sizeof(MIDIHDR)); - - if (ret == MMSYSERR_NOERROR) { - fMidiDestination[i].fHeader->dwUser = 1; - ret = midiInAddBuffer(handle, fMidiDestination[i].fHeader, sizeof(MIDIHDR)); - if (ret == MMSYSERR_NOERROR) { - ret = midiInStart(handle); - if (ret != MMSYSERR_NOERROR) { - jack_error("midiInStart error"); - CloseInput(&fMidiDestination[i]); - goto error; - } - } else { - jack_error ("midiInAddBuffer error"); - CloseInput(&fMidiDestination[i]); - goto error; - } - } else { - jack_error("midiInPrepareHeader error"); - midiInClose(handle); - goto error; - } - } else { - jack_error ("midiInOpen error"); - goto error; - } - } - - fMidiSource = new MidiSlot[fRealPlaybackChannels]; - assert(fMidiSource); - - // Real output - for (int i = 0; i < fRealPlaybackChannels; i++) { - MMRESULT res; - HMIDIOUT handle; - fMidiSource[i].fIndex = i; - UINT ret = midiOutOpen(&handle, fMidiSource[i].fIndex, 0L, 0L, CALLBACK_NULL); - if (ret == MMSYSERR_NOERROR) { - fMidiSource[i].fHandle = handle; - if (!InitHeaders(&fMidiSource[i])) { - jack_error("memory allocation failed"); - midiOutClose(handle); - //continue; - goto error; - } - res = midiOutPrepareHeader(handle, fMidiSource[i].fHeader, sizeof(MIDIHDR)); - if (res != MMSYSERR_NOERROR) { - jack_error("midiOutPrepareHeader error %d %d %d", i, handle, res); - //continue; - goto error; - } else { - fMidiSource[i].fHeader->dwUser = 1; - } - } else { - jack_error("midiOutOpen error"); - goto error; - } - } - - return 0; - -error: - Close(); - return -1; -} - -void JackWinMMEDriver::CloseInput(MidiSlot* slot) -{ - MMRESULT res; - int retry = 0; - - if (slot->fHandle == 0) - return; - - HMIDIIN handle = (HMIDIIN)slot->fHandle; - slot->fHeader->dwUser = 0; - res = midiInStop(handle); - if (res != MMSYSERR_NOERROR) { - jack_error("midiInStop error"); - } - res = midiInReset(handle); - if (res != MMSYSERR_NOERROR) { - jack_error("midiInReset error"); - } - res = midiInUnprepareHeader(handle, slot->fHeader, sizeof(MIDIHDR)); - if (res != MMSYSERR_NOERROR) { - jack_error("midiInUnprepareHeader error"); - } - do { - res = midiInClose(handle); - if (res != MMSYSERR_NOERROR) { - jack_error("midiInClose error"); - } - if (res == MIDIERR_STILLPLAYING) - midiInReset(handle); - Sleep (10); - retry++; - } while ((res == MIDIERR_STILLPLAYING) && (retry < 10)); - - if (slot->fHeader) { - GlobalFreePtr(slot->fHeader); - } -} - -void JackWinMMEDriver::CloseOutput(MidiSlot* slot) -{ - MMRESULT res; - int retry = 0; - - if (slot->fHandle == 0) - return; - - HMIDIOUT handle = (HMIDIOUT)slot->fHandle; - res = midiOutReset(handle); - if (res != MMSYSERR_NOERROR) - jack_error("midiOutReset error"); - midiOutUnprepareHeader(handle, slot->fHeader, sizeof(MIDIHDR)); - do { - res = midiOutClose(handle); - if (res != MMSYSERR_NOERROR) - jack_error("midiOutClose error"); - Sleep(10); - retry++; - } while ((res == MIDIERR_STILLPLAYING) && (retry < 10)); - - if (slot->fHeader) { - GlobalFreePtr(slot->fHeader); - } -} - -int JackWinMMEDriver::Close() -{ - jack_log("JackWinMMEDriver::Close"); - - // Close input - if (fMidiDestination) { - for (int i = 0; i < fRealCaptureChannels; i++) { - CloseInput(&fMidiDestination[i]); - } - delete[] fMidiDestination; - } - - // Close output - if (fMidiSource) { - for (int i = 0; i < fRealPlaybackChannels; i++) { - CloseOutput(&fMidiSource[i]); - } - delete[] fMidiSource; - } - - return 0; -} - -int JackWinMMEDriver::Attach() -{ - JackPort* port; - jack_port_id_t port_index; - char name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE]; - char alias[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE]; - unsigned long port_flags = JackPortIsOutput | JackPortIsPhysical | JackPortIsTerminal; - MMRESULT res; - int i; - - jack_log("JackMidiDriver::Attach fBufferSize = %ld fSampleRate = %ld", fEngineControl->fBufferSize, fEngineControl->fSampleRate); - - for (i = 0; i < fCaptureChannels; i++) { - MIDIINCAPS caps; - res = midiInGetDevCaps(i, &caps, sizeof(caps)); - if (res == MMSYSERR_NOERROR) { - snprintf(alias, sizeof(alias) - 1, "%s:%s:out%d", fAliasName, caps.szPname, i + 1); - } else { - snprintf(alias, sizeof(alias) - 1, "%s:%s:out%d", fAliasName, fCaptureDriverName, i + 1); - } - snprintf(name, sizeof(name) - 1, "%s:capture_%d", fClientControl.fName, i + 1); - - if ((port_index = fGraphManager->AllocatePort(fClientControl.fRefNum, name, JACK_DEFAULT_MIDI_TYPE, (JackPortFlags)port_flags, fEngineControl->fBufferSize)) == NO_PORT) { - jack_error("driver: cannot register port for %s", name); - return -1; - } - port = fGraphManager->GetPort(port_index); - port->SetAlias(alias); - fCapturePortList[i] = port_index; - jack_log("JackMidiDriver::Attach fCapturePortList[i] port_index = %ld", port_index); - } - - port_flags = JackPortIsInput | JackPortIsPhysical | JackPortIsTerminal; - - for (i = 0; i < fPlaybackChannels; i++) { - MIDIOUTCAPS caps; - res = midiOutGetDevCaps(i, &caps, sizeof(caps)); - if (res == MMSYSERR_NOERROR) { - snprintf(alias, sizeof(alias) - 1, "%s:%s:out%d", fAliasName, caps.szPname, i + 1); - } else { - snprintf(alias, sizeof(alias) - 1, "%s:%s:out%d", fAliasName, fPlaybackDriverName, i + 1); - } - snprintf(name, sizeof(name) - 1, "%s:playback_%d", fClientControl.fName, i + 1); - - if ((port_index = fGraphManager->AllocatePort(fClientControl.fRefNum, name, JACK_DEFAULT_MIDI_TYPE, (JackPortFlags)port_flags, fEngineControl->fBufferSize)) == NO_PORT) { - jack_error("driver: cannot register port for %s", name); - return -1; - } - port = fGraphManager->GetPort(port_index); - port->SetAlias(alias); - fPlaybackPortList[i] = port_index; - jack_log("JackMidiDriver::Attach fPlaybackPortList[i] port_index = %ld", port_index); - } - - return 0; -} - -int JackWinMMEDriver::Read() -{ - size_t size; - - for (int chan = 0; chan < fCaptureChannels; chan++) { - - if (fGraphManager->GetConnectionsNum(fCapturePortList[chan]) > 0) { - - JackMidiBuffer* midi_buffer = GetInputBuffer(chan); - - if (jack_ringbuffer_read_space (fRingBuffer[chan]) == 0) { - // Reset buffer - midi_buffer->Reset(midi_buffer->nframes); - } else { - - while ((size = jack_ringbuffer_read_space (fRingBuffer[chan])) > 0) { - - //jack_info("jack_ringbuffer_read_space %d", size); - int ev_count = 0; - jack_ringbuffer_read(fRingBuffer[chan], (char*)&ev_count, sizeof(int)); - - if (ev_count > 0) { - for (int j = 0; j < ev_count; j++) { - unsigned int event_len = 3; - // Read event actual data - jack_midi_data_t* dest = midi_buffer->ReserveEvent(0, event_len); - jack_ringbuffer_read(fRingBuffer[chan], (char*)dest, event_len); - } - } - } - } - } else { - //jack_info("Consume ring buffer"); - jack_ringbuffer_read_advance(fRingBuffer[chan], jack_ringbuffer_read_space(fRingBuffer[chan])); - } - } - return 0; -} - -int JackWinMMEDriver::Write() -{ - for (int chan = 0; chan < fPlaybackChannels; chan++) { - - if (fGraphManager->GetConnectionsNum(fPlaybackPortList[chan]) > 0) { - - JackMidiBuffer* midi_buffer = GetOutputBuffer(chan); - - // TODO : use timestamp - - for (unsigned int j = 0; j < midi_buffer->event_count; j++) { - JackMidiEvent* ev = &midi_buffer->events[j]; - if (ev->size <= 3) { - MMRESULT res = midiOutShortMsg((HMIDIOUT)fMidiSource[chan].fHandle, *((DWORD*)ev->GetData(midi_buffer))); - if (res != MMSYSERR_NOERROR) - jack_error ("midiOutShortMsg error res %d", res); - } else { - - } - } - } - } - - return 0; -} - -} // end of namespace - -#ifdef __cplusplus -extern "C" -{ -#endif - - SERVER_EXPORT jack_driver_desc_t * driver_get_descriptor() - { - jack_driver_desc_t * desc; - unsigned int i; - - desc = (jack_driver_desc_t*)calloc (1, sizeof (jack_driver_desc_t)); - strcpy(desc->name, "winmme"); // size MUST be less then JACK_DRIVER_NAME_MAX + 1 - strcpy(desc->desc, "WinMME API based MIDI backend"); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1 - - desc->nparams = 0; - desc->params = (jack_driver_param_desc_t*)calloc (desc->nparams, sizeof (jack_driver_param_desc_t)); - - return desc; - } - - SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params) - { - /* - unsigned int capture_ports = 2; - unsigned int playback_ports = 2; - unsigned long wait_time = 0; - const JSList * node; - const jack_driver_param_t * param; - bool monitor = false; - - for (node = params; node; node = jack_slist_next (node)) { - param = (const jack_driver_param_t *) node->data; - - switch (param->character) { - - case 'C': - capture_ports = param->value.ui; - break; - - case 'P': - playback_ports = param->value.ui; - break; - - case 'r': - sample_rate = param->value.ui; - break; - - case 'p': - period_size = param->value.ui; - break; - - case 'w': - wait_time = param->value.ui; - break; - - case 'm': - monitor = param->value.i; - break; - } - } - */ - - Jack::JackDriverClientInterface* driver = new Jack::JackWinMMEDriver("system_midi", "winmme", engine, table); - if (driver->Open(1, 1, 0, 0, false, "in", "out", 0, 0) == 0) { - return driver; - } else { - delete driver; - return NULL; - } - } - -#ifdef __cplusplus -} -#endif - - -/* -jack_connect system:midi_capture_1 system_midi:playback_1 -jack_connect system:midi_capture_1 system_midi:playback_2 - -jack_connect system:midi_capture_1 system_midi:playback_1 - -jack_connect system:midi_capture_1 system_midi:playback_1 - -jack_connect system:midi_capture_1 system_midi:playback_1 - -jack_connect system_midi:capture_1 system:midi_playback_1 -jack_connect system_midi:capture_2 system:midi_playback_1 - -jack_connect system_midi:capture_1 system_midi:playback_1 - -*/ +/* +Copyright (C) 2009 Grame + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include "JackWinMMEDriver.h" +#include "JackGraphManager.h" +#include "JackEngineControl.h" +#include "JackDriverLoader.h" + +#include +#include +#include +#include + +#include +#include +#include + +namespace Jack +{ + +static bool InitHeaders(MidiSlot* slot) +{ + slot->fHeader = (LPMIDIHDR)GlobalAllocPtr(GMEM_MOVEABLE|GMEM_SHARE|GMEM_ZEROINIT, sizeof(MIDIHDR) + kBuffSize); + if (!slot->fHeader) + return false; + + slot->fHeader->lpData = (LPSTR)((LPBYTE)slot->fHeader + sizeof(MIDIHDR)); + slot->fHeader->dwBufferLength = kBuffSize; + slot->fHeader->dwFlags = 0; + slot->fHeader->dwUser = 0; + slot->fHeader->lpNext = 0; + slot->fHeader->dwBytesRecorded = 0; + return true; +} + +void CALLBACK JackWinMMEDriver::MidiInProc(HMIDIIN hMidiIn, UINT wMsg, DWORD userData, DWORD dwParam1, DWORD dwParam2) +{ + jack_ringbuffer_t* ringbuffer = (jack_ringbuffer_t*)userData; + //jack_info("JackWinMMEDriver::MidiInProc 0\n"); + + switch (wMsg) { + case MIM_OPEN: + break; + + case MIM_ERROR: + case MIM_DATA: { + + //jack_info("JackWinMMEDriver::MidiInProc"); + + // One event + unsigned int num_packet = 1; + jack_ringbuffer_write(ringbuffer, (char*)&num_packet, sizeof(unsigned int)); + + // Write event actual data + jack_ringbuffer_write(ringbuffer, (char*)&dwParam1, 3); + break; + } + + case MIM_LONGERROR: + case MIM_LONGDATA: + /* + Nothing for now + */ + break; + } +} + +JackWinMMEDriver::JackWinMMEDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table) + : JackMidiDriver(name, alias, engine, table), + fRealCaptureChannels(0), + fRealPlaybackChannels(0), + fMidiSource(NULL), + fMidiDestination(NULL) +{} + +JackWinMMEDriver::~JackWinMMEDriver() +{} + +int JackWinMMEDriver::Open(bool capturing, + bool playing, + int inchannels, + int outchannels, + bool monitor, + const char* capture_driver_name, + const char* playback_driver_name, + jack_nframes_t capture_latency, + jack_nframes_t playback_latency) +{ + + jack_log("JackWinMMEDriver::Open"); + + fRealCaptureChannels = midiInGetNumDevs(); + fRealPlaybackChannels = midiOutGetNumDevs(); + + // Generic JackMidiDriver Open + if (JackMidiDriver::Open(capturing, playing, fRealCaptureChannels, fRealPlaybackChannels, monitor, capture_driver_name, playback_driver_name, capture_latency, playback_latency) != 0) + return -1; + + fMidiDestination = new MidiSlot[fRealCaptureChannels]; + assert(fMidiDestination); + + // Real input + for (int i = 0; i < fRealCaptureChannels; i++) { + + HMIDIIN handle; + fMidiDestination[i].fIndex = i; + MMRESULT ret = midiInOpen(&handle, fMidiDestination[i].fIndex, (DWORD)MidiInProc, (DWORD)fRingBuffer[i], CALLBACK_FUNCTION); + + if (ret == MMSYSERR_NOERROR) { + fMidiDestination[i].fHandle = handle; + if (!InitHeaders(&fMidiDestination[i])) { + jack_error("memory allocation failed"); + midiInClose(handle); + goto error; + //continue; + } + ret = midiInPrepareHeader(handle, fMidiDestination[i].fHeader, sizeof(MIDIHDR)); + + if (ret == MMSYSERR_NOERROR) { + fMidiDestination[i].fHeader->dwUser = 1; + ret = midiInAddBuffer(handle, fMidiDestination[i].fHeader, sizeof(MIDIHDR)); + if (ret == MMSYSERR_NOERROR) { + ret = midiInStart(handle); + if (ret != MMSYSERR_NOERROR) { + jack_error("midiInStart error"); + CloseInput(&fMidiDestination[i]); + goto error; + } + } else { + jack_error ("midiInAddBuffer error"); + CloseInput(&fMidiDestination[i]); + goto error; + } + } else { + jack_error("midiInPrepareHeader error"); + midiInClose(handle); + goto error; + } + } else { + jack_error ("midiInOpen error"); + goto error; + } + } + + fMidiSource = new MidiSlot[fRealPlaybackChannels]; + assert(fMidiSource); + + // Real output + for (int i = 0; i < fRealPlaybackChannels; i++) { + MMRESULT res; + HMIDIOUT handle; + fMidiSource[i].fIndex = i; + UINT ret = midiOutOpen(&handle, fMidiSource[i].fIndex, 0L, 0L, CALLBACK_NULL); + if (ret == MMSYSERR_NOERROR) { + fMidiSource[i].fHandle = handle; + if (!InitHeaders(&fMidiSource[i])) { + jack_error("memory allocation failed"); + midiOutClose(handle); + //continue; + goto error; + } + res = midiOutPrepareHeader(handle, fMidiSource[i].fHeader, sizeof(MIDIHDR)); + if (res != MMSYSERR_NOERROR) { + jack_error("midiOutPrepareHeader error %d %d %d", i, handle, res); + //continue; + goto error; + } else { + fMidiSource[i].fHeader->dwUser = 1; + } + } else { + jack_error("midiOutOpen error"); + goto error; + } + } + + return 0; + +error: + Close(); + return -1; +} + +void JackWinMMEDriver::CloseInput(MidiSlot* slot) +{ + MMRESULT res; + int retry = 0; + + if (slot->fHandle == 0) + return; + + HMIDIIN handle = (HMIDIIN)slot->fHandle; + slot->fHeader->dwUser = 0; + res = midiInStop(handle); + if (res != MMSYSERR_NOERROR) { + jack_error("midiInStop error"); + } + res = midiInReset(handle); + if (res != MMSYSERR_NOERROR) { + jack_error("midiInReset error"); + } + res = midiInUnprepareHeader(handle, slot->fHeader, sizeof(MIDIHDR)); + if (res != MMSYSERR_NOERROR) { + jack_error("midiInUnprepareHeader error"); + } + do { + res = midiInClose(handle); + if (res != MMSYSERR_NOERROR) { + jack_error("midiInClose error"); + } + if (res == MIDIERR_STILLPLAYING) + midiInReset(handle); + Sleep (10); + retry++; + } while ((res == MIDIERR_STILLPLAYING) && (retry < 10)); + + if (slot->fHeader) { + GlobalFreePtr(slot->fHeader); + } +} + +void JackWinMMEDriver::CloseOutput(MidiSlot* slot) +{ + MMRESULT res; + int retry = 0; + + if (slot->fHandle == 0) + return; + + HMIDIOUT handle = (HMIDIOUT)slot->fHandle; + res = midiOutReset(handle); + if (res != MMSYSERR_NOERROR) + jack_error("midiOutReset error"); + midiOutUnprepareHeader(handle, slot->fHeader, sizeof(MIDIHDR)); + do { + res = midiOutClose(handle); + if (res != MMSYSERR_NOERROR) + jack_error("midiOutClose error"); + Sleep(10); + retry++; + } while ((res == MIDIERR_STILLPLAYING) && (retry < 10)); + + if (slot->fHeader) { + GlobalFreePtr(slot->fHeader); + } +} + +int JackWinMMEDriver::Close() +{ + jack_log("JackWinMMEDriver::Close"); + + // Close input + if (fMidiDestination) { + for (int i = 0; i < fRealCaptureChannels; i++) { + CloseInput(&fMidiDestination[i]); + } + delete[] fMidiDestination; + } + + // Close output + if (fMidiSource) { + for (int i = 0; i < fRealPlaybackChannels; i++) { + CloseOutput(&fMidiSource[i]); + } + delete[] fMidiSource; + } + + return 0; +} + +int JackWinMMEDriver::Attach() +{ + JackPort* port; + jack_port_id_t port_index; + char name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE]; + char alias[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE]; + unsigned long port_flags = JackPortIsOutput | JackPortIsPhysical | JackPortIsTerminal; + MMRESULT res; + int i; + + jack_log("JackMidiDriver::Attach fBufferSize = %ld fSampleRate = %ld", fEngineControl->fBufferSize, fEngineControl->fSampleRate); + + for (i = 0; i < fCaptureChannels; i++) { + MIDIINCAPS caps; + res = midiInGetDevCaps(i, &caps, sizeof(caps)); + if (res == MMSYSERR_NOERROR) { + snprintf(alias, sizeof(alias) - 1, "%s:%s:out%d", fAliasName, caps.szPname, i + 1); + } else { + snprintf(alias, sizeof(alias) - 1, "%s:%s:out%d", fAliasName, fCaptureDriverName, i + 1); + } + snprintf(name, sizeof(name) - 1, "%s:capture_%d", fClientControl.fName, i + 1); + + if ((port_index = fGraphManager->AllocatePort(fClientControl.fRefNum, name, JACK_DEFAULT_MIDI_TYPE, (JackPortFlags)port_flags, fEngineControl->fBufferSize)) == NO_PORT) { + jack_error("driver: cannot register port for %s", name); + return -1; + } + port = fGraphManager->GetPort(port_index); + port->SetAlias(alias); + fCapturePortList[i] = port_index; + jack_log("JackMidiDriver::Attach fCapturePortList[i] port_index = %ld", port_index); + } + + port_flags = JackPortIsInput | JackPortIsPhysical | JackPortIsTerminal; + + for (i = 0; i < fPlaybackChannels; i++) { + MIDIOUTCAPS caps; + res = midiOutGetDevCaps(i, &caps, sizeof(caps)); + if (res == MMSYSERR_NOERROR) { + snprintf(alias, sizeof(alias) - 1, "%s:%s:out%d", fAliasName, caps.szPname, i + 1); + } else { + snprintf(alias, sizeof(alias) - 1, "%s:%s:out%d", fAliasName, fPlaybackDriverName, i + 1); + } + snprintf(name, sizeof(name) - 1, "%s:playback_%d", fClientControl.fName, i + 1); + + if ((port_index = fGraphManager->AllocatePort(fClientControl.fRefNum, name, JACK_DEFAULT_MIDI_TYPE, (JackPortFlags)port_flags, fEngineControl->fBufferSize)) == NO_PORT) { + jack_error("driver: cannot register port for %s", name); + return -1; + } + port = fGraphManager->GetPort(port_index); + port->SetAlias(alias); + fPlaybackPortList[i] = port_index; + jack_log("JackMidiDriver::Attach fPlaybackPortList[i] port_index = %ld", port_index); + } + + return 0; +} + +int JackWinMMEDriver::Read() +{ + size_t size; + + for (int chan = 0; chan < fCaptureChannels; chan++) { + + if (fGraphManager->GetConnectionsNum(fCapturePortList[chan]) > 0) { + + JackMidiBuffer* midi_buffer = GetInputBuffer(chan); + + if (jack_ringbuffer_read_space (fRingBuffer[chan]) == 0) { + // Reset buffer + midi_buffer->Reset(midi_buffer->nframes); + } else { + + while ((size = jack_ringbuffer_read_space (fRingBuffer[chan])) > 0) { + + //jack_info("jack_ringbuffer_read_space %d", size); + int ev_count = 0; + jack_ringbuffer_read(fRingBuffer[chan], (char*)&ev_count, sizeof(int)); + + if (ev_count > 0) { + for (int j = 0; j < ev_count; j++) { + unsigned int event_len = 3; + // Read event actual data + jack_midi_data_t* dest = midi_buffer->ReserveEvent(0, event_len); + jack_ringbuffer_read(fRingBuffer[chan], (char*)dest, event_len); + } + } + } + } + } else { + //jack_info("Consume ring buffer"); + jack_ringbuffer_read_advance(fRingBuffer[chan], jack_ringbuffer_read_space(fRingBuffer[chan])); + } + } + return 0; +} + +int JackWinMMEDriver::Write() +{ + for (int chan = 0; chan < fPlaybackChannels; chan++) { + + if (fGraphManager->GetConnectionsNum(fPlaybackPortList[chan]) > 0) { + + JackMidiBuffer* midi_buffer = GetOutputBuffer(chan); + + // TODO : use timestamp + + for (unsigned int j = 0; j < midi_buffer->event_count; j++) { + JackMidiEvent* ev = &midi_buffer->events[j]; + if (ev->size <= 3) { + MMRESULT res = midiOutShortMsg((HMIDIOUT)fMidiSource[chan].fHandle, *((DWORD*)ev->GetData(midi_buffer))); + if (res != MMSYSERR_NOERROR) + jack_error ("midiOutShortMsg error res %d", res); + } else { + + } + } + } + } + + return 0; +} + +} // end of namespace + +#ifdef __cplusplus +extern "C" +{ +#endif + + SERVER_EXPORT jack_driver_desc_t * driver_get_descriptor() + { + jack_driver_desc_t * desc; + unsigned int i; + + desc = (jack_driver_desc_t*)calloc (1, sizeof (jack_driver_desc_t)); + strcpy(desc->name, "winmme"); // size MUST be less then JACK_DRIVER_NAME_MAX + 1 + strcpy(desc->desc, "WinMME API based MIDI backend"); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1 + + desc->nparams = 0; + desc->params = (jack_driver_param_desc_t*)calloc (desc->nparams, sizeof (jack_driver_param_desc_t)); + + return desc; + } + + SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params) + { + /* + unsigned int capture_ports = 2; + unsigned int playback_ports = 2; + unsigned long wait_time = 0; + const JSList * node; + const jack_driver_param_t * param; + bool monitor = false; + + for (node = params; node; node = jack_slist_next (node)) { + param = (const jack_driver_param_t *) node->data; + + switch (param->character) { + + case 'C': + capture_ports = param->value.ui; + break; + + case 'P': + playback_ports = param->value.ui; + break; + + case 'r': + sample_rate = param->value.ui; + break; + + case 'p': + period_size = param->value.ui; + break; + + case 'w': + wait_time = param->value.ui; + break; + + case 'm': + monitor = param->value.i; + break; + } + } + */ + + Jack::JackDriverClientInterface* driver = new Jack::JackWinMMEDriver("system_midi", "winmme", engine, table); + if (driver->Open(1, 1, 0, 0, false, "in", "out", 0, 0) == 0) { + return driver; + } else { + delete driver; + return NULL; + } + } + +#ifdef __cplusplus +} +#endif + + +/* +jack_connect system:midi_capture_1 system_midi:playback_1 +jack_connect system:midi_capture_1 system_midi:playback_2 + +jack_connect system:midi_capture_1 system_midi:playback_1 + +jack_connect system:midi_capture_1 system_midi:playback_1 + +jack_connect system:midi_capture_1 system_midi:playback_1 + +jack_connect system_midi:capture_1 system:midi_playback_1 +jack_connect system_midi:capture_2 system:midi_playback_1 + +jack_connect system_midi:capture_1 system_midi:playback_1 + +*/