| @@ -422,7 +422,8 @@ bool juce_launchFile (const String& fileName, | |||||
| String cmdString (fileName); | String cmdString (fileName); | ||||
| cmdString << " " << parameters; | cmdString << " " << parameters; | ||||
| if (URL::isProbablyAWebsiteURL (cmdString) || URL::isProbablyAnEmailAddress (cmdString)) | |||||
| if (URL::isProbablyAWebsiteURL (fileName) | |||||
| || URL::isProbablyAnEmailAddress (fileName)) | |||||
| { | { | ||||
| // create a command that tries to launch a bunch of likely browsers | // create a command that tries to launch a bunch of likely browsers | ||||
| const char* const browserNames[] = { "/etc/alternatives/x-www-browser", "firefox", "mozilla", "konqueror", "opera" }; | const char* const browserNames[] = { "/etc/alternatives/x-www-browser", "firefox", "mozilla", "konqueror", "opera" }; | ||||
| @@ -435,6 +436,9 @@ bool juce_launchFile (const String& fileName, | |||||
| cmdString = cmdLines.joinIntoString (T(" || ")); | cmdString = cmdLines.joinIntoString (T(" || ")); | ||||
| } | } | ||||
| if (cmdString.startsWithIgnoreCase (T("file:"))) | |||||
| cmdString = cmdString.substring (5); | |||||
| char* const argv[4] = { "/bin/sh", "-c", (char*) cmdString.toUTF8(), 0 }; | char* const argv[4] = { "/bin/sh", "-c", (char*) cmdString.toUTF8(), 0 }; | ||||
| const int cpid = fork(); | const int cpid = fork(); | ||||
| @@ -38,6 +38,8 @@ | |||||
| */ | */ | ||||
| #define JUCE_QUICKTIME 0 | #define JUCE_QUICKTIME 0 | ||||
| #define JUCE_SUPPORT_CARBON 1 | |||||
| //#define JUCE_PLUGINHOST_VST 1 | //#define JUCE_PLUGINHOST_VST 1 | ||||
| //#define JUCE_PLUGINHOST_AU 1 | //#define JUCE_PLUGINHOST_AU 1 | ||||
| //#define JUCE_ONLY_BUILD_CORE_LIBRARY 1 | //#define JUCE_ONLY_BUILD_CORE_LIBRARY 1 | ||||
| @@ -109,6 +109,8 @@ | |||||
| #endif | #endif | ||||
| #include "../juce_PluginHeaders.h" | #include "../juce_PluginHeaders.h" | ||||
| #include "../../../../src/juce_appframework/audio/plugins/formats/juce_VSTMidiEventList.h" | |||||
| #ifdef _MSC_VER | #ifdef _MSC_VER | ||||
| #pragma pack (pop) | #pragma pack (pop) | ||||
| @@ -336,8 +338,6 @@ public: | |||||
| filter (filter_) | filter (filter_) | ||||
| { | { | ||||
| editorComp = 0; | editorComp = 0; | ||||
| outgoingEvents = 0; | |||||
| outgoingEventSize = 0; | |||||
| chunkMemoryTime = 0; | chunkMemoryTime = 0; | ||||
| isProcessing = false; | isProcessing = false; | ||||
| hasShutdown = false; | hasShutdown = false; | ||||
| @@ -393,15 +393,6 @@ public: | |||||
| delete filter; | delete filter; | ||||
| filter = 0; | filter = 0; | ||||
| if (outgoingEvents != 0) | |||||
| { | |||||
| for (int i = outgoingEventSize; --i >= 0;) | |||||
| juce_free (outgoingEvents->events[i]); | |||||
| juce_free (outgoingEvents); | |||||
| outgoingEvents = 0; | |||||
| } | |||||
| jassert (editorComp == 0); | jassert (editorComp == 0); | ||||
| juce_free (channels); | juce_free (channels); | ||||
| @@ -560,20 +551,7 @@ public: | |||||
| VstInt32 processEvents (VstEvents* events) | VstInt32 processEvents (VstEvents* events) | ||||
| { | { | ||||
| #if JucePlugin_WantsMidiInput | #if JucePlugin_WantsMidiInput | ||||
| for (int i = 0; i < events->numEvents; ++i) | |||||
| { | |||||
| const VstEvent* const e = events->events[i]; | |||||
| if (e != 0 && e->type == kVstMidiType) | |||||
| { | |||||
| const VstMidiEvent* const vme = (const VstMidiEvent*) e; | |||||
| midiEvents.addEvent ((const JUCE_NAMESPACE::uint8*) vme->midiData, | |||||
| 4, | |||||
| vme->deltaFrames); | |||||
| } | |||||
| } | |||||
| VSTMidiEventList::addEventsToMidiBuffer (events, midiEvents); | |||||
| return 1; | return 1; | ||||
| #else | #else | ||||
| return 0; | return 0; | ||||
| @@ -682,8 +660,8 @@ public: | |||||
| #if JucePlugin_ProducesMidiOutput | #if JucePlugin_ProducesMidiOutput | ||||
| const int numEvents = midiEvents.getNumEvents(); | const int numEvents = midiEvents.getNumEvents(); | ||||
| ensureOutgoingEventSize (numEvents); | |||||
| outgoingEvents->numEvents = 0; | |||||
| outgoingEvents.ensureSize (numEvents); | |||||
| outgoingEvents.clear(); | |||||
| const JUCE_NAMESPACE::uint8* midiEventData; | const JUCE_NAMESPACE::uint8* midiEventData; | ||||
| int midiEventSize, midiEventPosition; | int midiEventSize, midiEventPosition; | ||||
| @@ -691,18 +669,12 @@ public: | |||||
| while (i.getNextEvent (midiEventData, midiEventSize, midiEventPosition)) | while (i.getNextEvent (midiEventData, midiEventSize, midiEventPosition)) | ||||
| { | { | ||||
| if (midiEventSize <= 4) | |||||
| { | |||||
| VstMidiEvent* const vme = (VstMidiEvent*) outgoingEvents->events [outgoingEvents->numEvents++]; | |||||
| memcpy (vme->midiData, midiEventData, midiEventSize); | |||||
| vme->deltaFrames = midiEventPosition; | |||||
| jassert (midiEventPosition >= 0 && midiEventPosition < numSamples); | |||||
| jassert (vme->deltaFrames >= 0 && vme->deltaFrames < numSamples); | |||||
| } | |||||
| outgoingEvents.addEvent (midiEventData, midiEventSize, midiEventPosition); | |||||
| } | } | ||||
| sendVstEventsToHost (outgoingEvents); | |||||
| sendVstEventsToHost (outgoingEvents.events); | |||||
| #else | #else | ||||
| /* This assertion is caused when you've added some events to the | /* This assertion is caused when you've added some events to the | ||||
| midiMessages array in your processBlock() method, which usually means | midiMessages array in your processBlock() method, which usually means | ||||
| @@ -763,7 +735,7 @@ public: | |||||
| AudioEffectX::resume(); | AudioEffectX::resume(); | ||||
| #if JucePlugin_ProducesMidiOutput | #if JucePlugin_ProducesMidiOutput | ||||
| ensureOutgoingEventSize (64); | |||||
| outgoingEvents.ensureSize (64); | |||||
| #endif | #endif | ||||
| #if JucePlugin_WantsMidiInput && ! JUCE_USE_VSTSDK_2_4 | #if JucePlugin_WantsMidiInput && ! JUCE_USE_VSTSDK_2_4 | ||||
| @@ -779,7 +751,7 @@ public: | |||||
| AudioEffectX::suspend(); | AudioEffectX::suspend(); | ||||
| filter->releaseResources(); | filter->releaseResources(); | ||||
| midiEvents.clear(); | |||||
| outgoingEvents.freeEvents(); | |||||
| isProcessing = false; | isProcessing = false; | ||||
| juce_free (channels); | juce_free (channels); | ||||
| @@ -1355,8 +1327,7 @@ private: | |||||
| EditorCompWrapper* editorComp; | EditorCompWrapper* editorComp; | ||||
| ERect editorSize; | ERect editorSize; | ||||
| MidiBuffer midiEvents; | MidiBuffer midiEvents; | ||||
| VstEvents* outgoingEvents; | |||||
| int outgoingEventSize; | |||||
| VSTMidiEventList outgoingEvents; | |||||
| bool isProcessing; | bool isProcessing; | ||||
| bool hasShutdown; | bool hasShutdown; | ||||
| bool firstProcessCallback; | bool firstProcessCallback; | ||||
| @@ -1381,31 +1352,6 @@ private: | |||||
| hasCreatedTempChannels = false; | hasCreatedTempChannels = false; | ||||
| } | } | ||||
| void ensureOutgoingEventSize (int numEvents) | |||||
| { | |||||
| if (outgoingEventSize < numEvents) | |||||
| { | |||||
| numEvents += 32; | |||||
| const int size = 16 + sizeof (VstEvent*) * numEvents; | |||||
| if (outgoingEvents == 0) | |||||
| outgoingEvents = (VstEvents*) juce_calloc (size); | |||||
| else | |||||
| outgoingEvents = (VstEvents*) juce_realloc (outgoingEvents, size); | |||||
| for (int i = outgoingEventSize; i < numEvents; ++i) | |||||
| { | |||||
| VstMidiEvent* const e = (VstMidiEvent*) juce_calloc (sizeof (VstMidiEvent)); | |||||
| e->type = kVstMidiType; | |||||
| e->byteSize = 24; | |||||
| outgoingEvents->events[i] = (VstEvent*) e; | |||||
| } | |||||
| outgoingEventSize = numEvents; | |||||
| } | |||||
| } | |||||
| const String getHostName() | const String getHostName() | ||||
| { | { | ||||
| char host[256]; | char host[256]; | ||||
| @@ -42,6 +42,7 @@ | |||||
| */ | */ | ||||
| #include "JucePluginCharacteristics.h" | #include "JucePluginCharacteristics.h" | ||||
| #define SUPPORT_CARBON 1 | |||||
| //============================================================================== | //============================================================================== | ||||
| // The following stuff is just to cause a compile error if you've forgotten to | // The following stuff is just to cause a compile error if you've forgotten to | ||||
| @@ -615,6 +615,243 @@ | |||||
| #pragma warning (disable: 4309 4305) | #pragma warning (disable: 4309 4305) | ||||
| #endif | #endif | ||||
| #if JUCE_MAC && JUCE_SUPPORT_CARBON | |||||
| BEGIN_JUCE_NAMESPACE | |||||
| /********* Start of inlined file: juce_mac_CarbonViewWrapperComponent.h *********/ | |||||
| #ifndef __JUCE_MAC_CARBONVIEWWRAPPERCOMPONENT_JUCEHEADER__ | |||||
| #define __JUCE_MAC_CARBONVIEWWRAPPERCOMPONENT_JUCEHEADER__ | |||||
| /** | |||||
| Creates a floating carbon window that can be used to hold a carbon UI. | |||||
| This is a handy class that's designed to be inlined where needed, e.g. | |||||
| in the audio plugin hosting code. | |||||
| */ | |||||
| class CarbonViewWrapperComponent : public Component, | |||||
| public ComponentMovementWatcher, | |||||
| public Timer | |||||
| { | |||||
| public: | |||||
| CarbonViewWrapperComponent() | |||||
| : ComponentMovementWatcher (this), | |||||
| wrapperWindow (0), | |||||
| embeddedView (0), | |||||
| recursiveResize (false) | |||||
| { | |||||
| } | |||||
| virtual ~CarbonViewWrapperComponent() | |||||
| { | |||||
| jassert (embeddedView == 0); // must call deleteWindow() in the subclass's destructor! | |||||
| } | |||||
| virtual HIViewRef attachView (WindowRef windowRef, HIViewRef rootView) = 0; | |||||
| virtual void removeView (HIViewRef embeddedView) = 0; | |||||
| virtual void mouseDown (int x, int y) {} | |||||
| virtual void paint() {} | |||||
| virtual bool getEmbeddedViewSize (int& w, int& h) | |||||
| { | |||||
| if (embeddedView == 0) | |||||
| return false; | |||||
| HIRect bounds; | |||||
| HIViewGetBounds (embeddedView, &bounds); | |||||
| w = jmax (1, roundFloatToInt (bounds.size.width)); | |||||
| h = jmax (1, roundFloatToInt (bounds.size.height)); | |||||
| return true; | |||||
| } | |||||
| void createWindow() | |||||
| { | |||||
| if (wrapperWindow == 0) | |||||
| { | |||||
| Rect r; | |||||
| r.left = getScreenX(); | |||||
| r.top = getScreenY(); | |||||
| r.right = r.left + getWidth(); | |||||
| r.bottom = r.top + getHeight(); | |||||
| CreateNewWindow (kDocumentWindowClass, | |||||
| (WindowAttributes) (kWindowStandardHandlerAttribute | kWindowCompositingAttribute | |||||
| | kWindowNoShadowAttribute | kWindowNoTitleBarAttribute), | |||||
| &r, &wrapperWindow); | |||||
| jassert (wrapperWindow != 0); | |||||
| if (wrapperWindow == 0) | |||||
| return; | |||||
| NSWindow* carbonWindow = [[NSWindow alloc] initWithWindowRef: wrapperWindow]; | |||||
| NSWindow* ownerWindow = [((NSView*) getWindowHandle()) window]; | |||||
| [ownerWindow addChildWindow: carbonWindow | |||||
| ordered: NSWindowAbove]; | |||||
| embeddedView = attachView (wrapperWindow, HIViewGetRoot (wrapperWindow)); | |||||
| EventTypeSpec windowEventTypes[] = { { kEventClassWindow, kEventWindowGetClickActivation }, | |||||
| { kEventClassWindow, kEventWindowHandleDeactivate } }; | |||||
| EventHandlerUPP upp = NewEventHandlerUPP (carbonEventCallback); | |||||
| InstallWindowEventHandler (wrapperWindow, upp, | |||||
| sizeof (windowEventTypes) / sizeof (EventTypeSpec), | |||||
| windowEventTypes, this, &eventHandlerRef); | |||||
| setOurSizeToEmbeddedViewSize(); | |||||
| setEmbeddedWindowToOurSize(); | |||||
| creationTime = Time::getCurrentTime(); | |||||
| } | |||||
| } | |||||
| void deleteWindow() | |||||
| { | |||||
| removeView (embeddedView); | |||||
| embeddedView = 0; | |||||
| if (wrapperWindow != 0) | |||||
| { | |||||
| RemoveEventHandler (eventHandlerRef); | |||||
| DisposeWindow (wrapperWindow); | |||||
| wrapperWindow = 0; | |||||
| } | |||||
| } | |||||
| void setOurSizeToEmbeddedViewSize() | |||||
| { | |||||
| int w, h; | |||||
| if (getEmbeddedViewSize (w, h)) | |||||
| { | |||||
| if (w != getWidth() || h != getHeight()) | |||||
| { | |||||
| startTimer (50); | |||||
| setSize (w, h); | |||||
| if (getParentComponent() != 0) | |||||
| getParentComponent()->setSize (w, h); | |||||
| } | |||||
| else | |||||
| { | |||||
| startTimer (jlimit (50, 500, getTimerInterval() + 20)); | |||||
| } | |||||
| } | |||||
| else | |||||
| { | |||||
| stopTimer(); | |||||
| } | |||||
| } | |||||
| void setEmbeddedWindowToOurSize() | |||||
| { | |||||
| if (! recursiveResize) | |||||
| { | |||||
| recursiveResize = true; | |||||
| if (embeddedView != 0) | |||||
| { | |||||
| HIRect r; | |||||
| r.origin.x = 0; | |||||
| r.origin.y = 0; | |||||
| r.size.width = (float) getWidth(); | |||||
| r.size.height = (float) getHeight(); | |||||
| HIViewSetFrame (embeddedView, &r); | |||||
| } | |||||
| if (wrapperWindow != 0) | |||||
| { | |||||
| Rect wr; | |||||
| wr.left = getScreenX(); | |||||
| wr.top = getScreenY(); | |||||
| wr.right = wr.left + getWidth(); | |||||
| wr.bottom = wr.top + getHeight(); | |||||
| SetWindowBounds (wrapperWindow, kWindowContentRgn, &wr); | |||||
| ShowWindow (wrapperWindow); | |||||
| } | |||||
| recursiveResize = false; | |||||
| } | |||||
| } | |||||
| void componentMovedOrResized (bool /*wasMoved*/, bool /*wasResized*/) | |||||
| { | |||||
| setEmbeddedWindowToOurSize(); | |||||
| } | |||||
| void componentPeerChanged() | |||||
| { | |||||
| deleteWindow(); | |||||
| createWindow(); | |||||
| } | |||||
| void componentVisibilityChanged (Component&) | |||||
| { | |||||
| if (isShowing()) | |||||
| createWindow(); | |||||
| else | |||||
| deleteWindow(); | |||||
| setEmbeddedWindowToOurSize(); | |||||
| } | |||||
| void timerCallback() | |||||
| { | |||||
| setOurSizeToEmbeddedViewSize(); | |||||
| // To avoid strange overpainting problems when the UI is first opened, we'll | |||||
| // repaint it a few times during the first second that it's on-screen.. | |||||
| if ((Time::getCurrentTime() - creationTime).inMilliseconds() < 1000) | |||||
| HIViewSetNeedsDisplay (embeddedView, true); | |||||
| } | |||||
| OSStatus carbonEventHandler (EventHandlerCallRef nextHandlerRef, | |||||
| EventRef event) | |||||
| { | |||||
| switch (GetEventKind (event)) | |||||
| { | |||||
| case kEventWindowHandleDeactivate: | |||||
| ActivateWindow (wrapperWindow, TRUE); | |||||
| break; | |||||
| case kEventWindowGetClickActivation: | |||||
| { | |||||
| getTopLevelComponent()->toFront (false); | |||||
| ClickActivationResult howToHandleClick = kActivateAndHandleClick; | |||||
| SetEventParameter (event, kEventParamClickActivation, typeClickActivationResult, | |||||
| sizeof (ClickActivationResult), &howToHandleClick); | |||||
| HIViewSetNeedsDisplay (embeddedView, true); | |||||
| } | |||||
| break; | |||||
| } | |||||
| return noErr; | |||||
| } | |||||
| static pascal OSStatus carbonEventCallback (EventHandlerCallRef nextHandlerRef, | |||||
| EventRef event, void* userData) | |||||
| { | |||||
| return ((CarbonViewWrapperComponent*) userData)->carbonEventHandler (nextHandlerRef, event); | |||||
| } | |||||
| protected: | |||||
| WindowRef wrapperWindow; | |||||
| HIViewRef embeddedView; | |||||
| bool recursiveResize; | |||||
| Time creationTime; | |||||
| EventHandlerRef eventHandlerRef; | |||||
| }; | |||||
| #endif // __JUCE_MAC_CARBONVIEWWRAPPERCOMPONENT_JUCEHEADER__ | |||||
| /********* End of inlined file: juce_mac_CarbonViewWrapperComponent.h *********/ | |||||
| END_JUCE_NAMESPACE | |||||
| #endif | |||||
| //============================================================================== | //============================================================================== | ||||
| /********* Start of inlined file: juce_FileLogger.cpp *********/ | /********* Start of inlined file: juce_FileLogger.cpp *********/ | ||||
| @@ -7191,17 +7428,27 @@ bool URL::isWellFormed() const | |||||
| bool URL::isProbablyAWebsiteURL (const String& possibleURL) | bool URL::isProbablyAWebsiteURL (const String& possibleURL) | ||||
| { | { | ||||
| return (possibleURL.containsChar (T('.')) | |||||
| && (! possibleURL.containsChar (T('@'))) | |||||
| && (! possibleURL.endsWithChar (T('.'))) | |||||
| && (possibleURL.startsWithIgnoreCase (T("www.")) | |||||
| || possibleURL.startsWithIgnoreCase (T("http:")) | |||||
| || possibleURL.startsWithIgnoreCase (T("ftp:")) | |||||
| || possibleURL.endsWithIgnoreCase (T(".com")) | |||||
| || possibleURL.endsWithIgnoreCase (T(".net")) | |||||
| || possibleURL.endsWithIgnoreCase (T(".org")) | |||||
| || possibleURL.endsWithIgnoreCase (T(".co.uk"))) | |||||
| || possibleURL.startsWithIgnoreCase (T("file:"))); | |||||
| if (possibleURL.startsWithIgnoreCase (T("http:")) | |||||
| || possibleURL.startsWithIgnoreCase (T("ftp:"))) | |||||
| return true; | |||||
| if (possibleURL.startsWithIgnoreCase (T("file:")) | |||||
| || possibleURL.containsChar (T('@')) | |||||
| || possibleURL.endsWithChar (T('.')) | |||||
| || (! possibleURL.containsChar (T('.')))) | |||||
| return false; | |||||
| if (possibleURL.startsWithIgnoreCase (T("www.")) | |||||
| && possibleURL.substring (5).containsChar (T('.'))) | |||||
| return true; | |||||
| const char* commonTLDs[] = { "com", "net", "org", "uk", "de", "fr", "jp" }; | |||||
| for (int i = 0; i < numElementsInArray (commonTLDs); ++i) | |||||
| if ((possibleURL + T("/")).containsIgnoreCase (T(".") + String (commonTLDs[i]) + T("/"))) | |||||
| return true; | |||||
| return false; | |||||
| } | } | ||||
| bool URL::isProbablyAnEmailAddress (const String& possibleEmailAddress) | bool URL::isProbablyAnEmailAddress (const String& possibleEmailAddress) | ||||
| @@ -27674,241 +27921,6 @@ BEGIN_JUCE_NAMESPACE | |||||
| #define log(a) | #define log(a) | ||||
| #endif | #endif | ||||
| #if JUCE_SUPPORT_CARBON | |||||
| /********* Start of inlined file: juce_mac_CarbonViewWrapperComponent.h *********/ | |||||
| #ifndef __JUCE_MAC_CARBONVIEWWRAPPERCOMPONENT_JUCEHEADER__ | |||||
| #define __JUCE_MAC_CARBONVIEWWRAPPERCOMPONENT_JUCEHEADER__ | |||||
| /** | |||||
| Creates a floating carbon window that can be used to hold a carbon UI. | |||||
| This is a handy class that's designed to be inlined where needed, e.g. | |||||
| in the audio plugin hosting code. | |||||
| */ | |||||
| class CarbonViewWrapperComponent : public Component, | |||||
| public ComponentMovementWatcher, | |||||
| public Timer | |||||
| { | |||||
| public: | |||||
| CarbonViewWrapperComponent() | |||||
| : ComponentMovementWatcher (this), | |||||
| wrapperWindow (0), | |||||
| embeddedView (0), | |||||
| recursiveResize (false) | |||||
| { | |||||
| } | |||||
| virtual ~CarbonViewWrapperComponent() | |||||
| { | |||||
| jassert (embeddedView == 0); // must call deleteWindow() in the subclass's destructor! | |||||
| } | |||||
| virtual HIViewRef attachView (WindowRef windowRef, HIViewRef rootView) = 0; | |||||
| virtual void removeView (HIViewRef embeddedView) = 0; | |||||
| virtual void mouseDown (int x, int y) {} | |||||
| virtual void paint() {} | |||||
| virtual bool getEmbeddedViewSize (int& w, int& h) | |||||
| { | |||||
| if (embeddedView == 0) | |||||
| return false; | |||||
| HIRect bounds; | |||||
| HIViewGetBounds (embeddedView, &bounds); | |||||
| w = jmax (1, roundFloatToInt (bounds.size.width)); | |||||
| h = jmax (1, roundFloatToInt (bounds.size.height)); | |||||
| return true; | |||||
| } | |||||
| void createWindow() | |||||
| { | |||||
| if (wrapperWindow == 0) | |||||
| { | |||||
| Rect r; | |||||
| r.left = getScreenX(); | |||||
| r.top = getScreenY(); | |||||
| r.right = r.left + getWidth(); | |||||
| r.bottom = r.top + getHeight(); | |||||
| CreateNewWindow (kDocumentWindowClass, | |||||
| (WindowAttributes) (kWindowStandardHandlerAttribute | kWindowCompositingAttribute | |||||
| | kWindowNoShadowAttribute | kWindowNoTitleBarAttribute), | |||||
| &r, &wrapperWindow); | |||||
| jassert (wrapperWindow != 0); | |||||
| if (wrapperWindow == 0) | |||||
| return; | |||||
| NSWindow* carbonWindow = [[NSWindow alloc] initWithWindowRef: wrapperWindow]; | |||||
| NSWindow* ownerWindow = [((NSView*) getWindowHandle()) window]; | |||||
| [ownerWindow addChildWindow: carbonWindow | |||||
| ordered: NSWindowAbove]; | |||||
| embeddedView = attachView (wrapperWindow, HIViewGetRoot (wrapperWindow)); | |||||
| EventTypeSpec windowEventTypes[] = { { kEventClassWindow, kEventWindowGetClickActivation }, | |||||
| { kEventClassWindow, kEventWindowHandleDeactivate } }; | |||||
| EventHandlerUPP upp = NewEventHandlerUPP (carbonEventCallback); | |||||
| InstallWindowEventHandler (wrapperWindow, upp, | |||||
| sizeof (windowEventTypes) / sizeof (EventTypeSpec), | |||||
| windowEventTypes, this, &eventHandlerRef); | |||||
| setOurSizeToEmbeddedViewSize(); | |||||
| setEmbeddedWindowToOurSize(); | |||||
| creationTime = Time::getCurrentTime(); | |||||
| } | |||||
| } | |||||
| void deleteWindow() | |||||
| { | |||||
| removeView (embeddedView); | |||||
| embeddedView = 0; | |||||
| if (wrapperWindow != 0) | |||||
| { | |||||
| RemoveEventHandler (eventHandlerRef); | |||||
| DisposeWindow (wrapperWindow); | |||||
| wrapperWindow = 0; | |||||
| } | |||||
| } | |||||
| void setOurSizeToEmbeddedViewSize() | |||||
| { | |||||
| int w, h; | |||||
| if (getEmbeddedViewSize (w, h)) | |||||
| { | |||||
| if (w != getWidth() || h != getHeight()) | |||||
| { | |||||
| startTimer (50); | |||||
| setSize (w, h); | |||||
| if (getParentComponent() != 0) | |||||
| getParentComponent()->setSize (w, h); | |||||
| } | |||||
| else | |||||
| { | |||||
| startTimer (jlimit (50, 500, getTimerInterval() + 20)); | |||||
| } | |||||
| } | |||||
| else | |||||
| { | |||||
| stopTimer(); | |||||
| } | |||||
| } | |||||
| void setEmbeddedWindowToOurSize() | |||||
| { | |||||
| if (! recursiveResize) | |||||
| { | |||||
| recursiveResize = true; | |||||
| if (embeddedView != 0) | |||||
| { | |||||
| HIRect r; | |||||
| r.origin.x = 0; | |||||
| r.origin.y = 0; | |||||
| r.size.width = (float) getWidth(); | |||||
| r.size.height = (float) getHeight(); | |||||
| HIViewSetFrame (embeddedView, &r); | |||||
| } | |||||
| if (wrapperWindow != 0) | |||||
| { | |||||
| Rect wr; | |||||
| wr.left = getScreenX(); | |||||
| wr.top = getScreenY(); | |||||
| wr.right = wr.left + getWidth(); | |||||
| wr.bottom = wr.top + getHeight(); | |||||
| SetWindowBounds (wrapperWindow, kWindowContentRgn, &wr); | |||||
| ShowWindow (wrapperWindow); | |||||
| } | |||||
| recursiveResize = false; | |||||
| } | |||||
| } | |||||
| void componentMovedOrResized (bool /*wasMoved*/, bool /*wasResized*/) | |||||
| { | |||||
| setEmbeddedWindowToOurSize(); | |||||
| } | |||||
| void componentPeerChanged() | |||||
| { | |||||
| deleteWindow(); | |||||
| createWindow(); | |||||
| } | |||||
| void componentVisibilityChanged (Component&) | |||||
| { | |||||
| if (isShowing()) | |||||
| createWindow(); | |||||
| else | |||||
| deleteWindow(); | |||||
| setEmbeddedWindowToOurSize(); | |||||
| } | |||||
| void timerCallback() | |||||
| { | |||||
| setOurSizeToEmbeddedViewSize(); | |||||
| // To avoid strange overpainting problems when the UI is first opened, we'll | |||||
| // repaint it a few times during the first second that it's on-screen.. | |||||
| if ((Time::getCurrentTime() - creationTime).inMilliseconds() < 1000) | |||||
| HIViewSetNeedsDisplay (embeddedView, true); | |||||
| } | |||||
| OSStatus carbonEventHandler (EventHandlerCallRef nextHandlerRef, | |||||
| EventRef event) | |||||
| { | |||||
| switch (GetEventKind (event)) | |||||
| { | |||||
| case kEventWindowHandleDeactivate: | |||||
| ActivateWindow (wrapperWindow, TRUE); | |||||
| break; | |||||
| case kEventWindowGetClickActivation: | |||||
| { | |||||
| getTopLevelComponent()->toFront (false); | |||||
| ClickActivationResult howToHandleClick = kActivateAndHandleClick; | |||||
| SetEventParameter (event, kEventParamClickActivation, typeClickActivationResult, | |||||
| sizeof (ClickActivationResult), &howToHandleClick); | |||||
| HIViewSetNeedsDisplay (embeddedView, true); | |||||
| } | |||||
| break; | |||||
| } | |||||
| return noErr; | |||||
| } | |||||
| static pascal OSStatus carbonEventCallback (EventHandlerCallRef nextHandlerRef, | |||||
| EventRef event, void* userData) | |||||
| { | |||||
| return ((CarbonViewWrapperComponent*) userData)->carbonEventHandler (nextHandlerRef, event); | |||||
| } | |||||
| protected: | |||||
| WindowRef wrapperWindow; | |||||
| HIViewRef embeddedView; | |||||
| bool recursiveResize; | |||||
| Time creationTime; | |||||
| EventHandlerRef eventHandlerRef; | |||||
| }; | |||||
| #endif // __JUCE_MAC_CARBONVIEWWRAPPERCOMPONENT_JUCEHEADER__ | |||||
| /********* End of inlined file: juce_mac_CarbonViewWrapperComponent.h *********/ | |||||
| #endif | |||||
| static int insideCallback = 0; | static int insideCallback = 0; | ||||
| static const String osTypeToString (OSType type) throw() | static const String osTypeToString (OSType type) throw() | ||||
| @@ -29525,9 +29537,9 @@ END_JUCE_NAMESPACE | |||||
| #endif | #endif | ||||
| /********* End of inlined file: juce_Config.h *********/ | /********* End of inlined file: juce_Config.h *********/ | ||||
| #if JUCE_PLUGINHOST_VST && (JUCE_MAC || JUCE_WIN32) | |||||
| #if JUCE_PLUGINHOST_VST | |||||
| #ifdef _WIN32 | |||||
| #if (defined (_WIN32) || defined (_WIN64)) | |||||
| #undef _WIN32_WINNT | #undef _WIN32_WINNT | ||||
| #define _WIN32_WINNT 0x500 | #define _WIN32_WINNT 0x500 | ||||
| #undef STRICT | #undef STRICT | ||||
| @@ -29535,7 +29547,7 @@ END_JUCE_NAMESPACE | |||||
| #include <windows.h> | #include <windows.h> | ||||
| #include <float.h> | #include <float.h> | ||||
| #pragma warning (disable : 4312 4355) | #pragma warning (disable : 4312 4355) | ||||
| #elif defined (LINUX) | |||||
| #elif defined (LINUX) || defined (__linux__) | |||||
| #include <float.h> | #include <float.h> | ||||
| #include <sys/time.h> | #include <sys/time.h> | ||||
| #include <X11/Xlib.h> | #include <X11/Xlib.h> | ||||
| @@ -29559,10 +29571,6 @@ END_JUCE_NAMESPACE | |||||
| BEGIN_JUCE_NAMESPACE | BEGIN_JUCE_NAMESPACE | ||||
| #if JUCE_MAC | |||||
| #endif | |||||
| #undef PRAGMA_ALIGN_SUPPORTED | #undef PRAGMA_ALIGN_SUPPORTED | ||||
| #define VST_FORCE_DEPRECATED 0 | #define VST_FORCE_DEPRECATED 0 | ||||
| @@ -29590,6 +29598,163 @@ BEGIN_JUCE_NAMESPACE | |||||
| #define Time JUCE_NAMESPACE::Time | #define Time JUCE_NAMESPACE::Time | ||||
| #endif | #endif | ||||
| /********* Start of inlined file: juce_VSTMidiEventList.h *********/ | |||||
| #ifdef __aeffect__ | |||||
| #ifndef __JUCE_VSTMIDIEVENTLIST_JUCEHEADER__ | |||||
| #define __JUCE_VSTMIDIEVENTLIST_JUCEHEADER__ | |||||
| /** Holds a set of VSTMidiEvent objects and makes it easy to add | |||||
| events to the list. | |||||
| This is used by both the VST hosting code and the plugin wrapper. | |||||
| */ | |||||
| class VSTMidiEventList | |||||
| { | |||||
| public: | |||||
| VSTMidiEventList() | |||||
| : events (0), numEventsUsed (0), numEventsAllocated (0) | |||||
| { | |||||
| } | |||||
| ~VSTMidiEventList() | |||||
| { | |||||
| freeEvents(); | |||||
| } | |||||
| void clear() | |||||
| { | |||||
| numEventsUsed = 0; | |||||
| } | |||||
| void addEvent (const void* const midiData, const int numBytes, const int frameOffset) | |||||
| { | |||||
| ensureSize (numEventsUsed + 1); | |||||
| VstMidiEvent* const e = (VstMidiEvent*) (events->events [numEventsUsed]); | |||||
| events->numEvents = ++numEventsUsed; | |||||
| if (numBytes <= 4) | |||||
| { | |||||
| if (e->type == kVstSysExType) | |||||
| { | |||||
| juce_free (((VstMidiSysexEvent*) e)->sysexDump); | |||||
| e->type = kVstMidiType; | |||||
| e->byteSize = sizeof (VstMidiEvent); | |||||
| e->noteLength = 0; | |||||
| e->noteOffset = 0; | |||||
| e->detune = 0; | |||||
| e->noteOffVelocity = 0; | |||||
| } | |||||
| e->deltaFrames = frameOffset; | |||||
| memcpy (e->midiData, midiData, numBytes); | |||||
| } | |||||
| else | |||||
| { | |||||
| VstMidiSysexEvent* const se = (VstMidiSysexEvent*) e; | |||||
| if (se->type == kVstSysExType) | |||||
| se->sysexDump = (char*) juce_realloc (se->sysexDump, numBytes); | |||||
| else | |||||
| se->sysexDump = (char*) juce_malloc (numBytes); | |||||
| memcpy (se->sysexDump, midiData, numBytes); | |||||
| se->type = kVstSysExType; | |||||
| se->byteSize = sizeof (VstMidiSysexEvent); | |||||
| se->deltaFrames = frameOffset; | |||||
| se->flags = 0; | |||||
| se->dumpBytes = numBytes; | |||||
| se->resvd1 = 0; | |||||
| se->resvd2 = 0; | |||||
| } | |||||
| } | |||||
| // Handy method to pull the events out of an event buffer supplied by the host | |||||
| // or plugin. | |||||
| static void addEventsToMidiBuffer (const VstEvents* events, MidiBuffer& dest) | |||||
| { | |||||
| for (int i = 0; i < events->numEvents; ++i) | |||||
| { | |||||
| const VstEvent* const e = events->events[i]; | |||||
| if (e != 0) | |||||
| { | |||||
| if (e->type == kVstMidiType) | |||||
| { | |||||
| dest.addEvent ((const JUCE_NAMESPACE::uint8*) ((const VstMidiEvent*) e)->midiData, | |||||
| 4, e->deltaFrames); | |||||
| } | |||||
| else if (e->type == kVstSysExType) | |||||
| { | |||||
| dest.addEvent ((const JUCE_NAMESPACE::uint8*) ((const VstMidiSysexEvent*) e)->sysexDump, | |||||
| (int) ((const VstMidiSysexEvent*) e)->dumpBytes, | |||||
| e->deltaFrames); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| void ensureSize (int numEventsNeeded) | |||||
| { | |||||
| if (numEventsNeeded > numEventsAllocated) | |||||
| { | |||||
| numEventsNeeded = (numEventsNeeded + 32) & ~31; | |||||
| const int size = 20 + sizeof (VstEvent*) * numEventsNeeded; | |||||
| if (events == 0) | |||||
| events = (VstEvents*) juce_calloc (size); | |||||
| else | |||||
| events = (VstEvents*) juce_realloc (events, size); | |||||
| for (int i = numEventsAllocated; i < numEventsNeeded; ++i) | |||||
| { | |||||
| VstMidiEvent* const e = (VstMidiEvent*) juce_calloc (jmax ((int) sizeof (VstMidiEvent), | |||||
| (int) sizeof (VstMidiSysexEvent))); | |||||
| e->type = kVstMidiType; | |||||
| e->byteSize = sizeof (VstMidiEvent); | |||||
| events->events[i] = (VstEvent*) e; | |||||
| } | |||||
| numEventsAllocated = numEventsNeeded; | |||||
| } | |||||
| } | |||||
| void freeEvents() | |||||
| { | |||||
| if (events != 0) | |||||
| { | |||||
| for (int i = numEventsAllocated; --i >= 0;) | |||||
| { | |||||
| VstMidiEvent* const e = (VstMidiEvent*) (events->events[i]); | |||||
| if (e->type == kVstSysExType) | |||||
| juce_free (((VstMidiSysexEvent*) e)->sysexDump); | |||||
| juce_free (e); | |||||
| } | |||||
| juce_free (events); | |||||
| events = 0; | |||||
| numEventsUsed = 0; | |||||
| numEventsAllocated = 0; | |||||
| } | |||||
| } | |||||
| VstEvents* events; | |||||
| private: | |||||
| int numEventsUsed, numEventsAllocated; | |||||
| }; | |||||
| #endif // __JUCE_VSTMIDIEVENTLIST_JUCEHEADER__ | |||||
| #endif // __JUCE_VSTMIDIEVENTLIST_JUCEHEADER__ | |||||
| /********* End of inlined file: juce_VSTMidiEventList.h *********/ | |||||
| #if ! JUCE_WIN32 | #if ! JUCE_WIN32 | ||||
| #define _fpreset() | #define _fpreset() | ||||
| #define _clearfp() | #define _clearfp() | ||||
| @@ -30224,8 +30389,7 @@ private: | |||||
| AudioSampleBuffer tempBuffer; | AudioSampleBuffer tempBuffer; | ||||
| CriticalSection midiInLock; | CriticalSection midiInLock; | ||||
| MidiBuffer incomingMidi; | MidiBuffer incomingMidi; | ||||
| void* midiEventsToSend; | |||||
| int numAllocatedMidiEvents; | |||||
| VSTMidiEventList midiEventsToSend; | |||||
| VstTimeInfo vstHostTime; | VstTimeInfo vstHostTime; | ||||
| float** channels; | float** channels; | ||||
| @@ -30237,8 +30401,6 @@ private: | |||||
| void setParamsInProgramBlock (fxProgram* const prog) throw(); | void setParamsInProgramBlock (fxProgram* const prog) throw(); | ||||
| void updateStoredProgramNames(); | void updateStoredProgramNames(); | ||||
| void initialise(); | void initialise(); | ||||
| void ensureMidiEventSize (int numEventsNeeded); | |||||
| void freeMidiEvents(); | |||||
| void handleMidiFromPlugin (const VstEvents* const events); | void handleMidiFromPlugin (const VstEvents* const events); | ||||
| void createTempParameterStore (MemoryBlock& dest); | void createTempParameterStore (MemoryBlock& dest); | ||||
| void restoreFromTempParameterStore (const MemoryBlock& mb); | void restoreFromTempParameterStore (const MemoryBlock& mb); | ||||
| @@ -30265,8 +30427,6 @@ VSTPluginInstance::VSTPluginInstance (const ReferenceCountedObjectPtr <ModuleHan | |||||
| wantsMidiMessages (false), | wantsMidiMessages (false), | ||||
| initialised (false), | initialised (false), | ||||
| isPowerOn (false), | isPowerOn (false), | ||||
| numAllocatedMidiEvents (0), | |||||
| midiEventsToSend (0), | |||||
| tempBuffer (1, 1), | tempBuffer (1, 1), | ||||
| channels (0), | channels (0), | ||||
| module (module_) | module (module_) | ||||
| @@ -30355,8 +30515,6 @@ VSTPluginInstance::~VSTPluginInstance() | |||||
| effect = 0; | effect = 0; | ||||
| } | } | ||||
| freeMidiEvents(); | |||||
| juce_free (channels); | juce_free (channels); | ||||
| channels = 0; | channels = 0; | ||||
| } | } | ||||
| @@ -30441,9 +30599,9 @@ void VSTPluginInstance::prepareToPlay (double sampleRate_, | |||||
| || (dispatch (effCanDo, 0, 0, (void*) "receiveVstMidiEvent", 0) > 0); | || (dispatch (effCanDo, 0, 0, (void*) "receiveVstMidiEvent", 0) > 0); | ||||
| if (wantsMidiMessages) | if (wantsMidiMessages) | ||||
| ensureMidiEventSize (256); | |||||
| midiEventsToSend.ensureSize (256); | |||||
| else | else | ||||
| freeMidiEvents(); | |||||
| midiEventsToSend.freeEvents(); | |||||
| incomingMidi.clear(); | incomingMidi.clear(); | ||||
| @@ -30478,7 +30636,7 @@ void VSTPluginInstance::releaseResources() | |||||
| tempBuffer.setSize (1, 1); | tempBuffer.setSize (1, 1); | ||||
| incomingMidi.clear(); | incomingMidi.clear(); | ||||
| freeMidiEvents(); | |||||
| midiEventsToSend.freeEvents(); | |||||
| juce_free (channels); | juce_free (channels); | ||||
| channels = 0; | channels = 0; | ||||
| } | } | ||||
| @@ -30524,43 +30682,22 @@ void VSTPluginInstance::processBlock (AudioSampleBuffer& buffer, | |||||
| if (wantsMidiMessages) | if (wantsMidiMessages) | ||||
| { | { | ||||
| MidiBuffer::Iterator iter (midiMessages); | |||||
| midiEventsToSend.clear(); | |||||
| midiEventsToSend.ensureSize (1); | |||||
| int eventIndex = 0; | |||||
| MidiBuffer::Iterator iter (midiMessages); | |||||
| const uint8* midiData; | const uint8* midiData; | ||||
| int numBytesOfMidiData, samplePosition; | int numBytesOfMidiData, samplePosition; | ||||
| while (iter.getNextEvent (midiData, numBytesOfMidiData, samplePosition)) | while (iter.getNextEvent (midiData, numBytesOfMidiData, samplePosition)) | ||||
| { | { | ||||
| if (numBytesOfMidiData < 4) | |||||
| { | |||||
| ensureMidiEventSize (eventIndex + 1); | |||||
| VstMidiEvent* const e | |||||
| = (VstMidiEvent*) ((VstEvents*) midiEventsToSend)->events [eventIndex++]; | |||||
| // check that some plugin hasn't messed up our objects | |||||
| jassert (e->type == kVstMidiType); | |||||
| jassert (e->byteSize == 24); | |||||
| e->deltaFrames = jlimit (0, numSamples - 1, samplePosition); | |||||
| e->noteLength = 0; | |||||
| e->noteOffset = 0; | |||||
| e->midiData[0] = midiData[0]; | |||||
| e->midiData[1] = midiData[1]; | |||||
| e->midiData[2] = midiData[2]; | |||||
| e->detune = 0; | |||||
| e->noteOffVelocity = 0; | |||||
| } | |||||
| midiEventsToSend.addEvent (midiData, numBytesOfMidiData, | |||||
| jlimit (0, numSamples - 1, samplePosition)); | |||||
| } | } | ||||
| if (midiEventsToSend == 0) | |||||
| ensureMidiEventSize (1); | |||||
| ((VstEvents*) midiEventsToSend)->numEvents = eventIndex; | |||||
| try | try | ||||
| { | { | ||||
| effect->dispatcher (effect, effProcessEvents, 0, 0, midiEventsToSend, 0); | |||||
| effect->dispatcher (effect, effProcessEvents, 0, 0, midiEventsToSend.events, 0); | |||||
| } | } | ||||
| catch (...) | catch (...) | ||||
| {} | {} | ||||
| @@ -30624,61 +30761,12 @@ void VSTPluginInstance::processBlock (AudioSampleBuffer& buffer, | |||||
| } | } | ||||
| } | } | ||||
| void VSTPluginInstance::ensureMidiEventSize (int numEventsNeeded) | |||||
| { | |||||
| if (numEventsNeeded > numAllocatedMidiEvents) | |||||
| { | |||||
| numEventsNeeded = (numEventsNeeded + 32) & ~31; | |||||
| const int size = 20 + sizeof (VstEvent*) * numEventsNeeded; | |||||
| if (midiEventsToSend == 0) | |||||
| midiEventsToSend = juce_calloc (size); | |||||
| else | |||||
| midiEventsToSend = juce_realloc (midiEventsToSend, size); | |||||
| for (int i = numAllocatedMidiEvents; i < numEventsNeeded; ++i) | |||||
| { | |||||
| VstMidiEvent* const e = (VstMidiEvent*) juce_calloc (sizeof (VstMidiEvent)); | |||||
| e->type = kVstMidiType; | |||||
| e->byteSize = 24; | |||||
| ((VstEvents*) midiEventsToSend)->events[i] = (VstEvent*) e; | |||||
| } | |||||
| numAllocatedMidiEvents = numEventsNeeded; | |||||
| } | |||||
| } | |||||
| void VSTPluginInstance::freeMidiEvents() | |||||
| { | |||||
| if (midiEventsToSend != 0) | |||||
| { | |||||
| for (int i = numAllocatedMidiEvents; --i >= 0;) | |||||
| juce_free (((VstEvents*) midiEventsToSend)->events[i]); | |||||
| juce_free (midiEventsToSend); | |||||
| midiEventsToSend = 0; | |||||
| numAllocatedMidiEvents = 0; | |||||
| } | |||||
| } | |||||
| void VSTPluginInstance::handleMidiFromPlugin (const VstEvents* const events) | void VSTPluginInstance::handleMidiFromPlugin (const VstEvents* const events) | ||||
| { | { | ||||
| if (events != 0) | if (events != 0) | ||||
| { | { | ||||
| const ScopedLock sl (midiInLock); | const ScopedLock sl (midiInLock); | ||||
| for (int i = 0; i < events->numEvents; ++i) | |||||
| { | |||||
| const VstEvent* const e = events->events[i]; | |||||
| if (e->type == kVstMidiType) | |||||
| { | |||||
| incomingMidi.addEvent ((const uint8*) ((const VstMidiEvent*) e)->midiData, | |||||
| 3, e->deltaFrames); | |||||
| } | |||||
| } | |||||
| VSTMidiEventList::addEventsToMidiBuffer (events, incomingMidi); | |||||
| } | } | ||||
| } | } | ||||
| @@ -31334,6 +31422,11 @@ private: | |||||
| #endif | #endif | ||||
| #if JUCE_MAC | #if JUCE_MAC | ||||
| #if ! JUCE_SUPPORT_CARBON | |||||
| #error "To build VSTs, you need to enable the JUCE_SUPPORT_CARBON flag in your config!" | |||||
| #endif | |||||
| class InnerWrapperComponent : public CarbonViewWrapperComponent | class InnerWrapperComponent : public CarbonViewWrapperComponent | ||||
| { | { | ||||
| public: | public: | ||||
| @@ -254315,7 +254408,8 @@ bool juce_launchFile (const String& fileName, | |||||
| String cmdString (fileName); | String cmdString (fileName); | ||||
| cmdString << " " << parameters; | cmdString << " " << parameters; | ||||
| if (URL::isProbablyAWebsiteURL (cmdString) || URL::isProbablyAnEmailAddress (cmdString)) | |||||
| if (URL::isProbablyAWebsiteURL (fileName) | |||||
| || URL::isProbablyAnEmailAddress (fileName)) | |||||
| { | { | ||||
| // create a command that tries to launch a bunch of likely browsers | // create a command that tries to launch a bunch of likely browsers | ||||
| const char* const browserNames[] = { "/etc/alternatives/x-www-browser", "firefox", "mozilla", "konqueror", "opera" }; | const char* const browserNames[] = { "/etc/alternatives/x-www-browser", "firefox", "mozilla", "konqueror", "opera" }; | ||||
| @@ -254328,6 +254422,9 @@ bool juce_launchFile (const String& fileName, | |||||
| cmdString = cmdLines.joinIntoString (T(" || ")); | cmdString = cmdLines.joinIntoString (T(" || ")); | ||||
| } | } | ||||
| if (cmdString.startsWithIgnoreCase (T("file:"))) | |||||
| cmdString = cmdString.substring (5); | |||||
| char* const argv[4] = { "/bin/sh", "-c", (char*) cmdString.toUTF8(), 0 }; | char* const argv[4] = { "/bin/sh", "-c", (char*) cmdString.toUTF8(), 0 }; | ||||
| const int cpid = fork(); | const int cpid = fork(); | ||||
| @@ -3088,7 +3088,7 @@ public: | |||||
| static int compareElements (const ElementType first, | static int compareElements (const ElementType first, | ||||
| const ElementType second) throw() | const ElementType second) throw() | ||||
| { | { | ||||
| return (first > second) - (second < first); | |||||
| return (first < second) ? -1 : ((first == second) ? 0 : 1); | |||||
| } | } | ||||
| }; | }; | ||||
| @@ -3114,7 +3114,7 @@ public: | |||||
| static int compareElements (const ElementType first, | static int compareElements (const ElementType first, | ||||
| const ElementType second) throw() | const ElementType second) throw() | ||||
| { | { | ||||
| return (first > second) - (second < first); | |||||
| return (first < second) ? -1 : ((first == second) ? 0 : 1); | |||||
| } | } | ||||
| }; | }; | ||||
| @@ -34902,6 +34902,166 @@ private: | |||||
| #endif // __JUCE_LADSPAPLUGINFORMAT_JUCEHEADER__ | #endif // __JUCE_LADSPAPLUGINFORMAT_JUCEHEADER__ | ||||
| /********* End of inlined file: juce_LADSPAPluginFormat.h *********/ | /********* End of inlined file: juce_LADSPAPluginFormat.h *********/ | ||||
| #endif | |||||
| #ifndef __JUCE_VSTMIDIEVENTLIST_JUCEHEADER__ | |||||
| /********* Start of inlined file: juce_VSTMidiEventList.h *********/ | |||||
| #ifdef __aeffect__ | |||||
| #ifndef __JUCE_VSTMIDIEVENTLIST_JUCEHEADER__ | |||||
| #define __JUCE_VSTMIDIEVENTLIST_JUCEHEADER__ | |||||
| /** Holds a set of VSTMidiEvent objects and makes it easy to add | |||||
| events to the list. | |||||
| This is used by both the VST hosting code and the plugin wrapper. | |||||
| */ | |||||
| class VSTMidiEventList | |||||
| { | |||||
| public: | |||||
| VSTMidiEventList() | |||||
| : events (0), numEventsUsed (0), numEventsAllocated (0) | |||||
| { | |||||
| } | |||||
| ~VSTMidiEventList() | |||||
| { | |||||
| freeEvents(); | |||||
| } | |||||
| void clear() | |||||
| { | |||||
| numEventsUsed = 0; | |||||
| } | |||||
| void addEvent (const void* const midiData, const int numBytes, const int frameOffset) | |||||
| { | |||||
| ensureSize (numEventsUsed + 1); | |||||
| VstMidiEvent* const e = (VstMidiEvent*) (events->events [numEventsUsed]); | |||||
| events->numEvents = ++numEventsUsed; | |||||
| if (numBytes <= 4) | |||||
| { | |||||
| if (e->type == kVstSysExType) | |||||
| { | |||||
| juce_free (((VstMidiSysexEvent*) e)->sysexDump); | |||||
| e->type = kVstMidiType; | |||||
| e->byteSize = sizeof (VstMidiEvent); | |||||
| e->noteLength = 0; | |||||
| e->noteOffset = 0; | |||||
| e->detune = 0; | |||||
| e->noteOffVelocity = 0; | |||||
| } | |||||
| e->deltaFrames = frameOffset; | |||||
| memcpy (e->midiData, midiData, numBytes); | |||||
| } | |||||
| else | |||||
| { | |||||
| VstMidiSysexEvent* const se = (VstMidiSysexEvent*) e; | |||||
| if (se->type == kVstSysExType) | |||||
| se->sysexDump = (char*) juce_realloc (se->sysexDump, numBytes); | |||||
| else | |||||
| se->sysexDump = (char*) juce_malloc (numBytes); | |||||
| memcpy (se->sysexDump, midiData, numBytes); | |||||
| se->type = kVstSysExType; | |||||
| se->byteSize = sizeof (VstMidiSysexEvent); | |||||
| se->deltaFrames = frameOffset; | |||||
| se->flags = 0; | |||||
| se->dumpBytes = numBytes; | |||||
| se->resvd1 = 0; | |||||
| se->resvd2 = 0; | |||||
| } | |||||
| } | |||||
| // Handy method to pull the events out of an event buffer supplied by the host | |||||
| // or plugin. | |||||
| static void addEventsToMidiBuffer (const VstEvents* events, MidiBuffer& dest) | |||||
| { | |||||
| for (int i = 0; i < events->numEvents; ++i) | |||||
| { | |||||
| const VstEvent* const e = events->events[i]; | |||||
| if (e != 0) | |||||
| { | |||||
| if (e->type == kVstMidiType) | |||||
| { | |||||
| dest.addEvent ((const JUCE_NAMESPACE::uint8*) ((const VstMidiEvent*) e)->midiData, | |||||
| 4, e->deltaFrames); | |||||
| } | |||||
| else if (e->type == kVstSysExType) | |||||
| { | |||||
| dest.addEvent ((const JUCE_NAMESPACE::uint8*) ((const VstMidiSysexEvent*) e)->sysexDump, | |||||
| (int) ((const VstMidiSysexEvent*) e)->dumpBytes, | |||||
| e->deltaFrames); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| void ensureSize (int numEventsNeeded) | |||||
| { | |||||
| if (numEventsNeeded > numEventsAllocated) | |||||
| { | |||||
| numEventsNeeded = (numEventsNeeded + 32) & ~31; | |||||
| const int size = 20 + sizeof (VstEvent*) * numEventsNeeded; | |||||
| if (events == 0) | |||||
| events = (VstEvents*) juce_calloc (size); | |||||
| else | |||||
| events = (VstEvents*) juce_realloc (events, size); | |||||
| for (int i = numEventsAllocated; i < numEventsNeeded; ++i) | |||||
| { | |||||
| VstMidiEvent* const e = (VstMidiEvent*) juce_calloc (jmax ((int) sizeof (VstMidiEvent), | |||||
| (int) sizeof (VstMidiSysexEvent))); | |||||
| e->type = kVstMidiType; | |||||
| e->byteSize = sizeof (VstMidiEvent); | |||||
| events->events[i] = (VstEvent*) e; | |||||
| } | |||||
| numEventsAllocated = numEventsNeeded; | |||||
| } | |||||
| } | |||||
| void freeEvents() | |||||
| { | |||||
| if (events != 0) | |||||
| { | |||||
| for (int i = numEventsAllocated; --i >= 0;) | |||||
| { | |||||
| VstMidiEvent* const e = (VstMidiEvent*) (events->events[i]); | |||||
| if (e->type == kVstSysExType) | |||||
| juce_free (((VstMidiSysexEvent*) e)->sysexDump); | |||||
| juce_free (e); | |||||
| } | |||||
| juce_free (events); | |||||
| events = 0; | |||||
| numEventsUsed = 0; | |||||
| numEventsAllocated = 0; | |||||
| } | |||||
| } | |||||
| VstEvents* events; | |||||
| private: | |||||
| int numEventsUsed, numEventsAllocated; | |||||
| }; | |||||
| #endif // __JUCE_VSTMIDIEVENTLIST_JUCEHEADER__ | |||||
| #endif // __JUCE_VSTMIDIEVENTLIST_JUCEHEADER__ | |||||
| /********* End of inlined file: juce_VSTMidiEventList.h *********/ | |||||
| #endif | #endif | ||||
| #ifndef __JUCE_VSTPLUGINFORMAT_JUCEHEADER__ | #ifndef __JUCE_VSTPLUGINFORMAT_JUCEHEADER__ | ||||
| @@ -66,6 +66,12 @@ | |||||
| #pragma warning (disable: 4309 4305) | #pragma warning (disable: 4309 4305) | ||||
| #endif | #endif | ||||
| #if JUCE_MAC && JUCE_SUPPORT_CARBON | |||||
| BEGIN_JUCE_NAMESPACE | |||||
| #include "../build/macosx/platform_specific_code/juce_mac_CarbonViewWrapperComponent.h" | |||||
| END_JUCE_NAMESPACE | |||||
| #endif | |||||
| //============================================================================== | //============================================================================== | ||||
| #include "juce_core/basics/juce_FileLogger.cpp" | #include "juce_core/basics/juce_FileLogger.cpp" | ||||
| #include "juce_core/basics/juce_Logger.cpp" | #include "juce_core/basics/juce_Logger.cpp" | ||||
| @@ -170,6 +170,9 @@ | |||||
| #ifndef __JUCE_LADSPAPLUGINFORMAT_JUCEHEADER__ | #ifndef __JUCE_LADSPAPLUGINFORMAT_JUCEHEADER__ | ||||
| #include "juce_appframework/audio/plugins/formats/juce_LADSPAPluginFormat.h" | #include "juce_appframework/audio/plugins/formats/juce_LADSPAPluginFormat.h" | ||||
| #endif | #endif | ||||
| #ifndef __JUCE_VSTMIDIEVENTLIST_JUCEHEADER__ | |||||
| #include "juce_appframework/audio/plugins/formats/juce_VSTMidiEventList.h" | |||||
| #endif | |||||
| #ifndef __JUCE_VSTPLUGINFORMAT_JUCEHEADER__ | #ifndef __JUCE_VSTPLUGINFORMAT_JUCEHEADER__ | ||||
| #include "juce_appframework/audio/plugins/formats/juce_VSTPluginFormat.h" | #include "juce_appframework/audio/plugins/formats/juce_VSTPluginFormat.h" | ||||
| #endif | #endif | ||||
| @@ -75,11 +75,6 @@ BEGIN_JUCE_NAMESPACE | |||||
| #define log(a) | #define log(a) | ||||
| #endif | #endif | ||||
| #if JUCE_SUPPORT_CARBON | |||||
| #include "../../../../../build/macosx/platform_specific_code/juce_mac_CarbonViewWrapperComponent.h" | |||||
| #endif | |||||
| static int insideCallback = 0; | static int insideCallback = 0; | ||||
| //============================================================================== | //============================================================================== | ||||
| @@ -0,0 +1,192 @@ | |||||
| /* | |||||
| ============================================================================== | |||||
| 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. | |||||
| ============================================================================== | |||||
| */ | |||||
| #ifdef __aeffect__ | |||||
| #ifndef __JUCE_VSTMIDIEVENTLIST_JUCEHEADER__ | |||||
| #define __JUCE_VSTMIDIEVENTLIST_JUCEHEADER__ | |||||
| //============================================================================== | |||||
| /** Holds a set of VSTMidiEvent objects and makes it easy to add | |||||
| events to the list. | |||||
| This is used by both the VST hosting code and the plugin wrapper. | |||||
| */ | |||||
| class VSTMidiEventList | |||||
| { | |||||
| public: | |||||
| //============================================================================== | |||||
| VSTMidiEventList() | |||||
| : events (0), numEventsUsed (0), numEventsAllocated (0) | |||||
| { | |||||
| } | |||||
| ~VSTMidiEventList() | |||||
| { | |||||
| freeEvents(); | |||||
| } | |||||
| //============================================================================== | |||||
| void clear() | |||||
| { | |||||
| numEventsUsed = 0; | |||||
| } | |||||
| void addEvent (const void* const midiData, const int numBytes, const int frameOffset) | |||||
| { | |||||
| ensureSize (numEventsUsed + 1); | |||||
| VstMidiEvent* const e = (VstMidiEvent*) (events->events [numEventsUsed]); | |||||
| events->numEvents = ++numEventsUsed; | |||||
| if (numBytes <= 4) | |||||
| { | |||||
| if (e->type == kVstSysExType) | |||||
| { | |||||
| juce_free (((VstMidiSysexEvent*) e)->sysexDump); | |||||
| e->type = kVstMidiType; | |||||
| e->byteSize = sizeof (VstMidiEvent); | |||||
| e->noteLength = 0; | |||||
| e->noteOffset = 0; | |||||
| e->detune = 0; | |||||
| e->noteOffVelocity = 0; | |||||
| } | |||||
| e->deltaFrames = frameOffset; | |||||
| memcpy (e->midiData, midiData, numBytes); | |||||
| } | |||||
| else | |||||
| { | |||||
| VstMidiSysexEvent* const se = (VstMidiSysexEvent*) e; | |||||
| if (se->type == kVstSysExType) | |||||
| se->sysexDump = (char*) juce_realloc (se->sysexDump, numBytes); | |||||
| else | |||||
| se->sysexDump = (char*) juce_malloc (numBytes); | |||||
| memcpy (se->sysexDump, midiData, numBytes); | |||||
| se->type = kVstSysExType; | |||||
| se->byteSize = sizeof (VstMidiSysexEvent); | |||||
| se->deltaFrames = frameOffset; | |||||
| se->flags = 0; | |||||
| se->dumpBytes = numBytes; | |||||
| se->resvd1 = 0; | |||||
| se->resvd2 = 0; | |||||
| } | |||||
| } | |||||
| //============================================================================== | |||||
| // Handy method to pull the events out of an event buffer supplied by the host | |||||
| // or plugin. | |||||
| static void addEventsToMidiBuffer (const VstEvents* events, MidiBuffer& dest) | |||||
| { | |||||
| for (int i = 0; i < events->numEvents; ++i) | |||||
| { | |||||
| const VstEvent* const e = events->events[i]; | |||||
| if (e != 0) | |||||
| { | |||||
| if (e->type == kVstMidiType) | |||||
| { | |||||
| dest.addEvent ((const JUCE_NAMESPACE::uint8*) ((const VstMidiEvent*) e)->midiData, | |||||
| 4, e->deltaFrames); | |||||
| } | |||||
| else if (e->type == kVstSysExType) | |||||
| { | |||||
| dest.addEvent ((const JUCE_NAMESPACE::uint8*) ((const VstMidiSysexEvent*) e)->sysexDump, | |||||
| (int) ((const VstMidiSysexEvent*) e)->dumpBytes, | |||||
| e->deltaFrames); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| //============================================================================== | |||||
| void ensureSize (int numEventsNeeded) | |||||
| { | |||||
| if (numEventsNeeded > numEventsAllocated) | |||||
| { | |||||
| numEventsNeeded = (numEventsNeeded + 32) & ~31; | |||||
| const int size = 20 + sizeof (VstEvent*) * numEventsNeeded; | |||||
| if (events == 0) | |||||
| events = (VstEvents*) juce_calloc (size); | |||||
| else | |||||
| events = (VstEvents*) juce_realloc (events, size); | |||||
| for (int i = numEventsAllocated; i < numEventsNeeded; ++i) | |||||
| { | |||||
| VstMidiEvent* const e = (VstMidiEvent*) juce_calloc (jmax ((int) sizeof (VstMidiEvent), | |||||
| (int) sizeof (VstMidiSysexEvent))); | |||||
| e->type = kVstMidiType; | |||||
| e->byteSize = sizeof (VstMidiEvent); | |||||
| events->events[i] = (VstEvent*) e; | |||||
| } | |||||
| numEventsAllocated = numEventsNeeded; | |||||
| } | |||||
| } | |||||
| void freeEvents() | |||||
| { | |||||
| if (events != 0) | |||||
| { | |||||
| for (int i = numEventsAllocated; --i >= 0;) | |||||
| { | |||||
| VstMidiEvent* const e = (VstMidiEvent*) (events->events[i]); | |||||
| if (e->type == kVstSysExType) | |||||
| juce_free (((VstMidiSysexEvent*) e)->sysexDump); | |||||
| juce_free (e); | |||||
| } | |||||
| juce_free (events); | |||||
| events = 0; | |||||
| numEventsUsed = 0; | |||||
| numEventsAllocated = 0; | |||||
| } | |||||
| } | |||||
| //============================================================================== | |||||
| VstEvents* events; | |||||
| private: | |||||
| int numEventsUsed, numEventsAllocated; | |||||
| }; | |||||
| #endif // __JUCE_VSTMIDIEVENTLIST_JUCEHEADER__ | |||||
| #endif // __JUCE_VSTMIDIEVENTLIST_JUCEHEADER__ | |||||
| @@ -31,9 +31,9 @@ | |||||
| #include "../../../../../juce_Config.h" | #include "../../../../../juce_Config.h" | ||||
| #if JUCE_PLUGINHOST_VST && (JUCE_MAC || JUCE_WIN32) | |||||
| #if JUCE_PLUGINHOST_VST | |||||
| #ifdef _WIN32 | |||||
| #if (defined (_WIN32) || defined (_WIN64)) | |||||
| #undef _WIN32_WINNT | #undef _WIN32_WINNT | ||||
| #define _WIN32_WINNT 0x500 | #define _WIN32_WINNT 0x500 | ||||
| #undef STRICT | #undef STRICT | ||||
| @@ -41,7 +41,7 @@ | |||||
| #include <windows.h> | #include <windows.h> | ||||
| #include <float.h> | #include <float.h> | ||||
| #pragma warning (disable : 4312 4355) | #pragma warning (disable : 4312 4355) | ||||
| #elif defined (LINUX) | |||||
| #elif defined (LINUX) || defined (__linux__) | |||||
| #include <float.h> | #include <float.h> | ||||
| #include <sys/time.h> | #include <sys/time.h> | ||||
| #include <X11/Xlib.h> | #include <X11/Xlib.h> | ||||
| @@ -72,6 +72,7 @@ BEGIN_JUCE_NAMESPACE | |||||
| #include "../../../../juce_core/threads/juce_Process.h" | #include "../../../../juce_core/threads/juce_Process.h" | ||||
| #include "../../../../juce_core/threads/juce_ScopedLock.h" | #include "../../../../juce_core/threads/juce_ScopedLock.h" | ||||
| #include "../../../../juce_core/basics/juce_Random.h" | #include "../../../../juce_core/basics/juce_Random.h" | ||||
| #include "../../../../juce_core/io/files/juce_DirectoryIterator.h" | |||||
| #include "../../../events/juce_Timer.h" | #include "../../../events/juce_Timer.h" | ||||
| #include "../../../events/juce_AsyncUpdater.h" | #include "../../../events/juce_AsyncUpdater.h" | ||||
| #include "../../../events/juce_MessageManager.h" | #include "../../../events/juce_MessageManager.h" | ||||
| @@ -79,10 +80,6 @@ BEGIN_JUCE_NAMESPACE | |||||
| #include "../../../application/juce_Application.h" | #include "../../../application/juce_Application.h" | ||||
| #include "../../../../juce_core/misc/juce_PlatformUtilities.h" | #include "../../../../juce_core/misc/juce_PlatformUtilities.h" | ||||
| #if JUCE_MAC | |||||
| #include "../../../../../build/macosx/platform_specific_code/juce_mac_CarbonViewWrapperComponent.h" | |||||
| #endif | |||||
| //============================================================================== | //============================================================================== | ||||
| #undef PRAGMA_ALIGN_SUPPORTED | #undef PRAGMA_ALIGN_SUPPORTED | ||||
| @@ -114,6 +111,7 @@ BEGIN_JUCE_NAMESPACE | |||||
| #endif | #endif | ||||
| #include "../juce_PluginDescription.h" | #include "../juce_PluginDescription.h" | ||||
| #include "juce_VSTMidiEventList.h" | |||||
| #if ! JUCE_WIN32 | #if ! JUCE_WIN32 | ||||
| #define _fpreset() | #define _fpreset() | ||||
| @@ -771,8 +769,7 @@ private: | |||||
| AudioSampleBuffer tempBuffer; | AudioSampleBuffer tempBuffer; | ||||
| CriticalSection midiInLock; | CriticalSection midiInLock; | ||||
| MidiBuffer incomingMidi; | MidiBuffer incomingMidi; | ||||
| void* midiEventsToSend; | |||||
| int numAllocatedMidiEvents; | |||||
| VSTMidiEventList midiEventsToSend; | |||||
| VstTimeInfo vstHostTime; | VstTimeInfo vstHostTime; | ||||
| float** channels; | float** channels; | ||||
| @@ -785,8 +782,6 @@ private: | |||||
| void setParamsInProgramBlock (fxProgram* const prog) throw(); | void setParamsInProgramBlock (fxProgram* const prog) throw(); | ||||
| void updateStoredProgramNames(); | void updateStoredProgramNames(); | ||||
| void initialise(); | void initialise(); | ||||
| void ensureMidiEventSize (int numEventsNeeded); | |||||
| void freeMidiEvents(); | |||||
| void handleMidiFromPlugin (const VstEvents* const events); | void handleMidiFromPlugin (const VstEvents* const events); | ||||
| void createTempParameterStore (MemoryBlock& dest); | void createTempParameterStore (MemoryBlock& dest); | ||||
| void restoreFromTempParameterStore (const MemoryBlock& mb); | void restoreFromTempParameterStore (const MemoryBlock& mb); | ||||
| @@ -814,8 +809,6 @@ VSTPluginInstance::VSTPluginInstance (const ReferenceCountedObjectPtr <ModuleHan | |||||
| wantsMidiMessages (false), | wantsMidiMessages (false), | ||||
| initialised (false), | initialised (false), | ||||
| isPowerOn (false), | isPowerOn (false), | ||||
| numAllocatedMidiEvents (0), | |||||
| midiEventsToSend (0), | |||||
| tempBuffer (1, 1), | tempBuffer (1, 1), | ||||
| channels (0), | channels (0), | ||||
| module (module_) | module (module_) | ||||
| @@ -904,8 +897,6 @@ VSTPluginInstance::~VSTPluginInstance() | |||||
| effect = 0; | effect = 0; | ||||
| } | } | ||||
| freeMidiEvents(); | |||||
| juce_free (channels); | juce_free (channels); | ||||
| channels = 0; | channels = 0; | ||||
| } | } | ||||
| @@ -993,9 +984,9 @@ void VSTPluginInstance::prepareToPlay (double sampleRate_, | |||||
| || (dispatch (effCanDo, 0, 0, (void*) "receiveVstMidiEvent", 0) > 0); | || (dispatch (effCanDo, 0, 0, (void*) "receiveVstMidiEvent", 0) > 0); | ||||
| if (wantsMidiMessages) | if (wantsMidiMessages) | ||||
| ensureMidiEventSize (256); | |||||
| midiEventsToSend.ensureSize (256); | |||||
| else | else | ||||
| freeMidiEvents(); | |||||
| midiEventsToSend.freeEvents(); | |||||
| incomingMidi.clear(); | incomingMidi.clear(); | ||||
| @@ -1030,7 +1021,7 @@ void VSTPluginInstance::releaseResources() | |||||
| tempBuffer.setSize (1, 1); | tempBuffer.setSize (1, 1); | ||||
| incomingMidi.clear(); | incomingMidi.clear(); | ||||
| freeMidiEvents(); | |||||
| midiEventsToSend.freeEvents(); | |||||
| juce_free (channels); | juce_free (channels); | ||||
| channels = 0; | channels = 0; | ||||
| } | } | ||||
| @@ -1076,43 +1067,22 @@ void VSTPluginInstance::processBlock (AudioSampleBuffer& buffer, | |||||
| if (wantsMidiMessages) | if (wantsMidiMessages) | ||||
| { | { | ||||
| MidiBuffer::Iterator iter (midiMessages); | |||||
| midiEventsToSend.clear(); | |||||
| midiEventsToSend.ensureSize (1); | |||||
| int eventIndex = 0; | |||||
| MidiBuffer::Iterator iter (midiMessages); | |||||
| const uint8* midiData; | const uint8* midiData; | ||||
| int numBytesOfMidiData, samplePosition; | int numBytesOfMidiData, samplePosition; | ||||
| while (iter.getNextEvent (midiData, numBytesOfMidiData, samplePosition)) | while (iter.getNextEvent (midiData, numBytesOfMidiData, samplePosition)) | ||||
| { | { | ||||
| if (numBytesOfMidiData < 4) | |||||
| { | |||||
| ensureMidiEventSize (eventIndex + 1); | |||||
| VstMidiEvent* const e | |||||
| = (VstMidiEvent*) ((VstEvents*) midiEventsToSend)->events [eventIndex++]; | |||||
| // check that some plugin hasn't messed up our objects | |||||
| jassert (e->type == kVstMidiType); | |||||
| jassert (e->byteSize == 24); | |||||
| e->deltaFrames = jlimit (0, numSamples - 1, samplePosition); | |||||
| e->noteLength = 0; | |||||
| e->noteOffset = 0; | |||||
| e->midiData[0] = midiData[0]; | |||||
| e->midiData[1] = midiData[1]; | |||||
| e->midiData[2] = midiData[2]; | |||||
| e->detune = 0; | |||||
| e->noteOffVelocity = 0; | |||||
| } | |||||
| midiEventsToSend.addEvent (midiData, numBytesOfMidiData, | |||||
| jlimit (0, numSamples - 1, samplePosition)); | |||||
| } | } | ||||
| if (midiEventsToSend == 0) | |||||
| ensureMidiEventSize (1); | |||||
| ((VstEvents*) midiEventsToSend)->numEvents = eventIndex; | |||||
| try | try | ||||
| { | { | ||||
| effect->dispatcher (effect, effProcessEvents, 0, 0, midiEventsToSend, 0); | |||||
| effect->dispatcher (effect, effProcessEvents, 0, 0, midiEventsToSend.events, 0); | |||||
| } | } | ||||
| catch (...) | catch (...) | ||||
| {} | {} | ||||
| @@ -1177,61 +1147,12 @@ void VSTPluginInstance::processBlock (AudioSampleBuffer& buffer, | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| void VSTPluginInstance::ensureMidiEventSize (int numEventsNeeded) | |||||
| { | |||||
| if (numEventsNeeded > numAllocatedMidiEvents) | |||||
| { | |||||
| numEventsNeeded = (numEventsNeeded + 32) & ~31; | |||||
| const int size = 20 + sizeof (VstEvent*) * numEventsNeeded; | |||||
| if (midiEventsToSend == 0) | |||||
| midiEventsToSend = juce_calloc (size); | |||||
| else | |||||
| midiEventsToSend = juce_realloc (midiEventsToSend, size); | |||||
| for (int i = numAllocatedMidiEvents; i < numEventsNeeded; ++i) | |||||
| { | |||||
| VstMidiEvent* const e = (VstMidiEvent*) juce_calloc (sizeof (VstMidiEvent)); | |||||
| e->type = kVstMidiType; | |||||
| e->byteSize = 24; | |||||
| ((VstEvents*) midiEventsToSend)->events[i] = (VstEvent*) e; | |||||
| } | |||||
| numAllocatedMidiEvents = numEventsNeeded; | |||||
| } | |||||
| } | |||||
| void VSTPluginInstance::freeMidiEvents() | |||||
| { | |||||
| if (midiEventsToSend != 0) | |||||
| { | |||||
| for (int i = numAllocatedMidiEvents; --i >= 0;) | |||||
| juce_free (((VstEvents*) midiEventsToSend)->events[i]); | |||||
| juce_free (midiEventsToSend); | |||||
| midiEventsToSend = 0; | |||||
| numAllocatedMidiEvents = 0; | |||||
| } | |||||
| } | |||||
| void VSTPluginInstance::handleMidiFromPlugin (const VstEvents* const events) | void VSTPluginInstance::handleMidiFromPlugin (const VstEvents* const events) | ||||
| { | { | ||||
| if (events != 0) | if (events != 0) | ||||
| { | { | ||||
| const ScopedLock sl (midiInLock); | const ScopedLock sl (midiInLock); | ||||
| for (int i = 0; i < events->numEvents; ++i) | |||||
| { | |||||
| const VstEvent* const e = events->events[i]; | |||||
| if (e->type == kVstMidiType) | |||||
| { | |||||
| incomingMidi.addEvent ((const uint8*) ((const VstMidiEvent*) e)->midiData, | |||||
| 3, e->deltaFrames); | |||||
| } | |||||
| } | |||||
| VSTMidiEventList::addEventsToMidiBuffer (events, incomingMidi); | |||||
| } | } | ||||
| } | } | ||||
| @@ -1899,6 +1820,11 @@ private: | |||||
| #endif | #endif | ||||
| #if JUCE_MAC | #if JUCE_MAC | ||||
| #if ! JUCE_SUPPORT_CARBON | |||||
| #error "To build VSTs, you need to enable the JUCE_SUPPORT_CARBON flag in your config!" | |||||
| #endif | |||||
| class InnerWrapperComponent : public CarbonViewWrapperComponent | class InnerWrapperComponent : public CarbonViewWrapperComponent | ||||
| { | { | ||||
| public: | public: | ||||
| @@ -34,8 +34,8 @@ | |||||
| #include "../juce_AudioPluginFormat.h" | #include "../juce_AudioPluginFormat.h" | ||||
| #if JUCE_PLUGINHOST_VST | |||||
| #if JUCE_PLUGINHOST_VST | |||||
| //============================================================================== | //============================================================================== | ||||
| /** | /** | ||||
| @@ -284,7 +284,7 @@ public: | |||||
| static int compareElements (const ElementType first, | static int compareElements (const ElementType first, | ||||
| const ElementType second) throw() | const ElementType second) throw() | ||||
| { | { | ||||
| return (first > second) - (second < first); | |||||
| return (first < second) ? -1 : ((first == second) ? 0 : 1); | |||||
| } | } | ||||
| }; | }; | ||||
| @@ -312,7 +312,7 @@ public: | |||||
| static int compareElements (const ElementType first, | static int compareElements (const ElementType first, | ||||
| const ElementType second) throw() | const ElementType second) throw() | ||||
| { | { | ||||
| return (first > second) - (second < first); | |||||
| return (first < second) ? -1 : ((first == second) ? 0 : 1); | |||||
| } | } | ||||
| }; | }; | ||||
| @@ -136,17 +136,27 @@ bool URL::isWellFormed() const | |||||
| //============================================================================== | //============================================================================== | ||||
| bool URL::isProbablyAWebsiteURL (const String& possibleURL) | bool URL::isProbablyAWebsiteURL (const String& possibleURL) | ||||
| { | { | ||||
| return (possibleURL.containsChar (T('.')) | |||||
| && (! possibleURL.containsChar (T('@'))) | |||||
| && (! possibleURL.endsWithChar (T('.'))) | |||||
| && (possibleURL.startsWithIgnoreCase (T("www.")) | |||||
| || possibleURL.startsWithIgnoreCase (T("http:")) | |||||
| || possibleURL.startsWithIgnoreCase (T("ftp:")) | |||||
| || possibleURL.endsWithIgnoreCase (T(".com")) | |||||
| || possibleURL.endsWithIgnoreCase (T(".net")) | |||||
| || possibleURL.endsWithIgnoreCase (T(".org")) | |||||
| || possibleURL.endsWithIgnoreCase (T(".co.uk"))) | |||||
| || possibleURL.startsWithIgnoreCase (T("file:"))); | |||||
| if (possibleURL.startsWithIgnoreCase (T("http:")) | |||||
| || possibleURL.startsWithIgnoreCase (T("ftp:"))) | |||||
| return true; | |||||
| if (possibleURL.startsWithIgnoreCase (T("file:")) | |||||
| || possibleURL.containsChar (T('@')) | |||||
| || possibleURL.endsWithChar (T('.')) | |||||
| || (! possibleURL.containsChar (T('.')))) | |||||
| return false; | |||||
| if (possibleURL.startsWithIgnoreCase (T("www.")) | |||||
| && possibleURL.substring (5).containsChar (T('.'))) | |||||
| return true; | |||||
| const char* commonTLDs[] = { "com", "net", "org", "uk", "de", "fr", "jp" }; | |||||
| for (int i = 0; i < numElementsInArray (commonTLDs); ++i) | |||||
| if ((possibleURL + T("/")).containsIgnoreCase (T(".") + String (commonTLDs[i]) + T("/"))) | |||||
| return true; | |||||
| return false; | |||||
| } | } | ||||
| bool URL::isProbablyAnEmailAddress (const String& possibleEmailAddress) | bool URL::isProbablyAnEmailAddress (const String& possibleEmailAddress) | ||||