| 
							- /*
 -   ==============================================================================
 - 
 -    This file is part of the JUCE library - "Jules' Utility Class Extensions"
 -    Copyright 2004-7 by Raw Material Software ltd.
 - 
 -   ------------------------------------------------------------------------------
 - 
 -    JUCE can be redistributed and/or modified 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.
 - 
 -    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.
 - 
 -    You should have received a copy of the GNU General Public License
 -    along with JUCE; if not, visit www.gnu.org/licenses or write to the
 -    Free Software Foundation, Inc., 59 Temple Place, Suite 330,
 -    Boston, MA 02111-1307 USA
 - 
 -   ------------------------------------------------------------------------------
 - 
 -    If you'd like to release a closed-source product which uses JUCE, commercial
 -    licenses are also available: visit www.rawmaterialsoftware.com/juce for
 -    more information.
 - 
 -   ==============================================================================
 - */
 - 
 - #include "win32_headers.h"
 - #undef WINDOWS
 - 
 - #if JUCE_ASIO
 - 
 - //==============================================================================
 - /*
 -     This is very frustrating - we only need to use a handful of definitions from
 -     a couple of the header files in Steinberg's ASIO SDK, and it'd be easy to copy
 -     about 30 lines of code into this cpp file to create a fully stand-alone ASIO
 -     implementation...
 - 
 -     ..unfortunately that would break Steinberg's license agreement for use of
 -     their SDK, so I'm not allowed to do this.
 - 
 -     This means that anyone who wants to use JUCE's ASIO abilities will have to:
 - 
 -     1) Agree to Steinberg's licensing terms and download the ASIO SDK
 -         (see www.steinberg.net/Steinberg/Developers.asp).
 - 
 -     2) Rebuild the whole of JUCE, setting the global definition JUCE_ASIO (you
 -        can un-comment the "#define JUCE_ASIO" line in juce_Config.h
 -        if you prefer). Make sure that your header search path will find the
 -        iasiodrv.h file that comes with the SDK. (Only about 2-3 of the SDK header
 -        files are actually needed - so to simplify things, you could just copy
 -        these into your JUCE directory).
 - */
 - #include "iasiodrv.h"   // if you're compiling and this line causes an error because
 -                         // you don't have the ASIO SDK installed, you can disable ASIO
 -                         // support by commenting-out the "#define JUCE_ASIO" line in
 -                         // juce_Config.h
 - 
 - #include "../../../src/juce_core/basics/juce_StandardHeader.h"
 - 
 - BEGIN_JUCE_NAMESPACE
 - 
 - #include "../../../src/juce_appframework/audio/devices/juce_AudioIODeviceType.h"
 - #include "../../../src/juce_appframework/audio/devices/juce_AudioDeviceManager.h"
 - #include "../../../src/juce_appframework/gui/components/buttons/juce_TextButton.h"
 - #include "../../../src/juce_appframework/gui/components/lookandfeel/juce_LookAndFeel.h"
 - #include "../../../src/juce_core/threads/juce_ScopedLock.h"
 - #include "../../../src/juce_core/basics/juce_Time.h"
 - #include "../../../src/juce_core/threads/juce_Thread.h"
 - #include "../../../src/juce_appframework/events/juce_Timer.h"
 - #include "../../../src/juce_appframework/events/juce_MessageManager.h"
 - #include "../../../src/juce_appframework/gui/components/windows/juce_AlertWindow.h"
 - #include "../../../src/juce_appframework/gui/components/controls/juce_ListBox.h"
 - #include "../../../src/juce_core/text/juce_LocalisedStrings.h"
 - 
 - 
 - //==============================================================================
 - // #define ASIO_DEBUGGING
 - 
 - #ifdef ASIO_DEBUGGING
 -   #define log(a) { Logger::writeToLog (a); DBG (a) }
 - #else
 -   #define log(a) {}
 - #endif
 - 
 - 
 - //==============================================================================
 - #ifdef ASIO_DEBUGGING
 - static void logError (const String& context, long error)
 - {
 -     String err ("unknown error");
 - 
 -     if (error == ASE_NotPresent)
 -         err = "Not Present";
 -     else if (error == ASE_HWMalfunction)
 -         err = "Hardware Malfunction";
 -     else if (error == ASE_InvalidParameter)
 -         err = "Invalid Parameter";
 -     else if (error == ASE_InvalidMode)
 -         err = "Invalid Mode";
 -     else if (error == ASE_SPNotAdvancing)
 -         err = "Sample position not advancing";
 -     else if (error == ASE_NoClock)
 -         err = "No Clock";
 -     else if (error == ASE_NoMemory)
 -         err = "Out of memory";
 - 
 -     log (T("!!error: ") + context + T(" - ") + err);
 - }
 - #else
 -   #define logError(a, b) {}
 - #endif
 - 
 - //==============================================================================
 - class ASIOAudioIODevice;
 - static ASIOAudioIODevice* volatile currentASIODev[3] = { 0, 0, 0 };
 - 
 - static const int maxASIOChannels = 160;
 - 
 - 
 - //==============================================================================
 - class JUCE_API  ASIOAudioIODevice  : public AudioIODevice,
 -                                      private Timer
 - {
 - public:
 -     Component ourWindow;
 - 
 -     ASIOAudioIODevice (const String& name_, const CLSID classId_, const int slotNumber)
 -        : AudioIODevice (name_, T("ASIO")),
 -          asioObject (0),
 -          classId (classId_),
 -          currentBitDepth (16),
 -          currentSampleRate (0),
 -          tempBuffer (0),
 -          isOpen_ (false),
 -          isStarted (false),
 -          postOutput (true),
 -          insideControlPanelModalLoop (false),
 -          shouldUsePreferredSize (false)
 -     {
 -         name = name_;
 - 
 -         ourWindow.addToDesktop (0);
 -         windowHandle = ourWindow.getWindowHandle();
 - 
 -         jassert (currentASIODev [slotNumber] == 0);
 -         currentASIODev [slotNumber] = this;
 - 
 -         openDevice();
 -     }
 - 
 -     ~ASIOAudioIODevice()
 -     {
 -         for (int i = 0; i < numElementsInArray (currentASIODev); ++i)
 -             if (currentASIODev[i] == this)
 -                 currentASIODev[i] = 0;
 - 
 -         close();
 -         log ("ASIO - exiting");
 -         removeCurrentDriver();
 - 
 -         juce_free (tempBuffer);
 -     }
 - 
 -     void updateSampleRates()
 -     {
 -         // find a list of sample rates..
 -         const double possibleSampleRates[] = { 44100.0, 48000.0, 88200.0, 96000.0, 176400.0, 192000.0 };
 -         sampleRates.clear();
 - 
 -         if (asioObject != 0)
 -         {
 -             for (int index = 0; index < numElementsInArray (possibleSampleRates); ++index)
 -             {
 -                 const long err = asioObject->canSampleRate (possibleSampleRates[index]);
 - 
 -                 if (err == 0)
 -                 {
 -                     sampleRates.add ((int) possibleSampleRates[index]);
 -                     log (T("rate: ") + String ((int) possibleSampleRates[index]));
 -                 }
 -                 else if (err != ASE_NoClock)
 -                 {
 -                     logError (T("CanSampleRate"), err);
 -                 }
 -             }
 - 
 -             if (sampleRates.size() == 0)
 -             {
 -                 double cr = 0;
 -                 const long err = asioObject->getSampleRate (&cr);
 -                 log (T("No sample rates supported - current rate: ") + String ((int) cr));
 - 
 -                 if (err == 0)
 -                     sampleRates.add ((int) cr);
 -             }
 -         }
 -     }
 - 
 -     const StringArray getOutputChannelNames()
 -     {
 -         return outputChannelNames;
 -     }
 - 
 -     const StringArray getInputChannelNames()
 -     {
 -         return inputChannelNames;
 -     }
 - 
 -     int getNumSampleRates()
 -     {
 -         return sampleRates.size();
 -     }
 - 
 -     double getSampleRate (int index)
 -     {
 -         return sampleRates [index];
 -     }
 - 
 -     int getNumBufferSizesAvailable()
 -     {
 -         return bufferSizes.size();
 -     }
 - 
 -     int getBufferSizeSamples (int index)
 -     {
 -         return bufferSizes [index];
 -     }
 - 
 -     int getDefaultBufferSize()
 -     {
 -         return preferredSize;
 -     }
 - 
 -     const String open (const BitArray& inputChannels,
 -                        const BitArray& outputChannels,
 -                        double sr,
 -                        int bufferSizeSamples)
 -     {
 -         close();
 -         currentCallback = 0;
 - 
 -         if (bufferSizeSamples <= 0)
 -             shouldUsePreferredSize = true;
 - 
 -         if (asioObject == 0 || ! isASIOOpen)
 -         {
 -             log ("Warning: device not open");
 -             const String err (openDevice());
 - 
 -             if (asioObject == 0 || ! isASIOOpen)
 -                 return err;
 -         }
 - 
 -         isStarted = false;
 -         bufferIndex = -1;
 -         long err = 0;
 - 
 -         long newPreferredSize = 0;
 - 
 -         // if the preferred size has just changed, assume it's a control panel thing and use it as the new value.
 -         minSize = 0;
 -         maxSize = 0;
 -         newPreferredSize = 0;
 -         granularity = 0;
 - 
 -         if (asioObject->getBufferSize (&minSize, &maxSize, &newPreferredSize, &granularity) == 0)
 -         {
 -             if (preferredSize != 0 && newPreferredSize != 0 && newPreferredSize != preferredSize)
 -                 shouldUsePreferredSize = true;
 - 
 -             preferredSize = newPreferredSize;
 -         }
 - 
 -         // unfortunate workaround for certain manufacturers whose drivers crash horribly if you make
 -         // dynamic changes to the buffer size...
 -         shouldUsePreferredSize = shouldUsePreferredSize
 -                                    || getName().containsIgnoreCase (T("Digidesign"));
 - 
 -         if (shouldUsePreferredSize)
 -         {
 -             log ("Using preferred size for buffer..");
 - 
 -             if ((err = asioObject->getBufferSize (&minSize, &maxSize, &preferredSize, &granularity)) == 0)
 -             {
 -                 bufferSizeSamples = preferredSize;
 -             }
 -             else
 -             {
 -                 bufferSizeSamples = 1024;
 -                 logError ("GetBufferSize1", err);
 -             }
 - 
 -             shouldUsePreferredSize = false;
 -         }
 - 
 -         int sampleRate = roundDoubleToInt (sr);
 -         currentSampleRate = sampleRate;
 -         currentBlockSizeSamples = bufferSizeSamples;
 -         currentChansOut.clear();
 -         currentChansIn.clear();
 -         zeromem (inBuffers, sizeof (inBuffers));
 -         zeromem (outBuffers, sizeof (outBuffers));
 - 
 -         updateSampleRates();
 - 
 -         if (sampleRate == 0 || (sampleRates.size() > 0 && ! sampleRates.contains (sampleRate)))
 -             sampleRate = sampleRates[0];
 - 
 -         jassert (sampleRate != 0);
 -         if (sampleRate == 0)
 -             sampleRate = 44100;
 - 
 -         long numSources = 32;
 -         ASIOClockSource clocks[32];
 -         zeromem (clocks, sizeof (clocks));
 -         asioObject->getClockSources (clocks, &numSources);
 -         bool isSourceSet = false;
 - 
 -         // careful not to remove this loop because it does more than just logging!
 -         int i;
 -         for (i = 0; i < numSources; ++i)
 -         {
 -             String s ("clock: ");
 -             s += clocks[i].name;
 - 
 -             if (clocks[i].isCurrentSource)
 -             {
 -                 isSourceSet = true;
 -                 s << " (cur)";
 -             }
 - 
 -             log (s);
 -         }
 - 
 -         if (numSources > 1 && ! isSourceSet)
 -         {
 -             log ("setting clock source");
 -             asioObject->setClockSource (clocks[0].index);
 -             Thread::sleep (20);
 -         }
 -         else
 -         {
 -             if (numSources == 0)
 -             {
 -                 log ("ASIO - no clock sources!");
 -             }
 -         }
 - 
 -         double cr = 0;
 -         err = asioObject->getSampleRate (&cr);
 -         if (err == 0)
 -         {
 -             currentSampleRate = cr;
 -         }
 -         else
 -         {
 -             logError ("GetSampleRate", err);
 -             currentSampleRate = 0;
 -         }
 - 
 -         error = String::empty;
 -         needToReset = false;
 -         isReSync = false;
 -         err = 0;
 -         bool buffersCreated = false;
 - 
 -         if (currentSampleRate != sampleRate)
 -         {
 -             log (T("ASIO samplerate: ") + String (currentSampleRate) + T(" to ") + String (sampleRate));
 -             err = asioObject->setSampleRate (sampleRate);
 - 
 -             if (err == ASE_NoClock && numSources > 0)
 -             {
 -                 log ("trying to set a clock source..");
 -                 Thread::sleep (10);
 -                 err = asioObject->setClockSource (clocks[0].index);
 -                 if (err != 0)
 -                 {
 -                     logError ("SetClock", err);
 -                 }
 - 
 -                 Thread::sleep (10);
 -                 err = asioObject->setSampleRate (sampleRate);
 -             }
 -         }
 - 
 -         if (err == 0)
 -         {
 -             currentSampleRate = sampleRate;
 - 
 -             if (needToReset)
 -             {
 -                 if (isReSync)
 -                 {
 -                     log ("Resync request");
 -                 }
 - 
 -                 log ("! Resetting ASIO after sample rate change");
 -                 removeCurrentDriver();
 - 
 -                 loadDriver();
 -                 const String error (initDriver());
 - 
 -                 if (error.isNotEmpty())
 -                 {
 -                     log (T("ASIOInit: ") + error);
 -                 }
 - 
 -                 needToReset = false;
 -                 isReSync = false;
 -             }
 - 
 -             numActiveInputChans = 0;
 -             numActiveOutputChans = 0;
 - 
 -             ASIOBufferInfo* info = bufferInfos;
 -             int i;
 -             for (i = 0; i < totalNumInputChans; ++i)
 -             {
 -                 if (inputChannels[i])
 -                 {
 -                     currentChansIn.setBit (i);
 -                     info->isInput = 1;
 -                     info->channelNum = i;
 -                     info->buffers[0] = info->buffers[1] = 0;
 -                     ++info;
 -                     ++numActiveInputChans;
 -                 }
 -             }
 - 
 -             for (i = 0; i < totalNumOutputChans; ++i)
 -             {
 -                 if (outputChannels[i])
 -                 {
 -                     currentChansOut.setBit (i);
 -                     info->isInput = 0;
 -                     info->channelNum = i;
 -                     info->buffers[0] = info->buffers[1] = 0;
 -                     ++info;
 -                     ++numActiveOutputChans;
 -                 }
 -             }
 - 
 -             const int totalBuffers = numActiveInputChans + numActiveOutputChans;
 - 
 -             callbacks.sampleRateDidChange = &sampleRateChangedCallback;
 - 
 -             if (currentASIODev[0] == this)
 -             {
 -                 callbacks.bufferSwitch = &bufferSwitchCallback0;
 -                 callbacks.asioMessage = &asioMessagesCallback0;
 -                 callbacks.bufferSwitchTimeInfo = &bufferSwitchTimeInfoCallback0;
 -             }
 -             else if (currentASIODev[1] == this)
 -             {
 -                 callbacks.bufferSwitch = &bufferSwitchCallback1;
 -                 callbacks.asioMessage = &asioMessagesCallback1;
 -                 callbacks.bufferSwitchTimeInfo = &bufferSwitchTimeInfoCallback1;
 -             }
 -             else if (currentASIODev[2] == this)
 -             {
 -                 callbacks.bufferSwitch = &bufferSwitchCallback2;
 -                 callbacks.asioMessage = &asioMessagesCallback2;
 -                 callbacks.bufferSwitchTimeInfo = &bufferSwitchTimeInfoCallback2;
 -             }
 -             else
 -             {
 -                 jassertfalse
 -             }
 - 
 -             log ("disposing buffers");
 -             err = asioObject->disposeBuffers();
 - 
 -             log (T("creating buffers: ") + String (totalBuffers) + T(", ") + String (currentBlockSizeSamples));
 -             err = asioObject->createBuffers (bufferInfos,
 -                                              totalBuffers,
 -                                              currentBlockSizeSamples,
 -                                              &callbacks);
 - 
 -             if (err != 0)
 -             {
 -                 currentBlockSizeSamples = preferredSize;
 -                 logError ("create buffers 2", err);
 - 
 -                 asioObject->disposeBuffers();
 -                 err = asioObject->createBuffers (bufferInfos,
 -                                                  totalBuffers,
 -                                                  currentBlockSizeSamples,
 -                                                  &callbacks);
 -             }
 - 
 -             if (err == 0)
 -             {
 -                 buffersCreated = true;
 - 
 -                 juce_free (tempBuffer);
 - 
 -                 tempBuffer = (float*) juce_calloc (totalBuffers * currentBlockSizeSamples * sizeof (float) + 128);
 - 
 -                 int n = 0;
 -                 Array <int> types;
 -                 currentBitDepth = 16;
 - 
 -                 for (i = 0; i < jmin (totalNumInputChans, maxASIOChannels); ++i)
 -                 {
 -                     if (inputChannels[i])
 -                     {
 -                         inBuffers[n] = tempBuffer + (currentBlockSizeSamples * n);
 - 
 -                         ASIOChannelInfo channelInfo;
 -                         zerostruct (channelInfo);
 - 
 -                         channelInfo.channel = i;
 -                         channelInfo.isInput = 1;
 -                         asioObject->getChannelInfo (&channelInfo);
 - 
 -                         types.addIfNotAlreadyThere (channelInfo.type);
 -                         typeToFormatParameters (channelInfo.type,
 -                                                 inputChannelBitDepths[n],
 -                                                 inputChannelBytesPerSample[n],
 -                                                 inputChannelIsFloat[n],
 -                                                 inputChannelLittleEndian[n]);
 - 
 -                         currentBitDepth = jmax (currentBitDepth, inputChannelBitDepths[n]);
 - 
 -                         ++n;
 -                     }
 -                 }
 - 
 -                 jassert (numActiveInputChans == n);
 -                 n = 0;
 - 
 -                 for (i = 0; i < jmin (totalNumOutputChans, maxASIOChannels); ++i)
 -                 {
 -                     if (outputChannels[i])
 -                     {
 -                         outBuffers[n] = tempBuffer + (currentBlockSizeSamples * (numActiveInputChans + n));
 - 
 -                         ASIOChannelInfo channelInfo;
 -                         zerostruct (channelInfo);
 - 
 -                         channelInfo.channel = i;
 -                         channelInfo.isInput = 0;
 -                         asioObject->getChannelInfo (&channelInfo);
 - 
 -                         types.addIfNotAlreadyThere (channelInfo.type);
 -                         typeToFormatParameters (channelInfo.type,
 -                                                 outputChannelBitDepths[n],
 -                                                 outputChannelBytesPerSample[n],
 -                                                 outputChannelIsFloat[n],
 -                                                 outputChannelLittleEndian[n]);
 - 
 -                         currentBitDepth = jmax (currentBitDepth, outputChannelBitDepths[n]);
 - 
 -                         ++n;
 -                     }
 -                 }
 - 
 -                 jassert (numActiveOutputChans == n);
 - 
 -                 for (i = types.size(); --i >= 0;)
 -                 {
 -                     log (T("channel format: ") + String (types[i]));
 -                 }
 - 
 -                 jassert (n <= totalBuffers);
 - 
 -                 for (i = 0; i < numActiveOutputChans; ++i)
 -                 {
 -                     const int size = currentBlockSizeSamples * (outputChannelBitDepths[i] >> 3);
 - 
 -                     if (bufferInfos [numActiveInputChans + i].buffers[0] == 0
 -                         || bufferInfos [numActiveInputChans + i].buffers[1] == 0)
 -                     {
 -                         log ("!! Null buffers");
 -                     }
 -                     else
 -                     {
 -                         zeromem (bufferInfos[numActiveInputChans + i].buffers[0], size);
 -                         zeromem (bufferInfos[numActiveInputChans + i].buffers[1], size);
 -                     }
 -                 }
 - 
 -                 inputLatency = outputLatency = 0;
 - 
 -                 if (asioObject->getLatencies (&inputLatency, &outputLatency) != 0)
 -                 {
 -                     log ("ASIO - no latencies");
 -                 }
 -                 else
 -                 {
 -                     log (T("ASIO latencies: ")
 -                            + String ((int) outputLatency)
 -                            + T(", ")
 -                            + String ((int) inputLatency));
 -                 }
 - 
 -                 isOpen_ = true;
 - 
 -                 log ("starting ASIO");
 -                 calledback = false;
 -                 err = asioObject->start();
 - 
 -                 if (err != 0)
 -                 {
 -                     isOpen_ = false;
 -                     log ("ASIO - stop on failure");
 -                     Thread::sleep (10);
 -                     asioObject->stop();
 -                     error = "Can't start device";
 -                     Thread::sleep (10);
 -                 }
 -                 else
 -                 {
 -                     int count = 300;
 -                     while (--count > 0 && ! calledback)
 -                         Thread::sleep (10);
 - 
 -                     isStarted = true;
 - 
 -                     if (! calledback)
 -                     {
 -                         error = "Device didn't start correctly";
 -                         log ("ASIO didn't callback - stopping..");
 -                         asioObject->stop();
 -                     }
 -                 }
 -             }
 -             else
 -             {
 -                 error = "Can't create i/o buffers";
 -             }
 -         }
 -         else
 -         {
 -             error = "Can't set sample rate: ";
 -             error << sampleRate;
 -         }
 - 
 -         if (error.isNotEmpty())
 -         {
 -             logError (error, err);
 - 
 -             if (asioObject != 0 && buffersCreated)
 -                 asioObject->disposeBuffers();
 - 
 -             Thread::sleep (20);
 -             isStarted = false;
 -             isOpen_ = false;
 -             close();
 -         }
 - 
 -         needToReset = false;
 -         isReSync = false;
 - 
 -         return error;
 -     }
 - 
 -     void close()
 -     {
 -         error = String::empty;
 -         stopTimer();
 -         stop();
 - 
 -         if (isASIOOpen && isOpen_)
 -         {
 -             const ScopedLock sl (callbackLock);
 - 
 -             isOpen_ = false;
 -             isStarted = false;
 -             needToReset = false;
 -             isReSync = false;
 - 
 -             log ("ASIO - stopping");
 - 
 -             if (asioObject != 0)
 -             {
 -                 Thread::sleep (20);
 -                 asioObject->stop();
 -                 Thread::sleep (10);
 -                 asioObject->disposeBuffers();
 -             }
 - 
 -             Thread::sleep (10);
 -         }
 -     }
 - 
 -     bool isOpen()
 -     {
 -         return isOpen_ || insideControlPanelModalLoop;
 -     }
 - 
 -     int getCurrentBufferSizeSamples()
 -     {
 -         return currentBlockSizeSamples;
 -     }
 - 
 -     double getCurrentSampleRate()
 -     {
 -         return currentSampleRate;
 -     }
 - 
 -     const BitArray getActiveOutputChannels() const
 -     {
 -         return currentChansOut;
 -     }
 - 
 -     const BitArray getActiveInputChannels() const
 -     {
 -         return currentChansIn;
 -     }
 - 
 -     int getCurrentBitDepth()
 -     {
 -         return currentBitDepth;
 -     }
 - 
 -     int getOutputLatencyInSamples()
 -     {
 -         return outputLatency + currentBlockSizeSamples / 4;
 -     }
 - 
 -     int getInputLatencyInSamples()
 -     {
 -         return inputLatency + currentBlockSizeSamples / 4;
 -     }
 - 
 -     void start (AudioIODeviceCallback* callback)
 -     {
 -         if (callback != 0)
 -         {
 -             callback->audioDeviceAboutToStart (this);
 - 
 -             const ScopedLock sl (callbackLock);
 -             currentCallback = callback;
 -         }
 -     }
 - 
 -     void stop()
 -     {
 -         AudioIODeviceCallback* const lastCallback = currentCallback;
 - 
 -         {
 -             const ScopedLock sl (callbackLock);
 -             currentCallback = 0;
 -         }
 - 
 -         if (lastCallback != 0)
 -             lastCallback->audioDeviceStopped();
 -     }
 - 
 -     bool isPlaying()
 -     {
 -         return isASIOOpen && (currentCallback != 0);
 -     }
 - 
 -     const String getLastError()
 -     {
 -         return error;
 -     }
 - 
 -     bool hasControlPanel() const
 -     {
 -         return true;
 -     }
 - 
 -     bool showControlPanel()
 -     {
 -         log ("ASIO - showing control panel");
 - 
 -         Component modalWindow (String::empty);
 -         modalWindow.setOpaque (true);
 -         modalWindow.addToDesktop (0);
 -         modalWindow.enterModalState();
 -         bool done = false;
 - 
 -         JUCE_TRY
 -         {
 -             close();
 -             insideControlPanelModalLoop = true;
 - 
 -             const uint32 started = Time::getMillisecondCounter();
 - 
 -             if (asioObject != 0)
 -             {
 -                 asioObject->controlPanel();
 - 
 -                 const int spent = (int) Time::getMillisecondCounter() - (int) started;
 - 
 -                 log (T("spent: ") + String (spent));
 - 
 -                 if (spent > 300)
 -                 {
 -                     shouldUsePreferredSize = true;
 -                     done = true;
 -                 }
 -             }
 -         }
 -         JUCE_CATCH_ALL
 - 
 -         insideControlPanelModalLoop = false;
 -         return done;
 -     }
 - 
 -     void resetRequest() throw()
 -     {
 -         needToReset = true;
 -     }
 - 
 -     void resyncRequest() throw()
 -     {
 -         needToReset = true;
 -         isReSync = true;
 -     }
 - 
 -     void timerCallback()
 -     {
 -         if (! insideControlPanelModalLoop)
 -         {
 -             stopTimer();
 - 
 -             // used to cause a reset
 -             log ("! ASIO restart request!");
 - 
 -             if (isOpen_)
 -             {
 -                 AudioIODeviceCallback* const oldCallback = currentCallback;
 - 
 -                 close();
 -                 open (currentChansIn, currentChansOut,
 -                       currentSampleRate, currentBlockSizeSamples);
 - 
 -                 if (oldCallback != 0)
 -                     start (oldCallback);
 -             }
 -         }
 -         else
 -         {
 -             startTimer (100);
 -         }
 -     }
 - 
 -     //==============================================================================
 -     juce_UseDebuggingNewOperator
 - 
 - private:
 -     //==============================================================================
 -     IASIO* volatile asioObject;
 -     ASIOCallbacks callbacks;
 - 
 -     void* windowHandle;
 -     CLSID classId;
 -     String error;
 - 
 -     long totalNumInputChans, totalNumOutputChans;
 -     StringArray inputChannelNames, outputChannelNames;
 - 
 -     Array<int> sampleRates, bufferSizes;
 -     long inputLatency, outputLatency;
 -     long minSize, maxSize, preferredSize, granularity;
 - 
 -     int volatile currentBlockSizeSamples;
 -     int volatile currentBitDepth;
 -     double volatile currentSampleRate;
 -     BitArray currentChansOut, currentChansIn;
 -     AudioIODeviceCallback* volatile currentCallback;
 -     CriticalSection callbackLock;
 - 
 -     ASIOBufferInfo bufferInfos [maxASIOChannels];
 -     float* inBuffers [maxASIOChannels];
 -     float* outBuffers [maxASIOChannels];
 - 
 -     int inputChannelBitDepths [maxASIOChannels];
 -     int outputChannelBitDepths [maxASIOChannels];
 -     int inputChannelBytesPerSample [maxASIOChannels];
 -     int outputChannelBytesPerSample [maxASIOChannels];
 -     bool inputChannelIsFloat [maxASIOChannels];
 -     bool outputChannelIsFloat [maxASIOChannels];
 -     bool inputChannelLittleEndian [maxASIOChannels];
 -     bool outputChannelLittleEndian [maxASIOChannels];
 - 
 -     WaitableEvent event1;
 -     float* tempBuffer;
 -     int volatile bufferIndex, numActiveInputChans, numActiveOutputChans;
 - 
 -     bool isOpen_, isStarted;
 -     bool volatile isASIOOpen;
 -     bool volatile calledback;
 -     bool volatile littleEndian, postOutput, needToReset, isReSync;
 -     bool volatile insideControlPanelModalLoop;
 -     bool volatile shouldUsePreferredSize;
 - 
 - 
 -     //==============================================================================
 -     void removeCurrentDriver()
 -     {
 -         if (asioObject != 0)
 -         {
 -             asioObject->Release();
 -             asioObject = 0;
 -         }
 -     }
 - 
 -     bool loadDriver()
 -     {
 -         removeCurrentDriver();
 - 
 -         JUCE_TRY
 -         {
 -             if (CoCreateInstance (classId, 0, CLSCTX_INPROC_SERVER,
 -                                   classId, (void**) &asioObject) == S_OK)
 -             {
 -                 return true;
 -             }
 -         }
 -         JUCE_CATCH_ALL
 - 
 -         asioObject = 0;
 - 
 -         return false;
 -     }
 - 
 -     const String initDriver()
 -     {
 -         if (asioObject != 0)
 -         {
 -             char buffer [256];
 -             zeromem (buffer, sizeof (buffer));
 - 
 -             if (! asioObject->init (windowHandle))
 -             {
 -                 asioObject->getErrorMessage (buffer);
 -                 return String (buffer, sizeof (buffer) - 1);
 -             }
 - 
 -             // just in case any daft drivers expect this to be called..
 -             asioObject->getDriverName (buffer);
 - 
 -             return String::empty;
 -         }
 - 
 -         return "No Driver";
 -     }
 - 
 -     const String openDevice()
 -     {
 -         // use this in case the driver starts opening dialog boxes..
 -         Component modalWindow (String::empty);
 -         modalWindow.setOpaque (true);
 -         modalWindow.addToDesktop (0);
 -         modalWindow.enterModalState();
 - 
 -         // open the device and get its info..
 -         log (T("opening ASIO device: ") + getName());
 - 
 -         needToReset = false;
 -         isReSync = false;
 -         outputChannelNames.clear();
 -         inputChannelNames.clear();
 -         bufferSizes.clear();
 -         sampleRates.clear();
 -         isASIOOpen = false;
 -         isOpen_ = false;
 -         totalNumInputChans = 0;
 -         totalNumOutputChans = 0;
 -         numActiveInputChans = 0;
 -         numActiveOutputChans = 0;
 -         currentCallback = 0;
 - 
 -         error = String::empty;
 - 
 -         if (getName().isEmpty())
 -             return error;
 - 
 -         long err = 0;
 - 
 -         if (loadDriver())
 -         {
 -             if ((error = initDriver()).isEmpty())
 -             {
 -                 numActiveInputChans = 0;
 -                 numActiveOutputChans = 0;
 -                 totalNumInputChans = 0;
 -                 totalNumOutputChans = 0;
 - 
 -                 if (asioObject != 0
 -                      && (err = asioObject->getChannels (&totalNumInputChans, &totalNumOutputChans)) == 0)
 -                 {
 -                     log (String ((int) totalNumInputChans) + T(" in, ") + String ((int) totalNumOutputChans) + T(" out"));
 - 
 -                     if ((err = asioObject->getBufferSize (&minSize, &maxSize, &preferredSize, &granularity)) == 0)
 -                     {
 -                         // find a list of buffer sizes..
 -                         log (String ((int) minSize) + T(" ") + String ((int) maxSize) + T(" ") + String ((int)preferredSize) + T(" ") + String ((int)granularity));
 - 
 -                         if (granularity >= 0)
 -                         {
 -                             granularity = jmax (1, (int) granularity);
 - 
 -                             for (int i = jmax (minSize, (int) granularity); i < jmin (6400, maxSize); i += granularity)
 -                                 bufferSizes.addIfNotAlreadyThere (granularity * (i / granularity));
 -                         }
 -                         else if (granularity < 0)
 -                         {
 -                             for (int i = 0; i < 18; ++i)
 -                             {
 -                                 const int s = (1 << i);
 - 
 -                                 if (s >= minSize && s <= maxSize)
 -                                     bufferSizes.add (s);
 -                             }
 -                         }
 - 
 -                         if (! bufferSizes.contains (preferredSize))
 -                             bufferSizes.insert (0, preferredSize);
 - 
 -                         double currentRate = 0;
 -                         asioObject->getSampleRate (¤tRate);
 - 
 -                         if (currentRate <= 0.0 || currentRate > 192001.0)
 -                         {
 -                             log ("setting sample rate");
 -                             err = asioObject->setSampleRate (44100.0);
 -                             if (err != 0)
 -                             {
 -                                 logError ("setting sample rate", err);
 -                             }
 - 
 -                             asioObject->getSampleRate (¤tRate);
 -                         }
 - 
 -                         currentSampleRate = currentRate;
 - 
 -                         postOutput = (asioObject->outputReady() == 0);
 -                         if (postOutput)
 -                         {
 -                             log ("ASIO outputReady = ok");
 -                         }
 - 
 -                         updateSampleRates();
 - 
 -                         // ..because cubase does it at this point
 -                         inputLatency = outputLatency = 0;
 -                         if (asioObject->getLatencies (&inputLatency, &outputLatency) != 0)
 -                         {
 -                             log ("ASIO - no latencies");
 -                         }
 - 
 -                         log (String ("latencies: ")
 -                                 + String ((int) inputLatency)
 -                                 + T(", ") + String ((int) outputLatency));
 - 
 -                         // create some dummy buffers now.. because cubase does..
 -                         numActiveInputChans = 0;
 -                         numActiveOutputChans = 0;
 - 
 -                         ASIOBufferInfo* info = bufferInfos;
 -                         int i, numChans = 0;
 -                         for (i = 0; i < jmin (2, totalNumInputChans); ++i)
 -                         {
 -                             info->isInput = 1;
 -                             info->channelNum = i;
 -                             info->buffers[0] = info->buffers[1] = 0;
 -                             ++info;
 -                             ++numChans;
 -                         }
 - 
 -                         const int outputBufferIndex = numChans;
 - 
 -                         for (i = 0; i < jmin (2, totalNumOutputChans); ++i)
 -                         {
 -                             info->isInput = 0;
 -                             info->channelNum = i;
 -                             info->buffers[0] = info->buffers[1] = 0;
 -                             ++info;
 -                             ++numChans;
 -                         }
 - 
 - 
 -                         callbacks.sampleRateDidChange = &sampleRateChangedCallback;
 - 
 -                         if (currentASIODev[0] == this)
 -                         {
 -                             callbacks.bufferSwitch = &bufferSwitchCallback0;
 -                             callbacks.asioMessage = &asioMessagesCallback0;
 -                             callbacks.bufferSwitchTimeInfo = &bufferSwitchTimeInfoCallback0;
 -                         }
 -                         else if (currentASIODev[1] == this)
 -                         {
 -                             callbacks.bufferSwitch = &bufferSwitchCallback1;
 -                             callbacks.asioMessage = &asioMessagesCallback1;
 -                             callbacks.bufferSwitchTimeInfo = &bufferSwitchTimeInfoCallback1;
 -                         }
 -                         else if (currentASIODev[2] == this)
 -                         {
 -                             callbacks.bufferSwitch = &bufferSwitchCallback2;
 -                             callbacks.asioMessage = &asioMessagesCallback2;
 -                             callbacks.bufferSwitchTimeInfo = &bufferSwitchTimeInfoCallback2;
 -                         }
 -                         else
 -                         {
 -                             jassertfalse
 -                         }
 - 
 -                         log (T("creating buffers (dummy): ") + String (numChans)
 -                                + T(", ") + String ((int) preferredSize));
 - 
 -                         if (preferredSize > 0)
 -                         {
 -                             err = asioObject->createBuffers (bufferInfos, numChans, preferredSize, &callbacks);
 -                             if (err != 0)
 -                             {
 -                                 logError ("dummy buffers", err);
 -                             }
 -                         }
 - 
 -                         long newInps = 0, newOuts = 0;
 -                         asioObject->getChannels (&newInps, &newOuts);
 - 
 -                         if (totalNumInputChans != newInps || totalNumOutputChans != newOuts)
 -                         {
 -                             totalNumInputChans = newInps;
 -                             totalNumOutputChans = newOuts;
 - 
 -                             log (String ((int) totalNumInputChans) + T(" in; ")
 -                                   + String ((int) totalNumOutputChans) + T(" out"));
 -                         }
 - 
 -                         updateSampleRates();
 - 
 -                         ASIOChannelInfo channelInfo;
 -                         channelInfo.type = 0;
 - 
 -                         for (i = 0; i < totalNumInputChans; ++i)
 -                         {
 -                             zerostruct (channelInfo);
 -                             channelInfo.channel = i;
 -                             channelInfo.isInput = 1;
 -                             asioObject->getChannelInfo (&channelInfo);
 - 
 -                             inputChannelNames.add (String (channelInfo.name));
 -                         }
 - 
 -                         for (i = 0; i < totalNumOutputChans; ++i)
 -                         {
 -                             zerostruct (channelInfo);
 -                             channelInfo.channel = i;
 -                             channelInfo.isInput = 0;
 -                             asioObject->getChannelInfo (&channelInfo);
 - 
 -                             outputChannelNames.add (String (channelInfo.name));
 - 
 -                             typeToFormatParameters (channelInfo.type,
 -                                                     outputChannelBitDepths[i],
 -                                                     outputChannelBytesPerSample[i],
 -                                                     outputChannelIsFloat[i],
 -                                                     outputChannelLittleEndian[i]);
 - 
 -                             if (i < 2)
 -                             {
 -                                 // clear the channels that are used with the dummy stuff
 -                                 const int bytesPerBuffer = preferredSize * (outputChannelBitDepths[i] >> 3);
 -                                 zeromem (bufferInfos [outputBufferIndex + i].buffers[0], bytesPerBuffer);
 -                                 zeromem (bufferInfos [outputBufferIndex + i].buffers[1], bytesPerBuffer);
 -                             }
 -                         }
 - 
 -                         outputChannelNames.trim();
 -                         inputChannelNames.trim();
 -                         outputChannelNames.appendNumbersToDuplicates (false, true);
 -                         inputChannelNames.appendNumbersToDuplicates (false, true);
 - 
 -                         // start and stop because cubase does it..
 -                         asioObject->getLatencies (&inputLatency, &outputLatency);
 - 
 -                         if ((err = asioObject->start()) != 0)
 -                         {
 -                             // ignore an error here, as it might start later after setting other stuff up
 -                             logError ("ASIO start", err);
 -                         }
 - 
 -                         Thread::sleep (100);
 -                         asioObject->stop();
 -                     }
 -                     else
 -                     {
 -                         error = "Can't detect buffer sizes";
 -                     }
 -                 }
 -                 else
 -                 {
 -                     error = "Can't detect asio channels";
 -                 }
 -             }
 -         }
 -         else
 -         {
 -             error = "No such device";
 -         }
 - 
 -         if (error.isNotEmpty())
 -         {
 -             logError (error, err);
 - 
 -             if (asioObject != 0)
 -                 asioObject->disposeBuffers();
 - 
 -             removeCurrentDriver();
 -             isASIOOpen = false;
 -         }
 -         else
 -         {
 -             isASIOOpen = true;
 -             log ("ASIO device open");
 -         }
 - 
 -         isOpen_ = false;
 -         needToReset = false;
 -         isReSync = false;
 - 
 -         return error;
 -     }
 - 
 -     //==============================================================================
 -     void callback (const long index) throw()
 -     {
 -         if (isStarted)
 -         {
 -             bufferIndex = index;
 -             processBuffer();
 -         }
 -         else
 -         {
 -             if (postOutput && (asioObject != 0))
 -                 asioObject->outputReady();
 -         }
 - 
 -         calledback = true;
 -     }
 - 
 -     void processBuffer() throw()
 -     {
 -         const ASIOBufferInfo* const infos = bufferInfos;
 -         const int bi = bufferIndex;
 - 
 -         const ScopedLock sl (callbackLock);
 - 
 -         if (needToReset)
 -         {
 -             needToReset = false;
 - 
 -             if (isReSync)
 -             {
 -                 log ("! ASIO resync");
 -                 isReSync = false;
 -             }
 -             else
 -             {
 -                 startTimer (20);
 -             }
 -         }
 - 
 -         if (bi >= 0)
 -         {
 -             const int samps = currentBlockSizeSamples;
 - 
 -             if (currentCallback != 0)
 -             {
 -                 int i;
 -                 for (i = 0; i < numActiveInputChans; ++i)
 -                 {
 -                     float* const dst = inBuffers[i];
 - 
 -                     jassert (dst != 0);
 - 
 -                     const char* const src = (const char*) (infos[i].buffers[bi]);
 - 
 -                     if (inputChannelIsFloat[i])
 -                     {
 -                         memcpy (dst, src, samps * sizeof (float));
 -                     }
 -                     else
 -                     {
 -                         jassert (dst == tempBuffer + (samps * i));
 - 
 -                         switch (inputChannelBitDepths[i])
 -                         {
 -                         case 16:
 -                             convertInt16ToFloat (src, dst, inputChannelBytesPerSample[i],
 -                                                  samps, inputChannelLittleEndian[i]);
 -                             break;
 - 
 -                         case 24:
 -                             convertInt24ToFloat (src, dst, inputChannelBytesPerSample[i],
 -                                                  samps, inputChannelLittleEndian[i]);
 -                             break;
 - 
 -                         case 32:
 -                             convertInt32ToFloat (src, dst, inputChannelBytesPerSample[i],
 -                                                  samps, inputChannelLittleEndian[i]);
 -                             break;
 - 
 -                         case 64:
 -                             jassertfalse
 -                             break;
 -                         }
 -                     }
 -                 }
 - 
 -                 currentCallback->audioDeviceIOCallback ((const float**) inBuffers,
 -                                                         numActiveInputChans,
 -                                                         outBuffers,
 -                                                         numActiveOutputChans,
 -                                                         samps);
 - 
 -                 for (i = 0; i < numActiveOutputChans; ++i)
 -                 {
 -                     float* const src = outBuffers[i];
 - 
 -                     jassert (src != 0);
 - 
 -                     char* const dst = (char*) (infos [numActiveInputChans + i].buffers[bi]);
 - 
 -                     if (outputChannelIsFloat[i])
 -                     {
 -                         memcpy (dst, src, samps * sizeof (float));
 -                     }
 -                     else
 -                     {
 -                         jassert (src == tempBuffer + (samps * (numActiveInputChans + i)));
 - 
 -                         switch (outputChannelBitDepths[i])
 -                         {
 -                         case 16:
 -                             convertFloatToInt16 (src, dst, outputChannelBytesPerSample[i],
 -                                                  samps, outputChannelLittleEndian[i]);
 -                             break;
 - 
 -                         case 24:
 -                             convertFloatToInt24 (src, dst, outputChannelBytesPerSample[i],
 -                                                  samps, outputChannelLittleEndian[i]);
 -                             break;
 - 
 -                         case 32:
 -                             convertFloatToInt32 (src, dst, outputChannelBytesPerSample[i],
 -                                                  samps, outputChannelLittleEndian[i]);
 -                             break;
 - 
 -                         case 64:
 -                             jassertfalse
 -                             break;
 -                         }
 -                     }
 -                 }
 -             }
 -             else
 -             {
 -                 for (int i = 0; i < numActiveOutputChans; ++i)
 -                 {
 -                     const int bytesPerBuffer = samps * (outputChannelBitDepths[i] >> 3);
 -                     zeromem (infos[numActiveInputChans + i].buffers[bi], bytesPerBuffer);
 -                 }
 -             }
 -         }
 - 
 -         if (postOutput)
 -             asioObject->outputReady();
 -     }
 - 
 -     //==============================================================================
 -     static ASIOTime* bufferSwitchTimeInfoCallback0 (ASIOTime*, long index, long) throw()
 -     {
 -         if (currentASIODev[0] != 0)
 -             currentASIODev[0]->callback (index);
 - 
 -         return 0;
 -     }
 - 
 -     static ASIOTime* bufferSwitchTimeInfoCallback1 (ASIOTime*, long index, long) throw()
 -     {
 -         if (currentASIODev[1] != 0)
 -             currentASIODev[1]->callback (index);
 - 
 -         return 0;
 -     }
 - 
 -     static ASIOTime* bufferSwitchTimeInfoCallback2 (ASIOTime*, long index, long) throw()
 -     {
 -         if (currentASIODev[2] != 0)
 -             currentASIODev[2]->callback (index);
 - 
 -         return 0;
 -     }
 - 
 -     static void bufferSwitchCallback0 (long index, long) throw()
 -     {
 -         if (currentASIODev[0] != 0)
 -             currentASIODev[0]->callback (index);
 -     }
 - 
 -     static void bufferSwitchCallback1 (long index, long) throw()
 -     {
 -         if (currentASIODev[1] != 0)
 -             currentASIODev[1]->callback (index);
 -     }
 - 
 -     static void bufferSwitchCallback2 (long index, long) throw()
 -     {
 -         if (currentASIODev[2] != 0)
 -             currentASIODev[2]->callback (index);
 -     }
 - 
 -     static long asioMessagesCallback0 (long selector, long value, void*, double*) throw()
 -     {
 -         return asioMessagesCallback (selector, value, 0);
 -     }
 - 
 -     static long asioMessagesCallback1 (long selector, long value, void*, double*) throw()
 -     {
 -         return asioMessagesCallback (selector, value, 1);
 -     }
 - 
 -     static long asioMessagesCallback2 (long selector, long value, void*, double*) throw()
 -     {
 -         return asioMessagesCallback (selector, value, 2);
 -     }
 - 
 -     //==============================================================================
 -     static long asioMessagesCallback (long selector, long value, const int deviceIndex) throw()
 -     {
 -         switch (selector)
 -         {
 -         case kAsioSelectorSupported:
 -             if (value == kAsioResetRequest
 -                 || value == kAsioEngineVersion
 -                 || value == kAsioResyncRequest
 -                 || value == kAsioLatenciesChanged
 -                 || value == kAsioSupportsInputMonitor)
 -                 return 1;
 -             break;
 - 
 -         case kAsioBufferSizeChange:
 -             break;
 - 
 -         case kAsioResetRequest:
 -             if (currentASIODev[deviceIndex] != 0)
 -                 currentASIODev[deviceIndex]->resetRequest();
 - 
 -             return 1;
 - 
 -         case kAsioResyncRequest:
 -             if (currentASIODev[deviceIndex] != 0)
 -                 currentASIODev[deviceIndex]->resyncRequest();
 - 
 -             return 1;
 - 
 -         case kAsioLatenciesChanged:
 -             return 1;
 - 
 -         case kAsioEngineVersion:
 -             return 2;
 - 
 -         case kAsioSupportsTimeInfo:
 -         case kAsioSupportsTimeCode:
 -             return 0;
 -         }
 - 
 -         return 0;
 -     }
 - 
 -     static void sampleRateChangedCallback (ASIOSampleRate) throw()
 -     {
 -     }
 - 
 -     //==============================================================================
 -     static void convertInt16ToFloat (const char* src,
 -                                      float* dest,
 -                                      const int srcStrideBytes,
 -                                      int numSamples,
 -                                      const bool littleEndian) throw()
 -     {
 -         const double g = 1.0 / 32768.0;
 - 
 -         if (littleEndian)
 -         {
 -             while (--numSamples >= 0)
 -             {
 -                 *dest++ = (float) (g * (short) littleEndianShort (src));
 -                 src += srcStrideBytes;
 -             }
 -         }
 -         else
 -         {
 -             while (--numSamples >= 0)
 -             {
 -                 *dest++ = (float) (g * (short) bigEndianShort (src));
 -                 src += srcStrideBytes;
 -             }
 -         }
 -     }
 - 
 -     static void convertFloatToInt16 (const float* src,
 -                                      char* dest,
 -                                      const int dstStrideBytes,
 -                                      int numSamples,
 -                                      const bool littleEndian) throw()
 -     {
 -         const double maxVal = (double) 0x7fff;
 - 
 -         if (littleEndian)
 -         {
 -             while (--numSamples >= 0)
 -             {
 -                 *(uint16*) dest = swapIfBigEndian ((uint16) (short) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * *src++)));
 -                 dest += dstStrideBytes;
 -             }
 -         }
 -         else
 -         {
 -             while (--numSamples >= 0)
 -             {
 -                 *(uint16*) dest = swapIfLittleEndian ((uint16) (short) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * *src++)));
 -                 dest += dstStrideBytes;
 -             }
 -         }
 -     }
 - 
 -     static void convertInt24ToFloat (const char* src,
 -                                      float* dest,
 -                                      const int srcStrideBytes,
 -                                      int numSamples,
 -                                      const bool littleEndian) throw()
 -     {
 -         const double g = 1.0 / 0x7fffff;
 - 
 -         if (littleEndian)
 -         {
 -             while (--numSamples >= 0)
 -             {
 -                 *dest++ = (float) (g * littleEndian24Bit (src));
 -                 src += srcStrideBytes;
 -             }
 -         }
 -         else
 -         {
 -             while (--numSamples >= 0)
 -             {
 -                 *dest++ = (float) (g * bigEndian24Bit (src));
 -                 src += srcStrideBytes;
 -             }
 -         }
 -     }
 - 
 -     static void convertFloatToInt24 (const float* src,
 -                                      char* dest,
 -                                      const int dstStrideBytes,
 -                                      int numSamples,
 -                                      const bool littleEndian) throw()
 -     {
 -         const double maxVal = (double) 0x7fffff;
 - 
 -         if (littleEndian)
 -         {
 -             while (--numSamples >= 0)
 -             {
 -                 littleEndian24BitToChars ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * *src++)), dest);
 -                 dest += dstStrideBytes;
 -             }
 -         }
 -         else
 -         {
 -             while (--numSamples >= 0)
 -             {
 -                 bigEndian24BitToChars ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * *src++)), dest);
 -                 dest += dstStrideBytes;
 -             }
 -         }
 -     }
 - 
 -     static void convertInt32ToFloat (const char* src,
 -                                      float* dest,
 -                                      const int srcStrideBytes,
 -                                      int numSamples,
 -                                      const bool littleEndian) throw()
 -     {
 -         const double g = 1.0 / 0x7fffffff;
 - 
 -         if (littleEndian)
 -         {
 -             while (--numSamples >= 0)
 -             {
 -                 *dest++ = (float) (g * (int) littleEndianInt (src));
 -                 src += srcStrideBytes;
 -             }
 -         }
 -         else
 -         {
 -             while (--numSamples >= 0)
 -             {
 -                 *dest++ = (float) (g * (int) bigEndianInt (src));
 -                 src += srcStrideBytes;
 -             }
 -         }
 -     }
 - 
 -     static void convertFloatToInt32 (const float* src,
 -                                      char* dest,
 -                                      const int dstStrideBytes,
 -                                      int numSamples,
 -                                      const bool littleEndian) throw()
 -     {
 -         const double maxVal = (double) 0x7fffffff;
 - 
 -         if (littleEndian)
 -         {
 -             while (--numSamples >= 0)
 -             {
 -                 *(uint32*) dest = swapIfBigEndian ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * *src++)));
 -                 dest += dstStrideBytes;
 -             }
 -         }
 -         else
 -         {
 -             while (--numSamples >= 0)
 -             {
 -                 *(uint32*) dest = swapIfLittleEndian ((uint32) roundDoubleToInt (jlimit (-maxVal, maxVal, maxVal * *src++)));
 -                 dest += dstStrideBytes;
 -             }
 -         }
 -     }
 - 
 -     //==============================================================================
 -     static void typeToFormatParameters (const long type,
 -                                         int& bitDepth,
 -                                         int& byteStride,
 -                                         bool& formatIsFloat,
 -                                         bool& littleEndian) throw()
 -     {
 -         bitDepth = 0;
 -         littleEndian = false;
 -         formatIsFloat = false;
 - 
 -         switch (type)
 -         {
 -             case ASIOSTInt16MSB:
 -             case ASIOSTInt16LSB:
 -             case ASIOSTInt32MSB16:
 -             case ASIOSTInt32LSB16:
 -                 bitDepth = 16; break;
 - 
 -             case ASIOSTFloat32MSB:
 -             case ASIOSTFloat32LSB:
 -                 formatIsFloat = true;
 -                 bitDepth = 32; break;
 - 
 -             case ASIOSTInt32MSB:
 -             case ASIOSTInt32LSB:
 -                 bitDepth = 32; break;
 - 
 -             case ASIOSTInt24MSB:
 -             case ASIOSTInt24LSB:
 -             case ASIOSTInt32MSB24:
 -             case ASIOSTInt32LSB24:
 -             case ASIOSTInt32MSB18:
 -             case ASIOSTInt32MSB20:
 -             case ASIOSTInt32LSB18:
 -             case ASIOSTInt32LSB20:
 -                 bitDepth = 24; break;
 - 
 -             case ASIOSTFloat64MSB:
 -             case ASIOSTFloat64LSB:
 -             default:
 -                 bitDepth = 64;
 -                 break;
 -         }
 - 
 -         switch (type)
 -         {
 -             case ASIOSTInt16MSB:
 -             case ASIOSTInt32MSB16:
 -             case ASIOSTFloat32MSB:
 -             case ASIOSTFloat64MSB:
 -             case ASIOSTInt32MSB:
 -             case ASIOSTInt32MSB18:
 -             case ASIOSTInt32MSB20:
 -             case ASIOSTInt32MSB24:
 -             case ASIOSTInt24MSB:
 -                 littleEndian = false; break;
 - 
 -             case ASIOSTInt16LSB:
 -             case ASIOSTInt32LSB16:
 -             case ASIOSTFloat32LSB:
 -             case ASIOSTFloat64LSB:
 -             case ASIOSTInt32LSB:
 -             case ASIOSTInt32LSB18:
 -             case ASIOSTInt32LSB20:
 -             case ASIOSTInt32LSB24:
 -             case ASIOSTInt24LSB:
 -                 littleEndian = true; break;
 - 
 -             default:
 -                 break;
 -         }
 - 
 -         switch (type)
 -         {
 -             case ASIOSTInt16LSB:
 -             case ASIOSTInt16MSB:
 -                 byteStride = 2; break;
 - 
 -             case ASIOSTInt24LSB:
 -             case ASIOSTInt24MSB:
 -                 byteStride = 3; break;
 - 
 -             case ASIOSTInt32MSB16:
 -             case ASIOSTInt32LSB16:
 -             case ASIOSTInt32MSB:
 -             case ASIOSTInt32MSB18:
 -             case ASIOSTInt32MSB20:
 -             case ASIOSTInt32MSB24:
 -             case ASIOSTInt32LSB:
 -             case ASIOSTInt32LSB18:
 -             case ASIOSTInt32LSB20:
 -             case ASIOSTInt32LSB24:
 -             case ASIOSTFloat32LSB:
 -             case ASIOSTFloat32MSB:
 -                 byteStride = 4; break;
 - 
 -             case ASIOSTFloat64MSB:
 -             case ASIOSTFloat64LSB:
 -                 byteStride = 8; break;
 - 
 -             default:
 -                 break;
 -         }
 -     }
 - };
 - 
 - //==============================================================================
 - class ASIOAudioIODeviceType  : public AudioIODeviceType
 - {
 - public:
 -     ASIOAudioIODeviceType()
 -         : AudioIODeviceType (T("ASIO")),
 -           classIds (2),
 -           hasScanned (false)
 -     {
 -         CoInitialize (0);
 -     }
 - 
 -     ~ASIOAudioIODeviceType()
 -     {
 -     }
 - 
 -     //==============================================================================
 -     void scanForDevices()
 -     {
 -         hasScanned = true;
 - 
 -         deviceNames.clear();
 -         classIds.clear();
 - 
 -         HKEY hk = 0;
 -         int index = 0;
 - 
 -         if (RegOpenKeyA (HKEY_LOCAL_MACHINE, "software\\asio", &hk) == ERROR_SUCCESS)
 -         {
 -             for (;;)
 -             {
 -                 char name [256];
 - 
 -                 if (RegEnumKeyA (hk, index++, name, 256) == ERROR_SUCCESS)
 -                 {
 -                     addDriverInfo (name, hk);
 -                 }
 -                 else
 -                 {
 -                     break;
 -                 }
 -             }
 - 
 -             RegCloseKey (hk);
 -         }
 -     }
 - 
 -     const StringArray getDeviceNames (const bool /*wantInputNames*/) const
 -     {
 -         jassert (hasScanned); // need to call scanForDevices() before doing this
 - 
 -         return deviceNames;
 -     }
 - 
 -     int getDefaultDeviceIndex (const bool) const
 -     {
 -         jassert (hasScanned); // need to call scanForDevices() before doing this
 - 
 -         for (int i = deviceNames.size(); --i >= 0;)
 -             if (deviceNames[i].containsIgnoreCase (T("asio4all")))
 -                 return i; // asio4all is a safe choice for a default..
 - 
 - #if JUCE_DEBUG
 -         if (deviceNames.size() > 1 && deviceNames[0].containsIgnoreCase (T("digidesign")))
 -             return 1; // (the digi m-box driver crashes the app when you run 
 -                       // it in the debugger, which can be a bit annoying)
 - #endif
 - 
 -         return 0;
 -     }
 - 
 -     static int findFreeSlot()
 -     {
 -         for (int i = 0; i < numElementsInArray (currentASIODev); ++i)
 -             if (currentASIODev[i] == 0)
 -                 return i;
 - 
 -         jassertfalse;  // unfortunately you can only have a finite number
 -                        // of ASIO devices open at the same time..
 -         return -1;
 -     }
 - 
 -     int getIndexOfDevice (AudioIODevice* d, const bool /*asInput*/) const
 -     {
 -         jassert (hasScanned); // need to call scanForDevices() before doing this
 - 
 -         return d == 0 ? -1 : deviceNames.indexOf (d->getName());
 -     }
 - 
 -     bool hasSeparateInputsAndOutputs() const    { return false; }
 - 
 -     AudioIODevice* createDevice (const String& outputDeviceName,
 -                                  const String& inputDeviceName)
 -     {
 -         jassert (inputDeviceName == outputDeviceName);
 -         (void) inputDeviceName;
 -         jassert (hasScanned); // need to call scanForDevices() before doing this
 - 
 -         const int index = deviceNames.indexOf (outputDeviceName);
 - 
 -         if (index >= 0)
 -         {
 -             const int freeSlot = findFreeSlot();
 - 
 -             if (freeSlot >= 0)
 -                 return new ASIOAudioIODevice (outputDeviceName, *(classIds [index]), freeSlot);
 -         }
 - 
 -         return 0;
 -     }
 - 
 -     //==============================================================================
 -     juce_UseDebuggingNewOperator
 - 
 - private:
 -     StringArray deviceNames;
 -     OwnedArray <CLSID> classIds;
 - 
 -     bool hasScanned;
 - 
 -     //==============================================================================
 -     static bool checkClassIsOk (const String& classId)
 -     {
 -         HKEY hk = 0;
 -         bool ok = false;
 - 
 -         if (RegOpenKeyA (HKEY_CLASSES_ROOT, "clsid", &hk) == ERROR_SUCCESS)
 -         {
 -             int index = 0;
 - 
 -             for (;;)
 -             {
 -                 char buf [512];
 - 
 -                 if (RegEnumKeyA (hk, index++, buf, 512) == ERROR_SUCCESS)
 -                 {
 -                     if (classId.equalsIgnoreCase (buf))
 -                     {
 -                         HKEY subKey, pathKey;
 - 
 -                         if (RegOpenKeyExA (hk, buf, 0, KEY_READ, &subKey) == ERROR_SUCCESS)
 -                         {
 -                             if (RegOpenKeyExA (subKey, "InprocServer32", 0, KEY_READ, &pathKey) == ERROR_SUCCESS)
 -                             {
 -                                 char pathName [600];
 -                                 DWORD dtype = REG_SZ;
 -                                 DWORD dsize = sizeof (pathName);
 - 
 -                                 if (RegQueryValueExA (pathKey, 0, 0, &dtype,
 -                                                       (LPBYTE) pathName, &dsize) == ERROR_SUCCESS)
 -                                 {
 -                                     OFSTRUCT of;
 -                                     zerostruct (of);
 - 
 -                                     of.cBytes = sizeof (of);
 - 
 -                                     ok = (OpenFile (String (pathName), &of, OF_EXIST) != 0);
 -                                 }
 - 
 -                                 RegCloseKey (pathKey);
 -                             }
 - 
 -                             RegCloseKey (subKey);
 -                         }
 - 
 -                         break;
 -                     }
 -                 }
 -                 else
 -                 {
 -                     break;
 -                 }
 -             }
 - 
 -             RegCloseKey (hk);
 -         }
 - 
 -         return ok;
 -     }
 - 
 -     //==============================================================================
 -     void addDriverInfo (const String& keyName, HKEY hk)
 -     {
 -         HKEY subKey;
 - 
 -         if (RegOpenKeyExA (hk, keyName, 0, KEY_READ, &subKey) == ERROR_SUCCESS)
 -         {
 -             char buf [256];
 -             DWORD dtype = REG_SZ;
 -             DWORD dsize = sizeof (buf);
 -             zeromem (buf, dsize);
 - 
 -             if (RegQueryValueExA (subKey, "clsid", 0, &dtype, (LPBYTE) buf, &dsize) == ERROR_SUCCESS)
 -             {
 -                 if (dsize > 0 && checkClassIsOk (buf))
 -                 {
 -                     wchar_t classIdStr [130];
 -                     MultiByteToWideChar (CP_ACP, 0, buf, -1, classIdStr, 128);
 - 
 -                     String deviceName;
 -                     CLSID classId;
 - 
 -                     if (CLSIDFromString ((LPOLESTR) classIdStr, &classId) == S_OK)
 -                     {
 -                         dtype = REG_SZ;
 -                         dsize = sizeof (buf);
 - 
 -                         if (RegQueryValueExA (subKey, "description", 0, &dtype, (LPBYTE) buf, &dsize) == ERROR_SUCCESS)
 -                             deviceName = buf;
 -                         else
 -                             deviceName = keyName;
 - 
 -                         log (T("found ") + deviceName);
 -                         deviceNames.add (deviceName);
 -                         classIds.add (new CLSID (classId));
 -                     }
 -                 }
 - 
 -                 RegCloseKey (subKey);
 -             }
 -         }
 -     }
 - 
 -     ASIOAudioIODeviceType (const ASIOAudioIODeviceType&);
 -     const ASIOAudioIODeviceType& operator= (const ASIOAudioIODeviceType&);
 - };
 - 
 - AudioIODeviceType* juce_createASIOAudioIODeviceType()
 - {
 -     return new ASIOAudioIODeviceType();
 - }
 - 
 - AudioIODevice* juce_createASIOAudioIODeviceForGUID (const String& name, 
 -                                                     void* guid)
 - {
 -     const int freeSlot = ASIOAudioIODeviceType::findFreeSlot();
 - 
 -     if (freeSlot < 0)
 -         return 0;
 - 
 -     return new ASIOAudioIODevice (name, *(CLSID*) guid, freeSlot);
 - }
 - 
 - 
 - END_JUCE_NAMESPACE
 - 
 - #undef log
 - 
 - #endif
 
 
  |