Standalone plug on linux?


#1

I noticed that there are no project files for plugins for linux, but I assume making a standalone synth should be quite doable? Anyone want to give me a brief description?

Or am I better off just starting from scratch (with a filterstreamer)…It doesn’t look too difficult either?


#2

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;

};

#3

LOL. Nice, but I’m looking to use the regular standalone wrapper. I’m just wondering how to setup the project. Do I need to set any defines for example.

Edit > …I just tried just bang all the files together in a make file to see what came of it, and the linker complains that the ELF has and undefined reference to “main”. I suppose this means that I need to do the export thing, is there a define for this hidden somewhere?


#4

the bad thing about the standalone wrapper is that it uses alsa only and you wouldn’t achieve the low latency you could with jack (i’m working usually with 2.9 - 5.8 ms latency here with jack).

for setting up the project, just start a simple juce app, no more nor less, better if your start from the premake file of the juce demo (it has all the linking libs you would need for audio applications), with my wrapper you should have installed jack, and link your app with -ljack


#5

By the way Kraken, my web space is going down in August so the peggy source will no longer be up there. Feel free to mirror it or something if you want.
I also found the original peggy, IE just the pattern arp, http://hem.bredband.net/b120780/peggy_04.zip if you want to convert it too.


#6

Hm, OK so the standalone wrapper is not like the VST wrapper etc. You have to make your own app to launch it from. I think I get it.


#7

ok, i will host its sources on my site. also, it is part of the jacklab svn repository.


#8

Edit

I’ve kludged my way past 4 assertions now. But they keep coming. :frowning:


#9

Ok, I do setStorageParameters, and then create the stand alone filter window in the app initializer.
The stand alone filter window constructor seems to pick up the demo plug in, at least the filter reports the right number of channels and so forth.

Then… nothing. It just waits at the prompt when executed , no window shows up.

Clues anyone?


#10