| @@ -730,7 +730,7 @@ public: | |||||
| * Rename plugin with id \a id to \a newName.\n | * Rename plugin with id \a id to \a newName.\n | ||||
| * Returns the new name, or nullptr if the operation failed. | * Returns the new name, or nullptr if the operation failed. | ||||
| */ | */ | ||||
| const char* renamePlugin(const unsigned int id, const char* const newName); | |||||
| virtual const char* renamePlugin(const unsigned int id, const char* const newName); | |||||
| /*! | /*! | ||||
| * Clone plugin with id \a id. | * Clone plugin with id \a id. | ||||
| @@ -764,7 +764,7 @@ public: | |||||
| * Get a unique plugin name within the engine.\n | * Get a unique plugin name within the engine.\n | ||||
| * Returned variable must NOT be free'd. | * Returned variable must NOT be free'd. | ||||
| */ | */ | ||||
| const char* getNewUniquePluginName(const char* const name); | |||||
| const char* getUniquePluginName(const char* const name); | |||||
| // ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
| // Project management | // Project management | ||||
| @@ -422,11 +422,18 @@ public: | |||||
| // Set data (internal stuff) | // Set data (internal stuff) | ||||
| /*! | /*! | ||||
| * Set the plugin's id to \a id. | |||||
| * Set the plugin's id to \a newId. | |||||
| * | * | ||||
| * \see id() | * \see id() | ||||
| */ | */ | ||||
| void setId(const unsigned int id); | |||||
| void setId(const unsigned int newId); | |||||
| /*! | |||||
| * Set the plugin's name to \a newName. | |||||
| * | |||||
| * \see name() | |||||
| */ | |||||
| void setName(const char* const newName); | |||||
| /*! | /*! | ||||
| * Set a plugin's option. | * Set a plugin's option. | ||||
| @@ -403,6 +403,23 @@ void doPluginRemove(CarlaEngineProtectedData* const kData, const bool unlock) | |||||
| kData->nextAction.mutex.unlock(); | kData->nextAction.mutex.unlock(); | ||||
| } | } | ||||
| void doPluginsSwitch(CarlaEngineProtectedData* const kData, const bool unlock) | |||||
| { | |||||
| CARLA_ASSERT(kData->curPluginCount >= 2); | |||||
| const unsigned int idA = kData->nextAction.pluginId; | |||||
| const unsigned int idB = kData->nextAction.value; | |||||
| CarlaPlugin* const tmp = kData->plugins[idA].plugin; | |||||
| kData->plugins[idA].plugin = kData->plugins[idB].plugin; | |||||
| kData->plugins[idB].plugin = tmp; | |||||
| kData->nextAction.opcode = EnginePostActionNull; | |||||
| if (unlock) | |||||
| kData->nextAction.mutex.unlock(); | |||||
| } | |||||
| const char* findDSSIGUI(const char* const filename, const char* const label) | const char* findDSSIGUI(const char* const filename, const char* const label) | ||||
| { | { | ||||
| QString guiFilename; | QString guiFilename; | ||||
| @@ -796,7 +813,6 @@ bool CarlaEngine::removePlugin(const unsigned int id) | |||||
| if (plugin == nullptr) | if (plugin == nullptr) | ||||
| { | { | ||||
| carla_stderr("CarlaEngine::removePlugin(%i) - could not find plugin", id); | |||||
| setLastError("Could not find plugin to remove"); | setLastError("Could not find plugin to remove"); | ||||
| return false; | return false; | ||||
| } | } | ||||
| @@ -877,7 +893,34 @@ void CarlaEngine::removeAllPlugins() | |||||
| const char* CarlaEngine::renamePlugin(const unsigned int id, const char* const newName) | const char* CarlaEngine::renamePlugin(const unsigned int id, const char* const newName) | ||||
| { | { | ||||
| setLastError("Not implemented yet"); | |||||
| CARLA_ASSERT(kData->curPluginCount > 0); | |||||
| CARLA_ASSERT(id < kData->curPluginCount); | |||||
| CARLA_ASSERT(kData->plugins != nullptr); | |||||
| CARLA_ASSERT(newName != nullptr); | |||||
| if (kData->plugins == nullptr) | |||||
| { | |||||
| setLastError("Critical error: no plugins are currently loaded!"); | |||||
| return nullptr; | |||||
| } | |||||
| CarlaPlugin* const plugin = kData->plugins[id].plugin; | |||||
| if (plugin == nullptr) | |||||
| { | |||||
| carla_stderr("CarlaEngine::clonePlugin(%i) - could not find plugin", id); | |||||
| return nullptr; | |||||
| } | |||||
| CARLA_ASSERT(plugin->id() == id); | |||||
| if (const char* const name = getUniquePluginName(newName)) | |||||
| { | |||||
| plugin->setName(name); | |||||
| return name; | |||||
| } | |||||
| return nullptr; | return nullptr; | ||||
| } | } | ||||
| @@ -896,43 +939,40 @@ bool CarlaEngine::clonePlugin(const unsigned int id) | |||||
| CarlaPlugin* const plugin = kData->plugins[id].plugin; | CarlaPlugin* const plugin = kData->plugins[id].plugin; | ||||
| CARLA_ASSERT(plugin != nullptr); | |||||
| if (plugin != nullptr) | |||||
| if (plugin == nullptr) | |||||
| { | { | ||||
| CARLA_ASSERT(plugin->id() == id); | |||||
| carla_stderr("CarlaEngine::clonePlugin(%i) - could not find plugin", id); | |||||
| return false; | |||||
| } | |||||
| CARLA_ASSERT(plugin->id() == id); | |||||
| const SaveState& saveState(plugin->getSaveState()); | |||||
| const SaveState& saveState(plugin->getSaveState()); | |||||
| char label[STR_MAX+1] = { '\0' }; | |||||
| plugin->getLabel(label); | |||||
| char label[STR_MAX+1] = { '\0' }; | |||||
| plugin->getLabel(label); | |||||
| BinaryType binaryType = BINARY_NATIVE; | |||||
| BinaryType binaryType = BINARY_NATIVE; | |||||
| #ifndef BUILD_BRIDGE | #ifndef BUILD_BRIDGE | ||||
| if (plugin->hints() & PLUGIN_IS_BRIDGE) | |||||
| binaryType = CarlaPluginGetBridgeBinaryType(plugin); | |||||
| if (plugin->hints() & PLUGIN_IS_BRIDGE) | |||||
| binaryType = CarlaPluginGetBridgeBinaryType(plugin); | |||||
| #endif | #endif | ||||
| const unsigned int pluginsBefore(kData->curPluginCount); | |||||
| const unsigned int pluginsBefore(kData->curPluginCount); | |||||
| if (! addPlugin(binaryType, plugin->type(), plugin->filename(), plugin->name(), label, plugin->getExtraStuff())) | |||||
| return false; | |||||
| CARLA_ASSERT(pluginsBefore+1 == kData->curPluginCount); | |||||
| if (! addPlugin(binaryType, plugin->type(), plugin->filename(), plugin->name(), label, plugin->getExtraStuff())) | |||||
| return false; | |||||
| CarlaPlugin* const newPlugin = kData->plugins[kData->curPluginCount-1].plugin; | |||||
| CARLA_ASSERT(pluginsBefore+1 == kData->curPluginCount); | |||||
| CARLA_ASSERT(newPlugin != nullptr); | |||||
| CarlaPlugin* const newPlugin = kData->plugins[kData->curPluginCount-1].plugin; | |||||
| newPlugin->loadSaveState(saveState); | |||||
| CARLA_ASSERT(newPlugin != nullptr); | |||||
| return true; | |||||
| } | |||||
| newPlugin->loadSaveState(saveState); | |||||
| carla_stderr("CarlaEngine::clonePlugin(%i) - could not find plugin", id); | |||||
| setLastError("Could not find plugin to clone"); | |||||
| return false; | |||||
| return true; | |||||
| } | } | ||||
| bool CarlaEngine::replacePlugin(const unsigned int id) | bool CarlaEngine::replacePlugin(const unsigned int id) | ||||
| @@ -943,8 +983,48 @@ bool CarlaEngine::replacePlugin(const unsigned int id) | |||||
| bool CarlaEngine::switchPlugins(const unsigned int idA, const unsigned int idB) | bool CarlaEngine::switchPlugins(const unsigned int idA, const unsigned int idB) | ||||
| { | { | ||||
| setLastError("Not implemented yet"); | |||||
| return false; | |||||
| CARLA_ASSERT(kData->curPluginCount > 0); | |||||
| CARLA_ASSERT(idA < kData->curPluginCount); | |||||
| CARLA_ASSERT(idB < kData->curPluginCount); | |||||
| CARLA_ASSERT(kData->plugins != nullptr); | |||||
| if (kData->plugins == nullptr) | |||||
| { | |||||
| setLastError("Critical error: no plugins are currently loaded!"); | |||||
| return false; | |||||
| } | |||||
| kData->thread.stopNow(); | |||||
| kData->nextAction.pluginId = idA; | |||||
| kData->nextAction.value = idB; | |||||
| kData->nextAction.opcode = EnginePostActionSwitchPlugins; | |||||
| kData->nextAction.mutex.lock(); | |||||
| if (isRunning()) | |||||
| { | |||||
| carla_stderr("CarlaEngine::switchPlugins(%i, %i) - switch blocking START", idA, idB); | |||||
| // block wait for unlock on proccessing side | |||||
| kData->nextAction.mutex.lock(); | |||||
| carla_stderr("CarlaEngine::switchPlugins(%i, %i) - switch blocking DONE", idA, idB); | |||||
| } | |||||
| else | |||||
| { | |||||
| doPluginsSwitch(kData, false); | |||||
| } | |||||
| #ifndef BUILD_BRIDGE // TODO | |||||
| //if (isOscControlRegistered()) | |||||
| // osc_send_control_remove_plugin(id); | |||||
| #endif | |||||
| kData->nextAction.mutex.unlock(); | |||||
| if (isRunning() && ! kData->aboutToClose) | |||||
| kData->thread.startNow(); | |||||
| return true; | |||||
| } | } | ||||
| CarlaPlugin* CarlaEngine::getPlugin(const unsigned int id) const | CarlaPlugin* CarlaEngine::getPlugin(const unsigned int id) const | ||||
| @@ -965,9 +1045,9 @@ CarlaPlugin* CarlaEngine::getPluginUnchecked(const unsigned int id) const | |||||
| return kData->plugins[id].plugin; | return kData->plugins[id].plugin; | ||||
| } | } | ||||
| const char* CarlaEngine::getNewUniquePluginName(const char* const name) | |||||
| const char* CarlaEngine::getUniquePluginName(const char* const name) | |||||
| { | { | ||||
| carla_debug("CarlaEngine::getNewUniquePluginName(\"%s\")", name); | |||||
| carla_debug("CarlaEngine::getUniquePluginName(\"%s\")", name); | |||||
| CARLA_ASSERT(kData->maxPluginNumber > 0); | CARLA_ASSERT(kData->maxPluginNumber > 0); | ||||
| CARLA_ASSERT(kData->plugins != nullptr); | CARLA_ASSERT(kData->plugins != nullptr); | ||||
| CARLA_ASSERT(name != nullptr); | CARLA_ASSERT(name != nullptr); | ||||
| @@ -1486,6 +1566,9 @@ void CarlaEngine::proccessPendingEvents() | |||||
| case EnginePostActionRemovePlugin: | case EnginePostActionRemovePlugin: | ||||
| doPluginRemove(kData, true); | doPluginRemove(kData, true); | ||||
| break; | break; | ||||
| case EnginePostActionSwitchPlugins: | |||||
| doPluginsSwitch(kData, true); | |||||
| break; | |||||
| } | } | ||||
| if (kData->time.playing) | if (kData->time.playing) | ||||
| @@ -116,7 +116,8 @@ const unsigned short RACK_EVENT_COUNT = 512; | |||||
| enum EnginePostAction { | enum EnginePostAction { | ||||
| EnginePostActionNull, | EnginePostActionNull, | ||||
| EnginePostActionRemovePlugin | |||||
| EnginePostActionRemovePlugin, | |||||
| EnginePostActionSwitchPlugins | |||||
| }; | }; | ||||
| struct EnginePluginData { | struct EnginePluginData { | ||||
| @@ -151,11 +152,18 @@ struct CarlaEngineProtectedData { | |||||
| struct NextAction { | struct NextAction { | ||||
| EnginePostAction opcode; | EnginePostAction opcode; | ||||
| unsigned int pluginId; | unsigned int pluginId; | ||||
| unsigned int value; | |||||
| CarlaMutex mutex; | CarlaMutex mutex; | ||||
| NextAction() | NextAction() | ||||
| : opcode(EnginePostActionNull), | : opcode(EnginePostActionNull), | ||||
| pluginId(0) {} | |||||
| pluginId(0), | |||||
| value(0) {} | |||||
| ~NextAction() | |||||
| { | |||||
| CARLA_ASSERT(opcode == EnginePostActionNull); | |||||
| } | |||||
| void ready() | void ready() | ||||
| { | { | ||||
| @@ -38,6 +38,7 @@ CARLA_BACKEND_START_NAMESPACE | |||||
| // Plugin Helpers, defined in CarlaPlugin.cpp | // Plugin Helpers, defined in CarlaPlugin.cpp | ||||
| extern CarlaEngine* CarlaPluginGetEngine(CarlaPlugin* const plugin); | extern CarlaEngine* CarlaPluginGetEngine(CarlaPlugin* const plugin); | ||||
| extern CarlaEngineClient* CarlaPluginGetEngineClient(CarlaPlugin* const plugin); | |||||
| extern CarlaEngineAudioPort* CarlaPluginGetAudioInPort(CarlaPlugin* const plugin, uint32_t index); | extern CarlaEngineAudioPort* CarlaPluginGetAudioInPort(CarlaPlugin* const plugin, uint32_t index); | ||||
| extern CarlaEngineAudioPort* CarlaPluginGetAudioOutPort(CarlaPlugin* const plugin, uint32_t index); | extern CarlaEngineAudioPort* CarlaPluginGetAudioOutPort(CarlaPlugin* const plugin, uint32_t index); | ||||
| @@ -485,6 +486,7 @@ private: | |||||
| jack_client_t* const kClient; | jack_client_t* const kClient; | ||||
| const bool kUseClient; | const bool kUseClient; | ||||
| friend class CarlaEngineJack; | |||||
| CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineJackClient) | CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineJackClient) | ||||
| }; | }; | ||||
| @@ -737,6 +739,64 @@ public: | |||||
| return new CarlaEngineJackClient(kEngineTypeJack, fOptions.processMode, client); | return new CarlaEngineJackClient(kEngineTypeJack, fOptions.processMode, client); | ||||
| } | } | ||||
| const char* renamePlugin(const unsigned int id, const char* const newName) override | |||||
| { | |||||
| CARLA_ASSERT(kData->curPluginCount > 0); | |||||
| CARLA_ASSERT(id < kData->curPluginCount); | |||||
| CARLA_ASSERT(kData->plugins != nullptr); | |||||
| CARLA_ASSERT(newName != nullptr); | |||||
| if (kData->plugins == nullptr) | |||||
| { | |||||
| setLastError("Critical error: no plugins are currently loaded!"); | |||||
| return nullptr; | |||||
| } | |||||
| CarlaPlugin* const plugin = kData->plugins[id].plugin; | |||||
| if (plugin == nullptr) | |||||
| { | |||||
| carla_stderr("CarlaEngine::clonePlugin(%i) - could not find plugin", id); | |||||
| return nullptr; | |||||
| } | |||||
| CARLA_ASSERT(plugin->id() == id); | |||||
| const char* name = getUniquePluginName(newName); | |||||
| // JACK client rename | |||||
| if (fOptions.processMode == PROCESS_MODE_MULTIPLE_CLIENTS) | |||||
| { | |||||
| // not supported yet in the JACK API | |||||
| if (bridge.client_rename_ptr != nullptr) | |||||
| { | |||||
| jack_client_t* const client = ((CarlaEngineJackClient*)CarlaPluginGetEngineClient(plugin))->kClient; | |||||
| name = bridge.client_rename_ptr(client, name); | |||||
| } | |||||
| else | |||||
| { | |||||
| setLastError("Your current JACK version does not allow renaming of clients"); | |||||
| return nullptr; | |||||
| } | |||||
| } | |||||
| if (name == nullptr) | |||||
| return nullptr; | |||||
| // Rename | |||||
| plugin->setName(name); | |||||
| if (fOptions.processMode == PROCESS_MODE_SINGLE_CLIENT) | |||||
| { | |||||
| // reload plugin to recreate its ports | |||||
| const SaveState& saveState(plugin->getSaveState()); | |||||
| plugin->reload(); | |||||
| plugin->loadSaveState(saveState); | |||||
| } | |||||
| return name; | |||||
| } | |||||
| #ifndef BUILD_BRIDGE | #ifndef BUILD_BRIDGE | ||||
| // ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
| // Patchbay | // Patchbay | ||||
| @@ -449,7 +449,7 @@ public: | |||||
| fInfo.copyright = copyright; | fInfo.copyright = copyright; | ||||
| if (fName.isEmpty()) | if (fName.isEmpty()) | ||||
| fName = kData->engine->getNewUniquePluginName(name); | |||||
| fName = kData->engine->getUniquePluginName(name); | |||||
| break; | break; | ||||
| } | } | ||||
| @@ -1140,7 +1140,7 @@ public: | |||||
| // set info | // set info | ||||
| if (name != nullptr) | if (name != nullptr) | ||||
| fName = kData->engine->getNewUniquePluginName(name); | |||||
| fName = kData->engine->getUniquePluginName(name); | |||||
| fFilename = filename; | fFilename = filename; | ||||
| @@ -235,6 +235,11 @@ CarlaEngine* CarlaPluginGetEngine(CarlaPlugin* const plugin) | |||||
| return CarlaPluginProtectedData::getEngine(plugin); | return CarlaPluginProtectedData::getEngine(plugin); | ||||
| } | } | ||||
| CarlaEngineClient* CarlaPluginGetEngineClient(CarlaPlugin* const plugin) | |||||
| { | |||||
| return CarlaPluginProtectedData::getEngineClient(plugin); | |||||
| } | |||||
| CarlaEngineAudioPort* CarlaPluginGetAudioInPort(CarlaPlugin* const plugin, const uint32_t index) | CarlaEngineAudioPort* CarlaPluginGetAudioInPort(CarlaPlugin* const plugin, const uint32_t index) | ||||
| { | { | ||||
| return CarlaPluginProtectedData::getAudioInPort(plugin, index); | return CarlaPluginProtectedData::getAudioInPort(plugin, index); | ||||
| @@ -977,9 +982,14 @@ bool CarlaPlugin::loadStateFromFile(const char* const filename) | |||||
| // ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
| // Set data (internal stuff) | // Set data (internal stuff) | ||||
| void CarlaPlugin::setId(const unsigned int id) | |||||
| void CarlaPlugin::setId(const unsigned int newId) | |||||
| { | |||||
| fId = newId; | |||||
| } | |||||
| void CarlaPlugin::setName(const char* const newName) | |||||
| { | { | ||||
| fId = id; | |||||
| fName = newName; | |||||
| } | } | ||||
| void CarlaPlugin::setOption(const unsigned int option, const bool yesNo) | void CarlaPlugin::setOption(const unsigned int option, const bool yesNo) | ||||
| @@ -670,6 +670,11 @@ struct CarlaPluginProtectedData { | |||||
| return plugin->kData->engine; | return plugin->kData->engine; | ||||
| } | } | ||||
| static CarlaEngineClient* getEngineClient(CarlaPlugin* const plugin) | |||||
| { | |||||
| return plugin->kData->client; | |||||
| } | |||||
| static CarlaEngineAudioPort* getAudioInPort(CarlaPlugin* const plugin, const uint32_t index) | static CarlaEngineAudioPort* getAudioInPort(CarlaPlugin* const plugin, const uint32_t index) | ||||
| { | { | ||||
| return plugin->kData->audioIn.ports[index].port; | return plugin->kData->audioIn.ports[index].port; | ||||
| @@ -1812,11 +1812,11 @@ public: | |||||
| // get info | // get info | ||||
| if (name != nullptr) | if (name != nullptr) | ||||
| fName = kData->engine->getNewUniquePluginName(name); | |||||
| fName = kData->engine->getUniquePluginName(name); | |||||
| else if (fDescriptor->Name != nullptr) | else if (fDescriptor->Name != nullptr) | ||||
| fName = kData->engine->getNewUniquePluginName(fDescriptor->Name); | |||||
| fName = kData->engine->getUniquePluginName(fDescriptor->Name); | |||||
| else | else | ||||
| fName = kData->engine->getNewUniquePluginName(fDescriptor->Label); | |||||
| fName = kData->engine->getUniquePluginName(fDescriptor->Label); | |||||
| fFilename = filename; | fFilename = filename; | ||||
| @@ -1447,9 +1447,9 @@ public: | |||||
| fLabel = label; | fLabel = label; | ||||
| if (name != nullptr) | if (name != nullptr) | ||||
| fName = kData->engine->getNewUniquePluginName(name); | |||||
| fName = kData->engine->getUniquePluginName(name); | |||||
| else | else | ||||
| fName = kData->engine->getNewUniquePluginName(label); | |||||
| fName = kData->engine->getUniquePluginName(label); | |||||
| // --------------------------------------------------------------- | // --------------------------------------------------------------- | ||||
| // register client | // register client | ||||
| @@ -1392,13 +1392,13 @@ public: | |||||
| fRdfDescriptor = ladspa_rdf_dup(rdfDescriptor); | fRdfDescriptor = ladspa_rdf_dup(rdfDescriptor); | ||||
| if (name != nullptr) | if (name != nullptr) | ||||
| fName = kData->engine->getNewUniquePluginName(name); | |||||
| fName = kData->engine->getUniquePluginName(name); | |||||
| else if (fRdfDescriptor != nullptr && fRdfDescriptor->Title != nullptr) | else if (fRdfDescriptor != nullptr && fRdfDescriptor->Title != nullptr) | ||||
| fName = kData->engine->getNewUniquePluginName(fRdfDescriptor->Title); | |||||
| fName = kData->engine->getUniquePluginName(fRdfDescriptor->Title); | |||||
| else if (fDescriptor->Name != nullptr) | else if (fDescriptor->Name != nullptr) | ||||
| fName = kData->engine->getNewUniquePluginName(fDescriptor->Name); | |||||
| fName = kData->engine->getUniquePluginName(fDescriptor->Name); | |||||
| else | else | ||||
| fName = kData->engine->getNewUniquePluginName(fDescriptor->Label); | |||||
| fName = kData->engine->getUniquePluginName(fDescriptor->Label); | |||||
| fFilename = filename; | fFilename = filename; | ||||
| @@ -1011,9 +1011,9 @@ public: | |||||
| fFilename = filename; | fFilename = filename; | ||||
| if (name != nullptr) | if (name != nullptr) | ||||
| fName = kData->engine->getNewUniquePluginName(name); | |||||
| fName = kData->engine->getUniquePluginName(name); | |||||
| else | else | ||||
| fName = kData->engine->getNewUniquePluginName((const char*)fRealName); | |||||
| fName = kData->engine->getUniquePluginName((const char*)fRealName); | |||||
| // --------------------------------------------------------------- | // --------------------------------------------------------------- | ||||
| // Register client | // Register client | ||||
| @@ -2049,11 +2049,11 @@ public: | |||||
| // get info | // get info | ||||
| if (name != nullptr) | if (name != nullptr) | ||||
| fName = kData->engine->getNewUniquePluginName(name); | |||||
| fName = kData->engine->getUniquePluginName(name); | |||||
| else if (fDescriptor->name != nullptr) | else if (fDescriptor->name != nullptr) | ||||
| fName = kData->engine->getNewUniquePluginName(fDescriptor->name); | |||||
| fName = kData->engine->getUniquePluginName(fDescriptor->name); | |||||
| else | else | ||||
| fName = kData->engine->getNewUniquePluginName(label); | |||||
| fName = kData->engine->getUniquePluginName(label); | |||||
| // --------------------------------------------------------------- | // --------------------------------------------------------------- | ||||
| // register client | // register client | ||||
| @@ -2158,7 +2158,7 @@ public: | |||||
| if (name != nullptr) | if (name != nullptr) | ||||
| { | { | ||||
| fName = kData->engine->getNewUniquePluginName(name); | |||||
| fName = kData->engine->getUniquePluginName(name); | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| @@ -2167,12 +2167,12 @@ public: | |||||
| if (strBuf[0] != '\0') | if (strBuf[0] != '\0') | ||||
| { | { | ||||
| fName = kData->engine->getNewUniquePluginName(strBuf); | |||||
| fName = kData->engine->getUniquePluginName(strBuf); | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| const char* const label = std::strrchr(filename, OS_SEP)+1; | const char* const label = std::strrchr(filename, OS_SEP)+1; | ||||
| fName = kData->engine->getNewUniquePluginName(label); | |||||
| fName = kData->engine->getUniquePluginName(label); | |||||
| } | } | ||||
| } | } | ||||
| @@ -708,7 +708,7 @@ class Host(object): | |||||
| self.lib.carla_remove_all_plugins() | self.lib.carla_remove_all_plugins() | ||||
| def rename_plugin(self, pluginId, newName): | def rename_plugin(self, pluginId, newName): | ||||
| return self.lib.carla_rename_plugin(pluginId, newName) | |||||
| return self.lib.carla_rename_plugin(pluginId, newName.encode("utf-8")) | |||||
| def clone_plugin(self, pluginId): | def clone_plugin(self, pluginId): | ||||
| return self.lib.carla_clone_plugin(pluginId) | return self.lib.carla_clone_plugin(pluginId) | ||||
| @@ -26,7 +26,7 @@ from copy import deepcopy | |||||
| from subprocess import Popen, PIPE | from subprocess import Popen, PIPE | ||||
| from PyQt4.QtCore import pyqtSlot, qWarning, Qt, QByteArray, QSettings, QThread, QTimer, SIGNAL, SLOT | from PyQt4.QtCore import pyqtSlot, qWarning, Qt, QByteArray, QSettings, QThread, QTimer, SIGNAL, SLOT | ||||
| from PyQt4.QtGui import QColor, QCursor, QDialog, QIcon, QInputDialog, QFileDialog, QFontMetrics, QFrame, QMenu | from PyQt4.QtGui import QColor, QCursor, QDialog, QIcon, QInputDialog, QFileDialog, QFontMetrics, QFrame, QMenu | ||||
| from PyQt4.QtGui import QMessageBox, QPainter, QPainterPath, QTableWidgetItem, QVBoxLayout, QWidget | |||||
| from PyQt4.QtGui import QLineEdit, QMessageBox, QPainter, QPainterPath, QTableWidgetItem, QVBoxLayout, QWidget | |||||
| # ------------------------------------------------------------------------------------------------------------ | # ------------------------------------------------------------------------------------------------------------ | ||||
| # Imports (Custom) | # Imports (Custom) | ||||
| @@ -2161,6 +2161,7 @@ class PluginWidget(QFrame): | |||||
| menu.addSeparator() | menu.addSeparator() | ||||
| actClone = menu.addAction(self.tr("Clone")) | actClone = menu.addAction(self.tr("Clone")) | ||||
| actRename = menu.addAction(self.tr("Rename...")) | |||||
| actRemove = menu.addAction(self.tr("Remove")) | actRemove = menu.addAction(self.tr("Remove")) | ||||
| actSel = menu.exec_(QCursor.pos()) | actSel = menu.exec_(QCursor.pos()) | ||||
| @@ -2179,6 +2180,24 @@ class PluginWidget(QFrame): | |||||
| CustomMessageBox(self, QMessageBox.Warning, self.tr("Error"), self.tr("Operation failed"), | CustomMessageBox(self, QMessageBox.Warning, self.tr("Error"), self.tr("Operation failed"), | ||||
| cString(Carla.host.get_last_error()), QMessageBox.Ok, QMessageBox.Ok) | cString(Carla.host.get_last_error()), QMessageBox.Ok, QMessageBox.Ok) | ||||
| elif actSel == actRename: | |||||
| oldName = self.fPluginInfo['name'] | |||||
| newNameTry = QInputDialog.getText(self, self.tr("Rename Plugin"), self.tr("New plugin name:"), QLineEdit.Normal, oldName) | |||||
| if not (newNameTry[1] and newNameTry[0] and oldName != newNameTry[0]): | |||||
| return | |||||
| newName = newNameTry[0] | |||||
| if Carla.host.rename_plugin(self.fPluginId, newName): | |||||
| self.fPluginInfo['name'] = newName | |||||
| self.ui.edit_dialog.fPluginInfo["name"] = newName | |||||
| self.ui.edit_dialog.reloadInfo() | |||||
| self.ui.label_name.setText(newName) | |||||
| else: | |||||
| CustomMessageBox(self, QMessageBox.Warning, self.tr("Error"), self.tr("Operation failed"), | |||||
| cString(Carla.host.get_last_error()), QMessageBox.Ok, QMessageBox.Ok) | |||||
| elif actSel == actRemove: | elif actSel == actRemove: | ||||
| if not Carla.host.remove_plugin(self.fPluginId): | if not Carla.host.remove_plugin(self.fPluginId): | ||||
| CustomMessageBox(self, QMessageBox.Warning, self.tr("Error"), self.tr("Operation failed"), | CustomMessageBox(self, QMessageBox.Warning, self.tr("Error"), self.tr("Operation failed"), | ||||
| @@ -35,6 +35,7 @@ | |||||
| typedef const char* (*jacksym_get_version_string)(); | typedef const char* (*jacksym_get_version_string)(); | ||||
| typedef jack_client_t* (*jacksym_client_open)(const char*, jack_options_t, jack_status_t*, ...); | typedef jack_client_t* (*jacksym_client_open)(const char*, jack_options_t, jack_status_t*, ...); | ||||
| typedef const char* (*jacksym_client_rename)(jack_client_t* client, const char* new_name); | |||||
| typedef int (*jacksym_client_close)(jack_client_t*); | typedef int (*jacksym_client_close)(jack_client_t*); | ||||
| typedef int (*jacksym_client_name_size)(); | typedef int (*jacksym_client_name_size)(); | ||||
| @@ -98,6 +99,7 @@ struct JackBridge { | |||||
| jacksym_get_version_string get_version_string_ptr; | jacksym_get_version_string get_version_string_ptr; | ||||
| jacksym_client_open client_open_ptr; | jacksym_client_open client_open_ptr; | ||||
| jacksym_client_rename client_rename_ptr; | |||||
| jacksym_client_close client_close_ptr; | jacksym_client_close client_close_ptr; | ||||
| jacksym_client_name_size client_name_size_ptr; | jacksym_client_name_size client_name_size_ptr; | ||||
| jacksym_get_client_name get_client_name_ptr; | jacksym_get_client_name get_client_name_ptr; | ||||
| @@ -150,6 +152,7 @@ struct JackBridge { | |||||
| : lib(nullptr), | : lib(nullptr), | ||||
| get_version_string_ptr(nullptr), | get_version_string_ptr(nullptr), | ||||
| client_open_ptr(nullptr), | client_open_ptr(nullptr), | ||||
| client_rename_ptr(nullptr), | |||||
| client_close_ptr(nullptr), | client_close_ptr(nullptr), | ||||
| client_name_size_ptr(nullptr), | client_name_size_ptr(nullptr), | ||||
| get_client_name_ptr(nullptr), | get_client_name_ptr(nullptr), | ||||
| @@ -197,19 +200,18 @@ struct JackBridge { | |||||
| transport_query_ptr(nullptr) | transport_query_ptr(nullptr) | ||||
| { | { | ||||
| #if defined(CARLA_OS_MAC) | #if defined(CARLA_OS_MAC) | ||||
| lib = lib_open("libjack.dylib"); | |||||
| fprintf(stderr, "load JACK DLL FOR MAC\n"); | |||||
| const char* const filename = "libjack.dylib"; | |||||
| #elif defined(CARLA_OS_WIN) && ! defined(__WINE__) | #elif defined(CARLA_OS_WIN) && ! defined(__WINE__) | ||||
| lib = lib_open("libjack.dll"); | |||||
| fprintf(stderr, "load JACK DLL FOR WINDOWS\n"); | |||||
| const char* const filename = "libjack.dll"; | |||||
| #else | #else | ||||
| lib = lib_open("libjack.so"); | |||||
| fprintf(stderr, "load JACK DLL FOR LINUX\n"); | |||||
| const char* const filename = "libjack.so.0"; | |||||
| #endif | #endif | ||||
| lib = lib_open(filename); | |||||
| if (lib == nullptr) | if (lib == nullptr) | ||||
| { | { | ||||
| fprintf(stderr, "Failed to load JACK DLL\n"); | |||||
| fprintf(stderr, "Failed to load JACK DLL, reason:\n%s\n", lib_error(filename)); | |||||
| return; | return; | ||||
| } | } | ||||
| @@ -218,6 +220,7 @@ struct JackBridge { | |||||
| LIB_SYMBOL(get_version_string) | LIB_SYMBOL(get_version_string) | ||||
| LIB_SYMBOL(client_open) | LIB_SYMBOL(client_open) | ||||
| LIB_SYMBOL(client_rename) | |||||
| LIB_SYMBOL(client_close) | LIB_SYMBOL(client_close) | ||||
| LIB_SYMBOL(client_name_size) | LIB_SYMBOL(client_name_size) | ||||
| LIB_SYMBOL(get_client_name) | LIB_SYMBOL(get_client_name) | ||||
| @@ -295,6 +298,13 @@ jack_client_t* jackbridge_client_open(const char* client_name, jack_options_t op | |||||
| return nullptr; | return nullptr; | ||||
| } | } | ||||
| const char* jackbridge_client_rename(jack_client_t* client, const char* new_name) | |||||
| { | |||||
| if (bridge.client_rename_ptr != nullptr) | |||||
| return bridge.client_rename_ptr(client, new_name); | |||||
| return nullptr; | |||||
| } | |||||
| // ----------------------------------------------------------------------------- | // ----------------------------------------------------------------------------- | ||||
| bool jackbridge_client_close(jack_client_t* client) | bool jackbridge_client_close(jack_client_t* client) | ||||
| @@ -164,6 +164,7 @@ typedef void (*JackShutdownCallback)(void *arg); | |||||
| CARLA_EXPORT const char* jackbridge_get_version_string(); | CARLA_EXPORT const char* jackbridge_get_version_string(); | ||||
| CARLA_EXPORT jack_client_t* jackbridge_client_open(const char* client_name, jack_options_t options, jack_status_t* status, ...); | CARLA_EXPORT jack_client_t* jackbridge_client_open(const char* client_name, jack_options_t options, jack_status_t* status, ...); | ||||
| CARLA_EXPORT const char* jackbridge_client_rename(jack_client_t* client, const char* new_name); | |||||
| CARLA_EXPORT bool jackbridge_client_close(jack_client_t* client); | CARLA_EXPORT bool jackbridge_client_close(jack_client_t* client); | ||||
| CARLA_EXPORT int jackbridge_client_name_size(); | CARLA_EXPORT int jackbridge_client_name_size(); | ||||