@@ -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(); | |||
@@ -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 | |||
@@ -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]; | |||
@@ -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 | |||
@@ -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 <windows.h> | |||
#include <float.h> | |||
#pragma warning (disable : 4312 4355) | |||
#elif defined (LINUX) | |||
#elif defined (LINUX) || defined (__linux__) | |||
#include <float.h> | |||
#include <sys/time.h> | |||
#include <X11/Xlib.h> | |||
@@ -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 <ModuleHan | |||
wantsMidiMessages (false), | |||
initialised (false), | |||
isPowerOn (false), | |||
numAllocatedMidiEvents (0), | |||
midiEventsToSend (0), | |||
tempBuffer (1, 1), | |||
channels (0), | |||
module (module_) | |||
@@ -30355,8 +30515,6 @@ VSTPluginInstance::~VSTPluginInstance() | |||
effect = 0; | |||
} | |||
freeMidiEvents(); | |||
juce_free (channels); | |||
channels = 0; | |||
} | |||
@@ -30441,9 +30599,9 @@ void VSTPluginInstance::prepareToPlay (double sampleRate_, | |||
|| (dispatch (effCanDo, 0, 0, (void*) "receiveVstMidiEvent", 0) > 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(); | |||
@@ -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__ | |||
@@ -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" | |||
@@ -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 | |||
@@ -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; | |||
//============================================================================== | |||
@@ -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" | |||
#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 <windows.h> | |||
#include <float.h> | |||
#pragma warning (disable : 4312 4355) | |||
#elif defined (LINUX) | |||
#elif defined (LINUX) || defined (__linux__) | |||
#include <float.h> | |||
#include <sys/time.h> | |||
#include <X11/Xlib.h> | |||
@@ -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 <ModuleHan | |||
wantsMidiMessages (false), | |||
initialised (false), | |||
isPowerOn (false), | |||
numAllocatedMidiEvents (0), | |||
midiEventsToSend (0), | |||
tempBuffer (1, 1), | |||
channels (0), | |||
module (module_) | |||
@@ -904,8 +897,6 @@ VSTPluginInstance::~VSTPluginInstance() | |||
effect = 0; | |||
} | |||
freeMidiEvents(); | |||
juce_free (channels); | |||
channels = 0; | |||
} | |||
@@ -993,9 +984,9 @@ void VSTPluginInstance::prepareToPlay (double sampleRate_, | |||
|| (dispatch (effCanDo, 0, 0, (void*) "receiveVstMidiEvent", 0) > 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: | |||
@@ -34,8 +34,8 @@ | |||
#include "../juce_AudioPluginFormat.h" | |||
#if JUCE_PLUGINHOST_VST | |||
#if JUCE_PLUGINHOST_VST | |||
//============================================================================== | |||
/** | |||
@@ -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); | |||
} | |||
}; | |||
@@ -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) | |||