From ec87ea494c2b383eee1b58252c700fd17e86d971 Mon Sep 17 00:00:00 2001 From: jules Date: Wed, 31 Dec 2008 14:18:22 +0000 Subject: [PATCH] added support for sysexes to the VST plugin/hosting. Also tweaked URL::isProbablyAWebsiteURL(), and fixed a couple of mac build problems. --- .../juce_linux_Files.cpp | 6 +- .../audio plugins/demo/src/juce_AppConfig.h | 2 + .../wrapper/VST/juce_VST_Wrapper.cpp | 76 +- .../wrapper/juce_IncludeCharacteristics.h | 1 + juce_amalgamated.cpp | 781 ++++++++++-------- juce_amalgamated.h | 164 +++- src/juce_amalgamated_template.cpp | 6 + src/juce_app_includes.h | 3 + .../formats/juce_AudioUnitPluginFormat.mm | 5 - .../plugins/formats/juce_VSTMidiEventList.h | 192 +++++ .../plugins/formats/juce_VSTPluginFormat.cpp | 116 +-- .../plugins/formats/juce_VSTPluginFormat.h | 2 +- .../containers/juce_ElementComparator.h | 4 +- src/juce_core/io/network/juce_URL.cpp | 32 +- 14 files changed, 866 insertions(+), 524 deletions(-) create mode 100644 src/juce_appframework/audio/plugins/formats/juce_VSTMidiEventList.h diff --git a/build/linux/platform_specific_code/juce_linux_Files.cpp b/build/linux/platform_specific_code/juce_linux_Files.cpp index 7f72717093..6ffd067947 100644 --- a/build/linux/platform_specific_code/juce_linux_Files.cpp +++ b/build/linux/platform_specific_code/juce_linux_Files.cpp @@ -422,7 +422,8 @@ bool juce_launchFile (const String& fileName, String cmdString (fileName); 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 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(" || ")); } + if (cmdString.startsWithIgnoreCase (T("file:"))) + cmdString = cmdString.substring (5); + char* const argv[4] = { "/bin/sh", "-c", (char*) cmdString.toUTF8(), 0 }; const int cpid = fork(); diff --git a/extras/audio plugins/demo/src/juce_AppConfig.h b/extras/audio plugins/demo/src/juce_AppConfig.h index 8cc549b973..62f1fdc5a7 100644 --- a/extras/audio plugins/demo/src/juce_AppConfig.h +++ b/extras/audio plugins/demo/src/juce_AppConfig.h @@ -38,6 +38,8 @@ */ #define JUCE_QUICKTIME 0 +#define JUCE_SUPPORT_CARBON 1 + //#define JUCE_PLUGINHOST_VST 1 //#define JUCE_PLUGINHOST_AU 1 //#define JUCE_ONLY_BUILD_CORE_LIBRARY 1 diff --git a/extras/audio plugins/wrapper/VST/juce_VST_Wrapper.cpp b/extras/audio plugins/wrapper/VST/juce_VST_Wrapper.cpp index 24866ee6e7..a31861f06a 100644 --- a/extras/audio plugins/wrapper/VST/juce_VST_Wrapper.cpp +++ b/extras/audio plugins/wrapper/VST/juce_VST_Wrapper.cpp @@ -109,6 +109,8 @@ #endif #include "../juce_PluginHeaders.h" +#include "../../../../src/juce_appframework/audio/plugins/formats/juce_VSTMidiEventList.h" + #ifdef _MSC_VER #pragma pack (pop) @@ -336,8 +338,6 @@ public: filter (filter_) { editorComp = 0; - outgoingEvents = 0; - outgoingEventSize = 0; chunkMemoryTime = 0; isProcessing = false; hasShutdown = false; @@ -393,15 +393,6 @@ public: delete filter; filter = 0; - if (outgoingEvents != 0) - { - for (int i = outgoingEventSize; --i >= 0;) - juce_free (outgoingEvents->events[i]); - - juce_free (outgoingEvents); - outgoingEvents = 0; - } - jassert (editorComp == 0); juce_free (channels); @@ -560,20 +551,7 @@ public: VstInt32 processEvents (VstEvents* events) { #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; #else return 0; @@ -682,8 +660,8 @@ public: #if JucePlugin_ProducesMidiOutput const int numEvents = midiEvents.getNumEvents(); - ensureOutgoingEventSize (numEvents); - outgoingEvents->numEvents = 0; + outgoingEvents.ensureSize (numEvents); + outgoingEvents.clear(); const JUCE_NAMESPACE::uint8* midiEventData; int midiEventSize, midiEventPosition; @@ -691,18 +669,12 @@ public: 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 /* This assertion is caused when you've added some events to the midiMessages array in your processBlock() method, which usually means @@ -763,7 +735,7 @@ public: AudioEffectX::resume(); #if JucePlugin_ProducesMidiOutput - ensureOutgoingEventSize (64); + outgoingEvents.ensureSize (64); #endif #if JucePlugin_WantsMidiInput && ! JUCE_USE_VSTSDK_2_4 @@ -779,7 +751,7 @@ public: AudioEffectX::suspend(); filter->releaseResources(); - midiEvents.clear(); + outgoingEvents.freeEvents(); isProcessing = false; juce_free (channels); @@ -1355,8 +1327,7 @@ private: EditorCompWrapper* editorComp; ERect editorSize; MidiBuffer midiEvents; - VstEvents* outgoingEvents; - int outgoingEventSize; + VSTMidiEventList outgoingEvents; bool isProcessing; bool hasShutdown; bool firstProcessCallback; @@ -1381,31 +1352,6 @@ private: 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() { char host[256]; diff --git a/extras/audio plugins/wrapper/juce_IncludeCharacteristics.h b/extras/audio plugins/wrapper/juce_IncludeCharacteristics.h index 8a06cadc7a..78a5181b3a 100644 --- a/extras/audio plugins/wrapper/juce_IncludeCharacteristics.h +++ b/extras/audio plugins/wrapper/juce_IncludeCharacteristics.h @@ -42,6 +42,7 @@ */ #include "JucePluginCharacteristics.h" +#define SUPPORT_CARBON 1 //============================================================================== // The following stuff is just to cause a compile error if you've forgotten to diff --git a/juce_amalgamated.cpp b/juce_amalgamated.cpp index ed5cba3d60..334a23440a 100644 --- a/juce_amalgamated.cpp +++ b/juce_amalgamated.cpp @@ -615,6 +615,243 @@ #pragma warning (disable: 4309 4305) #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 *********/ @@ -7191,17 +7428,27 @@ bool URL::isWellFormed() const 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) @@ -27674,241 +27921,6 @@ BEGIN_JUCE_NAMESPACE #define log(a) #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 const String osTypeToString (OSType type) throw() @@ -29525,9 +29537,9 @@ END_JUCE_NAMESPACE #endif /********* 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 #define _WIN32_WINNT 0x500 #undef STRICT @@ -29535,7 +29547,7 @@ END_JUCE_NAMESPACE #include #include #pragma warning (disable : 4312 4355) -#elif defined (LINUX) +#elif defined (LINUX) || defined (__linux__) #include #include #include @@ -29559,10 +29571,6 @@ END_JUCE_NAMESPACE BEGIN_JUCE_NAMESPACE -#if JUCE_MAC - -#endif - #undef PRAGMA_ALIGN_SUPPORTED #define VST_FORCE_DEPRECATED 0 @@ -29590,6 +29598,163 @@ BEGIN_JUCE_NAMESPACE #define Time JUCE_NAMESPACE::Time #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 #define _fpreset() #define _clearfp() @@ -30224,8 +30389,7 @@ private: AudioSampleBuffer tempBuffer; CriticalSection midiInLock; MidiBuffer incomingMidi; - void* midiEventsToSend; - int numAllocatedMidiEvents; + VSTMidiEventList midiEventsToSend; VstTimeInfo vstHostTime; float** channels; @@ -30237,8 +30401,6 @@ private: void setParamsInProgramBlock (fxProgram* const prog) throw(); void updateStoredProgramNames(); void initialise(); - void ensureMidiEventSize (int numEventsNeeded); - void freeMidiEvents(); void handleMidiFromPlugin (const VstEvents* const events); void createTempParameterStore (MemoryBlock& dest); void restoreFromTempParameterStore (const MemoryBlock& mb); @@ -30265,8 +30427,6 @@ VSTPluginInstance::VSTPluginInstance (const ReferenceCountedObjectPtr 0); if (wantsMidiMessages) - ensureMidiEventSize (256); + midiEventsToSend.ensureSize (256); else - freeMidiEvents(); + midiEventsToSend.freeEvents(); incomingMidi.clear(); @@ -30478,7 +30636,7 @@ void VSTPluginInstance::releaseResources() tempBuffer.setSize (1, 1); incomingMidi.clear(); - freeMidiEvents(); + midiEventsToSend.freeEvents(); juce_free (channels); channels = 0; } @@ -30524,43 +30682,22 @@ void VSTPluginInstance::processBlock (AudioSampleBuffer& buffer, if (wantsMidiMessages) { - MidiBuffer::Iterator iter (midiMessages); + midiEventsToSend.clear(); + midiEventsToSend.ensureSize (1); - int eventIndex = 0; + MidiBuffer::Iterator iter (midiMessages); const uint8* midiData; int 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 { - effect->dispatcher (effect, effProcessEvents, 0, 0, midiEventsToSend, 0); + effect->dispatcher (effect, effProcessEvents, 0, 0, midiEventsToSend.events, 0); } 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) { if (events != 0) { 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 #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 { public: @@ -254315,7 +254408,8 @@ bool juce_launchFile (const String& fileName, String cmdString (fileName); 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 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(" || ")); } + if (cmdString.startsWithIgnoreCase (T("file:"))) + cmdString = cmdString.substring (5); + char* const argv[4] = { "/bin/sh", "-c", (char*) cmdString.toUTF8(), 0 }; const int cpid = fork(); diff --git a/juce_amalgamated.h b/juce_amalgamated.h index c7d4b25091..3724a984b1 100644 --- a/juce_amalgamated.h +++ b/juce_amalgamated.h @@ -3088,7 +3088,7 @@ public: static int compareElements (const ElementType first, 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, 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__ /********* 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 #ifndef __JUCE_VSTPLUGINFORMAT_JUCEHEADER__ diff --git a/src/juce_amalgamated_template.cpp b/src/juce_amalgamated_template.cpp index 2a81298fdb..9bbe47bc52 100644 --- a/src/juce_amalgamated_template.cpp +++ b/src/juce_amalgamated_template.cpp @@ -66,6 +66,12 @@ #pragma warning (disable: 4309 4305) #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_Logger.cpp" diff --git a/src/juce_app_includes.h b/src/juce_app_includes.h index 8053319274..b7031d940d 100644 --- a/src/juce_app_includes.h +++ b/src/juce_app_includes.h @@ -170,6 +170,9 @@ #ifndef __JUCE_LADSPAPLUGINFORMAT_JUCEHEADER__ #include "juce_appframework/audio/plugins/formats/juce_LADSPAPluginFormat.h" #endif +#ifndef __JUCE_VSTMIDIEVENTLIST_JUCEHEADER__ + #include "juce_appframework/audio/plugins/formats/juce_VSTMidiEventList.h" +#endif #ifndef __JUCE_VSTPLUGINFORMAT_JUCEHEADER__ #include "juce_appframework/audio/plugins/formats/juce_VSTPluginFormat.h" #endif diff --git a/src/juce_appframework/audio/plugins/formats/juce_AudioUnitPluginFormat.mm b/src/juce_appframework/audio/plugins/formats/juce_AudioUnitPluginFormat.mm index 6b30ecde0c..17c4398e84 100644 --- a/src/juce_appframework/audio/plugins/formats/juce_AudioUnitPluginFormat.mm +++ b/src/juce_appframework/audio/plugins/formats/juce_AudioUnitPluginFormat.mm @@ -75,11 +75,6 @@ BEGIN_JUCE_NAMESPACE #define log(a) #endif -#if JUCE_SUPPORT_CARBON -#include "../../../../../build/macosx/platform_specific_code/juce_mac_CarbonViewWrapperComponent.h" -#endif - - static int insideCallback = 0; //============================================================================== diff --git a/src/juce_appframework/audio/plugins/formats/juce_VSTMidiEventList.h b/src/juce_appframework/audio/plugins/formats/juce_VSTMidiEventList.h new file mode 100644 index 0000000000..59021a6e73 --- /dev/null +++ b/src/juce_appframework/audio/plugins/formats/juce_VSTMidiEventList.h @@ -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__ diff --git a/src/juce_appframework/audio/plugins/formats/juce_VSTPluginFormat.cpp b/src/juce_appframework/audio/plugins/formats/juce_VSTPluginFormat.cpp index f2f9c0d86f..86f3bef596 100644 --- a/src/juce_appframework/audio/plugins/formats/juce_VSTPluginFormat.cpp +++ b/src/juce_appframework/audio/plugins/formats/juce_VSTPluginFormat.cpp @@ -31,9 +31,9 @@ #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 #define _WIN32_WINNT 0x500 #undef STRICT @@ -41,7 +41,7 @@ #include #include #pragma warning (disable : 4312 4355) -#elif defined (LINUX) +#elif defined (LINUX) || defined (__linux__) #include #include #include @@ -72,6 +72,7 @@ BEGIN_JUCE_NAMESPACE #include "../../../../juce_core/threads/juce_Process.h" #include "../../../../juce_core/threads/juce_ScopedLock.h" #include "../../../../juce_core/basics/juce_Random.h" +#include "../../../../juce_core/io/files/juce_DirectoryIterator.h" #include "../../../events/juce_Timer.h" #include "../../../events/juce_AsyncUpdater.h" #include "../../../events/juce_MessageManager.h" @@ -79,10 +80,6 @@ BEGIN_JUCE_NAMESPACE #include "../../../application/juce_Application.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 @@ -114,6 +111,7 @@ BEGIN_JUCE_NAMESPACE #endif #include "../juce_PluginDescription.h" +#include "juce_VSTMidiEventList.h" #if ! JUCE_WIN32 #define _fpreset() @@ -771,8 +769,7 @@ private: AudioSampleBuffer tempBuffer; CriticalSection midiInLock; MidiBuffer incomingMidi; - void* midiEventsToSend; - int numAllocatedMidiEvents; + VSTMidiEventList midiEventsToSend; VstTimeInfo vstHostTime; float** channels; @@ -785,8 +782,6 @@ private: void setParamsInProgramBlock (fxProgram* const prog) throw(); void updateStoredProgramNames(); void initialise(); - void ensureMidiEventSize (int numEventsNeeded); - void freeMidiEvents(); void handleMidiFromPlugin (const VstEvents* const events); void createTempParameterStore (MemoryBlock& dest); void restoreFromTempParameterStore (const MemoryBlock& mb); @@ -814,8 +809,6 @@ VSTPluginInstance::VSTPluginInstance (const ReferenceCountedObjectPtr 0); if (wantsMidiMessages) - ensureMidiEventSize (256); + midiEventsToSend.ensureSize (256); else - freeMidiEvents(); + midiEventsToSend.freeEvents(); incomingMidi.clear(); @@ -1030,7 +1021,7 @@ void VSTPluginInstance::releaseResources() tempBuffer.setSize (1, 1); incomingMidi.clear(); - freeMidiEvents(); + midiEventsToSend.freeEvents(); juce_free (channels); channels = 0; } @@ -1076,43 +1067,22 @@ void VSTPluginInstance::processBlock (AudioSampleBuffer& buffer, if (wantsMidiMessages) { - MidiBuffer::Iterator iter (midiMessages); + midiEventsToSend.clear(); + midiEventsToSend.ensureSize (1); - int eventIndex = 0; + MidiBuffer::Iterator iter (midiMessages); const uint8* midiData; int 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 { - effect->dispatcher (effect, effProcessEvents, 0, 0, midiEventsToSend, 0); + effect->dispatcher (effect, effProcessEvents, 0, 0, midiEventsToSend.events, 0); } 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) { if (events != 0) { 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 #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 { public: diff --git a/src/juce_appframework/audio/plugins/formats/juce_VSTPluginFormat.h b/src/juce_appframework/audio/plugins/formats/juce_VSTPluginFormat.h index 0a7009c408..7112117be5 100644 --- a/src/juce_appframework/audio/plugins/formats/juce_VSTPluginFormat.h +++ b/src/juce_appframework/audio/plugins/formats/juce_VSTPluginFormat.h @@ -34,8 +34,8 @@ #include "../juce_AudioPluginFormat.h" -#if JUCE_PLUGINHOST_VST +#if JUCE_PLUGINHOST_VST //============================================================================== /** diff --git a/src/juce_core/containers/juce_ElementComparator.h b/src/juce_core/containers/juce_ElementComparator.h index 1bb9f29835..5e4fd33d4d 100644 --- a/src/juce_core/containers/juce_ElementComparator.h +++ b/src/juce_core/containers/juce_ElementComparator.h @@ -284,7 +284,7 @@ public: static int compareElements (const ElementType first, 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, const ElementType second) throw() { - return (first > second) - (second < first); + return (first < second) ? -1 : ((first == second) ? 0 : 1); } }; diff --git a/src/juce_core/io/network/juce_URL.cpp b/src/juce_core/io/network/juce_URL.cpp index 4ae15ab8e8..6b29b7a2b0 100644 --- a/src/juce_core/io/network/juce_URL.cpp +++ b/src/juce_core/io/network/juce_URL.cpp @@ -136,17 +136,27 @@ bool URL::isWellFormed() const //============================================================================== 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)