| @@ -52,7 +52,7 @@ namespace ASIODebugging | |||
| switch (error) | |||
| { | |||
| case 0: return; | |||
| case ASE_OK: return; | |||
| case ASE_NotPresent: err = "Not Present"; break; | |||
| case ASE_HWMalfunction: err = "Hardware Malfunction"; break; | |||
| case ASE_InvalidParameter: err = "Invalid Parameter"; break; | |||
| @@ -313,20 +313,30 @@ class ASIOAudioIODevice : public AudioIODevice, | |||
| private Timer | |||
| { | |||
| public: | |||
| ASIOAudioIODevice (ASIOAudioIODeviceType* ownerType, | |||
| const String& devName, const CLSID clsID, | |||
| const int slotNumber, const String& dllForDirectLoading) | |||
| ASIOAudioIODevice (ASIOAudioIODeviceType* ownerType, const String& devName, | |||
| const CLSID clsID, const int slotNumber) | |||
| : AudioIODevice (devName, "ASIO"), | |||
| owner (ownerType), | |||
| asioObject (nullptr), | |||
| classId (clsID), | |||
| optionalDllForDirectLoading (dllForDirectLoading), | |||
| inputLatency (0), | |||
| outputLatency (0), | |||
| minSize (0), maxSize (0), | |||
| preferredSize (0), | |||
| granularity (0), | |||
| currentBlockSizeSamples (0), | |||
| currentBitDepth (16), | |||
| currentSampleRate (0), | |||
| currentCallback (nullptr), | |||
| bufferIndex (0), | |||
| numActiveInputChans (0), | |||
| numActiveOutputChans (0), | |||
| deviceIsOpen (false), | |||
| isStarted (false), | |||
| buffersCreated (false), | |||
| isASIOOpen (false), | |||
| calledback (false), | |||
| littleEndian (false), | |||
| postOutput (true), | |||
| needToReset (false), | |||
| insideControlPanelModalLoop (false), | |||
| @@ -401,13 +411,12 @@ public: | |||
| String open (const BigInteger& inputChannels, | |||
| const BigInteger& outputChannels, | |||
| double sr, | |||
| int bufferSizeSamples) | |||
| double sr, int bufferSizeSamples) | |||
| { | |||
| close(); | |||
| jassert (currentCallback == nullptr); | |||
| if (bufferSizeSamples <= 0) | |||
| if (bufferSizeSamples < 8 || bufferSizeSamples > 16384) | |||
| shouldUsePreferredSize = true; | |||
| { | |||
| @@ -432,6 +441,9 @@ public: | |||
| if (preferredSize != 0 && newPreferredSize != 0 && newPreferredSize != preferredSize) | |||
| shouldUsePreferredSize = true; | |||
| if (bufferSizeSamples < minSize || bufferSizeSamples > maxSize) | |||
| shouldUsePreferredSize = true; | |||
| preferredSize = newPreferredSize; | |||
| } | |||
| @@ -562,24 +574,18 @@ public: | |||
| err = asioObject->disposeBuffers(); | |||
| JUCE_ASIO_LOG ("creating buffers: " + String (totalBuffers) + ", " + String (currentBlockSizeSamples)); | |||
| err = asioObject->createBuffers (bufferInfos, | |||
| totalBuffers, | |||
| currentBlockSizeSamples, | |||
| &callbacks); | |||
| err = asioObject->createBuffers (bufferInfos, totalBuffers, currentBlockSizeSamples, &callbacks); | |||
| if (err != 0) | |||
| if (err != ASE_OK) | |||
| { | |||
| currentBlockSizeSamples = preferredSize; | |||
| JUCE_ASIO_LOG_ERROR ("create buffers 2", err); | |||
| asioObject->disposeBuffers(); | |||
| err = asioObject->createBuffers (bufferInfos, | |||
| totalBuffers, | |||
| currentBlockSizeSamples, | |||
| &callbacks); | |||
| err = asioObject->createBuffers (bufferInfos, totalBuffers, currentBlockSizeSamples, &callbacks); | |||
| } | |||
| if (err == 0) | |||
| if (err == ASE_OK) | |||
| { | |||
| buffersCreated = true; | |||
| @@ -848,7 +854,6 @@ private: | |||
| ASIOCallbacks callbacks; | |||
| CLSID classId; | |||
| const String optionalDllForDirectLoading; | |||
| String error; | |||
| long totalNumInputChans, totalNumOutputChans; | |||
| @@ -958,6 +963,36 @@ private: | |||
| return numActiveInputChans + numActiveOutputChans; | |||
| } | |||
| void addBufferSizes (long minSize, long maxSize, long preferredSize, long granularity) | |||
| { | |||
| // find a list of buffer sizes.. | |||
| JUCE_ASIO_LOG (String ((int) minSize) + "->" + String ((int) maxSize) + ", " | |||
| + String ((int) preferredSize) + ", " + String ((int) granularity)); | |||
| if (granularity >= 0) | |||
| { | |||
| granularity = jmax (16, (int) granularity); | |||
| for (int i = jmax ((int) (minSize + 15) & ~15, (int) granularity); i < jmin (6400, (int) 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); | |||
| } | |||
| } | |||
| bufferSizes.addIfNotAlreadyThere (preferredSize); | |||
| DefaultElementComparator <int> comparator; | |||
| bufferSizes.sort (comparator); | |||
| } | |||
| void removeCurrentDriver() | |||
| { | |||
| if (asioObject != nullptr) | |||
| @@ -971,45 +1006,28 @@ private: | |||
| { | |||
| removeCurrentDriver(); | |||
| JUCE_TRY | |||
| { | |||
| if (CoCreateInstance (classId, 0, CLSCTX_INPROC_SERVER, | |||
| classId, (void**) &asioObject) == S_OK) | |||
| { | |||
| return true; | |||
| } | |||
| bool crashed = false; | |||
| bool ok = tryCreatingDriver (crashed); | |||
| // If a class isn't registered but we have a path for it, we can fallback to | |||
| // doing a direct load of the COM object (only available via the juce_createASIOAudioIODeviceForGUID function). | |||
| if (optionalDllForDirectLoading.isNotEmpty()) | |||
| { | |||
| HMODULE h = LoadLibrary (optionalDllForDirectLoading.toWideCharPointer()); | |||
| if (crashed) | |||
| JUCE_ASIO_LOG ("** Driver crashed while being opened"); | |||
| if (h != 0) | |||
| { | |||
| typedef HRESULT (CALLBACK* DllGetClassObjectFunc) (REFCLSID clsid, REFIID iid, LPVOID* ppv); | |||
| DllGetClassObjectFunc dllGetClassObject = (DllGetClassObjectFunc) GetProcAddress (h, "DllGetClassObject"); | |||
| if (dllGetClassObject != 0) | |||
| { | |||
| IClassFactory* classFactory = nullptr; | |||
| HRESULT hr = dllGetClassObject (classId, IID_IClassFactory, (void**) &classFactory); | |||
| if (classFactory != nullptr) | |||
| { | |||
| hr = classFactory->CreateInstance (0, classId, (void**) &asioObject); | |||
| classFactory->Release(); | |||
| } | |||
| return ok; | |||
| } | |||
| return asioObject != nullptr; | |||
| } | |||
| } | |||
| } | |||
| bool tryCreatingDriver (bool& crashed) | |||
| { | |||
| #if ! JUCE_MINGW | |||
| __try | |||
| #endif | |||
| { | |||
| return CoCreateInstance (classId, 0, CLSCTX_INPROC_SERVER, | |||
| classId, (void**) &asioObject) == S_OK; | |||
| } | |||
| JUCE_CATCH_ALL | |||
| asioObject = nullptr; | |||
| #if ! JUCE_MINGW | |||
| __except (EXCEPTION_EXECUTE_HANDLER) { crashed = true; } | |||
| return false; | |||
| #endif | |||
| } | |||
| String getLastDriverError() const | |||
| @@ -1093,29 +1111,7 @@ private: | |||
| if ((err = asioObject->getBufferSize (&minSize, &maxSize, &preferredSize, &granularity)) == 0) | |||
| { | |||
| // find a list of buffer sizes.. | |||
| JUCE_ASIO_LOG (String ((int) minSize) + "->" + String ((int) maxSize) + ", " + String ((int) preferredSize) + ", " + String ((int) granularity)); | |||
| if (granularity >= 0) | |||
| { | |||
| granularity = jmax (16, (int) granularity); | |||
| for (int i = jmax ((int) (minSize + 15) & ~15, (int) granularity); i < jmin (6400, (int) 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); | |||
| addBufferSizes (minSize, maxSize, preferredSize, granularity); | |||
| double currentRate = 0; | |||
| asioObject->getSampleRate (¤tRate); | |||
| @@ -1412,7 +1408,6 @@ public: | |||
| : AudioIODeviceType ("ASIO"), | |||
| hasScanned (false) | |||
| { | |||
| CoInitialize (0); | |||
| } | |||
| ~ASIOAudioIODeviceType() | |||
| @@ -1501,7 +1496,8 @@ public: | |||
| const int freeSlot = findFreeSlot(); | |||
| if (freeSlot >= 0) | |||
| return new ASIOAudioIODevice (this, outputDeviceName, *(classIds [index]), freeSlot, String::empty); | |||
| return new ASIOAudioIODevice (this, outputDeviceName, | |||
| classIds.getReference (index), freeSlot); | |||
| } | |||
| return nullptr; | |||
| @@ -1516,7 +1512,7 @@ public: | |||
| private: | |||
| StringArray deviceNames; | |||
| OwnedArray <CLSID> classIds; | |||
| Array<CLSID> classIds; | |||
| bool hasScanned; | |||
| @@ -1595,7 +1591,7 @@ private: | |||
| JUCE_ASIO_LOG ("found " + deviceName); | |||
| deviceNames.add (deviceName); | |||
| classIds.add (new CLSID (classId)); | |||
| classIds.add (classId); | |||
| } | |||
| } | |||
| @@ -1617,14 +1613,3 @@ AudioIODeviceType* AudioIODeviceType::createAudioIODeviceType_ASIO() | |||
| { | |||
| return new ASIOAudioIODeviceType(); | |||
| } | |||
| AudioIODevice* juce_createASIOAudioIODeviceForGUID (const String& name, void* guid, | |||
| const String& optionalDllForDirectLoading) | |||
| { | |||
| const int freeSlot = ASIOAudioIODeviceType::findFreeSlot(); | |||
| if (freeSlot < 0) | |||
| return nullptr; | |||
| return new ASIOAudioIODevice (nullptr, name, *(CLSID*) guid, freeSlot, optionalDllForDirectLoading); | |||
| } | |||