| 
							- /*
 -   ==============================================================================
 - 
 -    This file is part of the JUCE library - "Jules' Utility Class Extensions"
 -    Copyright 2004-11 by Raw Material Software Ltd.
 - 
 -   ------------------------------------------------------------------------------
 - 
 -    JUCE can be redistributed and/or modified under the terms of the GNU General
 -    Public License (Version 2), as published by the Free Software Foundation.
 -    A copy of the license is included in the JUCE distribution, or can be found
 -    online at www.gnu.org/licenses.
 - 
 -    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.
 - 
 -   ------------------------------------------------------------------------------
 - 
 -    To release a closed-source product which uses JUCE, commercial licenses are
 -    available: visit www.rawmaterialsoftware.com/juce for more information.
 - 
 -   ==============================================================================
 - */
 - 
 - //==============================================================================
 - static void* juce_libjackHandle = nullptr;
 - 
 - static void* juce_loadJackFunction (const char* const name)
 - {
 -     if (juce_libjackHandle == nullptr)
 -         return nullptr;
 - 
 -     return dlsym (juce_libjackHandle, name);
 - }
 - 
 - #define JUCE_DECL_JACK_FUNCTION(return_type, fn_name, argument_types, arguments)  \
 -   return_type fn_name argument_types                                              \
 -   {                                                                               \
 -       typedef return_type (*fn_type) argument_types;                              \
 -       static fn_type fn = (fn_type) juce_loadJackFunction (#fn_name);             \
 -       return (fn != nullptr) ? ((*fn) arguments) : (return_type) 0;               \
 -   }
 - 
 - #define JUCE_DECL_VOID_JACK_FUNCTION(fn_name, argument_types, arguments)          \
 -   void fn_name argument_types                                                     \
 -   {                                                                               \
 -       typedef void (*fn_type) argument_types;                                     \
 -       static fn_type fn = (fn_type) juce_loadJackFunction (#fn_name);             \
 -       if (fn != nullptr) (*fn) arguments;                                         \
 -   }
 - 
 - //==============================================================================
 - JUCE_DECL_JACK_FUNCTION (jack_client_t*, jack_client_open, (const char* client_name, jack_options_t options, jack_status_t* status, ...), (client_name, options, status));
 - JUCE_DECL_JACK_FUNCTION (int, jack_client_close, (jack_client_t *client), (client));
 - JUCE_DECL_JACK_FUNCTION (int, jack_activate, (jack_client_t* client), (client));
 - JUCE_DECL_JACK_FUNCTION (int, jack_deactivate, (jack_client_t* client), (client));
 - JUCE_DECL_JACK_FUNCTION (jack_nframes_t, jack_get_buffer_size, (jack_client_t* client), (client));
 - JUCE_DECL_JACK_FUNCTION (jack_nframes_t, jack_get_sample_rate, (jack_client_t* client), (client));
 - JUCE_DECL_VOID_JACK_FUNCTION (jack_on_shutdown, (jack_client_t* client, void (*function)(void* arg), void* arg), (client, function, arg));
 - JUCE_DECL_JACK_FUNCTION (void* , jack_port_get_buffer, (jack_port_t* port, jack_nframes_t nframes), (port, nframes));
 - JUCE_DECL_JACK_FUNCTION (jack_nframes_t, jack_port_get_total_latency, (jack_client_t* client, jack_port_t* port), (client, port));
 - JUCE_DECL_JACK_FUNCTION (jack_port_t* , jack_port_register, (jack_client_t* client, const char* port_name, const char* port_type, unsigned long flags, unsigned long buffer_size), (client, port_name, port_type, flags, buffer_size));
 - JUCE_DECL_VOID_JACK_FUNCTION (jack_set_error_function, (void (*func)(const char*)), (func));
 - JUCE_DECL_JACK_FUNCTION (int, jack_set_process_callback, (jack_client_t* client, JackProcessCallback process_callback, void* arg), (client, process_callback, arg));
 - JUCE_DECL_JACK_FUNCTION (const char**, jack_get_ports, (jack_client_t* client, const char* port_name_pattern, const char* type_name_pattern, unsigned long flags), (client, port_name_pattern, type_name_pattern, flags));
 - JUCE_DECL_JACK_FUNCTION (int, jack_connect, (jack_client_t* client, const char* source_port, const char* destination_port), (client, source_port, destination_port));
 - JUCE_DECL_JACK_FUNCTION (const char*, jack_port_name, (const jack_port_t* port), (port));
 - JUCE_DECL_JACK_FUNCTION (int, jack_set_port_connect_callback, (jack_client_t* client, JackPortConnectCallback connect_callback, void* arg), (client, connect_callback, arg));
 - JUCE_DECL_JACK_FUNCTION (jack_port_t* , jack_port_by_id, (jack_client_t* client, jack_port_id_t port_id), (client, port_id));
 - JUCE_DECL_JACK_FUNCTION (int, jack_port_connected, (const jack_port_t* port), (port));
 - JUCE_DECL_JACK_FUNCTION (int, jack_port_connected_to, (const jack_port_t* port, const char* port_name), (port, port_name));
 - 
 - #if JUCE_DEBUG
 -  #define JACK_LOGGING_ENABLED 1
 - #endif
 - 
 - #if JACK_LOGGING_ENABLED
 - namespace
 - {
 -     void jack_Log (const String& s)
 -     {
 -         std::cerr << s << std::endl;
 -     }
 - 
 -     void dumpJackErrorMessage (const jack_status_t status)
 -     {
 -         if (status & JackServerFailed || status & JackServerError)  jack_Log ("Unable to connect to JACK server");
 -         if (status & JackVersionError)      jack_Log ("Client's protocol version does not match");
 -         if (status & JackInvalidOption)     jack_Log ("The operation contained an invalid or unsupported option");
 -         if (status & JackNameNotUnique)     jack_Log ("The desired client name was not unique");
 -         if (status & JackNoSuchClient)      jack_Log ("Requested client does not exist");
 -         if (status & JackInitFailure)       jack_Log ("Unable to initialize client");
 -     }
 - }
 - #else
 -  #define dumpJackErrorMessage(a) {}
 -  #define jack_Log(...) {}
 - #endif
 - 
 - 
 - //==============================================================================
 - #ifndef JUCE_JACK_CLIENT_NAME
 -  #define JUCE_JACK_CLIENT_NAME "JuceJack"
 - #endif
 - 
 - //==============================================================================
 - class JackAudioIODevice   : public AudioIODevice
 - {
 - public:
 -     JackAudioIODevice (const String& deviceName,
 -                        const String& inputId_,
 -                        const String& outputId_)
 -         : AudioIODevice (deviceName, "JACK"),
 -           inputId (inputId_),
 -           outputId (outputId_),
 -           isOpen_ (false),
 -           callback (nullptr),
 -           totalNumberOfInputChannels (0),
 -           totalNumberOfOutputChannels (0)
 -     {
 -         jassert (deviceName.isNotEmpty());
 - 
 -         jack_status_t status;
 -         client = juce::jack_client_open (JUCE_JACK_CLIENT_NAME, JackNoStartServer, &status);
 - 
 -         if (client == nullptr)
 -         {
 -             dumpJackErrorMessage (status);
 -         }
 -         else
 -         {
 -             juce::jack_set_error_function (errorCallback);
 - 
 -             // open input ports
 -             const StringArray inputChannels (getInputChannelNames());
 -             for (int i = 0; i < inputChannels.size(); i++)
 -             {
 -                 String inputName;
 -                 inputName << "in_" << ++totalNumberOfInputChannels;
 - 
 -                 inputPorts.add (juce::jack_port_register (client, inputName.toUTF8(),
 -                                                           JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0));
 -             }
 - 
 -             // open output ports
 -             const StringArray outputChannels (getOutputChannelNames());
 -             for (int i = 0; i < outputChannels.size (); i++)
 -             {
 -                 String outputName;
 -                 outputName << "out_" << ++totalNumberOfOutputChannels;
 - 
 -                 outputPorts.add (juce::jack_port_register (client, outputName.toUTF8(),
 -                                                            JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0));
 -             }
 - 
 -             inChans.calloc (totalNumberOfInputChannels + 2);
 -             outChans.calloc (totalNumberOfOutputChannels + 2);
 -         }
 -     }
 - 
 -     ~JackAudioIODevice()
 -     {
 -         close();
 -         if (client != nullptr)
 -         {
 -             juce::jack_client_close (client);
 -             client = nullptr;
 -         }
 -     }
 - 
 -     StringArray getChannelNames (bool forInput) const
 -     {
 -         StringArray names;
 -         const char** const ports = juce::jack_get_ports (client, 0, 0, /* JackPortIsPhysical | */
 -                                                          forInput ? JackPortIsInput : JackPortIsOutput);
 - 
 -         if (ports != 0)
 -         {
 -             int j = 0;
 -             while (ports[j] != 0)
 -             {
 -                 const String portName (ports [j++]);
 - 
 -                 if (portName.upToFirstOccurrenceOf (":", false, false) == getName())
 -                     names.add (portName.fromFirstOccurrenceOf (":", false, false));
 -             }
 - 
 -             free (ports);
 -         }
 - 
 -         return names;
 -     }
 - 
 -     StringArray getOutputChannelNames()         { return getChannelNames (false); }
 -     StringArray getInputChannelNames()          { return getChannelNames (true); }
 -     int getNumSampleRates()                     { return client != nullptr ? 1 : 0; }
 -     double getSampleRate (int index)            { return client != nullptr ? juce::jack_get_sample_rate (client) : 0; }
 -     int getNumBufferSizesAvailable()            { return client != nullptr ? 1 : 0; }
 -     int getBufferSizeSamples (int index)        { return getDefaultBufferSize(); }
 -     int getDefaultBufferSize()                  { return client != nullptr ? juce::jack_get_buffer_size (client) : 0; }
 - 
 -     String open (const BigInteger& inputChannels, const BigInteger& outputChannels,
 -                  double sampleRate, int bufferSizeSamples)
 -     {
 -         if (client == nullptr)
 -         {
 -             lastError = "No JACK client running";
 -             return lastError;
 -         }
 - 
 -         lastError = String::empty;
 -         close();
 - 
 -         juce::jack_set_process_callback (client, processCallback, this);
 -         juce::jack_on_shutdown (client, shutdownCallback, this);
 -         juce::jack_activate (client);
 -         isOpen_ = true;
 - 
 -         if (! inputChannels.isZero())
 -         {
 -             const char** const ports = juce::jack_get_ports (client, 0, 0, /* JackPortIsPhysical | */ JackPortIsOutput);
 - 
 -             if (ports != 0)
 -             {
 -                 const int numInputChannels = inputChannels.getHighestBit() + 1;
 - 
 -                 for (int i = 0; i < numInputChannels; ++i)
 -                 {
 -                     const String portName (ports[i]);
 - 
 -                     if (inputChannels[i] && portName.upToFirstOccurrenceOf (":", false, false) == getName())
 -                     {
 -                         int error = juce::jack_connect (client, ports[i], juce::jack_port_name ((jack_port_t*) inputPorts[i]));
 -                         if (error != 0)
 -                             jack_Log ("Cannot connect input port " + String (i) + " (" + String (ports[i]) + "), error " + String (error));
 -                     }
 -                 }
 - 
 -                 free (ports);
 -             }
 -         }
 - 
 -         if (! outputChannels.isZero())
 -         {
 -             const char** const ports = juce::jack_get_ports (client, 0, 0, /* JackPortIsPhysical | */ JackPortIsInput);
 - 
 -             if (ports != 0)
 -             {
 -                 const int numOutputChannels = outputChannels.getHighestBit() + 1;
 - 
 -                 for (int i = 0; i < numOutputChannels; ++i)
 -                 {
 -                     const String portName (ports[i]);
 - 
 -                     if (outputChannels[i] && portName.upToFirstOccurrenceOf (":", false, false) == getName())
 -                     {
 -                         int error = juce::jack_connect (client, juce::jack_port_name ((jack_port_t*) outputPorts[i]), ports[i]);
 -                         if (error != 0)
 -                             jack_Log ("Cannot connect output port " + String (i) + " (" + String (ports[i]) + "), error " + String (error));
 -                     }
 -                 }
 - 
 -                 free (ports);
 -             }
 -         }
 - 
 -         return lastError;
 -     }
 - 
 -     void close()
 -     {
 -         stop();
 - 
 -         if (client != nullptr)
 -         {
 -             juce::jack_deactivate (client);
 -             juce::jack_set_process_callback (client, processCallback, 0);
 -             juce::jack_on_shutdown (client, shutdownCallback, 0);
 -         }
 - 
 -         isOpen_ = false;
 -     }
 - 
 -     void start (AudioIODeviceCallback* newCallback)
 -     {
 -         if (isOpen_ && newCallback != callback)
 -         {
 -             if (newCallback != nullptr)
 -                 newCallback->audioDeviceAboutToStart (this);
 - 
 -             AudioIODeviceCallback* const oldCallback = callback;
 - 
 -             {
 -                 const ScopedLock sl (callbackLock);
 -                 callback = newCallback;
 -             }
 - 
 -             if (oldCallback != nullptr)
 -                 oldCallback->audioDeviceStopped();
 -         }
 -     }
 - 
 -     void stop()
 -     {
 -         start (nullptr);
 -     }
 - 
 -     bool isOpen()                           { return isOpen_; }
 -     bool isPlaying()                        { return callback != nullptr; }
 -     int getCurrentBufferSizeSamples()       { return getBufferSizeSamples (0); }
 -     double getCurrentSampleRate()           { return getSampleRate (0); }
 -     int getCurrentBitDepth()                { return 32; }
 -     String getLastError()                   { return lastError; }
 - 
 -     BigInteger getActiveOutputChannels() const
 -     {
 -         BigInteger outputBits;
 - 
 -         for (int i = 0; i < outputPorts.size(); i++)
 -             if (juce::jack_port_connected ((jack_port_t*) outputPorts [i]))
 -                 outputBits.setBit (i);
 - 
 -         return outputBits;
 -     }
 - 
 -     BigInteger getActiveInputChannels() const
 -     {
 -         BigInteger inputBits;
 - 
 -         for (int i = 0; i < inputPorts.size(); i++)
 -             if (juce::jack_port_connected ((jack_port_t*) inputPorts [i]))
 -                 inputBits.setBit (i);
 - 
 -         return inputBits;
 -     }
 - 
 -     int getOutputLatencyInSamples()
 -     {
 -         int latency = 0;
 - 
 -         for (int i = 0; i < outputPorts.size(); i++)
 -             latency = jmax (latency, (int) juce::jack_port_get_total_latency (client, (jack_port_t*) outputPorts [i]));
 - 
 -         return latency;
 -     }
 - 
 -     int getInputLatencyInSamples()
 -     {
 -         int latency = 0;
 - 
 -         for (int i = 0; i < inputPorts.size(); i++)
 -             latency = jmax (latency, (int) juce::jack_port_get_total_latency (client, (jack_port_t*) inputPorts [i]));
 - 
 -         return latency;
 -     }
 - 
 -     String inputId, outputId;
 - 
 - private:
 -     void process (const int numSamples)
 -     {
 -         int i, numActiveInChans = 0, numActiveOutChans = 0;
 - 
 -         for (i = 0; i < totalNumberOfInputChannels; ++i)
 -         {
 -             jack_default_audio_sample_t* in
 -                 = (jack_default_audio_sample_t*) juce::jack_port_get_buffer ((jack_port_t*) inputPorts.getUnchecked(i), numSamples);
 - 
 -             if (in != nullptr)
 -                 inChans [numActiveInChans++] = (float*) in;
 -         }
 - 
 -         for (i = 0; i < totalNumberOfOutputChannels; ++i)
 -         {
 -             jack_default_audio_sample_t* out
 -                 = (jack_default_audio_sample_t*) juce::jack_port_get_buffer ((jack_port_t*) outputPorts.getUnchecked(i), numSamples);
 - 
 -             if (out != nullptr)
 -                 outChans [numActiveOutChans++] = (float*) out;
 -         }
 - 
 -         const ScopedLock sl (callbackLock);
 - 
 -         if (callback != nullptr)
 -         {
 -             callback->audioDeviceIOCallback (const_cast <const float**> (inChans.getData()), numActiveInChans,
 -                                              outChans, numActiveOutChans, numSamples);
 -         }
 -         else
 -         {
 -             for (i = 0; i < numActiveOutChans; ++i)
 -                 zeromem (outChans[i], sizeof (float) * numSamples);
 -         }
 -     }
 - 
 -     static int processCallback (jack_nframes_t nframes, void* callbackArgument)
 -     {
 -         if (callbackArgument != 0)
 -             ((JackAudioIODevice*) callbackArgument)->process (nframes);
 - 
 -         return 0;
 -     }
 - 
 -     static void threadInitCallback (void* callbackArgument)
 -     {
 -         jack_Log ("JackAudioIODevice::initialise");
 -     }
 - 
 -     static void shutdownCallback (void* callbackArgument)
 -     {
 -         jack_Log ("JackAudioIODevice::shutdown");
 - 
 -         JackAudioIODevice* device = (JackAudioIODevice*) callbackArgument;
 - 
 -         if (device != nullptr)
 -         {
 -             device->client = nullptr;
 -             device->close();
 -         }
 -     }
 - 
 -     static void errorCallback (const char* msg)
 -     {
 -         jack_Log ("JackAudioIODevice::errorCallback " + String (msg));
 -     }
 - 
 -     bool isOpen_;
 -     jack_client_t* client;
 -     String lastError;
 -     AudioIODeviceCallback* callback;
 -     CriticalSection callbackLock;
 - 
 -     HeapBlock <float*> inChans, outChans;
 -     int totalNumberOfInputChannels;
 -     int totalNumberOfOutputChannels;
 -     Array<void*> inputPorts, outputPorts;
 - };
 - 
 - 
 - //==============================================================================
 - class JackAudioIODeviceType  : public AudioIODeviceType
 - {
 - public:
 -     //==============================================================================
 -     JackAudioIODeviceType()
 -         : AudioIODeviceType ("JACK"),
 -           hasScanned (false)
 -     {
 -     }
 - 
 -     //==============================================================================
 -     void scanForDevices()
 -     {
 -         hasScanned = true;
 -         inputNames.clear();
 -         inputIds.clear();
 -         outputNames.clear();
 -         outputIds.clear();
 - 
 -         if (juce_libjackHandle == nullptr)
 -         {
 -             juce_libjackHandle = dlopen ("libjack.so", RTLD_LAZY);
 - 
 -             if (juce_libjackHandle == nullptr)
 -                 return;
 -         }
 - 
 -         // open a dummy client
 -         jack_status_t status;
 -         jack_client_t* client = juce::jack_client_open ("JuceJackDummy", JackNoStartServer, &status);
 - 
 -         if (client == nullptr)
 -         {
 -             dumpJackErrorMessage (status);
 -         }
 -         else
 -         {
 -             // scan for output devices
 -             const char** ports = juce::jack_get_ports (client, 0, 0, /* JackPortIsPhysical | */ JackPortIsOutput);
 - 
 -             if (ports != nullptr)
 -             {
 -                 int j = 0;
 -                 while (ports[j] != 0)
 -                 {
 -                     String clientName (ports[j]);
 -                     clientName = clientName.upToFirstOccurrenceOf (":", false, false);
 - 
 -                     if (clientName != String (JUCE_JACK_CLIENT_NAME)
 -                          && ! inputNames.contains (clientName))
 -                     {
 -                         inputNames.add (clientName);
 -                         inputIds.add (ports [j]);
 -                     }
 - 
 -                     ++j;
 -                 }
 - 
 -                 free (ports);
 -             }
 - 
 -             // scan for input devices
 -             ports = juce::jack_get_ports (client, 0, 0, /* JackPortIsPhysical | */ JackPortIsInput);
 - 
 -             if (ports != nullptr)
 -             {
 -                 int j = 0;
 -                 while (ports[j] != 0)
 -                 {
 -                     String clientName (ports[j]);
 -                     clientName = clientName.upToFirstOccurrenceOf (":", false, false);
 - 
 -                     if (clientName != String (JUCE_JACK_CLIENT_NAME)
 -                          && ! outputNames.contains (clientName))
 -                     {
 -                         outputNames.add (clientName);
 -                         outputIds.add (ports [j]);
 -                     }
 - 
 -                     ++j;
 -                 }
 - 
 -                 free (ports);
 -             }
 - 
 -             juce::jack_client_close (client);
 -         }
 -     }
 - 
 -     StringArray getDeviceNames (bool wantInputNames) const
 -     {
 -         jassert (hasScanned); // need to call scanForDevices() before doing this
 -         return wantInputNames ? inputNames : outputNames;
 -     }
 - 
 -     int getDefaultDeviceIndex (bool forInput) const
 -     {
 -         jassert (hasScanned); // need to call scanForDevices() before doing this
 -         return 0;
 -     }
 - 
 -     bool hasSeparateInputsAndOutputs() const    { return true; }
 - 
 -     int getIndexOfDevice (AudioIODevice* device, bool asInput) const
 -     {
 -         jassert (hasScanned); // need to call scanForDevices() before doing this
 - 
 -         JackAudioIODevice* d = dynamic_cast <JackAudioIODevice*> (device);
 -         if (d == nullptr)
 -             return -1;
 - 
 -         return asInput ? inputIds.indexOf (d->inputId)
 -                        : outputIds.indexOf (d->outputId);
 -     }
 - 
 -     AudioIODevice* createDevice (const String& outputDeviceName,
 -                                  const String& inputDeviceName)
 -     {
 -         jassert (hasScanned); // need to call scanForDevices() before doing this
 - 
 -         const int inputIndex = inputNames.indexOf (inputDeviceName);
 -         const int outputIndex = outputNames.indexOf (outputDeviceName);
 - 
 -         if (inputIndex >= 0 || outputIndex >= 0)
 -             return new JackAudioIODevice (outputIndex >= 0 ? outputDeviceName
 -                                                            : inputDeviceName,
 -                                           inputIds [inputIndex],
 -                                           outputIds [outputIndex]);
 - 
 -         return nullptr;
 -     }
 - 
 -     //==============================================================================
 - private:
 -     StringArray inputNames, outputNames, inputIds, outputIds;
 -     bool hasScanned;
 - 
 -     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (JackAudioIODeviceType);
 - };
 - 
 - //==============================================================================
 - AudioIODeviceType* AudioIODeviceType::createAudioIODeviceType_JACK()
 - {
 -     return new JackAudioIODeviceType();
 - }
 
 
  |