| @@ -3,11 +3,11 @@ | |||
| .*.kate-swp | |||
| *~ | |||
| *.o | |||
| *.a | |||
| *.exe | |||
| *.o | |||
| *.so | |||
| *.dll | |||
| *.exe | |||
| *.carxp | |||
| *.carxs | |||
| @@ -9,7 +9,7 @@ DESTDIR = | |||
| SED_PREFIX = $(shell echo $(PREFIX) | sed "s/\//\\\\\\\\\//g") | |||
| PYUIC = pyuic4 --pyqt3-wrapper | |||
| PYUIC = pyuic4 | |||
| PYRCC = pyrcc4 -py3 | |||
| # Detect architecture | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| { | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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; | |||
| } | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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); | |||
| } | |||
| @@ -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(); | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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); | |||
| @@ -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 | |||
| @@ -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 | |||
| { | |||
| @@ -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 | |||
| { | |||
| @@ -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 | |||
| { | |||
| @@ -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 | |||
| @@ -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 | |||
| { | |||
| @@ -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 | |||
| @@ -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,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 | |||
| # -------------------------------------------------------------- | |||
| @@ -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; | |||
| @@ -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"))) | |||
| @@ -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 | |||
| @@ -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) | |||
| { | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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)) | |||