/* * Carla Plugin Host * Copyright (C) 2011-2020 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 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 doc/GPL.txt file. */ #include "CarlaEngineClient.hpp" #include "CarlaEngineUtils.hpp" #include "CarlaString.hpp" CARLA_BACKEND_START_NAMESPACE // ----------------------------------------------------------------------- static void _getUniquePortName(CarlaString& sname, const CarlaStringList& list) { for (CarlaStringList::Itenerator it = list.begin2(); it.valid(); it.next()) { const char* const portName(it.getValue(nullptr)); CARLA_SAFE_ASSERT_CONTINUE(portName != nullptr && portName[0] != '\0'); // Check if unique name doesn't exist if (sname != portName) continue; // Check if string has already been modified { const std::size_t len(sname.length()); // 1 digit, ex: " (2)" if (sname[len-4] == ' ' && sname[len-3] == '(' && sname.isDigit(len-2) && sname[len-1] == ')') { const int number = sname[len-2] - '0'; if (number == 9) { // next number is 10, 2 digits sname.truncate(len-4); sname += " (10)"; //sname.replace(" (9)", " (10)"); } else sname[len-2] = char('0' + number + 1); continue; } // 2 digits, ex: " (11)" if (sname[len-5] == ' ' && sname[len-4] == '(' && sname.isDigit(len-3) && sname.isDigit(len-2) && sname[len-1] == ')') { char n2 = sname[len-2]; char n3 = sname[len-3]; if (n2 == '9') { n2 = '0'; n3 = static_cast(n3 + 1); } else n2 = static_cast(n2 + 1); sname[len-2] = n2; sname[len-3] = n3; continue; } } // Modify string if not sname += " (2)"; } } // ----------------------------------------------------------------------- // Carla Engine Client #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH CarlaEngineClient::ProtectedData::ProtectedData(const CarlaEngine& eng, EngineInternalGraph& eg, const CarlaPluginPtr p) noexcept #else CarlaEngineClient::ProtectedData::ProtectedData(const CarlaEngine& eng) noexcept #endif : engine(eng), active(false), latency(0), #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH cvSourcePorts(), egraph(eg), plugin(p), #endif audioInList(), audioOutList(), cvInList(), cvOutList(), eventInList(), eventOutList() {} CarlaEngineClient::ProtectedData::~ProtectedData() { carla_debug("CarlaEngineClient::ProtectedData::~ProtectedData()"); #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH CARLA_SAFE_ASSERT(plugin.get() == nullptr); #endif } void CarlaEngineClient::ProtectedData::addAudioPortName(const bool isInput, const char* const name) { CARLA_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0',); CarlaStringList& portList(isInput ? audioInList : audioOutList); portList.append(name); } void CarlaEngineClient::ProtectedData::addCVPortName(const bool isInput, const char* const name) { CARLA_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0',); CarlaStringList& portList(isInput ? cvInList : cvOutList); portList.append(name); } void CarlaEngineClient::ProtectedData::addEventPortName(const bool isInput, const char* const name) { CARLA_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0',); CarlaStringList& portList(isInput ? eventInList : eventOutList); portList.append(name); } const char* CarlaEngineClient::ProtectedData::getUniquePortName(const char* const name) { CARLA_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0', nullptr); CarlaString sname; sname = name; _getUniquePortName(sname, audioInList); _getUniquePortName(sname, audioOutList); _getUniquePortName(sname, cvInList); _getUniquePortName(sname, cvOutList); _getUniquePortName(sname, eventInList); _getUniquePortName(sname, eventOutList); return sname.dup(); } void CarlaEngineClient::ProtectedData::clearPorts() { audioInList.clear(); audioOutList.clear(); cvInList.clear(); cvOutList.clear(); eventInList.clear(); eventOutList.clear(); } // ----------------------------------------------------------------------- CarlaEngineClient::CarlaEngineClient(ProtectedData* const p) : pData(p) { carla_debug("CarlaEngineClient::CarlaEngineClient()"); } CarlaEngineClient::~CarlaEngineClient() noexcept { carla_debug("CarlaEngineClient::~CarlaEngineClient()"); } void CarlaEngineClient::activate() noexcept { CARLA_SAFE_ASSERT(! pData->active); carla_debug("CarlaEngineClient::activate()"); pData->active = true; } void CarlaEngineClient::deactivate(const bool willClose) noexcept { CARLA_SAFE_ASSERT(pData->active || willClose); carla_debug("CarlaEngineClient::deactivate(%s)", bool2str(willClose)); pData->active = false; if (willClose) { #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH pData->cvSourcePorts.resetGraphAndPlugin(); pData->plugin.reset(); #endif } } bool CarlaEngineClient::isActive() const noexcept { return pData->active; } bool CarlaEngineClient::isOk() const noexcept { return true; } uint32_t CarlaEngineClient::getLatency() const noexcept { return pData->latency; } void CarlaEngineClient::setLatency(const uint32_t samples) noexcept { pData->latency = samples; } CarlaEnginePort* CarlaEngineClient::addPort(const EnginePortType portType, const char* const name, const bool isInput, const uint32_t indexOffset) { CARLA_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0', nullptr); carla_debug("CarlaEngineClient::addPort(%i:%s, \"%s\", %s, %u)", portType, EnginePortType2Str(portType), name, bool2str(isInput), indexOffset); switch (portType) { case kEnginePortTypeNull: break; case kEnginePortTypeAudio: pData->addAudioPortName(isInput, name); return new CarlaEngineAudioPort(*this, isInput, indexOffset); case kEnginePortTypeCV: pData->addCVPortName(isInput, name); return new CarlaEngineCVPort(*this, isInput, indexOffset); case kEnginePortTypeEvent: pData->addEventPortName(isInput, name); return new CarlaEngineEventPort(*this, isInput, indexOffset); } carla_stderr("CarlaEngineClient::addPort(%i, \"%s\", %s) - invalid type", portType, name, bool2str(isInput)); return nullptr; } bool CarlaEngineClient::removePort(const EnginePortType portType, const char* const name, const bool isInput) { CARLA_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0', false); carla_debug("CarlaEngineClient::removePort(%i:%s, \"%s\", %s)", portType, EnginePortType2Str(portType), name, bool2str(isInput)); switch (portType) { case kEnginePortTypeNull: break; case kEnginePortTypeAudio: { CarlaStringList& portList(isInput ? pData->audioInList : pData->audioOutList); portList.append(name); return portList.removeOne(name); } case kEnginePortTypeCV: { CarlaStringList& portList(isInput ? pData->cvInList : pData->cvOutList); return portList.removeOne(name); } case kEnginePortTypeEvent: { CarlaStringList& portList(isInput ? pData->eventInList : pData->eventOutList); return portList.removeOne(name); } } return false; } #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH CarlaEngineCVSourcePorts* CarlaEngineClient::createCVSourcePorts() { pData->cvSourcePorts.setGraphAndPlugin(pData->egraph.getPatchbayGraphOrNull(), pData->plugin); return &pData->cvSourcePorts; } #endif const CarlaEngine& CarlaEngineClient::getEngine() const noexcept { return pData->engine; } EngineProcessMode CarlaEngineClient::getProcessMode() const noexcept { return pData->engine.getProccessMode(); } uint CarlaEngineClient::getPortCount(const EnginePortType portType, const bool isInput) const noexcept { size_t ret = 0; switch (portType) { case kEnginePortTypeNull: break; case kEnginePortTypeAudio: ret = isInput ? pData->audioInList.count() : pData->audioOutList.count(); break; case kEnginePortTypeCV: ret = isInput ? pData->cvInList.count() : pData->cvOutList.count(); break; case kEnginePortTypeEvent: ret = isInput ? pData->eventInList.count() : pData->eventOutList.count(); break; } return static_cast(ret); } const char* CarlaEngineClient::getAudioPortName(const bool isInput, const uint index) const noexcept { CarlaStringList& portList(isInput ? pData->audioInList : pData->audioOutList); CARLA_SAFE_ASSERT_RETURN(index < portList.count(), nullptr); return portList.getAt(index); } const char* CarlaEngineClient::getCVPortName(const bool isInput, const uint index) const noexcept { CarlaStringList& portList(isInput ? pData->cvInList : pData->cvOutList); CARLA_SAFE_ASSERT_RETURN(index < portList.count(), nullptr); return portList.getAt(index); } const char* CarlaEngineClient::getEventPortName(const bool isInput, const uint index) const noexcept { CarlaStringList& portList(isInput ? pData->eventInList : pData->eventOutList); CARLA_SAFE_ASSERT_RETURN(index < portList.count(), nullptr); return portList.getAt(index); } // ----------------------------------------------------------------------- CARLA_BACKEND_END_NAMESPACE