With this we can check if the osc messages come from the proper source (say a DSSI UI), so there won't be conflicts if external tools send random osc messages to Carlatags/1.9.6
| @@ -23,7 +23,7 @@ | |||||
| // ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
| // Avoid including extra libs here | // Avoid including extra libs here | ||||
| typedef void* lo_address; | |||||
| typedef void* lo_message; | |||||
| typedef struct _NativePluginDescriptor NativePluginDescriptor; | typedef struct _NativePluginDescriptor NativePluginDescriptor; | ||||
| struct LADSPA_RDF_Descriptor; | struct LADSPA_RDF_Descriptor; | ||||
| @@ -712,15 +712,15 @@ public: | |||||
| /*! | /*! | ||||
| * Register this plugin to the engine's OSC client (controller or bridge). | * Register this plugin to the engine's OSC client (controller or bridge). | ||||
| * TODO | |||||
| */ | */ | ||||
| void registerToOscClient() noexcept; | void registerToOscClient() noexcept; | ||||
| /*! | /*! | ||||
| * Update the plugin's internal OSC data according to @a source and @a url. | |||||
| * This is used for OSC-GUI bridges. | |||||
| * TODO remove | |||||
| * Handle an OSC message. | |||||
| * FIXME | |||||
| */ | */ | ||||
| virtual void updateOscData(const lo_address& source, const char* const url); | |||||
| virtual void handleOscMessage(const char* const method, const int argc, const void* const argv, const char* const types, const lo_message msg); | |||||
| #ifndef BUILD_BRIDGE | #ifndef BUILD_BRIDGE | ||||
| // ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
| @@ -209,7 +209,7 @@ int CarlaEngineOsc::handleMessage(const bool isTCP, const char* const path, cons | |||||
| } | } | ||||
| #endif | #endif | ||||
| const size_t nameSize(fName.length()); | |||||
| const std::size_t nameSize(fName.length()); | |||||
| // Check if message is for this client | // Check if message is for this client | ||||
| if (std::strlen(path) <= nameSize || std::strncmp(path+1, fName, nameSize) != 0) | if (std::strlen(path) <= nameSize || std::strncmp(path+1, fName, nameSize) != 0) | ||||
| @@ -220,7 +220,7 @@ int CarlaEngineOsc::handleMessage(const bool isTCP, const char* const path, cons | |||||
| // Get plugin id from path, "/carla/23/method" -> 23 | // Get plugin id from path, "/carla/23/method" -> 23 | ||||
| uint pluginId = 0; | uint pluginId = 0; | ||||
| size_t offset; | |||||
| std::size_t offset; | |||||
| if (std::isdigit(path[nameSize+2])) | if (std::isdigit(path[nameSize+2])) | ||||
| { | { | ||||
| @@ -286,26 +286,7 @@ int CarlaEngineOsc::handleMessage(const bool isTCP, const char* const path, cons | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| // Common OSC methods (all bridges) | |||||
| if (std::strcmp(method, "update") == 0) | |||||
| { | |||||
| const lo_address source(lo_message_get_source(msg)); | |||||
| return handleMsgUpdate(plugin, argc, argv, types, source); | |||||
| } | |||||
| if (std::strcmp(method, "exiting") == 0) | |||||
| return handleMsgExiting(plugin); | |||||
| #ifndef BUILD_BRIDGE | #ifndef BUILD_BRIDGE | ||||
| // Common OSC methods (DSSI and bridge UIs) | |||||
| if (std::strcmp(method, "configure") == 0) | |||||
| return handleMsgConfigure(plugin, argc, argv, types); | |||||
| if (std::strcmp(method, "control") == 0) | |||||
| return handleMsgControl(plugin, argc, argv, types); | |||||
| if (std::strcmp(method, "program") == 0) | |||||
| return handleMsgProgram(plugin, argc, argv, types); | |||||
| if (std::strcmp(method, "midi") == 0) | |||||
| return handleMsgMidi(plugin, argc, argv, types); | |||||
| // Internal methods | // Internal methods | ||||
| if (std::strcmp(method, "set_active") == 0) | if (std::strcmp(method, "set_active") == 0) | ||||
| return handleMsgSetActive(plugin, argc, argv, types); | return handleMsgSetActive(plugin, argc, argv, types); | ||||
| @@ -333,90 +314,10 @@ int CarlaEngineOsc::handleMessage(const bool isTCP, const char* const path, cons | |||||
| return handleMsgNoteOn(plugin, argc, argv, types); | return handleMsgNoteOn(plugin, argc, argv, types); | ||||
| if (std::strcmp(method, "note_off") == 0) | if (std::strcmp(method, "note_off") == 0) | ||||
| return handleMsgNoteOff(plugin, argc, argv, types); | return handleMsgNoteOff(plugin, argc, argv, types); | ||||
| // Plugin Bridges | |||||
| if ((plugin->getHints() & PLUGIN_IS_BRIDGE) != 0 && std::strlen(method) >= 11 && std::strncmp(method, "bridge_", 7) == 0) | |||||
| { | |||||
| const char* const bmethod(method+7); | |||||
| if (std::strcmp(bmethod, "pong") == 0) | |||||
| return CarlaPluginSetOscBridgeInfo(plugin, kPluginBridgeOscPong, argc, argv, types); | |||||
| if (std::strcmp(bmethod, "plugin_info1") == 0) | |||||
| return CarlaPluginSetOscBridgeInfo(plugin, kPluginBridgeOscPluginInfo1, argc, argv, types); | |||||
| if (std::strcmp(bmethod, "plugin_info2") == 0) | |||||
| return CarlaPluginSetOscBridgeInfo(plugin, kPluginBridgeOscPluginInfo2, argc, argv, types); | |||||
| if (std::strcmp(bmethod, "audio_count") == 0) | |||||
| return CarlaPluginSetOscBridgeInfo(plugin, kPluginBridgeOscAudioCount, argc, argv, types); | |||||
| if (std::strcmp(bmethod, "midi_count") == 0) | |||||
| return CarlaPluginSetOscBridgeInfo(plugin, kPluginBridgeOscMidiCount, argc, argv, types); | |||||
| if (std::strcmp(bmethod, "parameter_count") == 0) | |||||
| return CarlaPluginSetOscBridgeInfo(plugin, kPluginBridgeOscParameterCount, argc, argv, types); | |||||
| if (std::strcmp(bmethod, "program_count") == 0) | |||||
| return CarlaPluginSetOscBridgeInfo(plugin, kPluginBridgeOscProgramCount, argc, argv, types); | |||||
| if (std::strcmp(bmethod, "midi_program_count") == 0) | |||||
| return CarlaPluginSetOscBridgeInfo(plugin, kPluginBridgeOscMidiProgramCount, argc, argv, types); | |||||
| if (std::strcmp(bmethod, "parameter_data1") == 0) | |||||
| return CarlaPluginSetOscBridgeInfo(plugin, kPluginBridgeOscParameterData1, argc, argv, types); | |||||
| if (std::strcmp(bmethod, "parameter_data2") == 0) | |||||
| return CarlaPluginSetOscBridgeInfo(plugin, kPluginBridgeOscParameterData2, argc, argv, types); | |||||
| if (std::strcmp(bmethod, "parameter_ranges1") == 0) | |||||
| return CarlaPluginSetOscBridgeInfo(plugin, kPluginBridgeOscParameterRanges1, argc, argv, types); | |||||
| if (std::strcmp(bmethod, "parameter_ranges2") == 0) | |||||
| return CarlaPluginSetOscBridgeInfo(plugin, kPluginBridgeOscParameterRanges2, argc, argv, types); | |||||
| if (std::strcmp(bmethod, "parameter_value") == 0) | |||||
| return CarlaPluginSetOscBridgeInfo(plugin, kPluginBridgeOscParameterValue, argc, argv, types); | |||||
| if (std::strcmp(bmethod, "default_value") == 0) | |||||
| return CarlaPluginSetOscBridgeInfo(plugin, kPluginBridgeOscDefaultValue, argc, argv, types); | |||||
| if (std::strcmp(bmethod, "current_program") == 0) | |||||
| return CarlaPluginSetOscBridgeInfo(plugin, kPluginBridgeOscCurrentProgram, argc, argv, types); | |||||
| if (std::strcmp(bmethod, "current_midi_program") == 0) | |||||
| return CarlaPluginSetOscBridgeInfo(plugin, kPluginBridgeOscCurrentMidiProgram, argc, argv, types); | |||||
| if (std::strcmp(bmethod, "program_name") == 0) | |||||
| return CarlaPluginSetOscBridgeInfo(plugin, kPluginBridgeOscProgramName, argc, argv, types); | |||||
| if (std::strcmp(bmethod, "midi_program_data") == 0) | |||||
| return CarlaPluginSetOscBridgeInfo(plugin, kPluginBridgeOscMidiProgramData, argc, argv, types); | |||||
| if (std::strcmp(bmethod, "configure") == 0) | |||||
| return CarlaPluginSetOscBridgeInfo(plugin, kPluginBridgeOscConfigure, argc, argv, types); | |||||
| if (std::strcmp(bmethod, "set_custom_data") == 0) | |||||
| return CarlaPluginSetOscBridgeInfo(plugin, kPluginBridgeOscSetCustomData, argc, argv, types); | |||||
| if (std::strcmp(bmethod, "set_chunk_data_file") == 0) | |||||
| return CarlaPluginSetOscBridgeInfo(plugin, kPluginBridgeOscSetChunkDataFile, argc, argv, types); | |||||
| if (std::strcmp(bmethod, "latency") == 0) | |||||
| return CarlaPluginSetOscBridgeInfo(plugin, kPluginBridgeOscLatency, argc, argv, types); | |||||
| if (std::strcmp(bmethod, "ready") == 0) | |||||
| return CarlaPluginSetOscBridgeInfo(plugin, kPluginBridgeOscReady, argc, argv, types); | |||||
| if (std::strcmp(bmethod, "error") == 0) | |||||
| return CarlaPluginSetOscBridgeInfo(plugin, kPluginBridgeOscError, argc, argv, types); | |||||
| } | |||||
| #endif | |||||
| carla_stderr("CarlaEngineOsc::handleMessage() - unsupported OSC method '%s'", method); | |||||
| return 1; | |||||
| } | |||||
| // ----------------------------------------------------------------------- | |||||
| int CarlaEngineOsc::handleMsgUpdate(CARLA_ENGINE_OSC_HANDLE_ARGS2, const lo_address source) | |||||
| { | |||||
| carla_debug("CarlaEngineOsc::handleMsgUpdate()"); | |||||
| CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "s"); | |||||
| #ifndef BUILD_BRIDGE | |||||
| const char* const url = (const char*)&argv[0]->s; | |||||
| plugin->updateOscData(source, url); | |||||
| #endif | #endif | ||||
| return 0; | |||||
| } | |||||
| int CarlaEngineOsc::handleMsgExiting(CARLA_ENGINE_OSC_HANDLE_ARGS1) | |||||
| { | |||||
| carla_debug("CarlaEngineOsc::handleMsgExiting()"); | |||||
| // TODO - check for non-UIs (dssi-vst) and set to -1 instead | |||||
| fEngine->callback(ENGINE_CALLBACK_UI_STATE_CHANGED, plugin->getId(), 0, 0, 0.0f, nullptr); | |||||
| plugin->showCustomUI(false); | |||||
| // Send all other methods to plugins, TODO | |||||
| plugin->handleOscMessage(method, argc, argv, types, msg); | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| @@ -481,114 +382,7 @@ int CarlaEngineOsc::handleMsgUnregister() | |||||
| // ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
| int CarlaEngineOsc::handleMsgConfigure(CARLA_ENGINE_OSC_HANDLE_ARGS2) | |||||
| { | |||||
| carla_debug("CarlaEngineOsc::handleMsgConfigure()"); | |||||
| CARLA_ENGINE_OSC_CHECK_OSC_TYPES(2, "ss"); | |||||
| const char* const key = (const char*)&argv[0]->s; | |||||
| const char* const value = (const char*)&argv[1]->s; | |||||
| plugin->setCustomData(CUSTOM_DATA_TYPE_STRING, key, value, false); | |||||
| return 0; | |||||
| } | |||||
| int CarlaEngineOsc::handleMsgControl(CARLA_ENGINE_OSC_HANDLE_ARGS2) | |||||
| { | |||||
| carla_debug("CarlaEngineOsc::handleMsgControl()"); | |||||
| CARLA_ENGINE_OSC_CHECK_OSC_TYPES(2, "if"); | |||||
| const int32_t rindex = argv[0]->i; | |||||
| const float value = argv[1]->f; | |||||
| plugin->setParameterValueByRealIndex(rindex, value, false, true, true); | |||||
| return 0; | |||||
| } | |||||
| int CarlaEngineOsc::handleMsgProgram(CARLA_ENGINE_OSC_HANDLE_ARGS2) | |||||
| { | |||||
| carla_debug("CarlaEngineOsc::handleMsgProgram()"); | |||||
| if (argc == 2) | |||||
| { | |||||
| CARLA_ENGINE_OSC_CHECK_OSC_TYPES(2, "ii"); | |||||
| const int32_t bank = argv[0]->i; | |||||
| const int32_t program = argv[1]->i; | |||||
| CARLA_SAFE_ASSERT_RETURN(bank >= 0, 0); | |||||
| CARLA_SAFE_ASSERT_RETURN(program >= 0, 0); | |||||
| plugin->setMidiProgramById(static_cast<uint32_t>(bank), static_cast<uint32_t>(program), false, true, true); | |||||
| return 0; | |||||
| } | |||||
| else | |||||
| { | |||||
| CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "i"); | |||||
| const int32_t program = argv[0]->i; | |||||
| CARLA_SAFE_ASSERT_RETURN(program >= 0, 0); | |||||
| CARLA_SAFE_ASSERT_RETURN(program < static_cast<int32_t>(plugin->getProgramCount()), 0); | |||||
| plugin->setProgram(program, false, true, true); | |||||
| return 0; | |||||
| } | |||||
| } | |||||
| int CarlaEngineOsc::handleMsgMidi(CARLA_ENGINE_OSC_HANDLE_ARGS2) | |||||
| { | |||||
| carla_debug("CarlaEngineOsc::handleMsgMidi()"); | |||||
| CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "m"); | |||||
| #ifdef BUILD_BRIDGE | |||||
| CARLA_ASSERT(false); // this should never happen | |||||
| return 0; | |||||
| // unused | |||||
| (void)plugin; | |||||
| (void)argv; | |||||
| #else | |||||
| if (plugin->getMidiInCount() == 0) | |||||
| { | |||||
| carla_stderr("CarlaEngineOsc::handleMsgMidi() - received midi when plugin has no midi inputs"); | |||||
| return 0; | |||||
| } | |||||
| const uint8_t* const data = argv[0]->m; | |||||
| uint8_t status = data[1]; | |||||
| uint8_t channel = status & 0x0F; | |||||
| // Fix bad note-off | |||||
| if (MIDI_IS_STATUS_NOTE_ON(status) && data[3] == 0) | |||||
| status = MIDI_STATUS_NOTE_OFF; | |||||
| if (MIDI_IS_STATUS_NOTE_OFF(status)) | |||||
| { | |||||
| const uint8_t note = data[2]; | |||||
| CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE, 0); | |||||
| plugin->sendMidiSingleNote(channel, note, 0, false, true, true); | |||||
| } | |||||
| else if (MIDI_IS_STATUS_NOTE_ON(status)) | |||||
| { | |||||
| const uint8_t note = data[2]; | |||||
| const uint8_t velo = data[3]; | |||||
| CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE, 0); | |||||
| CARLA_SAFE_ASSERT_RETURN(velo < MAX_MIDI_VALUE, 0); | |||||
| plugin->sendMidiSingleNote(channel, note, velo, false, true, true); | |||||
| } | |||||
| return 0; | |||||
| #endif | |||||
| } | |||||
| // ----------------------------------------------------------------------- | |||||
| int CarlaEngineOsc::handleMsgSetActive(CARLA_ENGINE_OSC_HANDLE_ARGS2) | |||||
| int CarlaEngineOsc::handleMsgSetActive(CARLA_ENGINE_OSC_HANDLE_ARGS) | |||||
| { | { | ||||
| carla_debug("CarlaEngineOsc::handleMsgSetActive()"); | carla_debug("CarlaEngineOsc::handleMsgSetActive()"); | ||||
| CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "i"); | CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "i"); | ||||
| @@ -599,7 +393,7 @@ int CarlaEngineOsc::handleMsgSetActive(CARLA_ENGINE_OSC_HANDLE_ARGS2) | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| int CarlaEngineOsc::handleMsgSetDryWet(CARLA_ENGINE_OSC_HANDLE_ARGS2) | |||||
| int CarlaEngineOsc::handleMsgSetDryWet(CARLA_ENGINE_OSC_HANDLE_ARGS) | |||||
| { | { | ||||
| carla_debug("CarlaEngineOsc::handleMsgSetDryWet()"); | carla_debug("CarlaEngineOsc::handleMsgSetDryWet()"); | ||||
| CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "f"); | CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "f"); | ||||
| @@ -610,7 +404,7 @@ int CarlaEngineOsc::handleMsgSetDryWet(CARLA_ENGINE_OSC_HANDLE_ARGS2) | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| int CarlaEngineOsc::handleMsgSetVolume(CARLA_ENGINE_OSC_HANDLE_ARGS2) | |||||
| int CarlaEngineOsc::handleMsgSetVolume(CARLA_ENGINE_OSC_HANDLE_ARGS) | |||||
| { | { | ||||
| carla_debug("CarlaEngineOsc::handleMsgSetVolume()"); | carla_debug("CarlaEngineOsc::handleMsgSetVolume()"); | ||||
| CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "f"); | CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "f"); | ||||
| @@ -621,7 +415,7 @@ int CarlaEngineOsc::handleMsgSetVolume(CARLA_ENGINE_OSC_HANDLE_ARGS2) | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| int CarlaEngineOsc::handleMsgSetBalanceLeft(CARLA_ENGINE_OSC_HANDLE_ARGS2) | |||||
| int CarlaEngineOsc::handleMsgSetBalanceLeft(CARLA_ENGINE_OSC_HANDLE_ARGS) | |||||
| { | { | ||||
| carla_debug("CarlaEngineOsc::handleMsgSetBalanceLeft()"); | carla_debug("CarlaEngineOsc::handleMsgSetBalanceLeft()"); | ||||
| CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "f"); | CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "f"); | ||||
| @@ -632,7 +426,7 @@ int CarlaEngineOsc::handleMsgSetBalanceLeft(CARLA_ENGINE_OSC_HANDLE_ARGS2) | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| int CarlaEngineOsc::handleMsgSetBalanceRight(CARLA_ENGINE_OSC_HANDLE_ARGS2) | |||||
| int CarlaEngineOsc::handleMsgSetBalanceRight(CARLA_ENGINE_OSC_HANDLE_ARGS) | |||||
| { | { | ||||
| carla_debug("CarlaEngineOsc::handleMsgSetBalanceRight()"); | carla_debug("CarlaEngineOsc::handleMsgSetBalanceRight()"); | ||||
| CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "f"); | CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "f"); | ||||
| @@ -643,7 +437,7 @@ int CarlaEngineOsc::handleMsgSetBalanceRight(CARLA_ENGINE_OSC_HANDLE_ARGS2) | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| int CarlaEngineOsc::handleMsgSetPanning(CARLA_ENGINE_OSC_HANDLE_ARGS2) | |||||
| int CarlaEngineOsc::handleMsgSetPanning(CARLA_ENGINE_OSC_HANDLE_ARGS) | |||||
| { | { | ||||
| carla_debug("CarlaEngineOsc::handleMsgSetPanning()"); | carla_debug("CarlaEngineOsc::handleMsgSetPanning()"); | ||||
| CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "f"); | CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "f"); | ||||
| @@ -654,7 +448,7 @@ int CarlaEngineOsc::handleMsgSetPanning(CARLA_ENGINE_OSC_HANDLE_ARGS2) | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| int CarlaEngineOsc::handleMsgSetParameterValue(CARLA_ENGINE_OSC_HANDLE_ARGS2) | |||||
| int CarlaEngineOsc::handleMsgSetParameterValue(CARLA_ENGINE_OSC_HANDLE_ARGS) | |||||
| { | { | ||||
| carla_debug("CarlaEngineOsc::handleMsgSetParameterValue()"); | carla_debug("CarlaEngineOsc::handleMsgSetParameterValue()"); | ||||
| CARLA_ENGINE_OSC_CHECK_OSC_TYPES(2, "if"); | CARLA_ENGINE_OSC_CHECK_OSC_TYPES(2, "if"); | ||||
| @@ -668,7 +462,7 @@ int CarlaEngineOsc::handleMsgSetParameterValue(CARLA_ENGINE_OSC_HANDLE_ARGS2) | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| int CarlaEngineOsc::handleMsgSetParameterMidiCC(CARLA_ENGINE_OSC_HANDLE_ARGS2) | |||||
| int CarlaEngineOsc::handleMsgSetParameterMidiCC(CARLA_ENGINE_OSC_HANDLE_ARGS) | |||||
| { | { | ||||
| carla_debug("CarlaEngineOsc::handleMsgSetParameterMidiCC()"); | carla_debug("CarlaEngineOsc::handleMsgSetParameterMidiCC()"); | ||||
| CARLA_ENGINE_OSC_CHECK_OSC_TYPES(2, "ii"); | CARLA_ENGINE_OSC_CHECK_OSC_TYPES(2, "ii"); | ||||
| @@ -683,7 +477,7 @@ int CarlaEngineOsc::handleMsgSetParameterMidiCC(CARLA_ENGINE_OSC_HANDLE_ARGS2) | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| int CarlaEngineOsc::handleMsgSetParameterMidiChannel(CARLA_ENGINE_OSC_HANDLE_ARGS2) | |||||
| int CarlaEngineOsc::handleMsgSetParameterMidiChannel(CARLA_ENGINE_OSC_HANDLE_ARGS) | |||||
| { | { | ||||
| carla_debug("CarlaEngineOsc::handleMsgSetParameterMidiChannel()"); | carla_debug("CarlaEngineOsc::handleMsgSetParameterMidiChannel()"); | ||||
| CARLA_ENGINE_OSC_CHECK_OSC_TYPES(2, "ii"); | CARLA_ENGINE_OSC_CHECK_OSC_TYPES(2, "ii"); | ||||
| @@ -698,7 +492,7 @@ int CarlaEngineOsc::handleMsgSetParameterMidiChannel(CARLA_ENGINE_OSC_HANDLE_ARG | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| int CarlaEngineOsc::handleMsgSetProgram(CARLA_ENGINE_OSC_HANDLE_ARGS2) | |||||
| int CarlaEngineOsc::handleMsgSetProgram(CARLA_ENGINE_OSC_HANDLE_ARGS) | |||||
| { | { | ||||
| carla_debug("CarlaEngineOsc::handleMsgSetProgram()"); | carla_debug("CarlaEngineOsc::handleMsgSetProgram()"); | ||||
| CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "i"); | CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "i"); | ||||
| @@ -711,7 +505,7 @@ int CarlaEngineOsc::handleMsgSetProgram(CARLA_ENGINE_OSC_HANDLE_ARGS2) | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| int CarlaEngineOsc::handleMsgSetMidiProgram(CARLA_ENGINE_OSC_HANDLE_ARGS2) | |||||
| int CarlaEngineOsc::handleMsgSetMidiProgram(CARLA_ENGINE_OSC_HANDLE_ARGS) | |||||
| { | { | ||||
| carla_debug("CarlaEngineOsc::handleMsgSetMidiProgram()"); | carla_debug("CarlaEngineOsc::handleMsgSetMidiProgram()"); | ||||
| CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "i"); | CARLA_ENGINE_OSC_CHECK_OSC_TYPES(1, "i"); | ||||
| @@ -724,7 +518,7 @@ int CarlaEngineOsc::handleMsgSetMidiProgram(CARLA_ENGINE_OSC_HANDLE_ARGS2) | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| int CarlaEngineOsc::handleMsgNoteOn(CARLA_ENGINE_OSC_HANDLE_ARGS2) | |||||
| int CarlaEngineOsc::handleMsgNoteOn(CARLA_ENGINE_OSC_HANDLE_ARGS) | |||||
| { | { | ||||
| carla_debug("CarlaEngineOsc::handleMsgNoteOn()"); | carla_debug("CarlaEngineOsc::handleMsgNoteOn()"); | ||||
| CARLA_ENGINE_OSC_CHECK_OSC_TYPES(3, "iii"); | CARLA_ENGINE_OSC_CHECK_OSC_TYPES(3, "iii"); | ||||
| @@ -741,7 +535,7 @@ int CarlaEngineOsc::handleMsgNoteOn(CARLA_ENGINE_OSC_HANDLE_ARGS2) | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| int CarlaEngineOsc::handleMsgNoteOff(CARLA_ENGINE_OSC_HANDLE_ARGS2) | |||||
| int CarlaEngineOsc::handleMsgNoteOff(CARLA_ENGINE_OSC_HANDLE_ARGS) | |||||
| { | { | ||||
| carla_debug("CarlaEngineOsc::handleMsgNoteOff()"); | carla_debug("CarlaEngineOsc::handleMsgNoteOff()"); | ||||
| CARLA_ENGINE_OSC_CHECK_OSC_TYPES(2, "ii"); | CARLA_ENGINE_OSC_CHECK_OSC_TYPES(2, "ii"); | ||||
| @@ -22,8 +22,7 @@ | |||||
| #include "CarlaOscUtils.hpp" | #include "CarlaOscUtils.hpp" | ||||
| #include "CarlaString.hpp" | #include "CarlaString.hpp" | ||||
| #define CARLA_ENGINE_OSC_HANDLE_ARGS1 CarlaPlugin* const plugin | |||||
| #define CARLA_ENGINE_OSC_HANDLE_ARGS2 CarlaPlugin* const plugin, const int argc, const lo_arg* const* const argv, const char* const types | |||||
| #define CARLA_ENGINE_OSC_HANDLE_ARGS CarlaPlugin* const plugin, const int argc, const lo_arg* const* const argv, const char* const types | |||||
| #define CARLA_ENGINE_OSC_CHECK_OSC_TYPES(/* argc, types, */ argcToCompare, typesToCompare) \ | #define CARLA_ENGINE_OSC_CHECK_OSC_TYPES(/* argc, types, */ argcToCompare, typesToCompare) \ | ||||
| /* check argument count */ \ | /* check argument count */ \ | ||||
| @@ -108,34 +107,24 @@ private: | |||||
| int handleMessage(const bool isTCP, const char* const path, const int argc, const lo_arg* const* const argv, const char* const types, const lo_message msg); | int handleMessage(const bool isTCP, const char* const path, const int argc, const lo_arg* const* const argv, const char* const types, const lo_message msg); | ||||
| // Common OSC methods (all bridges) | |||||
| int handleMsgUpdate(CARLA_ENGINE_OSC_HANDLE_ARGS2, const lo_address source); | |||||
| int handleMsgExiting(CARLA_ENGINE_OSC_HANDLE_ARGS1); | |||||
| #ifndef BUILD_BRIDGE | #ifndef BUILD_BRIDGE | ||||
| int handleMsgRegister(const bool isTCP, const int argc, const lo_arg* const* const argv, const char* const types, const lo_address source); | int handleMsgRegister(const bool isTCP, const int argc, const lo_arg* const* const argv, const char* const types, const lo_address source); | ||||
| int handleMsgUnregister(); | int handleMsgUnregister(); | ||||
| // Common OSC methods (DSSI and bridge UIs) | |||||
| int handleMsgConfigure(CARLA_ENGINE_OSC_HANDLE_ARGS2); | |||||
| int handleMsgControl(CARLA_ENGINE_OSC_HANDLE_ARGS2); | |||||
| int handleMsgProgram(CARLA_ENGINE_OSC_HANDLE_ARGS2); | |||||
| int handleMsgMidi(CARLA_ENGINE_OSC_HANDLE_ARGS2); | |||||
| // Internal methods | // Internal methods | ||||
| int handleMsgSetActive(CARLA_ENGINE_OSC_HANDLE_ARGS2); | |||||
| int handleMsgSetDryWet(CARLA_ENGINE_OSC_HANDLE_ARGS2); | |||||
| int handleMsgSetVolume(CARLA_ENGINE_OSC_HANDLE_ARGS2); | |||||
| int handleMsgSetBalanceLeft(CARLA_ENGINE_OSC_HANDLE_ARGS2); | |||||
| int handleMsgSetBalanceRight(CARLA_ENGINE_OSC_HANDLE_ARGS2); | |||||
| int handleMsgSetPanning(CARLA_ENGINE_OSC_HANDLE_ARGS2); | |||||
| int handleMsgSetParameterValue(CARLA_ENGINE_OSC_HANDLE_ARGS2); | |||||
| int handleMsgSetParameterMidiCC(CARLA_ENGINE_OSC_HANDLE_ARGS2); | |||||
| int handleMsgSetParameterMidiChannel(CARLA_ENGINE_OSC_HANDLE_ARGS2); | |||||
| int handleMsgSetProgram(CARLA_ENGINE_OSC_HANDLE_ARGS2); | |||||
| int handleMsgSetMidiProgram(CARLA_ENGINE_OSC_HANDLE_ARGS2); | |||||
| int handleMsgNoteOn(CARLA_ENGINE_OSC_HANDLE_ARGS2); | |||||
| int handleMsgNoteOff(CARLA_ENGINE_OSC_HANDLE_ARGS2); | |||||
| int handleMsgSetActive(CARLA_ENGINE_OSC_HANDLE_ARGS); | |||||
| int handleMsgSetDryWet(CARLA_ENGINE_OSC_HANDLE_ARGS); | |||||
| int handleMsgSetVolume(CARLA_ENGINE_OSC_HANDLE_ARGS); | |||||
| int handleMsgSetBalanceLeft(CARLA_ENGINE_OSC_HANDLE_ARGS); | |||||
| int handleMsgSetBalanceRight(CARLA_ENGINE_OSC_HANDLE_ARGS); | |||||
| int handleMsgSetPanning(CARLA_ENGINE_OSC_HANDLE_ARGS); | |||||
| int handleMsgSetParameterValue(CARLA_ENGINE_OSC_HANDLE_ARGS); | |||||
| int handleMsgSetParameterMidiCC(CARLA_ENGINE_OSC_HANDLE_ARGS); | |||||
| int handleMsgSetParameterMidiChannel(CARLA_ENGINE_OSC_HANDLE_ARGS); | |||||
| int handleMsgSetProgram(CARLA_ENGINE_OSC_HANDLE_ARGS); | |||||
| int handleMsgSetMidiProgram(CARLA_ENGINE_OSC_HANDLE_ARGS); | |||||
| int handleMsgNoteOn(CARLA_ENGINE_OSC_HANDLE_ARGS); | |||||
| int handleMsgNoteOff(CARLA_ENGINE_OSC_HANDLE_ARGS); | |||||
| #endif | #endif | ||||
| // ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
| @@ -1576,10 +1576,9 @@ void CarlaPlugin::registerToOscClient() noexcept | |||||
| #endif | #endif | ||||
| } | } | ||||
| void CarlaPlugin::updateOscData(const lo_address&, const char* const) | |||||
| void CarlaPlugin::handleOscMessage(const char* const, const int, const void* const, const char* const, const lo_message) | |||||
| { | { | ||||
| // should not happen | |||||
| CARLA_SAFE_ASSERT(false); | |||||
| // do nothing | |||||
| } | } | ||||
| // ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
| @@ -30,9 +30,30 @@ using juce::ScopedPointer; | |||||
| using juce::String; | using juce::String; | ||||
| using juce::StringArray; | using juce::StringArray; | ||||
| CARLA_BACKEND_START_NAMESPACE | |||||
| #define CARLA_PLUGIN_DSSI_OSC_CHECK_OSC_TYPES(/* argc, types, */ argcToCompare, typesToCompare) \ | |||||
| /* check argument count */ \ | |||||
| if (argc != argcToCompare) \ | |||||
| { \ | |||||
| carla_stderr("CarlaPluginDSSI::%s() - argument count mismatch: %i != %i", __FUNCTION__, argc, argcToCompare); \ | |||||
| return; \ | |||||
| } \ | |||||
| if (argc > 0) \ | |||||
| { \ | |||||
| /* check for nullness */ \ | |||||
| if (types == nullptr || typesToCompare == nullptr) \ | |||||
| { \ | |||||
| carla_stderr("CarlaPluginDSSI::%s() - argument types are null", __FUNCTION__); \ | |||||
| return; \ | |||||
| } \ | |||||
| /* check argument types */ \ | |||||
| if (std::strcmp(types, typesToCompare) != 0) \ | |||||
| { \ | |||||
| carla_stderr("CarlaPluginDSSI::%s() - argument types mismatch: '%s' != '%s'", __FUNCTION__, types, typesToCompare); \ | |||||
| return; \ | |||||
| } \ | |||||
| } | |||||
| class CarlaPluginDSSI; | |||||
| CARLA_BACKEND_START_NAMESPACE | |||||
| // ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
| // Fallback data | // Fallback data | ||||
| @@ -2091,93 +2112,136 @@ public: | |||||
| } | } | ||||
| // ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
| // Post-poned UI Stuff | |||||
| // OSC stuff | |||||
| void uiParameterChange(const uint32_t index, const float value) noexcept override | |||||
| void handleOscMessage(const char* const method, const int argc, const void* const argvx, const char* const types, const lo_message msg) override | |||||
| { | { | ||||
| CARLA_SAFE_ASSERT_RETURN(index < pData->param.count,); | |||||
| const lo_address source(lo_message_get_source(msg)); | |||||
| CARLA_SAFE_ASSERT_RETURN(source != nullptr,); | |||||
| if (fOscData.target == nullptr) | |||||
| return; | |||||
| // protocol for DSSI UIs *must* be UDP | |||||
| CARLA_SAFE_ASSERT_RETURN(lo_address_get_protocol(source) == LO_UDP,); | |||||
| osc_send_control(fOscData, pData->param.data[index].rindex, value); | |||||
| if (fOscData.source == nullptr) | |||||
| { | |||||
| // if no UI is registered yet only "update" message is valid | |||||
| CARLA_SAFE_ASSERT_RETURN(std::strcmp(method, "update") == 0,) | |||||
| } | |||||
| else | |||||
| { | |||||
| // make sure message source is the DSSI UI | |||||
| const char* const msghost = lo_address_get_hostname(source); | |||||
| const char* const msgport = lo_address_get_port(source); | |||||
| const char* const ourhost = lo_address_get_hostname(fOscData.source); | |||||
| const char* const ourport = lo_address_get_port(fOscData.source); | |||||
| CARLA_SAFE_ASSERT_RETURN(std::strcmp(msghost, ourhost) == 0,); | |||||
| CARLA_SAFE_ASSERT_RETURN(std::strcmp(msgport, ourport) == 0,); | |||||
| } | |||||
| const lo_arg* const* const argv(static_cast<const lo_arg* const* const>(argvx)); | |||||
| if (std::strcmp(method, "configure") == 0) | |||||
| return handleOscMessageConfigure(argc, argv, types); | |||||
| if (std::strcmp(method, "control") == 0) | |||||
| return handleOscMessageControl(argc, argv, types); | |||||
| if (std::strcmp(method, "program") == 0) | |||||
| return handleOscMessageProgram(argc, argv, types); | |||||
| if (std::strcmp(method, "midi") == 0) | |||||
| return handleOscMessageMIDI(argc, argv, types); | |||||
| if (std::strcmp(method, "update") == 0) | |||||
| return handleOscMessageUpdate(argc, argv, types, lo_message_get_source(msg)); | |||||
| if (std::strcmp(method, "exiting") == 0) | |||||
| return handleOscMessageExiting(); | |||||
| carla_stdout("CarlaPluginDSSI::handleOscMessage() - unknown method '%s'", method); | |||||
| } | } | ||||
| void uiMidiProgramChange(const uint32_t index) noexcept override | |||||
| void handleOscMessageConfigure(const int argc, const lo_arg* const* const argv, const char* const types) | |||||
| { | { | ||||
| CARLA_SAFE_ASSERT_RETURN(index < pData->midiprog.count,); | |||||
| carla_debug("CarlaPluginDSSI::handleMsgConfigure()"); | |||||
| CARLA_PLUGIN_DSSI_OSC_CHECK_OSC_TYPES(2, "ss"); | |||||
| if (fOscData.target == nullptr) | |||||
| return; | |||||
| const char* const key = (const char*)&argv[0]->s; | |||||
| const char* const value = (const char*)&argv[1]->s; | |||||
| osc_send_program(fOscData, pData->midiprog.data[index].bank, pData->midiprog.data[index].program); | |||||
| setCustomData(CUSTOM_DATA_TYPE_STRING, key, value, false); | |||||
| } | } | ||||
| void uiNoteOn(const uint8_t channel, const uint8_t note, const uint8_t velo) noexcept override | |||||
| void handleOscMessageControl(const int argc, const lo_arg* const* const argv, const char* const types) | |||||
| { | { | ||||
| CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,); | |||||
| CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,); | |||||
| CARLA_SAFE_ASSERT_RETURN(velo > 0 && velo < MAX_MIDI_VALUE,); | |||||
| carla_debug("CarlaPluginDSSI::handleMsgControl()"); | |||||
| CARLA_PLUGIN_DSSI_OSC_CHECK_OSC_TYPES(2, "if"); | |||||
| if (fOscData.target == nullptr) | |||||
| return; | |||||
| const int32_t rindex = argv[0]->i; | |||||
| const float value = argv[1]->f; | |||||
| #if 0 | |||||
| uint8_t midiData[4]; | |||||
| midiData[0] = 0; | |||||
| midiData[1] = uint8_t(MIDI_STATUS_NOTE_ON | (channel & MIDI_CHANNEL_BIT)); | |||||
| midiData[2] = note; | |||||
| midiData[3] = velo; | |||||
| setParameterValueByRealIndex(rindex, value, false, true, true); | |||||
| } | |||||
| osc_send_midi(fOscData, midiData); | |||||
| #endif | |||||
| void handleOscMessageProgram(const int argc, const lo_arg* const* const argv, const char* const types) | |||||
| { | |||||
| carla_debug("CarlaPluginDSSI::handleMsgProgram()"); | |||||
| CARLA_PLUGIN_DSSI_OSC_CHECK_OSC_TYPES(2, "ii"); | |||||
| const int32_t bank = argv[0]->i; | |||||
| const int32_t program = argv[1]->i; | |||||
| CARLA_SAFE_ASSERT_RETURN(bank >= 0,); | |||||
| CARLA_SAFE_ASSERT_RETURN(program >= 0,); | |||||
| setMidiProgramById(static_cast<uint32_t>(bank), static_cast<uint32_t>(program), false, true, true); | |||||
| } | } | ||||
| void uiNoteOff(const uint8_t channel, const uint8_t note) noexcept override | |||||
| void handleOscMessageMIDI(const int argc, const lo_arg* const* const argv, const char* const types) | |||||
| { | { | ||||
| CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,); | |||||
| CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,); | |||||
| carla_debug("CarlaPluginDSSI::handleMsgMidi()"); | |||||
| CARLA_PLUGIN_DSSI_OSC_CHECK_OSC_TYPES(1, "m"); | |||||
| if (fOscData.target == nullptr) | |||||
| if (getMidiInCount() == 0) | |||||
| { | |||||
| carla_stderr("CarlaPluginDSSI::handleMsgMidi() - received midi when plugin has no midi inputs"); | |||||
| return; | return; | ||||
| } | |||||
| #if 0 | |||||
| uint8_t midiData[4]; | |||||
| midiData[0] = 0; | |||||
| midiData[1] = uint8_t(MIDI_STATUS_NOTE_ON | (channel & MIDI_CHANNEL_BIT)); | |||||
| midiData[2] = note; | |||||
| midiData[3] = 0; | |||||
| #ifndef BUILD_BRIDGE | |||||
| const uint8_t* const data = argv[0]->m; | |||||
| uint8_t status = data[1]; | |||||
| uint8_t channel = status & 0x0F; | |||||
| osc_send_midi(fOscData, midiData); | |||||
| #endif | |||||
| } | |||||
| // Fix bad note-off | |||||
| if (MIDI_IS_STATUS_NOTE_ON(status) && data[3] == 0) | |||||
| status = MIDI_STATUS_NOTE_OFF; | |||||
| // ------------------------------------------------------------------- | |||||
| if (MIDI_IS_STATUS_NOTE_OFF(status)) | |||||
| { | |||||
| const uint8_t note = data[2]; | |||||
| void* getNativeHandle() const noexcept override | |||||
| { | |||||
| return fHandle; | |||||
| } | |||||
| CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,); | |||||
| const void* getNativeDescriptor() const noexcept override | |||||
| { | |||||
| return fDssiDescriptor; | |||||
| } | |||||
| sendMidiSingleNote(channel, note, 0, false, true, true); | |||||
| } | |||||
| else if (MIDI_IS_STATUS_NOTE_ON(status)) | |||||
| { | |||||
| const uint8_t note = data[2]; | |||||
| const uint8_t velo = data[3]; | |||||
| uintptr_t getUiBridgeProcessId() const noexcept override | |||||
| { | |||||
| return fThreadUI.getProcessPID(); | |||||
| CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,); | |||||
| CARLA_SAFE_ASSERT_RETURN(velo < MAX_MIDI_VALUE,); | |||||
| sendMidiSingleNote(channel, note, velo, false, true, true); | |||||
| } | |||||
| #endif | |||||
| } | } | ||||
| const void* getExtraStuff() const noexcept override | |||||
| void handleOscMessageUpdate(const int argc, const lo_arg* const* const argv, const char* const types, const lo_address source) | |||||
| { | { | ||||
| return fUiFilename; | |||||
| } | |||||
| carla_debug("CarlaPluginDSSI::handleMsgUpdate()"); | |||||
| CARLA_PLUGIN_DSSI_OSC_CHECK_OSC_TYPES(1, "s"); | |||||
| // ------------------------------------------------------------------- | |||||
| const char* const url = (const char*)&argv[0]->s; | |||||
| void updateOscData(const lo_address& source, const char* const url) override | |||||
| { | |||||
| // FIXME - remove debug prints later | // FIXME - remove debug prints later | ||||
| carla_stdout("CarlaPluginDSSI::updateOscData(%p, \"%s\")", source, url); | carla_stdout("CarlaPluginDSSI::updateOscData(%p, \"%s\")", source, url); | ||||
| @@ -2237,6 +2301,101 @@ public: | |||||
| carla_stdout("CarlaPluginDSSI::updateOscData() - done"); | carla_stdout("CarlaPluginDSSI::updateOscData() - done"); | ||||
| } | } | ||||
| void handleOscMessageExiting() | |||||
| { | |||||
| carla_debug("CarlaPluginDSSI::handleMsgExiting()"); | |||||
| // hide UI | |||||
| showCustomUI(false); | |||||
| // tell frontend | |||||
| pData->engine->callback(ENGINE_CALLBACK_UI_STATE_CHANGED, pData->id, 0, 0, 0.0f, nullptr); | |||||
| } | |||||
| // ------------------------------------------------------------------- | |||||
| // Post-poned UI Stuff | |||||
| void uiParameterChange(const uint32_t index, const float value) noexcept override | |||||
| { | |||||
| CARLA_SAFE_ASSERT_RETURN(index < pData->param.count,); | |||||
| if (fOscData.target == nullptr) | |||||
| return; | |||||
| osc_send_control(fOscData, pData->param.data[index].rindex, value); | |||||
| } | |||||
| void uiMidiProgramChange(const uint32_t index) noexcept override | |||||
| { | |||||
| CARLA_SAFE_ASSERT_RETURN(index < pData->midiprog.count,); | |||||
| if (fOscData.target == nullptr) | |||||
| return; | |||||
| osc_send_program(fOscData, pData->midiprog.data[index].bank, pData->midiprog.data[index].program); | |||||
| } | |||||
| void uiNoteOn(const uint8_t channel, const uint8_t note, const uint8_t velo) noexcept override | |||||
| { | |||||
| CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,); | |||||
| CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,); | |||||
| CARLA_SAFE_ASSERT_RETURN(velo > 0 && velo < MAX_MIDI_VALUE,); | |||||
| if (fOscData.target == nullptr) | |||||
| return; | |||||
| #if 0 | |||||
| uint8_t midiData[4]; | |||||
| midiData[0] = 0; | |||||
| midiData[1] = uint8_t(MIDI_STATUS_NOTE_ON | (channel & MIDI_CHANNEL_BIT)); | |||||
| midiData[2] = note; | |||||
| midiData[3] = velo; | |||||
| osc_send_midi(fOscData, midiData); | |||||
| #endif | |||||
| } | |||||
| void uiNoteOff(const uint8_t channel, const uint8_t note) noexcept override | |||||
| { | |||||
| CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,); | |||||
| CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,); | |||||
| if (fOscData.target == nullptr) | |||||
| return; | |||||
| #if 0 | |||||
| uint8_t midiData[4]; | |||||
| midiData[0] = 0; | |||||
| midiData[1] = uint8_t(MIDI_STATUS_NOTE_ON | (channel & MIDI_CHANNEL_BIT)); | |||||
| midiData[2] = note; | |||||
| midiData[3] = 0; | |||||
| osc_send_midi(fOscData, midiData); | |||||
| #endif | |||||
| } | |||||
| // ------------------------------------------------------------------- | |||||
| void* getNativeHandle() const noexcept override | |||||
| { | |||||
| return fHandle; | |||||
| } | |||||
| const void* getNativeDescriptor() const noexcept override | |||||
| { | |||||
| return fDssiDescriptor; | |||||
| } | |||||
| uintptr_t getUiBridgeProcessId() const noexcept override | |||||
| { | |||||
| return fThreadUI.getProcessPID(); | |||||
| } | |||||
| const void* getExtraStuff() const noexcept override | |||||
| { | |||||
| return fUiFilename; | |||||
| } | |||||
| // ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
| bool init(const char* const filename, const char* const name, const char* const label) | bool init(const char* const filename, const char* const name, const char* const label) | ||||