JackAudioIODevice input/output channel count

hi!

i’m currently working on ambisonics audio processors which require a rather large number of input/output channels.

i realized that the JackAudioIODevice (juce_linux_JackAudio.cpp) registers its jack ports in the constructor, depending on how many physical in/output channels are available to jack.

i think this is not really a good way of jack integration, as the channel count of a jack application should be independent of the hardware in/outputs.
most people are using eg. qjackctl to set the connections between applications and hardware devices anyway.

i suggest moving jack port registration into the open method, where the input/output channel count is already known.

there are many pros and cons about if the jack ports of an application should be auto connected with the physical outputs. personally i like to do my connections manually.

best,
matthias

Have to admit that I know almost nothing about Jack, so am very open to suggestions here! Anyone else got opinions on how best to handle this?

you may want to look at the version I had posted here a long time ago:

http://www.rawmaterialsoftware.com/viewtopic.php?p=21027#p21027

In this version the number of channels is set by the application, and the connections to the default output can be automatically established, or let to user (I expose two JackAudioIODeviceType, one for the ‘auto-connect’ mode, on for the “no auto-connect” mode. I can post an update to this code as it has evolved a bit since then, but basically I think the correct approach with Jack is that the juce application chooses the number of channels exposed to jack.

[quote=“jpo”]you may want to look at the version I had posted here a long time ago:

http://www.rawmaterialsoftware.com/viewtopic.php?p=21027#p21027

In this version the number of channels is set by the application, and the connections to the default output can be automatically established, or let to user (I expose two JackAudioIODeviceType, one for the ‘auto-connect’ mode, on for the “no auto-connect” mode. I can post an update to this code as it has evolved a bit since then, but basically I think the correct approach with Jack is that the juce application chooses the number of channels exposed to jack.[/quote]
oh nice, can you please share that (updated) code?

having transport support in there would be cool too, I can do that myself if it’s not implemented yet.

Here it is. It handles jack midi, jack session callbacks, and freewheeling (in a very ugly way , cf the ‘freewheel_flag’). But there is no transport handling.

It assumes that the user supplies a function ‘getJackClientConfiguration(JackClientConfiguration &conf)’ that provides the necessary configuration info to the JackAudioIODeviceType during instanciation.

custom_jack_device.h:

[code]#ifndef JACK_DEVICE_HH
#define JACK_DEVICE_HH

struct JackSessionCallbackArg {
String session_directory;
String session_uuid;
String command_line;
bool quit;
};

struct JackClientConfiguration {
String clientName;
// size of array = number of input channels. If the strings are empty, default names are chosen (in_1 , in_2 etc)
StringArray inputChannels;
StringArray outputChannels;
MidiBuffer *midi_events; // optional buffer where the jack midi events will get written to before each audio callback
int *freewheel_flag; // optional flag toggled in freewheel mode
String session_uuid;

typedef void (*SessionCallback)(JackSessionCallbackArg &arg);
SessionCallback session_callback;
};

// user supplied function for jack config
void getJackClientConfiguration(JackClientConfiguration &conf);

#endif // JACK_DEVICE_HH
[/code]

custom_jack_device.cpp:

#include <jack/jack.h>
#include <jack/midiport.h>
#include <jack/transport.h>
#include <jack/session.h>

#include <juce.h>
#include "jack_device.hh"

extern "C" int libjack_is_present;
extern "C" int libjack_session_is_supported;

static const char* jackAudioDeviceLocalName(bool autoconnect) {
    if (!autoconnect) return "Auto-connect OFF";
    else return "Auto-connect ON";
}

int display_jack_errors_in_message_box = 0;

//==============================================================================
class JackAudioIODevice   : public AudioIODevice,
                            public MessageListener
{
    bool autoconnect;
    JackClientConfiguration config;
public:
    JackAudioIODevice (JackClientConfiguration &config_, bool autoconnect_)
      : AudioIODevice (jackAudioDeviceLocalName(autoconnect_), "JACK"),
          autoconnect(autoconnect_),
          config(config_),
          isOpen_ (false),
          isStarted (false),
          callback (0),
        client (0),
        client_activated(false)
    {
        midi_in = 0;
        for (int i=0; i < config.inputChannels.size(); ++i) {
            if (config.inputChannels[i].length() == 0) config.inputChannels.set(i, "in_"+String(i+1));
        }
        for (int i = 0; i < config.outputChannels.size(); i++) {
            if (config.outputChannels[i].length() == 0) config.outputChannels.set(i, "out_"+String(i+1));
        }
        display_jack_errors_in_message_box = 0; // these messages sucks..
        jack_set_error_function (JackAudioIODevice::errorCallback);
        jack_status_t status;
        if (config.session_uuid.isNotEmpty() && libjack_session_is_supported) {
          //cerr << "JackAudioIODevice: opening with session_uuid: '" << config.session_uuid << "'\n";
          client = jack_client_open (config.clientName.toUTF8().getAddress(), JackSessionID, &status, config.session_uuid.toUTF8().getAddress());
        } else {
          //cerr << "JackAudioIODevice: opening WITHOUT session_uuid: '" << config.session_uuid << "'\n";          
          client = jack_client_open (config.clientName.toUTF8().getAddress(), JackNoStartServer, &status);
        }
        display_jack_errors_in_message_box = 0;
        if (client == 0)
        {
            if ((status & JackServerFailed) || (status & JackServerError))
                printf ("Unable to connect to JACK server\n");
            else if ((status & JackVersionError))
                printf ("Client's protocol version does not match\n");
            else if ((status & JackInvalidOption))
                printf ("The operation contained an invalid or unsupported option\n");
            else if ((status & JackNameNotUnique))
                printf ("The desired client name was not unique\n");
            else if ((status & JackNoSuchClient))
                printf ("Requested client does not exist\n");
            else if ((status & JackInitFailure))
                printf ("Unable to initialize client\n");
            else printf ("Unknown jack error [%d]\n", (int)status);
        }
        else
        {

            for (int i=0; i < config.inputChannels.size(); ++i) {
                jack_port_t* input =
                    jack_port_register (client, config.inputChannels[i].toUTF8().getAddress(), JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
                inputPorts.add (input);
            }

            for (int i = 0; i < config.outputChannels.size(); i++) {
                jack_port_t* output =
                    jack_port_register (client, config.outputChannels[i].toUTF8().getAddress(), JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
                outputPorts.add (output);
           }
           if (config.midi_events) 
              midi_in = jack_port_register(client, "midi_in", JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0);

           if (libjack_session_is_supported && config.session_callback) {
             jack_set_session_callback(client, sessionCallback, this);
           }
        }
        inChans  = (float**)malloc(config.inputChannels.size() *sizeof(float*));
        outChans = (float**)malloc(config.outputChannels.size()*sizeof(float*));
    }

    ~JackAudioIODevice()
    {
        if (client)
        {
            close ();

            jack_client_close (client);
            client = 0;
        }
        free(inChans);
        free(outChans);
    }

    bool autoConnect() const { return autoconnect; }

    StringArray getOutputChannelNames() { return config.outputChannels; }

    StringArray getInputChannelNames() { return config.inputChannels; }

    int getNumSampleRates()
    {
        return client ? 1 : 0;
    }

    double getSampleRate (int /*index*/)
    {
        return client ? jack_get_sample_rate (client) : 0;
    }

    int getNumBufferSizesAvailable()
    {
        return client ? 1 : 0;
    }

    int getBufferSizeSamples (int /*index*/)
    {
        return client ? jack_get_buffer_size (client) : 0;
    }

    int getDefaultBufferSize()
    {
        return client ? jack_get_buffer_size (client) : 0;
    }

    String open (const BitArray& /*inputChannels*/,
                 const BitArray& /*outputChannels*/,
                 double /*sampleRate*/,
                 int /*bufferSizeSamples*/)
    {
        if (! client)
        {
            return "Jack server is not running";
        }

        close();

        // activate client !        
        jack_set_process_callback (client, JackAudioIODevice::processCallback, this);
	jack_set_freewheel_callback (client, JackAudioIODevice::freewheelCallback, this);
        jack_on_shutdown (client, JackAudioIODevice::shutdownCallback, this);

        jack_activate (client); client_activated = true;

        if (autoconnect) {
            const char **ports = jack_get_ports (client, NULL, NULL, JackPortIsPhysical|JackPortIsInput);
            for (int i=0; i < 2 && i < outputPorts.size() && ports[i]; ++i) {
                jack_connect(client, jack_port_name((jack_port_t*)outputPorts[i]), ports[i]);
            }
        }

        isOpen_ = true;

        return String::empty;
    }

    void close()
    {
        stop();

        if (client && client_activated)
        {
          jack_deactivate (client); client_activated = false;

            jack_set_process_callback (client, JackAudioIODevice::processCallback, 0);
            jack_on_shutdown (client, JackAudioIODevice::shutdownCallback, 0);
        }
        if (config.freewheel_flag) *config.freewheel_flag = -1;
        isOpen_ = false;
    }

    bool isOpen()
    {
        return isOpen_;
    }

    int getCurrentBufferSizeSamples()
    {
        return getBufferSizeSamples (0);
    }

    double getCurrentSampleRate()
    {
        return getSampleRate (0);
    }

    int getCurrentBitDepth()
    {
        return 32;
    }

    BitArray getActiveOutputChannels() const
    {
        BitArray outputBits;
        outputBits.setRange(0, outputPorts.size(), true);
        return outputBits;
    }

    BitArray getActiveInputChannels() const
    {
        BitArray inputBits;
        inputBits.setRange(0, inputPorts.size(), true);
        return inputBits;
    }

    int getOutputLatencyInSamples()
    {
        int latency = 0;
        
        for (int i = 0; i < outputPorts.size(); i++)
            latency = jmax (latency, (int) 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) jack_port_get_total_latency (client, (jack_port_t*) inputPorts [i]));
    
        return latency;
    }

    void start (AudioIODeviceCallback* callback_)
    {
        if (! isOpen_)
            callback_ = 0;

        callback = callback_;

        if (callback != 0)
            callback->audioDeviceAboutToStart (this);

        isStarted = (callback != 0);
    }

    void freewheel (int starting ) {
        if (config.freewheel_flag) *config.freewheel_flag = starting; 
    }

    void process (int numSamples)
    {
      if (config.midi_events) {
        void* buf = jack_port_get_buffer(midi_in, numSamples);
        jack_nframes_t event_count = jack_midi_get_event_count(buf);
        jack_midi_event_t in_event;
        config.midi_events->clear();
        for (jack_nframes_t i=0; i < event_count; ++i) {
          jack_midi_event_get(&in_event, buf, i);
          //cerr << "add event : "<< (void*)*(const uint8_t*)in_event.buffer << ", sz=" << in_event.size << " sample: " << in_event.time << "\n";
          config.midi_events->addEvent((const uint8_t*)in_event.buffer, in_event.size, in_event.time);
        }
      }

        int i, numActiveInChans = 0, numActiveOutChans = 0;

        for (i = 0; i < inputPorts.size(); ++i)
        {
            jack_default_audio_sample_t *in =
                (jack_default_audio_sample_t *) jack_port_get_buffer (
                                                        (jack_port_t*) inputPorts.getUnchecked(i), numSamples);
            jassert (in != 0);
            inChans [numActiveInChans++] = (float*) in;
        }

        for (i = 0; i < outputPorts.size(); ++i)
        {
            jack_default_audio_sample_t *out =
                (jack_default_audio_sample_t *) jack_port_get_buffer (
                                                        (jack_port_t*) outputPorts.getUnchecked(i), numSamples);
            jassert (out != 0);
            outChans [numActiveOutChans++] = (float*) out;
        }

        if (callback != 0)
        {
            callback->audioDeviceIOCallback ((const float**) inChans,
                                             inputPorts.size(), 
                                             outChans,
                                             outputPorts.size(),
                                             numSamples);
        }
        else
        {
            for (i = 0; i < outputPorts.size(); ++i)
                zeromem (outChans[i], sizeof (float) * numSamples);
        }
    }

    void stop()
    {
        AudioIODeviceCallback* const oldCallback = callback;

        start (0);

        if (oldCallback != 0)
            oldCallback->audioDeviceStopped();
    }

    bool isPlaying()
    {
        return isStarted;
    }

    String getLastError()
    {
        return String::empty;
    }

    String inputId, outputId;

private:

    static void threadInitCallback (void* /*callbackArgument*/)
    {
    }
    
    static void shutdownCallback (void* callbackArgument)
    {
        JackAudioIODevice* device = (JackAudioIODevice*) callbackArgument;
    
        if (device) 
        {
            device->client = 0;
            device->close ();
        }
    }
    
    static int processCallback (jack_nframes_t nframes, void* callbackArgument)
    {
        JackAudioIODevice* device = (JackAudioIODevice*) callbackArgument;

        if (device)
            device->process (nframes);

        return 0;
    }

    struct SessionCallbackMessage : public Message {
      jack_session_event_t *event;
    };

    void handleMessage(const Message &msg) {
      const SessionCallbackMessage *sm;
      //printf("sessionCallback, received message\n");
      if ((sm = dynamic_cast<const SessionCallbackMessage*>(&msg))) {
        if (config.session_callback) {
          JackSessionCallbackArg arg;
          arg.session_directory = sm->event->session_dir;
          arg.session_uuid = sm->event->client_uuid;
          arg.quit = (sm->event->type == JackSessionSaveAndQuit);
          config.session_callback(arg);

          sm->event->command_line = strdup(arg.command_line.toUTF8().getAddress());
        }
        jack_session_reply(client, sm->event);
        jack_session_event_free(sm->event); 
      }
    }

    static void sessionCallback (jack_session_event_t *event, void *callbackArgument) 
    { 
      //printf("sessionCallback, posting message\n");
      JackAudioIODevice* device = (JackAudioIODevice*) callbackArgument;
      SessionCallbackMessage *m = new SessionCallbackMessage; m->event = event;
      device->postMessage(m);
    }

    static void freewheelCallback (int starting, void *callbackArgument)
    {
        JackAudioIODevice* device = (JackAudioIODevice*) callbackArgument;
	if (device) {
       	    device->freewheel (starting);
	}
    }

    static void errorCallback (const char *msg)
    {
        char errmsg[1024]; 
        const char *extra_msg = "";
        if (strcmp(msg, "Only external clients need attach port segments")==0) {
            extra_msg = "\nThis probably means that you are trying to connect a 32-bit jack client to a 64-bit server -- you need to make sure that you are using a recent version of jack (at least 0.116)";
        }
        snprintf(errmsg, 1024, "Jack error: %s%s", msg, extra_msg);
        fprintf (stderr, "%s\n", errmsg);
        if (display_jack_errors_in_message_box) {
            AlertWindow::showMessageBoxAsync(AlertWindow::WarningIcon, "JACK error", errmsg);
            display_jack_errors_in_message_box = 0; // only once
        }
    }

    bool isOpen_, isStarted;

    AudioIODeviceCallback* callback;
    
    float** inChans;
    float** outChans;

    jack_client_t *client;
    bool client_activated;
    Array<void*> inputPorts;
    Array<void*> outputPorts;
    jack_port_t *midi_in;
};


//==============================================================================
class JackAudioIODeviceType  : public AudioIODeviceType
{
public:
    //==============================================================================
    JackAudioIODeviceType()
        : AudioIODeviceType("JACK")
    {
    }

    ~JackAudioIODeviceType()
    {
    }

    

    //==============================================================================
    void scanForDevices()
    {
    }

    StringArray getDeviceNames (const bool /*wantInputNames*/) const
    {
        StringArray s; 
        s.add(jackAudioDeviceLocalName(true)); // autoconnect is first
        s.add(jackAudioDeviceLocalName(false));
        return s;
    }

    int getDefaultDeviceIndex (const bool /*forInput*/) const
    {
        return 0; // autoconnect is default
    }

    bool hasSeparateInputsAndOutputs() const    { return false; }

    int getIndexOfDevice (AudioIODevice* device, const bool /*asInput*/) const
    {
        JackAudioIODevice* const d = dynamic_cast <JackAudioIODevice*> (device);
        if (d == 0) return -1;
        return d->autoConnect() ? 0 : 1;
    }

    AudioIODevice* createDevice (const String& outputDeviceName,
                                 const String& /*inputDeviceName*/)
    {
        bool autoconnect = (outputDeviceName == jackAudioDeviceLocalName(true));
        JackClientConfiguration config;
        getJackClientConfiguration(config);
        return new JackAudioIODevice(config, autoconnect);
    }

    //==============================================================================
    juce_UseDebuggingNewOperator

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

AudioIODeviceType* createAudioIODeviceType_JACK_Custom()
{
    /* detect if libjack.so is available using relaytool on linux */
    if (!libjack_is_present) return 0;
    else return new JackAudioIODeviceType();
}

relay_libjack.cpp (code for loading the libjack.so):

[code]#include <dlfcn.h>
#include <stdlib.h>
#include <jack/jack.h>
#include <jack/midiport.h>
#include <jack/session.h>

#include
#include

/* dynamically load libjack and forward all registered calls to libjack
(similar to what relaytool is trying to do, but more portably…)
*/

using std::cerr;

int libjack_is_present = 0; // public symbol , similar to what relaytool does.
int libjack_session_is_supported = 0;

static void *libjack_handle = 0;

static void attribute((constructor)) tryload_libjack()
{
if (getenv(“SKIP_LIBJACK”) == 0) { // just in case libjack is causing troubles…
libjack_handle = dlopen(“libjack.so.0”, RTLD_LAZY);
}
libjack_is_present = (libjack_handle != 0);
libjack_session_is_supported = (libjack_handle && dlsym(libjack_handle, “jack_set_session_callback”) != 0);
}

void *load_jack_function(const char *fn_name) {
void *fn = 0;
if (!libjack_handle) {
std::cerr << “libjack not found, so do not try to load " << fn_name << " ffs !\n”;
return 0;
}
fn = dlsym(libjack_handle, fn_name);
if (!fn) {
std::cerr << “could not dlsym(” << libjack_handle << "), " << dlerror() << “\n”;
}
return fn;
}

#define DECL_FUNCTION(return_type, fn_name, arguments_types, arguments)
typedef return_type (*fn_name##_ptr_t)arguments_types;
return_type fn_name arguments_types {
static fn_name##_ptr_t fn = 0;
if (fn == 0) { fn = (fn_name##_ptr_t)load_jack_function(#fn_name); }
if (fn) return (*fn)arguments;
else return 0;
}

#define DECL_VOID_FUNCTION(fn_name, arguments_types, arguments)
typedef void (*fn_name##_ptr_t)arguments_types;
void fn_name arguments_types {
static fn_name##_ptr_t fn = 0;
if (fn == 0) { fn = (fn_name##_ptr_t)load_jack_function(#fn_name); }
if (fn) (*fn)arguments;
}

DECL_FUNCTION(jack_client_t *, jack_client_open, (const char *client_name, jack_options_t options, jack_status_t *status, …),
(client_name, options, status));

// variant with the session UUID…
jack_client_t *jack_client_open_with_uuid(const char *client_name, jack_options_t options, jack_status_t *status, const char *uuid) {
static jack_client_open_ptr_t fn = 0;
if (fn == 0) { fn = (jack_client_open_ptr_t)load_jack_function(“jack_client_open”); }
if (fn) return (*fn)(client_name, options, status, uuid);
else return 0;
}

DECL_FUNCTION(int, jack_client_close, (jack_client_t *client), (client));
DECL_FUNCTION(int, jack_activate, (jack_client_t *client), (client));
DECL_FUNCTION(int, jack_deactivate, (jack_client_t *client), (client));
DECL_FUNCTION(jack_nframes_t, jack_get_buffer_size, (jack_client_t *client), (client));
DECL_FUNCTION(jack_nframes_t, jack_get_sample_rate, (jack_client_t *client), (client));
DECL_VOID_FUNCTION(jack_on_shutdown, (jack_client_t *client, void (*function)(void *arg), void *arg), (client, function, arg));
DECL_FUNCTION(void *, jack_port_get_buffer, (jack_port_t *port, jack_nframes_t nframes), (port, nframes));
DECL_FUNCTION(jack_nframes_t, jack_port_get_total_latency, (jack_client_t *client, jack_port_t *port), (client, port));
DECL_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));
DECL_VOID_FUNCTION(jack_set_error_function, (void (*func)(const char *)), (func));
DECL_FUNCTION(int, jack_set_process_callback, (jack_client_t *client, JackProcessCallback process_callback, void *arg), (client, process_callback, arg));
DECL_FUNCTION(int, jack_set_freewheel_callback, (jack_client_t *client, JackFreewheelCallback freewheel_callback, void *arg), (client, freewheel_callback, arg));

DECL_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));
DECL_FUNCTION(int, jack_connect, (jack_client_t *client, const char *source_port, const char destination_port), (client, source_port, destination_port));
DECL_FUNCTION(const char
, jack_port_name, (const jack_port_t *port), (port));
DECL_FUNCTION(int, jack_set_port_connect_callback, (jack_client_t *client, JackPortConnectCallback connect_callback, void *arg),
(client, connect_callback, arg));
DECL_FUNCTION(jack_port_t *, jack_port_by_id, (jack_client_t *client, jack_port_id_t port_id), (client, port_id));

DECL_FUNCTION(jack_nframes_t, jack_midi_get_event_count, (void* port_buffer), (port_buffer));
DECL_FUNCTION(int, jack_midi_event_get, (jack_midi_event_t *event, void *port_buffer, jack_nframes_t event_index), (event, port_buffer, event_index));

DECL_FUNCTION(int, jack_session_reply, (jack_client_t *client, jack_session_event_t *event), (client, event));
DECL_FUNCTION(int, jack_set_session_callback, (jack_client_t *client, JackSessionCallback session_callback, void *arg),
(client, session_callback, arg));
DECL_VOID_FUNCTION(jack_session_event_free, (jack_session_event_t *event), (event));
[/code]

Thanks, I’ll give those a look very soon.
One thing I’m looking for is to have JACK working in Windows and Mac, so I guess I’ll make some small adjustments.

thank you very much!
please keep us updated about working with jack on windows and mac.

but anyway it may be worth to allow the original JackAudioIODevice register more ports than physically available.

matthias

Hi,

 


first of all I want to thank you, jpo, for your awesome contribution. yes When I'm trying to initialize your version of the jack-audio-device I get the following jack-log :
 


Jack: JackClient::SetupDriverSync driver sem in flush mode
Jack: JackPosixSemaphore::Connect name = jack_sem.1000_default_JACK
Jack: JackPosixSemaphore::Connect sem_getvalue 0
Jack: Clock source : system clock via clock_gettime
Jack: JackLibClient::Open name = JACK refnum = 4
Jack: JackClient::PortRegister ref = 4 name = JACK:1 type = 32 bit float mono audio port_index = 5
Jack: JackClient::PortRegister ref = 4 name = JACK:2 type = 32 bit float mono audio port_index = 6
Jack: JackClient::PortRegister ref = 4 name = JACK:3 type = 32 bit float mono audio port_index = 7
Jack: JackClient::PortRegister ref = 4 name = JACK:4 type = 32 bit float mono audio port_index = 8
Jack: JackClient::PortRegister ref = 4 name = JACK:eins type = 32 bit float mono audio port_index = 9
Jack: JackClient::PortRegister ref = 4 name = JACK:einsO type = 32 bit float mono audio port_index = 10
Jack: jack_set_session_callback ext_client 2765230 client 2765230 
Jack: jack_client_open JuceJackDummy
Jack: JackGenericClientChannel::ServerCheck = default
Jack: JackClientSocket::Connect : addr.sun_path /dev/shm/jack_default_1000_0
Jack: JackClientSocket::Close
Jack: JackLibClient::JackLibClient table = 2760c20
Jack: JackLibClient::Open name = JuceJackDummy
Jack: JackSocketClientChannel::Open name = JuceJackDummy
Jack: JackClientSocket::Connect : addr.sun_path /dev/shm/jack_default_1000_0
Jack: JackServerSocket::Bind : addr.sun_path /dev/shm/jack_JuceJackDummy_1000_0
Jack: JackSocketClientChannel::Start
Jack: JackPosixThread::StartImp : create non RT thread
Jack: JackPosixThread::ThreadHandler : start
Jack: JackSocketClientChannel::Init
Jack: JackServerSocket::Close /dev/shm/jack_JuceJackDummy_1000_0
Jack: JackClient::ClientNotify ref = 0 name = system notify = 0
Jack: JackClient::AddClient name = system, ref = 0 
Jack: JackPosixSemaphore::Connect name = jack_sem.1000_default_system
Jack: Already connected name = system
Jack: JackClient::ClientNotify ref = 1 name = freewheel notify = 0
Jack: JackClient::AddClient name = freewheel, ref = 1 
Jack: JackPosixSemaphore::Connect name = jack_sem.1000_default_freewheel
Jack: Already connected name = freewheel
Jack: JackClient::ClientNotify ref = 2 name = dbusapi notify = 0
Jack: JackClient::AddClient name = dbusapi, ref = 2 
Jack: JackPosixSemaphore::Connect name = jack_sem.1000_default_dbusapi
Jack: Already connected name = dbusapi
Jack: JackClient::ClientNotify ref = 3 name = qjackctl notify = 0
Jack: JackClient::AddClient name = qjackctl, ref = 3 
Jack: JackPosixSemaphore::Connect name = jack_sem.1000_default_qjackctl
Jack: Already connected name = qjackctl
Jack: JackClient::ClientNotify ref = 5 name = JuceJackDummy notify = 0
Jack: JackClient::AddClient name = JuceJackDummy, ref = 5 
Jack: JackPosixSemaphore::Connect name = jack_sem.1000_default_JuceJackDummy
Jack: JackPosixSemaphore::Connect sem_getvalue 0
Jack: JackClient::ClientNotify ref = 4 name = JACK notify = 0
Jack: JackClient::AddClient name = JACK, ref = 4 
Jack: JackPosixSemaphore::Connect name = jack_sem.1000_default_JACK
Jack: Already connected name = JACK
Jack: JackShmReadWritePtr1::Init 4 4294967295
Jack: Succeeded in locking 422 byte memory area
Jack: JackClient::SetupDriverSync driver sem in flush mode
Jack: JackPosixSemaphore::Connect name = jack_sem.1000_default_JuceJackDummy
Jack: Already connected name = JuceJackDummy
Jack: Clock source : system clock via clock_gettime
Jack: JackLibClient::Open name = JuceJackDummy refnum = 5
Jack: jack_client_close
Jack: JackClient::Close ref = 5
Jack: JackClient::Deactivate
Jack: JackSocketClientChannel::Stop
Jack: JackPosixThread::Kill
Jack: JackClient::ClientNotify ref = 5 name = JuceJackDummy notify = 1
Jack: JackClient::RemoveClient name = JuceJackDummy, ref = 5 
Jack: JackPosixSemaphore::Disconnect name = jack_sem.1000_default_JuceJackDummy
Jack: JackClientSocket::Close
Jack: JackClientSocket::Close
Jack: JackLibClient::~JackLibClient
Jack: JackShmReadWritePtr1::~JackShmReadWritePtr1 4
Jack: Succeeded in unlocking 422 byte memory area
Jack: jack_client_close res = 0
Jack: JackClient::Activate
Jack: JackPosixThread::StartImp : create non RT thread
Jack: JackPosixThread::ThreadHandler : start
Jack: JackClient::kBufferSizeCallback buffer_size = 1024
Jack: JackClient::Init : period = 23219 computation = 100 constraint = 23219
Jack: JackPosixThread::AcquireRealTimeImp priority = 5
Jack: JackClient::ClientNotify ref = 4 name = JACK notify = 2
Jack: JackClient::kActivateClient name = JACK ref = 4 
Jack: JackClient::Deactivate
Jack: JackClient::ClientNotify ref = 4 name = JACK notify = 18
Jack: JackClient::ClientNotify ref = 4 name = JACK notify = 18
Jack: JackClient::Deactivate res = 0
Jack: JackPosixThread::Kill
Jack: jack_client_close
Jack: JackClient::Close ref = 4
Jack: JackClient::Deactivate
Jack: JackSocketClientChannel::Stop
Jack: JackPosixThread::Kill
Jack: JackClientSocket::Close
Jack: JackClientSocket::Close
Jack: JackPosixSemaphore::Disconnect name = jack_sem.1000_default_JACK
Jack: JackLibClient::~JackLibClient
Jack: JackShmReadWritePtr1::~JackShmReadWritePtr1 3
Jack: Succeeded in unlocking 422 byte memory area
Jack: JackLibGlobals Destroy 2760c00
Jack: ~JackLibGlobals
Jack: JackPosixSemaphore::Disconnect name = jack_sem.1000_default_system
Jack: JackPosixSemaphore::Disconnect name = jack_sem.1000_default_freewheel
Jack: JackPosixSemaphore::Disconnect name = jack_sem.1000_default_dbusapi
Jack: JackPosixSemaphore::Disconnect name = jack_sem.1000_default_qjackctl
Jack: no message buffer overruns
Jack: JackPosixThread::Stop
Jack: JackPosixThread::ThreadHandler : exit
Jack: JackShmReadWritePtr::~JackShmReadWritePtr 1
Jack: Succeeded in unlocking 1186 byte memory area
Jack: JackShmReadWritePtr::~JackShmReadWritePtr 0
Jack: Succeeded in unlocking 82274202 byte memory area
Jack: jack_client_close res = 0

 


It immediately shuts down after booting. I already start the jack server before with qjackctl and expected the JuceJack-client to connect to that server. I know I'm doing something wrong, but the question would be what it could be.
 

The native jucey jack-audio-device works fine, but it only creates as many ports as supported by hardware and in my case I need more. crying

 

Thanks for the info.

are you running JACK with the temporary flag on?

because temporary is on it means JACK will auto-close when the first client is closed (in this case the juce scanner thing).

 

Hi,

 

I got it working after simply exchanging the native audioiodevicetype_jack with the new one.

 

I was using the AudioDeviceManager, so attempts to manually starting and connecting the device,  as I first tried, were always overwritten by the DeviceManager, which was hardwired to the native jack devicetype.

 

 

Thanks for your code @jpo.