Browse Source

Carla: Small engine rework, misc fixing

tags/v0.9.0
falkTX 13 years ago
parent
commit
6c2d23963b
16 changed files with 816 additions and 850 deletions
  1. +11
    -93
      c++/carla-backend/carla_backend_standalone.cpp
  2. +2
    -2
      c++/carla-backend/carla_bridge.cpp
  3. +124
    -61
      c++/carla-backend/carla_engine.cpp
  4. +17
    -85
      c++/carla-backend/carla_engine.h
  5. +425
    -371
      c++/carla-backend/carla_engine_jack.cpp
  6. +196
    -180
      c++/carla-backend/carla_engine_rtaudio.cpp
  7. +23
    -2
      c++/carla-backend/carla_native.cpp
  8. +2
    -38
      c++/carla-backend/carla_plugin.h
  9. +2
    -2
      c++/carla-backend/dssi.cpp
  10. +2
    -2
      c++/carla-backend/fluidsynth.cpp
  11. +3
    -3
      c++/carla-backend/ladspa.cpp
  12. +2
    -2
      c++/carla-backend/linuxsampler.cpp
  13. +2
    -2
      c++/carla-backend/lv2.cpp
  14. +1
    -2
      c++/carla-backend/plugins/carla_native.h
  15. +1
    -2
      c++/carla-backend/plugins/carla_nativemm.h
  16. +3
    -3
      c++/carla-backend/vst.cpp

+ 11
- 93
c++/carla-backend/carla_backend_standalone.cpp View File

@@ -83,63 +83,14 @@ unsigned int get_engine_driver_count()
{
qDebug("CarlaBackendStandalone::get_engine_driver_count()");

unsigned int count = 0;
#ifdef CARLA_ENGINE_JACK
count += 1;
#endif
#ifdef CARLA_ENGINE_RTAUDIO
std::vector<RtAudio::Api> apis;
RtAudio::getCompiledApi(apis);
count += apis.size();
#endif
return count;
return CarlaBackend::CarlaEngine::getDriverCount();
}

const char* get_engine_driver_name(unsigned int index)
{
qDebug("CarlaBackendStandalone::get_engine_driver_name(%i)", index);

#ifdef CARLA_ENGINE_JACK
if (index == 0)
return "JACK";
else
index -= 1;
#endif

#ifdef CARLA_ENGINE_RTAUDIO
std::vector<RtAudio::Api> apis;
RtAudio::getCompiledApi(apis);

if (index < apis.size())
{
RtAudio::Api api = apis[index];

switch (api)
{
case RtAudio::UNSPECIFIED:
return "Unspecified";
case RtAudio::LINUX_ALSA:
return "ALSA";
case RtAudio::LINUX_PULSE:
return "PulseAudio";
case RtAudio::LINUX_OSS:
return "OSS";
case RtAudio::UNIX_JACK:
return "JACK (RtAudio)";
case RtAudio::MACOSX_CORE:
return "CoreAudio";
case RtAudio::WINDOWS_ASIO:
return "ASIO";
case RtAudio::WINDOWS_DS:
return "DirectSound";
case RtAudio::RTAUDIO_DUMMY:
return "Dummy";
}
}
#endif

qWarning("CarlaBackendStandalone::get_engine_driver_name(%i) - invalid index", index);
return nullptr;
return CarlaBackend::CarlaEngine::getDriverName(index);
}

// -------------------------------------------------------------------------------------------------------------------
@@ -183,49 +134,9 @@ bool engine_init(const char* driver_name, const char* client_name)
qDebug("CarlaBackendStandalone::engine_init(\"%s\", \"%s\")", driver_name, client_name);
CARLA_ASSERT(! carlaEngine);

#ifdef CARLA_ENGINE_JACK
if (strcmp(driver_name, "JACK") == 0)
carlaEngine = new CarlaBackend::CarlaEngineJack;
#else
if (false)
pass();
#endif
carlaEngine = CarlaBackend::CarlaEngine::newDriverByName(driver_name);

#ifdef CARLA_ENGINE_RTAUDIO
#ifdef __LINUX_ALSA__
else if (strcmp(driver_name, "ALSA") == 0)
carlaEngine = new CarlaBackend::CarlaEngineRtAudio(RtAudio::LINUX_ALSA);
#endif
#ifdef __LINUX_PULSE__
else if (strcmp(driver_name, "PulseAudio") == 0)
carlaEngine = new CarlaBackend::CarlaEngineRtAudio(RtAudio::LINUX_PULSE);
#endif
#ifdef __LINUX_OSS__
else if (strcmp(driver_name, "OSS") == 0)
carlaEngine = new CarlaBackend::CarlaEngineRtAudio(RtAudio::LINUX_OSS);
#endif
#ifdef __UNIX_JACK__
else if (strcmp(driver_name, "JACK (RtAudio)") == 0)
carlaEngine = new CarlaBackend::CarlaEngineRtAudio(RtAudio::UNIX_JACK);
#endif
#ifdef __MACOSX_CORE__
else if (strcmp(driver_name, "CoreAudio") == 0)
carlaEngine = new CarlaBackend::CarlaEngineRtAudio(RtAudio::MACOSX_CORE);
#endif
#ifdef __WINDOWS_ASIO__
else if (strcmp(driver_name, "ASIO") == 0)
carlaEngine = new CarlaBackend::CarlaEngineRtAudio(RtAudio::WINDOWS_ASIO);
#endif
#ifdef __WINDOWS_DS__
else if (strcmp(driver_name, "DirectSound") == 0)
carlaEngine = new CarlaBackend::CarlaEngineRtAudio(RtAudio::WINDOWS_DS);
#endif
#ifdef __RTAUDIO_DUMMY__
else if (strcmp(driver_name, "Dummy") == 0)
carlaEngine = new CarlaBackend::CarlaEngineRtAudio(RtAudio::RTAUDIO_DUMMY);
#endif
#endif
else
if (! carlaEngine)
{
CarlaBackend::setLastError("The seleted audio driver is not available!");
return false;
@@ -245,7 +156,14 @@ bool engine_init(const char* driver_name, const char* client_name)
carlaEngineStarted = carlaEngine->init(client_name);

if (carlaEngineStarted)
{
CarlaBackend::setLastError("no error");
}
else if (carlaEngine)
{
delete carlaEngine;
carlaEngine = nullptr;
}

return carlaEngineStarted;
}


+ 2
- 2
c++/carla-backend/carla_bridge.cpp View File

@@ -427,7 +427,7 @@ public:
info.copyright = strdup(copyright);

if (! m_name)
m_name = x_engine->getUniqueName(name);
m_name = x_engine->getUniquePluginName(name);

break;
}
@@ -936,7 +936,7 @@ public:
m_filename = strdup(filename);

if (name)
m_name = x_engine->getUniqueName(name);
m_name = x_engine->getUniquePluginName(name);

// register plugin now so we can receive OSC (and wait for it)
x_engine->__bridgePluginRegister(m_id, this);


+ 124
- 61
c++/carla-backend/carla_engine.cpp View File

@@ -102,6 +102,127 @@ unsigned short CarlaEngine::maxPluginNumber()
return m_maxPluginNumber;
}

const char* CarlaEngine::getFixedClientName(const char* const clientName)
{
char* fixedName = strdup(clientName);
for (size_t i=0; i < strlen(fixedName); i++)
{
if (! (std::isalpha(fixedName[i]) || std::isdigit(fixedName[i])))
fixedName[i] = '_';
}
return fixedName;
}

unsigned int CarlaEngine::getDriverCount()
{
unsigned int count = 0;
#ifdef CARLA_ENGINE_JACK
count += 1;
#endif
#ifdef CARLA_ENGINE_RTAUDIO
std::vector<RtAudio::Api> apis;
RtAudio::getCompiledApi(apis);
count += apis.size();
#endif
return count;
}

const char* CarlaEngine::getDriverName(unsigned int index)
{
#ifdef CARLA_ENGINE_JACK
if (index == 0)
return "JACK";
else
index -= 1;
#endif

#ifdef CARLA_ENGINE_RTAUDIO
std::vector<RtAudio::Api> apis;
RtAudio::getCompiledApi(apis);

if (index < apis.size())
{
RtAudio::Api api = apis[index];

switch (api)
{
case RtAudio::UNSPECIFIED:
return "Unspecified";
case RtAudio::LINUX_ALSA:
return "ALSA";
case RtAudio::LINUX_PULSE:
return "PulseAudio";
case RtAudio::LINUX_OSS:
return "OSS";
case RtAudio::UNIX_JACK:
return "JACK (RtAudio)";
case RtAudio::MACOSX_CORE:
return "CoreAudio";
case RtAudio::WINDOWS_ASIO:
return "ASIO";
case RtAudio::WINDOWS_DS:
return "DirectSound";
case RtAudio::RTAUDIO_DUMMY:
return "Dummy";
}
}
#endif

qWarning("CarlaEngine::getDriverName(%i) - invalid index", index);
return nullptr;
}

CarlaEngine* CarlaEngine::newDriverByName(const char* driverName)
{
#ifdef CARLA_ENGINE_JACK
if (strcmp(driverName, "JACK") == 0)
return newJack();
#else
if (false)
pass();
#endif

#ifdef CARLA_ENGINE_RTAUDIO
#ifdef __LINUX_ALSA__
else if (strcmp(driverName, "ALSA") == 0)
return newRtAudio(RtAudio::LINUX_ALSA);
#endif
#ifdef __LINUX_PULSE__
else if (strcmp(driverName, "PulseAudio") == 0)
return newRtAudio(RtAudio::LINUX_PULSE);
#endif
#ifdef __LINUX_OSS__
else if (strcmp(driverName, "OSS") == 0)
return newRtAudio(RtAudio::LINUX_OSS);
#endif
#ifdef __UNIX_JACK__
else if (strcmp(driverName, "JACK (RtAudio)") == 0)
return newRtAudio(RtAudio::UNIX_JACK);
#endif
#ifdef __MACOSX_CORE__
else if (strcmp(driverName, "CoreAudio") == 0)
return newRtAudio(RtAudio::MACOSX_CORE);
#endif
#ifdef __WINDOWS_ASIO__
else if (strcmp(driverName, "ASIO") == 0)
return newRtAudio(RtAudio::WINDOWS_ASIO);
#endif
#ifdef __WINDOWS_DS__
else if (strcmp(driverName, "DirectSound") == 0)
return newRtAudio(RtAudio::WINDOWS_DS);
#endif
#ifdef __RTAUDIO_DUMMY__
else if (strcmp(driverName, "Dummy") == 0)
return newRtAudio(RtAudio::RTAUDIO_DUMMY);
#endif
#endif

return nullptr;
}

// -----------------------------------------------------------------------
// Virtual, per-engine type calls

bool CarlaEngine::init(const char* const clientName)
{
qDebug("CarlaEngine::init(\"%s\")", clientName);
@@ -169,9 +290,10 @@ CarlaPlugin* CarlaEngine::getPluginUnchecked(const unsigned short id) const
return m_carlaPlugins[id];
}

const char* CarlaEngine::getUniqueName(const char* const name)
const char* CarlaEngine::getUniquePluginName(const char* const name)
{
qDebug("CarlaEngine::getUniqueName(\"%s\")", name);
qDebug("CarlaEngine::getUniquePluginName(\"%s\")", name);
CARLA_ASSERT(name);

QString qname(name);

@@ -695,10 +817,6 @@ CarlaEngineClient::~CarlaEngineClient()
#ifdef CARLA_ENGINE_JACK
if (handle.jackClient)
jackbridge_client_close(handle.jackClient);
#endif
#ifdef CARLA_ENGINE_RTAUDIO
if (handle.rtAudioPtr)
delete handle.rtAudioPtr;
#endif
}
}
@@ -717,10 +835,6 @@ void CarlaEngineClient::activate()
#ifdef CARLA_ENGINE_JACK
if (handle.jackClient)
jackbridge_activate(handle.jackClient);
#endif
#ifdef CARLA_ENGINE_RTAUDIO
if (handle.rtAudioPtr)
handle.rtAudioPtr->startStream();
#endif
}
}
@@ -742,10 +856,6 @@ void CarlaEngineClient::deactivate()
#ifdef CARLA_ENGINE_JACK
if (handle.jackClient)
jackbridge_deactivate(handle.jackClient);
#endif
#ifdef CARLA_ENGINE_RTAUDIO
if (handle.rtAudioPtr)
handle.rtAudioPtr->stopStream();
#endif
}
}
@@ -771,10 +881,6 @@ bool CarlaEngineClient::isOk() const
#ifdef CARLA_ENGINE_JACK
if (handle.type == CarlaEngineTypeJack)
return bool(handle.jackClient);
#endif
#ifdef CARLA_ENGINE_RTAUDIO
if (handle.type == CarlaEngineTypeRtAudio)
return bool(handle.rtAudioPtr);
#endif
}

@@ -809,13 +915,6 @@ const CarlaEngineBasePort* CarlaEngineClient::addPort(const CarlaEnginePortType
}
}
#endif

#ifdef CARLA_ENGINE_RTAUDIO
if (handle.type == CarlaEngineTypeRtAudio)
{
// TODO
}
#endif
}

switch (portType)
@@ -857,10 +956,6 @@ CarlaEngineBasePort::~CarlaEngineBasePort()
if (handle.jackClient && handle.jackPort)
jackbridge_port_unregister(handle.jackClient, handle.jackPort);
#endif

#ifdef CARLA_ENGINE_RTAUDIO
// TODO
#endif
}

// -------------------------------------------------------------------------------------------------------------------
@@ -918,10 +1013,6 @@ void CarlaEngineControlPort::initBuffer(CarlaEngine* const engine)
jackbridge_midi_clear_buffer(buffer);
}
#endif

#ifdef CARLA_ENGINE_RTAUDIO
// TODO
#endif
}

uint32_t CarlaEngineControlPort::getEventCount()
@@ -954,10 +1045,6 @@ uint32_t CarlaEngineControlPort::getEventCount()
return jackbridge_midi_get_event_count(buffer);
#endif

#ifdef CARLA_ENGINE_RTAUDIO
// TODO
#endif

return 0;
}

@@ -1037,10 +1124,6 @@ const CarlaEngineControlEvent* CarlaEngineControlPort::getEvent(uint32_t index)
}
#endif

#ifdef CARLA_ENGINE_RTAUDIO
// TODO
#endif

return nullptr;
}

@@ -1116,10 +1199,6 @@ void CarlaEngineControlPort::writeEvent(CarlaEngineControlEventType type, uint32
}
}
#endif

#ifdef CARLA_ENGINE_RTAUDIO
// TODO
#endif
}

// -------------------------------------------------------------------------------------------------------------------
@@ -1152,10 +1231,6 @@ void CarlaEngineMidiPort::initBuffer(CarlaEngine* const engine)
jackbridge_midi_clear_buffer(buffer);
}
#endif

#ifdef CARLA_ENGINE_RTAUDIO
// TODO
#endif
}

uint32_t CarlaEngineMidiPort::getEventCount()
@@ -1188,10 +1263,6 @@ uint32_t CarlaEngineMidiPort::getEventCount()
return jackbridge_midi_get_event_count(buffer);
#endif

#ifdef CARLA_ENGINE_RTAUDIO
// TODO
#endif

return 0;
}

@@ -1232,10 +1303,6 @@ const CarlaEngineMidiEvent* CarlaEngineMidiPort::getEvent(uint32_t index)
}
#endif

#ifdef CARLA_ENGINE_RTAUDIO
// TODO
#endif

return nullptr;
}

@@ -1275,10 +1342,6 @@ void CarlaEngineMidiPort::writeEvent(uint32_t time, const uint8_t* data, uint8_t
if (handle.jackPort)
jackbridge_midi_event_write(buffer, time, data, size);
#endif

#ifdef CARLA_ENGINE_RTAUDIO
// TODO
#endif
}

// -------------------------------------------------------------------------------------------------------------------


+ 17
- 85
c++/carla-backend/carla_engine.h View File

@@ -142,18 +142,12 @@ struct CarlaEngineClientNativeHandle {
#ifdef CARLA_ENGINE_JACK
jack_client_t* jackClient;
#endif
#ifdef CARLA_ENGINE_RTAUDIO
RtAudio* rtAudioPtr;
#endif

CarlaEngineClientNativeHandle()
{
type = CarlaEngineTypeNull;
#ifdef CARLA_ENGINE_JACK
jackClient = nullptr;
#endif
#ifdef CARLA_ENGINE_RTAUDIO
rtAudioPtr = nullptr;
#endif
}
};
@@ -199,6 +193,11 @@ public:
static int maxClientNameSize();
static int maxPortNameSize();
static unsigned short maxPluginNumber();
static const char* getFixedClientName(const char* const clientName);

static unsigned int getDriverCount();
static const char* getDriverName(unsigned int index);
static CarlaEngine* newDriverByName(const char* driverName);

// -------------------------------------------------------------------
// Virtual, per-engine type calls
@@ -216,7 +215,7 @@ public:
short getNewPluginId() const;
CarlaPlugin* getPlugin(const unsigned short id) const;
CarlaPlugin* getPluginUnchecked(const unsigned short id) const;
const char* getUniqueName(const char* const name);
const char* getUniquePluginName(const char* const name);

short addPlugin(const BinaryType btype, const PluginType ptype, const char* const filename, const char* const name, const char* const label, void* const extra = nullptr);
short addPlugin(const PluginType ptype, const char* const filename, const char* const name, const char* const label, void* const extra = nullptr);
@@ -404,6 +403,13 @@ private:
double m_outsPeak[MAX_PLUGINS * MAX_PEAKS];

static unsigned short m_maxPluginNumber;

#ifdef CARLA_ENGINE_JACK
static CarlaEngine* newJack();
#endif
#ifdef CARLA_ENGINE_RTAUDIO
static CarlaEngine* newRtAudio(RtAudio::Api api);
#endif
};

// -----------------------------------------------------------------------
@@ -429,6 +435,7 @@ private:

// -----------------------------------------------------------------------

// base
class CarlaEngineBasePort
{
public:
@@ -443,6 +450,7 @@ protected:
const CarlaEnginePortNativeHandle handle;
};

// audio
class CarlaEngineAudioPort : public CarlaEngineBasePort
{
public:
@@ -455,6 +463,7 @@ public:
#endif
};

// control
class CarlaEngineControlPort : public CarlaEngineBasePort
{
public:
@@ -468,6 +477,7 @@ public:
void writeEvent(CarlaEngineControlEventType type, uint32_t time, uint8_t channel, uint8_t controller, double value);
};

// midi
class CarlaEngineMidiPort : public CarlaEngineBasePort
{
public:
@@ -483,84 +493,6 @@ public:

// -----------------------------------------------------------------------

#ifdef CARLA_ENGINE_JACK
class CarlaEngineJack : public CarlaEngine
{
public:
CarlaEngineJack();
~CarlaEngineJack();

// -------------------------------------

bool init(const char* const clientName);
bool close();

bool isOffline();
bool isRunning();

CarlaEngineClient* addClient(CarlaPlugin* const plugin);

// -------------------------------------

void handleSampleRateCallback(double newSampleRate);
void handleBufferSizeCallback(uint32_t newBufferSize);
void handleFreewheelCallback(bool isFreewheel);
void handleProcessCallback(uint32_t nframes);
void handleShutdownCallback();

// -------------------------------------

private:
jack_client_t* client;
jack_transport_state_t state;
jack_position_t pos;
bool freewheel;

// -------------------------------------

#ifndef BUILD_BRIDGE
static const unsigned short rackPortAudioIn1 = 0;
static const unsigned short rackPortAudioIn2 = 1;
static const unsigned short rackPortAudioOut1 = 2;
static const unsigned short rackPortAudioOut2 = 3;
static const unsigned short rackPortControlIn = 4;
static const unsigned short rackPortControlOut = 5;
static const unsigned short rackPortMidiIn = 6;
static const unsigned short rackPortMidiOut = 7;
static const unsigned short rackPortCount = 8;
jack_port_t* rackJackPorts[rackPortCount];
#endif
};
#endif

// -----------------------------------------------------------------------

#ifdef CARLA_ENGINE_RTAUDIO
class CarlaEngineRtAudio : public CarlaEngine
{
public:
CarlaEngineRtAudio(RtAudio::Api api);
~CarlaEngineRtAudio();

// -------------------------------------

bool init(const char* const clientName);
bool close();

bool isOffline();
bool isRunning();

CarlaEngineClient* addClient(CarlaPlugin* const plugin);

// -------------------------------------

void handleProcessCallback(void* outputBuffer, void* inputBuffer, unsigned int nframes, double streamTime, RtAudioStreamStatus status);

private:
RtAudio adac;
};
#endif

/**@}*/

CARLA_BACKEND_END_NAMESPACE


+ 425
- 371
c++/carla-backend/carla_engine_jack.cpp View File

@@ -20,492 +20,546 @@
#include "carla_engine.h"
#include "carla_plugin.h"

#include <iostream>

CARLA_BACKEND_START_NAMESPACE

// -------------------------------------------------------------------------------------------------------------------
// static JACK<->Engine calls

static int carla_jack_srate_callback(jack_nframes_t newSampleRate, void* arg)
{
CarlaEngineJack* const engine = (CarlaEngineJack*)arg;
engine->handleSampleRateCallback(newSampleRate);
return 0;
}

static int carla_jack_bufsize_callback(jack_nframes_t newBufferSize, void* arg)
{
CarlaEngineJack* const engine = (CarlaEngineJack*)arg;
engine->handleBufferSizeCallback(newBufferSize);
return 0;
}

static void carla_jack_freewheel_callback(int starting, void* arg)
{
CarlaEngineJack* const engine = (CarlaEngineJack*)arg;
engine->handleFreewheelCallback(bool(starting));
}

static int carla_jack_process_callback(jack_nframes_t nframes, void* arg)
{
CarlaEngineJack* const engine = (CarlaEngineJack*)arg;
engine->handleProcessCallback(nframes);
return 0;
}
// -----------------------------------------

static int carla_jack_process_callback_plugin(jack_nframes_t nframes, void* arg)
class CarlaEngineJack : public CarlaEngine
{
CarlaPlugin* const plugin = (CarlaPlugin*)arg;
if (plugin && plugin->enabled())
{
plugin->engineProcessLock();
plugin->initBuffers();
plugin->process_jack(nframes);
plugin->engineProcessUnlock();
}
return 0;
}

static void carla_jack_shutdown_callback(void* arg)
{
CarlaEngineJack* const engine = (CarlaEngineJack*)arg;
engine->handleShutdownCallback();
}

// -------------------------------------------------------------------------------------------------------------------
// Carla Engine (JACK)

CarlaEngineJack::CarlaEngineJack()
: CarlaEngine()
public:
CarlaEngineJack()
: CarlaEngine()
#ifndef BUILD_BRIDGE
# ifdef Q_COMPILER_INITIALIZER_LISTS
, rackJackPorts{nullptr}
, rackJackPorts{nullptr}
# endif
#endif
{
qDebug("CarlaEngineJack::CarlaEngineJack()");
{
qDebug("CarlaEngineJack::CarlaEngineJack()");

type = CarlaEngineTypeJack;
type = CarlaEngineTypeJack;

client = nullptr;
state = JackTransportStopped;
freewheel = false;
client = nullptr;
state = JackTransportStopped;
freewheel = false;

memset(&pos, 0, sizeof(jack_position_t));
memset(&pos, 0, sizeof(jack_position_t));

#ifndef BUILD_BRIDGE
# ifndef Q_COMPILER_INITIALIZER_LISTS
for (unsigned short i=0; i < rackPortCount; i++)
rackJackPorts[i] = nullptr;
for (unsigned short i=0; i < rackPortCount; i++)
rackJackPorts[i] = nullptr;
# endif
#endif
}
}

CarlaEngineJack::~CarlaEngineJack()
{
qDebug("CarlaEngineJack::~CarlaEngineJack()");
}
~CarlaEngineJack()
{
qDebug("CarlaEngineJack::~CarlaEngineJack()");
}

// -------------------------------------------------------------------------------------------------------------------
// -------------------------------------

bool CarlaEngineJack::init(const char* const clientName)
{
qDebug("CarlaEngineJack::init(\"%s\")", clientName);
bool init(const char* const clientName)
{
qDebug("CarlaEngineJack::init(\"%s\")", clientName);

client = jackbridge_client_open(clientName, JackNullOption, nullptr);
state = JackTransportStopped;
freewheel = false;
client = jackbridge_client_open(clientName, JackNullOption, nullptr);
state = JackTransportStopped;
freewheel = false;

if (client)
{
sampleRate = jackbridge_get_sample_rate(client);
bufferSize = jackbridge_get_buffer_size(client);
if (client)
{
sampleRate = jackbridge_get_sample_rate(client);
bufferSize = jackbridge_get_buffer_size(client);

jackbridge_set_sample_rate_callback(client, carla_jack_srate_callback, this);
jackbridge_set_buffer_size_callback(client, carla_jack_bufsize_callback, this);
jackbridge_set_freewheel_callback(client, carla_jack_freewheel_callback, this);
jackbridge_set_process_callback(client, carla_jack_process_callback, this);
jackbridge_on_shutdown(client, carla_jack_shutdown_callback, this);
jackbridge_set_sample_rate_callback(client, carla_jack_srate_callback, this);
jackbridge_set_buffer_size_callback(client, carla_jack_bufsize_callback, this);
jackbridge_set_freewheel_callback(client, carla_jack_freewheel_callback, this);
jackbridge_set_process_callback(client, carla_jack_process_callback, this);
jackbridge_on_shutdown(client, carla_jack_shutdown_callback, this);

#ifndef BUILD_BRIDGE
if (carlaOptions.processMode == PROCESS_MODE_CONTINUOUS_RACK)
{
rackJackPorts[rackPortAudioIn1] = jackbridge_port_register(client, "in1", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
rackJackPorts[rackPortAudioIn2] = jackbridge_port_register(client, "in2", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
rackJackPorts[rackPortAudioOut1] = jackbridge_port_register(client, "out1", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
rackJackPorts[rackPortAudioOut2] = jackbridge_port_register(client, "out2", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
rackJackPorts[rackPortControlIn] = jackbridge_port_register(client, "control-in", JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0);
rackJackPorts[rackPortControlOut] = jackbridge_port_register(client, "control-out", JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0);
rackJackPorts[rackPortMidiIn] = jackbridge_port_register(client, "midi-in", JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0);
rackJackPorts[rackPortMidiOut] = jackbridge_port_register(client, "midi-out", JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0);
}
if (carlaOptions.processMode == PROCESS_MODE_CONTINUOUS_RACK)
{
rackJackPorts[rackPortAudioIn1] = jackbridge_port_register(client, "in1", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
rackJackPorts[rackPortAudioIn2] = jackbridge_port_register(client, "in2", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
rackJackPorts[rackPortAudioOut1] = jackbridge_port_register(client, "out1", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
rackJackPorts[rackPortAudioOut2] = jackbridge_port_register(client, "out2", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
rackJackPorts[rackPortControlIn] = jackbridge_port_register(client, "control-in", JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0);
rackJackPorts[rackPortControlOut] = jackbridge_port_register(client, "control-out", JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0);
rackJackPorts[rackPortMidiIn] = jackbridge_port_register(client, "midi-in", JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0);
rackJackPorts[rackPortMidiOut] = jackbridge_port_register(client, "midi-out", JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0);
}
#endif

if (jackbridge_activate(client) == 0)
{
// set client name, fixed for OSC usage
// FIXME - put this in shared?
char* fixedName = strdup(jackbridge_get_client_name(client));
for (size_t i=0; i < strlen(fixedName); i++)
if (jackbridge_activate(client) == 0)
{
name = getFixedClientName(jackbridge_get_client_name(client));
CarlaEngine::init(name);
return true;
}
else
{
if (! (std::isalpha(fixedName[i]) || std::isdigit(fixedName[i])))
fixedName[i] = '_';
setLastError("Failed to activate the JACK client");
client = nullptr;
}
}
else
setLastError("Failed to create new JACK client");

name = strdup(fixedName);
free((void*)fixedName);
return false;
}

CarlaEngine::init(name);
bool close()
{
qDebug("CarlaEngineJack::close()");
CarlaEngine::close();

return true;
if (name)
{
free((void*)name);
name = nullptr;
}
else

if (jackbridge_deactivate(client) == 0)
{
setLastError("Failed to activate the JACK client");
client = nullptr;
#ifndef BUILD_BRIDGE
if (carlaOptions.processMode == PROCESS_MODE_CONTINUOUS_RACK)
{
jackbridge_port_unregister(client, rackJackPorts[rackPortAudioIn1]);
jackbridge_port_unregister(client, rackJackPorts[rackPortAudioIn2]);
jackbridge_port_unregister(client, rackJackPorts[rackPortAudioOut1]);
jackbridge_port_unregister(client, rackJackPorts[rackPortAudioOut2]);
jackbridge_port_unregister(client, rackJackPorts[rackPortControlIn]);
jackbridge_port_unregister(client, rackJackPorts[rackPortControlOut]);
jackbridge_port_unregister(client, rackJackPorts[rackPortMidiIn]);
jackbridge_port_unregister(client, rackJackPorts[rackPortMidiOut]);
}
#endif

if (jackbridge_client_close(client) == 0)
{
client = nullptr;
return true;
}
else
setLastError("Failed to close the JACK client");
}
}
else
setLastError("Failed to create new JACK client");
else
setLastError("Failed to deactivate the JACK client");

return false;
}
client = nullptr;
return false;
}

bool CarlaEngineJack::close()
{
qDebug("CarlaEngineJack::close()");
CarlaEngine::close();
bool isOffline()
{
return freewheel;
}

if (name)
bool isRunning()
{
free((void*)name);
name = nullptr;
return bool(client);
}

if (jackbridge_deactivate(client) == 0)
CarlaEngineClient* addClient(CarlaPlugin* const plugin)
{
CarlaEngineClientNativeHandle handle;
handle.type = CarlaEngineTypeJack;

#ifndef BUILD_BRIDGE
if (carlaOptions.processMode == PROCESS_MODE_CONTINUOUS_RACK)
if (carlaOptions.processMode == PROCESS_MODE_SINGLE_CLIENT)
{
jackbridge_port_unregister(client, rackJackPorts[rackPortAudioIn1]);
jackbridge_port_unregister(client, rackJackPorts[rackPortAudioIn2]);
jackbridge_port_unregister(client, rackJackPorts[rackPortAudioOut1]);
jackbridge_port_unregister(client, rackJackPorts[rackPortAudioOut2]);
jackbridge_port_unregister(client, rackJackPorts[rackPortControlIn]);
jackbridge_port_unregister(client, rackJackPorts[rackPortControlOut]);
jackbridge_port_unregister(client, rackJackPorts[rackPortMidiIn]);
jackbridge_port_unregister(client, rackJackPorts[rackPortMidiOut]);
handle.jackClient = client;
}
else if (carlaOptions.processMode == PROCESS_MODE_MULTIPLE_CLIENTS)
#endif

if (jackbridge_client_close(client) == 0)
{
client = nullptr;
return true;
handle.jackClient = jackbridge_client_open(plugin->name(), JackNullOption, nullptr);
jackbridge_set_process_callback(handle.jackClient, carla_jack_process_callback_plugin, plugin);
}
else
setLastError("Failed to close the JACK client");
}
else
setLastError("Failed to deactivate the JACK client");

client = nullptr;
return false;
}

bool CarlaEngineJack::isOffline()
{
return freewheel;
}

bool CarlaEngineJack::isRunning()
{
return bool(client);
}
return new CarlaEngineClient(handle);
}

CarlaEngineClient* CarlaEngineJack::addClient(CarlaPlugin* const plugin)
{
CarlaEngineClientNativeHandle handle;
handle.type = type;
// -------------------------------------

#ifndef BUILD_BRIDGE
if (carlaOptions.processMode == PROCESS_MODE_SINGLE_CLIENT)
{
handle.jackClient = client;
}
else if (carlaOptions.processMode == PROCESS_MODE_MULTIPLE_CLIENTS)
#endif
protected:
void handleSampleRateCallback(double newSampleRate)
{
handle.jackClient = jackbridge_client_open(plugin->name(), JackNullOption, nullptr);
jackbridge_set_process_callback(handle.jackClient, carla_jack_process_callback_plugin, plugin);
sampleRate = newSampleRate;
}
//else if (carla_options.process_mode == PROCESS_MODE_CONTINUOUS_RACK)
//{
//}

return new CarlaEngineClient(handle);
}

// -------------------------------------------------------------------------------------------------------------------

void CarlaEngineJack::handleSampleRateCallback(double newSampleRate)
{
sampleRate = newSampleRate;
}

void CarlaEngineJack::handleBufferSizeCallback(uint32_t newBufferSize)
{
void handleBufferSizeCallback(uint32_t newBufferSize)
{
#ifndef BUILD_BRIDGE
if (carlaOptions.processHighPrecision)
return;
if (carlaOptions.processHighPrecision)
return;
#endif

bufferSizeChanged(newBufferSize);
}
bufferSizeChanged(newBufferSize);
}

void CarlaEngineJack::handleFreewheelCallback(bool isFreewheel)
{
freewheel = isFreewheel;
}
void handleFreewheelCallback(bool isFreewheel)
{
freewheel = isFreewheel;
}

void CarlaEngineJack::handleProcessCallback(uint32_t nframes)
{
void handleProcessCallback(uint32_t nframes)
{
#ifndef BUILD_BRIDGE
if (maxPluginNumber() == 0)
return;
if (maxPluginNumber() == 0)
return;
#endif

state = jackbridge_transport_query(client, &pos);
state = jackbridge_transport_query(client, &pos);

timeInfo.playing = (state != JackTransportStopped);
timeInfo.playing = (state != JackTransportStopped);

if (pos.unique_1 == pos.unique_2)
{
timeInfo.frame = pos.frame;
timeInfo.time = pos.usecs;

if (pos.valid & JackPositionBBT)
if (pos.unique_1 == pos.unique_2)
{
timeInfo.valid = CarlaEngineTimeBBT;
timeInfo.bbt.bar = pos.bar;
timeInfo.bbt.beat = pos.beat;
timeInfo.bbt.tick = pos.tick;
timeInfo.bbt.bar_start_tick = pos.bar_start_tick;
timeInfo.bbt.beats_per_bar = pos.beats_per_bar;
timeInfo.bbt.beat_type = pos.beat_type;
timeInfo.bbt.ticks_per_beat = pos.ticks_per_beat;
timeInfo.bbt.beats_per_minute = pos.beats_per_minute;
timeInfo.frame = pos.frame;
timeInfo.time = pos.usecs;

if (pos.valid & JackPositionBBT)
{
timeInfo.valid = CarlaEngineTimeBBT;
timeInfo.bbt.bar = pos.bar;
timeInfo.bbt.beat = pos.beat;
timeInfo.bbt.tick = pos.tick;
timeInfo.bbt.bar_start_tick = pos.bar_start_tick;
timeInfo.bbt.beats_per_bar = pos.beats_per_bar;
timeInfo.bbt.beat_type = pos.beat_type;
timeInfo.bbt.ticks_per_beat = pos.ticks_per_beat;
timeInfo.bbt.beats_per_minute = pos.beats_per_minute;
}
else
timeInfo.valid = 0;
}
else
{
timeInfo.frame = 0;
timeInfo.valid = 0;
}
else
{
timeInfo.frame = 0;
timeInfo.valid = 0;
}
}

#ifndef BUILD_BRIDGE
if (carlaOptions.processMode == PROCESS_MODE_SINGLE_CLIENT)
{
for (unsigned short i=0, max=maxPluginNumber(); i < max; i++)
if (carlaOptions.processMode == PROCESS_MODE_SINGLE_CLIENT)
{
CarlaPlugin* const plugin = getPluginUnchecked(i);

if (plugin && plugin->enabled())
for (unsigned short i=0, max=maxPluginNumber(); i < max; i++)
{
plugin->engineProcessLock();
plugin->initBuffers();
plugin->process_jack(nframes);
plugin->engineProcessUnlock();
CarlaPlugin* const plugin = getPluginUnchecked(i);

if (plugin && plugin->enabled())
{
plugin->engineProcessLock();
plugin->initBuffers();
processPlugin(plugin, nframes);
plugin->engineProcessUnlock();
}
}
}
}
else if (carlaOptions.processMode == PROCESS_MODE_CONTINUOUS_RACK)
{
// get buffers from jack
float* audioIn1 = (float*)jackbridge_port_get_buffer(rackJackPorts[rackPortAudioIn1], nframes);
float* audioIn2 = (float*)jackbridge_port_get_buffer(rackJackPorts[rackPortAudioIn2], nframes);
float* audioOut1 = (float*)jackbridge_port_get_buffer(rackJackPorts[rackPortAudioOut1], nframes);
float* audioOut2 = (float*)jackbridge_port_get_buffer(rackJackPorts[rackPortAudioOut2], nframes);
void* controlIn = jackbridge_port_get_buffer(rackJackPorts[rackPortControlIn], nframes);
void* controlOut = jackbridge_port_get_buffer(rackJackPorts[rackPortControlOut], nframes);
void* midiIn = jackbridge_port_get_buffer(rackJackPorts[rackPortMidiIn], nframes);
void* midiOut = jackbridge_port_get_buffer(rackJackPorts[rackPortMidiOut], nframes);

// assert buffers
CARLA_ASSERT(audioIn1);
CARLA_ASSERT(audioIn2);
CARLA_ASSERT(audioOut1);
CARLA_ASSERT(audioOut2);
CARLA_ASSERT(controlIn);
CARLA_ASSERT(controlOut);
CARLA_ASSERT(midiIn);
CARLA_ASSERT(midiOut);

// create audio buffers
float* inBuf[2] = { audioIn1, audioIn2 };
float* outBuf[2] = { audioOut1, audioOut2 };

// initialize control input
memset(rackControlEventsIn, 0, sizeof(CarlaEngineControlEvent)*MAX_ENGINE_CONTROL_EVENTS);
else if (carlaOptions.processMode == PROCESS_MODE_CONTINUOUS_RACK)
{
jackbridge_midi_event_t jackEvent;
const uint32_t jackEventCount = jackbridge_midi_get_event_count(controlIn);

uint32_t carlaEventIndex = 0;

for (uint32_t jackEventIndex=0; jackEventIndex < jackEventCount; jackEventIndex++)
// get buffers from jack
float* audioIn1 = (float*)jackbridge_port_get_buffer(rackJackPorts[rackPortAudioIn1], nframes);
float* audioIn2 = (float*)jackbridge_port_get_buffer(rackJackPorts[rackPortAudioIn2], nframes);
float* audioOut1 = (float*)jackbridge_port_get_buffer(rackJackPorts[rackPortAudioOut1], nframes);
float* audioOut2 = (float*)jackbridge_port_get_buffer(rackJackPorts[rackPortAudioOut2], nframes);
void* controlIn = jackbridge_port_get_buffer(rackJackPorts[rackPortControlIn], nframes);
void* controlOut = jackbridge_port_get_buffer(rackJackPorts[rackPortControlOut], nframes);
void* midiIn = jackbridge_port_get_buffer(rackJackPorts[rackPortMidiIn], nframes);
void* midiOut = jackbridge_port_get_buffer(rackJackPorts[rackPortMidiOut], nframes);

// assert buffers
CARLA_ASSERT(audioIn1);
CARLA_ASSERT(audioIn2);
CARLA_ASSERT(audioOut1);
CARLA_ASSERT(audioOut2);
CARLA_ASSERT(controlIn);
CARLA_ASSERT(controlOut);
CARLA_ASSERT(midiIn);
CARLA_ASSERT(midiOut);

// create audio buffers
float* inBuf[2] = { audioIn1, audioIn2 };
float* outBuf[2] = { audioOut1, audioOut2 };

// initialize control input
memset(rackControlEventsIn, 0, sizeof(CarlaEngineControlEvent)*MAX_ENGINE_CONTROL_EVENTS);
{
if (jackbridge_midi_event_get(&jackEvent, controlIn, jackEventIndex) != 0)
continue;
jackbridge_midi_event_t jackEvent;
const uint32_t jackEventCount = jackbridge_midi_get_event_count(controlIn);

CarlaEngineControlEvent* const carlaEvent = &rackControlEventsIn[carlaEventIndex++];
uint32_t carlaEventIndex = 0;

uint8_t midiStatus = jackEvent.buffer[0];
uint8_t midiChannel = midiStatus & 0x0F;
for (uint32_t jackEventIndex=0; jackEventIndex < jackEventCount; jackEventIndex++)
{
if (jackbridge_midi_event_get(&jackEvent, controlIn, jackEventIndex) != 0)
continue;

carlaEvent->time = jackEvent.time;
carlaEvent->channel = midiChannel;
CarlaEngineControlEvent* const carlaEvent = &rackControlEventsIn[carlaEventIndex++];

if (MIDI_IS_STATUS_CONTROL_CHANGE(midiStatus))
{
uint8_t midiControl = jackEvent.buffer[1];
uint8_t midiStatus = jackEvent.buffer[0];
uint8_t midiChannel = midiStatus & 0x0F;

if (MIDI_IS_CONTROL_BANK_SELECT(midiControl))
{
uint8_t midiBank = jackEvent.buffer[2];
carlaEvent->type = CarlaEngineEventMidiBankChange;
carlaEvent->value = midiBank;
}
else if (midiControl == MIDI_CONTROL_ALL_SOUND_OFF)
carlaEvent->time = jackEvent.time;
carlaEvent->channel = midiChannel;

if (MIDI_IS_STATUS_CONTROL_CHANGE(midiStatus))
{
carlaEvent->type = CarlaEngineEventAllSoundOff;
uint8_t midiControl = jackEvent.buffer[1];

if (MIDI_IS_CONTROL_BANK_SELECT(midiControl))
{
uint8_t midiBank = jackEvent.buffer[2];
carlaEvent->type = CarlaEngineEventMidiBankChange;
carlaEvent->value = midiBank;
}
else if (midiControl == MIDI_CONTROL_ALL_SOUND_OFF)
{
carlaEvent->type = CarlaEngineEventAllSoundOff;
}
else if (midiControl == MIDI_CONTROL_ALL_NOTES_OFF)
{
carlaEvent->type = CarlaEngineEventAllNotesOff;
}
else
{
uint8_t midiValue = jackEvent.buffer[2];
carlaEvent->type = CarlaEngineEventControlChange;
carlaEvent->controller = midiControl;
carlaEvent->value = double(midiValue)/127;
}
}
else if (midiControl == MIDI_CONTROL_ALL_NOTES_OFF)
else if (MIDI_IS_STATUS_PROGRAM_CHANGE(midiStatus))
{
carlaEvent->type = CarlaEngineEventAllNotesOff;
uint8_t midiProgram = jackEvent.buffer[1];
carlaEvent->type = CarlaEngineEventMidiProgramChange;
carlaEvent->value = midiProgram;
}
else
}
}

// initialize midi input
memset(rackMidiEventsIn, 0, sizeof(CarlaEngineMidiEvent)*MAX_ENGINE_MIDI_EVENTS);
{
uint32_t i = 0, j = 0;
jackbridge_midi_event_t jackEvent;

while (jackbridge_midi_event_get(&jackEvent, midiIn, j++) == 0)
{
if (i == MAX_ENGINE_MIDI_EVENTS)
break;

if (jackEvent.size < 4)
{
uint8_t midiValue = jackEvent.buffer[2];
carlaEvent->type = CarlaEngineEventControlChange;
carlaEvent->controller = midiControl;
carlaEvent->value = double(midiValue)/127;
rackMidiEventsIn[i].time = jackEvent.time;
rackMidiEventsIn[i].size = jackEvent.size;
memcpy(rackMidiEventsIn[i].data, jackEvent.buffer, jackEvent.size);
i += 1;
}
}
else if (MIDI_IS_STATUS_PROGRAM_CHANGE(midiStatus))
}

// process rack
processRack(inBuf, outBuf, nframes);

// output control
{
jackbridge_midi_clear_buffer(controlOut);

for (unsigned short i=0; i < MAX_ENGINE_CONTROL_EVENTS; i++)
{
uint8_t midiProgram = jackEvent.buffer[1];
carlaEvent->type = CarlaEngineEventMidiProgramChange;
carlaEvent->value = midiProgram;
CarlaEngineControlEvent* const event = &rackControlEventsOut[i];

if (event->type == CarlaEngineEventControlChange && MIDI_IS_CONTROL_BANK_SELECT(event->controller))
event->type = CarlaEngineEventMidiBankChange;

uint8_t data[4] = { 0 };

switch (event->type)
{
case CarlaEngineEventNull:
break;
case CarlaEngineEventControlChange:
data[0] = MIDI_STATUS_CONTROL_CHANGE + event->channel;
data[1] = event->controller;
data[2] = event->value * 127;
jackbridge_midi_event_write(controlOut, event->time, data, 3);
break;
case CarlaEngineEventMidiBankChange:
data[0] = MIDI_STATUS_CONTROL_CHANGE + event->channel;
data[1] = MIDI_CONTROL_BANK_SELECT;
data[2] = event->value;
jackbridge_midi_event_write(controlOut, event->time, data, 3);
break;
case CarlaEngineEventMidiProgramChange:
data[0] = MIDI_STATUS_PROGRAM_CHANGE + event->channel;
data[1] = event->value;
jackbridge_midi_event_write(controlOut, event->time, data, 2);
break;
case CarlaEngineEventAllSoundOff:
data[0] = MIDI_STATUS_CONTROL_CHANGE + event->channel;
data[1] = MIDI_CONTROL_ALL_SOUND_OFF;
jackbridge_midi_event_write(controlOut, event->time, data, 2);
break;
case CarlaEngineEventAllNotesOff:
data[0] = MIDI_STATUS_CONTROL_CHANGE + event->channel;
data[1] = MIDI_CONTROL_ALL_NOTES_OFF;
jackbridge_midi_event_write(controlOut, event->time, data, 2);
break;
}
}
}
}

// initialize midi input
memset(rackMidiEventsIn, 0, sizeof(CarlaEngineMidiEvent)*MAX_ENGINE_MIDI_EVENTS);
{
uint32_t i = 0, j = 0;
jackbridge_midi_event_t jackEvent;

while (jackbridge_midi_event_get(&jackEvent, midiIn, j++) == 0)
// output midi
{
if (i == MAX_ENGINE_MIDI_EVENTS)
break;
jackbridge_midi_clear_buffer(midiOut);

if (jackEvent.size < 4)
for (unsigned short i=0; i < MAX_ENGINE_MIDI_EVENTS; i++)
{
rackMidiEventsIn[i].time = jackEvent.time;
rackMidiEventsIn[i].size = jackEvent.size;
memcpy(rackMidiEventsIn[i].data, jackEvent.buffer, jackEvent.size);
i += 1;
if (rackMidiEventsOut[i].size == 0)
break;
jackbridge_midi_event_write(midiOut, rackMidiEventsOut[i].time, rackMidiEventsOut[i].data, rackMidiEventsOut[i].size);
}
}
}
#else
Q_UNUSED(nframes);
#endif
}

// process rack
processRack(inBuf, outBuf, nframes);

// output control
void handleShutdownCallback()
{
for (unsigned short i=0, max=maxPluginNumber(); i < max; i++)
{
jackbridge_midi_clear_buffer(controlOut);
CarlaPlugin* const plugin = getPluginUnchecked(i);
plugin->x_client = nullptr;
}

for (unsigned short i=0; i < MAX_ENGINE_CONTROL_EVENTS; i++)
{
CarlaEngineControlEvent* const event = &rackControlEventsOut[i];
client = nullptr;
callback(CALLBACK_QUIT, 0, 0, 0, 0.0);
}

if (event->type == CarlaEngineEventControlChange && MIDI_IS_CONTROL_BANK_SELECT(event->controller))
event->type = CarlaEngineEventMidiBankChange;
// -------------------------------------

uint8_t data[4] = { 0 };
private:
jack_client_t* client;
jack_transport_state_t state;
jack_position_t pos;
bool freewheel;

switch (event->type)
{
case CarlaEngineEventNull:
break;
case CarlaEngineEventControlChange:
data[0] = MIDI_STATUS_CONTROL_CHANGE + event->channel;
data[1] = event->controller;
data[2] = event->value * 127;
jackbridge_midi_event_write(controlOut, event->time, data, 3);
break;
case CarlaEngineEventMidiBankChange:
data[0] = MIDI_STATUS_CONTROL_CHANGE + event->channel;
data[1] = MIDI_CONTROL_BANK_SELECT;
data[2] = event->value;
jackbridge_midi_event_write(controlOut, event->time, data, 3);
break;
case CarlaEngineEventMidiProgramChange:
data[0] = MIDI_STATUS_PROGRAM_CHANGE + event->channel;
data[1] = event->value;
jackbridge_midi_event_write(controlOut, event->time, data, 2);
break;
case CarlaEngineEventAllSoundOff:
data[0] = MIDI_STATUS_CONTROL_CHANGE + event->channel;
data[1] = MIDI_CONTROL_ALL_SOUND_OFF;
jackbridge_midi_event_write(controlOut, event->time, data, 2);
break;
case CarlaEngineEventAllNotesOff:
data[0] = MIDI_STATUS_CONTROL_CHANGE + event->channel;
data[1] = MIDI_CONTROL_ALL_NOTES_OFF;
jackbridge_midi_event_write(controlOut, event->time, data, 2);
break;
}
}
}
// -------------------------------------

#ifndef BUILD_BRIDGE
enum RackPorts {
rackPortAudioIn1 = 0,
rackPortAudioIn2 = 1,
rackPortAudioOut1 = 2,
rackPortAudioOut2 = 3,
rackPortControlIn = 4,
rackPortControlOut = 5,
rackPortMidiIn = 6,
rackPortMidiOut = 7,
rackPortCount = 8
};

jack_port_t* rackJackPorts[rackPortCount];
#endif

static void processPlugin(CarlaPlugin* const p, const uint32_t nframes)
{
float* inBuffer[p->aIn.count];
float* outBuffer[p->aOut.count];

// output midi
for (uint32_t i=0; i < p->aIn.count; i++)
inBuffer[i] = p->aIn.ports[i]->getJackAudioBuffer(nframes);

for (uint32_t i=0; i < p->aOut.count; i++)
outBuffer[i] = p->aOut.ports[i]->getJackAudioBuffer(nframes);

#ifndef BUILD_BRIDGE
if (carlaOptions.processHighPrecision)
{
jackbridge_midi_clear_buffer(midiOut);
float* inBuffer2[p->aIn.count];
float* outBuffer2[p->aOut.count];

for (unsigned short i=0; i < MAX_ENGINE_MIDI_EVENTS; i++)
for (uint32_t i=0, j; i < nframes; i += 8)
{
if (rackMidiEventsOut[i].size == 0)
break;
for (j=0; j < p->aIn.count; j++)
inBuffer2[j] = inBuffer[j] + i;

jackbridge_midi_event_write(midiOut, rackMidiEventsOut[i].time, rackMidiEventsOut[i].data, rackMidiEventsOut[i].size);
for (j=0; j < p->aOut.count; j++)
outBuffer2[j] = outBuffer[j] + i;

p->process(inBuffer2, outBuffer2, 8, i);
}
}
}
#else
Q_UNUSED(nframes);
else
#endif
}
p->process(inBuffer, outBuffer, nframes);
}

void CarlaEngineJack::handleShutdownCallback()
static int carla_jack_srate_callback(jack_nframes_t newSampleRate, void* arg)
{
CarlaEngineJack* const _this_ = (CarlaEngineJack*)arg;
_this_->handleSampleRateCallback(newSampleRate);
return 0;
}

static int carla_jack_bufsize_callback(jack_nframes_t newBufferSize, void* arg)
{
CarlaEngineJack* const _this_ = (CarlaEngineJack*)arg;
_this_->handleBufferSizeCallback(newBufferSize);
return 0;
}

static void carla_jack_freewheel_callback(int starting, void* arg)
{
CarlaEngineJack* const _this_ = (CarlaEngineJack*)arg;
_this_->handleFreewheelCallback(bool(starting));
}

static int carla_jack_process_callback(jack_nframes_t nframes, void* arg)
{
CarlaEngineJack* const _this_ = (CarlaEngineJack*)arg;
_this_->handleProcessCallback(nframes);
return 0;
}

static int carla_jack_process_callback_plugin(jack_nframes_t nframes, void* arg)
{
CarlaPlugin* const plugin = (CarlaPlugin*)arg;

if (plugin && plugin->enabled())
{
plugin->engineProcessLock();
plugin->initBuffers();
processPlugin(plugin, nframes);
plugin->engineProcessUnlock();
}

return 0;
}

static void carla_jack_shutdown_callback(void* arg)
{
CarlaEngineJack* const _this_ = (CarlaEngineJack*)arg;
_this_->handleShutdownCallback();
}
};

// -----------------------------------------

CarlaEngine* CarlaEngine::newJack()
{
//for (unsigned short i=0, max=maxPluginNumber(); i < max; i++)
//{
//CarlaPlugin* const plugin = getPluginUnchecked(i);
//plugin->x_client
//}

client = nullptr;
callback(CALLBACK_QUIT, 0, 0, 0, 0.0);
return new CarlaEngineJack();
}

// -----------------------------------------

CARLA_BACKEND_END_NAMESPACE

#endif // CARLA_ENGINE_JACK

+ 196
- 180
c++/carla-backend/carla_engine_rtaudio.cpp View File

@@ -22,223 +22,239 @@

CARLA_BACKEND_START_NAMESPACE

// -------------------------------------------------------------------------------------------------------------------
// static RtAudio<->Engine calls
// -----------------------------------------

static int carla_rtaudio_process_callback(void* outputBuffer, void* inputBuffer, unsigned int nframes, double streamTime, RtAudioStreamStatus status, void* userData)
class CarlaEngineRtAudio : public CarlaEngine
{
CarlaEngineRtAudio* const engine = (CarlaEngineRtAudio*)userData;
engine->handleProcessCallback(outputBuffer, inputBuffer, nframes, streamTime, status);
return 0;
}
public:
CarlaEngineRtAudio(RtAudio::Api api)
: CarlaEngine(),
audio(api)
{
qDebug("CarlaEngineRtAudio::CarlaEngineRtAudio()");

// -------------------------------------------------------------------------------------------------------------------
// Carla Engine (RtAudio)
type = CarlaEngineTypeRtAudio;

CarlaEngineRtAudio::CarlaEngineRtAudio(RtAudio::Api api)
: CarlaEngine(),
adac(api)
{
qDebug("CarlaEngineRtAudio::CarlaEngineRtAudio()");
midiIn = nullptr;
midiOut = nullptr;

type = CarlaEngineTypeRtAudio;
}

CarlaEngineRtAudio::~CarlaEngineRtAudio()
{
qDebug("CarlaEngineRtAudio::~CarlaEngineRtAudio()");
}

bool CarlaEngineRtAudio::init(const char* const clientName)
{
qDebug("CarlaEngineRtAudio::init(\"%s\")", clientName);

if (adac.getDeviceCount() < 1)
{
setLastError("No audio devices available");
return false;
// just to make sure
carlaOptions.forceStereo = true;
carlaOptions.processMode = PROCESS_MODE_CONTINUOUS_RACK;
}

sampleRate = 48000;
unsigned int rtBufferFrames = 512;

RtAudio::StreamParameters iParams, oParams;
//iParams.deviceId = 3;
//oParams.deviceId = 2;
iParams.nChannels = 2;
oParams.nChannels = 2;
RtAudio::StreamOptions options;
options.flags = /*RTAUDIO_NONINTERLEAVED |*/ RTAUDIO_MINIMIZE_LATENCY /*| RTAUDIO_HOG_DEVICE*/ | RTAUDIO_SCHEDULE_REALTIME | RTAUDIO_ALSA_USE_DEFAULT;
options.streamName = clientName;
options.priority = 85;

try {
adac.openStream(&oParams, &iParams, RTAUDIO_FLOAT32, sampleRate, &rtBufferFrames, carla_rtaudio_process_callback, this, &options);
}
catch (RtError& e)
~CarlaEngineRtAudio()
{
setLastError(e.what());
return false;
qDebug("CarlaEngineRtAudio::~CarlaEngineRtAudio()");
}

bufferSize = rtBufferFrames;
// -------------------------------------

// set client name, fixed for OSC usage
// FIXME - put this in shared?
char* fixedName = strdup(clientName);
for (size_t i=0; i < strlen(fixedName); i++)
bool init(const char* const clientName)
{
if (! (std::isalpha(fixedName[i]) || std::isdigit(fixedName[i])))
fixedName[i] = '_';
qDebug("CarlaEngineRtAudio::init(\"%s\")", clientName);

if (audio.getDeviceCount() < 1)
{
setLastError("No audio devices available for this driver");
return false;
}

bufferSize = carlaOptions.preferredBufferSize;
sampleRate = carlaOptions.preferredSampleRate;

RtAudio::StreamParameters iParams, oParams;
//iParams.deviceId = 3;
//oParams.deviceId = 2;
iParams.nChannels = 2;
oParams.nChannels = 2;

RtAudio::StreamOptions options;
options.flags = /*RTAUDIO_NONINTERLEAVED |*/ RTAUDIO_MINIMIZE_LATENCY /*| RTAUDIO_HOG_DEVICE*/ | RTAUDIO_SCHEDULE_REALTIME | RTAUDIO_ALSA_USE_DEFAULT;
options.streamName = clientName;
options.priority = 85;

try {
audio.openStream(&oParams, &iParams, RTAUDIO_FLOAT32, sampleRate, &bufferSize, carla_rtaudio_process_callback, this, &options);
}
catch (RtError& e)
{
setLastError(e.what());
return false;
}

try {
audio.startStream();
}
catch (RtError& e)
{
setLastError(e.what());
return false;
}

midiIn = new MidiInAlsa(clientName, 512);
midiIn->openVirtualPort("control-in");
midiIn->openVirtualPort("midi-in");

midiOut = new MidiOutAlsa(clientName);
midiOut->openVirtualPort("control-out");
midiOut->openVirtualPort("midi-out");

name = getFixedClientName(clientName);
CarlaEngine::init(name);
return true;
}
name = strdup(fixedName);
free((void*)fixedName);

qDebug("RtAudio bufferSize = %i", bufferSize);

try {
adac.startStream();
}
catch (RtError& e)
bool close()
{
setLastError(e.what());
return false;
qDebug("CarlaEngineRtAudio::close()");
CarlaEngine::close();

if (name)
{
free((void*)name);
name = nullptr;
}

if (audio.isStreamRunning())
audio.stopStream();

if (audio.isStreamOpen())
audio.closeStream();

if (midiIn)
{
midiIn->cancelCallback();
midiIn->closePort();
delete midiIn;
midiIn = nullptr;
}

if (midiOut)
{
midiOut->closePort();
delete midiOut;
midiOut = nullptr;
}

return true;
}

CarlaEngine::init(name);

return true;
}

bool CarlaEngineRtAudio::close()
{
qDebug("CarlaEngineRtAudio::close()");
CarlaEngine::close();

if (name)
bool isOffline()
{
free((void*)name);
name = nullptr;
return false;
}

if (adac.isStreamRunning())
adac.stopStream();

if (adac.isStreamOpen())
adac.closeStream();

return true;
}

bool CarlaEngineRtAudio::isOffline()
{
return false;
}

bool CarlaEngineRtAudio::isRunning()
{
return adac.isStreamRunning();
}

CarlaEngineClient* CarlaEngineRtAudio::addClient(CarlaPlugin* const plugin)
{
CarlaEngineClientNativeHandle handle;
handle.type = type;

// unsigned int rtBufferFrames = getBufferSize();

// RtAudio::StreamParameters iParams, oParams;
// iParams.nChannels = plugin->audioInCount();
// oParams.nChannels = plugin->audioOutCount();
// RtAudio::StreamOptions options;
// options.flags = /*RTAUDIO_NONINTERLEAVED |*/ RTAUDIO_MINIMIZE_LATENCY /*| RTAUDIO_HOG_DEVICE*/ | RTAUDIO_SCHEDULE_REALTIME | RTAUDIO_ALSA_USE_DEFAULT;
// options.streamName = plugin->name();
// options.priority = 85;

// try {
// adac.openStream(&oParams, &iParams, RTAUDIO_FLOAT32, getSampleRate(), &rtBufferFrames, carla_rtaudio_process_callback, this, &options);
// }
// catch (RtError& e)
// {
// setLastError(e.what());
// return false;
// }

return new CarlaEngineClient(handle);
Q_UNUSED(plugin);
}

// -------------------------------------------------------------------------------------------------------------------

void CarlaEngineRtAudio::handleProcessCallback(void* outputBuffer, void* inputBuffer, unsigned int nframes, double streamTime, RtAudioStreamStatus status)
{
if (maxPluginNumber() == 0)
return;

// get buffers from RtAudio
float* insPtr = (float*)inputBuffer;
float* outsPtr = (float*)outputBuffer;

// assert buffers
CARLA_ASSERT(insPtr);
CARLA_ASSERT(outsPtr);

// create temporary audio buffers
float inBuf1[nframes];
float inBuf2[nframes];
float outBuf1[nframes];
float outBuf2[nframes];

// initialize audio input
for (unsigned int i=0; i < nframes*2; i++)
bool isRunning()
{
if (i % 2)
inBuf2[i/2] = insPtr[i];
else
inBuf1[i/2] = insPtr[i];
return audio.isStreamRunning();
}

// create (real) audio buffers
float* inBuf[2] = { inBuf1, inBuf2 };
float* outBuf[2] = { outBuf1, outBuf2 };

// initialize control input
memset(rackControlEventsIn, 0, sizeof(CarlaEngineControlEvent)*MAX_ENGINE_CONTROL_EVENTS);
CarlaEngineClient* addClient(CarlaPlugin* const plugin)
{
// TODO
}
CarlaEngineClientNativeHandle handle;
handle.type = CarlaEngineTypeRtAudio;

// initialize midi input
memset(rackMidiEventsIn, 0, sizeof(CarlaEngineMidiEvent)*MAX_ENGINE_MIDI_EVENTS);
{
// TODO
return new CarlaEngineClient(handle);
Q_UNUSED(plugin);
}

processRack(inBuf, outBuf, nframes);
// -------------------------------------

// output audio
for (unsigned int i=0; i < nframes*2; i++)
protected:
void handleProcessCallback(void* outputBuffer, void* inputBuffer, unsigned int nframes, double streamTime, RtAudioStreamStatus status)
{
if (i % 2)
outsPtr[i] = outBuf2[i/2];
else
outsPtr[i] = outBuf1[i/2];
if (maxPluginNumber() == 0)
return;

// get buffers from RtAudio
float* insPtr = (float*)inputBuffer;
float* outsPtr = (float*)outputBuffer;

// assert buffers
CARLA_ASSERT(insPtr);
CARLA_ASSERT(outsPtr);

// create temporary audio buffers
float inBuf1[nframes];
float inBuf2[nframes];
float outBuf1[nframes];
float outBuf2[nframes];

// initialize audio input
for (unsigned int i=0; i < nframes*2; i++)
{
if (i % 2)
inBuf2[i/2] = insPtr[i];
else
inBuf1[i/2] = insPtr[i];
}

// create (real) audio buffers
float* inBuf[2] = { inBuf1, inBuf2 };
float* outBuf[2] = { outBuf1, outBuf2 };

// initialize control input
memset(rackControlEventsIn, 0, sizeof(CarlaEngineControlEvent)*MAX_ENGINE_CONTROL_EVENTS);
{
// TODO
}

// initialize midi input
memset(rackMidiEventsIn, 0, sizeof(CarlaEngineMidiEvent)*MAX_ENGINE_MIDI_EVENTS);
{
// TODO
}

processRack(inBuf, outBuf, nframes);

// output audio
for (unsigned int i=0; i < nframes*2; i++)
{
if (i % 2)
outsPtr[i] = outBuf2[i/2];
else
outsPtr[i] = outBuf1[i/2];
}

// output control
{
// TODO
}

// output midi
{
// TODO
}

Q_UNUSED(streamTime);
Q_UNUSED(status);
}

// output control
{
// TODO
}
// -------------------------------------

private:
RtAudio audio;
MidiInApi* midiIn;
MidiOutApi* midiOut;

// output midi
static int carla_rtaudio_process_callback(void* outputBuffer, void* inputBuffer, unsigned int nframes, double streamTime, RtAudioStreamStatus status, void* userData)
{
// TODO
CarlaEngineRtAudio* const _this_ = (CarlaEngineRtAudio*)userData;
_this_->handleProcessCallback(outputBuffer, inputBuffer, nframes, streamTime, status);
return 0;
}
};

Q_UNUSED(streamTime);
Q_UNUSED(status);
// -----------------------------------------

CarlaEngine* CarlaEngine::newRtAudio(RtAudio::Api api)
{
return new CarlaEngineRtAudio(api);
}

// -----------------------------------------

CARLA_BACKEND_END_NAMESPACE

#endif // CARLA_ENGINE_RTAUDIO

+ 23
- 2
c++/carla-backend/carla_native.cpp View File

@@ -18,6 +18,14 @@
#include "carla_plugin.h"
#include "plugins/carla_native.h"

// Internal C plugins
extern "C" {
extern void carla_register_native_plugin_bypass();
}

// Internal C++ plugins
extern void carla_register_native_plugin_midiSplit();

CARLA_BACKEND_START_NAMESPACE

struct NativePluginMidiData {
@@ -36,6 +44,7 @@ class NativePluginScopedInitiliazer
public:
NativePluginScopedInitiliazer()
{
firstInit = true;
}

~NativePluginScopedInitiliazer()
@@ -51,6 +60,16 @@ public:
descriptors.clear();
}

void maybeFirstInit()
{
if (firstInit)
{
firstInit = false;
carla_register_native_plugin_bypass();
carla_register_native_plugin_midiSplit();
}
}

void initializeIfNeeded(const PluginDescriptor* const desc)
{
if (descriptors.empty() || std::find(descriptors.begin(), descriptors.end(), desc) == descriptors.end())
@@ -63,6 +82,7 @@ public:
}

private:
bool firstInit;
std::vector<const PluginDescriptor*> descriptors;
};

@@ -1541,6 +1561,7 @@ public:

static size_t getPluginCount()
{
scopedInitliazer.maybeFirstInit();
return pluginDescriptors.size();
}

@@ -1601,9 +1622,9 @@ public:
// get info

if (name)
m_name = x_engine->getUniqueName(name);
m_name = x_engine->getUniquePluginName(name);
else
m_name = x_engine->getUniqueName(descriptor->name);
m_name = x_engine->getUniquePluginName(descriptor->name);

// ---------------------------------------------------------------
// register client


+ 2
- 38
c++/carla-backend/carla_plugin.h View File

@@ -1358,44 +1358,6 @@ public:
Q_UNUSED(framesOffset);
}

#ifdef CARLA_ENGINE_JACK
/*!
* Plugin process callback, JACK helper version.
*/
void process_jack(const uint32_t nframes)
{
float* inBuffer[aIn.count];
float* outBuffer[aOut.count];

for (uint32_t i=0; i < aIn.count; i++)
inBuffer[i] = aIn.ports[i]->getJackAudioBuffer(nframes);

for (uint32_t i=0; i < aOut.count; i++)
outBuffer[i] = aOut.ports[i]->getJackAudioBuffer(nframes);

#ifndef BUILD_BRIDGE
if (carlaOptions.processHighPrecision)
{
float* inBuffer2[aIn.count];
float* outBuffer2[aOut.count];

for (uint32_t i=0, j; i < nframes; i += 8)
{
for (j=0; j < aIn.count; j++)
inBuffer2[j] = inBuffer[j] + i;

for (j=0; j < aOut.count; j++)
outBuffer2[j] = outBuffer[j] + i;

process(inBuffer2, outBuffer2, 8, i);
}
}
else
#endif
process(inBuffer, outBuffer, nframes);
}
#endif

/*!
* Tell the plugin the current buffer size has changed.
*/
@@ -2266,6 +2228,8 @@ protected:
{
return (value < 0.0) ? -value : value;
}

friend class CarlaEngineJack;
};

/**@}*/


+ 2
- 2
c++/carla-backend/dssi.cpp View File

@@ -1483,9 +1483,9 @@ public:
m_filename = strdup(filename);

if (name)
m_name = x_engine->getUniqueName(name);
m_name = x_engine->getUniquePluginName(name);
else
m_name = x_engine->getUniqueName(ldescriptor->Name);
m_name = x_engine->getUniquePluginName(ldescriptor->Name);

// ---------------------------------------------------------------
// register client


+ 2
- 2
c++/carla-backend/fluidsynth.cpp View File

@@ -1251,9 +1251,9 @@ public:
m_label = strdup(label);

if (name)
m_name = x_engine->getUniqueName(name);
m_name = x_engine->getUniquePluginName(name);
else
m_name = x_engine->getUniqueName(label);
m_name = x_engine->getUniquePluginName(label);

// ---------------------------------------------------------------
// register client


+ 3
- 3
c++/carla-backend/ladspa.cpp View File

@@ -1102,11 +1102,11 @@ public:
rdf_descriptor = ladspa_rdf_dup(rdf_descriptor_);

if (name)
m_name = x_engine->getUniqueName(name);
m_name = x_engine->getUniquePluginName(name);
else if (rdf_descriptor && rdf_descriptor->Title)
m_name = x_engine->getUniqueName(rdf_descriptor->Title);
m_name = x_engine->getUniquePluginName(rdf_descriptor->Title);
else
m_name = x_engine->getUniqueName(descriptor->Name);
m_name = x_engine->getUniquePluginName(descriptor->Name);

// ---------------------------------------------------------------
// register client


+ 2
- 2
c++/carla-backend/linuxsampler.cpp View File

@@ -721,9 +721,9 @@ public:
m_filename = strdup(filename);

if (name)
m_name = x_engine->getUniqueName(name);
m_name = x_engine->getUniquePluginName(name);
else
m_name = x_engine->getUniqueName(label && label[0] ? label : info.InstrumentName.c_str());
m_name = x_engine->getUniquePluginName(label && label[0] ? label : info.InstrumentName.c_str());

sampler_channel = sampler->AddSamplerChannel();
sampler_channel->SetEngineType(stype);


+ 2
- 2
c++/carla-backend/lv2.cpp View File

@@ -4031,9 +4031,9 @@ public:
m_filename = strdup(bundle);

if (name)
m_name = x_engine->getUniqueName(name);
m_name = x_engine->getUniquePluginName(name);
else
m_name = x_engine->getUniqueName(rdf_descriptor->Name);
m_name = x_engine->getUniquePluginName(rdf_descriptor->Name);

// ---------------------------------------------------------------
// register client


+ 1
- 2
c++/carla-backend/plugins/carla_native.h View File

@@ -170,8 +170,7 @@ typedef struct _PluginDescriptor {

void carla_register_native_plugin(const PluginDescriptor* desc);

#define CARLA_REGISTER_NATIVE_PLUGIN(label, desc) \
void carla_register_native_plugin_##label () __attribute__((constructor)); \
#define CARLA_REGISTER_NATIVE_PLUGIN(label, desc) \
void carla_register_native_plugin_##label () { carla_register_native_plugin(&desc); }

#ifdef __cplusplus


+ 1
- 2
c++/carla-backend/plugins/carla_nativemm.h View File

@@ -436,8 +436,7 @@ private:

// -----------------------------------------------------------------------

#define CARLA_REGISTER_NATIVE_PLUGIN_MM(label, descMM) \
void carla_register_native_plugin_##label () __attribute__((constructor)); \
#define CARLA_REGISTER_NATIVE_PLUGIN_MM(label, descMM) \
void carla_register_native_plugin_##label () { carla_register_native_plugin(descMM.descriptorInit()); }

#endif // CARLA_NATIVE_MM_H

+ 3
- 3
c++/carla-backend/vst.cpp View File

@@ -2163,7 +2163,7 @@ public:

if (name)
{
m_name = x_engine->getUniqueName(name);
m_name = x_engine->getUniquePluginName(name);
}
else
{
@@ -2171,9 +2171,9 @@ public:
effect->dispatcher(effect, effGetEffectName, 0, 0, strBuf, 0.0f);

if (strBuf[0] != 0)
m_name = x_engine->getUniqueName(strBuf);
m_name = x_engine->getUniquePluginName(strBuf);
else
m_name = x_engine->getUniqueName(label);
m_name = x_engine->getUniquePluginName(label);
}

// ---------------------------------------------------------------


Loading…
Cancel
Save