Browse Source

Start some Carla engine rework to allow using it as plugin

tags/v0.9.0
falkTX 13 years ago
parent
commit
072eda7d2b
34 changed files with 1692 additions and 993 deletions
  1. +2
    -2
      .gitignore
  2. +1
    -1
      Makefile
  3. +2
    -2
      src/carla-backend/Makefile
  4. +127
    -40
      src/carla-backend/carla_backend.cpp
  5. +37
    -16
      src/carla-backend/carla_backend.h
  6. +11
    -10
      src/carla-backend/carla_bridge.cpp
  7. +167
    -0
      src/carla-backend/carla_engine.h
  8. +456
    -0
      src/carla-backend/carla_engine_jack.cpp
  9. +156
    -0
      src/carla-backend/carla_engine_rtaudio.cpp
  10. +0
    -273
      src/carla-backend/carla_jack.cpp
  11. +8
    -11
      src/carla-backend/carla_jack.h
  12. +2
    -2
      src/carla-backend/carla_midi.h
  13. +14
    -6
      src/carla-backend/carla_osc.cpp
  14. +1
    -2
      src/carla-backend/carla_osc.h
  15. +379
    -268
      src/carla-backend/carla_plugin.h
  16. +8
    -5
      src/carla-backend/carla_shared.cpp
  17. +5
    -2
      src/carla-backend/carla_shared.h
  18. +40
    -35
      src/carla-backend/carla_threads.cpp
  19. +1
    -2
      src/carla-backend/carla_threads.h
  20. +135
    -181
      src/carla-backend/dssi.cpp
  21. +22
    -11
      src/carla-backend/ladspa.cpp
  22. +15
    -13
      src/carla-backend/lv2.cpp
  23. +13
    -13
      src/carla-backend/qtcreator/carla-backend.pro
  24. +13
    -13
      src/carla-backend/sf2.cpp
  25. +17
    -32
      src/carla-backend/vst.cpp
  26. +15
    -14
      src/carla-bridge/Makefile
  27. +8
    -8
      src/carla-discovery/Makefile
  28. +1
    -1
      src/carla-discovery/carla-discovery.cpp
  29. +4
    -2
      src/carla-includes/carla_includes.h
  30. +9
    -7
      src/carla-includes/carla_lib_includes.h
  31. +5
    -3
      src/carla-includes/carla_vst_includes.h
  32. +1
    -1
      src/carla-lilv/Makefile
  33. +3
    -3
      src/carla.py
  34. +14
    -14
      src/carla_backend.py

+ 2
- 2
.gitignore View File

@@ -3,11 +3,11 @@
.*.kate-swp

*~
*.o
*.a
*.exe
*.o
*.so
*.dll
*.exe

*.carxp
*.carxs


+ 1
- 1
Makefile View File

@@ -9,7 +9,7 @@ DESTDIR =

SED_PREFIX = $(shell echo $(PREFIX) | sed "s/\//\\\\\\\\\//g")

PYUIC = pyuic4 --pyqt3-wrapper
PYUIC = pyuic4
PYRCC = pyrcc4 -py3

# Detect architecture


+ 2
- 2
src/carla-backend/Makefile View File

@@ -8,13 +8,13 @@ CC ?= gcc
CXX ?= g++

CARLA_C_FLAGS = -Wall -fPIC -I. -I../carla-includes $(CFLAGS)
CARLA_CXX_FLAGS = -Wall -std=c++0x -fPIC -I. -I../carla-includes `pkg-config --cflags jack fluidsynth liblo QtCore QtGui` $(CXXFLAGS)
CARLA_CXX_FLAGS = -Wall -std=c++0x -fPIC -I. -I../carla-includes `pkg-config --cflags jack fluidsynth liblo QtCore QtGui` -DCARLA_ENGINE_JACK $(CXXFLAGS)
CARLA_CXX_FLAGS += -DVESTIGE_HEADER -I../carla-includes/vestige # Comment this line to not use vestige header
CARLA_CXX_FLAGS += -DNDEBUG -DQT_NO_DEBUG -DQT_NO_DEBUG_STREAM -DQT_NO_DEBUG_OUTPUT -O2 -ffast-math -fomit-frame-pointer -fvisibility=hidden -mtune=generic -msse
# CARLA_CXX_FLAGS += -DDEBUG -O0 -g
CARLA_LINK_FLAGS = -shared -fPIC -ldl `pkg-config --libs jack fluidsynth liblo QtCore QtGui` $(LDFLAGS)

OBJS = carla_backend.o carla_bridge.o carla_jack.o carla_osc.o carla_shared.o carla_threads.o ladspa.o dssi.o lv2.o vst.o sf2.o lv2-rtmempool/rtmempool.o
OBJS = carla_backend.o carla_bridge.o carla_engine_jack.o carla_osc.o carla_shared.o carla_threads.o ladspa.o dssi.o lv2.o vst.o sf2.o lv2-rtmempool/rtmempool.o


all: carla_backend.so


+ 127
- 40
src/carla-backend/carla_backend.cpp View File

@@ -15,6 +15,8 @@
* For a full copy of the GNU General Public License see the COPYING file
*/

#include "carla_backend.h"
#include "carla_engine.h"
#include "carla_plugin.h"
#include "carla_threads.h"

@@ -24,18 +26,23 @@ short add_plugin_dssi(const char* filename, const char* label, const void* extra
short add_plugin_lv2(const char* filename, const char* label);
short add_plugin_vst(const char* filename, const char* label);
short add_plugin_sf2(const char* filename, const char* label);
short add_plugin_bridge(BinaryType btype, PluginType ptype, const char* filename, const char* label, void* extra_stuff);
#ifndef BUILD_BRIDGE
//short add_plugin_bridge(CarlaBackend::BinaryType btype, CarlaBackend::PluginType ptype, const char* filename, const char* label, void* extra_stuff);
#endif

CarlaEngine carla_engine;
CarlaCheckThread carla_check_thread;

// -------------------------------------------------------------------------------------------------------------------
// Exported symbols (API)

bool carla_init(const char* client_name)
CARLA_BACKEND_START_NAMESPACE

bool engine_init(const char* client_name)
{
qDebug("carla_init(%s)", client_name);
qDebug("carla_backend_init(%s)", client_name);

bool started = carla_jack_init(client_name);
bool started = carla_engine.init(client_name);

if (started)
{
@@ -47,16 +54,15 @@ bool carla_init(const char* client_name)
return started;
}

bool carla_close()
bool engine_close()
{
qDebug("carla_close()");
qDebug("carla_backend_close()");

bool closed = carla_jack_close();
bool closed = carla_engine.close();

for (unsigned short i=0; i<MAX_PLUGINS; i++)
{
CarlaPlugin* plugin = CarlaPlugins[i];
if (plugin && plugin->id() >= 0)
if (CarlaPlugins[i])
remove_plugin(i);
}

@@ -118,7 +124,7 @@ short add_plugin(BinaryType btype, PluginType ptype, const char* filename, const
{
qDebug("add_plugin(%i, %i, %s, %s, %p)", btype, ptype, filename, label, extra_stuff);

#ifndef BUILD_BRIDGE
#if 0 //ndef BUILD_BRIDGE
if (btype != BINARY_NATIVE)
{
if (carla_options.global_jack_client)
@@ -161,17 +167,18 @@ bool remove_plugin(unsigned short plugin_id)
osc_global_send_remove_plugin(plugin->id());

carla_proc_lock();
plugin->set_id(-1);
plugin->set_enabled(false);
carla_proc_unlock();

carla_check_thread.stopNow();
if (is_engine_running() && carla_check_thread.isRunning())
carla_check_thread.stopNow();

delete plugin;

CarlaPlugins[i] = nullptr;
unique_names[i] = nullptr;

if (carla_is_engine_running())
if (is_engine_running())
carla_check_thread.start(QThread::HighPriority);

return true;
@@ -226,7 +233,7 @@ PluginInfo* get_plugin_info(unsigned short plugin_id)
}
}

if (carla_is_engine_running())
if (is_engine_running())
qCritical("get_plugin_info(%i) - could not find plugin", plugin_id);

return &info;
@@ -345,7 +352,7 @@ ParameterInfo* get_parameter_info(unsigned short plugin_id, uint32_t parameter_i
}
}

if (carla_is_engine_running())
if (is_engine_running())
qCritical("get_parameter_info(%i, %i) - could not find plugin", plugin_id, parameter_id);

return &info;
@@ -389,7 +396,7 @@ ScalePointInfo* get_scalepoint_info(unsigned short plugin_id, uint32_t parameter
}
}

if (carla_is_engine_running())
if (is_engine_running())
qCritical("get_scalepoint_info(%i, %i, %i) - could not find plugin", plugin_id, parameter_id, scalepoint_id);

return &info;
@@ -444,7 +451,7 @@ GuiInfo* get_gui_info(unsigned short plugin_id)
return &info;
}

ParameterData* get_parameter_data(unsigned short plugin_id, uint32_t parameter_id)
const ParameterData* get_parameter_data(unsigned short plugin_id, uint32_t parameter_id)
{
qDebug("get_parameter_data(%i, %i)", plugin_id, parameter_id);

@@ -468,7 +475,7 @@ ParameterData* get_parameter_data(unsigned short plugin_id, uint32_t parameter_i
return &data;
}

ParameterRanges* get_parameter_ranges(unsigned short plugin_id, uint32_t parameter_id)
const ParameterRanges* get_parameter_ranges(unsigned short plugin_id, uint32_t parameter_id)
{
qDebug("get_parameter_ranges(%i, %i)", plugin_id, parameter_id);

@@ -492,7 +499,7 @@ ParameterRanges* get_parameter_ranges(unsigned short plugin_id, uint32_t paramet
return &ranges;
}

CustomData* get_custom_data(unsigned short plugin_id, uint32_t custom_data_id)
const CustomData* get_custom_data(unsigned short plugin_id, uint32_t custom_data_id)
{
qDebug("get_custom_data(%i, %i)", plugin_id, custom_data_id);

@@ -552,7 +559,7 @@ const char* get_chunk_data(unsigned short plugin_id)
}
}

if (carla_is_engine_running())
if (is_engine_running())
qCritical("get_chunk_data(%i) - could not find plugin", plugin_id);

return chunk_data;
@@ -674,8 +681,9 @@ const char* get_program_name(unsigned short plugin_id, uint32_t program_id)
}
}

if (carla_is_engine_running())
if (is_engine_running())
qCritical("get_program_name(%i, %i) - could not find plugin", plugin_id, program_id);

return nullptr;
}

@@ -711,8 +719,9 @@ const char* get_midi_program_name(unsigned short plugin_id, uint32_t midi_progra
}
}

if (carla_is_engine_running())
if (is_engine_running())
qCritical("get_midi_program_name(%i, %i) - could not find plugin", plugin_id, midi_program_id);

return nullptr;
}

@@ -741,7 +750,7 @@ const char* get_real_plugin_name(unsigned short plugin_id)
}
}

if (carla_is_engine_running())
if (is_engine_running())
qCritical("get_real_plugin_name(%i) - could not find plugin", plugin_id);

return real_plugin_name;
@@ -1086,6 +1095,20 @@ void set_gui_data(unsigned short plugin_id, int data, quintptr gui_addr)
qCritical("set_gui_data(%i, %i, " P_UINTPTR ") - could not find plugin", plugin_id, data, gui_addr);
}

// TESTING
//void set_name(unsigned short plugin_id, const char* name)
//{

// for (unsigned short i=0; i<MAX_PLUGINS; i++)
// {
// CarlaPlugin* plugin = CarlaPlugins[i];
// if (plugin && plugin->id() == plugin_id)
// {
// plugin->set_name(name);
// }
// }
//}

void show_gui(unsigned short plugin_id, bool yesno)
{
qDebug("show_gui(%i, %s)", plugin_id, bool2str(yesno));
@@ -1108,7 +1131,7 @@ void idle_guis()
for (unsigned short i=0; i<MAX_PLUGINS; i++)
{
CarlaPlugin* plugin = CarlaPlugins[i];
if (plugin && plugin->id() >= 0)
if (plugin && plugin->enabled())
plugin->idle_gui();
}
}
@@ -1148,38 +1171,28 @@ void set_option(OptionsType option, int value, const char* value_str)
{
qDebug("set_option(%i, %i, %s)", option, value, value_str);

//if (carla_options.initiated)
// return;
// TODO

switch(option)
{
case OPTION_GLOBAL_JACK_CLIENT:
carla_options.global_jack_client = value;
break;
case OPTION_USE_DSSI_CHUNKS:
carla_options.use_dssi_chunks = value;
break;
case OPTION_PREFER_UI_BRIDGES:
carla_options.prefer_ui_bridges = value;
break;
#ifndef Q_OS_WIN
// FIXME
case OPTION_PATH_LADSPA:
setenv("LADSPA_PATH", value_str, 1);
carla_setenv("LADSPA_PATH", value_str);
break;
case OPTION_PATH_DSSI:
setenv("DSSI_PATH", value_str, 1);
carla_setenv("DSSI_PATH", value_str);
break;
case OPTION_PATH_LV2:
setenv("LV2_PATH", value_str, 1);
carla_setenv("LV2_PATH", value_str);
break;
case OPTION_PATH_VST:
setenv("VST_PATH", value_str, 1);
carla_setenv("VST_PATH", value_str);
break;
case OPTION_PATH_SF2:
setenv("SF2_PATH", value_str, 1);
carla_setenv("SF2_PATH", value_str);
break;
#endif
case OPTION_PATH_BRIDGE_UNIX32:
carla_options.bridge_unix32 = strdup(value_str);
break;
@@ -1206,5 +1219,79 @@ void set_option(OptionsType option, int value, const char* value_str)
}
}

CARLA_BACKEND_END_NAMESPACE

// End of exported symbols (API)
// -------------------------------------------------------------------------------------------------------------------

#ifdef QTCREATOR_TEST

#include <QtGui/QApplication>
#include <QtGui/QDialog>

QDialog* gui;

#ifndef CARLA_BACKEND_NO_NAMESPACE
using namespace CarlaBackend;
#endif

void main_callback(CallbackType action, unsigned short plugin_id, int value1, int value2, double value3)
{
qDebug("Callback(%i, %u, %i, %i, %f)", action, plugin_id, value1, value2, value3);

switch (action)
{
case CALLBACK_SHOW_GUI:
if (! value1)
gui->close();
break;
case CALLBACK_RESIZE_GUI:
gui->setFixedSize(value1, value2);
break;
default:
break;
}
}

int main(int argc, char* argv[])
{
QApplication app(argc, argv);
gui = new QDialog(nullptr);

if (engine_init("carla_demo"))
{
set_callback_function(main_callback);
short id = add_plugin_dssi("/usr/lib/dssi/horgand.so", "horgand", "/usr/lib/dssi/horgand/horgand_fltk");

if (id >= 0)
{
qDebug("Main Initiated, id = %u", id);
//const char* test_name = strdup("test reloaded named");
//set_name(id, test_name);

const GuiInfo* guiInfo = get_gui_info(id);

if (guiInfo->type == GUI_INTERNAL_QT4 || guiInfo->type == GUI_INTERNAL_X11)
{
set_gui_data(id, 0, (quintptr)gui);
gui->show();
}

show_gui(id, true);
app.exec();

remove_plugin(id);
}
else
qCritical("failed: %s", get_last_error());

engine_close();
}
else
qCritical("failed to start backend engine");

delete gui;
return 0;
}

#endif

+ 37
- 16
src/carla-backend/carla_backend.h View File

@@ -20,15 +20,27 @@

#include "carla_includes.h"

#define CARLA_BACKEND_NO_NAMESPACE

#ifdef CARLA_BACKEND_NO_NAMESPACE
#define CARLA_BACKEND_START_NAMESPACE
#define CARLA_BACKEND_END_NAMESPACE
#else
#define CARLA_BACKEND_START_NAMESPACE namespace CarlaBackend {
#define CARLA_BACKEND_END_NAMESPACE }
#endif

CARLA_BACKEND_START_NAMESPACE

#define STR_MAX 256

// static max values
#ifdef BUILD_BRIDGE
const unsigned short MAX_PLUGINS = 1;
const unsigned short MAX_PLUGINS = 1;
#else
const unsigned short MAX_PLUGINS = 99;
const unsigned short MAX_PLUGINS = 99;
#endif
const unsigned int MAX_PARAMETERS = 200;
const unsigned int MAX_PARAMETERS = 200;

// plugin hints
const unsigned int PLUGIN_IS_BRIDGE = 0x01;
@@ -110,9 +122,9 @@ enum GuiType {
};

enum OptionsType {
OPTION_GLOBAL_JACK_CLIENT = 1,
OPTION_USE_DSSI_CHUNKS = 2,
OPTION_PREFER_UI_BRIDGES = 3,
OPTION_MAX_PARAMETERS = 1,
OPTION_PREFER_UI_BRIDGES = 2,
OPTION_PROCESS_32X = 3,
OPTION_PATH_LADSPA = 4,
OPTION_PATH_DSSI = 5,
OPTION_PATH_LV2 = 6,
@@ -226,16 +238,18 @@ struct PluginBridgeInfo {
quint32 mouts;
};

class CarlaPlugin;

typedef void (*CallbackFunc)(CallbackType action, unsigned short plugin_id, int value1, int value2, double value3);

#ifndef CARLA_NO_EXPORTS

// -----------------------------------------------------
// Exported symbols (API)

#ifndef CARLA_NO_EXPORTS

CARLA_EXPORT bool carla_init(const char* client_name);
CARLA_EXPORT bool carla_close();
CARLA_EXPORT bool carla_is_engine_running();
CARLA_EXPORT bool engine_init(const char* client_name);
CARLA_EXPORT bool engine_close();
CARLA_EXPORT bool is_engine_running();

CARLA_EXPORT short add_plugin(BinaryType btype, PluginType ptype, const char* filename, const char* label, void* extra_stuff);
CARLA_EXPORT bool remove_plugin(unsigned short plugin_id);
@@ -249,9 +263,9 @@ CARLA_EXPORT ScalePointInfo* get_scalepoint_info(unsigned short plugin_id, quint
CARLA_EXPORT MidiProgramInfo* get_midi_program_info(unsigned short plugin_id, quint32 midi_program_id);
CARLA_EXPORT GuiInfo* get_gui_info(unsigned short plugin_id);

CARLA_EXPORT ParameterData* get_parameter_data(unsigned short plugin_id, quint32 parameter_id);
CARLA_EXPORT ParameterRanges* get_parameter_ranges(unsigned short plugin_id, quint32 parameter_id);
CARLA_EXPORT CustomData* get_custom_data(unsigned short plugin_id, quint32 custom_data_id);
CARLA_EXPORT const ParameterData* get_parameter_data(unsigned short plugin_id, quint32 parameter_id);
CARLA_EXPORT const ParameterRanges* get_parameter_ranges(unsigned short plugin_id, quint32 parameter_id);
CARLA_EXPORT const CustomData* get_custom_data(unsigned short plugin_id, quint32 custom_data_id);
CARLA_EXPORT const char* get_chunk_data(unsigned short plugin_id);

CARLA_EXPORT quint32 get_parameter_count(unsigned short plugin_id);
@@ -288,6 +302,7 @@ CARLA_EXPORT void set_midi_program(unsigned short plugin_id, quint32 midi_progra
CARLA_EXPORT void set_custom_data(unsigned short plugin_id, CustomDataType dtype, const char* key, const char* value);
CARLA_EXPORT void set_chunk_data(unsigned short plugin_id, const char* chunk_data);
CARLA_EXPORT void set_gui_data(unsigned short plugin_id, int data, quintptr gui_addr);
//CARLA_EXPORT void set_name(unsigned short plugin_id, const char* name); // TESTING

CARLA_EXPORT void show_gui(unsigned short plugin_id, bool yesno);
CARLA_EXPORT void idle_guis();
@@ -306,9 +321,15 @@ CARLA_EXPORT quint32 get_buffer_size();
CARLA_EXPORT double get_sample_rate();
CARLA_EXPORT double get_latency();

#endif // CARLA_NO_EXPORTS

// End of exported symbols
// -----------------------------------------------------

#endif // CARLA_NO_EXPORTS

CARLA_BACKEND_END_NAMESPACE

#ifndef CARLA_BACKEND_NO_NAMESPACE
typedef CarlaBackend::CarlaPlugin CarlaPlugin;
#endif

#endif // CARLA_BACKEND_H

+ 11
- 10
src/carla-backend/carla_bridge.cpp View File

@@ -17,6 +17,8 @@

#include "carla_plugin.h"

CARLA_BACKEND_START_NAMESPACE

struct BridgeParamInfo {
QString name;
QString unit;
@@ -25,7 +27,7 @@ struct BridgeParamInfo {
class BridgePlugin : public CarlaPlugin
{
public:
BridgePlugin(BinaryType btype, PluginType ptype) : CarlaPlugin(),
BridgePlugin(BinaryType btype, PluginType ptype, unsigned short id) : CarlaPlugin(id),
m_binary(btype)
{
qDebug("BridgePlugin::BridgePlugin()");
@@ -203,21 +205,21 @@ public:

switch (intoType)
{
case PluginBridgeAudioCountInfo:
case PluginBridgeAudioCount:
{
m_info.ains = argv[0]->i;
m_info.aouts = argv[1]->i;
break;
}

case PluginBridgeMidiCountInfo:
case PluginBridgeMidiCount:
{
m_info.mins = argv[0]->i;
m_info.mouts = argv[1]->i;
break;
}

case PluginBridgeParameterCountInfo:
case PluginBridgeParameterCount:
{
// delete old data
if (param.count > 0)
@@ -232,7 +234,7 @@ public:

if (param.count > 0 && param.count < MAX_PARAMETERS)
{
param.data = new ParameterData[param.count];
param.data = new ::ParameterData[param.count];
param.ranges = new ParameterRanges[param.count];
param_buffers = new double[param.count];
param_info = new BridgeParamInfo[param.count];
@@ -379,6 +381,8 @@ private:
BridgeParamInfo* param_info;
};

CARLA_BACKEND_END_NAMESPACE

short add_plugin_bridge(BinaryType btype, PluginType ptype, const char* filename, const char* label, void* extra_stuff)
{
qDebug("add_plugin_bridge(%i, %i, %s, %s, %p)", btype, ptype, filename, label, extra_stuff);
@@ -387,19 +391,16 @@ short add_plugin_bridge(BinaryType btype, PluginType ptype, const char* filename

if (id >= 0)
{
BridgePlugin* plugin = new BridgePlugin(btype, ptype);
BridgePlugin* plugin = new BridgePlugin(btype, ptype, id);

if (plugin->init(filename, label, (PluginBridgeInfo*)extra_stuff))
{
plugin->reload();
plugin->set_id(id);

unique_names[id] = plugin->name();
CarlaPlugins[id] = plugin;

#ifndef BUILD_BRIDGE
plugin->osc_global_register_new();
#endif
plugin->osc_register_new();
}
else
{


+ 167
- 0
src/carla-backend/carla_engine.h View File

@@ -0,0 +1,167 @@
/*
* JACK Backend code for Carla
* Copyright (C) 2012 Filipe Coelho <falktx@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* any later version.
*
* This program 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.
*
* For a full copy of the GNU General Public License see the COPYING file
*/

#ifndef CARLA_ENGINE_H
#define CARLA_ENGINE_H

#include "carla_backend.h"

#if defined(CARLA_ENGINE_JACK)
#include <jack/jack.h>
#include <jack/midiport.h>
typedef jack_client_t CarlaEngineClientNativeHandle;
typedef jack_port_t CarlaEnginePortNativeHandle;
#elif defined(CARLA_ENGINE_RTAUDIO)
#include <RtAudio.h>
#include <RtMidi.h>
typedef void* CarlaEngineClientNativeHandle;
typedef void* CarlaEnginePortNativeHandle;
#endif

CARLA_BACKEND_START_NAMESPACE

#if 0
} /* adjust editor indent */
#endif

enum CarlaEnginePortType {
CarlaEnginePortTypeAudio,
CarlaEnginePortTypeControl,
CarlaEnginePortTypeMIDI
};

enum CarlaEngineEventType {
CarlaEngineEventControlChange,
CarlaEngineEventMidiBankChange,
CarlaEngineEventMidiProgramChange,
CarlaEngineEventAllSoundOff,
CarlaEngineEventAllNotesOff
};

struct CarlaEngineControlEvent {
CarlaEngineEventType type;
uint32_t time;
uint8_t channel;
uint8_t controller;
double value;
};

struct CarlaEngineMidiEvent {
uint32_t time;
uint8_t size;
uint8_t data[4];
};

//struct CarlaTimeInfo {
// bool playing;
// double bpm;
//};

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

class CarlaEngine
{
public:
CarlaEngine();
~CarlaEngine();

static bool init(const char* name);
static bool close();
static bool isOnAudioThread();
static bool isOffline();
static int maxClientNameSize();

//static const CarlaTimeInfo* getTimeInfo();
};

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

class CarlaEngineBasePort
{
public:
CarlaEngineBasePort(CarlaEngineClientNativeHandle* const client, bool isInput);
virtual ~CarlaEngineBasePort();

virtual void* getBuffer(uint32_t frames) = 0;

protected:
const bool isInput;
CarlaEnginePortNativeHandle* handle;
CarlaEngineClientNativeHandle* const client;
};

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

class CarlaEngineClient
{
public:
CarlaEngineClient(CarlaPlugin* const plugin);
~CarlaEngineClient();

void activate();
void deactivate();

bool isActive();
bool isOk();

CarlaEngineBasePort* addPort(const char* name, CarlaEnginePortType type, bool isInput);

private:
CarlaEngineClientNativeHandle* handle;
bool m_active;
};

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

class CarlaEngineAudioPort : public CarlaEngineBasePort
{
public:
CarlaEngineAudioPort(CarlaEngineClientNativeHandle* const client, const char* name, bool isInput);

void* getBuffer(uint32_t frames);
};

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

class CarlaEngineControlPort : public CarlaEngineBasePort
{
public:
CarlaEngineControlPort(CarlaEngineClientNativeHandle* const client, const char* name, bool isInput);

void* getBuffer(uint32_t frames);

uint32_t getEventCount(void* buffer);
const CarlaEngineControlEvent* getEvent(void* buffer, uint32_t index);
void writeEvent(void* buffer, uint8_t channel, uint8_t controller, double value);
};

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

class CarlaEngineMidiPort : public CarlaEngineBasePort
{
public:
CarlaEngineMidiPort(CarlaEngineClientNativeHandle* const client, const char* name, bool isInput);

void* getBuffer(uint32_t frames);

uint32_t getEventCount(void* buffer);
const CarlaEngineMidiEvent* getEvent(void* buffer, uint32_t index);
};

CARLA_BACKEND_END_NAMESPACE

#endif // CARLA_ENGINE_H

+ 456
- 0
src/carla-backend/carla_engine_jack.cpp View File

@@ -0,0 +1,456 @@
/*
* JACK Backend code for Carla
* Copyright (C) 2011-2012 Filipe Coelho <falktx@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* any later version.
*
* This program 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.
*
* For a full copy of the GNU General Public License see the COPYING file
*/

#ifdef CARLA_ENGINE_JACK

#include "carla_engine.h"
#include "carla_plugin.h"

#include <iostream>

CARLA_BACKEND_START_NAMESPACE

// Global JACK stuff
static jack_client_t* carla_jack_client = nullptr;
static jack_nframes_t carla_buffer_size = 512;
static jack_nframes_t carla_sample_rate = 44100;
static jack_transport_state_t carla_jack_state = JackTransportStopped;
static jack_position_t carla_jack_pos;

static bool carla_jack_is_freewheel = false;
static const char* carla_client_name = nullptr;
static QThread* carla_jack_thread = nullptr;

// -------------------------------------------------------------------------------------------------------------------
// Exported symbols (API)

bool is_engine_running()
{
return bool(carla_jack_client);
}

const char* get_host_client_name()
{
return carla_client_name;
}

quint32 get_buffer_size()
{
qDebug("get_buffer_size()");
if (carla_options.proccess_32x)
return 32;
return carla_buffer_size;
}

double get_sample_rate()
{
qDebug("get_sample_rate()");
return carla_sample_rate;
}

double get_latency()
{
qDebug("get_latency()");
return double(carla_buffer_size)/carla_sample_rate*1000;
}

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

static int carla_jack_bufsize_callback(jack_nframes_t new_buffer_size, void*)
{
carla_buffer_size = new_buffer_size;

if (carla_options.proccess_32x)
return 0;

for (unsigned short i=0; i<MAX_PLUGINS; i++)
{
CarlaPlugin* plugin = CarlaPlugins[i];
if (plugin && plugin->enabled())
plugin->buffer_size_changed(new_buffer_size);
}

return 0;
}

static int carla_jack_srate_callback(jack_nframes_t new_sample_rate, void*)
{
carla_sample_rate = new_sample_rate;
return 0;
}

static void carla_jack_freewheel_callback(int starting, void*)
{
carla_jack_is_freewheel = bool(starting);
}

static int carla_jack_process_callback(jack_nframes_t nframes, void* arg)
{
if (carla_jack_thread == nullptr)
carla_jack_thread = QThread::currentThread();

// request time info once (arg only null on global client)
if (carla_jack_client && ! arg)
carla_jack_state = jack_transport_query(carla_jack_client, &carla_jack_pos);

CarlaPlugin* plugin = (CarlaPlugin*)arg;

if (plugin && plugin->enabled())
{
carla_proc_lock();
plugin->process_jack(nframes);
carla_proc_unlock();
}

return 0;
}

static void carla_jack_shutdown_callback(void*)
{
for (unsigned short i=0; i<MAX_PLUGINS; i++)
{
// FIXME
//CarlaPlugin* plugin = CarlaPlugins[i];
//if (plugin && plugin->id() == plugin_id)
// plugin->jack_client = nullptr;
}
carla_jack_client = nullptr;
carla_jack_thread = nullptr;
callback_action(CALLBACK_QUIT, 0, 0, 0, 0.0);
}

// -------------------------------------------------------------------------------------------------------------------
// Carla Engine

CarlaEngine::CarlaEngine() {}
CarlaEngine::~CarlaEngine() {}

bool CarlaEngine::init(const char* name)
{
carla_jack_client = jack_client_open(name, JackNullOption, nullptr);

if (carla_jack_client)
{
carla_buffer_size = jack_get_buffer_size(carla_jack_client);
carla_sample_rate = jack_get_sample_rate(carla_jack_client);

jack_set_buffer_size_callback(carla_jack_client, carla_jack_bufsize_callback, nullptr);
jack_set_sample_rate_callback(carla_jack_client, carla_jack_srate_callback, nullptr);
jack_set_freewheel_callback(carla_jack_client, carla_jack_freewheel_callback, nullptr);
jack_set_process_callback(carla_jack_client, carla_jack_process_callback, nullptr);
jack_on_shutdown(carla_jack_client, carla_jack_shutdown_callback, nullptr);

if (jack_activate(carla_jack_client) == 0)
{
// set client name, fixed for OSC usage
// FIXME - put this in shared
char* fixed_name = strdup(jack_get_client_name(carla_jack_client));
for (size_t i=0; i < strlen(fixed_name); i++)
{
if (std::isalpha(fixed_name[i]) == false && std::isdigit(fixed_name[i]) == false)
fixed_name[i] = '_';
}

carla_client_name = strdup(fixed_name);
free((void*)fixed_name);

return true;
}
else
{
set_last_error("Failed to activate the JACK client");
carla_jack_client = nullptr;
}
}
else
set_last_error("Failed to create new JACK client");

return false;
}

bool CarlaEngine::close()
{
if (carla_client_name)
{
free((void*)carla_client_name);
carla_client_name = nullptr;
}

if (jack_deactivate(carla_jack_client) == 0)
{
if (jack_client_close(carla_jack_client) == 0)
{
carla_jack_client = nullptr;
return true;
}
else
set_last_error("Failed to close the JACK client");
}
else
set_last_error("Failed to deactivate the JACK client");

carla_jack_client = nullptr;
return false;
}

bool CarlaEngine::isOnAudioThread()
{
return (QThread::currentThread() == carla_jack_thread);
}

bool CarlaEngine::isOffline()
{
return carla_jack_is_freewheel;
}

int CarlaEngine::maxClientNameSize()
{
return jack_client_name_size();
}

// -------------------------------------------------------------------------------------------------------------------
// Carla Engine Port (Base class)

CarlaEngineBasePort::CarlaEngineBasePort(CarlaEngineClientNativeHandle* const clientHandle, bool isInput_) :
isInput(isInput_),
client(clientHandle)
{
}

CarlaEngineBasePort::~CarlaEngineBasePort()
{
if (handle)
jack_port_unregister(client, handle);
}

// -------------------------------------------------------------------------------------------------------------------
// Carla Engine Client

CarlaEngineClient::CarlaEngineClient(CarlaPlugin* const plugin)
{
m_active = false;
handle = jack_client_open(plugin->name(), JackNullOption, nullptr);

if (handle)
jack_set_process_callback(handle, carla_jack_process_callback, plugin);
}

CarlaEngineClient::~CarlaEngineClient()
{
if (handle)
jack_client_close(handle);
}

void CarlaEngineClient::activate()
{
if (handle)
jack_activate(handle);
m_active = true;
}

void CarlaEngineClient::deactivate()
{
if (handle)
jack_deactivate(handle);
m_active = false;
}

bool CarlaEngineClient::isActive()
{
return m_active;
}

bool CarlaEngineClient::isOk()
{
return bool(handle);
}

CarlaEngineBasePort* CarlaEngineClient::addPort(const char* name, CarlaEnginePortType type, bool isInput)
{
if (type == CarlaEnginePortTypeAudio)
return new CarlaEngineAudioPort(handle, name, isInput);
if (type == CarlaEnginePortTypeControl)
return new CarlaEngineControlPort(handle, name, isInput);
if (type == CarlaEnginePortTypeMIDI)
return new CarlaEngineMidiPort(handle, name, isInput);
return nullptr;
}

// -------------------------------------------------------------------------------------------------------------------
// Carla Engine Port (Audio)

CarlaEngineAudioPort::CarlaEngineAudioPort(CarlaEngineClientNativeHandle* const client, const char* name, bool isInput) :
CarlaEngineBasePort(client, isInput)
{
handle = jack_port_register(client, name, JACK_DEFAULT_AUDIO_TYPE, isInput ? JackPortIsInput : JackPortIsOutput, 0);
}

void* CarlaEngineAudioPort::getBuffer(uint32_t frames)
{
return jack_port_get_buffer(handle, frames);
}

// -------------------------------------------------------------------------------------------------------------------
// Carla Engine Port (Control)

CarlaEngineControlPort::CarlaEngineControlPort(CarlaEngineClientNativeHandle* const client, const char* name, bool isInput) :
CarlaEngineBasePort(client, isInput)
{
handle = jack_port_register(client, name, JACK_DEFAULT_MIDI_TYPE, isInput ? JackPortIsInput : JackPortIsOutput, 0);
}

void* CarlaEngineControlPort::getBuffer(uint32_t frames)
{
void* buffer = jack_port_get_buffer(handle, frames);

if (! isInput)
jack_midi_clear_buffer(buffer);

return buffer;
}

uint32_t CarlaEngineControlPort::getEventCount(void* buffer)
{
if (! isInput)
return 0;

return jack_midi_get_event_count(buffer);
}

const CarlaEngineControlEvent* CarlaEngineControlPort::getEvent(void* buffer, uint32_t index)
{
if (! isInput)
return nullptr;

static jack_midi_event_t jackEvent;
static CarlaEngineControlEvent carlaEvent;

if (jack_midi_event_get(&jackEvent, buffer, index) != 0)
return nullptr;

memset(&carlaEvent, 0, sizeof(CarlaEngineControlEvent));

uint8_t midiStatus = jackEvent.buffer[0];
uint8_t midiChannel = midiStatus & 0x0F;

carlaEvent.time = jackEvent.time;
carlaEvent.channel = midiChannel;

if (MIDI_IS_STATUS_CONTROL_CHANGE(midiStatus))
{
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;
}

return &carlaEvent;
}
else if (MIDI_IS_STATUS_PROGRAM_CHANGE(midiStatus))
{
uint8_t midiProgram = jackEvent.buffer[1];
carlaEvent.type = CarlaEngineEventMidiProgramChange;
carlaEvent.value = midiProgram;

return &carlaEvent;
}

return nullptr;
}

void CarlaEngineControlPort::writeEvent(void* buffer, uint8_t channel, uint8_t controller, double value)
{
if (isInput)
return;

jack_midi_data_t* event_buffer = jack_midi_event_reserve(buffer, 0, 3);

if (event_buffer)
{
event_buffer[0] = MIDI_STATUS_CONTROL_CHANGE + channel;
event_buffer[1] = controller;
event_buffer[2] = value * 127;
}
}

// -------------------------------------------------------------------------------------------------------------------
// Carla Engine Port (MIDI)

CarlaEngineMidiPort::CarlaEngineMidiPort(CarlaEngineClientNativeHandle* const client, const char* name, bool isInput) :
CarlaEngineBasePort(client, isInput)
{
handle = jack_port_register(client, name, JACK_DEFAULT_MIDI_TYPE, isInput ? JackPortIsInput : JackPortIsOutput, 0);
}

void* CarlaEngineMidiPort::getBuffer(uint32_t frames)
{
void* buffer = jack_port_get_buffer(handle, frames);

if (! isInput)
jack_midi_clear_buffer(buffer);

return buffer;
}

uint32_t CarlaEngineMidiPort::getEventCount(void* buffer)
{
if (! isInput)
return 0;

return jack_midi_get_event_count(buffer);
}

const CarlaEngineMidiEvent* CarlaEngineMidiPort::getEvent(void* buffer, uint32_t index)
{
if (! isInput)
return nullptr;

static jack_midi_event_t jackEvent;
static CarlaEngineMidiEvent carlaEvent;

if (jack_midi_event_get(&jackEvent, buffer, index) != 0)
return nullptr;

carlaEvent.time = jackEvent.time;
carlaEvent.size = jackEvent.size;
memcpy(carlaEvent.data, jackEvent.buffer, jackEvent.size);

return &carlaEvent;
}

CARLA_BACKEND_END_NAMESPACE

#endif // CARLA_ENGINE_JACK

+ 156
- 0
src/carla-backend/carla_engine_rtaudio.cpp View File

@@ -0,0 +1,156 @@
/*
* JACK Backend code for Carla
* Copyright (C) 2012 Filipe Coelho <falktx@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* any later version.
*
* This program 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.
*
* For a full copy of the GNU General Public License see the COPYING file
*/

#ifdef CARLA_ENGINE_RTAUDIO

#include "carla_engine.h"
#include "carla_plugin.h"

static RtAudio adac(RtAudio::LINUX_ALSA);

static uint32_t carla_buffer_size = 512;
static const char* carla_client_name = nullptr;

// -------------------------------------------------------------------------------------------------------------------
// Exported symbols (API)

CARLA_BACKEND_START_NAMESPACE

bool is_engine_running()
{
return adac.isStreamRunning();
}

const char* get_host_client_name()
{
return carla_client_name;
}

quint32 get_buffer_size()
{
qDebug("get_buffer_size()");
if (carla_options.proccess_32x)
return 32;
return carla_buffer_size;
}

double get_sample_rate()
{
qDebug("get_sample_rate()");
return adac.getStreamSampleRate();
}

double get_latency()
{
qDebug("get_latency()");
return double(carla_buffer_size)/get_sample_rate()*1000;
}

CARLA_BACKEND_END_NAMESPACE

// End of exported symbols (API)
// -------------------------------------------------------------------------------------------------------------------

static int process_callback(void* outputBuffer, void* inputBuffer, unsigned int frames, double streamTime, RtAudioStreamStatus status, void* data)
{
// Since the number of input and output channels is equal, we can do
// a simple buffer copy operation here.
if ( status ) std::cout << "Stream over/underflow detected." << std::endl;

float* in1 = ((float**)inputBuffer)[0];
float* in2 = ((float**)inputBuffer)[1];
float* out1 = ((float**)outputBuffer)[0];
float* out2 = ((float**)outputBuffer)[1];

memcpy(out1, in1, frames);
memcpy(out2, in2, frames);

return 0;
}

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

CarlaEngine::CarlaEngine()
{
}

CarlaEngine::~CarlaEngine()
{
}

bool CarlaEngine::init(const char* name)
{
if (adac.getDeviceCount() < 1)
{
CarlaBackend::set_last_error("No audio devices available");
return false;
}

// Set the same number of channels for both input and output.
unsigned int bufferFrames = 512;
RtAudio::StreamParameters iParams, oParams;
iParams.nChannels = 2;
oParams.nChannels = 2;
RtAudio::StreamOptions options;
options.flags = RTAUDIO_MINIMIZE_LATENCY | RTAUDIO_SCHEDULE_REALTIME | RTAUDIO_ALSA_USE_DEFAULT;
options.streamName = name;
options.priority = 85;

try {
adac.openStream(&oParams, &iParams, RTAUDIO_FLOAT32, 44100, &bufferFrames, process_callback, nullptr, &options);
}
catch (RtError& e)
{
CarlaBackend::set_last_error(e.what());
return false;
}

try {
adac.startStream();
}
catch (RtError& e)
{
CarlaBackend::set_last_error(e.what());
return false;
}
}

bool CarlaEngine::close()
{
if (adac.isStreamRunning())
adac.stopStream();

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

bool CarlaEngine::isOnAudioThread()
{

}

bool CarlaEngine::isOffline()
{

}

int CarlaEngine::maxClientNameSize()
{

}

#endif // CARLA_ENGINE_RTAUDIO

+ 0
- 273
src/carla-backend/carla_jack.cpp View File

@@ -1,273 +0,0 @@
/*
* JACK Backend code for Carla
* Copyright (C) 2011-2012 Filipe Coelho <falktx@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* any later version.
*
* This program 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.
*
* For a full copy of the GNU General Public License see the COPYING file
*/

#include "carla_jack.h"
#include "carla_plugin.h"

#include <iostream>

// Global JACK stuff
static jack_client_t* carla_jack_client = nullptr;
static jack_nframes_t carla_buffer_size = 512;
static jack_nframes_t carla_sample_rate = 44100;
static jack_transport_state_t carla_jack_state = JackTransportStopped;
static jack_position_t carla_jack_pos;

static bool carla_jack_is_freewheel = false;
static const char* carla_client_name = nullptr;
static QThread* carla_jack_thread = nullptr;

// -------------------------------------------------------------------------------------------------------------------
// Exported symbols (API)

bool carla_is_engine_running()
{
return bool(carla_jack_client);
}

const char* get_host_client_name()
{
return carla_client_name;
}

uint32_t get_buffer_size()
{
qDebug("get_buffer_size()");
return carla_buffer_size;
}

double get_sample_rate()
{
qDebug("get_sample_rate()");
return carla_sample_rate;
}

double get_latency()
{
qDebug("get_latency()");
return double(carla_buffer_size)/carla_sample_rate*1000;
}

// End of exported symbols (API)
// -------------------------------------------------------------------------------------------------------------------

static int carla_jack_bufsize_callback(jack_nframes_t new_buffer_size, void*)
{
carla_buffer_size = new_buffer_size;

#ifdef BUILD_BRIDGE
CarlaPlugin* plugin = CarlaPlugins[0];
if (plugin && plugin->id() >= 0)
plugin->buffer_size_changed(new_buffer_size);
#else
for (unsigned short i=0; i<MAX_PLUGINS; i++)
{
CarlaPlugin* plugin = CarlaPlugins[i];
if (plugin && plugin->id() >= 0)
plugin->buffer_size_changed(new_buffer_size);
}
#endif

return 0;
}

static int carla_jack_srate_callback(jack_nframes_t new_sample_rate, void*)
{
carla_sample_rate = new_sample_rate;
return 0;
}

static void carla_jack_freewheel_callback(int starting, void*)
{
carla_jack_is_freewheel = (starting != 0);
}

static int carla_jack_process_callback(jack_nframes_t nframes, void* arg)
{
if (carla_jack_thread == nullptr)
carla_jack_thread = QThread::currentThread();

// request time info once (arg only null on global client)
if (carla_jack_client && arg == nullptr)
carla_jack_state = jack_transport_query(carla_jack_client, &carla_jack_pos);

#ifndef BUILD_BRIDGE
if (carla_options.global_jack_client)
{
for (unsigned short i=0; i<MAX_PLUGINS; i++)
{
CarlaPlugin* plugin = CarlaPlugins[i];
if (plugin && plugin->id() >= 0)
{
carla_proc_lock();
plugin->process(nframes);
carla_proc_unlock();
}
}
return 0;
}
#endif

#ifdef BUILD_BRIDGE
CarlaPlugin* plugin = CarlaPlugins[0];
#else
CarlaPlugin* plugin = (CarlaPlugin*)arg;
#endif
if (plugin && plugin->id() >= 0)
{
carla_proc_lock();
plugin->process(nframes);
carla_proc_unlock();
}

return 0;
}

static void carla_jack_shutdown_callback(void*)
{
for (unsigned short i=0; i<MAX_PLUGINS; i++)
{
// FIXME
//CarlaPlugin* plugin = CarlaPlugins[i];
//if (plugin && plugin->id() == plugin_id)
// plugin->jack_client = nullptr;
}
carla_jack_client = nullptr;
carla_jack_thread = nullptr;
callback_action(CALLBACK_QUIT, 0, 0, 0, 0.0);
}

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

bool carla_jack_init(const char* client_name)
{
carla_jack_client = jack_client_open(client_name, JackNullOption, nullptr);

if (carla_jack_client)
{
carla_buffer_size = jack_get_buffer_size(carla_jack_client);
carla_sample_rate = jack_get_sample_rate(carla_jack_client);

#ifndef BUILD_BRIDGE
jack_set_buffer_size_callback(carla_jack_client, carla_jack_bufsize_callback, nullptr);
jack_set_sample_rate_callback(carla_jack_client, carla_jack_srate_callback, nullptr);
jack_set_freewheel_callback(carla_jack_client, carla_jack_freewheel_callback, nullptr);
jack_set_process_callback(carla_jack_client, carla_jack_process_callback, nullptr);
jack_on_shutdown(carla_jack_client, carla_jack_shutdown_callback, nullptr);

if (jack_activate(carla_jack_client) == 0)
{
// set client name, fixed for OSC usage
char* fixed_name = strdup(jack_get_client_name(carla_jack_client));
for (size_t i=0; i < strlen(fixed_name); i++)
{
if (std::isalpha(fixed_name[i]) == false && std::isdigit(fixed_name[i]) == false)
fixed_name[i] = '_';
}

carla_client_name = strdup(fixed_name);
free((void*)fixed_name);

return true;
}
else
{
set_last_error("Failed to activate the JACK client");
carla_jack_client = nullptr;
}
#endif
}
else
{
set_last_error("Failed to create new JACK client");
carla_jack_client = nullptr;
}

return false;
}

bool carla_jack_close()
{
if (carla_client_name)
free((void*)carla_client_name);

if (jack_deactivate(carla_jack_client) == 0)
{
#ifndef BUILD_BRIDGE
if (jack_client_close(carla_jack_client) == 0)
{
carla_jack_client = nullptr;
return true;
}
else
set_last_error("Failed to close the JACK client");
#endif
}
else
set_last_error("Failed to deactivate the JACK client");

carla_jack_client = nullptr;
return false;
}

bool carla_jack_register_plugin(CarlaPlugin* plugin, jack_client_t** client)
{
#ifndef BUILD_BRIDGE
if (carla_options.global_jack_client)
{
*client = carla_jack_client;
return true;
}
#endif

*client = jack_client_open(plugin->name(), JackNullOption, nullptr);

if (*client)
{
#ifdef BUILD_BRIDGE
carla_buffer_size = jack_get_buffer_size(*client);
carla_sample_rate = jack_get_sample_rate(*client);

jack_set_buffer_size_callback(*client, carla_jack_bufsize_callback, nullptr);
jack_set_sample_rate_callback(*client, carla_jack_srate_callback, nullptr);
jack_set_freewheel_callback(*client, carla_jack_freewheel_callback, nullptr);
jack_set_process_callback(*client, carla_jack_process_callback, nullptr);
jack_on_shutdown(*client, carla_jack_shutdown_callback, nullptr);
#else
jack_set_process_callback(*client, carla_jack_process_callback, plugin);
#endif
return true;
}

return false;
}

bool carla_jack_transport_query(jack_position_t** pos)
{
*pos = &carla_jack_pos;
return (carla_jack_state != JackTransportStopped);
}

bool carla_jack_on_audio_thread()
{
return (QThread::currentThread() == carla_jack_thread);
}

bool carla_jack_on_freewheel()
{
return carla_jack_is_freewheel;
}

+ 8
- 11
src/carla-backend/carla_jack.h View File

@@ -18,18 +18,15 @@
#ifndef CARLA_JACK_H
#define CARLA_JACK_H

#include "carla_includes.h"
//#include "carla_includes.h"

#include <jack/jack.h>
#include <jack/midiport.h>
//class CarlaPlugin;

class CarlaPlugin;

bool carla_jack_init(const char* client_name);
bool carla_jack_close();
bool carla_jack_register_plugin(CarlaPlugin* plugin, jack_client_t** client);
bool carla_jack_transport_query(jack_position_t** pos);
bool carla_jack_on_audio_thread();
bool carla_jack_on_freewheel();
//bool carla_jack_init(const char* client_name);
//bool carla_jack_close();
//bool carla_jack_register_plugin(CarlaPlugin* plugin, jack_client_t** client);
//bool carla_jack_transport_query(jack_position_t** pos);
//bool carla_jack_on_audio_thread();
//bool carla_jack_on_freewheel();

#endif // CARLA_JACK_H

+ 2
- 2
src/carla-backend/carla_midi.h View File

@@ -59,7 +59,7 @@
#define MIDI_CONTROL_BREATH_CONTROLLER 0x02 // 0-127, MSB
#define MIDI_CONTROL_FOOT_CONTROLLER 0x04 // 0-127, MSB
#define MIDI_CONTROL_PORTAMENTO_TIME 0x05 // 0-127, MSB
//#define MIDI_CONTROL_DATA_ENTRY 0x06 // 0-127, MSB
#define MIDI_CONTROL_DATA_ENTRY 0x06 // 0-127, MSB
#define MIDI_CONTROL_CHANNEL_VOLUME 0x07 // 0-127, MSB
#define MIDI_CONTROL_BALANCE 0x08 // 0-127, MSB
#define MIDI_CONTROL_PAN 0x0A // 0-127, MSB
@@ -75,7 +75,7 @@
#define MIDI_CONTROL_BREATH_CONTROLLER__LSB 0x22 // 0-127, LSB
#define MIDI_CONTROL_FOOT_CONTROLLER__LSB 0x24 // 0-127, LSB
#define MIDI_CONTROL_PORTAMENTO_TIME__LSB 0x25 // 0-127, LSB
//#define MIDI_CONTROL_DATA_ENTRY__LSB 0x26 // 0-127, LSB
#define MIDI_CONTROL_DATA_ENTRY__LSB 0x26 // 0-127, LSB
#define MIDI_CONTROL_CHANNEL_VOLUME__LSB 0x27 // 0-127, LSB
#define MIDI_CONTROL_BALANCE__LSB 0x28 // 0-127, LSB
#define MIDI_CONTROL_PAN__LSB 0x2A // 0-127, LSB


+ 14
- 6
src/carla-backend/carla_osc.cpp View File

@@ -28,15 +28,23 @@ OscData global_osc_data = { nullptr, nullptr, nullptr };
// -------------------------------------------------------------------------------------------------------------------
// Exported symbols (API)

CARLA_BACKEND_START_NAMESPACE

const char* get_host_osc_url()
{
qDebug("get_host_osc_url()");
return global_osc_server_path;
}

CARLA_BACKEND_END_NAMESPACE

// End of exported symbols (API)
// -------------------------------------------------------------------------------------------------------------------

#ifndef CARLA_BACKEND_NO_NAMESPACE
using namespace CarlaBackend;
#endif

void osc_init(const char*)
{
qDebug("osc_init()");
@@ -189,15 +197,15 @@ int osc_message_handler(const char* path, const char* types, lo_arg** argv, int
else if (strcmp(method, "bridge_aouts_peak") == 0)
return osc_handle_bridge_aouts_peak(plugin, argv);
else if (strcmp(method, "bridge_audio_count") == 0)
return plugin->set_osc_bridge_info(PluginBridgeAudioCountInfo, argv);
return plugin->set_osc_bridge_info(PluginBridgeAudioCount, argv);
else if (strcmp(method, "bridge_midi_count") == 0)
return plugin->set_osc_bridge_info(PluginBridgeMidiCountInfo, argv);
return plugin->set_osc_bridge_info(PluginBridgeMidiCount, argv);
else if (strcmp(method, "bridge_param_count") == 0)
return plugin->set_osc_bridge_info(PluginBridgeParameterCountInfo, argv);
return plugin->set_osc_bridge_info(PluginBridgeParameterCount, argv);
else if (strcmp(method, "bridge_program_count") == 0)
return plugin->set_osc_bridge_info(PluginBridgeProgramCountInfo, argv);
return plugin->set_osc_bridge_info(PluginBridgeProgramCount, argv);
else if (strcmp(method, "bridge_midi_program_count") == 0)
return plugin->set_osc_bridge_info(PluginBridgeMidiProgramCountInfo, argv);
return plugin->set_osc_bridge_info(PluginBridgeMidiProgramCount, argv);
else if (strcmp(method, "bridge_plugin_info") == 0)
return plugin->set_osc_bridge_info(PluginBridgePluginInfo, argv);
else if (strcmp(method, "bridge_param_info") == 0)
@@ -276,7 +284,7 @@ int osc_handle_register(lo_arg** argv, lo_address source)
for (unsigned short i=0; i<MAX_PLUGINS; i++)
{
//CarlaPlugin* plugin = CarlaPlugins[i];
//if (plugin && plugin->id() >= 0)
//if (plugin && plugin->enabled())
// osc_new_plugin(plugin);
}



+ 1
- 2
src/carla-backend/carla_osc.h View File

@@ -19,8 +19,7 @@
#define CARLA_OSC_H

#include "carla_osc_includes.h"

class CarlaPlugin;
#include "carla_backend.h"

int osc_handle_register(lo_arg** argv, lo_address source);
int osc_handle_unregister();


+ 379
- 268
src/carla-backend/carla_plugin.h
File diff suppressed because it is too large
View File


+ 8
- 5
src/carla-backend/carla_shared.cpp View File

@@ -16,11 +16,13 @@
*/

#include "carla_shared.h"
#include "carla_jack.h"
#include "carla_engine.h"

#include <QtCore/QMutex>
#include <QtCore/QString>

CARLA_BACKEND_START_NAMESPACE

// Global variables (shared)
const char* unique_names[MAX_PLUGINS] = { nullptr };
CarlaPlugin* CarlaPlugins[MAX_PLUGINS] = { nullptr };
@@ -31,9 +33,8 @@ volatile double aouts_peak[MAX_PLUGINS*2] = { 0.0 };
#ifndef BUILD_BRIDGE
// Global options
carla_options_t carla_options = {
/* global_jack_client */ false,
/* use_dssi_chunks */ false,
/* prefer_ui_bridges */ true,
/* proccess_32x */ false,
/* bridge_unix32 */ nullptr,
/* bridge_unix64 */ nullptr,
/* bridge_win32 */ nullptr,
@@ -51,7 +52,7 @@ QMutex carla_proc_lock_var;
QMutex carla_midi_lock_var;

// define max possible client name
const unsigned short max_client_name_size = jack_client_name_size() - 1 - 5; // 5 = strlen(" (10)")
const unsigned short max_client_name_size = CarlaEngine::maxClientNameSize() - 5; // 5 = strlen(" (10)")

// -------------------------------------------------------------------------------------------------------------------
// Exported symbols (API)
@@ -156,7 +157,7 @@ const char* get_unique_name(const char* name)
if (qname.isEmpty())
qname = "(No name)";

qname.truncate(max_client_name_size);
qname.truncate(max_client_name_size-1);
qname.replace(":", "."); // ":" is used in JACK to split client/port names

for (unsigned short i=0; i<MAX_PLUGINS; i++)
@@ -318,3 +319,5 @@ void callback_action(CallbackType action, unsigned short plugin_id, int value1,
if (Callback)
Callback(action, plugin_id, value1, value2, value3);
}

CARLA_BACKEND_END_NAMESPACE

+ 5
- 2
src/carla-backend/carla_shared.h View File

@@ -20,6 +20,8 @@

#include "carla_backend.h"

CARLA_BACKEND_START_NAMESPACE

class CarlaPlugin;

const char* bool2str(bool yesno);
@@ -48,9 +50,8 @@ extern volatile double aouts_peak[MAX_PLUGINS*2];
#ifndef BUILD_BRIDGE
// Global options
struct carla_options_t {
bool global_jack_client;
bool use_dssi_chunks;
bool prefer_ui_bridges;
bool proccess_32x;
const char* bridge_unix32;
const char* bridge_unix64;
const char* bridge_win32;
@@ -63,4 +64,6 @@ struct carla_options_t {
extern carla_options_t carla_options;
#endif

CARLA_BACKEND_END_NAMESPACE

#endif // CARLA_SHARED_H

+ 40
- 35
src/carla-backend/carla_threads.cpp View File

@@ -16,11 +16,14 @@
*/

#include "carla_threads.h"

#include "carla_plugin.h"

#include <QtCore/QProcess>

#ifndef CARLA_BACKEND_NO_NAMESPACE
using namespace CarlaBackend;
#endif

// --------------------------------------------------------------------------------------------------------
// CarlaCheckThread

@@ -46,112 +49,112 @@ void CarlaCheckThread::run()

uint32_t j, k;
double value;
ParameterData* param_data;
PluginPostEvent post_events[MAX_POST_EVENTS];
const ParameterData* paramData;
PluginPostEvent postEvents[MAX_POST_EVENTS];

m_stopNow = false;
while (carla_is_engine_running() && ! m_stopNow)
while (is_engine_running() && ! m_stopNow)
{
for (unsigned short i=0; i<MAX_PLUGINS; i++)
{
CarlaPlugin* plugin = CarlaPlugins[i];
if (plugin && plugin->id() >= 0)
if (plugin && plugin->enabled())
{
// --------------------------------------------------------------------------------------------------------
// Process postponed events

// Make a safe copy of events, and clear them
plugin->post_events_copy(post_events);
plugin->post_events_copy(postEvents);

OscData* osc_data = plugin->osc_data();

// Process events now
for (j=0; j < MAX_POST_EVENTS; j++)
{
if (post_events[j].valid)
if (postEvents[j].type != PluginPostEventNull)
{
switch (post_events[j].type)
switch (postEvents[j].type)
{
case PostEventDebug:
callback_action(CALLBACK_DEBUG, plugin->id(), post_events[j].index, 0, post_events[j].value);
case PluginPostEventDebug:
callback_action(CALLBACK_DEBUG, plugin->id(), postEvents[j].index, 0, postEvents[j].value);
break;

case PostEventParameterChange:
case PluginPostEventParameterChange:
// Update OSC based UIs
osc_send_control(osc_data, post_events[j].index, post_events[j].value);
osc_send_control(osc_data, postEvents[j].index, postEvents[j].value);

// Update OSC control client
osc_global_send_set_parameter_value(plugin->id(), post_events[j].index, post_events[j].value);
osc_global_send_set_parameter_value(plugin->id(), postEvents[j].index, postEvents[j].value);

// Update Host
callback_action(CALLBACK_PARAMETER_CHANGED, plugin->id(), post_events[j].index, 0, post_events[j].value);
callback_action(CALLBACK_PARAMETER_CHANGED, plugin->id(), postEvents[j].index, 0, postEvents[j].value);

break;

case PostEventProgramChange:
case PluginPostEventProgramChange:
// Update OSC based UIs
osc_send_program(osc_data, post_events[j].index);
osc_send_program(osc_data, postEvents[j].index);

// Update OSC control client
osc_global_send_set_program(plugin->id(), post_events[j].index);
osc_global_send_set_program(plugin->id(), postEvents[j].index);

for (k=0; k < plugin->param_count(); k++)
osc_global_send_set_default_value(plugin->id(), k, plugin->param_ranges(k)->def);

// Update Host
callback_action(CALLBACK_PROGRAM_CHANGED, plugin->id(), post_events[j].index, 0, 0.0);
callback_action(CALLBACK_PROGRAM_CHANGED, plugin->id(), postEvents[j].index, 0, 0.0);

break;

case PostEventMidiProgramChange:
if (post_events[j].index < (int32_t)plugin->midiprog_count())
case PluginPostEventMidiProgramChange:
if (postEvents[j].index < (int32_t)plugin->midiprog_count())
{
MidiProgramInfo midiprog = { false, 0, 0, nullptr };
plugin->get_midi_program_info(&midiprog, post_events[j].index);
plugin->get_midi_program_info(&midiprog, postEvents[j].index);

// Update OSC based UIs
osc_send_midi_program(osc_data, midiprog.bank, midiprog.program, (plugin->type() == PLUGIN_DSSI));

// Update OSC control client
osc_global_send_set_midi_program(plugin->id(), post_events[j].index);
osc_global_send_set_midi_program(plugin->id(), postEvents[j].index);

for (k=0; k < plugin->param_count(); k++)
osc_global_send_set_default_value(plugin->id(), k, plugin->param_ranges(k)->def);

// Update Host
callback_action(CALLBACK_MIDI_PROGRAM_CHANGED, plugin->id(), post_events[j].index, 0, 0.0);
callback_action(CALLBACK_MIDI_PROGRAM_CHANGED, plugin->id(), postEvents[j].index, 0, 0.0);
}

break;

case PostEventNoteOn:
case PluginPostEventNoteOn:
// Update OSC based UIs
//if (plugin->type() == PLUGIN_LV2)
// osc_send_note_on(osc_data, plugin->id(), post_events[j].index, post_events[j].value);

// Update OSC control client
osc_global_send_note_on(plugin->id(), post_events[j].index, post_events[j].value);
osc_global_send_note_on(plugin->id(), postEvents[j].index, postEvents[j].value);

// Update Host
callback_action(CALLBACK_NOTE_ON, plugin->id(), post_events[j].index, post_events[j].value, 0.0);
callback_action(CALLBACK_NOTE_ON, plugin->id(), postEvents[j].index, postEvents[j].value, 0.0);

break;

case PostEventNoteOff:
case PluginPostEventNoteOff:
// Update OSC based UIs
//if (plugin->type() == PLUGIN_LV2)
// osc_send_note_off(osc_data, plugin->id(), post_events[j].index, 0);

// Update OSC control client
osc_global_send_note_off(plugin->id(), post_events[j].index);
osc_global_send_note_off(plugin->id(), postEvents[j].index);

// Update Host
callback_action(CALLBACK_NOTE_OFF, plugin->id(), post_events[j].index, 0, 0.0);
callback_action(CALLBACK_NOTE_OFF, plugin->id(), postEvents[j].index, 0, 0.0);

break;

case PostEventCustom:
plugin->run_custom_event(&post_events[j]);
case PluginPostEventCustom:
plugin->run_custom_event(&postEvents[j]);
break;

default:
@@ -172,14 +175,14 @@ void CarlaCheckThread::run()
// Update
for (j=0; j < plugin->param_count(); j++)
{
param_data = plugin->param_data(j);
paramData = plugin->param_data(j);

if (param_data->type == PARAMETER_OUTPUT && (param_data->hints & PARAMETER_IS_AUTOMABLE) > 0)
if (paramData->type == PARAMETER_OUTPUT && (paramData->hints & PARAMETER_IS_AUTOMABLE) > 0)
{
value = plugin->get_parameter_value(j);

if (update_ports_gui)
osc_send_control(osc_data, param_data->rindex, value);
osc_send_control(osc_data, paramData->rindex, value);

osc_global_send_set_parameter_value(plugin->id(), j, value);
}
@@ -237,6 +240,8 @@ void CarlaPluginThread::setOscData(const char* binary, const char* label, const

void CarlaPluginThread::run()
{
qDebug("CarlaPluginThread::run()");

if (m_process == nullptr)
m_process = new QProcess(nullptr);

@@ -281,7 +286,7 @@ void CarlaPluginThread::run()
{
case PLUGIN_THREAD_DSSI_GUI:
case PLUGIN_THREAD_LV2_GUI:
if (m_plugin->update_osc_gui())
if (m_plugin->show_osc_gui())
{
m_process->waitForFinished(-1);



+ 1
- 2
src/carla-backend/carla_threads.h View File

@@ -18,12 +18,11 @@
#ifndef CARLA_THREADS_H
#define CARLA_THREADS_H

#include "carla_includes.h"
#include "carla_backend.h"

#include <QtCore/QThread>

class QProcess;
class CarlaPlugin;

// --------------------------------------------------------------------------------------------------------
// CarlaCheckThread


+ 135
- 181
src/carla-backend/dssi.cpp View File

@@ -22,7 +22,7 @@
class DssiPlugin : public CarlaPlugin
{
public:
DssiPlugin() : CarlaPlugin()
DssiPlugin(unsigned short id) : CarlaPlugin(id)
{
qDebug("DssiPlugin::DssiPlugin()");
m_type = PLUGIN_DSSI;
@@ -193,7 +193,7 @@ public:
{
if (index >= 0)
{
if (carla_jack_on_freewheel())
if (0) //(carla_jack_on_freewheel())
{
if (block) carla_proc_lock();
descriptor->select_program(handle, midiprog.data[index].bank, midiprog.data[index].program);
@@ -248,15 +248,15 @@ public:
void reload()
{
qDebug("DssiPlugin::reload() - start");
short _id = m_id;

// Safely disable plugin for reload
carla_proc_lock();
m_id = -1;
carla_proc_unlock();
const CarlaPluginScopedDisabler m(this);

// Unregister previous jack ports if needed
remove_from_jack(bool(_id >= 0));
if (x_client->isActive())
x_client->deactivate();

// Remove client ports
remove_client_ports();

// Delete old data
delete_buffers();
@@ -285,13 +285,13 @@ public:

if (ains > 0)
{
ain.ports = new jack_port_t*[ains];
ain.ports = new CarlaEngineAudioPort*[ains];
ain.rindexes = new uint32_t[ains];
}

if (aouts > 0)
{
aout.ports = new jack_port_t*[aouts];
aout.ports = new CarlaEngineAudioPort*[aouts];
aout.rindexes = new uint32_t[aouts];
}

@@ -314,27 +314,18 @@ public:

if (LADSPA_IS_PORT_AUDIO(PortType))
{
#ifndef BUILD_BRIDGE
if (carla_options.global_jack_client)
{
strcpy(port_name, m_name);
strcat(port_name, ":");
strncat(port_name, ldescriptor->PortNames[i], port_name_size/2);
}
else
#endif
strncpy(port_name, ldescriptor->PortNames[i], port_name_size);
strncpy(port_name, ldescriptor->PortNames[i], port_name_size);

if (LADSPA_IS_PORT_INPUT(PortType))
{
j = ain.count++;
ain.ports[j] = jack_port_register(jack_client, port_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
ain.ports[j] = (CarlaEngineAudioPort*)x_client->addPort(port_name, CarlaEnginePortTypeAudio, true);
ain.rindexes[j] = i;
}
else if (LADSPA_IS_PORT_OUTPUT(PortType))
{
j = aout.count++;
aout.ports[j] = jack_port_register(jack_client, port_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
aout.ports[j] = (CarlaEngineAudioPort*)x_client->addPort(port_name, CarlaEnginePortTypeAudio, false);
aout.rindexes[j] = i;
needs_cin = true;
}
@@ -541,47 +532,20 @@ public:

if (needs_cin)
{
#ifndef BUILD_BRIDGE
if (carla_options.global_jack_client)
{
strcpy(port_name, m_name);
strcat(port_name, ":control-in");
}
else
#endif
strcpy(port_name, "control-in");

param.port_cin = jack_port_register(jack_client, port_name, JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0);
strcpy(port_name, "control-in");
param.port_cin = (CarlaEngineControlPort*)x_client->addPort(port_name, CarlaEnginePortTypeControl, true);
}

if (needs_cout)
{
#ifndef BUILD_BRIDGE
if (carla_options.global_jack_client)
{
strcpy(port_name, m_name);
strcat(port_name, ":control-out");
}
else
#endif
strcpy(port_name, "control-out");

param.port_cout = jack_port_register(jack_client, port_name, JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0);
strcpy(port_name, "control-out");
param.port_cout = (CarlaEngineControlPort*)x_client->addPort(port_name, CarlaEnginePortTypeControl, false);
}

if (mins == 1)
if (mins > 0)
{
#ifndef BUILD_BRIDGE
if (carla_options.global_jack_client)
{
strcpy(port_name, m_name);
strcat(port_name, ":midi-in");
}
else
#endif
strcpy(port_name, "midi-in");

midi.port_min = jack_port_register(jack_client, port_name, JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0);
strcpy(port_name, "midi-in");
midi.port_min = (CarlaEngineMidiPort*)x_client->addPort(port_name, CarlaEnginePortTypeMIDI, true);
}

ain.count = ains;
@@ -596,7 +560,7 @@ public:
if (midi.port_min > 0 && aout.count > 0)
m_hints |= PLUGIN_IS_SYNTH;

#ifndef BUILD_BRIDGE
#if 0
if (carla_options.use_dssi_chunks && QString(m_filename).endsWith("dssi-vst.so", Qt::CaseInsensitive))
{
if (descriptor->get_custom_data && descriptor->set_custom_data)
@@ -613,19 +577,12 @@ public:
if (aouts >= 2 && aouts%2 == 0)
m_hints |= PLUGIN_CAN_BALANCE;

carla_proc_lock();
m_id = _id;
carla_proc_unlock();

#ifndef BUILD_BRIDGE
if (carla_options.global_jack_client == false)
#endif
jack_activate(jack_client);
x_client->activate();

qDebug("DssiPlugin::reload() - end");
}

virtual void reload_programs(bool init)
void reload_programs(bool init)
{
qDebug("DssiPlugin::reload_programs(%s)", bool2str(init));
uint32_t i, old_count = midiprog.count;
@@ -722,7 +679,7 @@ public:
}
}

virtual void process(jack_nframes_t nframes)
void process(float** ains_buffer, float** aouts_buffer, uint32_t nframes, uint32_t nframesOffset)
{
uint32_t i, k;
unsigned short plugin_id = m_id;
@@ -731,19 +688,6 @@ public:
double ains_peak_tmp[2] = { 0.0 };
double aouts_peak_tmp[2] = { 0.0 };

jack_audio_sample_t* ains_buffer[ain.count];
jack_audio_sample_t* aouts_buffer[aout.count];
void* min_buffer = nullptr;

for (i=0; i < ain.count; i++)
ains_buffer[i] = (jack_audio_sample_t*)jack_port_get_buffer(ain.ports[i], nframes);

for (i=0; i < aout.count; i++)
aouts_buffer[i] = (jack_audio_sample_t*)jack_port_get_buffer(aout.ports[i], nframes);

if (midi.port_min > 0)
min_buffer = jack_port_get_buffer(midi.port_min, nframes);

// --------------------------------------------------------------------------------------------------------
// Input VU

@@ -777,59 +721,53 @@ public:

if (param.port_cin)
{
void* pin_buffer = jack_port_get_buffer(param.port_cin, nframes);
void* cin_buffer = param.port_cin->getBuffer(nframes);

jack_midi_event_t pin_event;
uint32_t n_pin_events = jack_midi_get_event_count(pin_buffer);
const CarlaEngineControlEvent* cin_event;
uint32_t n_cin_events = param.port_cin->getEventCount(cin_buffer);

unsigned char next_bank_id = 0;
uint32_t next_bank_id = 0;
if (midiprog.current > 0 && midiprog.count > 0)
next_bank_id = midiprog.data[midiprog.current].bank;

for (i=0; i < n_pin_events; i++)
for (i=0; i < n_cin_events; i++)
{
if (jack_midi_event_get(&pin_event, pin_buffer, i) != 0)
break;
cin_event = param.port_cin->getEvent(cin_buffer, i);

if (! cin_event)
continue;

jack_midi_data_t status = pin_event.buffer[0];
jack_midi_data_t channel = status & 0x0F;
if (carla_options.proccess_32x && cin_event->time < 32)
break;

// Control change
if (MIDI_IS_STATUS_CONTROL_CHANGE(status))
switch (cin_event->type)
{
case CarlaEngineEventControlChange:
{
jack_midi_data_t control = pin_event.buffer[1];
jack_midi_data_t c_value = pin_event.buffer[2];

// Bank Select
if (MIDI_IS_CONTROL_BANK_SELECT(control))
{
next_bank_id = c_value;
continue;
}

double value;

// Control backend stuff
if (channel == cin_channel)
if (cin_event->channel == cin_channel)
{
if (MIDI_IS_CONTROL_BREATH_CONTROLLER(control) && (m_hints & PLUGIN_CAN_DRYWET) > 0)
if (MIDI_IS_CONTROL_BREATH_CONTROLLER(cin_event->controller) && (m_hints & PLUGIN_CAN_DRYWET) > 0)
{
value = double(c_value)/127;
value = cin_event->value;
set_drywet(value, false, false);
postpone_event(PostEventParameterChange, PARAMETER_DRYWET, value);
postpone_event(PluginPostEventParameterChange, PARAMETER_DRYWET, value);
continue;
}
else if (MIDI_IS_CONTROL_CHANNEL_VOLUME(control) && (m_hints & PLUGIN_CAN_VOLUME) > 0)
else if (MIDI_IS_CONTROL_CHANNEL_VOLUME(cin_event->controller) && (m_hints & PLUGIN_CAN_VOLUME) > 0)
{
value = double(c_value)/100;
value = cin_event->value*127/100;
set_volume(value, false, false);
postpone_event(PostEventParameterChange, PARAMETER_VOLUME, value);
postpone_event(PluginPostEventParameterChange, PARAMETER_VOLUME, value);
continue;
}
else if (MIDI_IS_CONTROL_BALANCE(control) && (m_hints & PLUGIN_CAN_BALANCE) > 0)
else if (MIDI_IS_CONTROL_BALANCE(cin_event->controller) && (m_hints & PLUGIN_CAN_BALANCE) > 0)
{
double left, right;
value = (double(c_value)-63.5)/63.5;
value = cin_event->value/0.5 - 1.0;

if (value < 0)
{
@@ -849,29 +787,8 @@ public:

set_balance_left(left, false, false);
set_balance_right(right, false, false);
postpone_event(PostEventParameterChange, PARAMETER_BALANCE_LEFT, left);
postpone_event(PostEventParameterChange, PARAMETER_BALANCE_RIGHT, right);
continue;
}
else if (control == MIDI_CONTROL_ALL_SOUND_OFF)
{
if (midi.port_min)
send_midi_all_notes_off();

if (m_active && m_active_before)
{
if (ldescriptor->deactivate)
ldescriptor->deactivate(handle);

if (ldescriptor->activate)
ldescriptor->activate(handle);
}
continue;
}
else if (control == MIDI_CONTROL_ALL_NOTES_OFF)
{
if (midi.port_min)
send_midi_all_notes_off();
postpone_event(PluginPostEventParameterChange, PARAMETER_BALANCE_LEFT, left);
postpone_event(PluginPostEventParameterChange, PARAMETER_BALANCE_RIGHT, right);
continue;
}
}
@@ -879,40 +796,76 @@ public:
// Control plugin parameters
for (k=0; k < param.count; k++)
{
if (param.data[k].midi_channel == channel && param.data[k].midi_cc == control && param.data[k].type == PARAMETER_INPUT && (param.data[k].hints & PARAMETER_IS_AUTOMABLE) > 0)
if (param.data[k].midi_channel == cin_event->channel && param.data[k].midi_cc == cin_event->controller && param.data[k].type == PARAMETER_INPUT && (param.data[k].hints & PARAMETER_IS_AUTOMABLE) > 0)
{
if (param.data[k].hints & PARAMETER_IS_BOOLEAN)
{
value = c_value <= 63 ? param.ranges[k].min : param.ranges[k].max;
value = cin_event->value < 0.5 ? param.ranges[k].min : param.ranges[k].max;
}
else
{
value = (double(c_value) / 127 * (param.ranges[k].max - param.ranges[k].min)) + param.ranges[k].min;
value = cin_event->value * (param.ranges[k].max - param.ranges[k].min) + param.ranges[k].min;

if (param.data[k].hints & PARAMETER_IS_INTEGER)
value = rint(value);
}

set_parameter_value(k, value, false, false, false);
postpone_event(PostEventParameterChange, k, value);
postpone_event(PluginPostEventParameterChange, k, value);
}
}

break;
}

case CarlaEngineEventMidiBankChange:
{
next_bank_id = cin_event->value;
break;
}
// Program change
else if (MIDI_IS_STATUS_PROGRAM_CHANGE(status))
case CarlaEngineEventMidiProgramChange:
{
uint32_t mbank_id = next_bank_id;
uint32_t mprog_id = pin_event.buffer[1];
uint32_t mprog_id = cin_event->value;

for (k=0; k < midiprog.count; k++)
{
if (midiprog.data[k].bank == mbank_id && midiprog.data[k].program == mprog_id)
{
set_midi_program(k, false, false, false, false);
postpone_event(PostEventMidiProgramChange, k, 0.0);
postpone_event(PluginPostEventMidiProgramChange, k, 0.0);
break;
}
}

break;
}

case CarlaEngineEventAllSoundOff:
if (cin_event->channel == cin_channel)
{
if (midi.port_min)
send_midi_all_notes_off();

if (m_active && m_active_before)
{
if (ldescriptor->deactivate)
ldescriptor->deactivate(handle);

if (ldescriptor->activate)
ldescriptor->activate(handle);
}
}
break;

case CarlaEngineEventAllNotesOff:
if (cin_event->channel == cin_channel)
{
if (midi.port_min)
send_midi_all_notes_off();
}
break;
}
}
} // End of Parameters Input
@@ -928,17 +881,17 @@ public:

for (i=0; i < MAX_MIDI_EVENTS && midi_event_count < MAX_MIDI_EVENTS; i++)
{
if (ext_midi_notes[i].valid)
if (extMidiNotes[i].valid)
{
snd_seq_event_t* midi_event = &midi_events[midi_event_count];
memset(midi_event, 0, sizeof(snd_seq_event_t));

midi_event->type = ext_midi_notes[i].onoff ? SND_SEQ_EVENT_NOTEON : SND_SEQ_EVENT_NOTEOFF;
midi_event->type = extMidiNotes[i].onoff ? SND_SEQ_EVENT_NOTEON : SND_SEQ_EVENT_NOTEOFF;
midi_event->data.note.channel = 0;
midi_event->data.note.note = ext_midi_notes[i].note;
midi_event->data.note.velocity = ext_midi_notes[i].velo;
midi_event->data.note.note = extMidiNotes[i].note;
midi_event->data.note.velocity = extMidiNotes[i].velo;

ext_midi_notes[i].valid = false;
extMidiNotes[i].valid = false;
midi_event_count += 1;
}
else
@@ -956,50 +909,57 @@ public:

if (midi.port_min)
{
jack_midi_event_t min_event;
uint32_t n_min_events = jack_midi_get_event_count(min_buffer);
void* min_buffer = midi.port_min->getBuffer(nframes);

const CarlaEngineMidiEvent* min_event;
uint32_t n_min_events = midi.port_min->getEventCount(min_buffer);

for (k=0; k < n_min_events && midi_event_count < MAX_MIDI_EVENTS; k++)
for (i=0; i < n_min_events && midi_event_count < MAX_MIDI_EVENTS; i++)
{
if (jack_midi_event_get(&min_event, min_buffer, k) != 0)
min_event = midi.port_min->getEvent(min_buffer, i);

if (! min_event)
break;

if (carla_options.proccess_32x && min_event->time < 32)
break;

jack_midi_data_t status = min_event.buffer[0];
jack_midi_data_t channel = status & 0x0F;
uint8_t status = min_event->data[0];
uint8_t channel = status & 0x0F;

// Fix bad note-off
if (MIDI_IS_STATUS_NOTE_ON(status) && min_event.buffer[2] == 0)
if (MIDI_IS_STATUS_NOTE_ON(status) && min_event->data[2] == 0)
status -= 0x10;

snd_seq_event_t* midi_event = &midi_events[midi_event_count];
memset(midi_event, 0, sizeof(snd_seq_event_t));

midi_event->time.tick = min_event.time;
midi_event->time.tick = min_event->time - nframesOffset;

if (MIDI_IS_STATUS_NOTE_OFF(status))
{
jack_midi_data_t note = min_event.buffer[1];
uint8_t note = min_event->data[1];

midi_event->type = SND_SEQ_EVENT_NOTEOFF;
midi_event->data.note.channel = channel;
midi_event->data.note.note = note;
postpone_event(PostEventNoteOff, note, 0.0);
postpone_event(PluginPostEventNoteOff, note, 0.0);
}
else if (MIDI_IS_STATUS_NOTE_ON(status))
{
jack_midi_data_t note = min_event.buffer[1];
jack_midi_data_t velo = min_event.buffer[2];
uint8_t note = min_event->data[1];
uint8_t velo = min_event->data[2];

midi_event->type = SND_SEQ_EVENT_NOTEON;
midi_event->data.note.channel = channel;
midi_event->data.note.note = note;
midi_event->data.note.velocity = velo;
postpone_event(PostEventNoteOn, note, velo);
postpone_event(PluginPostEventNoteOn, note, velo);
}
else if (MIDI_IS_STATUS_POLYPHONIC_AFTERTOUCH(status))
{
jack_midi_data_t note = min_event.buffer[1];
jack_midi_data_t pressure = min_event.buffer[2];
uint8_t note = min_event->data[1];
uint8_t pressure = min_event->data[2];

midi_event->type = SND_SEQ_EVENT_KEYPRESS;
midi_event->data.note.channel = channel;
@@ -1008,7 +968,7 @@ public:
}
else if (MIDI_IS_STATUS_AFTERTOUCH(status))
{
jack_midi_data_t pressure = min_event.buffer[1];
uint8_t pressure = min_event->data[1];

midi_event->type = SND_SEQ_EVENT_CHANPRESS;
midi_event->data.control.channel = channel;
@@ -1016,8 +976,8 @@ public:
}
else if (MIDI_IS_STATUS_PITCH_WHEEL_CONTROL(status))
{
jack_midi_data_t lsb = min_event.buffer[1];
jack_midi_data_t msb = min_event.buffer[2];
uint8_t lsb = min_event->data[1];
uint8_t msb = min_event->data[2];

midi_event->type = SND_SEQ_EVENT_PITCHBEND;
midi_event->data.control.channel = channel;
@@ -1097,7 +1057,7 @@ public:
bool do_balance = (m_hints & PLUGIN_CAN_BALANCE) > 0 && (x_bal_left != -1.0 || x_bal_right != 1.0);

double bal_rangeL, bal_rangeR;
jack_audio_sample_t old_bal_left[do_balance ? nframes : 0];
float old_bal_left[do_balance ? nframes : 0];

for (i=0; i < aout.count; i++)
{
@@ -1123,7 +1083,7 @@ public:
if (do_balance)
{
if (i%2 == 0)
memcpy(&old_bal_left, aouts_buffer[i], sizeof(jack_audio_sample_t)*nframes);
memcpy(&old_bal_left, aouts_buffer[i], sizeof(float)*nframes);

bal_rangeL = (x_bal_left+1.0)/2;
bal_rangeR = (x_bal_right+1.0)/2;
@@ -1157,7 +1117,7 @@ public:
{
// disable any output sound if not active
for (i=0; i < aout.count; i++)
memset(aouts_buffer[i], 0.0f, sizeof(jack_audio_sample_t)*nframes);
memset(aouts_buffer[i], 0.0f, sizeof(float)*nframes);

aouts_peak_tmp[0] = 0.0;
aouts_peak_tmp[1] = 0.0;
@@ -1171,21 +1131,15 @@ public:

if (param.port_cout)
{
void* cout_buffer = jack_port_get_buffer(param.port_cout, nframes);
jack_midi_clear_buffer(cout_buffer);

void* cout_buffer = param.port_cout->getBuffer(nframes);
double value;

for (k=0; k < param.count; k++)
{
if (param.data[k].type == PARAMETER_OUTPUT && param.data[k].midi_cc > 0)
{
value = (param_buffers[k] - param.ranges[k].min) / (param.ranges[k].max - param.ranges[k].min) * 127;

jack_midi_data_t* event_buffer = jack_midi_event_reserve(cout_buffer, 0, 3);
event_buffer[0] = MIDI_STATUS_CONTROL_CHANGE + param.data[k].midi_channel;
event_buffer[1] = param.data[k].midi_cc;
event_buffer[2] = value;
value = (param_buffers[k] - param.ranges[k].min) / (param.ranges[k].max - param.ranges[k].min);
param.port_cout->writeEvent(cout_buffer, param.data[k].midi_channel, param.data[k].midi_cc, value);
}
}
} // End of Control Output
@@ -1203,7 +1157,7 @@ public:
m_active_before = m_active;
}

virtual void delete_buffers()
void delete_buffers()
{
qDebug("DssiPlugin::delete_buffers() - start");

@@ -1239,8 +1193,9 @@ public:
{
m_filename = strdup(filename);
m_name = get_unique_name(ldescriptor->Name);
x_client = new CarlaEngineClient(this);

if (carla_jack_register_plugin(this, &jack_client))
if (x_client->isOk())
{
#ifndef BUILD_BRIDGE
if (gui_filename)
@@ -1257,7 +1212,7 @@ public:
return true;
}
else
set_last_error("Failed to register plugin in JACK");
set_last_error("Failed to register plugin client");
}
else
set_last_error("Plugin failed to initialize");
@@ -1291,17 +1246,16 @@ short add_plugin_dssi(const char* filename, const char* label, const void* extra

if (id >= 0)
{
DssiPlugin* plugin = new DssiPlugin;
DssiPlugin* plugin = new DssiPlugin(id);

if (plugin->init(filename, label, (const char*)extra_stuff))
{
plugin->reload();
plugin->set_id(id);

unique_names[id] = plugin->name();
CarlaPlugins[id] = plugin;

plugin->osc_global_register_new();
plugin->osc_register_new();
}
else
{


+ 22
- 11
src/carla-backend/ladspa.cpp View File

@@ -20,6 +20,8 @@
#include "ladspa/ladspa.h"
#include "ladspa_rdf.h"

CARLA_BACKEND_START_NAMESPACE

bool is_rdf_port_good(int Type1, int Type2)
{
if (LADSPA_IS_PORT_INPUT(Type1) && ! LADSPA_IS_PORT_INPUT(Type2))
@@ -64,7 +66,7 @@ bool is_ladspa_rdf_descriptor_valid(const LADSPA_RDF_Descriptor* rdf_descriptor,
class LadspaPlugin : public CarlaPlugin
{
public:
LadspaPlugin() : CarlaPlugin()
LadspaPlugin(unsigned short id) : CarlaPlugin(id)
{
qDebug("LadspaPlugin::LadspaPlugin()");
m_type = PLUGIN_LADSPA;
@@ -264,6 +266,7 @@ public:
CarlaPlugin::set_parameter_value(param_id, value, gui_send, osc_send, callback_send);
}

#if 0
void reload()
{
qDebug("LadspaPlugin::reload() - start");
@@ -345,13 +348,13 @@ public:
if (LADSPA_IS_PORT_INPUT(PortType))
{
j = ain.count++;
ain.ports[j] = jack_port_register(jack_client, port_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
ain.ports[j] = jack_port_register(x_client, port_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
ain.rindexes[j] = i;
}
else if (LADSPA_IS_PORT_OUTPUT(PortType))
{
j = aout.count++;
aout.ports[j] = jack_port_register(jack_client, port_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
aout.ports[j] = jack_port_register(x_client, port_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
aout.rindexes[j] = i;
needs_cin = true;
}
@@ -563,7 +566,7 @@ public:
#endif
strcpy(port_name, "control-in");

param.port_cin = jack_port_register(jack_client, port_name, JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0);
param.port_cin = jack_port_register(x_client, port_name, JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0);
}

if (needs_cout)
@@ -578,7 +581,7 @@ public:
#endif
strcpy(port_name, "control-out");

param.port_cout = jack_port_register(jack_client, port_name, JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0);
param.port_cout = jack_port_register(x_client, port_name, JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0);
}

ain.count = ains;
@@ -609,7 +612,7 @@ public:
qDebug("LadspaPlugin::reload() - end");
}

void process(jack_nframes_t nframes)
void process(uint32_t nframes, uint32_t nframesOffset)
{
uint32_t i, k;
unsigned short plugin_id = m_id;
@@ -926,6 +929,7 @@ public:

m_active_before = m_active;
}
#endif

void delete_buffers()
{
@@ -970,12 +974,14 @@ public:
else
m_name = get_unique_name(descriptor->Name);

if (carla_jack_register_plugin(this, &jack_client))
x_client = new CarlaEngineClient(this);

if (x_client->isOk())
{
return true;
}
else
set_last_error("Failed to register plugin in JACK");
set_last_error("Failed to register plugin client");
}
else
set_last_error("Plugin failed to initialize");
@@ -1000,6 +1006,12 @@ private:
float* param_buffers;
};

CARLA_BACKEND_END_NAMESPACE

#ifndef CARLA_BACKEND_NO_NAMESPACE
typedef CarlaBackend::LadspaPlugin LadspaPlugin;
#endif

short add_plugin_ladspa(const char* filename, const char* label, const void* extra_stuff)
{
qDebug("add_plugin_ladspa(%s, %s, %p)", filename, label, extra_stuff);
@@ -1008,17 +1020,16 @@ short add_plugin_ladspa(const char* filename, const char* label, const void* ext

if (id >= 0)
{
LadspaPlugin* plugin = new LadspaPlugin;
LadspaPlugin* plugin = new LadspaPlugin(id);

if (plugin->init(filename, label, (LADSPA_RDF_Descriptor*)extra_stuff))
{
plugin->reload();
plugin->set_id(id);

unique_names[id] = plugin->name();
CarlaPlugins[id] = plugin;

plugin->osc_global_register_new();
plugin->osc_register_new();
}
else
{


+ 15
- 13
src/carla-backend/lv2.cpp View File

@@ -129,7 +129,7 @@ const char* lv2bridge2str(LV2_Property type)
class Lv2Plugin : public CarlaPlugin
{
public:
Lv2Plugin() : CarlaPlugin()
Lv2Plugin(unsigned short id) : CarlaPlugin(id)
{
qDebug("Lv2Plugin::Lv2Plugin()");
m_type = PLUGIN_LV2;
@@ -658,7 +658,7 @@ public:
{
if (ext.programs && index >= 0)
{
if (carla_jack_on_freewheel())
if (0) //carla_jack_on_freewheel())
{
if (block) carla_proc_lock();
ext.programs->select_program(handle, midiprog.data[index].bank, midiprog.data[index].program);
@@ -803,6 +803,7 @@ public:
}
}

#if 0
void reload()
{
qDebug("Lv2Plugin::reload() - start");
@@ -1339,7 +1340,7 @@ public:
}

// TODO - apply same to others (reload_programs() after hints)
reload_programs(true);
//reload_programs(true);

//if (ext.dynparam)
// ext.dynparam->host_attach(handle, &dynparam_host, this);
@@ -1349,7 +1350,7 @@ public:
carla_proc_unlock();

#ifndef BUILD_BRIDGE
if (carla_options.global_jack_client == false)
if (! carla_options.global_jack_client)
#endif
jack_activate(jack_client);

@@ -1459,7 +1460,7 @@ public:
ext.state->save(handle, carla_lv2_state_store, this, LV2_STATE_IS_POD, features);
}

void process(jack_nframes_t nframes)
void process(jack_nframes_t nframes, jack_nframes_t nframesOffset)
{
uint32_t i, k;
unsigned short plugin_id = m_id;
@@ -2109,7 +2110,7 @@ public:
}

// TODO, remove = true
void remove_from_jack(bool deactivate = true)
void remove_from_jack(bool deactivate)
{
qDebug("Lv2Plugin::remove_from_jack() - start");

@@ -2129,6 +2130,7 @@ public:

qDebug("Lv2Plugin::remove_from_jack() - end");
}
#endif

void run_custom_event(PluginPostEvent* event)
{
@@ -2537,9 +2539,10 @@ public:
if (handle)
{
m_filename = strdup(bundle);
m_name = get_unique_name(rdf_descriptor->Name);
m_name = get_unique_name(rdf_descriptor->Name);
x_client = new CarlaEngineClient(this);

if (carla_jack_register_plugin(this, &jack_client))
if (x_client->isOk())
{
// ----------------- GUI Stuff -------------------------------------------------------

@@ -2773,7 +2776,7 @@ public:
return true;
}
else
set_last_error("Failed to register plugin in JACK");
set_last_error("Failed to register plugin client");
}
else
set_last_error("Plugin failed to initialize");
@@ -3334,7 +3337,7 @@ public:
if (buffer_size == sizeof(float))
{
float value = *(float*)buffer;
plugin->set_parameter_value_rindex(port_index, value, false, true, true);
plugin->set_parameter_value_by_rindex(port_index, value, false, true, true);
}
}
else if (format == CARLA_URI_MAP_ID_MIDI_EVENT)
@@ -3430,17 +3433,16 @@ short add_plugin_lv2(const char* filename, const char* label)

if (id >= 0)
{
Lv2Plugin* plugin = new Lv2Plugin;
Lv2Plugin* plugin = new Lv2Plugin(id);

if (plugin->init(filename, label))
{
plugin->reload();
plugin->set_id(id);

unique_names[id] = plugin->name();
CarlaPlugins[id] = plugin;

plugin->osc_global_register_new();
plugin->osc_register_new();
}
else
{


+ 13
- 13
src/carla-backend/qtcreator/carla-backend.pro View File

@@ -2,16 +2,18 @@

QT = core gui

CONFIG += warn_on qt debug shared dll plugin link_pkgconfig
CONFIG = debug link_pkgconfig qt warn_on
PKGCONFIG = jack liblo fluidsynth

TEMPLATE = app #lib
TARGET = carla_backend
TEMPLATE = app
VERSION = 0.5.0

SOURCES = \
../carla_backend.cpp \
../carla_engine_jack.cpp \
../carla_engine_rtaudio.cpp \
../carla_bridge.cpp \
../carla_jack.cpp \
../carla_osc.cpp \
../carla_shared.cpp \
../carla_threads.cpp \
@@ -24,26 +26,24 @@ SOURCES = \

HEADERS = \
../carla_backend.h \
../carla_jack.h \
../carla_engine.h \
../carla_midi.h \
../carla_osc.h \
../carla_plugin.h \
../carla_shared.h \
../carla_threads.h \
../ladspa_rdf.h \
../lv2_rdf.h \
../../carla-includes/carla_includes.h \
../../carla-includes/carla_osc_includes.h
../../carla-includes/carla_lib_includes.h \
../../carla-includes/carla_osc_includes.h \
../../carla-includes/carla_vst_includes.h \
../../carla-includes/ladspa_rdf.h \
../../carla-includes/lv2_rdf.h

INCLUDEPATH = .. \
../../carla-includes \
../../carla-includes/vst
# ../../carla-includes/vestige

TARGET = carla_backend

#DEFINES = VESTIGE_HEADER

LIBS = ../../carla-lilv/carla_lilv.a
DEFINES = QTCREATOR_TEST CARLA_ENGINE_JACK
LIBS = ../../carla-lilv/carla_lilv.a -lrtaudio

QMAKE_CXXFLAGS *= -std=c++0x

+ 13
- 13
src/carla-backend/sf2.cpp View File

@@ -30,7 +30,7 @@
class Sf2Plugin : public CarlaPlugin
{
public:
Sf2Plugin() : CarlaPlugin()
Sf2Plugin(unsigned short id) : CarlaPlugin(id)
{
qDebug("Sf2Plugin::Sf2Plugin()");
m_type = PLUGIN_SF2;
@@ -275,7 +275,7 @@ public:
{
if (index >= 0)
{
if (carla_jack_on_freewheel())
if (0) //carla_jack_on_freewheel())
{
if (block) carla_proc_lock();
fluid_synth_program_select(f_synth, 0, f_id, midiprog.data[index].bank, midiprog.data[index].program);
@@ -306,6 +306,7 @@ public:
CarlaPlugin::set_midi_program(index, gui_send, osc_send, callback_send, block);
}

#if 0
void reload()
{
qDebug("Sf2AudioPlugin::reload() - start");
@@ -739,7 +740,7 @@ public:
}
}

virtual void process(jack_nframes_t nframes)
virtual void process(jack_nframes_t nframes, jack_nframes_t nframesOffset)
{
uint32_t i, k;
unsigned short plugin_id = m_id;
@@ -1121,6 +1122,7 @@ public:

qDebug("Sf2Plugin::delete_buffers() - end");
}
#endif

bool init(const char* filename, const char* label)
{
@@ -1129,13 +1131,14 @@ public:
if (f_id >= 0)
{
m_filename = strdup(filename);
m_label = strdup(label);
m_name = get_unique_name(label);
m_label = strdup(label);
m_name = get_unique_name(label);
x_client = new CarlaEngineClient(this);

if (carla_jack_register_plugin(this, &jack_client))
if (x_client->isOk())
return true;
else
set_last_error("Failed to register plugin in JACK");
set_last_error("Failed to register plugin client");
}
else
set_last_error("Failed to load SoundFont file");
@@ -1180,19 +1183,16 @@ short add_plugin_sf2(const char* filename, const char* label)
{
if (fluid_is_soundfont(filename))
{
Sf2Plugin* plugin = new Sf2Plugin;
Sf2Plugin* plugin = new Sf2Plugin(id);

if (plugin->init(filename, label))
{
plugin->reload();
plugin->set_id(id);

unique_names[id] = plugin->name();
CarlaPlugins[id] = plugin;

#ifndef BUILD_BRIDGE
plugin->osc_global_register_new();
#endif
plugin->osc_register_new();
}
else
{


+ 17
- 32
src/carla-backend/vst.cpp View File

@@ -27,7 +27,7 @@
class VstPlugin : public CarlaPlugin
{
public:
VstPlugin() : CarlaPlugin()
VstPlugin(unsigned short id) : CarlaPlugin(id)
{
qDebug("VstPlugin::VstPlugin()");
m_type = PLUGIN_VST;
@@ -181,7 +181,7 @@ public:
{
if (index >= 0)
{
if (carla_jack_on_freewheel())
if (0) //carla_jack_on_freewheel())
{
if (block) carla_proc_lock();
effect->dispatcher(effect, effSetProgram, 0, index, nullptr, 0.0f);
@@ -274,6 +274,7 @@ public:
effect->dispatcher(effect, effEditIdle, 0, 0, nullptr, 0.0f);
}

#if 0
void reload()
{
qDebug("VstPlugin::reload() - start");
@@ -630,7 +631,7 @@ public:
}
}

void process(jack_nframes_t nframes)
void process(jack_nframes_t nframes, jack_nframes_t nframesOffset)
{
uint32_t i, k;
unsigned short plugin_id = m_id;
@@ -1117,6 +1118,7 @@ public:
effect->dispatcher(effect, effStartProcess, 0, 0, nullptr, 0.0f);
}
}
#endif

bool init(const char* filename, const char* label)
{
@@ -1143,6 +1145,8 @@ public:
else
m_name = get_unique_name(label);

x_client = new CarlaEngineClient(this);

// Init plugin
effect->dispatcher(effect, effOpen, 0, 0, nullptr, 0.0f);
#if ! VST_FORCE_DEPRECATED
@@ -1153,7 +1157,7 @@ public:
effect->dispatcher(effect, effSetProcessPrecision, 0, kVstProcessPrecision32, nullptr, 0.0f);
effect->user = this;

if (carla_jack_register_plugin(this, &jack_client))
if (x_client->isOk())
{
// GUI Stuff
if (effect->flags & effFlagsHasEditor)
@@ -1162,7 +1166,7 @@ public:
return true;
}
else
set_last_error("Failed to register plugin in JACK");
set_last_error("Failed to register plugin client");
}
else
set_last_error("Plugin failed to initialize");
@@ -1197,10 +1201,10 @@ public:
case audioMasterAutomate:
if (self)
{
if (carla_jack_on_audio_thread())
if (1) //carla_jack_on_audio_thread())
{
self->set_parameter_value(index, opt, false, false, false);
self->postpone_event(PostEventParameterChange, index, opt);
//self->postpone_event(PostEventParameterChange, index, opt);
}
else
self->set_parameter_value(index, opt, false, true, true);
@@ -1255,6 +1259,7 @@ public:
break;
#endif

#if 0
case audioMasterGetTime:
{
static VstTimeInfo_R timeInfo;
@@ -1348,6 +1353,7 @@ public:
break;
#endif
#endif
#endif

#if 0
case audioMasterIOChanged:
@@ -1423,6 +1429,7 @@ public:
break;
#endif

#if 0
case audioMasterGetCurrentProcessLevel:
if (carla_jack_on_audio_thread())
{
@@ -1431,6 +1438,7 @@ public:
return kVstProcessLevelRealtime;
}
return kVstProcessLevelUser;
#endif

#if 0
case audioMasterGetAutomationState:
@@ -1615,17 +1623,16 @@ short add_plugin_vst(const char* filename, const char* label)

if (id >= 0)
{
VstPlugin* plugin = new VstPlugin;
VstPlugin* plugin = new VstPlugin(id);

if (plugin->init(filename, label))
{
plugin->reload();
plugin->set_id(id);

unique_names[id] = plugin->name();
CarlaPlugins[id] = plugin;

plugin->osc_global_register_new();
plugin->osc_register_new();
}
else
{
@@ -1638,25 +1645,3 @@ short add_plugin_vst(const char* filename, const char* label)

return id;
}

#if 1
#include <QtGui/QApplication>

int main(int argc, char* argv[])
{
QApplication app(argc, argv);
QDialog gui;
short id = add_plugin_vst("/usr/lib/vst/peq-2a.so", "ole");
if (id >= 0)
{
CarlaPlugins[id]->set_gui_data(0, &gui); //(void*)gui.winId()
show_gui(id, true);
gui.show();
app.exec();
remove_plugin(id);
}
else
qCritical("failed: %s", get_last_error());
return 0;
}
#endif

+ 15
- 14
src/carla-bridge/Makefile View File

@@ -12,7 +12,7 @@ WINECXX ?= wineg++
BUILD_CFLAGS = -O2 -ffast-math -fomit-frame-pointer -mtune=generic -msse -std=c99 -Wall -I. -I../carla -I../carla-includes $(CFLAGS)

BUILD_FLAGS = -O2 -ffast-math -fomit-frame-pointer -mtune=generic -msse -std=c++0x -Wall $(CXXFLAGS)
BUILD_FLAGS += -I. -I../carla -I../carla-includes $(shell pkg-config --cflags liblo QtCore)
BUILD_FLAGS += -I. -I../carla-backend -I../carla-includes $(shell pkg-config --cflags liblo QtCore)
BUILD_FLAGS += -DBUILD_BRIDGE -DNDEBUG -DQT_NO_DEBUG -DQT_NO_DEBUG_STREAM -DQT_NO_DEBUG_OUTPUT
BUILD_FLAGS += -DVESTIGE_HEADER -I../carla-includes/vestige # Comment this line to not use vestige header

@@ -22,39 +22,40 @@ LINK_FLAGS = $(shell pkg-config --libs liblo QtCore)

# --------------------------------------------------------------

BUILD_PLUGIN_FLAGS = $(shell pkg-config --cflags QtGui) $(BUILD_FLAGS)
LINK_PLUGIN_FLAGS = $(shell pkg-config --libs QtGui) $(LINK_FLAGS)
BUILD_PLUGIN_FLAGS = $(BUILD_FLAGS) $(shell pkg-config --cflags QtGui)
LINK_PLUGIN_FLAGS = $(LINK_FLAGS) $(shell pkg-config --libs QtGui)

UNIX_BUILD_FLAGS = $(BUILD_PLUGIN_FLAGS)
UNIX_32BIT_FLAGS = -L/usr/lib32 -L/usr/lib/i386-linux-gnu $(32BIT_FLAGS)
UNIX_64BIT_FLAGS = -L/usr/lib64 -L/usr/lib/x86_64-linux-gnu $(64BIT_FLAGS)
UNIX_LINK_FLAGS = -ldl $(LINK_PLUGIN_FLAGS)
UNIX_32BIT_FLAGS = $(32BIT_FLAGS) -L/usr/lib32 -L/usr/lib/i386-linux-gnu
UNIX_64BIT_FLAGS = $(64BIT_FLAGS) -L/usr/lib64 -L/usr/lib/x86_64-linux-gnu
UNIX_LINK_FLAGS = $(LINK_PLUGIN_FLAGS) -ldl

WIN_BUILD_FLAGS = $(BUILD_PLUGIN_FLAGS)
WIN_32BIT_FLAGS = $(32BIT_FLAGS)
WIN_64BIT_FLAGS = $(64BIT_FLAGS)
WIN_LINK_FLAGS = -static $(LINK_PLUGIN_FLAGS)
WIN_LINK_FLAGS = $(LINK_PLUGIN_FLAGS) -static

WINE_BUILD_FLAGS = $(BUILD_PLUGIN_FLAGS) # -fpermissive
WINE_32BIT_FLAGS = -L/usr/lib32/wine -L/usr/lib/i386-linux-gnu/wine $(32BIT_FLAGS)
WINE_64BIT_FLAGS = -L/usr/lib64/wine -L/usr/lib/x86_64-linux-gnu/wine $(64BIT_FLAGS)
WINE_LINK_FLAGS = -ldl $(LINK_PLUGIN_FLAGS)
WINE_32BIT_FLAGS = $(32BIT_FLAGS) -L/usr/lib32/wine -L/usr/lib/i386-linux-gnu/wine
WINE_64BIT_FLAGS = $(64BIT_FLAGS) -L/usr/lib64/wine -L/usr/lib/x86_64-linux-gnu/wine
WINE_LINK_FLAGS = $(LINK_PLUGIN_FLAGS) -ldl

# --------------------------------------------------------------

BUILD_UI_FLAGS = $(BUILD_FLAGS) -DBUILD_BRIDGE_UI
LINK_UI_FLAGS = $(LINK_FLAGS)

BUILD_UI_LV2_GTK2_FLAGS = $(BUILD_UI_FLAGS) -DBRIDGE_LV2_GTK2 $(shell pkg-config --cflags gtk+-2.0)
LINK_UI_LV2_GTK2_FLAGS = $(LINK_FLAGS) $(shell pkg-config --libs gtk+-2.0)
LINK_UI_LV2_GTK2_FLAGS = $(LINK_UI_FLAGS) $(shell pkg-config --libs gtk+-2.0)

BUILD_UI_LV2_QT4_FLAGS = $(BUILD_UI_FLAGS) -DBRIDGE_LV2_QT4 $(shell pkg-config --cflags QtGui)
LINK_UI_LV2_QT4_FLAGS = $(LINK_FLAGS) $(shell pkg-config --libs QtGui)
LINK_UI_LV2_QT4_FLAGS = $(LINK_UI_FLAGS) $(shell pkg-config --libs QtGui)

BUILD_UI_LV2_X11_FLAGS = $(BUILD_UI_FLAGS) -DBRIDGE_LV2_X11 $(shell pkg-config --cflags QtGui)
LINK_UI_LV2_X11_FLAGS = $(LINK_FLAGS) $(shell pkg-config --libs QtGui)
LINK_UI_LV2_X11_FLAGS = $(LINK_UI_FLAGS) $(shell pkg-config --libs QtGui)

BUILD_UI_VST_X11_FLAGS = $(BUILD_UI_FLAGS) -DBRIDGE_VST_X11 $(shell pkg-config --cflags QtGui)
LINK_UI_VST_X11_FLAGS = $(LINK_FLAGS) $(shell pkg-config --libs QtGui)
LINK_UI_VST_X11_FLAGS = $(LINK_UI_FLAGS) $(shell pkg-config --libs QtGui)

# --------------------------------------------------------------



+ 8
- 8
src/carla-discovery/Makefile View File

@@ -8,7 +8,7 @@ CXX ?= g++
WINECXX ?= wineg++

BUILD_FLAGS = -O2 -ffast-math -fomit-frame-pointer -mtune=generic -msse -std=c++0x -Wall $(CXXFLAGS)
BUILD_FLAGS += -I../carla-includes $(shell pkg-config --cflags QtCore)
BUILD_FLAGS += -I../carla-backend -I../carla-includes $(shell pkg-config --cflags QtCore)
BUILD_FLAGS += -DNDEBUG -DQT_NO_DEBUG -DQT_NO_DEBUG_STREAM -DQT_NO_DEBUG_OUTPUT
BUILD_FLAGS += -DVESTIGE_HEADER -I../carla-includes/vestige # Comment this line to not use vestige header

@@ -22,19 +22,19 @@ LINK_FLAGS += $(shell pkg-config --libs fluidsynth)
endif

UNIX_BUILD_FLAGS = $(BUILD_FLAGS)
UNIX_32BIT_FLAGS = -L/usr/lib32 -L/usr/lib/i386-linux-gnu $(32BIT_FLAGS)
UNIX_64BIT_FLAGS = -L/usr/lib64 -L/usr/lib/x86_64-linux-gnu $(64BIT_FLAGS)
UNIX_LINK_FLAGS = -ldl $(LINK_FLAGS)
UNIX_32BIT_FLAGS = $(32BIT_FLAGS) -L/usr/lib32 -L/usr/lib/i386-linux-gnu
UNIX_64BIT_FLAGS = $(64BIT_FLAGS) -L/usr/lib64 -L/usr/lib/x86_64-linux-gnu
UNIX_LINK_FLAGS = $(LINK_FLAGS) -ldl

WIN_BUILD_FLAGS = $(BUILD_FLAGS)
WIN_32BIT_FLAGS = $(32BIT_FLAGS)
WIN_64BIT_FLAGS = $(64BIT_FLAGS)
WIN_LINK_FLAGS = -static $(LINK_FLAGS)
WIN_LINK_FLAGS = $(LINK_FLAGS) -static

WINE_BUILD_FLAGS = $(BUILD_FLAGS) # -fpermissive
WINE_32BIT_FLAGS = -L/usr/lib32/wine -L/usr/lib/i386-linux-gnu/wine $(32BIT_FLAGS)
WINE_64BIT_FLAGS = -L/usr/lib64/wine -L/usr/lib/x86_64-linux-gnu/wine $(64BIT_FLAGS)
WINE_LINK_FLAGS = -ldl $(LINK_FLAGS)
WINE_32BIT_FLAGS = $(32BIT_FLAGS) -L/usr/lib32/wine -L/usr/lib/i386-linux-gnu/wine
WINE_64BIT_FLAGS = $(64BIT_FLAGS) -L/usr/lib64/wine -L/usr/lib/x86_64-linux-gnu/wine
WINE_LINK_FLAGS = $(LINK_FLAGS) -ldl

# --------------------------------------------------------------



+ 1
- 1
src/carla-discovery/carla-discovery.cpp View File

@@ -34,7 +34,7 @@
#endif

#define CARLA_NO_EXPORTS
#include "../carla/carla_backend.h"
#include "carla_backend.h"

#define DISCOVERY_OUT(x, y) std::cout << "\ncarla-discovery::" << x << "::" << y << std::endl;



+ 4
- 2
src/carla-includes/carla_includes.h View File

@@ -41,12 +41,14 @@
# define carla_sleep(t) Sleep(t * 1000)
# define carla_msleep(t) Sleep(t)
# define carla_usleep(t) Sleep(t / 1000)
# define carla_setenv(key, value) SetEnvironmentVariableA(key, value)
#else
# include <dlfcn.h>
# include <unistd.h>
# define carla_sleep(t) sleep(t)
# define carla_msleep(t) usleep(t * 1000)
# define carla_usleep(t) usleep(t)
# define carla_setenv(key, value) setenv(key, value, 1)
# ifndef __cdecl
# define __cdecl
# endif
@@ -77,7 +79,7 @@
# define BINARY_NATIVE BINARY_WIN32
# endif
#else
# warning Invalid build type
# warning Unknown binary type
# define BINARY_NATIVE BINARY_NONE
#endif

@@ -85,7 +87,7 @@
#ifdef BUILD_BRIDGE
# define CARLA_EXPORT
#else
# if defined(Q_OS_WIN) && !defined(__WINE__)
# if defined(Q_OS_WIN) && ! defined(__WINE__)
# define CARLA_EXPORT extern "C" __declspec (dllexport)
# else
# define CARLA_EXPORT extern "C" __attribute__ ((visibility("default")))


+ 9
- 7
src/carla-includes/carla_lib_includes.h View File

@@ -18,11 +18,13 @@
#ifndef CARLA_LIB_INCLUDES_H
#define CARLA_LIB_INCLUDES_H

#ifdef Q_OS_WIN
#include <cstdio>
#endif
#include "carla_includes.h"

//#ifdef Q_OS_WIN
//#include <cstdio>
//#endif

static
static inline
void* lib_open(const char* filename)
{
#ifdef Q_OS_WIN
@@ -32,7 +34,7 @@ void* lib_open(const char* filename)
#endif
}

static
static inline
bool lib_close(void* lib)
{
#ifdef Q_OS_WIN
@@ -42,7 +44,7 @@ bool lib_close(void* lib)
#endif
}

static
static inline
void* lib_symbol(void* lib, const char* symbol)
{
#ifdef Q_OS_WIN
@@ -52,7 +54,7 @@ void* lib_symbol(void* lib, const char* symbol)
#endif
}

static
static inline
const char* lib_error(const char* filename)
{
#ifdef Q_OS_WIN


+ 5
- 3
src/carla-includes/carla_vst_includes.h View File

@@ -18,7 +18,7 @@
#ifndef CARLA_VST_INCLUDES_H
#define CARLA_VST_INCLUDES_H

#define VST_FORCE_DEPRECATED 0
#define VST_FORCE_DEPRECATED 1
#include "aeffectx.h"

#if VESTIGE_HEADER
@@ -59,12 +59,14 @@ typedef VstTimeInfo VstTimeInfo_R;

typedef AEffect* (*VST_Function)(audioMasterCallback);

inline bool VstPluginCanDo(AEffect* effect, const char* feature)
static inline
bool VstPluginCanDo(AEffect* effect, const char* feature)
{
return (effect->dispatcher(effect, effCanDo, 0, 0, (void*)feature, 0.0f) == 1);
}

inline const char* VstOpcode2str(int32_t opcode)
static inline
const char* VstOpcode2str(int32_t opcode)
{
switch (opcode)
{


+ 1
- 1
src/carla-lilv/Makefile View File

@@ -12,7 +12,7 @@ SORD_VERSION = 0.8.0
SRATOM_VERSION = 0.2.0
LILV_VERSION = 0.14.2

BUILD_FLAGS = -O2 -fvisibility=hidden -fPIC -mtune=generic -std=c99 -Wall $(CFLAGS)
BUILD_FLAGS = -O2 -ffast-math -fomit-frame-pointer -fvisibility=hidden -fPIC -mtune=generic -msse -std=c99 -Wall $(CFLAGS)
BUILD_FLAGS += -Iconfig -I../carla-includes

32BIT_FLAGS = -m32


+ 3
- 3
src/carla.py View File

@@ -3451,7 +3451,7 @@ if __name__ == '__main__':
if (carla_bridge_lv2_x11):
CarlaHost.set_option(OPTION_PATH_BRIDGE_LV2_X11, 0, carla_bridge_lv2_x11)

if (not CarlaHost.carla_init("Carla")):
if (not CarlaHost.engine_init("Carla")):
CustomMessageBox(None, QMessageBox.Critical, "Error", "Could not connect to JACK",
cString(CarlaHost.get_last_error()), QMessageBox.Ok, QMessageBox.Ok)
sys.exit(1)
@@ -3471,8 +3471,8 @@ if __name__ == '__main__':
ret = app.exec_()

# Close Host
if (CarlaHost.carla_is_engine_running()):
if (not CarlaHost.carla_close()):
if (CarlaHost.is_engine_running()):
if (not CarlaHost.engine_close()):
print(cString(CarlaHost.get_last_error()))

# Exit properly


+ 14
- 14
src/carla_backend.py View File

@@ -181,8 +181,8 @@ else:
CWD = sys.path[0]

# find carla_library_path
if os.path.exists(os.path.join(CWD, "carla", carla_libname)):
carla_library_path = os.path.join(CWD, "carla", carla_libname)
if os.path.exists(os.path.join(CWD, "carla-backend", carla_libname)):
carla_library_path = os.path.join(CWD, "carla-backend", carla_libname)
else:
if WINDOWS:
CARLA_PATH = (os.path.join(PROGRAMFILES, "Cadence", "carla"),)
@@ -728,14 +728,14 @@ class Host(object):

self.lib = cdll.LoadLibrary(carla_library_path)

self.lib.carla_init.argtypes = [c_char_p]
self.lib.carla_init.restype = c_bool
self.lib.engine_init.argtypes = [c_char_p]
self.lib.engine_init.restype = c_bool

self.lib.carla_close.argtypes = None
self.lib.carla_close.restype = c_bool
self.lib.engine_close.argtypes = None
self.lib.engine_close.restype = c_bool

self.lib.carla_is_engine_running.argtypes = None
self.lib.carla_is_engine_running.restype = c_bool
self.lib.is_engine_running.argtypes = None
self.lib.is_engine_running.restype = c_bool

self.lib.add_plugin.argtypes = [c_enum, c_enum, c_char_p, c_char_p, c_void_p]
self.lib.add_plugin.restype = c_short
@@ -896,14 +896,14 @@ class Host(object):
self.lib.get_latency.argtypes = None
self.lib.get_latency.restype = c_double

def carla_init(self, client_name):
return self.lib.carla_init(client_name.encode("utf-8"))
def engine_init(self, client_name):
return self.lib.engine_init(client_name.encode("utf-8"))

def carla_close(self):
return self.lib.carla_close()
def engine_close(self):
return self.lib.engine_close()

def carla_is_engine_running(self):
return self.lib.carla_is_engine_running()
def is_engine_running(self):
return self.lib.is_engine_running()

def add_plugin(self, btype, ptype, filename, label, extra_stuff):
return self.lib.add_plugin(btype, ptype, filename.encode("utf-8"), label.encode("utf-8"), cast(extra_stuff, c_void_p))


Loading…
Cancel
Save