| @@ -1801,16 +1801,26 @@ public: | |||||
| // write parameter values | // write parameter values | ||||
| for (uint32_t i=0; i < pData->param.count; ++i) | for (uint32_t i=0; i < pData->param.count; ++i) | ||||
| { | { | ||||
| if (! fPipeServer.writeMessage("control\n", 8)) | |||||
| return; | |||||
| ParameterData& pdata(pData->param.data[i]); | |||||
| std::snprintf(tmpBuf, 0xff, "%i\n", pData->param.data[i].rindex); | |||||
| if (! fPipeServer.writeMessage(tmpBuf)) | |||||
| return; | |||||
| if (pdata.hints & PARAMETER_IS_NOT_SAVED) | |||||
| { | |||||
| int32_t rindex = pdata.rindex; | |||||
| CARLA_SAFE_ASSERT_CONTINUE(rindex - static_cast<int32_t>(fRdfDescriptor->PortCount) >= 0); | |||||
| std::snprintf(tmpBuf, 0xff, "%.12g\n", static_cast<double>(getParameterValue(i))); | |||||
| if (! fPipeServer.writeMessage(tmpBuf)) | |||||
| return; | |||||
| rindex -= static_cast<int32_t>(fRdfDescriptor->PortCount); | |||||
| CARLA_SAFE_ASSERT_CONTINUE(rindex < static_cast<int32_t>(fRdfDescriptor->ParameterCount)); | |||||
| if (! fPipeServer.writeLv2ParameterMessage(fRdfDescriptor->Parameters[rindex].URI, | |||||
| getParameterValue(i), false)) | |||||
| return; | |||||
| } | |||||
| else | |||||
| { | |||||
| if (! fPipeServer.writeControlMessage(static_cast<uint32_t>(pData->param.data[i].rindex), | |||||
| getParameterValue(i), false)) | |||||
| return; | |||||
| } | |||||
| } | } | ||||
| // ready to show | // ready to show | ||||
| @@ -4669,20 +4679,16 @@ public: | |||||
| if (fExt.options != nullptr && fExt.options->set != nullptr) | if (fExt.options != nullptr && fExt.options->set != nullptr) | ||||
| { | { | ||||
| LV2_Options_Option options[2]; | |||||
| carla_zeroStructs(options, 2); | |||||
| LV2_Options_Option options[4]; | |||||
| carla_zeroStructs(options, 4); | |||||
| carla_copyStruct(options[0], fLv2Options.opts[CarlaPluginLV2Options::MaxBlockLenth]); | carla_copyStruct(options[0], fLv2Options.opts[CarlaPluginLV2Options::MaxBlockLenth]); | ||||
| fExt.options->set(fHandle, options); | |||||
| carla_copyStruct(options[0], fLv2Options.opts[CarlaPluginLV2Options::NominalBlockLenth]); | |||||
| fExt.options->set(fHandle, options); | |||||
| carla_copyStruct(options[1], fLv2Options.opts[CarlaPluginLV2Options::NominalBlockLenth]); | |||||
| if (fLv2Options.minBufferSize != 1) | if (fLv2Options.minBufferSize != 1) | ||||
| { | |||||
| carla_copyStruct(options[0], fLv2Options.opts[CarlaPluginLV2Options::MinBlockLenth]); | |||||
| fExt.options->set(fHandle, options); | |||||
| } | |||||
| carla_copyStruct(options[2], fLv2Options.opts[CarlaPluginLV2Options::MinBlockLenth]); | |||||
| fExt.options->set(fHandle, options); | |||||
| } | } | ||||
| } | } | ||||
| @@ -4703,15 +4709,8 @@ public: | |||||
| if (fExt.options != nullptr && fExt.options->set != nullptr) | if (fExt.options != nullptr && fExt.options->set != nullptr) | ||||
| { | { | ||||
| LV2_Options_Option options[2]; | LV2_Options_Option options[2]; | ||||
| carla_zeroStructs(options, 2); | |||||
| LV2_Options_Option& optSampleRate(options[0]); | |||||
| optSampleRate.context = LV2_OPTIONS_INSTANCE; | |||||
| optSampleRate.subject = 0; | |||||
| optSampleRate.key = kUridParamSampleRate; | |||||
| optSampleRate.size = sizeof(float); | |||||
| optSampleRate.type = kUridAtomFloat; | |||||
| optSampleRate.value = &fLv2Options.sampleRate; | |||||
| carla_copyStruct(options[0], fLv2Options.opts[CarlaPluginLV2Options::SampleRate]); | |||||
| carla_zeroStruct(options[1]); | |||||
| fExt.options->set(fHandle, options); | fExt.options->set(fHandle, options); | ||||
| } | } | ||||
| @@ -4844,8 +4843,25 @@ public: | |||||
| if (fUI.type == UI::TYPE_BRIDGE) | if (fUI.type == UI::TYPE_BRIDGE) | ||||
| { | { | ||||
| if (fPipeServer.isPipeRunning()) | |||||
| fPipeServer.writeControlMessage(static_cast<uint32_t>(pData->param.data[index].rindex), value); | |||||
| if (! fPipeServer.isPipeRunning()) | |||||
| return; | |||||
| ParameterData& pdata(pData->param.data[index]); | |||||
| if (pdata.hints & PARAMETER_IS_NOT_SAVED) | |||||
| { | |||||
| int32_t rindex = pdata.rindex; | |||||
| CARLA_SAFE_ASSERT_RETURN(rindex - static_cast<int32_t>(fRdfDescriptor->PortCount) >= 0,); | |||||
| rindex -= static_cast<int32_t>(fRdfDescriptor->PortCount); | |||||
| CARLA_SAFE_ASSERT_RETURN(rindex < static_cast<int32_t>(fRdfDescriptor->ParameterCount),); | |||||
| fPipeServer.writeLv2ParameterMessage(fRdfDescriptor->Parameters[rindex].URI, value, true); | |||||
| } | |||||
| else | |||||
| { | |||||
| fPipeServer.writeControlMessage(static_cast<uint32_t>(pData->param.data[index].rindex), value, true); | |||||
| } | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| @@ -5926,6 +5942,49 @@ public: | |||||
| } | } | ||||
| } | } | ||||
| void handleUIBridgeParameter(const char* const uri, const float value) | |||||
| { | |||||
| CARLA_SAFE_ASSERT_RETURN(uri != nullptr,); | |||||
| carla_debug("CarlaPluginLV2::handleUIBridgeParameter(%s, %f)", uri, static_cast<double>(value)); | |||||
| uint32_t parameterId = UINT32_MAX; | |||||
| for (uint32_t i=0; i < fRdfDescriptor->ParameterCount; ++i) | |||||
| { | |||||
| const LV2_RDF_Parameter& rdfParam(fRdfDescriptor->Parameters[i]); | |||||
| if (std::strcmp(rdfParam.URI, uri) == 0) | |||||
| { | |||||
| const int32_t rindex = static_cast<int32_t>(fRdfDescriptor->PortCount + i); | |||||
| switch (rdfParam.Type) | |||||
| { | |||||
| case LV2_PARAMETER_BOOL: | |||||
| case LV2_PARAMETER_INT: | |||||
| // case LV2_PARAMETER_LONG: | |||||
| case LV2_PARAMETER_FLOAT: | |||||
| case LV2_PARAMETER_DOUBLE: | |||||
| for (uint32_t j=0; j < pData->param.count; ++j) | |||||
| { | |||||
| if (pData->param.data[j].rindex == rindex) | |||||
| { | |||||
| parameterId = j; | |||||
| break; | |||||
| } | |||||
| } | |||||
| break; | |||||
| } | |||||
| break; | |||||
| } | |||||
| } | |||||
| if (parameterId == UINT32_MAX) | |||||
| return; | |||||
| setParameterValue(parameterId, value, false, true, true); | |||||
| } | |||||
| // ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
| void handleLilvSetPortValue(const char* const portSymbol, const void* const value, const uint32_t size, const uint32_t type) | void handleLilvSetPortValue(const char* const portSymbol, const void* const value, const uint32_t size, const uint32_t type) | ||||
| @@ -7748,6 +7807,21 @@ bool CarlaPipeServerLV2::msgReceived(const char* const msg) noexcept | |||||
| return true; | return true; | ||||
| } | } | ||||
| if (std::strcmp(msg, "pcontrol") == 0) | |||||
| { | |||||
| const char* uri; | |||||
| float value; | |||||
| CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(uri, true), true); | |||||
| CARLA_SAFE_ASSERT_RETURN(readNextLineAsFloat(value), true); | |||||
| try { | |||||
| kPlugin->handleUIBridgeParameter(uri, value); | |||||
| } CARLA_SAFE_EXCEPTION("magReceived pcontrol"); | |||||
| return true; | |||||
| } | |||||
| if (std::strcmp(msg, "atom") == 0) | if (std::strcmp(msg, "atom") == 0) | ||||
| { | { | ||||
| uint32_t index, atomTotalSize, base64Size; | uint32_t index, atomTotalSize, base64Size; | ||||
| @@ -177,6 +177,18 @@ bool CarlaBridgeFormat::msgReceived(const char* const msg) noexcept | |||||
| return true; | return true; | ||||
| } | } | ||||
| if (std::strcmp(msg, "parameter") == 0) | |||||
| { | |||||
| const char* uri; | |||||
| float value; | |||||
| CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(uri, true), true); | |||||
| CARLA_SAFE_ASSERT_RETURN(readNextLineAsFloat(value), true); | |||||
| // dspParameterChanged(index, value); | |||||
| return true; | |||||
| } | |||||
| if (std::strcmp(msg, "program") == 0) | if (std::strcmp(msg, "program") == 0) | ||||
| { | { | ||||
| uint32_t index; | uint32_t index; | ||||
| @@ -71,6 +71,8 @@ class HostWindow(QMainWindow): | |||||
| self.fPorts = self.fPlugin['ports'] | self.fPorts = self.fPlugin['ports'] | ||||
| self.fPortSymbols = {} | self.fPortSymbols = {} | ||||
| self.fPortValues = {} | self.fPortValues = {} | ||||
| self.fParamTypes = {} | |||||
| self.fParamValues = {} | |||||
| for port in self.fPorts['control']['input']: | for port in self.fPorts['control']['input']: | ||||
| self.fPortSymbols[port['index']] = (port['symbol'], False) | self.fPortSymbols[port['index']] = (port['symbol'], False) | ||||
| @@ -80,6 +82,32 @@ class HostWindow(QMainWindow): | |||||
| self.fPortSymbols[port['index']] = (port['symbol'], True) | self.fPortSymbols[port['index']] = (port['symbol'], True) | ||||
| self.fPortValues [port['index']] = port['ranges']['default'] | self.fPortValues [port['index']] = port['ranges']['default'] | ||||
| for parameter in self.fPlugin['parameters']: | |||||
| if parameter['ranges'] is None: | |||||
| continue | |||||
| if parameter['type'] == "http://lv2plug.in/ns/ext/atom#Bool": | |||||
| paramtype = 'b' | |||||
| elif parameter['type'] == "http://lv2plug.in/ns/ext/atom#Int": | |||||
| paramtype = 'i' | |||||
| elif parameter['type'] == "http://lv2plug.in/ns/ext/atom#Long": | |||||
| paramtype = 'l' | |||||
| elif parameter['type'] == "http://lv2plug.in/ns/ext/atom#Float": | |||||
| paramtype = 'f' | |||||
| elif parameter['type'] == "http://lv2plug.in/ns/ext/atom#Double": | |||||
| paramtype = 'g' | |||||
| elif parameter['type'] == "http://lv2plug.in/ns/ext/atom#String": | |||||
| paramtype = 's' | |||||
| elif parameter['type'] == "http://lv2plug.in/ns/ext/atom#Path": | |||||
| paramtype = 'p' | |||||
| elif parameter['type'] == "http://lv2plug.in/ns/ext/atom#URI": | |||||
| paramtype = 'u' | |||||
| else: | |||||
| continue | |||||
| if paramtype not in ('s','p','u') and parameter['ranges']['minimum'] == parameter['ranges']['maximum']: | |||||
| continue | |||||
| self.fParamTypes [parameter['uri']] = paramtype | |||||
| self.fParamValues[parameter['uri']] = parameter['ranges']['default'] | |||||
| # ---------------------------------------------------------------------------------------------------- | # ---------------------------------------------------------------------------------------------------- | ||||
| # Init pipe | # Init pipe | ||||
| @@ -217,7 +245,7 @@ class HostWindow(QMainWindow): | |||||
| self.setFixedSize(size) | self.setFixedSize(size) | ||||
| # set initial values | # set initial values | ||||
| self.fCurrentFrame.evaluateJavaScript("icongui.setPortValue(':bypass', 0, null)") | |||||
| self.fCurrentFrame.evaluateJavaScript("icongui.setPortWidgetsValue(':bypass', 0, null)") | |||||
| for index in self.fPortValues.keys(): | for index in self.fPortValues.keys(): | ||||
| symbol, isOutput = self.fPortSymbols[index] | symbol, isOutput = self.fPortSymbols[index] | ||||
| @@ -225,7 +253,14 @@ class HostWindow(QMainWindow): | |||||
| if isOutput: | if isOutput: | ||||
| self.fCurrentFrame.evaluateJavaScript("icongui.setOutputPortValue('%s', %f)" % (symbol, value)) | self.fCurrentFrame.evaluateJavaScript("icongui.setOutputPortValue('%s', %f)" % (symbol, value)) | ||||
| else: | else: | ||||
| self.fCurrentFrame.evaluateJavaScript("icongui.setPortValue('%s', %f, null)" % (symbol, value)) | |||||
| self.fCurrentFrame.evaluateJavaScript("icongui.setPortWidgetsValue('%s', %f, null)" % (symbol, value)) | |||||
| for uri in self.fParamValues.keys(): | |||||
| ptype = self.fParamTypes[uri] | |||||
| value = str(self.fParamValues[uri]) | |||||
| print("icongui.setWritableParameterValue('%s', '%c', %s, 'from-carla')" % (uri, ptype, value)) | |||||
| self.fCurrentFrame.evaluateJavaScript("icongui.setWritableParameterValue('%s', '%c', %s, 'from-carla')" % ( | |||||
| uri, ptype, value)) | |||||
| # final setup | # final setup | ||||
| self.fCanSetValues = True | self.fCanSetValues = True | ||||
| @@ -251,12 +286,20 @@ class HostWindow(QMainWindow): | |||||
| continue | continue | ||||
| oldValue = self.fPortValues[index] | oldValue = self.fPortValues[index] | ||||
| newValue = self.fCurrentFrame.evaluateJavaScript("icongui.getPortValue('%s')" % (symbol,)) | |||||
| newValue = self.fCurrentFrame.evaluateJavaScript("icongui.controls['%s'].value" % (symbol,)) | |||||
| if oldValue != newValue: | if oldValue != newValue: | ||||
| self.fPortValues[index] = newValue | self.fPortValues[index] = newValue | ||||
| self.send(["control", index, newValue]) | self.send(["control", index, newValue]) | ||||
| for uri in self.fParamValues.keys(): | |||||
| oldValue = self.fParamValues[uri] | |||||
| newValue = self.fCurrentFrame.evaluateJavaScript("icongui.parameters['%s'].value" % (uri,)) | |||||
| if oldValue != newValue: | |||||
| self.fParamValues[uri] = newValue | |||||
| self.send(["pcontrol", uri, newValue]) | |||||
| # -------------------------------------------------------------------------------------------------------- | # -------------------------------------------------------------------------------------------------------- | ||||
| @pyqtSlot(bool) | @pyqtSlot(bool) | ||||
| @@ -280,7 +323,12 @@ class HostWindow(QMainWindow): | |||||
| if msg == "control": | if msg == "control": | ||||
| index = self.readlineblock_int() | index = self.readlineblock_int() | ||||
| value = self.readlineblock_float() | value = self.readlineblock_float() | ||||
| self.dspParameterChanged(index, value) | |||||
| self.dspControlChanged(index, value) | |||||
| elif msg == "parameter": | |||||
| uri = self.readlineblock() | |||||
| value = self.readlineblock_float() | |||||
| self.dspParameterChanged(uri, value) | |||||
| elif msg == "program": | elif msg == "program": | ||||
| index = self.readlineblock_int() | index = self.readlineblock_int() | ||||
| @@ -288,7 +336,7 @@ class HostWindow(QMainWindow): | |||||
| elif msg == "midiprogram": | elif msg == "midiprogram": | ||||
| bank = self.readlineblock_int() | bank = self.readlineblock_int() | ||||
| program = self.readlineblock_float() | |||||
| program = self.readlineblock_int() | |||||
| self.dspMidiProgramChanged(bank, program) | self.dspMidiProgramChanged(bank, program) | ||||
| elif msg == "configure": | elif msg == "configure": | ||||
| @@ -305,12 +353,14 @@ class HostWindow(QMainWindow): | |||||
| elif msg == "atom": | elif msg == "atom": | ||||
| index = self.readlineblock_int() | index = self.readlineblock_int() | ||||
| size = self.readlineblock_int() | |||||
| atomsize = self.readlineblock_int() | |||||
| base64size = self.readlineblock_int() | |||||
| base64atom = self.readlineblock() | base64atom = self.readlineblock() | ||||
| # nothing to do yet | # nothing to do yet | ||||
| elif msg == "urid": | elif msg == "urid": | ||||
| urid = self.readlineblock_int() | urid = self.readlineblock_int() | ||||
| size = self.readlineblock_int() | |||||
| uri = self.readlineblock() | uri = self.readlineblock() | ||||
| # nothing to do yet | # nothing to do yet | ||||
| @@ -347,17 +397,33 @@ class HostWindow(QMainWindow): | |||||
| # -------------------------------------------------------------------------------------------------------- | # -------------------------------------------------------------------------------------------------------- | ||||
| def dspParameterChanged(self, index, value): | |||||
| def dspControlChanged(self, index, value): | |||||
| self.fPortValues[index] = value | self.fPortValues[index] = value | ||||
| if self.fCurrentFrame is not None and self.fCanSetValues: | |||||
| symbol, isOutput = self.fPortSymbols[index] | |||||
| if self.fCurrentFrame is None or not self.fCanSetValues: | |||||
| return | |||||
| if isOutput: | |||||
| self.fPortValues[index] = value | |||||
| self.fCurrentFrame.evaluateJavaScript("icongui.setOutputPortValue('%s', %f)" % (symbol, value)) | |||||
| else: | |||||
| self.fCurrentFrame.evaluateJavaScript("icongui.setPortValue('%s', %f, null)" % (symbol, value)) | |||||
| symbol, isOutput = self.fPortSymbols[index] | |||||
| if isOutput: | |||||
| self.fCurrentFrame.evaluateJavaScript("icongui.setOutputPortValue('%s', %f)" % (symbol, value)) | |||||
| else: | |||||
| self.fCurrentFrame.evaluateJavaScript("icongui.setPortWidgetsValue('%s', %f, null)" % (symbol, value)) | |||||
| def dspParameterChanged(self, uri, value): | |||||
| print("dspParameterChanged", uri, value) | |||||
| if uri not in self.fParamValues: | |||||
| return | |||||
| self.fParamValues[uri] = value | |||||
| if self.fCurrentFrame is None or not self.fCanSetValues: | |||||
| return | |||||
| ptype = self.fParamTypes[uri] | |||||
| self.fCurrentFrame.evaluateJavaScript("icongui.setWritableParameterValue('%s', '%c', %f, 'from-carla')" % ( | |||||
| uri, ptype, value)) | |||||
| def dspProgramChanged(self, index): | def dspProgramChanged(self, index): | ||||
| return | return | ||||
| @@ -2,7 +2,7 @@ | |||||
| # -*- coding: utf-8 -*- | # -*- coding: utf-8 -*- | ||||
| # Carla bridge for LV2 modguis | # Carla bridge for LV2 modguis | ||||
| # Copyright (C) 2015-2019 Filipe Coelho <falktx@falktx.com> | |||||
| # Copyright (C) 2015-2020 Filipe Coelho <falktx@falktx.com> | |||||
| # | # | ||||
| # This program is free software; you can redistribute it and/or | # This program is free software; you can redistribute it and/or | ||||
| # modify it under the terms of the GNU General Public License as | # modify it under the terms of the GNU General Public License as | ||||
| @@ -958,33 +958,38 @@ bool CarlaPipeCommon::flushMessages() const noexcept | |||||
| // ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
| void CarlaPipeCommon::writeErrorMessage(const char* const error) const noexcept | |||||
| bool CarlaPipeCommon::writeErrorMessage(const char* const error) const noexcept | |||||
| { | { | ||||
| CARLA_SAFE_ASSERT_RETURN(error != nullptr && error[0] != '\0',); | |||||
| CARLA_SAFE_ASSERT_RETURN(error != nullptr && error[0] != '\0', false); | |||||
| const CarlaMutexLocker cml(pData->writeLock); | const CarlaMutexLocker cml(pData->writeLock); | ||||
| if (! _writeMsgBuffer("error\n", 6)) | if (! _writeMsgBuffer("error\n", 6)) | ||||
| return; | |||||
| return false; | |||||
| if (! writeAndFixMessage(error)) | if (! writeAndFixMessage(error)) | ||||
| return; | |||||
| return false; | |||||
| flushMessages(); | flushMessages(); | ||||
| return true; | |||||
| } | } | ||||
| void CarlaPipeCommon::writeControlMessage(const uint32_t index, const float value) const noexcept | |||||
| bool CarlaPipeCommon::writeControlMessage(const uint32_t index, const float value, const bool withWriteLock) const noexcept | |||||
| { | { | ||||
| if (withWriteLock) | |||||
| { | |||||
| const CarlaMutexLocker cml(pData->writeLock); | |||||
| return writeControlMessage(index, value, false); | |||||
| } | |||||
| char tmpBuf[0xff]; | char tmpBuf[0xff]; | ||||
| tmpBuf[0xfe] = '\0'; | tmpBuf[0xfe] = '\0'; | ||||
| const CarlaMutexLocker cml(pData->writeLock); | |||||
| if (! _writeMsgBuffer("control\n", 8)) | if (! _writeMsgBuffer("control\n", 8)) | ||||
| return; | |||||
| return false; | |||||
| std::snprintf(tmpBuf, 0xfe, "%i\n", index); | std::snprintf(tmpBuf, 0xfe, "%i\n", index); | ||||
| if (! _writeMsgBuffer(tmpBuf, std::strlen(tmpBuf))) | if (! _writeMsgBuffer(tmpBuf, std::strlen(tmpBuf))) | ||||
| return; | |||||
| return false; | |||||
| { | { | ||||
| const CarlaScopedLocale csl; | const CarlaScopedLocale csl; | ||||
| @@ -992,29 +997,31 @@ void CarlaPipeCommon::writeControlMessage(const uint32_t index, const float valu | |||||
| } | } | ||||
| if (! _writeMsgBuffer(tmpBuf, std::strlen(tmpBuf))) | if (! _writeMsgBuffer(tmpBuf, std::strlen(tmpBuf))) | ||||
| return; | |||||
| return false; | |||||
| flushMessages(); | flushMessages(); | ||||
| return true; | |||||
| } | } | ||||
| void CarlaPipeCommon::writeConfigureMessage(const char* const key, const char* const value) const noexcept | |||||
| bool CarlaPipeCommon::writeConfigureMessage(const char* const key, const char* const value) const noexcept | |||||
| { | { | ||||
| CARLA_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',); | |||||
| CARLA_SAFE_ASSERT_RETURN(value != nullptr,); | |||||
| CARLA_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0', false); | |||||
| CARLA_SAFE_ASSERT_RETURN(value != nullptr, false); | |||||
| const CarlaMutexLocker cml(pData->writeLock); | const CarlaMutexLocker cml(pData->writeLock); | ||||
| if (! _writeMsgBuffer("configure\n", 10)) | if (! _writeMsgBuffer("configure\n", 10)) | ||||
| return; | |||||
| return false; | |||||
| if (! writeAndFixMessage(key)) | if (! writeAndFixMessage(key)) | ||||
| return; | |||||
| return false; | |||||
| if (! writeAndFixMessage(value)) | if (! writeAndFixMessage(value)) | ||||
| return; | |||||
| return false; | |||||
| flushMessages(); | flushMessages(); | ||||
| return true; | |||||
| } | } | ||||
| void CarlaPipeCommon::writeProgramMessage(const uint32_t index) const noexcept | |||||
| bool CarlaPipeCommon::writeProgramMessage(const uint32_t index) const noexcept | |||||
| { | { | ||||
| char tmpBuf[0xff]; | char tmpBuf[0xff]; | ||||
| tmpBuf[0xfe] = '\0'; | tmpBuf[0xfe] = '\0'; | ||||
| @@ -1022,16 +1029,17 @@ void CarlaPipeCommon::writeProgramMessage(const uint32_t index) const noexcept | |||||
| const CarlaMutexLocker cml(pData->writeLock); | const CarlaMutexLocker cml(pData->writeLock); | ||||
| if (! _writeMsgBuffer("program\n", 8)) | if (! _writeMsgBuffer("program\n", 8)) | ||||
| return; | |||||
| return false; | |||||
| std::snprintf(tmpBuf, 0xfe, "%i\n", index); | std::snprintf(tmpBuf, 0xfe, "%i\n", index); | ||||
| if (! _writeMsgBuffer(tmpBuf, std::strlen(tmpBuf))) | if (! _writeMsgBuffer(tmpBuf, std::strlen(tmpBuf))) | ||||
| return; | |||||
| return false; | |||||
| flushMessages(); | flushMessages(); | ||||
| return true; | |||||
| } | } | ||||
| void CarlaPipeCommon::writeProgramMessage(const uint8_t channel, const uint32_t bank, const uint32_t program) const noexcept | |||||
| bool CarlaPipeCommon::writeProgramMessage(const uint8_t channel, const uint32_t bank, const uint32_t program) const noexcept | |||||
| { | { | ||||
| char tmpBuf[0xff]; | char tmpBuf[0xff]; | ||||
| tmpBuf[0xfe] = '\0'; | tmpBuf[0xfe] = '\0'; | ||||
| @@ -1039,24 +1047,25 @@ void CarlaPipeCommon::writeProgramMessage(const uint8_t channel, const uint32_t | |||||
| const CarlaMutexLocker cml(pData->writeLock); | const CarlaMutexLocker cml(pData->writeLock); | ||||
| if (! _writeMsgBuffer("program\n", 8)) | if (! _writeMsgBuffer("program\n", 8)) | ||||
| return; | |||||
| return false; | |||||
| std::snprintf(tmpBuf, 0xfe, "%i\n", channel); | std::snprintf(tmpBuf, 0xfe, "%i\n", channel); | ||||
| if (! _writeMsgBuffer(tmpBuf, std::strlen(tmpBuf))) | if (! _writeMsgBuffer(tmpBuf, std::strlen(tmpBuf))) | ||||
| return; | |||||
| return false; | |||||
| std::snprintf(tmpBuf, 0xfe, "%i\n", bank); | std::snprintf(tmpBuf, 0xfe, "%i\n", bank); | ||||
| if (! _writeMsgBuffer(tmpBuf, std::strlen(tmpBuf))) | if (! _writeMsgBuffer(tmpBuf, std::strlen(tmpBuf))) | ||||
| return; | |||||
| return false; | |||||
| std::snprintf(tmpBuf, 0xfe, "%i\n", program); | std::snprintf(tmpBuf, 0xfe, "%i\n", program); | ||||
| if (! _writeMsgBuffer(tmpBuf, std::strlen(tmpBuf))) | if (! _writeMsgBuffer(tmpBuf, std::strlen(tmpBuf))) | ||||
| return; | |||||
| return false; | |||||
| flushMessages(); | flushMessages(); | ||||
| return true; | |||||
| } | } | ||||
| void CarlaPipeCommon::writeMidiProgramMessage(const uint32_t bank, const uint32_t program) const noexcept | |||||
| bool CarlaPipeCommon::writeMidiProgramMessage(const uint32_t bank, const uint32_t program) const noexcept | |||||
| { | { | ||||
| char tmpBuf[0xff]; | char tmpBuf[0xff]; | ||||
| tmpBuf[0xfe] = '\0'; | tmpBuf[0xfe] = '\0'; | ||||
| @@ -1064,20 +1073,21 @@ void CarlaPipeCommon::writeMidiProgramMessage(const uint32_t bank, const uint32_ | |||||
| const CarlaMutexLocker cml(pData->writeLock); | const CarlaMutexLocker cml(pData->writeLock); | ||||
| if (! _writeMsgBuffer("midiprogram\n", 12)) | if (! _writeMsgBuffer("midiprogram\n", 12)) | ||||
| return; | |||||
| return false; | |||||
| std::snprintf(tmpBuf, 0xfe, "%i\n", bank); | std::snprintf(tmpBuf, 0xfe, "%i\n", bank); | ||||
| if (! _writeMsgBuffer(tmpBuf, std::strlen(tmpBuf))) | if (! _writeMsgBuffer(tmpBuf, std::strlen(tmpBuf))) | ||||
| return; | |||||
| return false; | |||||
| std::snprintf(tmpBuf, 0xfe, "%i\n", program); | std::snprintf(tmpBuf, 0xfe, "%i\n", program); | ||||
| if (! _writeMsgBuffer(tmpBuf, std::strlen(tmpBuf))) | if (! _writeMsgBuffer(tmpBuf, std::strlen(tmpBuf))) | ||||
| return; | |||||
| return false; | |||||
| flushMessages(); | flushMessages(); | ||||
| return true; | |||||
| } | } | ||||
| void CarlaPipeCommon::writeReloadProgramsMessage(const int32_t index) const noexcept | |||||
| bool CarlaPipeCommon::writeReloadProgramsMessage(const int32_t index) const noexcept | |||||
| { | { | ||||
| char tmpBuf[0xff]; | char tmpBuf[0xff]; | ||||
| tmpBuf[0xfe] = '\0'; | tmpBuf[0xfe] = '\0'; | ||||
| @@ -1085,20 +1095,21 @@ void CarlaPipeCommon::writeReloadProgramsMessage(const int32_t index) const noex | |||||
| const CarlaMutexLocker cml(pData->writeLock); | const CarlaMutexLocker cml(pData->writeLock); | ||||
| if (! _writeMsgBuffer("reloadprograms\n", 15)) | if (! _writeMsgBuffer("reloadprograms\n", 15)) | ||||
| return; | |||||
| return false; | |||||
| std::snprintf(tmpBuf, 0xfe, "%i\n", index); | std::snprintf(tmpBuf, 0xfe, "%i\n", index); | ||||
| if (! _writeMsgBuffer(tmpBuf, std::strlen(tmpBuf))) | if (! _writeMsgBuffer(tmpBuf, std::strlen(tmpBuf))) | ||||
| return; | |||||
| return false; | |||||
| flushMessages(); | flushMessages(); | ||||
| return true; | |||||
| } | } | ||||
| void CarlaPipeCommon::writeMidiNoteMessage(const bool onOff, const uint8_t channel, const uint8_t note, const uint8_t velocity) const noexcept | |||||
| bool CarlaPipeCommon::writeMidiNoteMessage(const bool onOff, const uint8_t channel, const uint8_t note, const uint8_t velocity) const noexcept | |||||
| { | { | ||||
| CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS,); | |||||
| CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,); | |||||
| CARLA_SAFE_ASSERT_RETURN(velocity < MAX_MIDI_VALUE,); | |||||
| CARLA_SAFE_ASSERT_RETURN(channel < MAX_MIDI_CHANNELS, false); | |||||
| CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE, false); | |||||
| CARLA_SAFE_ASSERT_RETURN(velocity < MAX_MIDI_VALUE, false); | |||||
| char tmpBuf[0xff]; | char tmpBuf[0xff]; | ||||
| tmpBuf[0xfe] = '\0'; | tmpBuf[0xfe] = '\0'; | ||||
| @@ -1106,30 +1117,31 @@ void CarlaPipeCommon::writeMidiNoteMessage(const bool onOff, const uint8_t chann | |||||
| const CarlaMutexLocker cml(pData->writeLock); | const CarlaMutexLocker cml(pData->writeLock); | ||||
| if (! _writeMsgBuffer("note\n", 5)) | if (! _writeMsgBuffer("note\n", 5)) | ||||
| return; | |||||
| return false; | |||||
| std::snprintf(tmpBuf, 0xfe, "%s\n", bool2str(onOff)); | std::snprintf(tmpBuf, 0xfe, "%s\n", bool2str(onOff)); | ||||
| if (! _writeMsgBuffer(tmpBuf, std::strlen(tmpBuf))) | if (! _writeMsgBuffer(tmpBuf, std::strlen(tmpBuf))) | ||||
| return; | |||||
| return false; | |||||
| std::snprintf(tmpBuf, 0xfe, "%i\n", channel); | std::snprintf(tmpBuf, 0xfe, "%i\n", channel); | ||||
| if (! _writeMsgBuffer(tmpBuf, std::strlen(tmpBuf))) | if (! _writeMsgBuffer(tmpBuf, std::strlen(tmpBuf))) | ||||
| return; | |||||
| return false; | |||||
| std::snprintf(tmpBuf, 0xfe, "%i\n", note); | std::snprintf(tmpBuf, 0xfe, "%i\n", note); | ||||
| if (! _writeMsgBuffer(tmpBuf, std::strlen(tmpBuf))) | if (! _writeMsgBuffer(tmpBuf, std::strlen(tmpBuf))) | ||||
| return; | |||||
| return false; | |||||
| std::snprintf(tmpBuf, 0xfe, "%i\n", velocity); | std::snprintf(tmpBuf, 0xfe, "%i\n", velocity); | ||||
| if (! _writeMsgBuffer(tmpBuf, std::strlen(tmpBuf))) | if (! _writeMsgBuffer(tmpBuf, std::strlen(tmpBuf))) | ||||
| return; | |||||
| return false; | |||||
| flushMessages(); | flushMessages(); | ||||
| return true; | |||||
| } | } | ||||
| void CarlaPipeCommon::writeLv2AtomMessage(const uint32_t index, const LV2_Atom* const atom) const noexcept | |||||
| bool CarlaPipeCommon::writeLv2AtomMessage(const uint32_t index, const LV2_Atom* const atom) const noexcept | |||||
| { | { | ||||
| CARLA_SAFE_ASSERT_RETURN(atom != nullptr,); | |||||
| CARLA_SAFE_ASSERT_RETURN(atom != nullptr, false); | |||||
| char tmpBuf[0xff]; | char tmpBuf[0xff]; | ||||
| tmpBuf[0xfe] = '\0'; | tmpBuf[0xfe] = '\0'; | ||||
| @@ -1140,30 +1152,60 @@ void CarlaPipeCommon::writeLv2AtomMessage(const uint32_t index, const LV2_Atom* | |||||
| const CarlaMutexLocker cml(pData->writeLock); | const CarlaMutexLocker cml(pData->writeLock); | ||||
| if (! _writeMsgBuffer("atom\n", 5)) | if (! _writeMsgBuffer("atom\n", 5)) | ||||
| return; | |||||
| return false; | |||||
| std::snprintf(tmpBuf, 0xfe, "%i\n", index); | std::snprintf(tmpBuf, 0xfe, "%i\n", index); | ||||
| if (! _writeMsgBuffer(tmpBuf, std::strlen(tmpBuf))) | if (! _writeMsgBuffer(tmpBuf, std::strlen(tmpBuf))) | ||||
| return; | |||||
| return false; | |||||
| std::snprintf(tmpBuf, 0xfe, "%i\n", atomTotalSize); | std::snprintf(tmpBuf, 0xfe, "%i\n", atomTotalSize); | ||||
| if (! _writeMsgBuffer(tmpBuf, std::strlen(tmpBuf))) | if (! _writeMsgBuffer(tmpBuf, std::strlen(tmpBuf))) | ||||
| return; | |||||
| return false; | |||||
| std::snprintf(tmpBuf, 0xfe, "%lu\n", static_cast<long unsigned>(base64atom.length())); | std::snprintf(tmpBuf, 0xfe, "%lu\n", static_cast<long unsigned>(base64atom.length())); | ||||
| if (! _writeMsgBuffer(tmpBuf, std::strlen(tmpBuf))) | if (! _writeMsgBuffer(tmpBuf, std::strlen(tmpBuf))) | ||||
| return; | |||||
| return false; | |||||
| if (! writeAndFixMessage(base64atom.buffer())) | if (! writeAndFixMessage(base64atom.buffer())) | ||||
| return; | |||||
| return false; | |||||
| flushMessages(); | flushMessages(); | ||||
| return true; | |||||
| } | } | ||||
| void CarlaPipeCommon::writeLv2UridMessage(const uint32_t urid, const char* const uri) const noexcept | |||||
| bool CarlaPipeCommon::writeLv2ParameterMessage(const char* const uri, const float value, const bool withWriteLock) const noexcept | |||||
| { | { | ||||
| CARLA_SAFE_ASSERT_RETURN(urid != 0,); | |||||
| CARLA_SAFE_ASSERT_RETURN(uri != nullptr && uri[0] != '\0',); | |||||
| if (withWriteLock) | |||||
| { | |||||
| const CarlaMutexLocker cml(pData->writeLock); | |||||
| return writeLv2ParameterMessage(uri, value, false); | |||||
| } | |||||
| char tmpBuf[0xff]; | |||||
| tmpBuf[0xfe] = '\0'; | |||||
| if (! _writeMsgBuffer("parameter\n", 10)) | |||||
| return false; | |||||
| if (! writeAndFixMessage(uri)) | |||||
| return false; | |||||
| { | |||||
| const CarlaScopedLocale csl; | |||||
| std::snprintf(tmpBuf, 0xfe, "%.12g\n", static_cast<double>(value)); | |||||
| } | |||||
| if (! _writeMsgBuffer(tmpBuf, std::strlen(tmpBuf))) | |||||
| return false; | |||||
| flushMessages(); | |||||
| return true; | |||||
| } | |||||
| bool CarlaPipeCommon::writeLv2UridMessage(const uint32_t urid, const char* const uri) const noexcept | |||||
| { | |||||
| CARLA_SAFE_ASSERT_RETURN(urid != 0, false); | |||||
| CARLA_SAFE_ASSERT_RETURN(uri != nullptr && uri[0] != '\0', false); | |||||
| char tmpBuf[0xff]; | char tmpBuf[0xff]; | ||||
| tmpBuf[0xfe] = '\0'; | tmpBuf[0xfe] = '\0'; | ||||
| @@ -1171,20 +1213,21 @@ void CarlaPipeCommon::writeLv2UridMessage(const uint32_t urid, const char* const | |||||
| const CarlaMutexLocker cml(pData->writeLock); | const CarlaMutexLocker cml(pData->writeLock); | ||||
| if (! _writeMsgBuffer("urid\n", 5)) | if (! _writeMsgBuffer("urid\n", 5)) | ||||
| return; | |||||
| return false; | |||||
| std::snprintf(tmpBuf, 0xfe, "%i\n", urid); | std::snprintf(tmpBuf, 0xfe, "%i\n", urid); | ||||
| if (! _writeMsgBuffer(tmpBuf, std::strlen(tmpBuf))) | if (! _writeMsgBuffer(tmpBuf, std::strlen(tmpBuf))) | ||||
| return; | |||||
| return false; | |||||
| std::snprintf(tmpBuf, 0xfe, "%lu\n", static_cast<long unsigned>(std::strlen(uri))); | std::snprintf(tmpBuf, 0xfe, "%lu\n", static_cast<long unsigned>(std::strlen(uri))); | ||||
| if (! _writeMsgBuffer(tmpBuf, std::strlen(tmpBuf))) | if (! _writeMsgBuffer(tmpBuf, std::strlen(tmpBuf))) | ||||
| return; | |||||
| return false; | |||||
| if (! writeAndFixMessage(uri)) | if (! writeAndFixMessage(uri)) | ||||
| return; | |||||
| return false; | |||||
| flushMessages(); | flushMessages(); | ||||
| return true; | |||||
| } | } | ||||
| // ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
| @@ -180,52 +180,57 @@ public: | |||||
| /*! | /*! | ||||
| * Write an "error" message. | * Write an "error" message. | ||||
| */ | */ | ||||
| void writeErrorMessage(const char* error) const noexcept; | |||||
| bool writeErrorMessage(const char* error) const noexcept; | |||||
| /*! | /*! | ||||
| * Write a "control" message used for parameter changes. | |||||
| * Write a "control" message used for parameter/control changes. | |||||
| */ | */ | ||||
| void writeControlMessage(uint32_t index, float value) const noexcept; | |||||
| bool writeControlMessage(uint32_t index, float value, bool withWriteLock = true) const noexcept; | |||||
| /*! | /*! | ||||
| * Write a "configure" message used for state changes. | * Write a "configure" message used for state changes. | ||||
| */ | */ | ||||
| void writeConfigureMessage(const char* key, const char* value) const noexcept; | |||||
| bool writeConfigureMessage(const char* key, const char* value) const noexcept; | |||||
| /*! | /*! | ||||
| * Write a "program" message (using index). | * Write a "program" message (using index). | ||||
| */ | */ | ||||
| void writeProgramMessage(uint32_t index) const noexcept; | |||||
| bool writeProgramMessage(uint32_t index) const noexcept; | |||||
| /*! | /*! | ||||
| * Write a "program" message (using channel, bank and program). | * Write a "program" message (using channel, bank and program). | ||||
| */ | */ | ||||
| void writeProgramMessage(uint8_t channel, uint32_t bank, uint32_t program) const noexcept; | |||||
| bool writeProgramMessage(uint8_t channel, uint32_t bank, uint32_t program) const noexcept; | |||||
| /*! | /*! | ||||
| * Write a "midiprogram" message (using bank and program). | * Write a "midiprogram" message (using bank and program). | ||||
| */ | */ | ||||
| void writeMidiProgramMessage(uint32_t bank, uint32_t program) const noexcept; | |||||
| bool writeMidiProgramMessage(uint32_t bank, uint32_t program) const noexcept; | |||||
| /*! | /*! | ||||
| * Write a "reloadprograms" message. | * Write a "reloadprograms" message. | ||||
| */ | */ | ||||
| void writeReloadProgramsMessage(int32_t index) const noexcept; | |||||
| bool writeReloadProgramsMessage(int32_t index) const noexcept; | |||||
| /*! | /*! | ||||
| * Write a MIDI "note" message. | * Write a MIDI "note" message. | ||||
| */ | */ | ||||
| void writeMidiNoteMessage(bool onOff, uint8_t channel, uint8_t note, uint8_t velocity) const noexcept; | |||||
| bool writeMidiNoteMessage(bool onOff, uint8_t channel, uint8_t note, uint8_t velocity) const noexcept; | |||||
| /*! | /*! | ||||
| * Write an lv2 "atom" message. | * Write an lv2 "atom" message. | ||||
| */ | */ | ||||
| void writeLv2AtomMessage(uint32_t index, const LV2_Atom* atom) const noexcept; | |||||
| bool writeLv2AtomMessage(uint32_t index, const LV2_Atom* atom) const noexcept; | |||||
| /*! | |||||
| * Write an lv2 "parameter" message. | |||||
| */ | |||||
| bool writeLv2ParameterMessage(const char* uri, float value, bool withWriteLock = true) const noexcept; | |||||
| /*! | /*! | ||||
| * Write an lv2 "urid" message. | * Write an lv2 "urid" message. | ||||
| */ | */ | ||||
| void writeLv2UridMessage(uint32_t urid, const char* uri) const noexcept; | |||||
| bool writeLv2UridMessage(uint32_t urid, const char* uri) const noexcept; | |||||
| // ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||