Browse Source

fix for linux midi output; fix for NSViewComponent; tidying up of demo audio plugin; fixed backslashes in the jucer's generated code; added addOrReplaceSorted method to ReferenceCountedArray; added an option to ThreadPool::removeAllJobs.

tags/2021-05-28
jules 16 years ago
parent
commit
f9f3351839
21 changed files with 2040 additions and 2639 deletions
  1. +205
    -199
      build/linux/JUCE.make
  2. +487
    -486
      build/linux/platform_specific_code/juce_linux_Midi.cpp
  3. +161
    -149
      build/macosx/platform_specific_code/juce_mac_NSViewComponent.mm
  4. +15
    -1
      build/macosx/platform_specific_code/juce_mac_NativeCode.mm
  5. +312
    -300
      extras/audio plugins/How to use this framework.txt
  6. BIN
      extras/audio plugins/demo/build/mac/English.lproj/InfoPlist.strings
  7. +8
    -6
      extras/audio plugins/demo/build/mac/Info.plist
  8. +16
    -4
      extras/audio plugins/demo/build/mac/JuceDemoPlugin.xcodeproj/project.pbxproj
  9. +31
    -19
      extras/juce demo/build/linux/JuceDemo.make
  10. +2
    -1
      extras/the jucer/src/model/components/jucer_JucerComponentHandler.h
  11. +2
    -1
      extras/the jucer/src/model/components/jucer_TabbedComponentHandler.h
  12. +692
    -689
      extras/the jucer/src/model/components/jucer_ViewportHandler.h
  13. +5
    -1
      extras/the jucer/src/model/jucer_BinaryResources.cpp
  14. +42
    -774
      juce_amalgamated.cpp
  15. +27
    -2
      juce_amalgamated.h
  16. +1
    -1
      src/juce_appframework/audio/plugins/formats/juce_AudioUnitPluginFormat.mm
  17. +1
    -1
      src/juce_core/basics/juce_StandardHeader.h
  18. +20
    -0
      src/juce_core/containers/juce_ReferenceCountedArray.h
  19. +2
    -3
      src/juce_core/io/streams/juce_GZIPDecompressorInputStream.cpp
  20. +5
    -1
      src/juce_core/threads/juce_ThreadPool.cpp
  21. +6
    -1
      src/juce_core/threads/juce_ThreadPool.h

+ 205
- 199
build/linux/JUCE.make
File diff suppressed because it is too large
View File


+ 487
- 486
build/linux/platform_specific_code/juce_linux_Midi.cpp View File

@@ -1,486 +1,487 @@
/*
==============================================================================
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.
==============================================================================
*/
#include "../../../juce_Config.h"
#if JUCE_ALSA
#include "../../../src/juce_core/basics/juce_StandardHeader.h"
#include <alsa/asoundlib.h>
BEGIN_JUCE_NAMESPACE
#include "../../../src/juce_appframework/audio/devices/juce_MidiOutput.h"
#include "../../../src/juce_appframework/audio/devices/juce_MidiInput.h"
#include "../../../src/juce_core/threads/juce_Thread.h"
#include "../../../src/juce_core/basics/juce_Time.h"
//==============================================================================
static snd_seq_t* iterateDevices (const bool forInput,
StringArray& deviceNamesFound,
const int deviceIndexToOpen)
{
snd_seq_t* returnedHandle = 0;
snd_seq_t* seqHandle;
if (snd_seq_open (&seqHandle, "default", forInput ? SND_SEQ_OPEN_INPUT
: SND_SEQ_OPEN_OUTPUT, 0) == 0)
{
snd_seq_system_info_t* systemInfo;
snd_seq_client_info_t* clientInfo;
if (snd_seq_system_info_malloc (&systemInfo) == 0)
{
if (snd_seq_system_info (seqHandle, systemInfo) == 0
&& snd_seq_client_info_malloc (&clientInfo) == 0)
{
int numClients = snd_seq_system_info_get_cur_clients (systemInfo);
while (--numClients >= 0 && returnedHandle == 0)
{
if (snd_seq_query_next_client (seqHandle, clientInfo) == 0)
{
snd_seq_port_info_t* portInfo;
if (snd_seq_port_info_malloc (&portInfo) == 0)
{
int numPorts = snd_seq_client_info_get_num_ports (clientInfo);
const int client = snd_seq_client_info_get_client (clientInfo);
snd_seq_port_info_set_client (portInfo, client);
snd_seq_port_info_set_port (portInfo, -1);
while (--numPorts >= 0)
{
if (snd_seq_query_next_port (seqHandle, portInfo) == 0
&& (snd_seq_port_info_get_capability (portInfo)
& (forInput ? SND_SEQ_PORT_CAP_READ
: SND_SEQ_PORT_CAP_WRITE)) != 0)
{
deviceNamesFound.add (snd_seq_client_info_get_name (clientInfo));
if (deviceNamesFound.size() == deviceIndexToOpen + 1)
{
const int sourcePort = snd_seq_port_info_get_port (portInfo);
const int sourceClient = snd_seq_client_info_get_client (clientInfo);
if (sourcePort != -1)
{
snd_seq_set_client_name (seqHandle,
forInput ? "Juce Midi Input"
: "Juce Midi Output");
const int portId
= snd_seq_create_simple_port (seqHandle,
forInput ? "Juce Midi In Port"
: "Juce Midi Out Port",
forInput ? (SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE)
: (SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ),
SND_SEQ_PORT_TYPE_MIDI_GENERIC);
snd_seq_connect_from (seqHandle, portId, sourceClient, sourcePort);
returnedHandle = seqHandle;
}
}
}
}
snd_seq_port_info_free (portInfo);
}
}
}
snd_seq_client_info_free (clientInfo);
}
snd_seq_system_info_free (systemInfo);
}
if (returnedHandle == 0)
snd_seq_close (seqHandle);
}
deviceNamesFound.appendNumbersToDuplicates (true, true);
return returnedHandle;
}
static snd_seq_t* createDevice (const bool forInput,
const String& deviceNameToOpen)
{
snd_seq_t* seqHandle = 0;
if (snd_seq_open (&seqHandle, "default", forInput ? SND_SEQ_OPEN_INPUT
: SND_SEQ_OPEN_OUTPUT, 0) == 0)
{
snd_seq_set_client_name (seqHandle,
(const char*) (forInput ? (deviceNameToOpen + T(" Input"))
: (deviceNameToOpen + T(" Output"))));
const int portId
= snd_seq_create_simple_port (seqHandle,
forInput ? "in"
: "out",
forInput ? (SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE)
: (SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ),
forInput ? SND_SEQ_PORT_TYPE_APPLICATION
: SND_SEQ_PORT_TYPE_MIDI_GENERIC);
if (portId < 0)
{
snd_seq_close (seqHandle);
seqHandle = 0;
}
}
return seqHandle;
}
//==============================================================================
class MidiOutputDevice
{
public:
MidiOutputDevice (MidiOutput* const midiOutput_,
snd_seq_t* const seqHandle_)
:
midiOutput (midiOutput_),
seqHandle (seqHandle_),
maxEventSize (16 * 1024)
{
jassert (seqHandle != 0 && midiOutput != 0);
snd_midi_event_new (maxEventSize, &midiParser);
}
~MidiOutputDevice()
{
snd_midi_event_free (midiParser);
snd_seq_close (seqHandle);
}
void sendMessageNow (const MidiMessage& message)
{
if (message.getRawDataSize() > maxEventSize)
{
maxEventSize = message.getRawDataSize();
snd_midi_event_free (midiParser);
snd_midi_event_new (maxEventSize, &midiParser);
}
snd_seq_event_t event;
snd_seq_ev_clear (&event);
snd_midi_event_encode (midiParser,
message.getRawData(),
message.getRawDataSize(),
&event);
snd_midi_event_reset_encode (midiParser);
snd_seq_ev_set_source (&event, 0);
snd_seq_ev_set_subs (&event);
snd_seq_ev_set_direct (&event);
snd_seq_event_output_direct (seqHandle, &event);
}
juce_UseDebuggingNewOperator
private:
MidiOutput* const midiOutput;
snd_seq_t* const seqHandle;
snd_midi_event_t* midiParser;
int maxEventSize;
};
const StringArray MidiOutput::getDevices()
{
StringArray devices;
iterateDevices (false, devices, -1);
return devices;
}
int MidiOutput::getDefaultDeviceIndex()
{
return 0;
}
MidiOutput* MidiOutput::openDevice (int deviceIndex)
{
MidiOutput* newDevice = 0;
StringArray devices;
snd_seq_t* const handle = iterateDevices (false, devices, deviceIndex);
if (handle != 0)
{
newDevice = new MidiOutput();
newDevice->internal = new MidiOutputDevice (newDevice, handle);
}
return newDevice;
}
MidiOutput* MidiOutput::createNewDevice (const String& deviceName)
{
MidiOutput* newDevice = 0;
snd_seq_t* const handle = createDevice (false, deviceName);
if (handle != 0)
{
newDevice = new MidiOutput();
newDevice->internal = new MidiOutputDevice (newDevice, handle);
}
return newDevice;
}
MidiOutput::~MidiOutput()
{
MidiOutputDevice* const device = (MidiOutputDevice*) internal;
delete device;
}
void MidiOutput::reset()
{
}
bool MidiOutput::getVolume (float& leftVol, float& rightVol)
{
return false;
}
void MidiOutput::setVolume (float leftVol, float rightVol)
{
}
void MidiOutput::sendMessageNow (const MidiMessage& message)
{
((MidiOutputDevice*) internal)->sendMessageNow (message);
}
//==============================================================================
class MidiInputThread : public Thread
{
public:
MidiInputThread (MidiInput* const midiInput_,
snd_seq_t* const seqHandle_,
MidiInputCallback* const callback_)
: Thread (T("Juce MIDI Input")),
midiInput (midiInput_),
seqHandle (seqHandle_),
callback (callback_)
{
jassert (seqHandle != 0 && callback != 0 && midiInput != 0);
}
~MidiInputThread()
{
snd_seq_close (seqHandle);
}
void run()
{
const int maxEventSize = 16 * 1024;
snd_midi_event_t* midiParser;
if (snd_midi_event_new (maxEventSize, &midiParser) >= 0)
{
uint8* const buffer = (uint8*) juce_malloc (maxEventSize);
const int numPfds = snd_seq_poll_descriptors_count (seqHandle, POLLIN);
struct pollfd* const pfd = (struct pollfd*) alloca (numPfds * sizeof (struct pollfd));
snd_seq_poll_descriptors (seqHandle, pfd, numPfds, POLLIN);
while (! threadShouldExit())
{
if (poll (pfd, numPfds, 500) > 0)
{
snd_seq_event_t* inputEvent = 0;
snd_seq_nonblock (seqHandle, 1);
do
{
if (snd_seq_event_input (seqHandle, &inputEvent) >= 0)
{
// xxx what about SYSEXes that are too big for the buffer?
const int numBytes = snd_midi_event_decode (midiParser, buffer, maxEventSize, inputEvent);
snd_midi_event_reset_decode (midiParser);
if (numBytes > 0)
{
const MidiMessage message ((const uint8*) buffer,
numBytes,
Time::getMillisecondCounter() * 0.001);
callback->handleIncomingMidiMessage (midiInput, message);
}
snd_seq_free_event (inputEvent);
}
}
while (snd_seq_event_input_pending (seqHandle, 0) > 0);
snd_seq_free_event (inputEvent);
}
}
snd_midi_event_free (midiParser);
juce_free (buffer);
}
};
juce_UseDebuggingNewOperator
private:
MidiInput* const midiInput;
snd_seq_t* const seqHandle;
MidiInputCallback* const callback;
};
//==============================================================================
MidiInput::MidiInput (const String& name_)
: name (name_),
internal (0)
{
}
MidiInput::~MidiInput()
{
stop();
MidiInputThread* const thread = (MidiInputThread*) internal;
delete thread;
}
void MidiInput::start()
{
((MidiInputThread*) internal)->startThread();
}
void MidiInput::stop()
{
((MidiInputThread*) internal)->stopThread (3000);
}
int MidiInput::getDefaultDeviceIndex()
{
return 0;
}
const StringArray MidiInput::getDevices()
{
StringArray devices;
iterateDevices (true, devices, -1);
return devices;
}
MidiInput* MidiInput::openDevice (int deviceIndex, MidiInputCallback* callback)
{
MidiInput* newDevice = 0;
StringArray devices;
snd_seq_t* const handle = iterateDevices (true, devices, deviceIndex);
if (handle != 0)
{
newDevice = new MidiInput (devices [deviceIndex]);
newDevice->internal = new MidiInputThread (newDevice, handle, callback);
}
return newDevice;
}
MidiInput* MidiInput::createNewDevice (const String& deviceName, MidiInputCallback* callback)
{
MidiInput* newDevice = 0;
snd_seq_t* const handle = createDevice (true, deviceName);
if (handle != 0)
{
newDevice = new MidiInput (deviceName);
newDevice->internal = new MidiInputThread (newDevice, handle, callback);
}
return newDevice;
}
END_JUCE_NAMESPACE
//==============================================================================
#else
//==============================================================================
// (These are just stub functions if ALSA is unavailable...)
#include "../../../src/juce_core/basics/juce_StandardHeader.h"
BEGIN_JUCE_NAMESPACE
#include "../../../src/juce_appframework/audio/devices/juce_MidiOutput.h"
#include "../../../src/juce_appframework/audio/devices/juce_MidiInput.h"
//==============================================================================
const StringArray MidiOutput::getDevices() { return StringArray(); }
int MidiOutput::getDefaultDeviceIndex() { return 0; }
MidiOutput* MidiOutput::openDevice (int) { return 0; }
MidiOutput* MidiOutput::createNewDevice (const String&) { return 0; }
MidiOutput::~MidiOutput() {}
void MidiOutput::reset() {}
bool MidiOutput::getVolume (float&, float&) { return false; }
void MidiOutput::setVolume (float, float) {}
void MidiOutput::sendMessageNow (const MidiMessage&) {}
MidiInput::MidiInput (const String& name_)
: name (name_),
internal (0)
{}
MidiInput::~MidiInput() {}
void MidiInput::start() {}
void MidiInput::stop() {}
int MidiInput::getDefaultDeviceIndex() { return 0; }
const StringArray MidiInput::getDevices() { return StringArray(); }
MidiInput* MidiInput::openDevice (int, MidiInputCallback*) { return 0; }
MidiInput* MidiInput::createNewDevice (const String&, MidiInputCallback*) { return 0; }
END_JUCE_NAMESPACE
#endif
/*
==============================================================================

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.

==============================================================================
*/

#include "../../../juce_Config.h"

#if JUCE_ALSA

#include "../../../src/juce_core/basics/juce_StandardHeader.h"
#include <alsa/asoundlib.h>

BEGIN_JUCE_NAMESPACE

#include "../../../src/juce_appframework/audio/devices/juce_MidiOutput.h"
#include "../../../src/juce_appframework/audio/devices/juce_MidiInput.h"
#include "../../../src/juce_core/threads/juce_Thread.h"
#include "../../../src/juce_core/basics/juce_Time.h"


//==============================================================================
static snd_seq_t* iterateDevices (const bool forInput,
StringArray& deviceNamesFound,
const int deviceIndexToOpen)
{
snd_seq_t* returnedHandle = 0;
snd_seq_t* seqHandle;

if (snd_seq_open (&seqHandle, "default", forInput ? SND_SEQ_OPEN_INPUT
: SND_SEQ_OPEN_OUTPUT, 0) == 0)
{
snd_seq_system_info_t* systemInfo;
snd_seq_client_info_t* clientInfo;

if (snd_seq_system_info_malloc (&systemInfo) == 0)
{
if (snd_seq_system_info (seqHandle, systemInfo) == 0
&& snd_seq_client_info_malloc (&clientInfo) == 0)
{
int numClients = snd_seq_system_info_get_cur_clients (systemInfo);

while (--numClients >= 0 && returnedHandle == 0)
{
if (snd_seq_query_next_client (seqHandle, clientInfo) == 0)
{
snd_seq_port_info_t* portInfo;
if (snd_seq_port_info_malloc (&portInfo) == 0)
{
int numPorts = snd_seq_client_info_get_num_ports (clientInfo);
const int client = snd_seq_client_info_get_client (clientInfo);

snd_seq_port_info_set_client (portInfo, client);
snd_seq_port_info_set_port (portInfo, -1);

while (--numPorts >= 0)
{
if (snd_seq_query_next_port (seqHandle, portInfo) == 0
&& (snd_seq_port_info_get_capability (portInfo)
& (forInput ? SND_SEQ_PORT_CAP_READ
: SND_SEQ_PORT_CAP_WRITE)) != 0)
{
deviceNamesFound.add (snd_seq_client_info_get_name (clientInfo));

if (deviceNamesFound.size() == deviceIndexToOpen + 1)
{
const int sourcePort = snd_seq_port_info_get_port (portInfo);
const int sourceClient = snd_seq_client_info_get_client (clientInfo);

if (sourcePort != -1)
{
snd_seq_set_client_name (seqHandle,
forInput ? "Juce Midi Input"
: "Juce Midi Output");

const int portId
= snd_seq_create_simple_port (seqHandle,
forInput ? "Juce Midi In Port"
: "Juce Midi Out Port",
forInput ? (SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE)
: (SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ),
SND_SEQ_PORT_TYPE_MIDI_GENERIC);

snd_seq_connect_from (seqHandle, portId, sourceClient, sourcePort);

returnedHandle = seqHandle;
}
}
}
}

snd_seq_port_info_free (portInfo);
}
}
}

snd_seq_client_info_free (clientInfo);
}

snd_seq_system_info_free (systemInfo);
}

if (returnedHandle == 0)
snd_seq_close (seqHandle);
}

deviceNamesFound.appendNumbersToDuplicates (true, true);

return returnedHandle;
}

static snd_seq_t* createDevice (const bool forInput,
const String& deviceNameToOpen)
{
snd_seq_t* seqHandle = 0;

if (snd_seq_open (&seqHandle, "default", forInput ? SND_SEQ_OPEN_INPUT
: SND_SEQ_OPEN_OUTPUT, 0) == 0)
{
snd_seq_set_client_name (seqHandle,
(const char*) (forInput ? (deviceNameToOpen + T(" Input"))
: (deviceNameToOpen + T(" Output"))));

const int portId
= snd_seq_create_simple_port (seqHandle,
forInput ? "in"
: "out",
forInput ? (SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE)
: (SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ),
forInput ? SND_SEQ_PORT_TYPE_APPLICATION
: SND_SEQ_PORT_TYPE_MIDI_GENERIC);

if (portId < 0)
{
snd_seq_close (seqHandle);
seqHandle = 0;
}
}

return seqHandle;
}

//==============================================================================
class MidiOutputDevice
{
public:
MidiOutputDevice (MidiOutput* const midiOutput_,
snd_seq_t* const seqHandle_)
:
midiOutput (midiOutput_),
seqHandle (seqHandle_),
maxEventSize (16 * 1024)
{
jassert (seqHandle != 0 && midiOutput != 0);
snd_midi_event_new (maxEventSize, &midiParser);
}

~MidiOutputDevice()
{
snd_midi_event_free (midiParser);
snd_seq_close (seqHandle);
}

void sendMessageNow (const MidiMessage& message)
{
if (message.getRawDataSize() > maxEventSize)
{
maxEventSize = message.getRawDataSize();
snd_midi_event_free (midiParser);
snd_midi_event_new (maxEventSize, &midiParser);
}

snd_seq_event_t event;
snd_seq_ev_clear (&event);

snd_midi_event_encode (midiParser,
message.getRawData(),
message.getRawDataSize(),
&event);

snd_midi_event_reset_encode (midiParser);

snd_seq_ev_set_source (&event, 0);
snd_seq_ev_set_subs (&event);
snd_seq_ev_set_direct (&event);

snd_seq_event_output (seqHandle, &event);
snd_seq_drain_output (seqHandle);
}

juce_UseDebuggingNewOperator

private:
MidiOutput* const midiOutput;
snd_seq_t* const seqHandle;
snd_midi_event_t* midiParser;
int maxEventSize;
};

const StringArray MidiOutput::getDevices()
{
StringArray devices;
iterateDevices (false, devices, -1);
return devices;
}

int MidiOutput::getDefaultDeviceIndex()
{
return 0;
}

MidiOutput* MidiOutput::openDevice (int deviceIndex)
{
MidiOutput* newDevice = 0;

StringArray devices;
snd_seq_t* const handle = iterateDevices (false, devices, deviceIndex);

if (handle != 0)
{
newDevice = new MidiOutput();
newDevice->internal = new MidiOutputDevice (newDevice, handle);
}

return newDevice;
}

MidiOutput* MidiOutput::createNewDevice (const String& deviceName)
{
MidiOutput* newDevice = 0;

snd_seq_t* const handle = createDevice (false, deviceName);

if (handle != 0)
{
newDevice = new MidiOutput();
newDevice->internal = new MidiOutputDevice (newDevice, handle);
}

return newDevice;
}

MidiOutput::~MidiOutput()
{
MidiOutputDevice* const device = (MidiOutputDevice*) internal;
delete device;
}

void MidiOutput::reset()
{
}

bool MidiOutput::getVolume (float& leftVol, float& rightVol)
{
return false;
}

void MidiOutput::setVolume (float leftVol, float rightVol)
{
}

void MidiOutput::sendMessageNow (const MidiMessage& message)
{
((MidiOutputDevice*) internal)->sendMessageNow (message);
}


//==============================================================================
class MidiInputThread : public Thread
{
public:
MidiInputThread (MidiInput* const midiInput_,
snd_seq_t* const seqHandle_,
MidiInputCallback* const callback_)
: Thread (T("Juce MIDI Input")),
midiInput (midiInput_),
seqHandle (seqHandle_),
callback (callback_)
{
jassert (seqHandle != 0 && callback != 0 && midiInput != 0);
}

~MidiInputThread()
{
snd_seq_close (seqHandle);
}

void run()
{
const int maxEventSize = 16 * 1024;
snd_midi_event_t* midiParser;

if (snd_midi_event_new (maxEventSize, &midiParser) >= 0)
{
uint8* const buffer = (uint8*) juce_malloc (maxEventSize);

const int numPfds = snd_seq_poll_descriptors_count (seqHandle, POLLIN);
struct pollfd* const pfd = (struct pollfd*) alloca (numPfds * sizeof (struct pollfd));

snd_seq_poll_descriptors (seqHandle, pfd, numPfds, POLLIN);

while (! threadShouldExit())
{
if (poll (pfd, numPfds, 500) > 0)
{
snd_seq_event_t* inputEvent = 0;

snd_seq_nonblock (seqHandle, 1);

do
{
if (snd_seq_event_input (seqHandle, &inputEvent) >= 0)
{
// xxx what about SYSEXes that are too big for the buffer?
const int numBytes = snd_midi_event_decode (midiParser, buffer, maxEventSize, inputEvent);

snd_midi_event_reset_decode (midiParser);

if (numBytes > 0)
{
const MidiMessage message ((const uint8*) buffer,
numBytes,
Time::getMillisecondCounter() * 0.001);


callback->handleIncomingMidiMessage (midiInput, message);
}

snd_seq_free_event (inputEvent);
}
}
while (snd_seq_event_input_pending (seqHandle, 0) > 0);

snd_seq_free_event (inputEvent);
}
}

snd_midi_event_free (midiParser);
juce_free (buffer);
}
};

juce_UseDebuggingNewOperator

private:
MidiInput* const midiInput;
snd_seq_t* const seqHandle;
MidiInputCallback* const callback;
};

//==============================================================================
MidiInput::MidiInput (const String& name_)
: name (name_),
internal (0)
{
}

MidiInput::~MidiInput()
{
stop();
MidiInputThread* const thread = (MidiInputThread*) internal;
delete thread;
}

void MidiInput::start()
{
((MidiInputThread*) internal)->startThread();
}

void MidiInput::stop()
{
((MidiInputThread*) internal)->stopThread (3000);
}

int MidiInput::getDefaultDeviceIndex()
{
return 0;
}

const StringArray MidiInput::getDevices()
{
StringArray devices;
iterateDevices (true, devices, -1);
return devices;
}

MidiInput* MidiInput::openDevice (int deviceIndex, MidiInputCallback* callback)
{
MidiInput* newDevice = 0;

StringArray devices;
snd_seq_t* const handle = iterateDevices (true, devices, deviceIndex);

if (handle != 0)
{
newDevice = new MidiInput (devices [deviceIndex]);
newDevice->internal = new MidiInputThread (newDevice, handle, callback);
}

return newDevice;
}

MidiInput* MidiInput::createNewDevice (const String& deviceName, MidiInputCallback* callback)
{
MidiInput* newDevice = 0;

snd_seq_t* const handle = createDevice (true, deviceName);

if (handle != 0)
{
newDevice = new MidiInput (deviceName);
newDevice->internal = new MidiInputThread (newDevice, handle, callback);
}

return newDevice;
}



END_JUCE_NAMESPACE

//==============================================================================

#else

//==============================================================================
// (These are just stub functions if ALSA is unavailable...)

#include "../../../src/juce_core/basics/juce_StandardHeader.h"

BEGIN_JUCE_NAMESPACE

#include "../../../src/juce_appframework/audio/devices/juce_MidiOutput.h"
#include "../../../src/juce_appframework/audio/devices/juce_MidiInput.h"

//==============================================================================
const StringArray MidiOutput::getDevices() { return StringArray(); }
int MidiOutput::getDefaultDeviceIndex() { return 0; }
MidiOutput* MidiOutput::openDevice (int) { return 0; }
MidiOutput* MidiOutput::createNewDevice (const String&) { return 0; }
MidiOutput::~MidiOutput() {}
void MidiOutput::reset() {}
bool MidiOutput::getVolume (float&, float&) { return false; }
void MidiOutput::setVolume (float, float) {}
void MidiOutput::sendMessageNow (const MidiMessage&) {}

MidiInput::MidiInput (const String& name_)
: name (name_),
internal (0)
{}

MidiInput::~MidiInput() {}
void MidiInput::start() {}
void MidiInput::stop() {}
int MidiInput::getDefaultDeviceIndex() { return 0; }
const StringArray MidiInput::getDevices() { return StringArray(); }
MidiInput* MidiInput::openDevice (int, MidiInputCallback*) { return 0; }
MidiInput* MidiInput::createNewDevice (const String&, MidiInputCallback*) { return 0; }

END_JUCE_NAMESPACE

#endif

+ 161
- 149
build/macosx/platform_specific_code/juce_mac_NSViewComponent.mm View File

@@ -1,149 +1,161 @@
/*
==============================================================================
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.
==============================================================================
*/
// (This file gets included by juce_mac_NativeCode.mm, rather than being
// compiled on its own).
#ifdef JUCE_INCLUDED_FILE
//==============================================================================
class NSViewComponentInternal : public ComponentMovementWatcher
{
Component* const owner;
NSViewComponentPeer* currentPeer;
bool wasShowing;
public:
NSView* view;
//==============================================================================
NSViewComponentInternal (NSView* view_, Component* const owner_)
: ComponentMovementWatcher (owner_),
owner (owner_),
currentPeer (0),
wasShowing (false),
view (view_)
{
[view retain];
if (owner_->isShowing())
componentPeerChanged();
}
~NSViewComponentInternal()
{
[view removeFromSuperview];
[view release];
}
//==============================================================================
void componentMovedOrResized (bool /*wasMoved*/, bool /*wasResized*/)
{
Component* const topComp = owner->getTopLevelComponent();
if (topComp->getPeer() != 0)
{
int x = 0, y = 0;
owner->relativePositionToOtherComponent (topComp, x, y);
NSRect r;
r.origin.x = (float) x;
r.origin.y = (float) y;
r.size.width = (float) owner->getWidth();
r.size.height = (float) owner->getHeight();
r.origin.y = [[view superview] frame].size.height - (r.origin.y + r.size.height);
[view setFrame: r];
}
}
void componentPeerChanged()
{
NSViewComponentPeer* const peer = dynamic_cast <NSViewComponentPeer*> (owner->getPeer());
if (currentPeer != peer)
{
[view removeFromSuperview];
currentPeer = peer;
if (peer != 0)
{
[peer->view addSubview: view];
componentMovedOrResized (false, false);
}
}
[view setHidden: ! owner->isShowing()];
}
void componentVisibilityChanged (Component&)
{
componentPeerChanged();
}
juce_UseDebuggingNewOperator
private:
NSViewComponentInternal (const NSViewComponentInternal&);
const NSViewComponentInternal& operator= (const NSViewComponentInternal&);
};
//==============================================================================
NSViewComponent::NSViewComponent()
: info (0)
{
}
NSViewComponent::~NSViewComponent()
{
delete info;
}
void NSViewComponent::setView (void* view)
{
if (view != getView())
{
deleteAndZero (info);
if (view != 0)
info = new NSViewComponentInternal ((NSView*) view, this);
}
}
void* NSViewComponent::getView() const
{
return info == 0 ? 0 : info->view;
}
void NSViewComponent::paint (Graphics& g)
{
}
#endif
/*
==============================================================================

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.

==============================================================================
*/

// (This file gets included by juce_mac_NativeCode.mm, rather than being
// compiled on its own).
#ifdef JUCE_INCLUDED_FILE

//==============================================================================
class NSViewComponentInternal : public ComponentMovementWatcher
{
Component* const owner;
NSViewComponentPeer* currentPeer;
bool wasShowing;

public:
NSView* const view;

//==============================================================================
NSViewComponentInternal (NSView* const view_, Component* const owner_)
: ComponentMovementWatcher (owner_),
owner (owner_),
currentPeer (0),
wasShowing (false),
view (view_)
{
[view_ retain];

if (owner_->isShowing())
componentPeerChanged();
}

~NSViewComponentInternal()
{
[view removeFromSuperview];
[view release];
}

//==============================================================================
void componentMovedOrResized (Component& comp, bool wasMoved, bool wasResized)
{
ComponentMovementWatcher::componentMovedOrResized (comp, wasMoved, wasResized);
// The ComponentMovementWatcher version of this method avoids calling
// us when the top-level comp is resized, but for an NSView we need to know this
// because with inverted co-ords, we need to update the position even if the
// top-left pos hasn't changed
if (comp.isOnDesktop() && wasResized)
componentMovedOrResized (wasMoved, wasResized);
}

void componentMovedOrResized (bool /*wasMoved*/, bool /*wasResized*/)
{
Component* const topComp = owner->getTopLevelComponent();

if (topComp->getPeer() != 0)
{
int x = 0, y = 0;
owner->relativePositionToOtherComponent (topComp, x, y);

NSRect r;
r.origin.x = (float) x;
r.origin.y = (float) y;
r.size.width = (float) owner->getWidth();
r.size.height = (float) owner->getHeight();
r.origin.y = [[view superview] frame].size.height - (r.origin.y + r.size.height);

[view setFrame: r];
}
}

void componentPeerChanged()
{
NSViewComponentPeer* const peer = dynamic_cast <NSViewComponentPeer*> (owner->getPeer());

if (currentPeer != peer)
{
[view removeFromSuperview];
currentPeer = peer;

if (peer != 0)
{
[peer->view addSubview: view];
componentMovedOrResized (false, false);
}
}

[view setHidden: ! owner->isShowing()];
}

void componentVisibilityChanged (Component&)
{
componentPeerChanged();
}

juce_UseDebuggingNewOperator

private:
NSViewComponentInternal (const NSViewComponentInternal&);
const NSViewComponentInternal& operator= (const NSViewComponentInternal&);
};

//==============================================================================
NSViewComponent::NSViewComponent()
: info (0)
{
}

NSViewComponent::~NSViewComponent()
{
delete info;
}

void NSViewComponent::setView (void* view)
{
if (view != getView())
{
deleteAndZero (info);

if (view != 0)
info = new NSViewComponentInternal ((NSView*) view, this);
}
}

void* NSViewComponent::getView() const
{
return info == 0 ? 0 : info->view;
}

void NSViewComponent::paint (Graphics& g)
{
}

#endif

+ 15
- 1
build/macosx/platform_specific_code/juce_mac_NativeCode.mm View File

@@ -80,9 +80,23 @@ BEGIN_JUCE_NAMESPACE
#undef Point
//==============================================================================
/** This suffix is used for naming all Obj-C classes that are used inside juce.
Because of the flat naming structure used by Obj-C, you can get horrible situations where
two DLLs are loaded into a host, each of which uses classes with the same names, and these get
cross-linked so that when you make a call to a class that you thought was private, it ends up
actually calling into a similarly named class in the other module's address space.
By changing this macro to a unique value, you ensure that all the obj-C classes in your app
have unique names, and should avoid this problem.
If you're using the amalgamated version, you can just set this macro to something unique before
you include juce_amalgamated.cpp.
*/
#ifndef JUCE_ObjCExtraSuffix
#define JUCE_ObjCExtraSuffix 2
#define JUCE_ObjCExtraSuffix 3
#endif
#define appendMacro1(a, b, c, d) a ## _ ## b ## _ ## c ## _ ## d
#define appendMacro2(a, b, c, d) appendMacro1(a, b, c, d)
#define MakeObjCClassName(rootName) appendMacro2 (rootName, JUCE_MAJOR_VERSION, JUCE_MINOR_VERSION, JUCE_ObjCExtraSuffix)


+ 312
- 300
extras/audio plugins/How to use this framework.txt View File

@@ -1,300 +1,312 @@
The Juce Polymorphic Plugin Project!
====================================
(c) 2008 by Raw Material Software, visit www.rawmaterialsoftware.com for more info.
-----------------------------------------------------------------------------------------------------
The purpose of this framework is to make is simple to write an audio plugin in a generic
way, which can then be compiled as a VST, AudioUnit, RTAS, or any combination of these.
It's "polymorphic" because the output is a single binary module that acts as all of the
different plugin formats at the same time. This means that you only need to maintain one
project, and only need to perform one build to create a multi-format plugin.
Also included are some helper classes that make it easy to create a stand-alone app to
run your plugin without a host. This might be useful in its own right, but can also be very
handy when developing your plugin, because you can build, test and debug it without needing
to keep restarting a 3rd-party host.
How does it work?
=================
To create your plugin, you just create a subclass of the AudioPluginInstance class to
perform the processing. And your plugin UI is written like any normal Juce UI component.
All the platform-specific code is hidden away in wrapper classes that you just add to
your project - you should (hopefully) never need to even see the inner workings of these.
Licensing issues
================
Juce is released under the GPL (Gnu Public License) - this means that you're free to use
and redistribute it as long as your products are also released under the GPL. Basically
this means that if you use it, you also have to give away your source code.
If you want to release a closed-source application, you can buy a commercial license
that lets you avoid this restriction - see http://www.rawmaterialsoftware.com/juce for more info,
or see the comments at the top of all the Juce source files.
If you're building the VST projects or releasing a VST, you'll need have a look at Steinberg's
developer site to see what licensing rules apply these days. Their website's at
http://www.steinberg.net
If you're building an RTAS then you'll need to sign Digidesign's developer license to get
their SDK. Visit http://www.digidesign.com for more info.
Getting Started
===============
There's also a 'demo' folder - this contains an example plugin which can be built in all
the different formats.
Have a look at the demo classes to see how it works, and then to create a real plugin,
you'll need to replace the demo files with your own code.
I've tried to add helpful comments where you might run across common compile errors, to
help describe what you might be doing wrong, as getting a build set-up for some of these
formats can be a bit of a pain. Please let me know if you find there's anything missing
from these instructions or anything I could change to help smooth the build process along
a bit.
I'd recommend NOT putting your own plugin code inside the demo plugin directory - it's
much neater to keep it somewhere separate and to alter the projects to point to your
files instead of the demo ones. That way when new versions of this library come out, it'll
make it easier to update to the latest code.
-----------------------------------------------------------------------------------------------------
Prerequisites for building a VST
================================
- Visit http://www.steinberg.net and jump through whatever hoops are necessary to download
and install the VST SDK.
- Make sure your include path contains an entry for the "vstsdk2.4" folder containing the SDK.
-----------------------------------------------------------------------------------------------------
Prerequisites for building an RTAS
==================================
- Contact Digidesign, ask to become a Digidesign Development Partner, sign the relevent
agreements and NDAs.
- From the Digidesign website, download their latest Plug-In SDK
- Install the SDK and build some of the demo plugins to make sure it all works.
- In Visual Studio: Add all of these to your include path:
c:\yourdirectory\PT_80_SDK\AlturaPorts\TDMPlugins\PluginLibrary\EffectClasses
c:\yourdirectory\PT_80_SDK\AlturaPorts\TDMPlugins\PluginLibrary\ProcessClasses
c:\yourdirectory\PT_80_SDK\AlturaPorts\TDMPlugins\PluginLibrary\ProcessClasses\Interfaces
c:\yourdirectory\PT_80_SDK\AlturaPorts\TDMPlugins\PluginLibrary\Utilities
c:\yourdirectory\PT_80_SDK\AlturaPorts\TDMPlugins\PluginLibrary\RTASP_Adapt
c:\yourdirectory\PT_80_SDK\AlturaPorts\TDMPlugins\PluginLibrary\CoreClasses
c:\yourdirectory\PT_80_SDK\AlturaPorts\TDMPlugins\PluginLibrary\Controls
c:\yourdirectory\PT_80_SDK\AlturaPorts\TDMPlugins\PluginLibrary\Meters
c:\yourdirectory\PT_80_SDK\AlturaPorts\TDMPlugins\PluginLibrary\ViewClasses
c:\yourdirectory\PT_80_SDK\AlturaPorts\TDMPlugins\PluginLibrary\DSPClasses
c:\yourdirectory\PT_80_SDK\AlturaPorts\TDMPlugins\PluginLibrary\Interfaces
c:\yourdirectory\PT_80_SDK\AlturaPorts\TDMPlugins\common
c:\yourdirectory\PT_80_SDK\AlturaPorts\TDMPlugins\common\Platform
c:\yourdirectory\PT_80_SDK\AlturaPorts\TDMPlugins\SignalProcessing\Public
C:\yourdirectory\PT_80_SDK\AlturaPorts\TDMPlugIns\DSPManager\Interfaces
c:\yourdirectory\PT_80_SDK\AlturaPorts\SADriver\Interfaces
c:\yourdirectory\PT_80_SDK\AlturaPorts\DigiPublic\Interfaces
c:\yourdirectory\PT_80_SDK\AlturaPorts\Fic\Interfaces\DAEClient
c:\yourdirectory\PT_80_SDK\AlturaPorts\NewFileLibs\Cmn
c:\yourdirectory\PT_80_SDK\AlturaPorts\NewFileLibs\DOA
c:\yourdirectory\PT_80_SDK\AlturaPorts\AlturaSource\PPC_H
c:\yourdirectory\PT_80_SDK\AlturaPorts\AlturaSource\AppSupport
c:\yourdirectory\PT_80_SDK\AvidCode\AVX2sdk\AVX\avx2\avx2sdk\inc
C:\yourdirectory\PT_80_SDK\xplat\AVX\avx2\avx2sdk\inc
- In Visual Studio: Using the Digidesign demo projects in the SDK, make sure you've compiled
debug and release versions of the following static libraries:
DAE.lib, DigiExt.lib, DSI.lib, PlugInLib.lib.
- In XCode: After installing the Digidesign SDK, make sure you've run the config_SDK_for_Mac
command in the SDK's root directory. This sets up some of the tools that it needs.
- In XCode: If you're using the Digi files CommonDebugSettings.xcconfig and CommonReleaseSettings.xcconfig,
then you'll probably have to remove the "-x c++" option from their OTHER_CFLAGS setting, because
that prevents it compiling obj-C. Also, you might need to comment-out the GCC_PREFIX_HEADER setting,
unless you can persuade precompiled headers to work (I've never managed to get them working myself..)
You'll also probably want to add a "MacBag" setting to these files, rather than putting it into
your project - e.g. "MacBag = /Users/jules/SDKs/PT_80_SDK/MacBag"
-----------------------------------------------------------------------------------------------------
Choosing the formats to build
=============================
Each plugin project needs to contain a JucePluginCharacteristics.h file, which holds all the
plugin-specific build details. In here, there are three macros that you can set to enable each
of the available formats:
#define JucePlugin_Build_VST 1
#define JucePlugin_Build_RTAS 1
#define JucePlugin_Build_AU 1
You can set these to 0 to disable the formats that you don't want to build, and this will avoid
any compilation problems if, for example, you don't have the appropriate SDK for a particular format.
-----------------------------------------------------------------------------------------------------
Creating a PC VST/RTAS plugin in Visual Studio
==============================================
- First try loading the VST demo project in JuceAudioPlugin/demo/build. Hopefully this
should build correctly.
- Create a new, empty, win32 project using Visual Studio. Choose "DLL" as the type of
product to build
- If building an RTAS, add to your project all the juce_RTAS_*.cpp files from the wrapper/RTAS folder.
- If building a VST, add to your project all the juce_VST_*.cpp files from the wrapper/VST folder.
- Create yourself a JucePluginCharacteristics.h file, starting with a copy of the one in the
demo project. Go through each item inside it carefully, and set them to the appropriate value
for your plugin.
- Under "Additional Include Directories", add the folder in which you're going to put
your JucePluginCharacteristics.h file.
- If you're doing an RTAS, change these project settings (these can all be ignored if you're only doing a VST):
- Set "C++/Code Generation/Runtime Library" to be "Multi-threaded DLL" or "Multi-threaded Debug DLL"
- Set the "Linker/Input/Module Definition file" to point to "wrapper/RTAS/juce_RTAS_WinExports.def"
- Under "Linker/Input/Delay loaded DLLs", add the following:
"DAE.dll; DigiExt.dll; DSI.dll; PluginLib.dll; DSPManager.dll"
- You may (or may not) need to add "libcmtd.lib; libcmt.lib" to the "Linker/Input/Ignore Specific Library" setting.
- For ONLY the following files:
juce_RTAS_Wrapper.cpp, juce_RTAS_DigiCode1.cpp, juce_RTAS_DigiCode2.cpp, juce_RTAS_DigiCode3.cpp,
change their "C++/Advanced/Calling Convention" property to "__stdcall". All other files should
be left with the default calling convention of "__cdecl"
- Set the "Linker/General/Output File" property to "$(OutDir)\$(ProjectName).dpm" (If you're building
a polymorphic VST/RTAS, then you can simply copy or rename the finished .dpm file to a .dll, and
it'll function as a VST)
- Under "Custom build step", add the following command:
copy /Y "\yourdirectory\juce\extras\audio plugins\wrapper\RTAS\juce_RTAS_WinResources.rsr" "$(TargetPath)".rsr
The corresponding "Outputs" setting for this must be set to "$(TargetPath)".rsr
(This will copy and rename the juce_RTAS_WinResources.rsr file to sit next to the finished .dpm file. It's
a dummy resource file, but PT will refuse to load the plugin unless it has a corresponding .rsr file)
- Because the RTAS code duplicates some win32 constants, you might need to force it to link correctly
by adding "/FORCE:multiple" to the linker's additional command line options.
- You might want to change the output directory to "\Program Files\Common Files\Digidesign\DAE\Plug-Ins\"
if you want the built plugin to go directly into the PT plugins folder
- When setting properties, remember to change them for both your debug and release builds!
- Create your actual plugin classes and add them to the project. Obviously this is the hard bit!
- Add the amalgamated juce source file to the project - have a look at the demo app for neat ways of doing this.
- NOTE: on Windows, because RTAS uses the altura mac-style code, there are annoying clashes caused if
you also include the Apple QuickTime headers, so you might need to turn off quicktime by setting the
juce config macro: #define JUCE_QUICKTIME 0
- NOTE: If you're using MSVC2005 to build your plugin, the users will need to
have the Microsoft VC8 Runtime installed on their machines, otherwise the DLL will
silently fail to load. You should probably add the runtime to your plugin's installer,
and you can get a copy of it here:
http://www.microsoft.com/downloads/details.aspx?FamilyID=32bc1bee-a3f9-4c13-9c99-220b62a191ee&DisplayLang=en
-----------------------------------------------------------------------------------------------------
Creating a Mac AU/VST/RTAS plugin in XCode
==========================================
- For an AU, make sure that the JucePlugin_Build_AU is enabled in your JucePluginCharacteristics.h
- In XCode, create a new project based on the "Audio Unit Effect" template
- XCode will create a bunch of template source files for you - you can remove all of these from the project
and delete them
- In the target settings, clear the "Exported Symbols File" setting. The exports are specified by directives
within the wrapper code, so don't need to be listed explicitly.
- All all the Apple frameworks that Juce normally requires to the "External Frameworks" list
- Add all the juce_AU_* files from the /wrapper/AU directory to your project
- The template project creates an AUPublic group that contains lots of AudioUnit source files. But
it leaves out files that it thinks you might not need, e.g. if you chose an "Audio Unit Effect" project,
then it won't add the classes for handling MIDI. So you'll probably need to go into this folder
and check that it contains AUMIDIBase.cpp, AUMidiEffectBase.cpp, MusicDeviceBase.cpp, etc
- As for the PC, you'll need to make sure your project contains a correctly set-up JucePluginCharacteristics.h
file - start with a copy of the one in the demo plugin project, and go through it making sure that
all the values make sense for your plugin.
- Create your actual plugin classes and add them to the project. Obviously this is the hard bit!
You should now be able to build a functional AU! If you want VST support as well, then read on...
- Make sure that the JucePlugin_Build_VST is enabled in your JucePluginCharacteristics.h
- For VST support, add all the juce_VST_* files from /wrapper/VST
- In your target info settings, add the vstsdk2_4 folder to your "Header Search Paths" list
- Make sure that in your Info.plist, the "Bundle Name" value is correctly set to the name of your plugin.
Now, if you compile, the resulting bundle should work as both a VST and AU - you can simply copy or rename it,
changing the suffix to ".vst", and put it in your VST folder.
If you also want to build an RTAS, then carry on reading...
- Make sure that the JucePlugin_Build_RTAS is enabled in your JucePluginCharacteristics.h
- After installing the Digidesign SDK, make sure you've run the config_SDK_for_Mac command in
its root directory. This sets up some of the tools that it needs.
- Add the files from /wrapper/RTAS to your project. Obviously a couple of these are for Windows, so
you shouldn't add those
- In the Digi SDK, in /AlturaPorts/TDMPlugins/common/mac, there are two config files:
CommonDebugSettings.xconfig and CommonReleaseSettings.xconfig
These contain lots of Digi hackery to get their stuff to compile, so you should add them to your project
and change your project's settings to use these files as their base config. Even so, it's all a bit of a mess,
and you may need to tweak them a bit to get it to work on your system.
- In your target settings, add a custom build setting called "MacBag", and set this to the path where the
"MacBag" folder of the Digi SDK lives.
- Add the following to your "Header Search Paths" setting (it's easiest to copy-and-paste this setting from
the demo project):
"$(MacBag)/../AlturaPorts/TDMPlugIns/PlugInLibrary/**"
"$(MacBag)/../AlturaPorts/TDMPlugIns/DSPManager/**"
"$(MacBag)/../AlturaPorts/TDMPlugIns/SupplementalPlugInLib/Encryption"
"$(MacBag)/../AlturaPorts/TDMPlugIns/SupplementalPlugInLib/GraphicsExtensions"
"$(MacBag)/../AlturaPorts/TDMPlugIns/common"
"$(MacBag)/../AlturaPorts/TDMPlugIns/common/PI_LibInterface"
"$(MacBag)/../AlturaPorts/TDMPlugIns/PACEProtection/**"
"$(MacBag)/../AlturaPorts/OMS/Headers"
"$(MacBag)/../AlturaPorts/Fic/Interfaces/**"
"$(MacBag)/../AlturaPorts/Fic/Source/SignalNets"
"$(MacBag)/../AlturaPorts/DSIPublicInterface/PublicHeaders"
"$(MacBag)/../DAEWin/Include"
"$(MacBag)/../AlturaPorts/DigiPublic/Interfaces"
"$(MacBag)/../AlturaPorts/DigiPublic"
"$(MacBag)/../AlturaPorts/NewFileLibs/DOA"
"$(MacBag)/../AlturaPorts/NewFileLibs/Cmn"
"$(MacBag)/../AlturaPorts/TDMPlugIns/SignalProcessing/**"
"$(MacBag)/../AvidCode/AVX2sdk/AVX/avx2/avx2sdk/inc"
"$(MacBag)/../AvidCode/AVX2sdk/AVX/avx2/avx2sdk/utils"
- If you get include errors compiling some of the DigiDesign code, you may need to
add "/Developer/Headers/FlatCarbon" to your header search path.
- In the SDK, find the PluginLibrary.xcodeproj file, and add this to your "External frameworks and Libraries".
If you've already compiled this library, you can open its item in your XCode project treeview, to find
the "libPluginLibrary.a" item inside it. Drag this subitem down to your Target/"Link Binary With Libraries"
build stage and drop it there to add it to the link process.
- In your Info.plist, change the "Bundle OS Type Code" to "TDMw", and the "Bundle Creator OS Type Code" to
"PTul".
- You may need to remove the "OTHER_CFLAGS = -x c++" from the RTAS settings file to stop it complaining about
obj-C code
You should now be able to build an RTAS! Again, just renaming the finished bundle to ".dpm" and
putting it in your RTAS folder should be do the trick.
If you get any weird build problems, a good tip is to try comparing the demo plugin's build settings with your
own - this should usually show up what's missing.
Note about exported symbols:
When XCode builds the plugin, I've had unpredictable results when trying to stop it from exporting
all of the internal functions as public symbols. There are some flags that are supposed to turn this
off, but sometimes they don't seem to have any effect, and using an explicit exports file also
seems a bit hit-and-miss. (If anyone knows better and can get this working, please let me know!)
Anyway, as well as being wasteful and showing everyone what's inside your plugin, leaving all
the symbols in there will cause fatal crashes when used with Tracktion, or alongside any other
Juce-based plugins. A way of making sure your plugin is stripped is to use the command
"strip -x -S YourPlugin.vst/Contents/MacOS/YourPlugin" after bulding it, which removes the
unnecessary symbols (although in my experience this also doesn't seem to work all the time,
so it's a good idea to check it using the unix "nm" command).

The Juce Polymorphic Plugin Project!
====================================

(c) 2008 by Raw Material Software, visit www.rawmaterialsoftware.com for more info.

-----------------------------------------------------------------------------------------------------

The purpose of this framework is to make is simple to write an audio plugin in a generic
way, which can then be compiled as a VST, AudioUnit, RTAS, or any combination of these.

It's "polymorphic" because the output is a single binary module that acts as all of the
different plugin formats at the same time. This means that you only need to maintain one
project, and only need to perform one build to create a multi-format plugin.

Also included are some helper classes that make it easy to create a stand-alone app to
run your plugin without a host. This might be useful in its own right, but can also be very
handy when developing your plugin, because you can build, test and debug it without needing
to keep restarting a 3rd-party host.


How does it work?
=================

To create your plugin, you just create a subclass of the AudioPluginInstance class to
perform the processing. And your plugin UI is written like any normal Juce UI component.

All the platform-specific code is hidden away in wrapper classes that you just add to
your project - you should (hopefully) never need to even see the inner workings of these.


Licensing issues
================

Juce is released under the GPL (Gnu Public License) - this means that you're free to use
and redistribute it as long as your products are also released under the GPL. Basically
this means that if you use it, you also have to give away your source code.
If you want to release a closed-source application, you can buy a commercial license
that lets you avoid this restriction - see http://www.rawmaterialsoftware.com/juce for more info,
or see the comments at the top of all the Juce source files.

If you're building the VST projects or releasing a VST, you'll need have a look at Steinberg's
developer site to see what licensing rules apply these days. Their website's at
http://www.steinberg.net

If you're building an RTAS then you'll need to sign Digidesign's developer license to get
their SDK. Visit http://www.digidesign.com for more info.



Getting Started
===============

There's also a 'demo' folder - this contains an example plugin which can be built in all
the different formats.

Have a look at the demo classes to see how it works, and then to create a real plugin,
you'll need to replace the demo files with your own code.

I've tried to add helpful comments where you might run across common compile errors, to
help describe what you might be doing wrong, as getting a build set-up for some of these
formats can be a bit of a pain. Please let me know if you find there's anything missing
from these instructions or anything I could change to help smooth the build process along
a bit.

I'd recommend NOT putting your own plugin code inside the demo plugin directory - it's
much neater to keep it somewhere separate and to alter the projects to point to your
files instead of the demo ones. That way when new versions of this library come out, it'll
make it easier to update to the latest code.

-----------------------------------------------------------------------------------------------------

Prerequisites for building a VST
================================

- Visit http://www.steinberg.net and jump through whatever hoops are necessary to download
and install the VST SDK.
- Make sure your include path contains an entry for the "vstsdk2.4" folder containing the SDK.

-----------------------------------------------------------------------------------------------------

Prerequisites for building an RTAS
==================================

- Contact Digidesign, ask to become a Digidesign Development Partner, sign the relevent
agreements and NDAs.
- From the Digidesign website, download their latest Plug-In SDK
- Install the SDK and build some of the demo plugins to make sure it all works.
- In Visual Studio: Add all of these to your include path:
c:\yourdirectory\PT_80_SDK\AlturaPorts\TDMPlugins\PluginLibrary\EffectClasses
c:\yourdirectory\PT_80_SDK\AlturaPorts\TDMPlugins\PluginLibrary\ProcessClasses
c:\yourdirectory\PT_80_SDK\AlturaPorts\TDMPlugins\PluginLibrary\ProcessClasses\Interfaces
c:\yourdirectory\PT_80_SDK\AlturaPorts\TDMPlugins\PluginLibrary\Utilities
c:\yourdirectory\PT_80_SDK\AlturaPorts\TDMPlugins\PluginLibrary\RTASP_Adapt
c:\yourdirectory\PT_80_SDK\AlturaPorts\TDMPlugins\PluginLibrary\CoreClasses
c:\yourdirectory\PT_80_SDK\AlturaPorts\TDMPlugins\PluginLibrary\Controls
c:\yourdirectory\PT_80_SDK\AlturaPorts\TDMPlugins\PluginLibrary\Meters
c:\yourdirectory\PT_80_SDK\AlturaPorts\TDMPlugins\PluginLibrary\ViewClasses
c:\yourdirectory\PT_80_SDK\AlturaPorts\TDMPlugins\PluginLibrary\DSPClasses
c:\yourdirectory\PT_80_SDK\AlturaPorts\TDMPlugins\PluginLibrary\Interfaces
c:\yourdirectory\PT_80_SDK\AlturaPorts\TDMPlugins\common
c:\yourdirectory\PT_80_SDK\AlturaPorts\TDMPlugins\common\Platform
c:\yourdirectory\PT_80_SDK\AlturaPorts\TDMPlugins\SignalProcessing\Public
C:\yourdirectory\PT_80_SDK\AlturaPorts\TDMPlugIns\DSPManager\Interfaces
c:\yourdirectory\PT_80_SDK\AlturaPorts\SADriver\Interfaces
c:\yourdirectory\PT_80_SDK\AlturaPorts\DigiPublic\Interfaces
c:\yourdirectory\PT_80_SDK\AlturaPorts\Fic\Interfaces\DAEClient
c:\yourdirectory\PT_80_SDK\AlturaPorts\NewFileLibs\Cmn
c:\yourdirectory\PT_80_SDK\AlturaPorts\NewFileLibs\DOA
c:\yourdirectory\PT_80_SDK\AlturaPorts\AlturaSource\PPC_H
c:\yourdirectory\PT_80_SDK\AlturaPorts\AlturaSource\AppSupport
c:\yourdirectory\PT_80_SDK\AvidCode\AVX2sdk\AVX\avx2\avx2sdk\inc
C:\yourdirectory\PT_80_SDK\xplat\AVX\avx2\avx2sdk\inc
- In Visual Studio: Using the Digidesign demo projects in the SDK, make sure you've compiled
debug and release versions of the following static libraries:
DAE.lib, DigiExt.lib, DSI.lib, PlugInLib.lib.
- In XCode: After installing the Digidesign SDK, make sure you've run the config_SDK_for_Mac
command in the SDK's root directory. This sets up some of the tools that it needs.
- In XCode: If you're using the Digi files CommonDebugSettings.xcconfig and CommonReleaseSettings.xcconfig,
then you'll probably have to remove the "-x c++" option from their OTHER_CFLAGS setting, because
that prevents it compiling obj-C. Also, you might need to comment-out the GCC_PREFIX_HEADER setting,
unless you can persuade precompiled headers to work (I've never managed to get them working myself..)
You'll also probably want to add a "MacBag" setting to these files, rather than putting it into
your project - e.g. "MacBag = /Users/jules/SDKs/PT_80_SDK/MacBag"


-----------------------------------------------------------------------------------------------------

Choosing the formats to build
=============================
Each plugin project needs to contain a JucePluginCharacteristics.h file, which holds all the
plugin-specific build details. In here, there are three macros that you can set to enable each
of the available formats:

#define JucePlugin_Build_VST 1
#define JucePlugin_Build_RTAS 1
#define JucePlugin_Build_AU 1

You can set these to 0 to disable the formats that you don't want to build, and this will avoid
any compilation problems if, for example, you don't have the appropriate SDK for a particular format.

-----------------------------------------------------------------------------------------------------

Creating a PC VST/RTAS plugin in Visual Studio
==============================================


- First try loading the VST demo project in JuceAudioPlugin/demo/build. Hopefully this
should build correctly.
- Create a new, empty, win32 project using Visual Studio. Choose "DLL" as the type of
product to build
- If building an RTAS, add to your project all the juce_RTAS_*.cpp files from the wrapper/RTAS folder.
- If building a VST, add to your project all the juce_VST_*.cpp files from the wrapper/VST folder.

- Create yourself a JucePluginCharacteristics.h file, starting with a copy of the one in the
demo project. Go through each item inside it carefully, and set them to the appropriate value
for your plugin.

- Under "Additional Include Directories", add the folder in which you're going to put
your JucePluginCharacteristics.h file.

- If you're doing an RTAS, change these project settings (these can all be ignored if you're only doing a VST):
- Set "C++/Code Generation/Runtime Library" to be "Multi-threaded DLL" or "Multi-threaded Debug DLL"
- Set the "Linker/Input/Module Definition file" to point to "wrapper/RTAS/juce_RTAS_WinExports.def"
- Under "Linker/Input/Delay loaded DLLs", add the following:
"DAE.dll; DigiExt.dll; DSI.dll; PluginLib.dll; DSPManager.dll"
- You may (or may not) need to add "libcmtd.lib; libcmt.lib" to the "Linker/Input/Ignore Specific Library" setting.
- For ONLY the following files:
juce_RTAS_Wrapper.cpp, juce_RTAS_DigiCode1.cpp, juce_RTAS_DigiCode2.cpp, juce_RTAS_DigiCode3.cpp,
change their "C++/Advanced/Calling Convention" property to "__stdcall". All other files should
be left with the default calling convention of "__cdecl"
- Set the "Linker/General/Output File" property to "$(OutDir)\$(ProjectName).dpm" (If you're building
a polymorphic VST/RTAS, then you can simply copy or rename the finished .dpm file to a .dll, and
it'll function as a VST)
- Under "Custom build step", add the following command:
copy /Y "\yourdirectory\juce\extras\audio plugins\wrapper\RTAS\juce_RTAS_WinResources.rsr" "$(TargetPath)".rsr
The corresponding "Outputs" setting for this must be set to "$(TargetPath)".rsr
(This will copy and rename the juce_RTAS_WinResources.rsr file to sit next to the finished .dpm file. It's
a dummy resource file, but PT will refuse to load the plugin unless it has a corresponding .rsr file)
- Because the RTAS code duplicates some win32 constants, you might need to force it to link correctly
by adding "/FORCE:multiple" to the linker's additional command line options.
- You might want to change the output directory to "\Program Files\Common Files\Digidesign\DAE\Plug-Ins\"
if you want the built plugin to go directly into the PT plugins folder
- When setting properties, remember to change them for both your debug and release builds!

- Create your actual plugin classes and add them to the project. Obviously this is the hard bit!

- Add the amalgamated juce source file to the project - have a look at the demo app for neat ways of doing this.

- NOTE: on Windows, because RTAS uses the altura mac-style code, there are annoying clashes caused if
you also include the Apple QuickTime headers, so you might need to turn off quicktime by setting the
juce config macro: #define JUCE_QUICKTIME 0

- NOTE: If you're using MSVC2005 to build your plugin, the users will need to
have the Microsoft VC8 Runtime installed on their machines, otherwise the DLL will
silently fail to load. You should probably add the runtime to your plugin's installer,
and you can get a copy of it here:
http://www.microsoft.com/downloads/details.aspx?FamilyID=32bc1bee-a3f9-4c13-9c99-220b62a191ee&DisplayLang=en



-----------------------------------------------------------------------------------------------------

Creating a Mac AU/VST/RTAS plugin in XCode
==========================================


- For an AU, make sure that the JucePlugin_Build_AU is enabled in your JucePluginCharacteristics.h
- In XCode, create a new project based on the "Audio Unit Effect" template
- XCode will create a bunch of template source files for you - you can remove all of these from the project
and delete them
- In the target settings, clear the "Exported Symbols File" setting. The exports are specified by directives
within the wrapper code, so don't need to be listed explicitly.
- All all the Apple frameworks that Juce normally requires to the "External Frameworks" list
- Add all the juce_AU_* files from the /wrapper/AU directory to your project
- The template project creates an AUPublic group that contains lots of AudioUnit source files. But
it leaves out files that it thinks you might not need, e.g. if you chose an "Audio Unit Effect" project,
then it won't add the classes for handling MIDI. So you'll probably need to go into this folder
and check that it contains AUMIDIBase.cpp, AUMidiEffectBase.cpp, MusicDeviceBase.cpp, etc
- As for the PC, you'll need to make sure your project contains a correctly set-up JucePluginCharacteristics.h
file - start with a copy of the one in the demo plugin project, and go through it making sure that
all the values make sense for your plugin.
- Because of the flat naming structure used by Objective-C, if a host loads several different plugins which
all contain slightly different versions of the juce library, you can get nasty situations where all their obj-C
classes are cross-linked to the similarly-named class in other modules, and everything turns into a big mess...
To avoid this, you're advised to set a unique JUCE_ObjCExtraSuffix value (you'll find this in juce_mac_NativeCode.mm,
or if you're using the amalgamated version, you can just set it before including juce_amalgamated.cpp). Choose a
suffix that's unique to both the name and version of your plugin.
- Create your actual plugin classes and add them to the project. Obviously this is the hard bit!

You should now be able to build a functional AU! If you want VST support as well, then read on...

- Make sure that the JucePlugin_Build_VST is enabled in your JucePluginCharacteristics.h
- For VST support, add all the juce_VST_* files from /wrapper/VST
- In your target info settings, add the vstsdk2_4 folder to your "Header Search Paths" list
- Make sure that in your Info.plist, the "Bundle Name" value is correctly set to the name of your plugin.

Now, if you compile, the resulting bundle should work as both a VST and AU - you can simply copy or rename it,
changing the suffix to ".vst", and put it in your VST folder.

NOTE! If you use the Finder to rename your xyz.component file to xyz.vst, it might look like it's done
exactly this... but in fact, the Finder may have secretly renamed it as "xyz.vst.component", even though
it shows "xyz.vst" as the name on the screen. I have wasted quite a lot of time angrily wondering why my VSTs
don't seem to work, before realising that this is what has happened. You should use the command-line to rename
it correctly.

If you also want to build an RTAS, then carry on reading...


- Make sure that the JucePlugin_Build_RTAS is enabled in your JucePluginCharacteristics.h
- After installing the Digidesign SDK, make sure you've run the config_SDK_for_Mac command in
its root directory. This sets up some of the tools that it needs.
- Add the files from /wrapper/RTAS to your project. Obviously a couple of these are for Windows, so
you shouldn't add those
- In the Digi SDK, in /AlturaPorts/TDMPlugins/common/mac, there are two config files:
CommonDebugSettings.xconfig and CommonReleaseSettings.xconfig
These contain lots of Digi hackery to get their stuff to compile, so you should add them to your project
and change your project's settings to use these files as their base config. Even so, it's all a bit of a mess,
and you may need to tweak them a bit to get it to work on your system.
- In your target settings, add a custom build setting called "MacBag", and set this to the path where the
"MacBag" folder of the Digi SDK lives.
- Add the following to your "Header Search Paths" setting (it's easiest to copy-and-paste this setting from
the demo project):
"$(MacBag)/../AlturaPorts/TDMPlugIns/PlugInLibrary/**"
"$(MacBag)/../AlturaPorts/TDMPlugIns/DSPManager/**"
"$(MacBag)/../AlturaPorts/TDMPlugIns/SupplementalPlugInLib/Encryption"
"$(MacBag)/../AlturaPorts/TDMPlugIns/SupplementalPlugInLib/GraphicsExtensions"
"$(MacBag)/../AlturaPorts/TDMPlugIns/common"
"$(MacBag)/../AlturaPorts/TDMPlugIns/common/PI_LibInterface"
"$(MacBag)/../AlturaPorts/TDMPlugIns/PACEProtection/**"
"$(MacBag)/../AlturaPorts/OMS/Headers"
"$(MacBag)/../AlturaPorts/Fic/Interfaces/**"
"$(MacBag)/../AlturaPorts/Fic/Source/SignalNets"
"$(MacBag)/../AlturaPorts/DSIPublicInterface/PublicHeaders"
"$(MacBag)/../DAEWin/Include"
"$(MacBag)/../AlturaPorts/DigiPublic/Interfaces"
"$(MacBag)/../AlturaPorts/DigiPublic"
"$(MacBag)/../AlturaPorts/NewFileLibs/DOA"
"$(MacBag)/../AlturaPorts/NewFileLibs/Cmn"
"$(MacBag)/../AlturaPorts/TDMPlugIns/SignalProcessing/**"
"$(MacBag)/../AvidCode/AVX2sdk/AVX/avx2/avx2sdk/inc"
"$(MacBag)/../AvidCode/AVX2sdk/AVX/avx2/avx2sdk/utils"
- If you get include errors compiling some of the DigiDesign code, you may need to
add "/Developer/Headers/FlatCarbon" to your header search path.
- In the SDK, find the PluginLibrary.xcodeproj file, and add this to your "External frameworks and Libraries".
If you've already compiled this library, you can open its item in your XCode project treeview, to find
the "libPluginLibrary.a" item inside it. Drag this subitem down to your Target/"Link Binary With Libraries"
build stage and drop it there to add it to the link process.
- In your Info.plist, change the "Bundle OS Type Code" to "TDMw", and the "Bundle Creator OS Type Code" to
"PTul".
- You may need to remove the "OTHER_CFLAGS = -x c++" from the RTAS settings file to stop it complaining about
obj-C code

You should now be able to build an RTAS! Again, just renaming the finished bundle to ".dpm" and
putting it in your RTAS folder should be do the trick.
If you get any weird build problems, a good tip is to try comparing the demo plugin's build settings with your
own - this should usually show up what's missing.


Note about exported symbols:
When XCode builds the plugin, I've had unpredictable results when trying to stop it from exporting
all of the internal functions as public symbols. There are some flags that are supposed to turn this
off, but sometimes they don't seem to have any effect, and using an explicit exports file also
seems a bit hit-and-miss. (If anyone knows better and can get this working, please let me know!)
Anyway, as well as being wasteful and showing everyone what's inside your plugin, leaving all
the symbols in there will cause fatal crashes when used with Tracktion, or alongside any other
Juce-based plugins. A way of making sure your plugin is stripped is to use the command
"strip -x -S YourPlugin.vst/Contents/MacOS/YourPlugin" after bulding it, which removes the
unnecessary symbols (although in my experience this also doesn't seem to work all the time,
so it's a good idea to check it using the unix "nm" command).

BIN
extras/audio plugins/demo/build/mac/English.lproj/InfoPlist.strings View File


+ 8
- 6
extras/audio plugins/demo/build/mac/Info.plist View File

@@ -5,23 +5,25 @@
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<string>EXECUTABLE_NAME</string>
<key>CFBundleGetInfoString</key>
<string>VERSION_STR</string>
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string>com.rawmaterialsoftware.${PRODUCT_NAME:identifier}</string>
<string>com.rawmaterialsoftware.PRODUCT_NAME</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<string>PRODUCT_NAME</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<string>TDMw</string>
<key>CFBundleShortVersionString</key>
<string>1.1</string>
<key>CFBundleSignature</key>
<string>????</string>
<string>PTul</string>
<key>CFBundleVersion</key>
<string>1.1</string>
<string>VERSION_NUM</string>
<key>CSResourcesFileMapped</key>
<true/>
</dict>


+ 16
- 4
extras/audio plugins/demo/build/mac/JuceDemoPlugin.xcodeproj/project.pbxproj View File

@@ -49,9 +49,8 @@
843796E00EFBFD16002A2725 /* juce_RTAS_MacResources.r in Rez */ = {isa = PBXBuildFile; fileRef = 843796D90EFBFD16002A2725 /* juce_RTAS_MacResources.r */; };
843796E10EFBFD16002A2725 /* juce_RTAS_MacUtilities.mm in Sources */ = {isa = PBXBuildFile; fileRef = 843796DA0EFBFD16002A2725 /* juce_RTAS_MacUtilities.mm */; };
843796E20EFBFD16002A2725 /* juce_RTAS_Wrapper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 843796DB0EFBFD16002A2725 /* juce_RTAS_Wrapper.cpp */; };
843796F60EFC0102002A2725 /* CommonDebugSettings.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 843796F40EFC0102002A2725 /* CommonDebugSettings.xcconfig */; };
843796F70EFC0102002A2725 /* CommonReleaseSettings.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 843796F50EFC0102002A2725 /* CommonReleaseSettings.xcconfig */; };
843797050EFC0269002A2725 /* libPluginLibrary.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 843797030EFC022E002A2725 /* libPluginLibrary.a */; };
849817021010B3C500297ECA /* JuceDemoPlugin.component in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8D01CCD20486CAD60068D4B7 /* JuceDemoPlugin.component */; };
84D3AB5F0FCC744600EA8080 /* AUCarbonViewBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84D3AB5E0FCC744600EA8080 /* AUCarbonViewBase.cpp */; };
84D3AB630FCC749100EA8080 /* AUCarbonViewBase.h in Headers */ = {isa = PBXBuildFile; fileRef = 84D3AB620FCC749100EA8080 /* AUCarbonViewBase.h */; };
84D3AB670FCC74B300EA8080 /* CarbonEventHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84D3AB650FCC74B300EA8080 /* CarbonEventHandler.cpp */; };
@@ -102,6 +101,19 @@
};
/* End PBXContainerItemProxy section */

/* Begin PBXCopyFilesBuildPhase section */
849817161010B3D100297ECA /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "~/Library/Audio/Plug-Ins/Components";
dstSubfolderSpec = 0;
files = (
849817021010B3C500297ECA /* JuceDemoPlugin.component in CopyFiles */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */

/* Begin PBXFileReference section */
089C167EFE841241C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; };
3EEA126B089847F5002C6BFC /* CAVectorUnit.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CAVectorUnit.cpp; sourceTree = "<group>"; };
@@ -500,6 +512,7 @@
8D01CCCB0486CAD60068D4B7 /* Sources */,
8D01CCCD0486CAD60068D4B7 /* Frameworks */,
8D01CCCF0486CAD60068D4B7 /* Rez */,
849817161010B3D100297ECA /* CopyFiles */,
);
buildRules = (
);
@@ -550,8 +563,6 @@
buildActionMask = 2147483647;
files = (
8D01CCCA0486CAD60068D4B7 /* InfoPlist.strings in Resources */,
843796F60EFC0102002A2725 /* CommonDebugSettings.xcconfig in Resources */,
843796F70EFC0102002A2725 /* CommonReleaseSettings.xcconfig in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -638,6 +649,7 @@
INFOPLIST_FILE = Info.plist;
INSTALL_PATH = "$(HOME)/Library/Audio/Plug-Ins/Components/";
LIBRARY_STYLE = Bundle;
MACOSX_DEPLOYMENT_TARGET = 10.4;
OTHER_LDFLAGS = "-bundle";
OTHER_REZFLAGS = "-d ppc_$ppc -d i386_$i386 -d ppc64_$ppc64 -d x86_64_$x86_64 -I /System/Library/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework/Versions/A/Headers -I \"$(DEVELOPER_DIR)/Examples/CoreAudio/AudioUnits/AUPublic/AUBase\"";
PRODUCT_NAME = JuceDemoPlugin;


+ 31
- 19
extras/juce demo/build/linux/JuceDemo.make View File

@@ -39,20 +39,22 @@ ifeq ($(CONFIG),Release)
endif

OBJECTS := \
$(OBJDIR)/MainDemoWindow.o \
$(OBJDIR)/BinaryData.o \
$(OBJDIR)/ApplicationStartup.o \
$(OBJDIR)/BinaryData.o \
$(OBJDIR)/juce_LibrarySource.o \
$(OBJDIR)/TreeViewDemo.o \
$(OBJDIR)/MainDemoWindow.o \
$(OBJDIR)/WebBrowserDemo.o \
$(OBJDIR)/WidgetsDemo.o \
$(OBJDIR)/DragAndDropDemo.o \
$(OBJDIR)/FontsAndTextDemo.o \
$(OBJDIR)/InterprocessCommsDemo.o \
$(OBJDIR)/OpenGLDemo.o \
$(OBJDIR)/PathsAndTransformsDemo.o \
$(OBJDIR)/ThreadingDemo.o \
$(OBJDIR)/TreeViewDemo.o \
$(OBJDIR)/QuickTimeDemo.o \
$(OBJDIR)/TableDemo.o \
$(OBJDIR)/ThreadingDemo.o \
$(OBJDIR)/OpenGLDemo.o \
$(OBJDIR)/PathsAndTransformsDemo.o \
$(OBJDIR)/FontsAndTextDemo.o \
$(OBJDIR)/InterprocessCommsDemo.o \
$(OBJDIR)/DragAndDropDemo.o \
$(OBJDIR)/CameraDemo.o \
$(OBJDIR)/AudioDemo.o \

MKDIR_TYPE := msdos
@@ -95,7 +97,7 @@ else
-@if exist $(subst /,\,$(OBJDIR)) rmdir /s /q $(subst /,\,$(OBJDIR))
endif

$(OBJDIR)/MainDemoWindow.o: ../../src/MainDemoWindow.cpp
$(OBJDIR)/ApplicationStartup.o: ../../src/ApplicationStartup.cpp
-@$(CMD_MKOBJDIR)
@echo $(notdir $<)
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
@@ -105,17 +107,17 @@ $(OBJDIR)/BinaryData.o: ../../src/BinaryData.cpp
@echo $(notdir $<)
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"

$(OBJDIR)/ApplicationStartup.o: ../../src/ApplicationStartup.cpp
$(OBJDIR)/juce_LibrarySource.o: ../../src/juce_LibrarySource.cpp
-@$(CMD_MKOBJDIR)
@echo $(notdir $<)
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"

$(OBJDIR)/juce_LibrarySource.o: ../../src/juce_LibrarySource.cpp
$(OBJDIR)/MainDemoWindow.o: ../../src/MainDemoWindow.cpp
-@$(CMD_MKOBJDIR)
@echo $(notdir $<)
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"

$(OBJDIR)/TreeViewDemo.o: ../../src/demos/TreeViewDemo.cpp
$(OBJDIR)/WebBrowserDemo.o: ../../src/demos/WebBrowserDemo.cpp
-@$(CMD_MKOBJDIR)
@echo $(notdir $<)
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
@@ -125,17 +127,22 @@ $(OBJDIR)/WidgetsDemo.o: ../../src/demos/WidgetsDemo.cpp
@echo $(notdir $<)
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"

$(OBJDIR)/DragAndDropDemo.o: ../../src/demos/DragAndDropDemo.cpp
$(OBJDIR)/ThreadingDemo.o: ../../src/demos/ThreadingDemo.cpp
-@$(CMD_MKOBJDIR)
@echo $(notdir $<)
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"

$(OBJDIR)/FontsAndTextDemo.o: ../../src/demos/FontsAndTextDemo.cpp
$(OBJDIR)/TreeViewDemo.o: ../../src/demos/TreeViewDemo.cpp
-@$(CMD_MKOBJDIR)
@echo $(notdir $<)
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"

$(OBJDIR)/InterprocessCommsDemo.o: ../../src/demos/InterprocessCommsDemo.cpp
$(OBJDIR)/QuickTimeDemo.o: ../../src/demos/QuickTimeDemo.cpp
-@$(CMD_MKOBJDIR)
@echo $(notdir $<)
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"

$(OBJDIR)/TableDemo.o: ../../src/demos/TableDemo.cpp
-@$(CMD_MKOBJDIR)
@echo $(notdir $<)
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
@@ -150,17 +157,22 @@ $(OBJDIR)/PathsAndTransformsDemo.o: ../../src/demos/PathsAndTransformsDemo.cpp
@echo $(notdir $<)
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"

$(OBJDIR)/QuickTimeDemo.o: ../../src/demos/QuickTimeDemo.cpp
$(OBJDIR)/FontsAndTextDemo.o: ../../src/demos/FontsAndTextDemo.cpp
-@$(CMD_MKOBJDIR)
@echo $(notdir $<)
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"

$(OBJDIR)/TableDemo.o: ../../src/demos/TableDemo.cpp
$(OBJDIR)/InterprocessCommsDemo.o: ../../src/demos/InterprocessCommsDemo.cpp
-@$(CMD_MKOBJDIR)
@echo $(notdir $<)
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"

$(OBJDIR)/ThreadingDemo.o: ../../src/demos/ThreadingDemo.cpp
$(OBJDIR)/DragAndDropDemo.o: ../../src/demos/DragAndDropDemo.cpp
-@$(CMD_MKOBJDIR)
@echo $(notdir $<)
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"

$(OBJDIR)/CameraDemo.o: ../../src/demos/CameraDemo.cpp
-@$(CMD_MKOBJDIR)
@echo $(notdir $<)
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"


+ 2
- 1
extras/the jucer/src/model/components/jucer_JucerComponentHandler.h View File

@@ -189,7 +189,8 @@ private:
void setFile (const File& newFile)
{
setJucerComponentFile (document, component,
newFile.getRelativePathFrom (document.getFile().getParentDirectory()));
newFile.getRelativePathFrom (document.getFile().getParentDirectory())
.replaceCharacter (T('\\'), T('/')));
}
const File getFile() const


+ 2
- 1
extras/the jucer/src/model/components/jucer_TabbedComponentHandler.h View File

@@ -999,7 +999,8 @@ private:
void setFile (const File& newFile)
{
document.perform (new JucerCompFileChangeAction (component, *document.getComponentLayout(), tabIndex,
newFile.getRelativePathFrom (document.getFile().getParentDirectory())),
newFile.getRelativePathFrom (document.getFile().getParentDirectory())
.replaceCharacter (T('\\'), T('/'))),
T("Change tab component file"));
}


+ 692
- 689
extras/the jucer/src/model/components/jucer_ViewportHandler.h
File diff suppressed because it is too large
View File


+ 5
- 1
extras/the jucer/src/model/jucer_BinaryResources.cpp View File

@@ -302,7 +302,11 @@ void BinaryResources::fillInGeneratedCode (GeneratedCode& code) const
const MemoryBlock& mb = resources[i]->data;
defs << "// JUCER_RESOURCE: " << name << ", " << mb.getSize()
<< ", \"" << File (resources[i]->originalFilename).getRelativePathFrom (code.document->getFile()) << "\"\n";
<< ", \""
<< File (resources[i]->originalFilename)
.getRelativePathFrom (code.document->getFile())
.replaceCharacter (T('\\'), T('/'))
<< "\"\n";
String line1;
line1 << "static const unsigned char resource_"


+ 42
- 774
juce_amalgamated.cpp View File

@@ -15826,7 +15826,8 @@ bool ThreadPool::removeJob (ThreadPoolJob* const job,
}

bool ThreadPool::removeAllJobs (const bool interruptRunningJobs,
const int timeOutMs)
const int timeOutMs,
const bool deleteInactiveJobs)
{
lock.enter();

@@ -15842,6 +15843,9 @@ bool ThreadPool::removeAllJobs (const bool interruptRunningJobs,
else
{
jobs.remove (i);

if (deleteInactiveJobs)
delete job;
}
}

@@ -30344,7 +30348,7 @@ bool AudioUnitPluginFormat::doesPluginStillExist (const PluginDescription& desc)

const FileSearchPath AudioUnitPluginFormat::getDefaultLocationsToSearch()
{
return FileSearchPath ("(Default AudioUnit locations)");
return FileSearchPath ("/(Default AudioUnit locations)");
}

#endif
@@ -96044,13 +96048,9 @@ local block_state deflate_rle(s, flush)
#endif
/********* End of inlined file: deflate.c *********/

/********* Start of inlined file: infback.c *********/
/*
This code is largely copied from inflate.c. Normally either infback.o or
inflate.o would be linked into an application--not both. The interface
with inffast.c is retained so that optimized assembler-coded versions of
inflate_fast() can be used with either inflate.c or infback.c.
*/
//#include "zlib/infback.c"

/********* Start of inlined file: inffast.c *********/

/********* Start of inlined file: inftrees.h *********/
/* WARNING: this file should *not* be used by applications. It is
@@ -96237,710 +96237,6 @@ struct inflate_state {
void inflate_fast OF((z_streamp strm, unsigned start));
/********* End of inlined file: inffast.h *********/

/* function prototypes */
local void fixedtables1 OF((struct inflate_state FAR *state));

/*
strm provides memory allocation functions in zalloc and zfree, or
Z_NULL to use the library memory allocation functions.

windowBits is in the range 8..15, and window is a user-supplied
window and output buffer that is 2**windowBits bytes.
*/
int ZEXPORT inflateBackInit_(z_streamp strm, int windowBits, unsigned char FAR *window, const char *version, int stream_size)
{
struct inflate_state FAR *state;

if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
stream_size != (int)(sizeof(z_stream)))
return Z_VERSION_ERROR;
if (strm == Z_NULL || window == Z_NULL ||
windowBits < 8 || windowBits > 15)
return Z_STREAM_ERROR;
strm->msg = Z_NULL; /* in case we return an error */
if (strm->zalloc == (alloc_func)0) {
strm->zalloc = zcalloc;
strm->opaque = (voidpf)0;
}
if (strm->zfree == (free_func)0) strm->zfree = zcfree;
state = (struct inflate_state FAR *)ZALLOC(strm, 1,
sizeof(struct inflate_state));
if (state == Z_NULL) return Z_MEM_ERROR;
Tracev((stderr, "inflate: allocated\n"));
strm->state = (struct internal_state FAR *)state;
state->dmax = 32768U;
state->wbits = windowBits;
state->wsize = 1U << windowBits;
state->window = window;
state->write = 0;
state->whave = 0;
return Z_OK;
}

/*
Return state with length and distance decoding tables and index sizes set to
fixed code decoding. Normally this returns fixed tables from inffixed.h.
If BUILDFIXED is defined, then instead this routine builds the tables the
first time it's called, and returns those tables the first time and
thereafter. This reduces the size of the code by about 2K bytes, in
exchange for a little execution time. However, BUILDFIXED should not be
used for threaded applications, since the rewriting of the tables and virgin
may not be thread-safe.
*/
local void fixedtables1 (struct inflate_state FAR *state)
{
#ifdef BUILDFIXED
static int virgin = 1;
static code *lenfix, *distfix;
static code fixed[544];

/* build fixed huffman tables if first call (may not be thread safe) */
if (virgin) {
unsigned sym, bits;
static code *next;

/* literal/length table */
sym = 0;
while (sym < 144) state->lens[sym++] = 8;
while (sym < 256) state->lens[sym++] = 9;
while (sym < 280) state->lens[sym++] = 7;
while (sym < 288) state->lens[sym++] = 8;
next = fixed;
lenfix = next;
bits = 9;
inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);

/* distance table */
sym = 0;
while (sym < 32) state->lens[sym++] = 5;
distfix = next;
bits = 5;
inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);

/* do this just once */
virgin = 0;
}
#else /* !BUILDFIXED */

/********* Start of inlined file: inffixed.h *********/
/* inffixed.h -- table for decoding fixed codes
* Generated automatically by makefixed().
*/

/* WARNING: this file should *not* be used by applications. It
is part of the implementation of the compression library and
is subject to change. Applications should only use zlib.h.
*/

static const code lenfix[512] = {
{96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48},
{0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128},
{0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59},
{0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176},
{0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20},
{21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100},
{0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8},
{0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216},
{18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76},
{0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114},
{0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2},
{0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148},
{20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42},
{0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86},
{0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15},
{0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236},
{16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62},
{0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142},
{0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31},
{0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162},
{0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25},
{0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105},
{0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4},
{0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202},
{17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69},
{0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125},
{0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13},
{0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195},
{19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35},
{0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91},
{0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19},
{0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246},
{16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55},
{0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135},
{0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99},
{0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190},
{0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16},
{20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96},
{0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6},
{0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209},
{17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72},
{0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116},
{0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4},
{0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153},
{20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44},
{0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82},
{0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11},
{0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229},
{16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58},
{0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138},
{0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51},
{0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173},
{0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30},
{0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110},
{0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0},
{0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195},
{16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65},
{0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121},
{0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9},
{0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258},
{19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37},
{0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93},
{0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23},
{0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251},
{16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51},
{0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131},
{0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67},
{0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183},
{0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23},
{64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103},
{0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9},
{0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223},
{18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79},
{0,9,255}
};

static const code distfix[32] = {
{16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025},
{21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193},
{18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385},
{19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577},
{16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073},
{22,5,193},{64,5,0}
};
/********* End of inlined file: inffixed.h *********/

#endif /* BUILDFIXED */
state->lencode = lenfix;
state->lenbits = 9;
state->distcode = distfix;
state->distbits = 5;
}

/* Macros for inflateBack(): */

/* Load returned state from inflate_fast() */
#define LOAD() \
do { \
put = strm->next_out; \
left = strm->avail_out; \
next = strm->next_in; \
have = strm->avail_in; \
hold = state->hold; \
bits = state->bits; \
} while (0)

/* Set state from registers for inflate_fast() */
#define RESTORE() \
do { \
strm->next_out = put; \
strm->avail_out = left; \
strm->next_in = next; \
strm->avail_in = have; \
state->hold = hold; \
state->bits = bits; \
} while (0)

/* Clear the input bit accumulator */
#define INITBITS() \
do { \
hold = 0; \
bits = 0; \
} while (0)

/* Assure that some input is available. If input is requested, but denied,
then return a Z_BUF_ERROR from inflateBack(). */
#define PULL() \
do { \
if (have == 0) { \
have = in(in_desc, &next); \
if (have == 0) { \
next = Z_NULL; \
ret = Z_BUF_ERROR; \
goto inf_leave; \
} \
} \
} while (0)

/* Get a byte of input into the bit accumulator, or return from inflateBack()
with an error if there is no input available. */
#define PULLBYTE() \
do { \
PULL(); \
have--; \
hold += (unsigned long)(*next++) << bits; \
bits += 8; \
} while (0)

/* Assure that there are at least n bits in the bit accumulator. If there is
not enough available input to do that, then return from inflateBack() with
an error. */
#define NEEDBITS(n) \
do { \
while (bits < (unsigned)(n)) \
PULLBYTE(); \
} while (0)

/* Return the low n bits of the bit accumulator (n < 16) */
#define BITS(n) \
((unsigned)hold & ((1U << (n)) - 1))

/* Remove n bits from the bit accumulator */
#define DROPBITS(n) \
do { \
hold >>= (n); \
bits -= (unsigned)(n); \
} while (0)

/* Remove zero to seven bits as needed to go to a byte boundary */
#define BYTEBITS() \
do { \
hold >>= bits & 7; \
bits -= bits & 7; \
} while (0)

/* Assure that some output space is available, by writing out the window
if it's full. If the write fails, return from inflateBack() with a
Z_BUF_ERROR. */
#define ROOM() \
do { \
if (left == 0) { \
put = state->window; \
left = state->wsize; \
state->whave = left; \
if (out(out_desc, put, left)) { \
ret = Z_BUF_ERROR; \
goto inf_leave; \
} \
} \
} while (0)

/*
strm provides the memory allocation functions and window buffer on input,
and provides information on the unused input on return. For Z_DATA_ERROR
returns, strm will also provide an error message.

in() and out() are the call-back input and output functions. When
inflateBack() needs more input, it calls in(). When inflateBack() has
filled the window with output, or when it completes with data in the
window, it calls out() to write out the data. The application must not
change the provided input until in() is called again or inflateBack()
returns. The application must not change the window/output buffer until
inflateBack() returns.

in() and out() are called with a descriptor parameter provided in the
inflateBack() call. This parameter can be a structure that provides the
information required to do the read or write, as well as accumulated
information on the input and output such as totals and check values.

in() should return zero on failure. out() should return non-zero on
failure. If either in() or out() fails, than inflateBack() returns a
Z_BUF_ERROR. strm->next_in can be checked for Z_NULL to see whether it
was in() or out() that caused in the error. Otherwise, inflateBack()
returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format
error, or Z_MEM_ERROR if it could not allocate memory for the state.
inflateBack() can also return Z_STREAM_ERROR if the input parameters
are not correct, i.e. strm is Z_NULL or the state was not initialized.
*/
int ZEXPORT inflateBack(z_streamp strm, in_func in, void FAR *in_desc, out_func out, void FAR *out_desc)
{
struct inflate_state FAR *state;
unsigned char FAR *next; /* next input */
unsigned char FAR *put; /* next output */
unsigned have, left; /* available input and output */
unsigned long hold; /* bit buffer */
unsigned bits; /* bits in bit buffer */
unsigned copy; /* number of stored or match bytes to copy */
unsigned char FAR *from; /* where to copy match bytes from */
code thisx; /* current decoding table entry */
code last; /* parent table entry */
unsigned len; /* length to copy for repeats, bits to drop */
int ret; /* return code */
static const unsigned short order[19] = /* permutation of code lengths */
{16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};

/* Check that the strm exists and that the state was initialized */
if (strm == Z_NULL || strm->state == Z_NULL)
return Z_STREAM_ERROR;
state = (struct inflate_state FAR *)strm->state;

/* Reset the state */
strm->msg = Z_NULL;
state->mode = TYPE;
state->last = 0;
state->whave = 0;
next = strm->next_in;
have = next != Z_NULL ? strm->avail_in : 0;
hold = 0;
bits = 0;
put = state->window;
left = state->wsize;

/* Inflate until end of block marked as last */
for (;;)
switch (state->mode) {
case TYPE:
/* determine and dispatch block type */
if (state->last) {
BYTEBITS();
state->mode = DONE;
break;
}
NEEDBITS(3);
state->last = BITS(1);
DROPBITS(1);
switch (BITS(2)) {
case 0: /* stored block */
Tracev((stderr, "inflate: stored block%s\n",
state->last ? " (last)" : ""));
state->mode = STORED;
break;
case 1: /* fixed block */
fixedtables1(state);
Tracev((stderr, "inflate: fixed codes block%s\n",
state->last ? " (last)" : ""));
state->mode = LEN; /* decode codes */
break;
case 2: /* dynamic block */
Tracev((stderr, "inflate: dynamic codes block%s\n",
state->last ? " (last)" : ""));
state->mode = TABLE;
break;
case 3:
strm->msg = (char *)"invalid block type";
state->mode = BAD;
}
DROPBITS(2);
break;

case STORED:
/* get and verify stored block length */
BYTEBITS(); /* go to byte boundary */
NEEDBITS(32);
if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
strm->msg = (char *)"invalid stored block lengths";
state->mode = BAD;
break;
}
state->length = (unsigned)hold & 0xffff;
Tracev((stderr, "inflate: stored length %u\n",
state->length));
INITBITS();

/* copy stored block from input to output */
while (state->length != 0) {
copy = state->length;
PULL();
ROOM();
if (copy > have) copy = have;
if (copy > left) copy = left;
zmemcpy(put, next, copy);
have -= copy;
next += copy;
left -= copy;
put += copy;
state->length -= copy;
}
Tracev((stderr, "inflate: stored end\n"));
state->mode = TYPE;
break;

case TABLE:
/* get dynamic table entries descriptor */
NEEDBITS(14);
state->nlen = BITS(5) + 257;
DROPBITS(5);
state->ndist = BITS(5) + 1;
DROPBITS(5);
state->ncode = BITS(4) + 4;
DROPBITS(4);
#ifndef PKZIP_BUG_WORKAROUND
if (state->nlen > 286 || state->ndist > 30) {
strm->msg = (char *)"too many length or distance symbols";
state->mode = BAD;
break;
}
#endif
Tracev((stderr, "inflate: table sizes ok\n"));

/* get code length code lengths (not a typo) */
state->have = 0;
while (state->have < state->ncode) {
NEEDBITS(3);
state->lens[order[state->have++]] = (unsigned short)BITS(3);
DROPBITS(3);
}
while (state->have < 19)
state->lens[order[state->have++]] = 0;
state->next = state->codes;
state->lencode = (code const FAR *)(state->next);
state->lenbits = 7;
ret = inflate_table(CODES, state->lens, 19, &(state->next),
&(state->lenbits), state->work);
if (ret) {
strm->msg = (char *)"invalid code lengths set";
state->mode = BAD;
break;
}
Tracev((stderr, "inflate: code lengths ok\n"));

/* get length and distance code code lengths */
state->have = 0;
while (state->have < state->nlen + state->ndist) {
for (;;) {
thisx = state->lencode[BITS(state->lenbits)];
if ((unsigned)(thisx.bits) <= bits) break;
PULLBYTE();
}
if (thisx.val < 16) {
NEEDBITS(thisx.bits);
DROPBITS(thisx.bits);
state->lens[state->have++] = thisx.val;
}
else {
if (thisx.val == 16) {
NEEDBITS(thisx.bits + 2);
DROPBITS(thisx.bits);
if (state->have == 0) {
strm->msg = (char *)"invalid bit length repeat";
state->mode = BAD;
break;
}
len = (unsigned)(state->lens[state->have - 1]);
copy = 3 + BITS(2);
DROPBITS(2);
}
else if (thisx.val == 17) {
NEEDBITS(thisx.bits + 3);
DROPBITS(thisx.bits);
len = 0;
copy = 3 + BITS(3);
DROPBITS(3);
}
else {
NEEDBITS(thisx.bits + 7);
DROPBITS(thisx.bits);
len = 0;
copy = 11 + BITS(7);
DROPBITS(7);
}
if (state->have + copy > state->nlen + state->ndist) {
strm->msg = (char *)"invalid bit length repeat";
state->mode = BAD;
break;
}
while (copy--)
state->lens[state->have++] = (unsigned short)len;
}
}

/* handle error breaks in while */
if (state->mode == BAD) break;

/* build code tables */
state->next = state->codes;
state->lencode = (code const FAR *)(state->next);
state->lenbits = 9;
ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
&(state->lenbits), state->work);
if (ret) {
strm->msg = (char *)"invalid literal/lengths set";
state->mode = BAD;
break;
}
state->distcode = (code const FAR *)(state->next);
state->distbits = 6;
ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
&(state->next), &(state->distbits), state->work);
if (ret) {
strm->msg = (char *)"invalid distances set";
state->mode = BAD;
break;
}
Tracev((stderr, "inflate: codes ok\n"));
state->mode = LEN;

case LEN:
/* use inflate_fast() if we have enough input and output */
if (have >= 6 && left >= 258) {
RESTORE();
if (state->whave < state->wsize)
state->whave = state->wsize - left;
inflate_fast(strm, state->wsize);
LOAD();
break;
}

/* get a literal, length, or end-of-block code */
for (;;) {
thisx = state->lencode[BITS(state->lenbits)];
if ((unsigned)(thisx.bits) <= bits) break;
PULLBYTE();
}
if (thisx.op && (thisx.op & 0xf0) == 0) {
last = thisx;
for (;;) {
thisx = state->lencode[last.val +
(BITS(last.bits + last.op) >> last.bits)];
if ((unsigned)(last.bits + thisx.bits) <= bits) break;
PULLBYTE();
}
DROPBITS(last.bits);
}
DROPBITS(thisx.bits);
state->length = (unsigned)thisx.val;

/* process literal */
if (thisx.op == 0) {
Tracevv((stderr, thisx.val >= 0x20 && thisx.val < 0x7f ?
"inflate: literal '%c'\n" :
"inflate: literal 0x%02x\n", thisx.val));
ROOM();
*put++ = (unsigned char)(state->length);
left--;
state->mode = LEN;
break;
}

/* process end of block */
if (thisx.op & 32) {
Tracevv((stderr, "inflate: end of block\n"));
state->mode = TYPE;
break;
}

/* invalid code */
if (thisx.op & 64) {
strm->msg = (char *)"invalid literal/length code";
state->mode = BAD;
break;
}

/* length code -- get extra bits, if any */
state->extra = (unsigned)(thisx.op) & 15;
if (state->extra != 0) {
NEEDBITS(state->extra);
state->length += BITS(state->extra);
DROPBITS(state->extra);
}
Tracevv((stderr, "inflate: length %u\n", state->length));

/* get distance code */
for (;;) {
thisx = state->distcode[BITS(state->distbits)];
if ((unsigned)(thisx.bits) <= bits) break;
PULLBYTE();
}
if ((thisx.op & 0xf0) == 0) {
last = thisx;
for (;;) {
thisx = state->distcode[last.val +
(BITS(last.bits + last.op) >> last.bits)];
if ((unsigned)(last.bits + thisx.bits) <= bits) break;
PULLBYTE();
}
DROPBITS(last.bits);
}
DROPBITS(thisx.bits);
if (thisx.op & 64) {
strm->msg = (char *)"invalid distance code";
state->mode = BAD;
break;
}
state->offset = (unsigned)thisx.val;

/* get distance extra bits, if any */
state->extra = (unsigned)(thisx.op) & 15;
if (state->extra != 0) {
NEEDBITS(state->extra);
state->offset += BITS(state->extra);
DROPBITS(state->extra);
}
if (state->offset > state->wsize - (state->whave < state->wsize ?
left : 0)) {
strm->msg = (char *)"invalid distance too far back";
state->mode = BAD;
break;
}
Tracevv((stderr, "inflate: distance %u\n", state->offset));

/* copy match from window to output */
do {
ROOM();
copy = state->wsize - state->offset;
if (copy < left) {
from = put + copy;
copy = left - copy;
}
else {
from = put - state->offset;
copy = left;
}
if (copy > state->length) copy = state->length;
state->length -= copy;
left -= copy;
do {
*put++ = *from++;
} while (--copy);
} while (state->length != 0);
break;

case DONE:
/* inflate stream terminated properly -- write leftover output */
ret = Z_STREAM_END;
if (left < state->wsize) {
if (out(out_desc, state->window, state->wsize - left))
ret = Z_BUF_ERROR;
}
goto inf_leave;

case BAD:
ret = Z_DATA_ERROR;
goto inf_leave;

default: /* can't happen, but makes compilers happy */
ret = Z_STREAM_ERROR;
goto inf_leave;
}

/* Return unused input */
inf_leave:
strm->next_in = next;
strm->avail_in = have;
return ret;
}

int ZEXPORT inflateBackEnd (z_streamp strm)
{
if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
return Z_STREAM_ERROR;
ZFREE(strm, strm->state);
strm->state = Z_NULL;
Tracev((stderr, "inflate: end\n"));
return Z_OK;
}
/********* End of inlined file: infback.c *********/

/********* Start of inlined file: inffast.c *********/

/********* Start of inlined file: inffast.h *********/
/* WARNING: this file should *not* be used by applications. It is
part of the implementation of the compression library and is
subject to change. Applications should only use zlib.h.
*/

void inflate_fast OF((z_streamp strm, unsigned start));
/********* End of inlined file: inffast.h *********/

#ifndef ASMINF

/* Allow machine dependent optimization for post-increment or pre-increment.
@@ -100332,62 +99628,7 @@ local void copy_block(deflate_state *s,
}
/********* End of inlined file: trees.c *********/

/********* Start of inlined file: uncompr.c *********/
/* @(#) $Id: uncompr.c,v 1.1 2007/06/07 17:54:37 jules_rms Exp $ */

#define ZLIB_INTERNAL

/* ===========================================================================
Decompresses the source buffer into the destination buffer. sourceLen is
the byte length of the source buffer. Upon entry, destLen is the total
size of the destination buffer, which must be large enough to hold the
entire uncompressed data. (The size of the uncompressed data must have
been saved previously by the compressor and transmitted to the decompressor
by some mechanism outside the scope of this compression library.)
Upon exit, destLen is the actual size of the compressed buffer.
This function can be used to decompress a whole file at once if the
input file is mmap'ed.

uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
enough memory, Z_BUF_ERROR if there was not enough room in the output
buffer, or Z_DATA_ERROR if the input data was corrupted.
*/
int ZEXPORT uncompress (Bytef *dest,
uLongf *destLen,
const Bytef *source,
uLong sourceLen)
{
z_stream stream;
int err;

stream.next_in = (Bytef*)source;
stream.avail_in = (uInt)sourceLen;
/* Check for source > 64K on 16-bit machine: */
if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;

stream.next_out = dest;
stream.avail_out = (uInt)*destLen;
if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;

stream.zalloc = (alloc_func)0;
stream.zfree = (free_func)0;

err = inflateInit(&stream);
if (err != Z_OK) return err;

err = inflate(&stream, Z_FINISH);
if (err != Z_STREAM_END) {
inflateEnd(&stream);
if (err == Z_NEED_DICT || (err == Z_BUF_ERROR && stream.avail_in == 0))
return Z_DATA_ERROR;
return err;
}
*destLen = stream.total_out;

err = inflateEnd(&stream);
return err;
}
/********* End of inlined file: uncompr.c *********/
//#include "zlib/uncompr.c"

/********* Start of inlined file: zutil.c *********/
/* @(#) $Id: zutil.c,v 1.1 2007/06/07 17:54:37 jules_rms Exp $ */
@@ -262226,7 +261467,8 @@ public:
snd_seq_ev_set_subs (&event);
snd_seq_ev_set_direct (&event);

snd_seq_event_output_direct (seqHandle, &event);
snd_seq_event_output (seqHandle, &event);
snd_seq_drain_output (seqHandle);
}

juce_UseDebuggingNewOperator
@@ -266089,9 +265331,23 @@ BEGIN_JUCE_NAMESPACE

#undef Point

/** This suffix is used for naming all Obj-C classes that are used inside juce.

Because of the flat naming structure used by Obj-C, you can get horrible situations where
two DLLs are loaded into a host, each of which uses classes with the same names, and these get
cross-linked so that when you make a call to a class that you thought was private, it ends up
actually calling into a similarly named class in the other module's address space.

By changing this macro to a unique value, you ensure that all the obj-C classes in your app
have unique names, and should avoid this problem.

If you're using the amalgamated version, you can just set this macro to something unique before
you include juce_amalgamated.cpp.
*/
#ifndef JUCE_ObjCExtraSuffix
#define JUCE_ObjCExtraSuffix 2
#define JUCE_ObjCExtraSuffix 3
#endif

#define appendMacro1(a, b, c, d) a ## _ ## b ## _ ## c ## _ ## d
#define appendMacro2(a, b, c, d) appendMacro1(a, b, c, d)
#define MakeObjCClassName(rootName) appendMacro2 (rootName, JUCE_MAJOR_VERSION, JUCE_MINOR_VERSION, JUCE_ObjCExtraSuffix)
@@ -270072,16 +269328,16 @@ class NSViewComponentInternal : public ComponentMovementWatcher
bool wasShowing;

public:
NSView* view;
NSView* const view;

NSViewComponentInternal (NSView* view_, Component* const owner_)
NSViewComponentInternal (NSView* const view_, Component* const owner_)
: ComponentMovementWatcher (owner_),
owner (owner_),
currentPeer (0),
wasShowing (false),
view (view_)
{
[view retain];
[view_ retain];

if (owner_->isShowing())
componentPeerChanged();
@@ -270093,6 +269349,18 @@ public:
[view release];
}

void componentMovedOrResized (Component& comp, bool wasMoved, bool wasResized)
{
ComponentMovementWatcher::componentMovedOrResized (comp, wasMoved, wasResized);

// The ComponentMovementWatcher version of this method avoids calling
// us when the top-level comp is resized, but for an NSView we need to know this
// because with inverted co-ords, we need to update the position even if the
// top-left pos hasn't changed
if (comp.isOnDesktop() && wasResized)
componentMovedOrResized (wasMoved, wasResized);
}

void componentMovedOrResized (bool /*wasMoved*/, bool /*wasResized*/)
{
Component* const topComp = owner->getTopLevelComponent();


+ 27
- 2
juce_amalgamated.h View File

@@ -66,7 +66,7 @@
See also SystemStats::getJUCEVersion() for a string version.
*/
#define JUCE_MAJOR_VERSION 1
#define JUCE_MINOR_VERSION 46
#define JUCE_MINOR_VERSION 50

/** Current Juce version number.

@@ -10115,6 +10115,26 @@ public:
lock.exit();
}

/** Inserts or replaces an object in the array, assuming it is sorted.

This is similar to addSorted, but if a matching element already exists, then it will be
replaced by the new one, rather than the new one being added as well.
*/
template <class ElementComparator>
void addOrReplaceSorted (ElementComparator& comparator,
ObjectClass* newObject) throw()
{
lock.enter();
const int index = findInsertIndexInSortedArray (comparator, this->elements, newObject, 0, numUsed);

if (index > 0 && comparator.compareElements (newObject, this->elements [index - 1]) == 0)
set (index - 1, newObject); // replace an existing object that matches
else
insert (index, newObject); // no match, so insert the new one

lock.exit();
}

/** Removes an object from the array.

This will remove the object at a given index and move back all the
@@ -15095,11 +15115,16 @@ public:
methods called to try to interrupt them
@param timeOutMilliseconds the length of time this method should wait for all the jobs to finish
before giving up and returning false
@param deleteInactiveJobs if true, any jobs that aren't currently running will be deleted. If false,
they will simply be removed from the pool. Jobs that are already running when
this method is called can choose whether they should be deleted by
returning jobHasFinishedAndShouldBeDeleted from their runJob() method.
@returns true if all jobs are successfully stopped and removed; false if the timeout period
expires while waiting for them to stop
*/
bool removeAllJobs (const bool interruptRunningJobs,
const int timeOutMilliseconds);
const int timeOutMilliseconds,
const bool deleteInactiveJobs = false);

/** Returns the number of jobs currently running or queued.
*/


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

@@ -1535,7 +1535,7 @@ bool AudioUnitPluginFormat::doesPluginStillExist (const PluginDescription& desc)
const FileSearchPath AudioUnitPluginFormat::getDefaultLocationsToSearch()
{
return FileSearchPath ("(Default AudioUnit locations)");
return FileSearchPath ("/(Default AudioUnit locations)");
}
#endif


+ 1
- 1
src/juce_core/basics/juce_StandardHeader.h View File

@@ -38,7 +38,7 @@
See also SystemStats::getJUCEVersion() for a string version.
*/
#define JUCE_MAJOR_VERSION 1
#define JUCE_MINOR_VERSION 46
#define JUCE_MINOR_VERSION 50
/** Current Juce version number.


+ 20
- 0
src/juce_core/containers/juce_ReferenceCountedArray.h View File

@@ -442,6 +442,26 @@ public:
lock.exit();
}
/** Inserts or replaces an object in the array, assuming it is sorted.
This is similar to addSorted, but if a matching element already exists, then it will be
replaced by the new one, rather than the new one being added as well.
*/
template <class ElementComparator>
void addOrReplaceSorted (ElementComparator& comparator,
ObjectClass* newObject) throw()
{
lock.enter();
const int index = findInsertIndexInSortedArray (comparator, this->elements, newObject, 0, numUsed);
if (index > 0 && comparator.compareElements (newObject, this->elements [index - 1]) == 0)
set (index - 1, newObject); // replace an existing object that matches
else
insert (index, newObject); // no match, so insert the new one
lock.exit();
}
//==============================================================================
/** Removes an object from the array.


+ 2
- 3
src/juce_core/io/streams/juce_GZIPDecompressorInputStream.cpp View File

@@ -46,14 +46,13 @@ namespace zlibNamespace
#define ZLIB_INTERNAL
#define NO_DUMMY_DECL
#include "zlib/zlib.h"
#include "zlib/adler32.c"
#include "zlib/compress.c"
#undef DO1
#undef DO8
#include "zlib/crc32.c"
#include "zlib/deflate.c"
#include "zlib/infback.c"
//#include "zlib/infback.c"
#include "zlib/inffast.c"
#undef PULLBYTE
#undef LOAD
@@ -65,7 +64,7 @@ namespace zlibNamespace
#include "zlib/inflate.c"
#include "zlib/inftrees.c"
#include "zlib/trees.c"
#include "zlib/uncompr.c"
//#include "zlib/uncompr.c"
#include "zlib/zutil.c"
#undef Byte
}


+ 5
- 1
src/juce_core/threads/juce_ThreadPool.cpp View File

@@ -264,7 +264,8 @@ bool ThreadPool::removeJob (ThreadPoolJob* const job,
}
bool ThreadPool::removeAllJobs (const bool interruptRunningJobs,
const int timeOutMs)
const int timeOutMs,
const bool deleteInactiveJobs)
{
lock.enter();
@@ -280,6 +281,9 @@ bool ThreadPool::removeAllJobs (const bool interruptRunningJobs,
else
{
jobs.remove (i);
if (deleteInactiveJobs)
delete job;
}
}


+ 6
- 1
src/juce_core/threads/juce_ThreadPool.h View File

@@ -218,11 +218,16 @@ public:
methods called to try to interrupt them
@param timeOutMilliseconds the length of time this method should wait for all the jobs to finish
before giving up and returning false
@param deleteInactiveJobs if true, any jobs that aren't currently running will be deleted. If false,
they will simply be removed from the pool. Jobs that are already running when
this method is called can choose whether they should be deleted by
returning jobHasFinishedAndShouldBeDeleted from their runJob() method.
@returns true if all jobs are successfully stopped and removed; false if the timeout period
expires while waiting for them to stop
*/
bool removeAllJobs (const bool interruptRunningJobs,
const int timeOutMilliseconds);
const int timeOutMilliseconds,
const bool deleteInactiveJobs = false);
/** Returns the number of jobs currently running or queued.
*/


Loading…
Cancel
Save