| @@ -4,7 +4,8 @@ | |||
| # Created by falkTX | |||
| # | |||
| CXX ?= g++ | |||
| CXX ?= g++ | |||
| WINECXX ?= wineg++ | |||
| BUILD_FLAGS = -DBUILD_BRIDGE -Wall -std=c++0x -I. -I../carla-includes -I../carla `pkg-config --cflags jack liblo QtCore QtGui` $(CXXFLAGS) | |||
| #BUILD_FLAGS += -DNDEBUG -DQT_NO_DEBUG -DQT_NO_DEBUG_STREAM -DQT_NO_DEBUG_OUTPUT -O2 -ffast-math -fomit-frame-pointer -mtune=generic -msse | |||
| @@ -21,12 +22,17 @@ 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) | |||
| WIN_BUILD_FLAGS = $(BUILD_FLAGS) | |||
| WIN_LINK_FLAGS = $(LINK_FLAGS) | |||
| WIN_32BIT_FLAGS = -L/usr/lib32/wine -L/usr/lib/i386-linux-gnu/wine $(32BIT_FLAGS) | |||
| WIN_64BIT_FLAGS = -L/usr/lib64/wine -L/usr/lib/x86_64-linux-gnu/wine $(64BIT_FLAGS) | |||
| WIN_LINK_FLAGS = -static $(LINK_FLAGS) | |||
| WIN_32BIT_FLAGS = $(32BIT_FLAGS) | |||
| WIN_64BIT_FLAGS = $(64BIT_FLAGS) | |||
| SOURCES = carla_bridge.cpp carla_osc.cpp ../carla/carla_jack.cpp ../carla/ladspa.cpp | |||
| # ../carla/carla_backend.cpp ../carla/carla_osc.cpp ../carla/carla_threads.cpp | |||
| WINE_BUILD_FLAGS = $(BUILD_FLAGS) | |||
| WINE_LINK_FLAGS = $(LINK_FLAGS) | |||
| 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) | |||
| SOURCES = carla_bridge.cpp carla_osc.cpp ../carla/carla_jack.cpp ../carla/carla_shared.cpp ../carla/ladspa.cpp | |||
| #../carla/dssi.cpp ../carla/vst.cpp | |||
| all: | |||
| @@ -40,6 +46,10 @@ win32: carla-bridge-win32.exe | |||
| win64: carla-bridge-win64.exe | |||
| wine32: carla-bridge-win32.exe.so | |||
| wine64: carla-bridge-win64.exe.so | |||
| carla-bridge-unix32: $(SOURCES) | |||
| $(CXX) $(SOURCES) $(UNIX_BUILD_FLAGS) $(UNIX_32BIT_FLAGS) $(UNIX_LINK_FLAGS) -o $@ | |||
| @@ -53,5 +63,11 @@ carla-bridge-win32.exe: $(SOURCES) | |||
| carla-bridge-win64.exe: $(SOURCES) | |||
| $(CXX) $(SOURCES) $(WIN_BUILD_FLAGS) $(WIN_64BIT_FLAGS) $(WIN_LINK_FLAGS) -o $@ | |||
| carla-bridge-win32.exe.so: $(SOURCES) | |||
| $(WINECXX) $(SOURCES) $(WINE_BUILD_FLAGS) $(WINE_32BIT_FLAGS) $(WINE_LINK_FLAGS) -o carla-bridge-win32.exe | |||
| carla-bridge-win64.exe.so: $(SOURCES) | |||
| $(WINECXX) $(SOURCES) $(WINE_BUILD_FLAGS) $(WINE_64BIT_FLAGS) $(WINE_LINK_FLAGS) -o carla-bridge-win64.exe | |||
| clean: | |||
| rm -f carla-bridge-* | |||
| @@ -15,182 +15,31 @@ | |||
| * For a full copy of the GNU General Public License see the COPYING file | |||
| */ | |||
| #include "carla_backend.h" | |||
| #include "carla_osc.h" | |||
| #include "carla_plugin.h" | |||
| #include <QtGui/QApplication> | |||
| // Global variables | |||
| CallbackFunc Callback = nullptr; | |||
| const char* last_error = nullptr; | |||
| QMutex carla_proc_lock_var; | |||
| QMutex carla_midi_lock_var; | |||
| // Global variables (shared) | |||
| const char* unique_names[MAX_PLUGINS] = { nullptr }; | |||
| CarlaPlugin* CarlaPlugins[MAX_PLUGINS] = { nullptr }; | |||
| volatile double ains_peak[MAX_PLUGINS*2] = { 0.0 }; | |||
| volatile double aouts_peak[MAX_PLUGINS*2] = { 0.0 }; | |||
| // Global OSC stuff | |||
| lo_server_thread global_osc_server_thread = nullptr; | |||
| const char* global_osc_server_path = nullptr; | |||
| OscData global_osc_data = { nullptr, nullptr, nullptr }; | |||
| // Global JACK stuff | |||
| jack_client_t* carla_jack_client = nullptr; | |||
| jack_nframes_t carla_buffer_size = 512; | |||
| jack_nframes_t carla_sample_rate = 44100; | |||
| // Global options | |||
| carla_options_t carla_options = { | |||
| /* initiated */ false, | |||
| /* global_jack_client */ false, | |||
| /* use_dssi_chunks */ false, | |||
| /* prefer_ui_bridges */ true | |||
| }; | |||
| // global check | |||
| bool close_now = false; | |||
| // plugin specific | |||
| short add_plugin_ladspa(const char* filename, const char* label, void* extra_stuff); | |||
| // TODO - make these shared: | |||
| short get_new_plugin_id() | |||
| { | |||
| for (unsigned short i=0; i<MAX_PLUGINS; i++) | |||
| { | |||
| if (CarlaPlugins[i] == nullptr) | |||
| return i; | |||
| } | |||
| return -1; | |||
| } | |||
| const char* get_unique_name(const char* name) | |||
| { | |||
| int max = jack_port_name_size()/2 - 5; | |||
| //if (carla_options.global_jack_client) | |||
| // max -= strlen(carla_client_name); | |||
| qDebug("get_unique_name(%s) - truncated to %i", name, max); | |||
| QString qname(name); | |||
| if (qname.isEmpty()) | |||
| qname = "(No name)"; | |||
| qname.truncate(max); | |||
| //qname.replace(":", "."); // ":" is used in JACK to split client/port names | |||
| for (unsigned short i=0; i<MAX_PLUGINS; i++) | |||
| { | |||
| // Check if unique name already exists | |||
| if (unique_names[i] && qname == unique_names[i]) | |||
| { | |||
| // Check if string has already been modified | |||
| uint len = qname.size(); | |||
| if (qname.at(len-3) == QChar('(') && qname.at(len-2).isDigit() && qname.at(len-1) == QChar(')')) | |||
| { | |||
| int number = qname.at(len-2).toAscii()-'0'; | |||
| if (number == 9) | |||
| // next number is 10, 2 digits | |||
| qname.replace(" (9)", " (10)"); | |||
| else | |||
| qname[len-2] = QChar('0'+number+1); | |||
| continue; | |||
| } | |||
| else if (qname.at(len-4) == QChar('(') && qname.at(len-3).isDigit() && qname.at(len-2).isDigit() && qname.at(len-1) == QChar(')')) | |||
| { | |||
| QChar n2 = qname.at(len-2); // (1x) | |||
| QChar n3 = qname.at(len-3); // (x0) | |||
| if (n2 == QChar('9')) | |||
| { | |||
| n2 = QChar('0'); | |||
| n3 = QChar(n3.toAscii()+1); | |||
| } | |||
| else | |||
| n2 = QChar(n2.toAscii()+1); | |||
| qname[len-2] = n2; | |||
| qname[len-3] = n3; | |||
| continue; | |||
| } | |||
| // Modify string if not | |||
| qname += " (2)"; | |||
| } | |||
| } | |||
| return strdup(qname.toUtf8().constData()); | |||
| } | |||
| void set_last_error(const char* error) | |||
| { | |||
| if (last_error) | |||
| free((void*)last_error); | |||
| last_error = strdup(error); | |||
| } | |||
| void carla_proc_lock() | |||
| { | |||
| carla_proc_lock_var.lock(); | |||
| } | |||
| void carla_proc_unlock() | |||
| { | |||
| carla_proc_lock_var.unlock(); | |||
| } | |||
| void carla_midi_lock() | |||
| { | |||
| carla_midi_lock_var.lock(); | |||
| } | |||
| void carla_midi_unlock() | |||
| { | |||
| carla_midi_lock_var.unlock(); | |||
| } | |||
| void callback_action(CallbackType action, unsigned short plugin_id, int value1, int value2, double value3) | |||
| { | |||
| if (Callback) | |||
| Callback(action, plugin_id, value1, value2, value3); | |||
| } | |||
| 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; | |||
| } | |||
| short add_plugin_dssi(const char* filename, const char* label, void* extra_stuff); | |||
| short add_plugin_vst(const char* filename, const char* label); | |||
| int main(int argc, char* argv[]) | |||
| { | |||
| if (argc != 6) | |||
| if (argc != 5) | |||
| { | |||
| qWarning("%s :: bad arguments", argv[0]); | |||
| return 1; | |||
| } | |||
| const char* stype = argv[1]; | |||
| const char* filename = argv[2]; | |||
| const char* label = argv[3]; | |||
| const char* pname = argv[4]; | |||
| const char* osc_url = argv[5]; | |||
| const char* osc_url = argv[1]; | |||
| const char* stype = argv[2]; | |||
| const char* filename = argv[3]; | |||
| const char* label = argv[4]; | |||
| short id; | |||
| PluginType itype; | |||
| @@ -208,31 +57,72 @@ int main(int argc, char* argv[]) | |||
| return 1; | |||
| } | |||
| osc_init(pname, osc_url); | |||
| set_last_error("no error"); | |||
| QApplication app(argc, argv); | |||
| osc_init(label, osc_url); | |||
| set_last_error("no error"); | |||
| switch (itype) | |||
| { | |||
| case PLUGIN_LADSPA: | |||
| id = add_plugin_ladspa(filename, label, nullptr); | |||
| break; | |||
| // case PLUGIN_DSSI: | |||
| // id = add_plugin_dssi(filename, label, nullptr); | |||
| // break; | |||
| // case PLUGIN_VST: | |||
| // id = add_plugin_vst(filename, label); | |||
| // break; | |||
| default: | |||
| break; | |||
| } | |||
| if (id >= 0) | |||
| { | |||
| app.exec(); | |||
| CarlaPlugin* plugin = CarlaPlugins[0]; | |||
| if (plugin && plugin->id() >= 0) | |||
| { | |||
| osc_send_update(); | |||
| // FIXME | |||
| plugin->set_active(true, false, false); | |||
| while (close_now == false) | |||
| { | |||
| app.processEvents(); | |||
| if (close_now) break; | |||
| if (plugin->ain_count() > 0) | |||
| { | |||
| osc_send_bridge_ains_peak(1, ains_peak[0]); | |||
| osc_send_bridge_ains_peak(2, ains_peak[1]); | |||
| } | |||
| if (close_now) break; | |||
| if (plugin->aout_count() > 0) | |||
| { | |||
| osc_send_bridge_aouts_peak(1, aouts_peak[0]); | |||
| osc_send_bridge_aouts_peak(2, aouts_peak[1]); | |||
| } | |||
| if (close_now) break; | |||
| usleep(50000); // 50 ms | |||
| } | |||
| delete plugin; | |||
| } | |||
| } | |||
| else | |||
| { | |||
| qWarning("Plugin failed to load, error was:\n%s", last_error); | |||
| qWarning("Plugin failed to load, error was:\n%s", get_last_error()); | |||
| return 1; | |||
| } | |||
| //remove_plugin(id); | |||
| osc_close(); | |||
| return 0; | |||
| @@ -16,20 +16,19 @@ | |||
| */ | |||
| #include "carla_osc.h" | |||
| #include "carla_plugin.h" | |||
| // Global variables | |||
| const char* plugin_name; | |||
| size_t plugin_name_len; | |||
| size_t plugin_name_len = 0; | |||
| const char* plugin_name = nullptr; | |||
| // Global OSC stuff | |||
| extern lo_server_thread global_osc_server_thread; | |||
| extern const char* global_osc_server_path; | |||
| extern OscData global_osc_data; | |||
| const char* global_osc_server_path = nullptr; | |||
| lo_server_thread global_osc_server_thread = nullptr; | |||
| OscData global_osc_data = { nullptr, nullptr, nullptr }; | |||
| void osc_init(const char* plugin_name_, const char* osc_url) | |||
| void osc_init(const char* osc_name, const char* osc_url) | |||
| { | |||
| qDebug("osc_init()"); | |||
| plugin_name = plugin_name_; | |||
| qDebug("osc_init(%s, %s)", osc_name, osc_url); | |||
| plugin_name = osc_name; | |||
| plugin_name_len = strlen(plugin_name); | |||
| const char* host = lo_url_get_hostname(osc_url); | |||
| @@ -134,3 +133,36 @@ int osc_message_handler(const char* path, const char* types, lo_arg** argv, int | |||
| return 1; | |||
| } | |||
| void osc_send_update() | |||
| { | |||
| if (global_osc_data.target) | |||
| { | |||
| char target_path[strlen(global_osc_data.path)+8]; | |||
| strcpy(target_path, global_osc_data.path); | |||
| strcat(target_path, "/update"); | |||
| lo_send(global_osc_data.target, target_path, "s", global_osc_server_path); | |||
| } | |||
| } | |||
| void osc_send_bridge_ains_peak(int index, double value) | |||
| { | |||
| if (global_osc_data.target) | |||
| { | |||
| char target_path[strlen(global_osc_data.path)+18]; | |||
| strcpy(target_path, global_osc_data.path); | |||
| strcat(target_path, "/bridge_ains_peak"); | |||
| lo_send(global_osc_data.target, target_path, "if", index, value); | |||
| } | |||
| } | |||
| void osc_send_bridge_aouts_peak(int index, double value) | |||
| { | |||
| if (global_osc_data.target) | |||
| { | |||
| char target_path[strlen(global_osc_data.path)+19]; | |||
| strcpy(target_path, global_osc_data.path); | |||
| strcat(target_path, "/bridge_aouts_peak"); | |||
| lo_send(global_osc_data.target, target_path, "if", index, value); | |||
| } | |||
| } | |||
| @@ -19,18 +19,18 @@ | |||
| #define CARLA_OSC_H | |||
| #include "carla_includes.h" | |||
| #include <lo/lo.h> | |||
| class CarlaPlugin; | |||
| struct OscData { | |||
| char* path; | |||
| lo_address source; | |||
| lo_address source; // unused | |||
| lo_address target; | |||
| }; | |||
| // public --------------------------------------------------------------------------- | |||
| void osc_init(const char* plugin_name, const char* osc_url); | |||
| void osc_init(const char* osc_name, const char* osc_url); | |||
| void osc_close(); | |||
| void osc_clear_data(OscData* osc_data); | |||
| @@ -46,4 +46,8 @@ void osc_send_show(OscData* osc_data); | |||
| void osc_send_hide(OscData* osc_data); | |||
| void osc_send_quit(OscData* osc_data); | |||
| void osc_send_update(); | |||
| void osc_send_bridge_ains_peak(int index, double value); | |||
| void osc_send_bridge_aouts_peak(int index, double value); | |||
| #endif // CARLA_OSC_H | |||
| @@ -1940,8 +1940,8 @@ class PluginWidget(QFrame, ui_carla_plugin.Ui_PluginWidget): | |||
| audio_count['outs'] = 0 | |||
| audio_count['total'] = 0 | |||
| self.peaks_in = audio_count['ins'] | |||
| self.peaks_out = audio_count['outs'] | |||
| self.peaks_in = int(audio_count['ins']) | |||
| self.peaks_out = int(audio_count['outs']) | |||
| if (self.peaks_in > 2): | |||
| self.peaks_in = 2 | |||
| @@ -2689,12 +2689,13 @@ class CarlaMainW(QMainWindow, ui_carla.Ui_CarlaMainW): | |||
| # ------------------------------------------------------------- | |||
| # Internal stuff | |||
| self.m_bridge_info = None | |||
| self.m_project_filename = None | |||
| self.m_plugin_list = [] | |||
| for x in range(MAX_PLUGINS): | |||
| self.m_plugin_list.append(None) | |||
| self.m_project_filename = None | |||
| CarlaHost.set_callback_function(self.callback_function) | |||
| # ------------------------------------------------------------- | |||
| @@ -2925,9 +2926,25 @@ class CarlaMainW(QMainWindow, ui_carla.Ui_CarlaMainW): | |||
| self.act_plugin_remove_all.setEnabled(False) | |||
| def get_extra_stuff(self, plugin): | |||
| build = plugin['build'] | |||
| ptype = plugin['type'] | |||
| if (ptype == PLUGIN_LADSPA): | |||
| print(ptype, plugin['type']) | |||
| if (build != BINARY_NATIVE): | |||
| # Store object so we can return a pointer | |||
| if (self.m_bridge_info == None): | |||
| self.m_bridge_info = PluginBridgeInfo() | |||
| self.m_bridge_info.category = plugin['category'] | |||
| self.m_bridge_info.hints = plugin['hints'] | |||
| self.m_bridge_info.name = plugin['name'].encode("utf-8") | |||
| self.m_bridge_info.maker = plugin['maker'].encode("utf-8") | |||
| self.m_bridge_info.unique_id = plugin['unique_id'] | |||
| self.m_bridge_info.ains = plugin['audio.ins'] | |||
| self.m_bridge_info.aouts = plugin['audio.outs'] | |||
| return pointer(self.m_bridge_info) | |||
| elif (ptype == PLUGIN_LADSPA): | |||
| unique_id = plugin['unique_id'] | |||
| for rdf_item in self.ladspa_rdf_list: | |||
| if (rdf_item.UniqueID == unique_id): | |||
| @@ -2952,19 +2969,6 @@ class CarlaMainW(QMainWindow, ui_carla.Ui_CarlaMainW): | |||
| else: | |||
| return c_nullptr | |||
| #elif (ptype == PLUGIN_WINVST): | |||
| ## Store object so we can return a pointer | |||
| #if (self.winvst_info == None): | |||
| #self.winvst_info = WinVstBaseInfo() | |||
| #self.winvst_info.category = plugin['category'] | |||
| #self.winvst_info.hints = plugin['hints'] | |||
| #self.winvst_info.name = plugin['name'] | |||
| #self.winvst_info.maker = plugin['maker'] | |||
| #self.winvst_info.unique_id = long(plugin['id']) | |||
| #self.winvst_info.ains = plugin['audio.ins'] | |||
| #self.winvst_info.aouts = plugin['audio.outs'] | |||
| #return pointer(self.winvst_info) | |||
| else: | |||
| return c_nullptr | |||
| @@ -12,7 +12,7 @@ CARLA_BUILD_FLAGS = -Wall -std=c++0x -fPIC -I. -I../carla-includes `pkg-config | |||
| CARLA_BUILD_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_threads.o ladspa.o dssi.o lv2.o vst.o sf2.o | |||
| 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 | |||
| @@ -15,56 +15,11 @@ | |||
| * For a full copy of the GNU General Public License see the COPYING file | |||
| */ | |||
| #include "carla_backend.h" | |||
| #include "carla_osc.h" | |||
| #include "carla_plugin.h" | |||
| #include "carla_threads.h" | |||
| #include <cstring> | |||
| #include <ostream> | |||
| #include <QtCore/QString> | |||
| // Global variables | |||
| CallbackFunc Callback = nullptr; | |||
| const char* last_error = nullptr; | |||
| const char* carla_client_name = nullptr; | |||
| QMutex carla_proc_lock_var; | |||
| QMutex carla_midi_lock_var; | |||
| CarlaCheckThread carla_check_thread; | |||
| // Global variables (shared) | |||
| const char* unique_names[MAX_PLUGINS] = { nullptr }; | |||
| CarlaPlugin* CarlaPlugins[MAX_PLUGINS] = { nullptr }; | |||
| volatile double ains_peak[MAX_PLUGINS*2] = { 0.0 }; | |||
| volatile double aouts_peak[MAX_PLUGINS*2] = { 0.0 }; | |||
| // Global JACK stuff | |||
| jack_client_t* carla_jack_client = nullptr; | |||
| jack_nframes_t carla_buffer_size = 512; | |||
| jack_nframes_t carla_sample_rate = 44100; | |||
| // Global OSC stuff | |||
| lo_server_thread global_osc_server_thread = nullptr; | |||
| const char* global_osc_server_path = nullptr; | |||
| OscData global_osc_data = { nullptr, nullptr, nullptr }; | |||
| // Global options | |||
| carla_options_t carla_options = { | |||
| /* initiated */ false, | |||
| /* global_jack_client */ true, | |||
| /* use_dssi_chunks */ false, | |||
| /* prefer_ui_bridges */ true | |||
| }; | |||
| // jack.cpp | |||
| int carla_jack_process_callback(jack_nframes_t nframes, void* arg); | |||
| int carla_jack_bufsize_callback(jack_nframes_t new_buffer_size, void* arg); | |||
| int carla_jack_srate_callback(jack_nframes_t new_sample_rate, void* arg); | |||
| void carla_jack_shutdown_callback(void* arg); | |||
| //#include <cstring> | |||
| //#include <ostream> | |||
| // plugin specific | |||
| short add_plugin_ladspa(const char* filename, const char* label, void* extra_stuff); | |||
| @@ -74,6 +29,8 @@ 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); | |||
| CarlaCheckThread carla_check_thread; | |||
| // ------------------------------------------------------------------------------------------------------------------- | |||
| // Exported symbols (API) | |||
| @@ -83,50 +40,10 @@ bool carla_init(const char* client_name) | |||
| carla_options.initiated = true; | |||
| bool started = false; | |||
| 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); | |||
| if (carla_options.global_jack_client) | |||
| jack_set_process_callback(carla_jack_client, carla_jack_process_callback, nullptr); | |||
| 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_on_shutdown(carla_jack_client, carla_jack_shutdown_callback, nullptr); | |||
| if (jack_activate(carla_jack_client)) | |||
| { | |||
| set_last_error("Failed to activate the JACK client"); | |||
| carla_jack_client = nullptr; | |||
| } | |||
| else | |||
| started = true; | |||
| } | |||
| else | |||
| { | |||
| set_last_error("Failed to create new JACK client"); | |||
| carla_jack_client = nullptr; | |||
| } | |||
| bool started = carla_jack_init(client_name); | |||
| if (started) | |||
| { | |||
| const char* real_client_name = jack_get_client_name(carla_jack_client); | |||
| // Fix name for OSC usage | |||
| char* fixed_name = strdup(real_client_name); | |||
| 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); | |||
| osc_init(); | |||
| carla_check_thread.start(QThread::HighPriority); | |||
| set_last_error("no error"); | |||
| @@ -139,21 +56,7 @@ bool carla_close() | |||
| { | |||
| qDebug("carla_close()"); | |||
| bool closed = false; | |||
| if (jack_deactivate(carla_jack_client)) | |||
| { | |||
| set_last_error("Failed to deactivate the JACK client"); | |||
| } | |||
| else | |||
| { | |||
| if (jack_client_close(carla_jack_client)) | |||
| set_last_error("Failed to close the JACK client"); | |||
| else | |||
| closed = true; | |||
| } | |||
| carla_jack_client = nullptr; | |||
| bool closed = carla_jack_close(); | |||
| for (unsigned short i=0; i<MAX_PLUGINS; i++) | |||
| { | |||
| @@ -167,40 +70,26 @@ bool carla_close() | |||
| if (carla_check_thread.wait(2000) == false) // 2 secs | |||
| qWarning("Failed to properly stop global check thread"); | |||
| osc_send_exit(&global_osc_data); | |||
| //osc_send_exit(&global_osc_data); | |||
| osc_close(); | |||
| if (carla_client_name) | |||
| free((void*)carla_client_name); | |||
| if (last_error) | |||
| free((void*)last_error); | |||
| // cleanup static data | |||
| get_plugin_info(0); | |||
| get_parameter_info(0, 0); | |||
| get_scalepoint_info(0, 0, 0); | |||
| get_chunk_data(0); | |||
| get_real_plugin_name(0); | |||
| set_last_error(nullptr); | |||
| return closed; | |||
| } | |||
| bool carla_is_engine_running() | |||
| { | |||
| return bool(carla_jack_client); | |||
| } | |||
| short add_plugin(BinaryType btype, PluginType ptype, const char* filename, const char* label, void* extra_stuff) | |||
| { | |||
| qDebug("add_plugin(%i, %i, %s, %s, %p)", btype, ptype, filename, label, extra_stuff); | |||
| if (btype != BINARY_NATIVE) | |||
| { | |||
| #ifdef BUILD_BRIDGE | |||
| set_last_error("Wrong binary type"); | |||
| return -1; | |||
| #else | |||
| if (carla_options.global_jack_client) | |||
| { | |||
| set_last_error("Cannot use bridged plugins while in global client mode"); | |||
| @@ -208,14 +97,12 @@ short add_plugin(BinaryType btype, PluginType ptype, const char* filename, const | |||
| } | |||
| else | |||
| return add_plugin_bridge(btype, ptype, filename, label, extra_stuff); | |||
| #endif | |||
| } | |||
| switch (ptype) | |||
| { | |||
| case PLUGIN_LADSPA: | |||
| return add_plugin_ladspa(filename, label, extra_stuff); | |||
| #ifndef BUILD_BRIDGE | |||
| case PLUGIN_DSSI: | |||
| return add_plugin_dssi(filename, label, extra_stuff); | |||
| case PLUGIN_LV2: | |||
| @@ -224,7 +111,6 @@ short add_plugin(BinaryType btype, PluginType ptype, const char* filename, const | |||
| return add_plugin_vst(filename, label); | |||
| case PLUGIN_SF2: | |||
| return add_plugin_sf2(filename, label); | |||
| #endif | |||
| default: | |||
| set_last_error("Unknown plugin type"); | |||
| return -1; | |||
| @@ -240,7 +126,7 @@ bool remove_plugin(unsigned short plugin_id) | |||
| CarlaPlugin* plugin = CarlaPlugins[i]; | |||
| if (plugin && plugin->id() == plugin_id) | |||
| { | |||
| osc_send_remove_plugin(&global_osc_data, plugin->id()); | |||
| //osc_send_remove_plugin(&global_osc_data, plugin->id()); | |||
| carla_proc_lock(); | |||
| plugin->set_id(-1); | |||
| @@ -1164,12 +1050,6 @@ void prepare_for_save(unsigned short plugin_id) | |||
| qCritical("prepare_for_save(%i) - could not find plugin", plugin_id); | |||
| } | |||
| void set_callback_function(CallbackFunc func) | |||
| { | |||
| qDebug("set_callback_function(%p)", func); | |||
| Callback = func; | |||
| } | |||
| void set_option(OptionsType option, int value, const char* value_str) | |||
| { | |||
| qDebug("set_option(%i, %i, %s)", option, value, value_str); | |||
| @@ -1187,169 +1067,5 @@ void set_option(OptionsType option, int value, const char* value_str) | |||
| } | |||
| } | |||
| const char* get_last_error() | |||
| { | |||
| qDebug("get_last_error()"); | |||
| return last_error; | |||
| } | |||
| const char* get_host_client_name() | |||
| { | |||
| qDebug("get_host_client_name()"); | |||
| return carla_client_name; | |||
| } | |||
| const char* get_host_osc_url() | |||
| { | |||
| qDebug("get_host_osc_url()"); | |||
| return global_osc_server_path; | |||
| } | |||
| 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) | |||
| // ------------------------------------------------------------------------------------------------------------------- | |||
| // ------------------------------------------------------------------------------------------------------------------- | |||
| // Helper functions | |||
| const char* bool2str(bool yesno) | |||
| { | |||
| if (yesno) | |||
| return "true"; | |||
| else | |||
| return "false"; | |||
| } | |||
| short get_new_plugin_id() | |||
| { | |||
| for (unsigned short i=0; i<MAX_PLUGINS; i++) | |||
| { | |||
| if (CarlaPlugins[i] == nullptr) | |||
| return i; | |||
| } | |||
| return -1; | |||
| } | |||
| const char* get_unique_name(const char* name) | |||
| { | |||
| int max = jack_port_name_size()/2 - 5; | |||
| if (carla_options.global_jack_client) | |||
| max -= strlen(carla_client_name); | |||
| qDebug("get_unique_name(%s) - truncated to %i", name, max); | |||
| QString qname(name); | |||
| if (qname.isEmpty()) | |||
| qname = "(No name)"; | |||
| qname.truncate(max); | |||
| //qname.replace(":", "."); // ":" is used in JACK to split client/port names | |||
| for (unsigned short i=0; i<MAX_PLUGINS; i++) | |||
| { | |||
| // Check if unique name already exists | |||
| if (unique_names[i] && qname == unique_names[i]) | |||
| { | |||
| // Check if string has already been modified | |||
| uint len = qname.size(); | |||
| if (qname.at(len-3) == QChar('(') && qname.at(len-2).isDigit() && qname.at(len-1) == QChar(')')) | |||
| { | |||
| int number = qname.at(len-2).toAscii()-'0'; | |||
| if (number == 9) | |||
| // next number is 10, 2 digits | |||
| qname.replace(" (9)", " (10)"); | |||
| else | |||
| qname[len-2] = QChar('0'+number+1); | |||
| continue; | |||
| } | |||
| else if (qname.at(len-4) == QChar('(') && qname.at(len-3).isDigit() && qname.at(len-2).isDigit() && qname.at(len-1) == QChar(')')) | |||
| { | |||
| QChar n2 = qname.at(len-2); // (1x) | |||
| QChar n3 = qname.at(len-3); // (x0) | |||
| if (n2 == QChar('9')) | |||
| { | |||
| n2 = QChar('0'); | |||
| n3 = QChar(n3.toAscii()+1); | |||
| } | |||
| else | |||
| n2 = QChar(n2.toAscii()+1); | |||
| qname[len-2] = n2; | |||
| qname[len-3] = n3; | |||
| continue; | |||
| } | |||
| // Modify string if not | |||
| qname += " (2)"; | |||
| } | |||
| } | |||
| return strdup(qname.toUtf8().constData()); | |||
| } | |||
| void* get_pointer(intptr_t ptr_addr) | |||
| { | |||
| intptr_t* ptr = (intptr_t*)ptr_addr; | |||
| return (void*)ptr; | |||
| } | |||
| void set_last_error(const char* error) | |||
| { | |||
| if (last_error) | |||
| free((void*)last_error); | |||
| last_error = strdup(error); | |||
| } | |||
| void carla_proc_lock() | |||
| { | |||
| carla_proc_lock_var.lock(); | |||
| } | |||
| void carla_proc_unlock() | |||
| { | |||
| carla_proc_lock_var.unlock(); | |||
| } | |||
| void carla_midi_lock() | |||
| { | |||
| carla_midi_lock_var.lock(); | |||
| } | |||
| void carla_midi_unlock() | |||
| { | |||
| carla_midi_lock_var.unlock(); | |||
| } | |||
| void callback_action(CallbackType action, unsigned short plugin_id, int value1, int value2, double value3) | |||
| { | |||
| if (Callback) | |||
| Callback(action, plugin_id, value1, value2, value3); | |||
| } | |||
| // End of helper functions | |||
| // ------------------------------------------------------------------------------------------------------------------- | |||
| @@ -297,28 +297,4 @@ CARLA_EXPORT double get_latency(); | |||
| // End of exported symbols | |||
| // ----------------------------------------------------- | |||
| class CarlaPlugin; | |||
| // Helper functions | |||
| const char* bool2str(bool yesno); | |||
| short get_new_plugin_id(); | |||
| const char* get_unique_name(const char* name); | |||
| void* get_pointer(intptr_t ptr_addr); | |||
| void set_last_error(const char* error); | |||
| void carla_proc_lock(); | |||
| void carla_proc_unlock(); | |||
| void carla_midi_lock(); | |||
| void carla_midi_unlock(); | |||
| void callback_action(CallbackType action, unsigned short plugin_id, int value1, int value2, double value3); | |||
| // Global variables (shared) | |||
| extern const char* unique_names[MAX_PLUGINS]; | |||
| extern CarlaPlugin* CarlaPlugins[MAX_PLUGINS]; | |||
| extern volatile double ains_peak[MAX_PLUGINS*2]; | |||
| extern volatile double aouts_peak[MAX_PLUGINS*2]; | |||
| // Global options | |||
| extern carla_options_t carla_options; | |||
| #endif // CARLA_BACKEND_H | |||
| @@ -24,31 +24,140 @@ public: | |||
| BridgePlugin(PluginType type) : CarlaPlugin() | |||
| { | |||
| qDebug("BridgePlugin::BridgePlugin()"); | |||
| m_type = type; | |||
| m_type = type; | |||
| m_hints = PLUGIN_IS_BRIDGE; | |||
| m_label = nullptr; | |||
| m_info.category = PLUGIN_CATEGORY_NONE; | |||
| m_info.hints = 0; | |||
| m_info.unique_id = 0; | |||
| m_info.ains = 0; | |||
| m_info.aouts = 0; | |||
| m_info.name = nullptr; | |||
| m_info.maker = nullptr; | |||
| m_thread = new CarlaPluginThread(this, CarlaPluginThread::PLUGIN_THREAD_BRIDGE); | |||
| } | |||
| virtual ~BridgePlugin() | |||
| { | |||
| qDebug("BridgePlugin::~BridgePlugin()"); | |||
| if (m_label) | |||
| free((void*)m_label); | |||
| if (m_info.name) | |||
| free((void*)m_info.name); | |||
| if (m_info.maker) | |||
| free((void*)m_info.maker); | |||
| if (m_thread->isRunning()) | |||
| m_thread->quit(); | |||
| delete m_thread; | |||
| } | |||
| virtual PluginCategory category() | |||
| { | |||
| return m_info.category; | |||
| } | |||
| virtual long unique_id() | |||
| { | |||
| return m_info.unique_id; | |||
| } | |||
| virtual uint32_t ain_count() | |||
| { | |||
| return m_info.ains; | |||
| } | |||
| virtual uint32_t aout_count() | |||
| { | |||
| return m_info.aouts; | |||
| } | |||
| virtual void get_label(char* buf_str) | |||
| { | |||
| strncpy(buf_str, m_label, STR_MAX); | |||
| } | |||
| virtual void get_maker(char* buf_str) | |||
| { | |||
| strncpy(buf_str, m_info.maker, STR_MAX); | |||
| } | |||
| virtual void get_copyright(char* buf_str) | |||
| { | |||
| strncpy(buf_str, m_info.maker, STR_MAX); | |||
| } | |||
| virtual void get_real_name(char* buf_str) | |||
| { | |||
| strncpy(buf_str, m_info.name, STR_MAX); | |||
| } | |||
| virtual void get_audio_port_count_info(PortCountInfo* info) | |||
| { | |||
| info->ins = m_info.ains; | |||
| info->outs = m_info.aouts; | |||
| info->total = m_info.ains + m_info.aouts; | |||
| } | |||
| virtual void reload() | |||
| { | |||
| m_hints = 0; | |||
| m_hints |= PLUGIN_IS_BRIDGE; | |||
| // plugin checks | |||
| m_hints &= ~(PLUGIN_IS_SYNTH | PLUGIN_USES_CHUNKS | PLUGIN_CAN_DRYWET | PLUGIN_CAN_VOLUME | PLUGIN_CAN_BALANCE); | |||
| if (m_info.aouts > 0 && (m_info.ains == m_info.aouts || m_info.ains == 1)) | |||
| m_hints |= PLUGIN_CAN_DRYWET; | |||
| if (m_info.aouts > 0) | |||
| m_hints |= PLUGIN_CAN_VOLUME; | |||
| if (m_info.aouts >= 2 && m_info.aouts % 2 == 0) | |||
| m_hints |= PLUGIN_CAN_BALANCE; | |||
| m_hints |= m_info.hints; | |||
| } | |||
| bool init(const char* filename, const char* label, void* extra_stuff) | |||
| { | |||
| if (extra_stuff == nullptr) | |||
| { | |||
| set_last_error("Invalid bridge info, cannot continue"); | |||
| return false; | |||
| } | |||
| set_last_error("Valid bridge info"); | |||
| PluginBridgeInfo* info = (PluginBridgeInfo*)extra_stuff; | |||
| m_info.category = info->category; | |||
| m_info.hints = info->hints; | |||
| m_info.unique_id = info->unique_id; | |||
| m_info.ains = info->ains; | |||
| m_info.aouts = info->aouts; | |||
| m_info.name = strdup(info->name); | |||
| m_info.maker = strdup(info->maker); | |||
| m_label = strdup(label); | |||
| m_name = get_unique_name(info->name); | |||
| m_filename = strdup(filename); | |||
| m_name = get_unique_name("TODO"); | |||
| Q_UNUSED(label); | |||
| Q_UNUSED(extra_stuff); | |||
| // TODO - get bridge binary here | |||
| m_thread->setOscData("/home/falktx/Personal/FOSS/GIT/Cadence/src/carla-bridge/carla-bridge-win32.exe", label, plugintype2str(m_type)); | |||
| m_thread->start(); | |||
| return true; | |||
| } | |||
| //private: | |||
| //CarlaPluginThread m_thread; | |||
| private: | |||
| const char* m_label; | |||
| PluginBridgeInfo m_info; | |||
| CarlaPluginThread* m_thread; | |||
| }; | |||
| short add_plugin_bridge(BinaryType btype, PluginType ptype, const char* filename, const char* label, void* extra_stuff) | |||
| @@ -72,7 +72,7 @@ | |||
| # error Invalid build type | |||
| #endif | |||
| // don't export symbols if using bridge mode | |||
| // don't export symbols if in bridge mode | |||
| #if defined(BUILD_BRIDGE) | |||
| # define CARLA_EXPORT | |||
| #else | |||
| @@ -15,15 +15,80 @@ | |||
| * For a full copy of the GNU General Public License see the COPYING file | |||
| */ | |||
| #include "carla_jack.h" | |||
| #include "carla_plugin.h" | |||
| // Global JACK stuff | |||
| extern jack_client_t* carla_jack_client; | |||
| extern jack_nframes_t carla_buffer_size; | |||
| extern jack_nframes_t carla_sample_rate; | |||
| jack_client_t* carla_jack_client = nullptr; | |||
| jack_nframes_t carla_buffer_size = 512; | |||
| jack_nframes_t carla_sample_rate = 44100; | |||
| const char* carla_client_name = nullptr; | |||
| // ------------------------------------------------------------------------------------------------------------------- | |||
| // Exported symbols (API) | |||
| bool carla_is_engine_running() | |||
| { | |||
| return bool(carla_jack_client); | |||
| } | |||
| const char* get_host_client_name() | |||
| { | |||
| //qDebug("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) | |||
| // ------------------------------------------------------------------------------------------------------------------- | |||
| 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; | |||
| } | |||
| int carla_jack_srate_callback(jack_nframes_t new_sample_rate, void*) | |||
| { | |||
| carla_sample_rate = new_sample_rate; | |||
| return 0; | |||
| } | |||
| int carla_jack_process_callback(jack_nframes_t nframes, void* arg) | |||
| { | |||
| #ifndef BUILD_BRIDGE | |||
| if (carla_options.global_jack_client) | |||
| { | |||
| for (unsigned short i=0; i<MAX_PLUGINS; i++) | |||
| @@ -36,49 +101,136 @@ int carla_jack_process_callback(jack_nframes_t nframes, void* arg) | |||
| carla_proc_unlock(); | |||
| } | |||
| } | |||
| return 0; | |||
| } | |||
| else if (arg) | |||
| #endif | |||
| #ifdef BUILD_BRIDGE | |||
| CarlaPlugin* plugin = CarlaPlugins[0]; | |||
| #else | |||
| CarlaPlugin* plugin = (CarlaPlugin*)arg; | |||
| #endif | |||
| if (plugin && plugin->id() >= 0) | |||
| { | |||
| CarlaPlugin* plugin = (CarlaPlugin*)arg; | |||
| if (plugin->id() >= 0) | |||
| { | |||
| carla_proc_lock(); | |||
| plugin->process(nframes); | |||
| carla_proc_unlock(); | |||
| } | |||
| carla_proc_lock(); | |||
| plugin->process(nframes); | |||
| carla_proc_unlock(); | |||
| } | |||
| return 0; | |||
| } | |||
| int carla_jack_bufsize_callback(jack_nframes_t new_buffer_size, void* arg) | |||
| void carla_jack_shutdown_callback(void*) | |||
| { | |||
| carla_buffer_size = new_buffer_size; | |||
| 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); | |||
| // FIXME | |||
| //CarlaPlugin* plugin = CarlaPlugins[i]; | |||
| //if (plugin && plugin->id() == plugin_id) | |||
| // plugin->jack_client = nullptr; | |||
| } | |||
| return 0; | |||
| carla_jack_client = nullptr; | |||
| callback_action(CALLBACK_QUIT, 0, 0, 0, 0.0); | |||
| } | |||
| int carla_jack_srate_callback(jack_nframes_t new_sample_rate, void*) | |||
| // ------------------------------------------------------------------------------------------------------------------- | |||
| bool carla_jack_init(const char* client_name) | |||
| { | |||
| carla_sample_rate = new_sample_rate; | |||
| return 0; | |||
| 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); | |||
| 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_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; | |||
| } | |||
| } | |||
| else | |||
| { | |||
| set_last_error("Failed to create new JACK client"); | |||
| carla_jack_client = nullptr; | |||
| } | |||
| return false; | |||
| } | |||
| void carla_jack_shutdown_callback(void*) | |||
| bool carla_jack_close() | |||
| { | |||
| for (unsigned short i=0; i<MAX_PLUGINS; i++) | |||
| if (carla_client_name) | |||
| free((void*)carla_client_name); | |||
| if (jack_deactivate(carla_jack_client) == 0) | |||
| { | |||
| //CarlaPlugin* plugin = CarlaPlugins[i]; | |||
| //if (plugin && plugin->id() == plugin_id) | |||
| // plugin->jack_client = nullptr; | |||
| 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; | |||
| callback_action(CALLBACK_QUIT, 0, 0, 0, 0.0f); | |||
| 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_process_callback(*client, carla_jack_process_callback, nullptr); | |||
| jack_on_shutdown(*client, carla_jack_shutdown_callback, nullptr); | |||
| if (jack_activate(*client) == 0) | |||
| return true; | |||
| #else | |||
| jack_set_process_callback(*client, carla_jack_process_callback, plugin); | |||
| return true; | |||
| #endif | |||
| } | |||
| return false; | |||
| } | |||
| @@ -0,0 +1,32 @@ | |||
| /* | |||
| * 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_includes.h" | |||
| #include <jack/jack.h> | |||
| #include <jack/midiport.h> | |||
| class CarlaPlugin; | |||
| int carla_jack_bufsize_callback(jack_nframes_t new_buffer_size, void* arg); | |||
| int carla_jack_srate_callback(jack_nframes_t new_sample_rate, void* arg); | |||
| int carla_jack_process_callback(jack_nframes_t nframes, void* arg); | |||
| void carla_jack_shutdown_callback(void* arg); | |||
| bool carla_jack_init(const char* client_name); | |||
| bool carla_jack_close(); | |||
| bool carla_jack_register_plugin(CarlaPlugin* plugin, jack_client_t** client); | |||
| @@ -18,22 +18,28 @@ | |||
| #include "carla_osc.h" | |||
| #include "carla_plugin.h" | |||
| // FIXME - check for std::isdigit() elsewhere | |||
| #include <iostream> | |||
| size_t client_name_len = 0; | |||
| const char* global_osc_server_path = nullptr; | |||
| lo_server_thread global_osc_server_thread = nullptr; | |||
| OscData global_osc_data = { nullptr, nullptr, nullptr }; | |||
| // Global variables | |||
| extern const char* carla_client_name; | |||
| size_t client_name_len; | |||
| // ------------------------------------------------------------------------------------------------------------------- | |||
| // Exported symbols (API) | |||
| // Global OSC stuff | |||
| extern lo_server_thread global_osc_server_thread; | |||
| extern const char* global_osc_server_path; | |||
| extern OscData global_osc_data; | |||
| const char* get_host_osc_url() | |||
| { | |||
| qDebug("get_host_osc_url()"); | |||
| return global_osc_server_path; | |||
| } | |||
| // End of exported symbols (API) | |||
| // ------------------------------------------------------------------------------------------------------------------- | |||
| void osc_init() | |||
| { | |||
| qDebug("osc_init()"); | |||
| client_name_len = strlen(carla_client_name); | |||
| const char* host_client_name = get_host_client_name(); | |||
| client_name_len = strlen(host_client_name); | |||
| // create new OSC thread | |||
| global_osc_server_thread = lo_server_thread_new(nullptr, osc_error_handler); | |||
| @@ -43,7 +49,7 @@ void osc_init() | |||
| char osc_path_tmp[strlen(osc_thread_path) + client_name_len + 1]; | |||
| strcpy(osc_path_tmp, osc_thread_path); | |||
| strcat(osc_path_tmp, carla_client_name); | |||
| strcat(osc_path_tmp, host_client_name); | |||
| free(osc_thread_path); | |||
| global_osc_server_path = strdup(osc_path_tmp); | |||
| @@ -88,6 +94,8 @@ void osc_clear_data(OscData* osc_data) | |||
| osc_data->target = nullptr; | |||
| } | |||
| // ------------------------------------------------------------------------------------------------------------------- | |||
| void osc_error_handler(int num, const char* msg, const char* path) | |||
| { | |||
| qCritical("osc_error_handler(%i, %s, %s)", num, msg, path); | |||
| @@ -95,7 +103,7 @@ void osc_error_handler(int num, const char* msg, const char* path) | |||
| int osc_message_handler(const char* path, const char* types, lo_arg** argv, int argc, void* data, void* user_data) | |||
| { | |||
| //qDebug("osc_message_handler(%s, %s, %p, %i, %p, %p)", path, types, argv, argc, data, user_data); | |||
| qDebug("osc_message_handler(%s, %s, %p, %i, %p, %p)", path, types, argv, argc, data, user_data); | |||
| // Initial path check | |||
| if (strcmp(path, "register") == 0) | |||
| @@ -111,9 +119,9 @@ int osc_message_handler(const char* path, const char* types, lo_arg** argv, int | |||
| else | |||
| { | |||
| // Check if message is for this client | |||
| if (strncmp(path+1, carla_client_name, client_name_len) != 0 && path[client_name_len+1] == '/') | |||
| if (strncmp(path+1, get_host_client_name(), client_name_len) != 0 && path[client_name_len+1] == '/') | |||
| { | |||
| qWarning("osc_message_handler() - message not for this client -> '%s'' != '/%s/'", path, carla_client_name); | |||
| qWarning("osc_message_handler() - message not for this client -> '%s'' != '/%s/'", path, get_host_client_name()); | |||
| return 1; | |||
| } | |||
| } | |||
| @@ -230,6 +238,8 @@ int osc_message_handler(const char* path, const char* types, lo_arg** argv, int | |||
| Q_UNUSED(user_data); | |||
| } | |||
| // ------------------------------------------------------------------------------------------------------------------- | |||
| int osc_handle_register(lo_arg** argv, lo_address source) | |||
| { | |||
| qDebug("osc_handle_register()"); | |||
| @@ -257,9 +267,9 @@ 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) | |||
| osc_new_plugin(plugin); | |||
| //CarlaPlugin* plugin = CarlaPlugins[i]; | |||
| //if (plugin && plugin->id() >= 0) | |||
| // osc_new_plugin(plugin); | |||
| } | |||
| return 0; | |||
| @@ -285,6 +295,131 @@ int osc_handle_unregister() | |||
| return 1; | |||
| } | |||
| // ------------------------------------------------------------------------------------------------------------------- | |||
| int osc_handle_update(CarlaPlugin* plugin, lo_arg** argv, lo_address source) | |||
| { | |||
| qDebug("osc_handle_update()"); | |||
| const char* url = (const char*)&argv[0]->s; | |||
| plugin->update_osc_data(source, url); | |||
| return 0; | |||
| } | |||
| int osc_handle_configure(CarlaPlugin* plugin, lo_arg** argv) | |||
| { | |||
| qDebug("osc_handle_configure()"); | |||
| const char* key = (const char*)&argv[0]->s; | |||
| const char* value = (const char*)&argv[1]->s; | |||
| plugin->set_custom_data(CUSTOM_DATA_STRING, key, value, false); | |||
| return 0; | |||
| } | |||
| int osc_handle_control(CarlaPlugin* plugin, lo_arg** argv) | |||
| { | |||
| qDebug("osc_handle_control()"); | |||
| int32_t rindex = argv[0]->i; | |||
| double value = argv[1]->f; | |||
| int32_t parameter_id = -1; | |||
| for (uint32_t i=0; i < plugin->param_count(); i++) | |||
| { | |||
| if (plugin->param_data(i)->rindex == rindex) | |||
| { | |||
| parameter_id = i; | |||
| break; | |||
| } | |||
| } | |||
| if (parameter_id >= 0) | |||
| plugin->set_parameter_value(parameter_id, value, false, true, true); | |||
| return 0; | |||
| } | |||
| int osc_handle_program(CarlaPlugin* plugin, lo_arg** argv) | |||
| { | |||
| qDebug("osc_handle_program()"); | |||
| uint32_t program_id = argv[0]->i; | |||
| if (program_id < plugin->prog_count()) | |||
| { | |||
| plugin->set_program(program_id, false, true, true, true); | |||
| return 0; | |||
| } | |||
| else | |||
| qCritical("osc_handle_program() - program_id '%i' out of bounds", program_id); | |||
| return 1; | |||
| } | |||
| int osc_handle_program_as_midi(CarlaPlugin* plugin, lo_arg** /*argv*/) | |||
| { | |||
| qDebug("osc_handle_program_as_midi()"); | |||
| //uint32_t bank_id = argv[0]->i; | |||
| //uint32_t program_id = argv[1]->i; | |||
| for (uint32_t i=0; i < plugin->midiprog_count(); i++) | |||
| { | |||
| //if (plugin->midiprog_data(i).bank == bank_id && plugin->midiprog.data[i].program == program_id) | |||
| //{ | |||
| // plugin->set_midi_program(i, false, true, true, false); | |||
| // return 0; | |||
| //} | |||
| } | |||
| qCritical("osc_handle_program_as_midi() - failed to find respective bank/program"); | |||
| return 1; | |||
| } | |||
| int osc_handle_midi(CarlaPlugin *plugin, lo_arg **argv) | |||
| { | |||
| qDebug("osc_handle_midi()"); | |||
| //if (plugin->min_count() > 0) | |||
| //{ | |||
| uint8_t* data = argv[0]->m; | |||
| uint8_t mode = data[1] & 0xff; | |||
| uint8_t note = data[2] & 0x7f; | |||
| uint8_t velo = data[3] & 0x7f; | |||
| // only receive notes | |||
| if (mode < 0x80 || mode > 0x9F) | |||
| return 1; | |||
| // fix bad note off | |||
| if (mode >= 0x90 && velo == 0) | |||
| { | |||
| mode -= 0x10; | |||
| velo = 0x64; | |||
| } | |||
| plugin->send_midi_note((mode >= 0x90), note, velo, false, true, true); | |||
| //} | |||
| return 0; | |||
| } | |||
| int osc_handle_exiting(CarlaPlugin* plugin) | |||
| { | |||
| qDebug("osc_handle_exiting()"); | |||
| // TODO - check for non-UIs (dssi-vst) and set to -1 instead | |||
| callback_action(CALLBACK_SHOW_GUI, plugin->id(), 0, 0, 0.0); | |||
| osc_clear_data(plugin->osc_data()); | |||
| return 0; | |||
| } | |||
| // ------------------------------------------------------------------------------------------------------------------- | |||
| int osc_handle_set_active(CarlaPlugin* plugin, lo_arg** argv) | |||
| { | |||
| qDebug("osc_handle_set_active()"); | |||
| @@ -396,148 +531,127 @@ int osc_handle_bridge_aouts_peak(CarlaPlugin* plugin, lo_arg** argv) | |||
| return 0; | |||
| } | |||
| int osc_handle_update(CarlaPlugin* plugin, lo_arg** argv, lo_address source) | |||
| { | |||
| qDebug("osc_handle_update()"); | |||
| const char* url = (const char*)&argv[0]->s; | |||
| plugin->update_osc_data(source, url); | |||
| // ------------------------------------------------------------------------------------------------------------------- | |||
| return 0; | |||
| void osc_send_configure(OscData* osc_data, const char* key, const char* value) | |||
| { | |||
| qDebug("osc_send_configure(%s, %s)", key, value); | |||
| if (osc_data->target) | |||
| { | |||
| char target_path[strlen(osc_data->path)+11]; | |||
| strcpy(target_path, osc_data->path); | |||
| strcat(target_path, "/configure"); | |||
| lo_send(osc_data->target, target_path, "ss", key, value); | |||
| } | |||
| } | |||
| int osc_handle_configure(CarlaPlugin* plugin, lo_arg** argv) | |||
| void osc_send_control(OscData* osc_data, int param, double value) | |||
| { | |||
| //qDebug("osc_handle_configure()"); | |||
| const char* key = (const char*)&argv[0]->s; | |||
| const char* value = (const char*)&argv[1]->s; | |||
| plugin->set_custom_data(CUSTOM_DATA_STRING, key, value, false); | |||
| return 0; | |||
| qDebug("osc_send_control(%i, %f)", param, value); | |||
| if (osc_data->target) | |||
| { | |||
| char target_path[strlen(osc_data->path)+9]; | |||
| strcpy(target_path, osc_data->path); | |||
| strcat(target_path, "/control"); | |||
| lo_send(osc_data->target, target_path, "if", param, value); | |||
| } | |||
| } | |||
| int osc_handle_control(CarlaPlugin* plugin, lo_arg** argv) | |||
| void osc_send_program(OscData* osc_data, int program_id) | |||
| { | |||
| qDebug("osc_handle_control()"); | |||
| int32_t rindex = argv[0]->i; | |||
| double value = argv[1]->f; | |||
| int32_t parameter_id = -1; | |||
| for (uint32_t i=0; i < plugin->param_count(); i++) | |||
| qDebug("osc_send_program(%i)", program_id); | |||
| if (osc_data->target) | |||
| { | |||
| if (plugin->param_data(i)->rindex == rindex) | |||
| { | |||
| parameter_id = i; | |||
| break; | |||
| } | |||
| char target_path[strlen(osc_data->path)+9]; | |||
| strcpy(target_path, osc_data->path); | |||
| strcat(target_path, "/program"); | |||
| lo_send(osc_data->target, target_path, "i", program_id); | |||
| } | |||
| if (parameter_id >= 0) | |||
| plugin->set_parameter_value(parameter_id, value, false, true, true); | |||
| return 0; | |||
| } | |||
| int osc_handle_program(CarlaPlugin* plugin, lo_arg** argv) | |||
| void osc_send_program_as_midi(OscData* osc_data, int bank, int program) | |||
| { | |||
| qDebug("osc_handle_program()"); | |||
| uint32_t program_id = argv[0]->i; | |||
| if (program_id < plugin->prog_count()) | |||
| qDebug("osc_send_program_as_midi(%i, %i)", bank, program); | |||
| if (osc_data->target) | |||
| { | |||
| plugin->set_program(program_id, false, true, true, true); | |||
| return 0; | |||
| char target_path[strlen(osc_data->path)+9]; | |||
| strcpy(target_path, osc_data->path); | |||
| strcat(target_path, "/program"); | |||
| lo_send(osc_data->target, target_path, "ii", bank, program); | |||
| } | |||
| else | |||
| qCritical("osc_handle_program() - program_id '%i' out of bounds", program_id); | |||
| return 1; | |||
| } | |||
| int osc_handle_program_as_midi(CarlaPlugin* plugin, lo_arg** /*argv*/) | |||
| void osc_send_midi_program(OscData* osc_data, int bank, int program) | |||
| { | |||
| qDebug("osc_handle_program_as_midi()"); | |||
| //uint32_t bank_id = argv[0]->i; | |||
| //uint32_t program_id = argv[1]->i; | |||
| for (uint32_t i=0; i < plugin->midiprog_count(); i++) | |||
| qDebug("osc_send_midi_program(%i, %i)", bank, program); | |||
| if (osc_data->target) | |||
| { | |||
| //if (plugin->midiprog_data(i).bank == bank_id && plugin->midiprog.data[i].program == program_id) | |||
| //{ | |||
| // plugin->set_midi_program(i, false, true, true, false); | |||
| // return 0; | |||
| //} | |||
| char target_path[strlen(osc_data->path)+9]; | |||
| strcpy(target_path, osc_data->path); | |||
| strcat(target_path, "/midi_program"); | |||
| lo_send(osc_data->target, target_path, "ii", bank, program); | |||
| } | |||
| qCritical("osc_handle_program_as_midi() - failed to find respective bank/program"); | |||
| return 1; | |||
| } | |||
| int osc_handle_midi(CarlaPlugin *plugin, lo_arg **argv) | |||
| void osc_send_show(OscData* osc_data) | |||
| { | |||
| qDebug("osc_handle_midi()"); | |||
| //if (plugin->min_count() > 0) | |||
| //{ | |||
| uint8_t* data = argv[0]->m; | |||
| uint8_t mode = data[1] & 0xff; | |||
| uint8_t note = data[2] & 0x7f; | |||
| uint8_t velo = data[3] & 0x7f; | |||
| // only receive notes | |||
| if (mode < 0x80 || mode > 0x9F) | |||
| return 1; | |||
| // fix bad note off | |||
| if (mode >= 0x90 && velo == 0) | |||
| { | |||
| mode -= 0x10; | |||
| velo = 0x64; | |||
| } | |||
| plugin->send_midi_note((mode >= 0x90), note, velo, false, true, true); | |||
| //} | |||
| return 0; | |||
| qDebug("osc_send_show()"); | |||
| if (osc_data->target) | |||
| { | |||
| char target_path[strlen(osc_data->path)+6]; | |||
| strcpy(target_path, osc_data->path); | |||
| strcat(target_path, "/show"); | |||
| lo_send(osc_data->target, target_path, ""); | |||
| } | |||
| } | |||
| int osc_handle_exiting(CarlaPlugin* plugin) | |||
| void osc_send_hide(OscData* osc_data) | |||
| { | |||
| qDebug("osc_handle_exiting()"); | |||
| // TODO - check for non-UIs (dssi-vst) and set to -1 instead | |||
| callback_action(CALLBACK_SHOW_GUI, plugin->id(), 0, 0, 0.0); | |||
| osc_clear_data(plugin->osc_data()); | |||
| qDebug("osc_send_hide()"); | |||
| if (osc_data->target) | |||
| { | |||
| char target_path[strlen(osc_data->path)+6]; | |||
| strcpy(target_path, osc_data->path); | |||
| strcat(target_path, "/hide"); | |||
| lo_send(osc_data->target, target_path, ""); | |||
| } | |||
| } | |||
| return 0; | |||
| void osc_send_quit(OscData* osc_data) | |||
| { | |||
| qDebug("osc_send_quit()"); | |||
| if (osc_data->target) | |||
| { | |||
| char target_path[strlen(osc_data->path)+6]; | |||
| strcpy(target_path, osc_data->path); | |||
| strcat(target_path, "/quit"); | |||
| lo_send(osc_data->target, target_path, ""); | |||
| } | |||
| } | |||
| void osc_new_plugin(CarlaPlugin* plugin) | |||
| // ------------------------------------------------------------------------------------------------------------------- | |||
| void osc_new_plugin(CarlaPlugin* /*plugin*/) | |||
| { | |||
| qDebug("osc_new_plugin()"); | |||
| if (global_osc_data.target) | |||
| { | |||
| osc_send_add_plugin(&global_osc_data, plugin->id(), plugin->name()); | |||
| //osc_send_add_plugin(&global_osc_data, plugin->id(), plugin->name()); | |||
| PluginInfo* info = get_plugin_info(plugin->id()); | |||
| //PluginInfo* info = get_plugin_info(plugin->id()); | |||
| PortCountInfo* audio_info = get_audio_port_count_info(plugin->id()); | |||
| PortCountInfo* midi_info = get_midi_port_count_info(plugin->id()); | |||
| PortCountInfo* param_info = get_parameter_count_info(plugin->id()); | |||
| //PortCountInfo* audio_info = get_audio_port_count_info(plugin->id()); | |||
| //PortCountInfo* midi_info = get_midi_port_count_info(plugin->id()); | |||
| //PortCountInfo* param_info = get_parameter_count_info(plugin->id()); | |||
| osc_send_set_plugin_data(&global_osc_data, plugin->id(), info->type, info->category, info->hints, | |||
| get_real_plugin_name(plugin->id()), info->label, info->maker, info->copyright, info->unique_id); | |||
| //osc_send_set_plugin_data(&global_osc_data, plugin->id(), info->type, info->category, info->hints, | |||
| // get_real_plugin_name(plugin->id()), info->label, info->maker, info->copyright, info->unique_id); | |||
| osc_send_set_plugin_ports(&global_osc_data, plugin->id(), | |||
| audio_info->ins, audio_info->outs, | |||
| midi_info->ins, midi_info->outs, | |||
| param_info->ins, param_info->outs, param_info->total); | |||
| //osc_send_set_plugin_ports(&global_osc_data, plugin->id(), | |||
| // audio_info->ins, audio_info->outs, | |||
| // midi_info->ins, midi_info->outs, | |||
| // param_info->ins, param_info->outs, param_info->total); | |||
| //osc_send_set_parameter_value(&global_osc_data, plugin->id, PARAMETER_ACTIVE, plugin->active ? 1.0f : 0.0f); | |||
| //osc_send_set_parameter_value(&global_osc_data, plugin->id, PARAMETER_DRYWET, plugin->x_drywet); | |||
| @@ -545,32 +659,32 @@ void osc_new_plugin(CarlaPlugin* plugin) | |||
| //osc_send_set_parameter_value(&global_osc_data, plugin->id, PARAMETER_BALANCE_LEFT, plugin->x_bal_left); | |||
| //osc_send_set_parameter_value(&global_osc_data, plugin->id, PARAMETER_BALANCE_RIGHT, plugin->x_bal_right); | |||
| uint32_t i; | |||
| // uint32_t i; | |||
| if (plugin->param_count() > 0 && plugin->param_count() < 200) | |||
| { | |||
| for (i=0; i < plugin->param_count(); i++) | |||
| { | |||
| ParameterInfo* info = get_parameter_info(plugin->id(), i); | |||
| ParameterData* data = plugin->param_data(i); | |||
| ParameterRanges* ranges = plugin->param_ranges(i); | |||
| osc_send_set_parameter_data(&global_osc_data, plugin->id(), i, data->type, data->hints, | |||
| info->name, info->label, | |||
| plugin->get_current_parameter_value(i), | |||
| ranges->min, ranges->max, ranges->def, | |||
| ranges->step, ranges->step_small, ranges->step_large); | |||
| } | |||
| } | |||
| // if (plugin->param_count() > 0 && plugin->param_count() < 200) | |||
| // { | |||
| // for (i=0; i < plugin->param_count(); i++) | |||
| // { | |||
| // ParameterInfo* info = get_parameter_info(plugin->id(), i); | |||
| // ParameterData* data = plugin->param_data(i); | |||
| // ParameterRanges* ranges = plugin->param_ranges(i); | |||
| osc_send_set_program_count(&global_osc_data, plugin->id(), plugin->prog_count()); | |||
| // osc_send_set_parameter_data(&global_osc_data, plugin->id(), i, data->type, data->hints, | |||
| // info->name, info->label, | |||
| // plugin->get_current_parameter_value(i), | |||
| // ranges->min, ranges->max, ranges->def, | |||
| // ranges->step, ranges->step_small, ranges->step_large); | |||
| // } | |||
| // } | |||
| //osc_send_set_program_count(&global_osc_data, plugin->id(), plugin->prog_count()); | |||
| //for (i=0; i < plugin->prog_count(); i++) | |||
| // osc_send_set_program_name(&global_osc_data, plugin->id, i, plugin->prog.names[i]); | |||
| //osc_send_set_program(&global_osc_data, plugin->id, plugin->prog.current); | |||
| osc_send_set_midi_program_count(&global_osc_data, plugin->id(), plugin->midiprog_count()); | |||
| //osc_send_set_midi_program_count(&global_osc_data, plugin->id(), plugin->midiprog_count()); | |||
| //for (i=0; i < plugin->midiprog.count; i++) | |||
| // osc_send_set_program_name(&global_osc_data, plugin->id, i, plugin->midiprog.names[i]); | |||
| @@ -629,7 +743,7 @@ void osc_send_set_plugin_ports(OscData* osc_data, int plugin_id, int ains, int a | |||
| void osc_send_set_parameter_value(OscData* osc_data, int plugin_id, int param_id, double value) | |||
| { | |||
| //qDebug("osc_send_set_parameter_value(%i, %i, %f)", plugin_id, param_id, value); | |||
| qDebug("osc_send_set_parameter_value(%i, %i, %f)", plugin_id, param_id, value); | |||
| if (osc_data->target) | |||
| { | |||
| char target_path[strlen(osc_data->path)+21]; | |||
| @@ -818,99 +932,3 @@ void osc_send_exit(OscData* osc_data) | |||
| lo_send(osc_data->target, target_path, ""); | |||
| } | |||
| } | |||
| void osc_send_configure(OscData* osc_data, const char* key, const char* value) | |||
| { | |||
| qDebug("osc_send_configure(%s, %s)", key, value); | |||
| if (osc_data->target) | |||
| { | |||
| char target_path[strlen(osc_data->path)+11]; | |||
| strcpy(target_path, osc_data->path); | |||
| strcat(target_path, "/configure"); | |||
| lo_send(osc_data->target, target_path, "ss", key, value); | |||
| } | |||
| } | |||
| void osc_send_control(OscData* osc_data, int param, double value) | |||
| { | |||
| //qDebug("osc_send_control(%i, %f)", param, value); | |||
| if (osc_data->target) | |||
| { | |||
| char target_path[strlen(osc_data->path)+9]; | |||
| strcpy(target_path, osc_data->path); | |||
| strcat(target_path, "/control"); | |||
| lo_send(osc_data->target, target_path, "if", param, value); | |||
| } | |||
| } | |||
| void osc_send_program(OscData* osc_data, int program_id) | |||
| { | |||
| qDebug("osc_send_program(%i)", program_id); | |||
| if (osc_data->target) | |||
| { | |||
| char target_path[strlen(osc_data->path)+9]; | |||
| strcpy(target_path, osc_data->path); | |||
| strcat(target_path, "/program"); | |||
| lo_send(osc_data->target, target_path, "i", program_id); | |||
| } | |||
| } | |||
| void osc_send_program_as_midi(OscData* osc_data, int bank, int program) | |||
| { | |||
| qDebug("osc_send_program_as_midi(%i, %i)", bank, program); | |||
| if (osc_data->target) | |||
| { | |||
| char target_path[strlen(osc_data->path)+9]; | |||
| strcpy(target_path, osc_data->path); | |||
| strcat(target_path, "/program"); | |||
| lo_send(osc_data->target, target_path, "ii", bank, program); | |||
| } | |||
| } | |||
| void osc_send_midi_program(OscData* osc_data, int bank, int program) | |||
| { | |||
| qDebug("osc_send_midi_program(%i, %i)", bank, program); | |||
| if (osc_data->target) | |||
| { | |||
| char target_path[strlen(osc_data->path)+9]; | |||
| strcpy(target_path, osc_data->path); | |||
| strcat(target_path, "/midi_program"); | |||
| lo_send(osc_data->target, target_path, "ii", bank, program); | |||
| } | |||
| } | |||
| void osc_send_show(OscData* osc_data) | |||
| { | |||
| qDebug("osc_send_show()"); | |||
| if (osc_data->target) | |||
| { | |||
| char target_path[strlen(osc_data->path)+6]; | |||
| strcpy(target_path, osc_data->path); | |||
| strcat(target_path, "/show"); | |||
| lo_send(osc_data->target, target_path, ""); | |||
| } | |||
| } | |||
| void osc_send_hide(OscData* osc_data) | |||
| { | |||
| qDebug("osc_send_hide()"); | |||
| if (osc_data->target) | |||
| { | |||
| char target_path[strlen(osc_data->path)+6]; | |||
| strcpy(target_path, osc_data->path); | |||
| strcat(target_path, "/hide"); | |||
| lo_send(osc_data->target, target_path, ""); | |||
| } | |||
| } | |||
| void osc_send_quit(OscData* osc_data) | |||
| { | |||
| qDebug("osc_send_quit()"); | |||
| if (osc_data->target) | |||
| { | |||
| char target_path[strlen(osc_data->path)+6]; | |||
| strcpy(target_path, osc_data->path); | |||
| strcat(target_path, "/quit"); | |||
| lo_send(osc_data->target, target_path, ""); | |||
| } | |||
| } | |||
| @@ -19,6 +19,7 @@ | |||
| #define CARLA_OSC_H | |||
| #include "carla_includes.h" | |||
| #include <lo/lo.h> | |||
| class CarlaPlugin; | |||
| @@ -34,11 +35,19 @@ void osc_close(); | |||
| void osc_clear_data(OscData* osc_data); | |||
| void osc_error_handler(int num, const char* msg, const char* path); | |||
| int osc_message_handler(const char* path, const char* types, lo_arg** argv, int argc, void* data, void* user_data); | |||
| int osc_message_handler(const char* path, const char* types, lo_arg** argv, int argc, void* data, void* user_data); | |||
| int osc_handle_register(lo_arg** argv, lo_address source); | |||
| int osc_handle_unregister(); | |||
| int osc_handle_update(CarlaPlugin* plugin, lo_arg** argv, lo_address source); | |||
| int osc_handle_configure(CarlaPlugin* plugin, lo_arg** argv); | |||
| int osc_handle_control(CarlaPlugin* plugin, lo_arg** argv); | |||
| int osc_handle_program(CarlaPlugin* plugin, lo_arg** argv); | |||
| int osc_handle_program_as_midi(CarlaPlugin* plugin, lo_arg** argv); | |||
| int osc_handle_midi(CarlaPlugin* plugin, lo_arg** argv); | |||
| int osc_handle_exiting(CarlaPlugin* plugin); | |||
| int osc_handle_set_active(CarlaPlugin* plugin, lo_arg** argv); | |||
| int osc_handle_set_drywet(CarlaPlugin* plugin, lo_arg** argv); | |||
| int osc_handle_set_volume(CarlaPlugin* plugin, lo_arg** argv); | |||
| @@ -51,36 +60,6 @@ int osc_handle_note_off(CarlaPlugin* plugin, lo_arg** argv); | |||
| int osc_handle_bridge_ains_peak(CarlaPlugin* plugin, lo_arg** argv); | |||
| int osc_handle_bridge_aouts_peak(CarlaPlugin* plugin, lo_arg** argv); | |||
| int osc_handle_update(CarlaPlugin* plugin, lo_arg** argv, lo_address source); | |||
| int osc_handle_configure(CarlaPlugin* plugin, lo_arg** argv); | |||
| int osc_handle_control(CarlaPlugin* plugin, lo_arg** argv); | |||
| int osc_handle_program(CarlaPlugin* plugin, lo_arg** argv); | |||
| int osc_handle_program_as_midi(CarlaPlugin* plugin, lo_arg** argv); | |||
| int osc_handle_midi(CarlaPlugin* plugin, lo_arg** argv); | |||
| int osc_handle_exiting(CarlaPlugin* plugin); | |||
| void osc_new_plugin(CarlaPlugin* plugin); | |||
| void osc_send_add_plugin(OscData* osc_data, int plugin_id, const char* plugin_name); | |||
| void osc_send_remove_plugin(OscData* osc_data, int plugin_id); | |||
| void osc_send_set_plugin_data(OscData* osc_data, int plugin_id, int type, int category, int hints, const char* name, const char* label, const char* maker, const char* copyright, long unique_id); | |||
| void osc_send_set_plugin_ports(OscData* osc_data, int plugin_id, int ains, int aouts, int mins, int mouts, int cins, int couts, int ctotals); | |||
| void osc_send_set_parameter_value(OscData* osc_data, int plugin_id, int param_id, double value); | |||
| void osc_send_set_parameter_data(OscData* osc_data, int plugin_id, int param_id, int ptype, int hints, const char* name, const char* label, double current, double x_min, double x_max, double x_def, double x_step, double x_step_small, double x_step_large); | |||
| void osc_send_set_parameter_midi_channel(OscData* osc_data, int plugin_id, int parameter_id, int midi_channel); | |||
| void osc_send_set_parameter_midi_cc(OscData* osc_data, int plugin_id, int parameter_id, int midi_cc); | |||
| void osc_send_set_default_value(OscData* osc_data, int plugin_id, int param_id, double value); | |||
| void osc_send_set_input_peak_value(OscData* osc_data, int plugin_id, int port_id, double value); | |||
| void osc_send_set_output_peak_value(OscData* osc_data, int plugin_id, int port_id, double value); | |||
| void osc_send_set_program(OscData* osc_data, int plugin_id, int program_id); | |||
| void osc_send_set_program_count(OscData* osc_data, int plugin_id, int program_count); | |||
| void osc_send_set_program_name(OscData* osc_data, int plugin_id, int program_id, const char* program_name); | |||
| void osc_send_set_midi_program(OscData* osc_data, int plugin_id, int midi_program_id); | |||
| void osc_send_set_midi_program_count(OscData* osc_data, int plugin_id, int midi_program_count); | |||
| void osc_send_set_midi_program_data(OscData* osc_data, int plugin_id, int midi_program_id, int bank_id, int program_id, const char* midi_program_name); | |||
| void osc_send_note_on(OscData* osc_data, int plugin_id, int note, int velo); | |||
| void osc_send_note_off(OscData* osc_data, int plugin_id, int note); | |||
| void osc_send_exit(OscData* osc_data); | |||
| void osc_send_configure(OscData* osc_data, const char* key, const char* value); | |||
| void osc_send_control(OscData* osc_data, int param_id, double value); | |||
| void osc_send_program(OscData* osc_data, int program_id); | |||
| @@ -90,4 +69,26 @@ void osc_send_show(OscData* osc_data); | |||
| void osc_send_hide(OscData* osc_data); | |||
| void osc_send_quit(OscData* osc_data); | |||
| //void osc_new_plugin(CarlaPlugin* plugin); | |||
| //void osc_send_add_plugin(OscData* osc_data, int plugin_id, const char* plugin_name); | |||
| //void osc_send_remove_plugin(OscData* osc_data, int plugin_id); | |||
| //void osc_send_set_plugin_data(OscData* osc_data, int plugin_id, int type, int category, int hints, const char* name, const char* label, const char* maker, const char* copyright, long unique_id); | |||
| //void osc_send_set_plugin_ports(OscData* osc_data, int plugin_id, int ains, int aouts, int mins, int mouts, int cins, int couts, int ctotals); | |||
| //void osc_send_set_parameter_value(OscData* osc_data, int plugin_id, int param_id, double value); | |||
| //void osc_send_set_parameter_data(OscData* osc_data, int plugin_id, int param_id, int ptype, int hints, const char* name, const char* label, double current, double x_min, double x_max, double x_def, double x_step, double x_step_small, double x_step_large); | |||
| //void osc_send_set_parameter_midi_channel(OscData* osc_data, int plugin_id, int parameter_id, int midi_channel); | |||
| //void osc_send_set_parameter_midi_cc(OscData* osc_data, int plugin_id, int parameter_id, int midi_cc); | |||
| //void osc_send_set_default_value(OscData* osc_data, int plugin_id, int param_id, double value); | |||
| //void osc_send_set_input_peak_value(OscData* osc_data, int plugin_id, int port_id, double value); | |||
| //void osc_send_set_output_peak_value(OscData* osc_data, int plugin_id, int port_id, double value); | |||
| //void osc_send_set_program(OscData* osc_data, int plugin_id, int program_id); | |||
| //void osc_send_set_program_count(OscData* osc_data, int plugin_id, int program_count); | |||
| //void osc_send_set_program_name(OscData* osc_data, int plugin_id, int program_id, const char* program_name); | |||
| //void osc_send_set_midi_program(OscData* osc_data, int plugin_id, int midi_program_id); | |||
| //void osc_send_set_midi_program_count(OscData* osc_data, int plugin_id, int midi_program_count); | |||
| //void osc_send_set_midi_program_data(OscData* osc_data, int plugin_id, int midi_program_id, int bank_id, int program_id, const char* midi_program_name); | |||
| //void osc_send_note_on(OscData* osc_data, int plugin_id, int note, int velo); | |||
| //void osc_send_note_off(OscData* osc_data, int plugin_id, int note); | |||
| //void osc_send_exit(OscData* osc_data); | |||
| #endif // CARLA_OSC_H | |||
| @@ -18,16 +18,14 @@ | |||
| #ifndef CARLA_PLUGIN_H | |||
| #define CARLA_PLUGIN_H | |||
| #include "carla_backend.h" | |||
| #include "carla_jack.h" | |||
| #include "carla_osc.h" | |||
| #include "carla_shared.h" | |||
| #include <cmath> | |||
| #include <cstring> | |||
| //#include <unistd.h> | |||
| #include <jack/jack.h> | |||
| #include <jack/midiport.h> | |||
| #include <QtCore/QList> | |||
| #include <QtCore/QMutex> | |||
| @@ -37,20 +35,9 @@ class CarlaPluginThread; | |||
| const unsigned short MAX_POSTEVENTS = 128; | |||
| // Global JACK client | |||
| extern jack_client_t* carla_jack_client; | |||
| // Global OSC stuff | |||
| extern OscData global_osc_data; | |||
| // jack.cpp | |||
| int carla_jack_process_callback(jack_nframes_t nframes, void* arg); | |||
| #ifdef BUILD_BRIDGE | |||
| int carla_jack_bufsize_callback(jack_nframes_t new_buffer_size, void* arg); | |||
| int carla_jack_srate_callback(jack_nframes_t new_sample_rate, void* arg); | |||
| void carla_jack_shutdown_callback(void* arg); | |||
| #endif | |||
| enum PluginPostEventType { | |||
| PostEventDebug, | |||
| PostEventParameterChange, | |||
| @@ -302,12 +289,12 @@ public: | |||
| return 0; | |||
| } | |||
| uint32_t ain_count() | |||
| virtual uint32_t ain_count() | |||
| { | |||
| return ain.count; | |||
| } | |||
| uint32_t aout_count() | |||
| virtual uint32_t aout_count() | |||
| { | |||
| return aout.count; | |||
| } | |||
| @@ -427,7 +414,7 @@ public: | |||
| Q_UNUSED(pindex); | |||
| } | |||
| void get_audio_port_count_info(PortCountInfo* info) | |||
| virtual void get_audio_port_count_info(PortCountInfo* info) | |||
| { | |||
| info->ins = ain.count; | |||
| info->outs = aout.count; | |||
| @@ -486,7 +473,7 @@ public: | |||
| #ifndef BUILD_BRIDGE | |||
| if (osc_send) | |||
| { | |||
| osc_send_set_parameter_value(&global_osc_data, m_id, PARAMETER_ACTIVE, value); | |||
| //osc_send_set_parameter_value(&global_osc_data, m_id, PARAMETER_ACTIVE, value); | |||
| if (m_hints & PLUGIN_IS_BRIDGE) | |||
| osc_send_control(&osc.data, PARAMETER_ACTIVE, value); | |||
| @@ -509,7 +496,7 @@ public: | |||
| #ifndef BUILD_BRIDGE | |||
| if (osc_send) | |||
| { | |||
| osc_send_set_parameter_value(&global_osc_data, m_id, PARAMETER_DRYWET, value); | |||
| //osc_send_set_parameter_value(&global_osc_data, m_id, PARAMETER_DRYWET, value); | |||
| if (m_hints & PLUGIN_IS_BRIDGE) | |||
| osc_send_control(&osc.data, PARAMETER_DRYWET, value); | |||
| @@ -532,7 +519,7 @@ public: | |||
| #ifndef BUILD_BRIDGE | |||
| if (osc_send) | |||
| { | |||
| osc_send_set_parameter_value(&global_osc_data, m_id, PARAMETER_VOLUME, value); | |||
| //osc_send_set_parameter_value(&global_osc_data, m_id, PARAMETER_VOLUME, value); | |||
| if (m_hints & PLUGIN_IS_BRIDGE) | |||
| osc_send_control(&osc.data, PARAMETER_VOLUME, value); | |||
| @@ -555,7 +542,7 @@ public: | |||
| #ifndef BUILD_BRIDGE | |||
| if (osc_send) | |||
| { | |||
| osc_send_set_parameter_value(&global_osc_data, m_id, PARAMETER_BALANCE_LEFT, value); | |||
| //osc_send_set_parameter_value(&global_osc_data, m_id, PARAMETER_BALANCE_LEFT, value); | |||
| if (m_hints & PLUGIN_IS_BRIDGE) | |||
| osc_send_control(&osc.data, PARAMETER_BALANCE_LEFT, value); | |||
| @@ -578,7 +565,7 @@ public: | |||
| #ifndef BUILD_BRIDGE | |||
| if (osc_send) | |||
| { | |||
| osc_send_set_parameter_value(&global_osc_data, m_id, PARAMETER_BALANCE_RIGHT, value); | |||
| //osc_send_set_parameter_value(&global_osc_data, m_id, PARAMETER_BALANCE_RIGHT, value); | |||
| if (m_hints & PLUGIN_IS_BRIDGE) | |||
| osc_send_control(&osc.data, PARAMETER_BALANCE_RIGHT, value); | |||
| @@ -604,7 +591,7 @@ public: | |||
| #ifndef BUILD_BRIDGE | |||
| if (osc_send) | |||
| { | |||
| osc_send_set_parameter_value(&global_osc_data, m_id, index, value); | |||
| //osc_send_set_parameter_value(&global_osc_data, m_id, index, value); | |||
| if (m_hints & PLUGIN_IS_BRIDGE) | |||
| osc_send_control(&osc.data, index, value); | |||
| @@ -622,8 +609,8 @@ public: | |||
| param.data[index].midi_channel = channel; | |||
| #ifndef BUILD_BRIDGE | |||
| if (m_hints & PLUGIN_IS_BRIDGE) | |||
| osc_send_set_parameter_midi_channel(&osc.data, m_id, index, channel); | |||
| //if (m_hints & PLUGIN_IS_BRIDGE) | |||
| // osc_send_set_parameter_midi_channel(&osc.data, m_id, index, channel); | |||
| #endif | |||
| } | |||
| @@ -632,8 +619,8 @@ public: | |||
| param.data[index].midi_cc = midi_cc; | |||
| #ifndef BUILD_BRIDGE | |||
| if (m_hints & PLUGIN_IS_BRIDGE) | |||
| osc_send_set_parameter_midi_cc(&osc.data, m_id, index, midi_cc); | |||
| //if (m_hints & PLUGIN_IS_BRIDGE) | |||
| // osc_send_set_parameter_midi_cc(&osc.data, m_id, index, midi_cc); | |||
| #endif | |||
| } | |||
| @@ -697,15 +684,15 @@ public: | |||
| param.ranges[i].def = get_current_parameter_value(i); | |||
| #ifndef BUILD_BRIDGE | |||
| if (osc_send) | |||
| osc_send_set_default_value(&global_osc_data, m_id, i, param.ranges[i].def); | |||
| //if (osc_send) | |||
| // osc_send_set_default_value(&global_osc_data, m_id, i, param.ranges[i].def); | |||
| #endif | |||
| } | |||
| #ifndef BUILD_BRIDGE | |||
| if (osc_send) | |||
| { | |||
| osc_send_set_program(&global_osc_data, m_id, prog.current); | |||
| //osc_send_set_program(&global_osc_data, m_id, prog.current); | |||
| if (m_hints & PLUGIN_IS_BRIDGE) | |||
| osc_send_program(&osc.data, prog.current); | |||
| @@ -726,15 +713,15 @@ public: | |||
| param.ranges[i].def = get_current_parameter_value(i); | |||
| #ifndef BUILD_BRIDGE | |||
| if (osc_send) | |||
| osc_send_set_default_value(&global_osc_data, m_id, i, param.ranges[i].def); | |||
| //if (osc_send) | |||
| // osc_send_set_default_value(&global_osc_data, m_id, i, param.ranges[i].def); | |||
| #endif | |||
| } | |||
| #ifndef BUILD_BRIDGE | |||
| if (osc_send) | |||
| { | |||
| osc_send_set_midi_program(&global_osc_data, m_id, midiprog.current); | |||
| //osc_send_set_midi_program(&global_osc_data, m_id, midiprog.current); | |||
| if (m_hints & PLUGIN_IS_BRIDGE) | |||
| osc_send_program(&osc.data, midiprog.current); | |||
| @@ -764,18 +751,18 @@ public: | |||
| #ifndef BUILD_BRIDGE | |||
| if (osc_send) | |||
| { | |||
| if (onoff) | |||
| osc_send_note_on(&global_osc_data, m_id, note, velo); | |||
| else | |||
| osc_send_note_off(&global_osc_data, m_id, note); | |||
| if (m_hints & PLUGIN_IS_BRIDGE) | |||
| { | |||
| if (onoff) | |||
| osc_send_note_on(&osc.data, m_id, note, velo); | |||
| else | |||
| osc_send_note_off(&osc.data, m_id, note); | |||
| } | |||
| //if (onoff) | |||
| // osc_send_note_on(&global_osc_data, m_id, note, velo); | |||
| //else | |||
| // osc_send_note_off(&global_osc_data, m_id, note); | |||
| //if (m_hints & PLUGIN_IS_BRIDGE) | |||
| //{ | |||
| // if (onoff) | |||
| // osc_send_note_on(&osc.data, m_id, note, velo); | |||
| // else | |||
| // osc_send_note_off(&osc.data, m_id, note); | |||
| //} | |||
| } | |||
| #endif | |||
| @@ -1000,33 +987,6 @@ public: | |||
| qDebug("CarlaPlugin::delete_buffers() - end"); | |||
| } | |||
| bool register_jack_plugin() | |||
| { | |||
| #ifndef BUILD_BRIDGE | |||
| if (carla_options.global_jack_client) | |||
| { | |||
| jack_client = carla_jack_client; | |||
| return true; | |||
| } | |||
| else | |||
| #endif | |||
| { | |||
| jack_client = jack_client_open(m_name, JackNullOption, nullptr); | |||
| if (jack_client) | |||
| { | |||
| #ifdef BUILD_BRIDGE | |||
| jack_set_buffer_size_callback(jack_client, carla_jack_bufsize_callback, nullptr); | |||
| jack_set_sample_rate_callback(jack_client, carla_jack_srate_callback, nullptr); | |||
| jack_on_shutdown(jack_client, carla_jack_shutdown_callback, nullptr); | |||
| #endif | |||
| jack_set_process_callback(jack_client, carla_jack_process_callback, this); | |||
| return true; | |||
| } | |||
| return false; | |||
| } | |||
| } | |||
| virtual int set_osc_bridge_info(PluginBridgeInfoType, lo_arg**) | |||
| { | |||
| return 1; | |||
| @@ -0,0 +1,210 @@ | |||
| /* | |||
| * 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_shared.h" | |||
| #include <QtCore/QMutex> | |||
| #include <QtCore/QString> | |||
| // Global variables (shared) | |||
| const char* unique_names[MAX_PLUGINS] = { nullptr }; | |||
| CarlaPlugin* CarlaPlugins[MAX_PLUGINS] = { nullptr }; | |||
| volatile double ains_peak[MAX_PLUGINS*2] = { 0.0 }; | |||
| volatile double aouts_peak[MAX_PLUGINS*2] = { 0.0 }; | |||
| // Global options | |||
| carla_options_t carla_options = { | |||
| /* initiated */ false, | |||
| #ifdef BUILD_BRIDGE | |||
| /* global_jack_client */ false, | |||
| /* use_dssi_chunks */ false, | |||
| /* prefer_ui_bridges */ false | |||
| #else | |||
| /* global_jack_client */ true, | |||
| /* use_dssi_chunks */ false, | |||
| /* prefer_ui_bridges */ true | |||
| #endif | |||
| }; | |||
| CallbackFunc Callback = nullptr; | |||
| const char* last_error = nullptr; | |||
| QMutex carla_proc_lock_var; | |||
| QMutex carla_midi_lock_var; | |||
| // ------------------------------------------------------------------------------------------------------------------- | |||
| // Exported symbols (API) | |||
| void set_callback_function(CallbackFunc func) | |||
| { | |||
| qDebug("set_callback_function(%p)", func); | |||
| Callback = func; | |||
| } | |||
| const char* get_last_error() | |||
| { | |||
| qDebug("get_last_error()"); | |||
| return last_error; | |||
| } | |||
| // End of exported symbols (API) | |||
| // ------------------------------------------------------------------------------------------------------------------- | |||
| const char* bool2str(bool yesno) | |||
| { | |||
| if (yesno) | |||
| return "true"; | |||
| else | |||
| return "false"; | |||
| } | |||
| const char* plugintype2str(PluginType type) | |||
| { | |||
| switch (type) | |||
| { | |||
| case PLUGIN_LADSPA: | |||
| return "LADSPA"; | |||
| case PLUGIN_DSSI: | |||
| return "DSSI"; | |||
| case PLUGIN_LV2: | |||
| return "LV2"; | |||
| case PLUGIN_VST: | |||
| return "VST"; | |||
| case PLUGIN_SF2: | |||
| return "SF2"; | |||
| default: | |||
| return "Unknown"; | |||
| } | |||
| } | |||
| short get_new_plugin_id() | |||
| { | |||
| for (unsigned short i=0; i<MAX_PLUGINS; i++) | |||
| { | |||
| if (CarlaPlugins[i] == nullptr) | |||
| return i; | |||
| } | |||
| return -1; | |||
| } | |||
| const char* get_unique_name(const char* name) | |||
| { | |||
| //int max = jack_port_name_size()/2 - 5; | |||
| //if (carla_options.global_jack_client) | |||
| // max -= strlen(carla_client_name); | |||
| //qDebug("get_unique_name(%s) - truncated to %i", name, max); | |||
| QString qname(name); | |||
| if (qname.isEmpty()) | |||
| qname = "(No name)"; | |||
| //qname.truncate(max); | |||
| //qname.replace(":", "."); // ":" is used in JACK to split client/port names | |||
| for (unsigned short i=0; i<MAX_PLUGINS; i++) | |||
| { | |||
| // Check if unique name already exists | |||
| if (unique_names[i] && qname == unique_names[i]) | |||
| { | |||
| // Check if string has already been modified | |||
| uint len = qname.size(); | |||
| if (qname.at(len-3) == QChar('(') && qname.at(len-2).isDigit() && qname.at(len-1) == QChar(')')) | |||
| { | |||
| int number = qname.at(len-2).toAscii()-'0'; | |||
| if (number == 9) | |||
| // next number is 10, 2 digits | |||
| qname.replace(" (9)", " (10)"); | |||
| else | |||
| qname[len-2] = QChar('0'+number+1); | |||
| continue; | |||
| } | |||
| else if (qname.at(len-4) == QChar('(') && qname.at(len-3).isDigit() && qname.at(len-2).isDigit() && qname.at(len-1) == QChar(')')) | |||
| { | |||
| QChar n2 = qname.at(len-2); // (1x) | |||
| QChar n3 = qname.at(len-3); // (x0) | |||
| if (n2 == QChar('9')) | |||
| { | |||
| n2 = QChar('0'); | |||
| n3 = QChar(n3.toAscii()+1); | |||
| } | |||
| else | |||
| n2 = QChar(n2.toAscii()+1); | |||
| qname[len-2] = n2; | |||
| qname[len-3] = n3; | |||
| continue; | |||
| } | |||
| // Modify string if not | |||
| qname += " (2)"; | |||
| } | |||
| } | |||
| return strdup(qname.toUtf8().constData()); | |||
| } | |||
| void* get_pointer(intptr_t ptr_addr) | |||
| { | |||
| intptr_t* ptr = (intptr_t*)ptr_addr; | |||
| return (void*)ptr; | |||
| } | |||
| void set_last_error(const char* error) | |||
| { | |||
| if (last_error) | |||
| free((void*)last_error); | |||
| if (error) | |||
| last_error = strdup(error); | |||
| else | |||
| last_error = nullptr; | |||
| } | |||
| void carla_proc_lock() | |||
| { | |||
| carla_proc_lock_var.lock(); | |||
| } | |||
| void carla_proc_unlock() | |||
| { | |||
| carla_proc_lock_var.unlock(); | |||
| } | |||
| void carla_midi_lock() | |||
| { | |||
| carla_midi_lock_var.lock(); | |||
| } | |||
| void carla_midi_unlock() | |||
| { | |||
| carla_midi_lock_var.unlock(); | |||
| } | |||
| void callback_action(CallbackType action, unsigned short plugin_id, int value1, int value2, double value3) | |||
| { | |||
| if (Callback) | |||
| Callback(action, plugin_id, value1, value2, value3); | |||
| } | |||
| @@ -0,0 +1,48 @@ | |||
| /* | |||
| * 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 | |||
| */ | |||
| #ifndef CARLA_SHARED_H | |||
| #define CARLA_SHARED_H | |||
| #include "carla_backend.h" | |||
| class CarlaPlugin; | |||
| const char* bool2str(bool yesno); | |||
| const char* plugintype2str(PluginType type); | |||
| short get_new_plugin_id(); | |||
| const char* get_unique_name(const char* name); | |||
| void* get_pointer(intptr_t ptr_addr); | |||
| void set_last_error(const char* error); | |||
| void carla_proc_lock(); | |||
| void carla_proc_unlock(); | |||
| void carla_midi_lock(); | |||
| void carla_midi_unlock(); | |||
| void callback_action(CallbackType action, unsigned short plugin_id, int value1, int value2, double value3); | |||
| // Global variables (shared) | |||
| extern const char* unique_names[MAX_PLUGINS]; | |||
| extern CarlaPlugin* CarlaPlugins[MAX_PLUGINS]; | |||
| extern volatile double ains_peak[MAX_PLUGINS*2]; | |||
| extern volatile double aouts_peak[MAX_PLUGINS*2]; | |||
| // Global options | |||
| extern carla_options_t carla_options; | |||
| #endif // CARLA_SHARED_H | |||
| @@ -63,7 +63,7 @@ void CarlaCheckThread::run() | |||
| break; | |||
| case PostEventParameterChange: | |||
| osc_send_set_parameter_value(&global_osc_data, plugin->id(), post_events[j].index, post_events[j].value); | |||
| //osc_send_set_parameter_value(&global_osc_data, plugin->id(), post_events[j].index, post_events[j].value); | |||
| callback_action(CALLBACK_PARAMETER_CHANGED, plugin->id(), post_events[j].index, 0, post_events[j].value); | |||
| // FIXME - can this happen? | |||
| @@ -73,20 +73,20 @@ void CarlaCheckThread::run() | |||
| break; | |||
| case PostEventProgramChange: | |||
| osc_send_set_program(&global_osc_data, plugin->id(), post_events[j].index); | |||
| //osc_send_set_program(&global_osc_data, plugin->id(), post_events[j].index); | |||
| callback_action(CALLBACK_PROGRAM_CHANGED, plugin->id(), post_events[j].index, 0, 0.0); | |||
| // FIXME - can this happen? | |||
| //if (plugin->hints() & PLUGIN_IS_BRIDGE) | |||
| // osc_send_program(plugin->osc_data(), post_events[j].index); | |||
| for (uint32_t k=0; k < plugin->param_count(); k++) | |||
| osc_send_set_default_value(&global_osc_data, plugin->id(), k, plugin->param_ranges(k)->def); | |||
| //for (uint32_t k=0; k < plugin->param_count(); k++) | |||
| // osc_send_set_default_value(&global_osc_data, plugin->id(), k, plugin->param_ranges(k)->def); | |||
| break; | |||
| case PostEventMidiProgramChange: | |||
| osc_send_set_midi_program(&global_osc_data, plugin->id(), post_events[j].index); | |||
| //osc_send_set_midi_program(&global_osc_data, plugin->id(), post_events[j].index); | |||
| callback_action(CALLBACK_MIDI_PROGRAM_CHANGED, plugin->id(), post_events[j].index, 0, 0.0); | |||
| //if (plugin->type() == PLUGIN_DSSI) | |||
| @@ -96,13 +96,13 @@ void CarlaCheckThread::run() | |||
| //if (plugin->hints & PLUGIN_IS_BRIDGE) | |||
| // osc_send_midi_program(&plugin->osc.data, plugin->midiprog.data[post_events[j].index].bank, plugin->midiprog.data[post_events[j].index].program); | |||
| for (uint32_t k=0; k < plugin->param_count(); k++) | |||
| osc_send_set_default_value(&global_osc_data, plugin->id(), k, plugin->param_ranges(k)->def); | |||
| //for (uint32_t k=0; k < plugin->param_count(); k++) | |||
| // osc_send_set_default_value(&global_osc_data, plugin->id(), k, plugin->param_ranges(k)->def); | |||
| break; | |||
| case PostEventNoteOn: | |||
| osc_send_note_on(&global_osc_data, plugin->id(), post_events[j].index, post_events[j].value); | |||
| //osc_send_note_on(&global_osc_data, plugin->id(), post_events[j].index, post_events[j].value); | |||
| callback_action(CALLBACK_NOTE_ON, plugin->id(), post_events[j].index, post_events[j].value, 0.0); | |||
| // FIXME - can this happen? | |||
| @@ -112,7 +112,7 @@ void CarlaCheckThread::run() | |||
| break; | |||
| case PostEventNoteOff: | |||
| osc_send_note_off(&global_osc_data, plugin->id(), post_events[j].index); | |||
| //osc_send_note_off(&global_osc_data, plugin->id(), post_events[j].index); | |||
| callback_action(CALLBACK_NOTE_OFF, plugin->id(), post_events[j].index, 0, 0.0); | |||
| // FIXME - can this happen? | |||
| @@ -146,7 +146,7 @@ void CarlaCheckThread::run() | |||
| if (update_ports_gui) | |||
| osc_send_control(plugin->osc_data(), plugin->param_data(j)->rindex, value); | |||
| osc_send_set_parameter_value(&global_osc_data, plugin->id(), j, value); | |||
| //osc_send_set_parameter_value(&global_osc_data, plugin->id(), j, value); | |||
| } | |||
| } | |||
| @@ -157,13 +157,13 @@ void CarlaCheckThread::run() | |||
| { | |||
| if (plugin->ain_count() > 0) | |||
| { | |||
| osc_send_set_input_peak_value(&global_osc_data, plugin->id(), 1, ains_peak[ (plugin->id() * 2) + 0 ]); | |||
| osc_send_set_input_peak_value(&global_osc_data, plugin->id(), 2, ains_peak[ (plugin->id() * 2) + 1 ]); | |||
| //osc_send_set_input_peak_value(&global_osc_data, plugin->id(), 1, ains_peak[ (plugin->id() * 2) + 0 ]); | |||
| //osc_send_set_input_peak_value(&global_osc_data, plugin->id(), 2, ains_peak[ (plugin->id() * 2) + 1 ]); | |||
| } | |||
| if (plugin->aout_count() > 0) | |||
| { | |||
| osc_send_set_output_peak_value(&global_osc_data, plugin->id(), 1, aouts_peak[ (plugin->id() * 2) + 0 ]); | |||
| osc_send_set_output_peak_value(&global_osc_data, plugin->id(), 2, aouts_peak[ (plugin->id() * 2) + 1 ]); | |||
| //osc_send_set_output_peak_value(&global_osc_data, plugin->id(), 1, aouts_peak[ (plugin->id() * 2) + 0 ]); | |||
| //osc_send_set_output_peak_value(&global_osc_data, plugin->id(), 2, aouts_peak[ (plugin->id() * 2) + 1 ]); | |||
| } | |||
| } | |||
| } | |||
| @@ -190,10 +190,11 @@ CarlaPluginThread::~CarlaPluginThread() | |||
| delete m_process; | |||
| } | |||
| void CarlaPluginThread::setOscData(const char* binary, const char* label) | |||
| void CarlaPluginThread::setOscData(const char* binary, const char* label, const char* data1) | |||
| { | |||
| m_binary = QString(binary); | |||
| m_label = QString(label); | |||
| m_data1 = QString(data1); | |||
| } | |||
| void CarlaPluginThread::run() | |||
| @@ -203,19 +204,23 @@ void CarlaPluginThread::run() | |||
| switch (m_mode) | |||
| { | |||
| case PLUGIN_THREAD_DSSI_GUI: | |||
| arguments << QString("%1/%2").arg(get_host_osc_url()).arg(m_plugin->id()); | |||
| arguments << m_plugin->filename(); | |||
| arguments << m_label; | |||
| arguments << QString("%1 (GUI)").arg(m_plugin->name()); | |||
| /* osc_url */ arguments << QString("%1/%2").arg(get_host_osc_url()).arg(m_plugin->id()); | |||
| /* filename */ arguments << m_plugin->filename(); | |||
| /* label */ arguments << m_label; | |||
| /* ui-title */ arguments << QString("%1 (GUI)").arg(m_plugin->name()); | |||
| break; | |||
| case PLUGIN_THREAD_LV2_GUI: | |||
| arguments << QString("%1/%2").arg(get_host_osc_url()).arg(m_plugin->id()); | |||
| arguments << m_label; | |||
| arguments << QString("%1 (GUI)").arg(m_plugin->name()); | |||
| //arguments << QString("%1/%2").arg(get_host_osc_url()).arg(m_plugin->id()); | |||
| //arguments << m_label; | |||
| //arguments << QString("%1 (GUI)").arg(m_plugin->name()); | |||
| break; | |||
| case PLUGIN_THREAD_BRIDGE: | |||
| arguments << m_label; | |||
| arguments << QString("%1 (GUI)").arg(m_plugin->name()); | |||
| /* osc_url */ arguments << QString("%1/%2").arg(get_host_osc_url()).arg(m_plugin->id()); | |||
| /* stype */ arguments << m_data1; | |||
| /* filename */ arguments << m_plugin->filename(); | |||
| /* label */ arguments << m_label; | |||
| break; | |||
| default: | |||
| break; | |||
| @@ -253,6 +258,18 @@ void CarlaPluginThread::run() | |||
| break; | |||
| case PLUGIN_THREAD_BRIDGE: | |||
| m_process->waitForFinished(-1); | |||
| if (m_process->exitCode() == 0) | |||
| qDebug("CarlaPluginThread::run() - bridge closed"); | |||
| else | |||
| qDebug("CarlaPluginThread::run() - bridge crashed"); | |||
| qDebug("%s", QString(m_process->readAllStandardOutput()).toUtf8().constData()); | |||
| break; | |||
| default: | |||
| break; | |||
| } | |||
| @@ -19,6 +19,7 @@ | |||
| #define CARLA_THREADS_H | |||
| #include "carla_includes.h" | |||
| #include <QtCore/QThread> | |||
| class QProcess; | |||
| @@ -49,7 +50,7 @@ public: | |||
| CarlaPluginThread(CarlaPlugin* plugin, PluginThreadMode mode); | |||
| ~CarlaPluginThread(); | |||
| void setOscData(const char* binary, const char* label); | |||
| void setOscData(const char* binary, const char* label, const char* data1=""); | |||
| protected: | |||
| virtual void run(); | |||
| @@ -60,6 +61,7 @@ private: | |||
| QString m_binary; | |||
| QString m_label; | |||
| QString m_data1; | |||
| QProcess* m_process; | |||
| }; | |||
| @@ -16,13 +16,11 @@ | |||
| */ | |||
| #include "carla_plugin.h" | |||
| #include "carla_osc.h" | |||
| #include "carla_threads.h" | |||
| #include "dssi/dssi.h" | |||
| #include <QtCore/QByteArray> | |||
| #include <QtCore/QString> | |||
| class DssiPlugin : public CarlaPlugin | |||
| { | |||
| @@ -167,7 +165,7 @@ public: | |||
| { | |||
| if (midiprog.count > 0) | |||
| { | |||
| osc_send_set_program_count(&global_osc_data, m_id, midiprog.count); | |||
| //osc_send_set_program_count(&global_osc_data, m_id, midiprog.count); | |||
| // Parse names | |||
| int j, k, last_str_n = 0; | |||
| @@ -189,7 +187,7 @@ public: | |||
| } | |||
| } | |||
| osc_send_set_program_name(&osc.data, m_id, i, midiprog.names[i]); | |||
| //osc_send_set_program_name(&osc.data, m_id, i, midiprog.names[i]); | |||
| } | |||
| callback_action(CALLBACK_RELOAD_PROGRAMS, m_id, 0, 0, 0.0); | |||
| @@ -651,10 +649,10 @@ public: | |||
| } | |||
| // Update OSC Names | |||
| osc_send_set_midi_program_count(&global_osc_data, m_id, midiprog.count); | |||
| //osc_send_set_midi_program_count(&global_osc_data, m_id, midiprog.count); | |||
| for (i=0; i < midiprog.count; i++) | |||
| osc_send_set_midi_program_data(&global_osc_data, m_id, i, midiprog.data[i].bank, midiprog.data[i].program, midiprog.names[i]); | |||
| //for (i=0; i < midiprog.count; i++) | |||
| // osc_send_set_midi_program_data(&global_osc_data, m_id, i, midiprog.data[i].bank, midiprog.data[i].program, midiprog.names[i]); | |||
| callback_action(CALLBACK_RELOAD_PROGRAMS, m_id, 0, 0, 0.0); | |||
| @@ -1122,7 +1120,7 @@ public: | |||
| m_filename = strdup(filename); | |||
| m_name = get_unique_name(ldescriptor->Name); | |||
| if (register_jack_plugin()) | |||
| if (carla_jack_register_plugin(this, &jack_client)) | |||
| { | |||
| if (extra_stuff) | |||
| { | |||
| @@ -1182,7 +1180,7 @@ short add_plugin_dssi(const char* filename, const char* label, void* extra_stuff | |||
| unique_names[id] = plugin->name(); | |||
| CarlaPlugins[id] = plugin; | |||
| osc_new_plugin(plugin); | |||
| //osc_new_plugin(plugin); | |||
| } | |||
| else | |||
| { | |||
| @@ -902,7 +902,7 @@ public: | |||
| else | |||
| m_name = get_unique_name(descriptor->Name); | |||
| if (register_jack_plugin()) | |||
| if (carla_jack_register_plugin(this, &jack_client)) | |||
| return true; | |||
| else | |||
| set_last_error("Failed to register plugin in JACK"); | |||
| @@ -932,14 +932,10 @@ private: | |||
| short add_plugin_ladspa(const char* filename, const char* label, void* extra_stuff) | |||
| { | |||
| qWarning("HERE 00X"); | |||
| qDebug("add_plugin_ladspa(%s, %s, %p)", filename, label, extra_stuff); | |||
| short id = get_new_plugin_id(); | |||
| qWarning("HERE 00X %i", id); | |||
| if (id >= 0) | |||
| { | |||
| LadspaPlugin* plugin = new LadspaPlugin; | |||
| @@ -953,7 +949,7 @@ short add_plugin_ladspa(const char* filename, const char* label, void* extra_stu | |||
| CarlaPlugins[id] = plugin; | |||
| #ifndef BUILD_BRIDGE | |||
| osc_new_plugin(plugin); | |||
| //osc_new_plugin(plugin); | |||
| #endif | |||
| } | |||
| else | |||
| @@ -312,7 +312,7 @@ public: | |||
| rdf_descriptor = lv2_rdf_dup(rdf_descriptor_); | |||
| if (register_jack_plugin()) | |||
| if (carla_jack_register_plugin(this, &jack_client)) | |||
| return true; | |||
| else | |||
| set_last_error("Failed to register plugin in JACK"); | |||
| @@ -599,7 +599,7 @@ public: | |||
| #endif | |||
| } | |||
| virtual void reload_programs(bool init) | |||
| virtual void reload_programs(bool /*init*/) | |||
| { | |||
| #if 0 | |||
| qDebug("Sf2AudioPlugin::reload_programs(%s)", bool2str(init)); | |||
| @@ -666,7 +666,7 @@ public: | |||
| #endif | |||
| } | |||
| virtual void process(jack_nframes_t nframes) | |||
| virtual void process(jack_nframes_t /*nframes*/) | |||
| { | |||
| #if 0 | |||
| uint32_t i, k; | |||
| @@ -1014,7 +1014,7 @@ public: | |||
| m_label = strdup(label); | |||
| m_name = get_unique_name(label); | |||
| if (register_jack_plugin()) | |||
| if (carla_jack_register_plugin(this, &jack_client)) | |||
| return true; | |||
| else | |||
| set_last_error("Failed to register plugin in JACK"); | |||
| @@ -1072,7 +1072,7 @@ short add_plugin_sf2(const char* filename, const char* label) | |||
| unique_names[id] = plugin->name(); | |||
| CarlaPlugins[id] = plugin; | |||
| osc_new_plugin(plugin); | |||
| //osc_new_plugin(plugin); | |||
| } | |||
| else | |||
| { | |||