you can use the standalone wrapper which uses alsa, or use this (which uses jack):
juce_JackAudioFilterStreamer.h
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-6 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.
==============================================================================
*/
#ifndef __JUCE_JACKAUDIOFILTERSTREAMER_H__
#define __JUCE_JACKAUDIOFILTERSTREAMER_H__
#include "../../juce_AudioFilterBase.h"
#include "jack/jack.h"
#include "jack/transport.h"
//==============================================================================
/**
A class that wraps an AudioFilterBase as an JackAudioConnectionKit client,
so its output can be streamed directly to/from some jack audio and midi
inputs and outputs.
To use it, just create an instance of this for your filter, and that's it.
@code
DemoFilter* myFilter = new DemoFilter ();
JackAudioFilterStreamer* myStreamer = new JackAudioFilterStreamer ();
myStreamer->setFilter (myFilter, true);
@endcode
*/
class JackAudioFilterStreamer : public Timer,
public MidiInputCallback,
public AudioFilterBase::FilterNativeCallbacks
{
public:
//==============================================================================
JackAudioFilterStreamer ();
~JackAudioFilterStreamer();
//==============================================================================
/**
Sets on the fly a new filter to be runned by this streamer
It is useful if you need to change the filter being played at runtime, and
this will take care of deactivating the old JACK client and create a new
one based on the filter you passed to it.
@param filterToUse the new filter to stream
@param checkForServer starts immediately checking if a jack
server is present
*/
void setFilter (AudioFilterBase* filterToUse, bool checkForServer = true);
/**
Calling this after you have created a filter streamer will start checking
for some JACK server daemon in background. If a server is found and running,
then your client filter will be activated.
@see activateClient
*/
void startCheckForServer ();
//==============================================================================
/**
Will suspend the jack thread temporarily, just in case you need to stop
the jack audio thread from outside the plugin
*/
void suspendProcessing (const bool suspend);
//==============================================================================
/**
Try to make this client grab main JACK transport
If you want to control transport from your filter, you should try to
grab it by using this function.
@param conditionalGrab if true, you can grab the transport ONLY if
no other jack applications have grabbed already.
if false, you are forcing grab of the transport
@return true if your client grabbed transport correctly
*/
bool grabTransport (const bool conditionalGrab = true);
/**
Release this client grabbing the main JACK transport
This works only if you already grabbed the transport over all the other
JACK clients.
*/
void releaseTransport ();
/**
Play the transport
This will call the server to notify all the other attached clients that
are listening for transport states. This only works if you already taken
the transport.
*/
void playTransport ();
/**
Stop main transport
This will call the server to notify all the other attached clients that
are listening for transport states. This only works if you already taken
the transport.
*/
void stopTransport ();
/**
Seek the transport to a specified frame number
This will call the server to notify all the other attached clients that
are listening for transport states. This only works if you already taken
the transport.
*/
void seekTransportToFrame (const int frameToSeekAt);
/**
Set JACK main tempo in beats per seconds
*/
void setTempo (const double bpmToSet);
/**
Set JACK sync timeout in seconds
*/
void setSyncTimeout (const double secondsTimeout);
//==============================================================================
/**
Create the editor using createEditorInternal of the AudioFilterBase.
This is needed cause we need to simulate to be a HOST application that
is trying to create the window for the Editor. And since a lot of
properties and useful functions are private in the AudioFilterBase, then
we need to wrap the creation of the editor with this function.
@see AudioFilterBase::createEditor()
*/
AudioFilterEditor* createFilterEditor ();
//==============================================================================
/** @internal */
bool activateClient ();
/** @internal */
void deactivateClient ();
/** @internal */
void closeClient ();
/** @internal */
void audioPluginAboutToStart (double sampleRate, int numSamplesPerBlock);
/** @internal */
void audioPluginStopped();
/** @internal */
void audioPluginIOCallback (int numSamples);
/** @internal */
void sampleRateCallback (int newSampleRate);
/** @internal */
void blockSizeCallback (int newBlockSize);
/** @internal */
void handleIncomingMidiMessage (MidiInput* source, const MidiMessage& message);
/** @internal */
bool getCurrentPositionInfo (AudioFilterBase::CurrentPositionInfo& info);
/** @internal */
void informHostOfParameterChange (int index, float newValue);
/** @internal */
void timerCallback ();
/** @internal */
jack_client_t* getJackClient () { return client; }
//==============================================================================
juce_UseDebuggingNewOperator
private:
//==============================================================================
AudioFilterBase* filter;
AudioFilterEditor* editor;
bool isPlaying;
double sampleRate;
int blockSize;
MidiMessageCollector midiCollector;
float* outChans [128];
float* inChans [128];
MidiInput* midiInput;
MidiOutput* midiOutput;
jack_client_t *client;
VoidArray inputPorts;
VoidArray outputPorts;
double beatsPerMinute;
double ticksPerBeat;
float beatsPerBar; // numerator
float beatType; // denominator
bool holdTransport;
bool timeHasChanged; // volatile ?
};
#endif
juce_JackAudioFilterStreamer.cpp
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-6 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_JackAudioFilterStreamer.h"
#include "JucePluginCharacteristics.h"
//==============================================================================
static void juce_internalJackThreadInitCallback (void *arg);
static void juce_internalJackOnShutdownCallback (void *arg);
static int juce_internalJackBufferSizeCallback (jack_nframes_t nframes, void *arg);
static int juce_internalJackSampleRateCallback (jack_nframes_t nframes, void *arg);
static void juce_internalJackPortRegistrationCallback (jack_port_id_t port, int, void *arg);
static void juce_internalJackFreewheelCallback (int starting, void *arg);
static int juce_internalJackGraphOrderCallback (void *arg);
static int juce_internalJackProcessCallback (jack_nframes_t nframes, void* arg);
static int juce_internalJackXRunCallback (void *arg);
static int juce_internalJackSyncCallback (jack_transport_state_t state, jack_position_t *pos, void *arg);
static void juce_internalJackTimebaseCallback (jack_transport_state_t state,
jack_nframes_t nframes,
jack_position_t *pos,
int new_pos,
void *arg);
//==============================================================================
JackAudioFilterStreamer::JackAudioFilterStreamer ()
: filter (0),
editor (0),
isPlaying (false),
sampleRate (0),
blockSize (0),
midiInput (0),
midiOutput (0),
client (0),
beatsPerMinute (120.0),
holdTransport (false),
timeHasChanged (false)
{
}
JackAudioFilterStreamer::~JackAudioFilterStreamer()
{
setFilter (0, false);
closeClient ();
}
//==============================================================================
void JackAudioFilterStreamer::setFilter (AudioFilterBase* filterToUse, bool checkForServer)
{
audioPluginStopped ();
deactivateClient ();
if (filter && editor != 0)
filter->editorBeingDeleted (editor);
filter = filterToUse;
if (filter)
{
filter->initialiseInternal (this);
if (checkForServer)
startCheckForServer ();
}
}
//==============================================================================
bool JackAudioFilterStreamer::activateClient ()
{
jassert (filter); // you should have already attached a filter,
// if not, how would this streamer works ?
sampleRate = 0;
blockSize = 0;
// create the jack client
jack_status_t status;
client = jack_client_open (JucePlugin_Name, JackNoStartServer, &status);
if (client == 0)
return false;
// setup callbacks
jack_set_thread_init_callback (client, juce_internalJackThreadInitCallback, this);
jack_on_shutdown (client, juce_internalJackOnShutdownCallback, this);
// jack_set_buffer_size_callback (client, juce_internalJackBufferSizeCallback, this);
// jack_set_sample_rate_callback (client, juce_internalJackSampleRateCallback, this);
// jack_set_port_registration_callback (client, juce_internalJackPortRegistrationCallback, this);
// jack_set_graph_order_callback (client, juce_internalJackGraphOrderCallback, this);
// jack_set_freewheel_callback (client, juce_internalJackFreewheelCallback, this);
jack_set_process_callback (client, juce_internalJackProcessCallback, this);
jack_set_xrun_callback (client, juce_internalJackXRunCallback, this);
// jack_set_sync_callback (client, juce_internalJackSyncCallback, this);
#ifdef JUCE_DEBUG
// jack_set_error_function (default_jack_error_callback);
#endif
jassert (JucePlugin_MaxNumInputChannels <= 128); // your filter have more input channels
// than the maximum allowed to be handle by this streamer !
jassert (JucePlugin_MaxNumOutputChannels <= 128); // your filter have more input channels
// than the maximum allowed to be handle by this streamer !
// register input ports
for (int i = 0; i < JucePlugin_MaxNumInputChannels; i++)
{
String inputName;
inputName << "in_" << (i+1);
jack_port_t* input =
jack_port_register (client, (const char*) inputName, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
inputPorts.add (input);
}
// register output ports
for (int i = 0; i < JucePlugin_MaxNumOutputChannels; i++)
{
String outputName;
outputName << "out_" << (i+1);
jack_port_t* output =
jack_port_register (client, (const char*) outputName, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
jack_port_set_latency (output, JucePlugin_Latency);
outputPorts.add (output);
}
// create midi devices
#if JucePlugin_WantsMidiInput
if (midiInput)
midiInput->stop ();
deleteAndZero (midiInput);
midiInput = MidiInput::createNewDevice (JucePlugin_Name, this);
if (midiInput)
midiInput->start ();
#endif
#if JucePlugin_ProducesMidiOutput
deleteAndZero (midiOutput);
midiOutput = MidiOutput::createNewDevice (JucePlugin_Name);
#endif
// reset midi collector before we start
midiCollector.reset (jack_get_sample_rate (client));
// update samplerate and block size before we just activate the client
audioPluginAboutToStart ((double) jack_get_sample_rate (client),
(int) jack_get_buffer_size (client));
// activate jack client
jack_activate (client);
return true;
}
void JackAudioFilterStreamer::deactivateClient ()
{
if (client)
{
jack_deactivate (client);
client = 0;
}
#if JucePlugin_WantsMidiInput
if (midiInput)
midiInput->stop ();
deleteAndZero (midiInput);
#endif
#if JucePlugin_ProducesMidiOutput
deleteAndZero (midiOutput);
#endif
}
void JackAudioFilterStreamer::closeClient ()
{
if (client)
{
jack_deactivate (client);
jack_client_close (client);
client = 0;
}
#if JucePlugin_WantsMidiInput
if (midiInput)
midiInput->stop ();
deleteAndZero (midiInput);
#endif
#if JucePlugin_ProducesMidiOutput
deleteAndZero (midiOutput);
#endif
}
//==============================================================================
void JackAudioFilterStreamer::audioPluginIOCallback (int numSamples)
{
// jassert (filter); // you should have already attached a filter,
// if not, how would this streamer works ?
if (filter == 0 || numSamples <= 0)
return;
MidiBuffer midiBuffer;
#if JucePlugin_WantsMidiInput
midiCollector.removeNextBlockOfMessages (midiBuffer, numSamples);
#endif
int i;
const int numOutsWanted = JucePlugin_MaxNumOutputChannels;
const int numInsWanted = JucePlugin_MaxNumInputChannels;
for (i = 0; i < numInsWanted; ++i)
{
jack_default_audio_sample_t *in =
(jack_default_audio_sample_t *) jack_port_get_buffer (
(jack_port_t*) inputPorts.getUnchecked(i), numSamples);
if (in != 0)
inChans [i] = in;
}
for (i = 0; i < numOutsWanted; ++i)
{
jack_default_audio_sample_t *out =
(jack_default_audio_sample_t *) jack_port_get_buffer (
(jack_port_t*) outputPorts.getUnchecked(i), numSamples);
if (out != 0)
outChans [i] = out;
}
AudioSampleBuffer input (inChans, numInsWanted, numSamples);
AudioSampleBuffer output (outChans, numOutsWanted, numSamples);
{
const ScopedLock sl (filter->getCallbackLock());
if (filter->suspended)
output.clear();
else
filter->processBlock (input, output, false, midiBuffer);
}
#if JucePlugin_ProducesMidiOutput
int samplePos = 0;
MidiMessage message (0,0);
MidiBuffer::Iterator eventIterator (midiBuffer);
while (eventIterator.getNextEvent (message, samplePos))
midiOutput->sendMessageNow (message);
#endif
}
void JackAudioFilterStreamer::sampleRateCallback (int newSampleRate)
{
sampleRate = (double) newSampleRate;
// audioPluginStopped ();
// if (sampleRate != 0 && blockSize != 0)
// audioPluginAboutToStart (sampleRate, blockSize);
}
void JackAudioFilterStreamer::blockSizeCallback (int newBlockSize)
{
blockSize = newBlockSize;
// audioPluginStopped ();
// if (sampleRate != 0 && blockSize != 0)
// audioPluginAboutToStart (sampleRate, blockSize);
}
void JackAudioFilterStreamer::audioPluginAboutToStart (double newSampleRate,
int newBlockSize)
{
sampleRate = newSampleRate;
blockSize = newBlockSize;
if (filter && ! isPlaying)
{
isPlaying = true;
midiCollector.reset (sampleRate);
filter->prepareToPlay (sampleRate, blockSize);
DBG (String (sampleRate, 2));
DBG (String (blockSize));
}
}
void JackAudioFilterStreamer::audioPluginStopped()
{
if (filter && isPlaying)
{
isPlaying = false;
filter->releaseResources();
midiCollector.reset (sampleRate);
}
}
//==============================================================================
void JackAudioFilterStreamer::handleIncomingMidiMessage (MidiInput* source, const MidiMessage& message)
{
#if JucePlugin_WantsMidiInput
midiCollector.addMessageToQueue (message);
#endif
}
bool JackAudioFilterStreamer::getCurrentPositionInfo (AudioFilterBase::CurrentPositionInfo& info)
{
jack_position_t pos;
jack_transport_state_t state = jack_transport_query (client, &pos);
/*
jack_nframes_t frame_rate;
jack_time_t usecs;
jack_transport_bits_t valid;
jack_transport_state_t transport_state;
jack_nframes_t frame;
jack_nframes_t loop_start;
jack_nframes_t loop_end;
long smpte_offset;
float smpte_frame_rate;
int bar;
int beat;
int tick;
double bar_start_tick;
float beats_per_bar;
float beat_type;
double ticks_per_beat;
double beats_per_minute;
*/
if ((pos.valid & JACK_POSITION_MASK) &&
pos.beat_type > 0 && pos.beats_per_minute > 0)
{
info.bpm = pos.beats_per_minute;
info.timeSigNumerator = roundFloatToInt (pos.beats_per_bar);
info.timeSigDenominator = roundFloatToInt (pos.beat_type);
info.timeInSeconds = pos.frame_time;
info.editOriginTime = 1; // @XXX;
info.ppqPosition = 1; // @XXX;
info.ppqPositionOfLastBarStart = 1; // @XXX;
info.frameRate = AudioFilterBase::CurrentPositionInfo::fpsUnknown;
info.isPlaying = (state & JackTransportRolling);
info.isRecording = false;
return true;
}
return false;
}
void JackAudioFilterStreamer::informHostOfParameterChange (int index, float newValue)
{
jassert (filter); // you should have already attached a filter,
// if not, how would this streamer works ?
filter->setParameter (index, newValue);
}
//==============================================================================
void JackAudioFilterStreamer::startCheckForServer ()
{
startTimer (1000);
}
void JackAudioFilterStreamer::timerCallback ()
{
if (activateClient())
{
stopTimer();
}
}
//==============================================================================
bool JackAudioFilterStreamer::grabTransport (const bool conditionalGrab)
{
if (client)
{
return (holdTransport = (jack_set_timebase_callback (client,
(conditionalGrab ? 1 : 0),
juce_internalJackTimebaseCallback,
this) == 0));
}
else
{
return false;
}
}
void JackAudioFilterStreamer::releaseTransport ()
{
if (client && holdTransport)
jack_release_timebase(client);
}
//==============================================================================
void JackAudioFilterStreamer::playTransport ()
{
if (client && holdTransport)
jack_transport_start(client);
}
void JackAudioFilterStreamer::stopTransport ()
{
if (client && holdTransport)
jack_transport_stop(client);
}
void JackAudioFilterStreamer::seekTransportToFrame (const int frameToSeekAt)
{
if (client && holdTransport)
{
jack_nframes_t frameNumber = 0;
if (frameToSeekAt >= 0)
frameNumber = frameToSeekAt;
jack_transport_locate (client, frameNumber);
}
}
//==============================================================================
void JackAudioFilterStreamer::setTempo (const double bpmToSet)
{
if (bpmToSet > 0.0)
{
if (beatsPerMinute != bpmToSet)
{
beatsPerMinute = bpmToSet;
timeHasChanged = true;
}
}
}
void JackAudioFilterStreamer::setSyncTimeout (const double secondsTimeout)
{
if (client && holdTransport)
{
double timeout = 2.0;
if (secondsTimeout > 0)
timeout = secondsTimeout;
jack_set_sync_timeout (client, (jack_time_t) (timeout * 1000000));
}
}
//==============================================================================
void JackAudioFilterStreamer::suspendProcessing (const bool suspend)
{
if (filter)
{
filter->suspendProcessing (suspend);
}
}
//==============================================================================
AudioFilterEditor* JackAudioFilterStreamer::createFilterEditor ()
{
jassert (editor == 0); // can't actually call this twice !
editor = (filter != 0) ? filter->createEditorIfNeeded() : 0;
return editor;
}
//==============================================================================
static void juce_internalJackThreadInitCallback (void *arg)
{
DBG ("jack started");
/*
JackAudioFilterStreamer* filter = (JackAudioFilterStreamer*) arg;
filter->audioPluginAboutToStart ((double) jack_get_sample_rate (filter->getJackClient()),
(int) jack_get_buffer_size (filter->getJackClient()));
*/
}
static void juce_internalJackOnShutdownCallback (void* arg)
{
DBG ("jack shutdown");
JackAudioFilterStreamer* filter = (JackAudioFilterStreamer*) arg;
filter->audioPluginStopped ();
filter->deactivateClient ();
filter->startCheckForServer ();
}
static int juce_internalJackBufferSizeCallback (jack_nframes_t nframes, void* arg)
{
DBG ("jack blocksize changed");
JackAudioFilterStreamer* filter = (JackAudioFilterStreamer*) arg;
filter->blockSizeCallback (nframes);
return 0;
}
static int juce_internalJackSampleRateCallback (jack_nframes_t nframes, void* arg)
{
DBG ("jack samplerate changed");
JackAudioFilterStreamer* filter = (JackAudioFilterStreamer*) arg;
filter->sampleRateCallback (nframes);
return 0;
}
static void juce_internalJackPortRegistrationCallback (jack_port_id_t port, int, void* arg)
{
// JackAudioFilterStreamer* filterStreamer = (JackAudioFilterStreamer*) arg;
}
static void juce_internalJackFreewheelCallback (int starting, void *arg)
{
// DBG ("server freewheel changed");
}
static int juce_internalJackGraphOrderCallback (void *arg)
{
// JackAudioFilterStreamer* filterStreamer = (JackAudioFilterStreamer*) arg;
// filterStreamer->audioPluginStopped ();
// printf ("graph reorder\n");
return 0;
}
static int juce_internalJackProcessCallback (jack_nframes_t nframes, void* arg)
{
((JackAudioFilterStreamer*) arg)->audioPluginIOCallback (nframes);
return 0;
}
static int juce_internalJackXRunCallback (void *arg)
{
DBG ("jack xrun");
return 0;
}
static int juce_internalJackSyncCallback (jack_transport_state_t state, jack_position_t *pos, void *arg)
{
/*
printf ("sync: %d:%d %d %3.1f/%3.1f %f %f\n",
pos->beat, pos->bar, pos->tick, pos->beats_per_bar, pos->beat_type, pos->ticks_per_beat, pos->beats_per_minute );
*/
return 0;
}
static float time_beats_per_bar = 4.0;
static float time_beat_type = 4.0;
static double time_ticks_per_beat = 1920.0;
static double time_beats_per_minute = 120.0;
volatile int time_reset = 0;
static void juce_internalJackTimebaseCallback (jack_transport_state_t state,
jack_nframes_t nframes,
jack_position_t *pos,
int new_pos,
void *arg)
{
double min; // minutes since frame 0
long abs_tick; // ticks since frame 0
long abs_beat; // beats since frame 0
// JackAudioFilterStreamer* filterStreamer = (JackAudioFilterStreamer*) arg;
if (new_pos || time_reset)
{
pos->valid = JackPositionBBT;
pos->beats_per_bar = time_beats_per_bar;
pos->beat_type = time_beat_type;
pos->ticks_per_beat = time_ticks_per_beat;
pos->beats_per_minute = time_beats_per_minute;
// filterStreamer->timeHasChanged = false; // time change complete
// Compute BBT info from frame number. This is relatively
// simple here, but would become complex if we supported tempo
// or time signature changes at specific locations in the
// transport timeline.
min = pos->frame / ((double) pos->frame_rate * 60.0);
abs_tick = roundDoubleToInt (min * pos->beats_per_minute * pos->ticks_per_beat);
abs_beat = roundDoubleToInt (abs_tick / pos->ticks_per_beat);
pos->bar = roundFloatToInt (abs_beat / pos->beats_per_bar);
pos->beat = roundFloatToInt (abs_beat - (pos->bar * pos->beats_per_bar) + 1);
pos->tick = roundFloatToInt (abs_tick - (abs_beat * pos->ticks_per_beat));
pos->bar_start_tick = roundFloatToInt (pos->bar * pos->beats_per_bar * pos->ticks_per_beat);
pos->bar++; // adjust start to bar 1
#if JUCE_DEBUG
// printf ("%f %f %f %f", pos->frame, pos->bar, pos->beat, pos->tick);
#endif
}
else
{
// Compute BBT info based on previous period.
pos->tick += roundDoubleToInt (nframes * pos->ticks_per_beat * pos->beats_per_minute / (pos->frame_rate * 60));
while (pos->tick >= pos->ticks_per_beat)
{
pos->tick -= roundDoubleToInt (pos->ticks_per_beat);
if (++pos->beat > pos->beats_per_bar)
{
pos->beat = 1;
++pos->bar;
pos->bar_start_tick += pos->beats_per_bar * pos->ticks_per_beat;
}
}
}
}
you can use it like any other plugin wrapper (vst, au…)
#include "MyFilterBase.h"
#include "MyFilterComponent.h"
#include "formats/Jack/juce_JackAudioFilterStreamer.h"
//==============================================================================
extern AudioFilterBase* createPluginFilter ();
//==============================================================================
class MyStandalonePluginWindow : public DocumentWindow
{
public:
MyStandalonePluginWindow ()
: DocumentWindow (T(""),
Colours::beige,
DocumentWindow::closeButton | DocumentWindow::minimiseButton,
true)
{
// create the filter
pluginFilter = createPluginFilter ();
// create the streamer and assign host to it
jackStreamer = new JackAudioFilterStreamer ();
jackStreamer->setFilter (pluginFilter, true);
// create the editor (will be the contentComponent)
AudioFilterEditor* pluginEditor = jackStreamer->createFilterEditor();
centreWithSize (pluginEditor->getWidth(),
pluginEditor->getHeight());
// setup main component and menu
setContentComponent (pluginEditor);
// we can resize ourselves
setResizable (true, false);
}
~HostWrapperWindow ()
{
// do this before pluginFilter gets deleted
deleteAndZero (jackStreamer);
if (getContentComponent() != 0)
setContentComponent (0);
// this must be the very latest thing you should do !
deleteAndZero (pluginFilter);
}
void closeButtonPressed ()
{
if (jackStreamer) jackStreamer->suspendProcessing (true);
JUCEApplication::getInstance()->systemRequestedQuit();
}
protected:
AudioFilterBase* pluginFilter;
JackAudioFilterStreamer* jackStreamer;
};