Browse Source

added support for sysexes to the VST plugin/hosting. Also tweaked URL::isProbablyAWebsiteURL(), and fixed a couple of mac build problems.

tags/2021-05-28
jules 16 years ago
parent
commit
ec87ea494c
14 changed files with 866 additions and 524 deletions
  1. +5
    -1
      build/linux/platform_specific_code/juce_linux_Files.cpp
  2. +2
    -0
      extras/audio plugins/demo/src/juce_AppConfig.h
  3. +11
    -65
      extras/audio plugins/wrapper/VST/juce_VST_Wrapper.cpp
  4. +1
    -0
      extras/audio plugins/wrapper/juce_IncludeCharacteristics.h
  5. +439
    -342
      juce_amalgamated.cpp
  6. +162
    -2
      juce_amalgamated.h
  7. +6
    -0
      src/juce_amalgamated_template.cpp
  8. +3
    -0
      src/juce_app_includes.h
  9. +0
    -5
      src/juce_appframework/audio/plugins/formats/juce_AudioUnitPluginFormat.mm
  10. +192
    -0
      src/juce_appframework/audio/plugins/formats/juce_VSTMidiEventList.h
  11. +21
    -95
      src/juce_appframework/audio/plugins/formats/juce_VSTPluginFormat.cpp
  12. +1
    -1
      src/juce_appframework/audio/plugins/formats/juce_VSTPluginFormat.h
  13. +2
    -2
      src/juce_core/containers/juce_ElementComparator.h
  14. +21
    -11
      src/juce_core/io/network/juce_URL.cpp

+ 5
- 1
build/linux/platform_specific_code/juce_linux_Files.cpp View File

@@ -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();


+ 2
- 0
extras/audio plugins/demo/src/juce_AppConfig.h View File

@@ -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


+ 11
- 65
extras/audio plugins/wrapper/VST/juce_VST_Wrapper.cpp View File

@@ -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];


+ 1
- 0
extras/audio plugins/wrapper/juce_IncludeCharacteristics.h View File

@@ -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


+ 439
- 342
juce_amalgamated.cpp View File

@@ -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();


+ 162
- 2
juce_amalgamated.h View File

@@ -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__



+ 6
- 0
src/juce_amalgamated_template.cpp View File

@@ -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"


+ 3
- 0
src/juce_app_includes.h View File

@@ -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


+ 0
- 5
src/juce_appframework/audio/plugins/formats/juce_AudioUnitPluginFormat.mm View File

@@ -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;
//==============================================================================


+ 192
- 0
src/juce_appframework/audio/plugins/formats/juce_VSTMidiEventList.h View File

@@ -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__

+ 21
- 95
src/juce_appframework/audio/plugins/formats/juce_VSTPluginFormat.cpp View File

@@ -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:


+ 1
- 1
src/juce_appframework/audio/plugins/formats/juce_VSTPluginFormat.h View File

@@ -34,8 +34,8 @@
#include "../juce_AudioPluginFormat.h"
#if JUCE_PLUGINHOST_VST
#if JUCE_PLUGINHOST_VST
//==============================================================================
/**


+ 2
- 2
src/juce_core/containers/juce_ElementComparator.h View File

@@ -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);
}
};


+ 21
- 11
src/juce_core/io/network/juce_URL.cpp View File

@@ -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)


Loading…
Cancel
Save