| 
							- /*
 -   ==============================================================================
 - 
 -    This file is part of the JUCE library - "Jules' Utility Class Extensions"
 -    Copyright 2004-11 by Raw Material Software Ltd.
 - 
 -   ------------------------------------------------------------------------------
 - 
 -    JUCE can be redistributed and/or modified under the terms of the GNU General
 -    Public License (Version 2), as published by the Free Software Foundation.
 -    A copy of the license is included in the JUCE distribution, or can be found
 -    online at www.gnu.org/licenses.
 - 
 -    JUCE 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.
 - 
 -   ------------------------------------------------------------------------------
 - 
 -    To release a closed-source product which uses JUCE, commercial licenses are
 -    available: visit www.rawmaterialsoftware.com/juce for more information.
 - 
 -   ==============================================================================
 - */
 - 
 - class MidiInCollector
 - {
 - public:
 -     //==============================================================================
 -     MidiInCollector (MidiInput* const input_,
 -                      MidiInputCallback& callback_)
 -         : deviceHandle (0),
 -           input (input_),
 -           callback (callback_),
 -           concatenator (4096),
 -           isStarted (false),
 -           startTime (0)
 -     {
 -     }
 - 
 -     ~MidiInCollector()
 -     {
 -         stop();
 - 
 -         if (deviceHandle != 0)
 -         {
 -             int count = 5;
 -             while (--count >= 0)
 -             {
 -                 if (midiInClose (deviceHandle) == MMSYSERR_NOERROR)
 -                     break;
 - 
 -                 Sleep (20);
 -             }
 -         }
 -     }
 - 
 -     //==============================================================================
 -     void handleMessage (const uint32 message, const uint32 timeStamp)
 -     {
 -         if ((message & 0xff) >= 0x80 && isStarted)
 -         {
 -             concatenator.pushMidiData (&message, 3, convertTimeStamp (timeStamp), input, callback);
 -             writeFinishedBlocks();
 -         }
 -     }
 - 
 -     void handleSysEx (MIDIHDR* const hdr, const uint32 timeStamp)
 -     {
 -         if (isStarted && hdr->dwBytesRecorded > 0)
 -         {
 -             concatenator.pushMidiData (hdr->lpData, (int) hdr->dwBytesRecorded, convertTimeStamp (timeStamp), input, callback);
 -             writeFinishedBlocks();
 -         }
 -     }
 - 
 -     void start()
 -     {
 -         jassert (deviceHandle != 0);
 -         if (deviceHandle != 0 && ! isStarted)
 -         {
 -             activeMidiCollectors.addIfNotAlreadyThere (this);
 - 
 -             for (int i = 0; i < (int) numHeaders; ++i)
 -                 headers[i].write (deviceHandle);
 - 
 -             startTime = Time::getMillisecondCounter();
 -             MMRESULT res = midiInStart (deviceHandle);
 - 
 -             if (res == MMSYSERR_NOERROR)
 -             {
 -                 concatenator.reset();
 -                 isStarted = true;
 -             }
 -             else
 -             {
 -                 unprepareAllHeaders();
 -             }
 -         }
 -     }
 - 
 -     void stop()
 -     {
 -         if (isStarted)
 -         {
 -             isStarted = false;
 -             midiInReset (deviceHandle);
 -             midiInStop (deviceHandle);
 -             activeMidiCollectors.removeValue (this);
 -             unprepareAllHeaders();
 -             concatenator.reset();
 -         }
 -     }
 - 
 -     static void CALLBACK midiInCallback (HMIDIIN, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR midiMessage, DWORD_PTR timeStamp)
 -     {
 -         MidiInCollector* const collector = reinterpret_cast <MidiInCollector*> (dwInstance);
 - 
 -         if (activeMidiCollectors.contains (collector))
 -         {
 -             if (uMsg == MIM_DATA)
 -                 collector->handleMessage ((uint32) midiMessage, (uint32) timeStamp);
 -             else if (uMsg == MIM_LONGDATA)
 -                 collector->handleSysEx ((MIDIHDR*) midiMessage, (uint32) timeStamp);
 -         }
 -     }
 - 
 -     HMIDIIN deviceHandle;
 - 
 - private:
 -     static Array <MidiInCollector*, CriticalSection> activeMidiCollectors;
 - 
 -     MidiInput* input;
 -     MidiInputCallback& callback;
 -     MidiDataConcatenator concatenator;
 -     bool volatile isStarted;
 -     uint32 startTime;
 - 
 -     class MidiHeader
 -     {
 -     public:
 -         MidiHeader()
 -         {
 -             zerostruct (hdr);
 -             hdr.lpData = data;
 -             hdr.dwBufferLength = (DWORD) numElementsInArray (data);
 -         }
 - 
 -         void write (HMIDIIN deviceHandle)
 -         {
 -             hdr.dwBytesRecorded = 0;
 -             MMRESULT res = midiInPrepareHeader (deviceHandle, &hdr, sizeof (hdr));
 -             res = midiInAddBuffer (deviceHandle, &hdr, sizeof (hdr));
 -         }
 - 
 -         void writeIfFinished (HMIDIIN deviceHandle)
 -         {
 -             if ((hdr.dwFlags & WHDR_DONE) != 0)
 -             {
 -                 MMRESULT res = midiInUnprepareHeader (deviceHandle, &hdr, sizeof (hdr));
 -                 (void) res;
 -                 write (deviceHandle);
 -             }
 -         }
 - 
 -         void unprepare (HMIDIIN deviceHandle)
 -         {
 -             if ((hdr.dwFlags & WHDR_DONE) != 0)
 -             {
 -                 int c = 10;
 -                 while (--c >= 0 && midiInUnprepareHeader (deviceHandle, &hdr, sizeof (hdr)) == MIDIERR_STILLPLAYING)
 -                     Thread::sleep (20);
 - 
 -                 jassert (c >= 0);
 -             }
 -         }
 - 
 -     private:
 -         MIDIHDR hdr;
 -         char data [256];
 - 
 -         JUCE_DECLARE_NON_COPYABLE (MidiHeader);
 -     };
 - 
 -     enum { numHeaders = 32 };
 -     MidiHeader headers [numHeaders];
 - 
 -     void writeFinishedBlocks()
 -     {
 -         for (int i = 0; i < (int) numHeaders; ++i)
 -             headers[i].writeIfFinished (deviceHandle);
 -     }
 - 
 -     void unprepareAllHeaders()
 -     {
 -         for (int i = 0; i < (int) numHeaders; ++i)
 -             headers[i].unprepare (deviceHandle);
 -     }
 - 
 -     double convertTimeStamp (uint32 timeStamp)
 -     {
 -         timeStamp += startTime;
 - 
 -         const uint32 now = Time::getMillisecondCounter();
 -         if (timeStamp > now)
 -         {
 -             if (timeStamp > now + 2)
 -                 --startTime;
 - 
 -             timeStamp = now;
 -         }
 - 
 -         return timeStamp * 0.001;
 -     }
 - 
 -     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MidiInCollector);
 - };
 - 
 - Array <MidiInCollector*, CriticalSection> MidiInCollector::activeMidiCollectors;
 - 
 - 
 - //==============================================================================
 - StringArray MidiInput::getDevices()
 - {
 -     StringArray s;
 -     const UINT num = midiInGetNumDevs();
 - 
 -     for (UINT i = 0; i < num; ++i)
 -     {
 -         MIDIINCAPS mc = { 0 };
 - 
 -         if (midiInGetDevCaps (i, &mc, sizeof (mc)) == MMSYSERR_NOERROR)
 -             s.add (String (mc.szPname, sizeof (mc.szPname)));
 -     }
 - 
 -     return s;
 - }
 - 
 - int MidiInput::getDefaultDeviceIndex()
 - {
 -     return 0;
 - }
 - 
 - MidiInput* MidiInput::openDevice (const int index, MidiInputCallback* const callback)
 - {
 -     if (callback == nullptr)
 -         return nullptr;
 - 
 -     UINT deviceId = MIDI_MAPPER;
 -     int n = 0;
 -     String name;
 - 
 -     const UINT num = midiInGetNumDevs();
 - 
 -     for (UINT i = 0; i < num; ++i)
 -     {
 -         MIDIINCAPS mc = { 0 };
 - 
 -         if (midiInGetDevCaps (i, &mc, sizeof (mc)) == MMSYSERR_NOERROR)
 -         {
 -             if (index == n)
 -             {
 -                 deviceId = i;
 -                 name = String (mc.szPname, (size_t) numElementsInArray (mc.szPname));
 -                 break;
 -             }
 - 
 -             ++n;
 -         }
 -     }
 - 
 -     ScopedPointer <MidiInput> in (new MidiInput (name));
 -     ScopedPointer <MidiInCollector> collector (new MidiInCollector (in, *callback));
 - 
 -     HMIDIIN h;
 -     MMRESULT err = midiInOpen (&h, deviceId,
 -                                (DWORD_PTR) &MidiInCollector::midiInCallback,
 -                                (DWORD_PTR) (MidiInCollector*) collector,
 -                                CALLBACK_FUNCTION);
 - 
 -     if (err == MMSYSERR_NOERROR)
 -     {
 -         collector->deviceHandle = h;
 -         in->internal = collector.release();
 -         return in.release();
 -     }
 - 
 -     return nullptr;
 - }
 - 
 - MidiInput::MidiInput (const String& name_)
 -     : name (name_),
 -       internal (0)
 - {
 - }
 - 
 - MidiInput::~MidiInput()
 - {
 -     delete static_cast <MidiInCollector*> (internal);
 - }
 - 
 - void MidiInput::start()
 - {
 -     static_cast <MidiInCollector*> (internal)->start();
 - }
 - 
 - void MidiInput::stop()
 - {
 -     static_cast <MidiInCollector*> (internal)->stop();
 - }
 - 
 - 
 - //==============================================================================
 - struct MidiOutHandle
 - {
 -     int refCount;
 -     UINT deviceId;
 -     HMIDIOUT handle;
 - 
 -     static Array<MidiOutHandle*> activeHandles;
 - 
 - private:
 -     JUCE_LEAK_DETECTOR (MidiOutHandle);
 - };
 - 
 - Array<MidiOutHandle*> MidiOutHandle::activeHandles;
 - 
 - //==============================================================================
 - StringArray MidiOutput::getDevices()
 - {
 -     StringArray s;
 -     const UINT num = midiOutGetNumDevs();
 - 
 -     for (UINT i = 0; i < num; ++i)
 -     {
 -         MIDIOUTCAPS mc = { 0 };
 - 
 -         if (midiOutGetDevCaps (i, &mc, sizeof (mc)) == MMSYSERR_NOERROR)
 -             s.add (String (mc.szPname, sizeof (mc.szPname)));
 -     }
 - 
 -     return s;
 - }
 - 
 - int MidiOutput::getDefaultDeviceIndex()
 - {
 -     const UINT num = midiOutGetNumDevs();
 -     int n = 0;
 - 
 -     for (UINT i = 0; i < num; ++i)
 -     {
 -         MIDIOUTCAPS mc = { 0 };
 - 
 -         if (midiOutGetDevCaps (i, &mc, sizeof (mc)) == MMSYSERR_NOERROR)
 -         {
 -             if ((mc.wTechnology & MOD_MAPPER) != 0)
 -                 return n;
 - 
 -              ++n;
 -         }
 -     }
 - 
 -     return 0;
 - }
 - 
 - MidiOutput* MidiOutput::openDevice (int index)
 - {
 -     UINT deviceId = MIDI_MAPPER;
 -     const UINT num = midiOutGetNumDevs();
 -     int n = 0;
 - 
 -     {
 -         for (UINT i = 0; i < num; ++i)
 -         {
 -             MIDIOUTCAPS mc = { 0 };
 - 
 -             if (midiOutGetDevCaps (i, &mc, sizeof (mc)) == MMSYSERR_NOERROR)
 -             {
 -                 // use the microsoft sw synth as a default - best not to allow deviceId
 -                 // to be MIDI_MAPPER, or else device sharing breaks
 -                 if (String (mc.szPname, sizeof (mc.szPname)).containsIgnoreCase ("microsoft"))
 -                     deviceId = i;
 - 
 -                 if (index == n)
 -                 {
 -                     deviceId = i;
 -                     break;
 -                 }
 - 
 -                 ++n;
 -             }
 -         }
 -     }
 - 
 -     int i;
 -     for (i = MidiOutHandle::activeHandles.size(); --i >= 0;)
 -     {
 -         MidiOutHandle* const han = MidiOutHandle::activeHandles.getUnchecked(i);
 - 
 -         if (han->deviceId == deviceId)
 -         {
 -             han->refCount++;
 - 
 -             MidiOutput* const out = new MidiOutput();
 -             out->internal = han;
 -             return out;
 -         }
 -     }
 - 
 -     for (i = 4; --i >= 0;)
 -     {
 -         HMIDIOUT h = 0;
 -         MMRESULT res = midiOutOpen (&h, deviceId, 0, 0, CALLBACK_NULL);
 - 
 -         if (res == MMSYSERR_NOERROR)
 -         {
 -             MidiOutHandle* const han = new MidiOutHandle();
 -             han->deviceId = deviceId;
 -             han->refCount = 1;
 -             han->handle = h;
 -             MidiOutHandle::activeHandles.add (han);
 - 
 -             MidiOutput* const out = new MidiOutput();
 -             out->internal = han;
 -             return out;
 -         }
 -         else if (res == MMSYSERR_ALLOCATED)
 -         {
 -             Sleep (100);
 -         }
 -         else
 -         {
 -             break;
 -         }
 -     }
 - 
 -     return nullptr;
 - }
 - 
 - MidiOutput::~MidiOutput()
 - {
 -     stopBackgroundThread();
 - 
 -     MidiOutHandle* const h = static_cast <MidiOutHandle*> (internal);
 - 
 -     if (MidiOutHandle::activeHandles.contains (h) && --(h->refCount) == 0)
 -     {
 -         midiOutClose (h->handle);
 -         MidiOutHandle::activeHandles.removeValue (h);
 -         delete h;
 -     }
 - }
 - 
 - void MidiOutput::sendMessageNow (const MidiMessage& message)
 - {
 -     const MidiOutHandle* const handle = static_cast <const MidiOutHandle*> (internal);
 - 
 -     if (message.getRawDataSize() > 3
 -          || message.isSysEx())
 -     {
 -         MIDIHDR h = { 0 };
 - 
 -         h.lpData = (char*) message.getRawData();
 -         h.dwBufferLength = (DWORD) message.getRawDataSize();
 -         h.dwBytesRecorded = (DWORD) message.getRawDataSize();
 - 
 -         if (midiOutPrepareHeader (handle->handle, &h, sizeof (MIDIHDR)) == MMSYSERR_NOERROR)
 -         {
 -             MMRESULT res = midiOutLongMsg (handle->handle, &h, sizeof (MIDIHDR));
 - 
 -             if (res == MMSYSERR_NOERROR)
 -             {
 -                 while ((h.dwFlags & MHDR_DONE) == 0)
 -                     Sleep (1);
 - 
 -                 int count = 500; // 1 sec timeout
 - 
 -                 while (--count >= 0)
 -                 {
 -                     res = midiOutUnprepareHeader (handle->handle, &h, sizeof (MIDIHDR));
 - 
 -                     if (res == MIDIERR_STILLPLAYING)
 -                         Sleep (2);
 -                     else
 -                         break;
 -                 }
 -             }
 -         }
 -     }
 -     else
 -     {
 -         midiOutShortMsg (handle->handle,
 -                          *(unsigned int*) message.getRawData());
 -     }
 - }
 
 
  |