| @@ -314,6 +314,7 @@ public: | |||||
| currentSampleRate (0), | currentSampleRate (0), | ||||
| deviceIsOpen (false), | deviceIsOpen (false), | ||||
| isStarted (false), | isStarted (false), | ||||
| buffersCreated (false), | |||||
| postOutput (true), | postOutput (true), | ||||
| insideControlPanelModalLoop (false), | insideControlPanelModalLoop (false), | ||||
| shouldUsePreferredSize (false) | shouldUsePreferredSize (false) | ||||
| @@ -508,7 +509,7 @@ public: | |||||
| needToReset = false; | needToReset = false; | ||||
| isReSync = false; | isReSync = false; | ||||
| err = 0; | err = 0; | ||||
| bool buffersCreated = false; | |||||
| buffersCreated = false; | |||||
| if (currentSampleRate != sampleRate) | if (currentSampleRate != sampleRate) | ||||
| { | { | ||||
| @@ -734,9 +735,7 @@ public: | |||||
| if (error.isNotEmpty()) | if (error.isNotEmpty()) | ||||
| { | { | ||||
| logError (error, err); | logError (error, err); | ||||
| if (asioObject != nullptr && buffersCreated) | |||||
| asioObject->disposeBuffers(); | |||||
| disposeBuffers(); | |||||
| Thread::sleep (20); | Thread::sleep (20); | ||||
| isStarted = false; | isStarted = false; | ||||
| @@ -775,7 +774,7 @@ public: | |||||
| Thread::sleep (20); | Thread::sleep (20); | ||||
| asioObject->stop(); | asioObject->stop(); | ||||
| Thread::sleep (10); | Thread::sleep (10); | ||||
| asioObject->disposeBuffers(); | |||||
| disposeBuffers(); | |||||
| } | } | ||||
| Thread::sleep (10); | Thread::sleep (10); | ||||
| @@ -931,7 +930,7 @@ private: | |||||
| HeapBlock <float> tempBuffer; | HeapBlock <float> tempBuffer; | ||||
| int volatile bufferIndex, numActiveInputChans, numActiveOutputChans; | int volatile bufferIndex, numActiveInputChans, numActiveOutputChans; | ||||
| bool deviceIsOpen, isStarted; | |||||
| bool deviceIsOpen, isStarted, buffersCreated; | |||||
| bool volatile isASIOOpen; | bool volatile isASIOOpen; | ||||
| bool volatile calledback; | bool volatile calledback; | ||||
| bool volatile littleEndian, postOutput, needToReset, isReSync; | bool volatile littleEndian, postOutput, needToReset, isReSync; | ||||
| @@ -1230,10 +1229,7 @@ private: | |||||
| if (error.isNotEmpty()) | if (error.isNotEmpty()) | ||||
| { | { | ||||
| logError (error, err); | logError (error, err); | ||||
| if (asioObject != nullptr) | |||||
| asioObject->disposeBuffers(); | |||||
| disposeBuffers(); | |||||
| removeCurrentDriver(); | removeCurrentDriver(); | ||||
| isASIOOpen = false; | isASIOOpen = false; | ||||
| } | } | ||||
| @@ -1250,6 +1246,15 @@ private: | |||||
| return error; | return error; | ||||
| } | } | ||||
| void disposeBuffers() | |||||
| { | |||||
| if (asioObject != nullptr && buffersCreated) | |||||
| { | |||||
| buffersCreated = false; | |||||
| asioObject->disposeBuffers(); | |||||
| } | |||||
| } | |||||
| //============================================================================== | //============================================================================== | ||||
| void JUCE_ASIOCALLBACK callback (const long index) | void JUCE_ASIOCALLBACK callback (const long index) | ||||
| { | { | ||||
| @@ -474,7 +474,10 @@ public: | |||||
| //============================================================================== | //============================================================================== | ||||
| #if BUILD_AU_CARBON_UI | #if BUILD_AU_CARBON_UI | ||||
| int GetNumCustomUIComponents() { return 1; } | |||||
| int GetNumCustomUIComponents() | |||||
| { | |||||
| return PluginHostType().isDigitalPerformer() ? 0 : 1; | |||||
| } | |||||
| void GetUIComponentDescs (ComponentDescription* inDescArray) | void GetUIComponentDescs (ComponentDescription* inDescArray) | ||||
| { | { | ||||
| @@ -60,25 +60,27 @@ public: | |||||
| MuseReceptorGeneric, | MuseReceptorGeneric, | ||||
| MagixSamplitude, | MagixSamplitude, | ||||
| FruityLoops, | FruityLoops, | ||||
| WaveBurner | |||||
| WaveBurner, | |||||
| DigitalPerformer | |||||
| }; | }; | ||||
| const HostType type; | const HostType type; | ||||
| //============================================================================== | //============================================================================== | ||||
| bool isAbletonLive() const noexcept { return type == AbletonLive6 || type == AbletonLive7 || type == AbletonLive8 || type == AbletonLiveGeneric; } | |||||
| bool isCubase() const noexcept { return type == SteinbergCubase4 || type == SteinbergCubase5 || type == SteinbergCubase5Bridged || type == SteinbergCubaseGeneric; } | |||||
| bool isCubaseBridged() const noexcept { return type == SteinbergCubase5Bridged; } | |||||
| bool isTracktion() const noexcept { return type == MackieTracktion3 || type == MackieTracktionGeneric; } | |||||
| bool isSonar() const noexcept { return type == CakewalkSonar8 || type == CakewalkSonarGeneric; } | |||||
| bool isWavelab() const noexcept { return isWavelabLegacy() || type == SteinbergWavelab7 || type == SteinbergWavelabGeneric; } | |||||
| bool isWavelabLegacy() const noexcept { return type == SteinbergWavelab5 || type == SteinbergWavelab6; } | |||||
| bool isPremiere() const noexcept { return type == AdobePremierePro; } | |||||
| bool isLogic() const noexcept { return type == AppleLogic || type == EmagicLogic; } | |||||
| bool isReceptor() const noexcept { return type == MuseReceptorGeneric; } | |||||
| bool isSamplitude() const noexcept { return type == MagixSamplitude; } | |||||
| bool isFruityLoops() const noexcept { return type == FruityLoops; } | |||||
| bool isWaveBurner() const noexcept { return type == WaveBurner; } | |||||
| bool isAbletonLive() const noexcept { return type == AbletonLive6 || type == AbletonLive7 || type == AbletonLive8 || type == AbletonLiveGeneric; } | |||||
| bool isCubase() const noexcept { return type == SteinbergCubase4 || type == SteinbergCubase5 || type == SteinbergCubase5Bridged || type == SteinbergCubaseGeneric; } | |||||
| bool isCubaseBridged() const noexcept { return type == SteinbergCubase5Bridged; } | |||||
| bool isTracktion() const noexcept { return type == MackieTracktion3 || type == MackieTracktionGeneric; } | |||||
| bool isSonar() const noexcept { return type == CakewalkSonar8 || type == CakewalkSonarGeneric; } | |||||
| bool isWavelab() const noexcept { return isWavelabLegacy() || type == SteinbergWavelab7 || type == SteinbergWavelabGeneric; } | |||||
| bool isWavelabLegacy() const noexcept { return type == SteinbergWavelab5 || type == SteinbergWavelab6; } | |||||
| bool isPremiere() const noexcept { return type == AdobePremierePro; } | |||||
| bool isLogic() const noexcept { return type == AppleLogic || type == EmagicLogic; } | |||||
| bool isReceptor() const noexcept { return type == MuseReceptorGeneric; } | |||||
| bool isSamplitude() const noexcept { return type == MagixSamplitude; } | |||||
| bool isFruityLoops() const noexcept { return type == FruityLoops; } | |||||
| bool isWaveBurner() const noexcept { return type == WaveBurner; } | |||||
| bool isDigitalPerformer() const noexcept { return type == DigitalPerformer; } | |||||
| //============================================================================== | //============================================================================== | ||||
| static String getHostPath() | static String getHostPath() | ||||
| @@ -94,18 +96,19 @@ private: | |||||
| const String hostFilename (File (hostPath).getFileName()); | const String hostFilename (File (hostPath).getFileName()); | ||||
| #if JUCE_MAC | #if JUCE_MAC | ||||
| if (hostPath.containsIgnoreCase ("Live 6.")) return AbletonLive6; | |||||
| if (hostPath.containsIgnoreCase ("Live 7.")) return AbletonLive7; | |||||
| if (hostPath.containsIgnoreCase ("Live 8.")) return AbletonLive8; | |||||
| if (hostFilename.containsIgnoreCase ("Live")) return AbletonLiveGeneric; | |||||
| if (hostFilename.containsIgnoreCase ("Adobe Premiere")) return AdobePremierePro; | |||||
| if (hostFilename.contains ("Logic")) return AppleLogic; | |||||
| if (hostFilename.containsIgnoreCase ("Pro Tools")) return DigidesignProTools; | |||||
| if (hostFilename.containsIgnoreCase ("Cubase 4")) return SteinbergCubase4; | |||||
| if (hostFilename.containsIgnoreCase ("Cubase 5")) return SteinbergCubase5; | |||||
| if (hostPath.containsIgnoreCase ("Wavelab 7")) return SteinbergWavelab7; | |||||
| if (hostFilename.containsIgnoreCase ("Wavelab")) return SteinbergWavelabGeneric; | |||||
| if (hostFilename.containsIgnoreCase ("WaveBurner")) return WaveBurner; | |||||
| if (hostPath.containsIgnoreCase ("Live 6.")) return AbletonLive6; | |||||
| if (hostPath.containsIgnoreCase ("Live 7.")) return AbletonLive7; | |||||
| if (hostPath.containsIgnoreCase ("Live 8.")) return AbletonLive8; | |||||
| if (hostFilename.containsIgnoreCase ("Live")) return AbletonLiveGeneric; | |||||
| if (hostFilename.containsIgnoreCase ("Adobe Premiere")) return AdobePremierePro; | |||||
| if (hostFilename.contains ("Logic")) return AppleLogic; | |||||
| if (hostFilename.containsIgnoreCase ("Pro Tools")) return DigidesignProTools; | |||||
| if (hostFilename.containsIgnoreCase ("Cubase 4")) return SteinbergCubase4; | |||||
| if (hostFilename.containsIgnoreCase ("Cubase 5")) return SteinbergCubase5; | |||||
| if (hostPath.containsIgnoreCase ("Wavelab 7")) return SteinbergWavelab7; | |||||
| if (hostFilename.containsIgnoreCase ("Wavelab")) return SteinbergWavelabGeneric; | |||||
| if (hostFilename.containsIgnoreCase ("WaveBurner")) return WaveBurner; | |||||
| if (hostFilename.contains ("Digital Performer")) return DigitalPerformer; | |||||
| #elif JUCE_WINDOWS | #elif JUCE_WINDOWS | ||||
| if (hostFilename.containsIgnoreCase ("Live 6.")) return AbletonLive6; | if (hostFilename.containsIgnoreCase ("Live 6.")) return AbletonLive6; | ||||
| @@ -132,11 +135,11 @@ private: | |||||
| if (hostFilename.startsWithIgnoreCase ("Sam")) return MagixSamplitude; | if (hostFilename.startsWithIgnoreCase ("Sam")) return MagixSamplitude; | ||||
| if (hostFilename.startsWith ("FL")) return FruityLoops; | if (hostFilename.startsWith ("FL")) return FruityLoops; | ||||
| #elif JUCE_LINUX | |||||
| #elif JUCE_LINUX | |||||
| jassertfalse // not yet done! | jassertfalse // not yet done! | ||||
| #else | |||||
| #else | |||||
| #error | #error | ||||
| #endif | |||||
| #endif | |||||
| return UnknownHost; | return UnknownHost; | ||||
| } | } | ||||
| @@ -289,7 +289,7 @@ void PluginListComponent::scanFor (AudioPluginFormat* format) | |||||
| aw.setMessage (TRANS("Testing:\n\n") | aw.setMessage (TRANS("Testing:\n\n") | ||||
| + scanner.getNextPluginFileThatWillBeScanned()); | + scanner.getNextPluginFileThatWillBeScanned()); | ||||
| MessageManager::getInstance()->runDispatchLoopUntil (20); | |||||
| MessageManager::getInstance()->runDispatchLoopUntil (100); | |||||
| if (! scanner.scanNextFile (true)) | if (! scanner.scanNextFile (true)) | ||||
| break; | break; | ||||
| @@ -269,14 +269,16 @@ private: | |||||
| { | { | ||||
| uint32 argb; | uint32 argb; | ||||
| struct | |||||
| struct Components | |||||
| { | { | ||||
| #if JUCE_BIG_ENDIAN | #if JUCE_BIG_ENDIAN | ||||
| uint8 a : 8, r : 8, g : 8, b : 8; | uint8 a : 8, r : 8, g : 8, b : 8; | ||||
| #else | #else | ||||
| uint8 b, g, r, a; | uint8 b, g, r, a; | ||||
| #endif | #endif | ||||
| } PACKED components; | |||||
| } PACKED; | |||||
| Components components; | |||||
| }; | }; | ||||
| } | } | ||||
| #ifndef DOXYGEN | #ifndef DOXYGEN | ||||
| @@ -1431,65 +1431,79 @@ private: | |||||
| return 1000 / 60; // Throttling the incoming mouse-events seems to still be needed in XP.. | return 1000 / 60; // Throttling the incoming mouse-events seems to still be needed in XP.. | ||||
| } | } | ||||
| static bool isCurrentEventFromTouchScreen() noexcept | |||||
| { | |||||
| return (GetMessageExtraInfo() & 0xffffff00 /* SIGNATURE_MASK */) == 0xff515700; /* MI_WP_SIGNATURE */ | |||||
| } | |||||
| void doMouseMove (const Point<int>& position) | void doMouseMove (const Point<int>& position) | ||||
| { | { | ||||
| if (! isMouseOver) | |||||
| if (! isCurrentEventFromTouchScreen()) | |||||
| { | { | ||||
| isMouseOver = true; | |||||
| ModifierKeys::getCurrentModifiersRealtime(); // (This avoids a rare stuck-button problem when focus is lost unexpectedly) | |||||
| updateKeyModifiers(); | |||||
| if (! isMouseOver) | |||||
| { | |||||
| isMouseOver = true; | |||||
| ModifierKeys::getCurrentModifiersRealtime(); // (This avoids a rare stuck-button problem when focus is lost unexpectedly) | |||||
| updateKeyModifiers(); | |||||
| TRACKMOUSEEVENT tme; | |||||
| tme.cbSize = sizeof (tme); | |||||
| tme.dwFlags = TME_LEAVE; | |||||
| tme.hwndTrack = hwnd; | |||||
| tme.dwHoverTime = 0; | |||||
| TRACKMOUSEEVENT tme; | |||||
| tme.cbSize = sizeof (tme); | |||||
| tme.dwFlags = TME_LEAVE; | |||||
| tme.hwndTrack = hwnd; | |||||
| tme.dwHoverTime = 0; | |||||
| if (! TrackMouseEvent (&tme)) | |||||
| jassertfalse; | |||||
| if (! TrackMouseEvent (&tme)) | |||||
| jassertfalse; | |||||
| Desktop::getInstance().getMainMouseSource().forceMouseCursorUpdate(); | |||||
| } | |||||
| else if (! isDragging) | |||||
| { | |||||
| if (! contains (position, false)) | |||||
| return; | |||||
| } | |||||
| Desktop::getInstance().getMainMouseSource().forceMouseCursorUpdate(); | |||||
| } | |||||
| else if (! isDragging) | |||||
| { | |||||
| if (! contains (position, false)) | |||||
| return; | |||||
| } | |||||
| static uint32 lastMouseTime = 0; | |||||
| static int minTimeBetweenMouses = getMinTimeBetweenMouseMoves(); | |||||
| const uint32 now = Time::getMillisecondCounter(); | |||||
| static uint32 lastMouseTime = 0; | |||||
| static int minTimeBetweenMouses = getMinTimeBetweenMouseMoves(); | |||||
| const uint32 now = Time::getMillisecondCounter(); | |||||
| if (now >= lastMouseTime + minTimeBetweenMouses) | |||||
| { | |||||
| lastMouseTime = now; | |||||
| doMouseEvent (position); | |||||
| if (now >= lastMouseTime + minTimeBetweenMouses) | |||||
| { | |||||
| lastMouseTime = now; | |||||
| doMouseEvent (position); | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| void doMouseDown (const Point<int>& position, const WPARAM wParam) | void doMouseDown (const Point<int>& position, const WPARAM wParam) | ||||
| { | { | ||||
| if (GetCapture() != hwnd) | |||||
| SetCapture (hwnd); | |||||
| if (! isCurrentEventFromTouchScreen()) | |||||
| { | |||||
| if (GetCapture() != hwnd) | |||||
| SetCapture (hwnd); | |||||
| doMouseMove (position); | |||||
| doMouseMove (position); | |||||
| updateModifiersFromWParam (wParam); | |||||
| isDragging = true; | |||||
| updateModifiersFromWParam (wParam); | |||||
| isDragging = true; | |||||
| doMouseEvent (position); | |||||
| doMouseEvent (position); | |||||
| } | |||||
| } | } | ||||
| void doMouseUp (const Point<int>& position, const WPARAM wParam) | void doMouseUp (const Point<int>& position, const WPARAM wParam) | ||||
| { | { | ||||
| updateModifiersFromWParam (wParam); | |||||
| isDragging = false; | |||||
| if (! isCurrentEventFromTouchScreen()) | |||||
| { | |||||
| updateModifiersFromWParam (wParam); | |||||
| isDragging = false; | |||||
| // release the mouse capture if the user has released all buttons | |||||
| if ((wParam & (MK_LBUTTON | MK_RBUTTON | MK_MBUTTON)) == 0 && hwnd == GetCapture()) | |||||
| ReleaseCapture(); | |||||
| // release the mouse capture if the user has released all buttons | |||||
| if ((wParam & (MK_LBUTTON | MK_RBUTTON | MK_MBUTTON)) == 0 && hwnd == GetCapture()) | |||||
| ReleaseCapture(); | |||||
| doMouseEvent (position); | |||||
| doMouseEvent (position); | |||||
| } | |||||
| } | } | ||||
| void doCaptureChanged() | void doCaptureChanged() | ||||
| @@ -1282,7 +1282,9 @@ void TextEditor::textWasChangedByValue() | |||||
| void TextEditor::textChanged() | void TextEditor::textChanged() | ||||
| { | { | ||||
| updateTextHolderSize(); | updateTextHolderSize(); | ||||
| postCommandMessage (TextEditorDefs::textChangeMessageId); | |||||
| if (listeners.size() > 0) | |||||
| postCommandMessage (TextEditorDefs::textChangeMessageId); | |||||
| if (textValue.getValueSource().getReferenceCount() > 1) | if (textValue.getValueSource().getReferenceCount() > 1) | ||||
| { | { | ||||