diff --git a/source/backend/carla_backend.hpp b/source/backend/carla_backend.hpp index 594517865..35044b44c 100644 --- a/source/backend/carla_backend.hpp +++ b/source/backend/carla_backend.hpp @@ -529,7 +529,8 @@ enum ProcessMode { PROCESS_MODE_SINGLE_CLIENT = 0, //!< Single client mode (dynamic input/outputs as needed by plugins) PROCESS_MODE_MULTIPLE_CLIENTS = 1, //!< Multiple client mode (1 master client + 1 client per plugin) PROCESS_MODE_CONTINUOUS_RACK = 2, //!< Single client, 'rack' mode. Processes plugins in order of id, with forced stereo. - PROCESS_MODE_PATCHBAY = 3 //!< Single client, 'patchbay' mode. + PROCESS_MODE_PATCHBAY = 3, //!< Single client, 'patchbay' mode. + PROCESS_MODE_BRIDGE = 4 //!< Special mode, used in plugin-bridges only. RT buffers come from shared memory in a separate host app. }; /*! diff --git a/source/backend/carla_engine.hpp b/source/backend/carla_engine.hpp index f1142d96a..6059fe6b1 100644 --- a/source/backend/carla_engine.hpp +++ b/source/backend/carla_engine.hpp @@ -577,7 +577,7 @@ public: static CarlaEngine* newDriverByName(const char* const driverName); // ------------------------------------------------------------------- - // Maximum values + // Constant values /*! * Maximum client name size. @@ -592,13 +592,13 @@ public: /*! * Current number of plugins loaded. */ - unsigned int currentPluginCount() const; + int currentPluginCount() const; /*! * Maximum number of loadable plugins allowed. * \note This function returns 0 if engine is not started. */ - unsigned int maxPluginNumber() const; + int maxPluginNumber() const; // ------------------------------------------------------------------- // Virtual, per-engine type calls @@ -679,7 +679,7 @@ public: /*! * Remove plugin with id \a id. */ - bool removePlugin(const unsigned int id); + bool removePlugin(const int id); /*! * Remove all plugins. @@ -838,9 +838,10 @@ public: // ------------------------------------- protected: + uint32_t fBufferSize; + double fSampleRate; + CarlaString fName; - uint32_t fBufferSize; - double fSampleRate; EngineOptions fOptions; EngineTimeInfo fTimeInfo; @@ -953,6 +954,7 @@ public: void osc_send_control_exit(); #endif +private: friend class CarlaEngineEventPort; CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngine) diff --git a/source/backend/carla_native.h b/source/backend/carla_native.h index 0bb7bcd6a..de6e96d60 100644 --- a/source/backend/carla_native.h +++ b/source/backend/carla_native.h @@ -19,7 +19,6 @@ #define __CARLA_NATIVE_H__ #ifdef __cplusplus -# include # include extern "C" { #else diff --git a/source/backend/carla_native.hpp b/source/backend/carla_native.hpp index d38736ac3..f1fd44dbc 100644 --- a/source/backend/carla_native.hpp +++ b/source/backend/carla_native.hpp @@ -1,5 +1,5 @@ /* - * Carla Native Plugin API + * Carla Native Plugin API (C++) * Copyright (C) 2012-2013 Filipe Coelho * * This program is free software; you can redistribute it and/or @@ -30,9 +30,9 @@ class PluginDescriptorClass { public: PluginDescriptorClass(const HostDescriptor* const host) - : fHost(host) + : kHost(host) { - CARLA_ASSERT(fHost); + CARLA_ASSERT(host); } virtual ~PluginDescriptorClass() @@ -44,77 +44,77 @@ public: const HostDescriptor* getHostHandle() const { - return fHost; + return kHost; } uint32_t getBufferSize() const { - CARLA_ASSERT(fHost); + CARLA_ASSERT(kHost); - if (fHost) - return fHost->get_buffer_size(fHost->handle); + if (kHost) + return kHost->get_buffer_size(kHost->handle); return 0; } double getSampleRate() const { - CARLA_ASSERT(fHost); + CARLA_ASSERT(kHost); - if (fHost) - return fHost->get_sample_rate(fHost->handle); + if (kHost) + return kHost->get_sample_rate(kHost->handle); return 0.0; } const TimeInfo* getTimeInfo() const { - CARLA_ASSERT(fHost); + CARLA_ASSERT(kHost); - if (fHost) - return fHost->get_time_info(fHost->handle); + if (kHost) + return kHost->get_time_info(kHost->handle); return nullptr; } void writeMidiEvent(const MidiEvent* const event) { - CARLA_ASSERT(fHost); + CARLA_ASSERT(kHost); - if (fHost) - fHost->write_midi_event(fHost->handle, event); + if (kHost) + kHost->write_midi_event(kHost->handle, event); } void uiParameterChanged(const uint32_t index, const float value) { - CARLA_ASSERT(fHost); + CARLA_ASSERT(kHost); - if (fHost) - fHost->ui_parameter_changed(fHost->handle, index, value); + if (kHost) + kHost->ui_parameter_changed(kHost->handle, index, value); } void uiMidiProgramChanged(const uint32_t bank, const uint32_t program) { - CARLA_ASSERT(fHost); + CARLA_ASSERT(kHost); - if (fHost) - fHost->ui_midi_program_changed(fHost->handle, bank, program); + if (kHost) + kHost->ui_midi_program_changed(kHost->handle, bank, program); } void uiCustomDataChanged(const char* const key, const char* const value) { - CARLA_ASSERT(fHost); + CARLA_ASSERT(kHost); - if (fHost) - fHost->ui_custom_data_changed(fHost->handle, key, value); + if (kHost) + kHost->ui_custom_data_changed(kHost->handle, key, value); } void uiClosed() { - CARLA_ASSERT(fHost); + CARLA_ASSERT(kHost); - if (fHost) - fHost->ui_closed(fHost->handle); + if (kHost) + kHost->ui_closed(kHost->handle); } protected: @@ -271,7 +271,7 @@ protected: // ------------------------------------------------------------------- private: - const HostDescriptor* const fHost; + const HostDescriptor* const kHost; // ------------------------------------------------------------------- diff --git a/source/backend/carla_plugin.hpp b/source/backend/carla_plugin.hpp index d84c304ab..df1475da4 100644 --- a/source/backend/carla_plugin.hpp +++ b/source/backend/carla_plugin.hpp @@ -94,7 +94,7 @@ public: * \param engine The engine which this plugin belongs to, must not be null * \param id The 'id' of this plugin, must be between 0 and CarlaEngine::maxPluginNumber() */ - CarlaPlugin(CarlaEngine* const engine, const unsigned int id); + CarlaPlugin(CarlaEngine* const engine, const int id); /*! * This is the destructor of the base plugin class. @@ -657,13 +657,13 @@ public: * Post pone an event of type \a type.\n * The event will be processed later, but as soon as possible. */ - void postponeEvent(const PluginPostRtEventType type, const int32_t value1, const int32_t value2, const double value3); + void postponeRtEvent(const PluginPostRtEventType type, const int32_t value1, const int32_t value2, const double value3); /*! * Process all the post-poned events. * This function must be called from the main thread (ie, idleGui()) if PLUGIN_USES_SINGLE_THREAD is set. */ - void postEventsRun(); + void postRtEventsRun(); /*! * Tell the UI a parameter has changed. @@ -746,13 +746,13 @@ public: static const PluginDescriptor* getNativePluginDescriptor(const size_t index); static CarlaPlugin* newNative(const Initializer& init); - static CarlaPlugin* newBridge(const Initializer& init, const BinaryType btype, const PluginType ptype, const void* const extra); + static CarlaPlugin* newBridge(const Initializer& init, const BinaryType btype, const PluginType ptype, const char* const bridgeFilename); #endif #ifdef WANT_LADSPA - static CarlaPlugin* newLADSPA(const Initializer& init, const void* const extra); + static CarlaPlugin* newLADSPA(const Initializer& init, const LADSPA_RDF_Descriptor* const rdfDescriptor); #endif #ifdef WANT_DSSI - static CarlaPlugin* newDSSI(const Initializer& init, const void* const extra); + static CarlaPlugin* newDSSI(const Initializer& init, const char* const guiFilename); #endif #ifdef WANT_LV2 static CarlaPlugin* newLV2(const Initializer& init); diff --git a/source/backend/engine/carla_engine.cpp b/source/backend/engine/carla_engine.cpp index 65c55c5ef..cd1ab7537 100644 --- a/source/backend/engine/carla_engine.cpp +++ b/source/backend/engine/carla_engine.cpp @@ -452,12 +452,12 @@ unsigned int CarlaEngine::maxPortNameSize() const return STR_MAX; } -unsigned int CarlaEngine::currentPluginCount() const +int CarlaEngine::currentPluginCount() const { return fData->curPluginCount; } -unsigned int CarlaEngine::maxPluginNumber() const +int CarlaEngine::maxPluginNumber() const { return fData->maxPluginNumber; } @@ -769,16 +769,16 @@ int CarlaEngine::addPlugin(const BinaryType btype, const PluginType ptype, const if (! plugin) return -1; - const unsigned int id = fData->curPluginCount++; + const int id = fData->curPluginCount++; #if 0 plugin->setId(id); #endif - return static_cast(id); + return id; } -bool CarlaEngine::removePlugin(const unsigned int id) +bool CarlaEngine::removePlugin(const int id) { qDebug("CarlaEngine::removePlugin(%i)", id); CARLA_ASSERT(fData->curPluginCount > 0); diff --git a/source/backend/engine/carla_engine_internal.hpp b/source/backend/engine/carla_engine_internal.hpp index cac1423a5..d6148d14f 100644 --- a/source/backend/engine/carla_engine_internal.hpp +++ b/source/backend/engine/carla_engine_internal.hpp @@ -24,8 +24,6 @@ #include "carla_plugin.hpp" -//#include "rt_list.hpp" - #ifndef BUILD_BRIDGE # include #endif @@ -99,7 +97,8 @@ const char* EngineControlEventType2Str(const EngineControlEventType type) * Maximum number of peaks per plugin.\n * \note There are both input and output peaks. */ -/*static*/ const unsigned short MAX_PEAKS = 2; +/*static*/ +const unsigned short MAX_PEAKS = 2; const uint32_t PATCHBAY_BUFFER_SIZE = 128; const unsigned short PATCHBAY_EVENT_COUNT = 512; @@ -151,9 +150,9 @@ struct CarlaEngineProtectedData { QProcessEnvironment procEnv; #endif - bool aboutToClose; // don't re-activate thread if true - unsigned int curPluginCount; // number of plugins loaded (0...max) - unsigned int maxPluginNumber; // number of plugins allowed (0, 16, 99 or 999) + bool aboutToClose; // don't re-activate thread if true + int curPluginCount; // number of plugins loaded (0...max) + int maxPluginNumber; // number of plugins allowed (0, 16, 99 or 999) EnginePluginData* plugins; diff --git a/source/backend/engine/carla_engine_osc.cpp b/source/backend/engine/carla_engine_osc.cpp index ed623908e..3835572e0 100644 --- a/source/backend/engine/carla_engine_osc.cpp +++ b/source/backend/engine/carla_engine_osc.cpp @@ -1,18 +1,18 @@ /* * Carla Engine OSC - * Copyright (C) 2011-2012 Filipe Coelho + * Copyright (C) 2012-2013 Filipe Coelho * - * 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 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 + * 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 + * For a full copy of the GNU General Public License see the GPL.txt file */ #include "carla_engine.hpp" @@ -20,31 +20,27 @@ #include "carla_plugin.hpp" #include "carla_midi.h" -#include - CARLA_BACKEND_START_NAMESPACE // ----------------------------------------------------------------------- -CarlaEngineOsc::CarlaEngineOsc(CarlaEngine* const engine_) - : engine(engine_) +CarlaEngineOsc::CarlaEngineOsc(CarlaEngine* const engine) + : kEngine(engine), + fServerTCP(nullptr), + fServerUDP(nullptr) { qDebug("CarlaEngineOsc::CarlaEngineOsc(%p)", engine); - CARLA_ASSERT(engine); - - m_name = nullptr; - m_nameSize = 0; - - m_serverTCP = nullptr; - m_serverUDP = nullptr; + CARLA_ASSERT(engine != nullptr); } CarlaEngineOsc::~CarlaEngineOsc() { qDebug("CarlaEngineOsc::~CarlaEngineOsc()"); - CARLA_ASSERT(! m_name); - CARLA_ASSERT(! m_serverTCP); - CARLA_ASSERT(! m_serverUDP); + CARLA_ASSERT(fName.isEmpty()); + CARLA_ASSERT(fServerPathTCP.isEmpty()); + CARLA_ASSERT(fServerPathUDP.isEmpty()); + CARLA_ASSERT(fServerTCP == nullptr); + CARLA_ASSERT(fServerUDP == nullptr); } // ----------------------------------------------------------------------- @@ -52,117 +48,115 @@ CarlaEngineOsc::~CarlaEngineOsc() void CarlaEngineOsc::init(const char* const name) { qDebug("CarlaEngineOsc::init(\"%s\")", name); - CARLA_ASSERT(! m_name); - CARLA_ASSERT(! m_serverTCP); - CARLA_ASSERT(! m_serverUDP); - CARLA_ASSERT(m_nameSize == 0); - CARLA_ASSERT(m_serverPathTCP.isEmpty()); - CARLA_ASSERT(m_serverPathUDP.isEmpty()); + CARLA_ASSERT(fName.isEmpty()); + CARLA_ASSERT(fServerPathTCP.isEmpty()); + CARLA_ASSERT(fServerPathUDP.isEmpty()); + CARLA_ASSERT(fServerTCP == nullptr); + CARLA_ASSERT(fServerUDP == nullptr); CARLA_ASSERT(name); - m_name = strdup(name ? name : ""); - m_nameSize = strlen(m_name); + fName = name; + fName.toBasic(); - m_serverTCP = lo_server_new_with_proto(nullptr, LO_TCP, osc_error_handlerTCP); - m_serverUDP = lo_server_new_with_proto(nullptr, LO_UDP, osc_error_handlerUDP); + fServerTCP = lo_server_new_with_proto(nullptr, LO_TCP, osc_error_handler_TCP); - if (m_serverTCP) + if (fServerTCP != nullptr) { - if (char* const serverPathTCP = lo_server_get_url(m_serverTCP)) + if (char* const tmpServerPathTCP = lo_server_get_url(fServerTCP)) { - m_serverPathTCP = serverPathTCP; - m_serverPathTCP += m_name; - free(serverPathTCP); + fServerPathTCP = tmpServerPathTCP; + fServerPathTCP += fName; + free(tmpServerPathTCP); } - lo_server_add_method(m_serverTCP, nullptr, nullptr, osc_message_handler, this); + lo_server_add_method(fServerTCP, nullptr, nullptr, osc_message_handler, this); } - if (m_serverUDP) + fServerUDP = lo_server_new_with_proto(nullptr, LO_UDP, osc_error_handler_UDP); + + if (fServerUDP != nullptr) { - if (char* const serverPathUDP = lo_server_get_url(m_serverUDP)) + if (char* const tmpServerPathUDP = lo_server_get_url(fServerUDP)) { - m_serverPathUDP = serverPathUDP; - m_serverPathUDP += m_name; - free(serverPathUDP); + fServerPathUDP = tmpServerPathUDP; + fServerPathUDP += fName; + free(tmpServerPathUDP); } - lo_server_add_method(m_serverUDP, nullptr, nullptr, osc_message_handler, this); + lo_server_add_method(fServerUDP, nullptr, nullptr, osc_message_handler, this); } } void CarlaEngineOsc::idle() { - if (m_serverTCP) + if (fServerTCP != nullptr) { - while (lo_server_recv_noblock(m_serverTCP, 0) != 0) {} + while (lo_server_recv_noblock(fServerTCP, 0) != 0) {} } - if (m_serverUDP) + if (fServerUDP != nullptr) { - while (lo_server_recv_noblock(m_serverUDP, 0) != 0) {} + while (lo_server_recv_noblock(fServerUDP, 0) != 0) {} } } void CarlaEngineOsc::close() { qDebug("CarlaEngineOsc::close()"); - CARLA_ASSERT(m_name); - CARLA_ASSERT(m_serverTCP); - CARLA_ASSERT(m_serverUDP); - CARLA_ASSERT(m_serverPathTCP.isNotEmpty()); - CARLA_ASSERT(m_serverPathUDP.isNotEmpty()); + CARLA_ASSERT(fName.isNotEmpty()); + CARLA_ASSERT(fServerPathTCP.isNotEmpty()); + CARLA_ASSERT(fServerPathUDP.isNotEmpty()); + CARLA_ASSERT(fServerTCP != nullptr); + CARLA_ASSERT(fServerUDP != nullptr); - m_nameSize = 0; + fName.clear(); - if (m_name) + if (fServerTCP != nullptr) { - free(m_name); - m_name = nullptr; + lo_server_del_method(fServerTCP, nullptr, nullptr); + lo_server_free(fServerTCP); + fServerTCP = nullptr; } - if (m_serverTCP) + if (fServerUDP != nullptr) { - lo_server_del_method(m_serverTCP, nullptr, nullptr); - lo_server_free(m_serverTCP); - m_serverTCP = nullptr; + lo_server_del_method(fServerUDP, nullptr, nullptr); + lo_server_free(fServerUDP); + fServerUDP = nullptr; } - if (m_serverUDP) - { - lo_server_del_method(m_serverUDP, nullptr, nullptr); - lo_server_free(m_serverUDP); - m_serverUDP = nullptr; - } - - m_serverPathTCP.clear(); - m_serverPathUDP.clear(); + fServerPathTCP.clear(); + fServerPathUDP.clear(); #ifndef BUILD_BRIDGE - m_controlData.free(); + fControlData.free(); #endif } // ----------------------------------------------------------------------- +bool isDigit(const char c) +{ + return (c >= '0' && c <= '9'); +} + int CarlaEngineOsc::handleMessage(const char* const path, const int argc, const lo_arg* const* const argv, const char* const types, const lo_message msg) { #if DEBUG - if (! QString(path).endsWith("peak")) - qDebug("CarlaEngineOsc::handleMessage(%s, %i, %p, %s, %p)", path, argc, argv, types, msg); + qDebug("CarlaEngineOsc::handleMessage(%s, %i, %p, %s, %p)", path, argc, argv, types, msg); #endif - CARLA_ASSERT(m_name); - CARLA_ASSERT(m_serverTCP || m_serverUDP); - CARLA_ASSERT(m_serverPathTCP.isNotEmpty() || m_serverPathUDP.isNotEmpty()); - CARLA_ASSERT(path); + CARLA_ASSERT(fName.isNotEmpty()); + CARLA_ASSERT(fServerPathTCP.isNotEmpty() || fServerPathUDP.isNotEmpty()); + CARLA_ASSERT(fServerTCP != nullptr || fServerUDP != nullptr); + CARLA_ASSERT(path != nullptr); - if (! path) + if (path == nullptr) { qCritical("CarlaEngineOsc::handleMessage() - got invalid path"); return 1; } - if (! m_name) + if (fName.isEmpty()) { qCritical("CarlaEngineOsc::handleMessage(\"%s\", ...) - received message but client is offline", path); return 1; @@ -181,43 +175,69 @@ int CarlaEngineOsc::handleMessage(const char* const path, const int argc, const } #endif + const size_t nameSize = fName.length(); + // Check if message is for this client - if (strlen(path) <= m_nameSize || strncmp(path+1, m_name, m_nameSize) != 0) + if (std::strlen(path) <= nameSize || std::strncmp(path+1, (const char*)fName, nameSize) != 0) { - qWarning("CarlaEngineOsc::handleMessage() - message not for this client -> '%s' != '/%s/'", path, m_name); + qWarning("CarlaEngineOsc::handleMessage() - message not for this client -> '%s' != '/%s/'", path, (const char*)fName); return 1; } // Get plugin id from message - int pluginId = 0; + // eg, /carla/23/method - if (std::isdigit(path[m_nameSize+2])) - pluginId += path[m_nameSize+2]-'0'; + int pluginId = -1; - if (std::isdigit(path[m_nameSize+3])) - pluginId += (path[m_nameSize+3]-'0')*10; + if (isDigit(path[nameSize+2])) + { + if (isDigit(path[nameSize+3])) + { + if (isDigit(path[nameSize+5])) + { + qCritical("CarlaEngineOsc::handleMessage() - invalid plugin id, over 999? (value: \"%s\")", path+nameSize); + return 1; + } + else if (isDigit(path[nameSize+4])) + { + // 3 digits, /xyz/method + pluginId += (path[nameSize+2]-'0')*100; + pluginId += (path[nameSize+3]-'0')*10; + pluginId += (path[nameSize+4]-'0'); + } + else + { + // 2 digits, /xy/method + pluginId += (path[nameSize+2]-'0')*10; + pluginId += (path[nameSize+3]-'0'); + } + } + else + { + // single digit, /x/method + pluginId += path[nameSize+2]-'0'; + } + } - if (pluginId < 0 || pluginId > static_cast(engine->currentPluginCount())) + if (pluginId < 0 || pluginId > kEngine->currentPluginCount()) { qCritical("CarlaEngineOsc::handleMessage() - failed to get plugin, wrong id '%i'", pluginId); return 1; } // Get plugin - CarlaPlugin* const plugin = engine->getPluginUnchecked(pluginId); + CarlaPlugin* const plugin = kEngine->getPluginUnchecked(pluginId); -#if 0 if (plugin == nullptr || plugin->id() != pluginId) { qWarning("CarlaEngineOsc::handleMessage() - invalid plugin id '%i', probably has been removed", pluginId); return 1; } -#endif - // Get method from path, "/Carla/i/method" + // Get method from path, "/Carla/i/method" -> "method" const int offset = (pluginId >= 10) ? 5 : 4; char method[32] = { 0 }; - strncpy(method, path + (m_nameSize + offset), 31); + strncpy(method, path + (nameSize + offset), 31); if (method[0] == '\0') { @@ -269,7 +289,7 @@ int CarlaEngineOsc::handleMessage(const char* const path, const int argc, const if (strcmp(method, "note_off") == 0) return handleMsgNoteOff(plugin, argc, argv, types); -#if 0 +#if 0 // FIXME // Plugin Bridges if ((plugin->hints() & PLUGIN_IS_BRIDGE) > 0 && strlen(method) > 11 && strncmp(method, "bridge_", 7) == 0) { @@ -321,14 +341,12 @@ int CarlaEngineOsc::handleMessage(const char* const path, const int argc, const #endif #endif -#if 0 - // Plugin-specific methods -#ifdef WANT_LV2 + // Plugin-specific methods, FIXME +#if 0 //def WANT_LV2 if (strcmp(method, "lv2_atom_transfer") == 0) return handleMsgLv2AtomTransfer(plugin, argc, argv, types); if (strcmp(method, "lv2_event_transfer") == 0) return handleMsgLv2EventTransfer(plugin, argc, argv, types); -#endif #endif qWarning("CarlaEngineOsc::handleMessage() - unsupported OSC method '%s'", method); @@ -402,10 +420,9 @@ int CarlaEngineOsc::handleMsgUpdate(CARLA_ENGINE_OSC_HANDLE_ARGS2, const lo_addr qDebug("CarlaEngineOsc::handleMsgUpdate()"); CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "s"); -#if 0 const char* const url = (const char*)&argv[0]->s; + plugin->updateOscData(source, url); -#endif return 0; } @@ -418,13 +435,8 @@ int CarlaEngineOsc::handleMsgConfigure(CARLA_ENGINE_OSC_HANDLE_ARGS2) const char* const key = (const char*)&argv[0]->s; const char* const value = (const char*)&argv[1]->s; -#ifdef DEBUG - qDebug("CarlaEngineOsc::handleMsgConfigure(\"%s\", \"%s\")", key, value); -#endif - -#if 0 - plugin->setCustomData(CUSTOM_DATA_STRING, key, value, false); -#endif + // FIXME + plugin->setCustomData("CUSTOM_DATA_STRING", key, value, false); return 0; } @@ -434,11 +446,10 @@ int CarlaEngineOsc::handleMsgControl(CARLA_ENGINE_OSC_HANDLE_ARGS2) qDebug("CarlaEngineOsc::handleMsgControl()"); CARLA_ENGINE_OSC_CHECK_OSC_TYPES(2, "if"); -#if 0 - const int rindex = argv[0]->i; - const float value = argv[1]->f; + const int32_t rindex = argv[0]->i; + const float value = argv[1]->f; + plugin->setParameterValueByRIndex(rindex, value, false, true, true); -#endif return 0; } @@ -447,14 +458,14 @@ int CarlaEngineOsc::handleMsgProgram(CARLA_ENGINE_OSC_HANDLE_ARGS2) { qDebug("CarlaEngineOsc::handleMsgProgram()"); -#if 0 if (argc == 2) { CARLA_ENGINE_OSC_CHECK_OSC_TYPES(2, "ii"); - const uint32_t bank_id = argv[0]->i; - const uint32_t program_id = argv[1]->i; - plugin->setMidiProgramById(bank_id, program_id, false, true, true, true); + const uint32_t bank = argv[0]->i; + const uint32_t program = argv[1]->i; + + plugin->setMidiProgramById(bank, program, false, true, true, true); return 0; } @@ -462,17 +473,16 @@ int CarlaEngineOsc::handleMsgProgram(CARLA_ENGINE_OSC_HANDLE_ARGS2) { CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "i"); - const uint32_t program_id = argv[0]->i; + const uint32_t program = argv[0]->i; - if (program_id < plugin->programCount()) + if (program < plugin->programCount()) { - plugin->setProgram(program_id, false, true, true, true); + plugin->setProgram(program, false, true, true, true); return 0; } - qCritical("CarlaEngineOsc::handleMsgProgram() - program_id '%i' out of bounds", program_id); + qCritical("CarlaEngineOsc::handleMsgProgram() - program_id '%i' out of bounds", program); } -#endif return 1; } @@ -482,9 +492,9 @@ int CarlaEngineOsc::handleMsgMidi(CARLA_ENGINE_OSC_HANDLE_ARGS2) qDebug("CarlaEngineOsc::handleMsgMidi()"); CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "m"); -#if 0 if (plugin->midiInCount() > 0) { +#if 0 const uint8_t* const data = argv[0]->m; uint8_t status = data[1]; uint8_t channel = status & 0x0F; @@ -504,10 +514,10 @@ int CarlaEngineOsc::handleMsgMidi(CARLA_ENGINE_OSC_HANDLE_ARGS2) uint8_t velo = data[3]; plugin->sendMidiSingleNote(channel, note, velo, false, true, true); } +#endif return 0; } -#endif qWarning("CarlaEngineOsc::handleMsgMidi() - recived midi when plugin has no midi inputs"); return 1; @@ -517,11 +527,10 @@ int CarlaEngineOsc::handleMsgExiting(CARLA_ENGINE_OSC_HANDLE_ARGS1) { qDebug("CarlaEngineOsc::handleMsgExiting()"); -#if 0 // TODO - check for non-UIs (dssi-vst) and set to -1 instead - engine->callback(CALLBACK_SHOW_GUI, plugin->id(), 0, 0, 0.0, nullptr); + kEngine->callback(CALLBACK_SHOW_GUI, plugin->id(), 0, 0, 0.0, nullptr); + plugin->freeOscData(); -#endif return 0; } diff --git a/source/backend/engine/carla_engine_osc.hpp b/source/backend/engine/carla_engine_osc.hpp index 2263535f5..7b3cd8057 100644 --- a/source/backend/engine/carla_engine_osc.hpp +++ b/source/backend/engine/carla_engine_osc.hpp @@ -66,43 +66,44 @@ public: // ------------------------------------------------------------------- -#ifndef BUILD_BRIDGE - bool isControlRegistered() const + const char* getServerPathTCP() const { - return bool(m_controlData.target); + return (const char*)fServerPathTCP; } - const CarlaOscData* getControlData() const + const char* getServerPathUDP() const { - return &m_controlData; + return (const char*)fServerPathUDP; } -#endif - const char* getServerPathTCP() const + // ------------------------------------------------------------------- + +#ifndef BUILD_BRIDGE + bool isControlRegistered() const { - return (const char*)m_serverPathTCP; + return bool(fControlData.target); } - const char* getServerPathUDP() const + const CarlaOscData* getControlData() const { - return (const char*)m_serverPathUDP; + return &fControlData; } +#endif // ------------------------------------------------------------------- private: - CarlaEngine* const engine; + CarlaEngine* const kEngine; - char* m_name; - size_t m_nameSize; + CarlaString fName; - lo_server m_serverTCP; - lo_server m_serverUDP; - CarlaString m_serverPathTCP; - CarlaString m_serverPathUDP; + CarlaString fServerPathTCP; + CarlaString fServerPathUDP; + lo_server fServerTCP; + lo_server fServerUDP; #ifndef BUILD_BRIDGE - CarlaOscData m_controlData; // for carla-control + CarlaOscData fControlData; // for carla-control #endif // ------------------------------------------------------------------- @@ -146,17 +147,17 @@ private: // ----------------------------------------------------------------------- - static void osc_error_handlerTCP(const int num, const char* const msg, const char* const path) + static void osc_error_handler_TCP(int num, const char* msg, const char* path) { - qWarning("CarlaEngineOsc::osc_error_handlerTCP(%i, \"%s\", \"%s\")", num, msg, path); + qWarning("CarlaEngineOsc::osc_error_handler_TCP(%i, \"%s\", \"%s\")", num, msg, path); } - static void osc_error_handlerUDP(const int num, const char* const msg, const char* const path) + static void osc_error_handler_UDP(int num, const char* msg, const char* path) { - qWarning("CarlaEngineOsc::osc_error_handlerUDP(%i, \"%s\", \"%s\")", num, msg, path); + qWarning("CarlaEngineOsc::osc_error_handler_UDP(%i, \"%s\", \"%s\")", num, msg, path); } - static int osc_message_handler(const char* const path, const char* const types, lo_arg** const argv, const int argc, const lo_message msg, void* const userData) + static int osc_message_handler(const char* path, const char* types, lo_arg** argv, int argc, lo_message msg, void* userData) { CARLA_ASSERT(userData); if (CarlaEngineOsc* const _this_ = (CarlaEngineOsc*)userData) diff --git a/source/backend/engine/carla_engine_thread.cpp b/source/backend/engine/carla_engine_thread.cpp index 4f8513ad0..a2442dbea 100644 --- a/source/backend/engine/carla_engine_thread.cpp +++ b/source/backend/engine/carla_engine_thread.cpp @@ -25,7 +25,7 @@ CARLA_BACKEND_START_NAMESPACE CarlaEngineThread::CarlaEngineThread(CarlaEngine* const engine, QObject* const parent) : QThread(parent), - fEngine(engine) + kEngine(engine) { qDebug("CarlaEngineThread::CarlaEngineThread(%p, %p)", engine, parent); CARLA_ASSERT(engine); @@ -76,28 +76,27 @@ void CarlaEngineThread::stopNow() void CarlaEngineThread::run() { qDebug("CarlaEngineThread::run()"); - CARLA_ASSERT(fEngine->isRunning()); + CARLA_ASSERT(kEngine->isRunning()); bool oscRegisted, usesSingleThread; int i, count; double value; - while (fEngine->isRunning() && ! fStopNow) + while (kEngine->isRunning() && ! fStopNow) { const CarlaMutex::ScopedLocker sl(&fMutex); -#ifndef BUILD_BRIDGE - oscRegisted = fEngine->isOscControlRegistered(); +#ifdef BUILD_BRIDGE + oscRegisted = kEngine->isOscBridgeRegistered(); #else - oscRegisted = fEngine->isOscBridgeRegistered(); + oscRegisted = kEngine->isOscControlRegistered(); #endif - for (i=0, count = fEngine->currentPluginCount(); i < count; i++) + for (i=0, count = kEngine->currentPluginCount(); i < count; i++) { - CarlaPlugin* const plugin = fEngine->getPluginUnchecked(i); + CarlaPlugin* const plugin = kEngine->getPluginUnchecked(i); -#if 0 - if (! (plugin && plugin->enabled())) + if (plugin == nullptr || ! plugin->enabled()) continue; CARLA_ASSERT(i == plugin->id()); @@ -107,11 +106,11 @@ void CarlaEngineThread::run() // ------------------------------------------------------- // Process postponed events - if (! usesSingleThread) - plugin->postEventsRun(); - if (oscRegisted || ! usesSingleThread) { + if (! usesSingleThread) + plugin->postRtEventsRun(); + // --------------------------------------------------- // Update parameter outputs @@ -130,9 +129,9 @@ void CarlaEngineThread::run() if (oscRegisted) { #ifdef BUILD_BRIDGE - fEngine->osc_send_bridge_set_parameter_value(j, value); + kEngine->osc_send_bridge_set_parameter_value(j, value); #else - fEngine->osc_send_control_set_parameter_value(i, j, value); + kEngine->osc_send_control_set_parameter_value(i, j, value); #endif } } @@ -143,16 +142,15 @@ void CarlaEngineThread::run() if (oscRegisted) { #ifdef BUILD_BRIDGE - fEngine->osc_send_peaks(plugin); + kEngine->osc_send_peaks(plugin); #else - fEngine->osc_send_peaks(plugin, i); + kEngine->osc_send_peaks(plugin, i); #endif } } -#endif } - fEngine->idleOsc(); + kEngine->idleOsc(); msleep(oscRegisted ? 40 : 50); } } diff --git a/source/backend/engine/carla_engine_thread.hpp b/source/backend/engine/carla_engine_thread.hpp index 28373f36b..905d808a0 100644 --- a/source/backend/engine/carla_engine_thread.hpp +++ b/source/backend/engine/carla_engine_thread.hpp @@ -46,7 +46,7 @@ protected: // ---------------------------------------------- private: - CarlaEngine* const fEngine; + CarlaEngine* const kEngine; CarlaMutex fMutex; bool fStopNow; diff --git a/source/backend/plugin/carla_plugin.cpp b/source/backend/plugin/carla_plugin.cpp index 22eb40bdf..7971c6753 100644 --- a/source/backend/plugin/carla_plugin.cpp +++ b/source/backend/plugin/carla_plugin.cpp @@ -34,7 +34,7 @@ static const CustomData kCustomDataNull; // ------------------------------------------------------------------- // Constructor and destructor -CarlaPlugin::CarlaPlugin(CarlaEngine* const engine, const unsigned int id) +CarlaPlugin::CarlaPlugin(CarlaEngine* const engine, const int id) : fData(new CarlaPluginProtectedData(engine, id)) { CARLA_ASSERT(engine); @@ -1216,7 +1216,7 @@ void CarlaPlugin::sendMidiAllNotesOff() // ------------------------------------------------------------------- // Post-poned events -void CarlaPlugin::postponeEvent(const PluginPostRtEventType type, const int32_t value1, const int32_t value2, const double value3) +void CarlaPlugin::postponeRtEvent(const PluginPostRtEventType type, const int32_t value1, const int32_t value2, const double value3) { PluginPostRtEvent event; event.type = type; @@ -1224,36 +1224,40 @@ void CarlaPlugin::postponeEvent(const PluginPostRtEventType type, const int32_t event.value2 = value2; event.value3 = value3; - fData->postRtEvents.append(event); + fData->postRtEvents.appendRT(event); } -#if 0 -void CarlaPlugin::postEventsRun() +void CarlaPlugin::postRtEventsRun() { - PluginPostEvent newPostEvents[MAX_POST_EVENTS]; + int i = 0; + PluginPostRtEvent listData[512]; - // Make a safe copy of events, and clear them - postEvents.mutex.lock(); - memcpy(newPostEvents, postEvents.data, sizeof(PluginPostEvent)*MAX_POST_EVENTS); - for (unsigned short i=0; i < MAX_POST_EVENTS; i++) - postEvents.data[i].type = PluginPostEventNull; - postEvents.mutex.unlock(); + // Make a safe copy of events while clearing them + fData->postRtEvents.mutex.lock(); + + while (! fData->postRtEvents.data.isEmpty()) + { + PluginPostRtEvent& event = fData->postRtEvents.data.getFirst(true); + listData[i++] = event; + } + + fData->postRtEvents.mutex.unlock(); // Handle events now - for (uint32_t i=0; i < MAX_POST_EVENTS; i++) + for (i=0; i < 512; i++) { - const PluginPostEvent* const event = &newPostEvents[i]; + const PluginPostRtEvent* const event = &listData[i]; switch (event->type) { - case PluginPostEventNull: + case kPluginPostRtEventNull: break; - case PluginPostEventDebug: - x_engine->callback(CALLBACK_DEBUG, m_id, event->value1, event->value2, event->value3, nullptr); + case kPluginPostRtEventDebug: + fData->engine->callback(CALLBACK_DEBUG, fData->id, event->value1, event->value2, event->value3, nullptr); break; - case PluginPostEventParameterChange: + case kPluginPostRtEventParameterChange: // Update UI if (event->value1 >= 0) uiParameterChange(event->value1, event->value3); @@ -1261,89 +1265,83 @@ void CarlaPlugin::postEventsRun() #ifndef BUILD_BRIDGE // Update OSC control client if (x_engine->isOscControlRegistered()) - x_engine->osc_send_control_set_parameter_value(m_id, event->value1, event->value3); + x_engine->osc_send_control_set_parameter_value(fData->id, event->value1, event->value3); #endif // Update Host - x_engine->callback(CALLBACK_PARAMETER_VALUE_CHANGED, m_id, event->value1, 0, event->value3, nullptr); + fData->engine->callback(CALLBACK_PARAMETER_VALUE_CHANGED, fData->id, event->value1, 0, event->value3, nullptr); break; - case PluginPostEventProgramChange: + case kPluginPostRtEventProgramChange: // Update UI if (event->value1 >= 0) uiProgramChange(event->value1); #ifndef BUILD_BRIDGE // Update OSC control client - if (x_engine->isOscControlRegistered()) + if (fData->engine->isOscControlRegistered()) { - x_engine->osc_send_control_set_program(m_id, event->value1); + fData->engine->osc_send_control_set_program(m_id, event->value1); - for (uint32_t j=0; j < param.count; j++) - x_engine->osc_send_control_set_default_value(m_id, j, param.ranges[j].def); + for (uint32_t j=0; j < fData->param.count; j++) + fData->engine->osc_send_control_set_default_value(fData->id, j, fData->param.ranges[j].def); } #endif // Update Host - x_engine->callback(CALLBACK_PROGRAM_CHANGED, m_id, event->value1, 0, 0.0, nullptr); + fData->engine->callback(CALLBACK_PROGRAM_CHANGED, fData->id, event->value1, 0, 0.0, nullptr); break; - case PluginPostEventMidiProgramChange: + case kPluginPostRtEventMidiProgramChange: // Update UI if (event->value1 >= 0) uiMidiProgramChange(event->value1); #ifndef BUILD_BRIDGE // Update OSC control client - if (x_engine->isOscControlRegistered()) + if (fData->engine->isOscControlRegistered()) { - x_engine->osc_send_control_set_midi_program(m_id, event->value1); + fData->engine->osc_send_control_set_midi_program(fData->id, event->value1); for (uint32_t j=0; j < param.count; j++) - x_engine->osc_send_control_set_default_value(m_id, j, param.ranges[j].def); + fData->engine->osc_send_control_set_default_value(fData->id, j, fData->param.ranges[j].def); } #endif // Update Host - x_engine->callback(CALLBACK_MIDI_PROGRAM_CHANGED, m_id, event->value1, 0, 0.0, nullptr); + fData->engine->callback(CALLBACK_MIDI_PROGRAM_CHANGED, fData->id, event->value1, 0, 0.0, nullptr); break; - case PluginPostEventNoteOn: + case kPluginPostRtEventNoteOn: // Update UI - uiNoteOn(event->value1, event->value2, rint(event->value3)); + uiNoteOn(event->value1, event->value2, int(event->value3)); #ifndef BUILD_BRIDGE // Update OSC control client - if (x_engine->isOscControlRegistered()) - x_engine->osc_send_control_note_on(m_id, event->value1, event->value2, rint(event->value3)); + if (fData->engine->isOscControlRegistered()) + fData->engine->osc_send_control_note_on(fData->id, event->value1, event->value2, int(event->value3)); #endif // Update Host - x_engine->callback(CALLBACK_NOTE_ON, m_id, event->value1, event->value2, rint(event->value3), nullptr); + fData->engine->callback(CALLBACK_NOTE_ON, fData->id, event->value1, event->value2, int(event->value3), nullptr); break; - case PluginPostEventNoteOff: + case kPluginPostRtEventNoteOff: // Update UI uiNoteOff(event->value1, event->value2); #ifndef BUILD_BRIDGE // Update OSC control client - if (x_engine->isOscControlRegistered()) - x_engine->osc_send_control_note_off(m_id, event->value1, event->value2); + if (fData->engine->isOscControlRegistered()) + fData->engine->osc_send_control_note_off(fData->id, event->value1, event->value2); #endif // Update Host - x_engine->callback(CALLBACK_NOTE_OFF, m_id, event->value1, event->value2, 0.0, nullptr); - break; - - case PluginPostEventCustom: - // Handle custom event - postEventHandleCustom(event->value1, event->value2, event->value3, event->cdata); + fData->engine->callback(CALLBACK_NOTE_OFF, fData->id, event->value1, event->value2, 0.0, nullptr); break; } } } -#endif void CarlaPlugin::uiParameterChange(const uint32_t index, const double value) { diff --git a/source/backend/plugin/carla_plugin_internal.hpp b/source/backend/plugin/carla_plugin_internal.hpp index a8ee786cb..483b56cfd 100644 --- a/source/backend/plugin/carla_plugin_internal.hpp +++ b/source/backend/plugin/carla_plugin_internal.hpp @@ -286,7 +286,7 @@ const unsigned int PLUGIN_OPTION2_HAS_MIDI_IN = 0x1; const unsigned int PLUGIN_OPTION2_HAS_MIDI_OUT = 0x2; struct CarlaPluginProtectedData { - unsigned short id; + int id; CarlaEngine* const engine; CarlaEngineClient* client; @@ -328,13 +328,21 @@ struct CarlaPluginProtectedData { struct PostRtEvents { CarlaMutex mutex; RtList data; + RtList dataPendingRT; PostRtEvents() - : data(152, 512) {} + : data(152, 512), + dataPendingRT(152, 256) {} - void append(const PluginPostRtEvent& event) + void appendRT(const PluginPostRtEvent& event) { - data.append(event); + dataPendingRT.append(event); + + if (mutex.tryLock()) + { + dataPendingRT.splice(data, true); + mutex.unlock(); + } } } postRtEvents; diff --git a/source/bridges/qtcreator/carla-bridge-plugin.pro b/source/bridges/qtcreator/carla-bridge-plugin.pro index 271a5f3e1..f976c834e 100644 --- a/source/bridges/qtcreator/carla-bridge-plugin.pro +++ b/source/bridges/qtcreator/carla-bridge-plugin.pro @@ -25,12 +25,6 @@ HEADERS = \ ../carla_bridge_osc.hpp \ ../carla_bridge_toolkit.hpp \ -# common -HEADERS += \ - ../../backend/carla_backend.hpp \ - ../../backend/carla_engine.hpp \ - ../../backend/carla_plugin.hpp - # carla-engine SOURCES += \ ../../backend/engine/carla_engine.cpp \ @@ -38,11 +32,6 @@ SOURCES += \ ../../backend/engine/carla_engine_thread.cpp \ ../../backend/engine/jack.cpp -HEADERS += \ - ../../backend/engine/carla_engine.hpp \ - ../../backend/engine/carla_engine_osc.hpp \ - ../../backend/engine/carla_engine_thread.hpp \ - # carla-plugin SOURCES += \ ../../backend/plugin/carla_plugin.cpp @@ -52,13 +41,28 @@ SOURCES += \ # ../../backend/plugin/lv2.cpp \ # ../../backend/plugin/vst.cpp -HEADERS += \ - ../../backend/plugin/carla_plugin_thread.hpp - # carla-utils SOURCES += \ ../../backend/utils/Shared.cpp +# common +HEADERS += \ + ../../backend/carla_backend.hpp \ + ../../backend/carla_engine.hpp \ + ../../backend/carla_native.h \ + ../../backend/carla_native.hpp \ + ../../backend/carla_plugin.hpp \ + ../../backend/carla_standalone.hpp + +HEADERS += \ + ../../backend/engine/carla_engine_internal.hpp \ + ../../backend/engine/carla_engine_osc.hpp \ + ../../backend/engine/carla_engine_thread.hpp \ + +HEADERS += \ + ../../backend/plugin/carla_plugin_internal.hpp \ + ../../backend/plugin/carla_plugin_thread.hpp + HEADERS += \ ../../backend/utils/Shared.hpp @@ -71,12 +75,15 @@ HEADERS += \ # utils HEADERS += \ - ../../utils/carla_lib_utils.hpp \ - ../../utils/carla_osc_utils.hpp \ + ../../utils/carla_backend_utils.hpp\ + ../../utils/carla_juce_utils.hpp \ ../../utils/carla_ladspa_utils.hpp \ + ../../utils/carla_lib_utils.hpp \ ../../utils/carla_lv2_utils.hpp \ + ../../utils/carla_osc_utils.hpp \ ../../utils/carla_vst_utils.hpp \ - ../../utils/carla_backend_utils.hpp + ../../utils/lv2_atom_queue.hpp \ + ../../utils/rt_list.hpp INCLUDEPATH = .. \ ../../backend \ diff --git a/source/carla_shared.py b/source/carla_shared.py index d24f91981..cf2561be6 100644 --- a/source/carla_shared.py +++ b/source/carla_shared.py @@ -886,7 +886,7 @@ class PluginParameter(QWidget): # ------------------------------------------------------------------------------------------------------------ # TESTING -from PyQt4.QtGui import QApplication +#from PyQt4.QtGui import QApplication #Carla.isControl = True diff --git a/source/includes/ladspa_rdf.hpp b/source/includes/ladspa_rdf.hpp index 57f2773fc..c8d3573ce 100644 --- a/source/includes/ladspa_rdf.hpp +++ b/source/includes/ladspa_rdf.hpp @@ -2,17 +2,17 @@ * Custom types to store LADSPA-RDF information * Copyright (C) 2011-2013 Filipe Coelho * - * 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 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 + * For a full copy of the GNU General Public License see the GPL.txt file */ #ifndef LADSPA_RDF_INCLUDED diff --git a/source/includes/lv2_rdf.hpp b/source/includes/lv2_rdf.hpp index 7ed5f425d..8e63ae232 100644 --- a/source/includes/lv2_rdf.hpp +++ b/source/includes/lv2_rdf.hpp @@ -2,17 +2,17 @@ * Custom types to store LV2 information * Copyright (C) 2011-2013 Filipe Coelho * - * 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 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 + * For a full copy of the GNU General Public License see the GPL.txt file */ #ifndef LV2_RDF_INCLUDED diff --git a/source/utils/carla_backend_utils.hpp b/source/utils/carla_backend_utils.hpp index 376604cfb..65f30425c 100644 --- a/source/utils/carla_backend_utils.hpp +++ b/source/utils/carla_backend_utils.hpp @@ -297,6 +297,8 @@ const char* ProcessMode2Str(const ProcessMode& mode) return "PROCESS_MODE_CONTINUOUS_RACK"; case PROCESS_MODE_PATCHBAY: return "PROCESS_MODE_PATCHBAY"; + case PROCESS_MODE_BRIDGE: + return "PROCESS_MODE_BRIDGE"; } qWarning("CarlaBackend::ProcessModeType2Str(%i) - invalid type", mode); diff --git a/source/utils/rt_list.hpp b/source/utils/rt_list.hpp index ce7946fc3..486d0b11f 100644 --- a/source/utils/rt_list.hpp +++ b/source/utils/rt_list.hpp @@ -80,14 +80,17 @@ public: return (fCount == 0); } - void append(const T& value) + bool append(const T& value) { if (Data* const data = _allocate()) { std::memcpy(&data->value, &value, sizeof(T)); list_add_tail(&data->siblings, &fQueue); fCount++; + return true; } + + return false; } T& getAt(const size_t index, const bool remove = false) @@ -173,6 +176,14 @@ public: } } + void splice(List& list, const bool init = false) + { + if (init) + list_splice_init(&fQueue, &list.fQueue); + else + list_splice(&fQueue, &list.fQueue); + } + protected: const size_t fDataSize; size_t fCount;