* unfinished commit Signed-off-by: falkTX <falktx@falktx.com> * Finish optimizationstags/v2.1-rc2
| @@ -1561,8 +1561,8 @@ public: | |||
| // manually write messages so we can take the lock for ourselves | |||
| { | |||
| char tmpBuf[0xff+1]; | |||
| tmpBuf[0xff] = '\0'; | |||
| char tmpBuf[0xff]; | |||
| tmpBuf[0xfe] = '\0'; | |||
| const CarlaMutexLocker cml(fPipeServer.getPipeLock()); | |||
| const CarlaScopedLocale csl; | |||
| @@ -1575,12 +1575,17 @@ public: | |||
| continue; | |||
| const std::string& uri(*it); | |||
| std::snprintf(tmpBuf, 0xff, "%u\n", u); | |||
| if (! fPipeServer.writeMessage("urid\n", 5)) | |||
| return; | |||
| std::snprintf(tmpBuf, 0xfe, "%u\n", u); | |||
| if (! fPipeServer.writeMessage(tmpBuf)) | |||
| return; | |||
| std::snprintf(tmpBuf, 0xfe, "%lu\n", static_cast<long unsigned>(uri.length())); | |||
| if (! fPipeServer.writeMessage(tmpBuf)) | |||
| return; | |||
| if (! fPipeServer.writeAndFixMessage(uri.c_str())) | |||
| return; | |||
| } | |||
| @@ -7252,15 +7257,16 @@ bool CarlaPipeServerLV2::msgReceived(const char* const msg) noexcept | |||
| if (std::strcmp(msg, "atom") == 0) | |||
| { | |||
| uint32_t index, size; | |||
| uint32_t index, atomTotalSize, base64Size; | |||
| const char* base64atom; | |||
| CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(index), true); | |||
| CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(size), true); | |||
| CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(base64atom, false), true); | |||
| CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(atomTotalSize), true); | |||
| CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(base64Size), true); | |||
| CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(base64atom, false, base64Size), true); | |||
| std::vector<uint8_t> chunk(carla_getChunkFromBase64String(base64atom)); | |||
| CARLA_SAFE_ASSERT_RETURN(chunk.size() >= sizeof(LV2_Atom), true); | |||
| CARLA_SAFE_ASSERT_UINT2_RETURN(chunk.size() >= sizeof(LV2_Atom), chunk.size(), sizeof(LV2_Atom), true); | |||
| #ifdef CARLA_PROPER_CPP11_SUPPORT | |||
| const LV2_Atom* const atom((const LV2_Atom*)chunk.data()); | |||
| @@ -7291,11 +7297,12 @@ bool CarlaPipeServerLV2::msgReceived(const char* const msg) noexcept | |||
| if (std::strcmp(msg, "urid") == 0) | |||
| { | |||
| uint32_t urid; | |||
| uint32_t urid, size; | |||
| const char* uri; | |||
| CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(urid), true); | |||
| CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(uri, false), true); | |||
| CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(size), true); | |||
| CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(uri, false, size), true); | |||
| if (urid != 0) | |||
| { | |||
| @@ -88,7 +88,7 @@ public: | |||
| #endif | |||
| delete[] fLastReadLine; | |||
| fLastReadLine = CarlaPipeClient::_readlineblock(true, timeout); | |||
| fLastReadLine = CarlaPipeClient::_readlineblock(true, 0, timeout); | |||
| return fLastReadLine; | |||
| } | |||
| @@ -103,7 +103,7 @@ public: | |||
| } | |||
| #endif | |||
| if (const char* const line = CarlaPipeClient::_readlineblock(false, timeout)) | |||
| if (const char* const line = CarlaPipeClient::_readlineblock(false, 0, timeout)) | |||
| return std::strcmp(line, "true") == 0; | |||
| return false; | |||
| @@ -120,7 +120,7 @@ public: | |||
| } | |||
| #endif | |||
| if (const char* const line = CarlaPipeClient::_readlineblock(false, timeout)) | |||
| if (const char* const line = CarlaPipeClient::_readlineblock(false, 0, timeout)) | |||
| return std::atoi(line); | |||
| return 0; | |||
| @@ -137,7 +137,7 @@ public: | |||
| } | |||
| #endif | |||
| if (const char* const line = CarlaPipeClient::_readlineblock(false, timeout)) | |||
| if (const char* const line = CarlaPipeClient::_readlineblock(false, 0, timeout)) | |||
| return std::atof(line); | |||
| return 0.0; | |||
| @@ -42,7 +42,8 @@ CarlaBridgeFormat::CarlaBridgeFormat() noexcept | |||
| fLastMsgTimer(-1), | |||
| fToolkit(nullptr), | |||
| fLib(nullptr), | |||
| fLibFilename() | |||
| fLibFilename(), | |||
| fBase64ReservedChunk() | |||
| { | |||
| carla_debug("CarlaBridgeFormat::CarlaBridgeFormat()"); | |||
| @@ -120,6 +121,50 @@ bool CarlaBridgeFormat::msgReceived(const char* const msg) noexcept | |||
| if (fLastMsgTimer > 0) | |||
| --fLastMsgTimer; | |||
| if (std::strcmp(msg, "atom") == 0) | |||
| { | |||
| uint32_t index, atomTotalSize, base64Size; | |||
| const char* base64atom; | |||
| CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(index), true); | |||
| CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(atomTotalSize), true); | |||
| CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(base64Size), true); | |||
| CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(base64atom, false, base64Size), true); | |||
| carla_getChunkFromBase64String_impl(fBase64ReservedChunk, base64atom); | |||
| CARLA_SAFE_ASSERT_UINT2_RETURN(fBase64ReservedChunk.size() >= sizeof(LV2_Atom), | |||
| fBase64ReservedChunk.size(), sizeof(LV2_Atom), true); | |||
| #ifdef CARLA_PROPER_CPP11_SUPPORT | |||
| const LV2_Atom* const atom((const LV2_Atom*)fBase64ReservedChunk.data()); | |||
| #else | |||
| const LV2_Atom* const atom((const LV2_Atom*)&fBase64ReservedChunk.front()); | |||
| #endif | |||
| const uint32_t atomTotalSizeCheck(lv2_atom_total_size(atom)); | |||
| CARLA_SAFE_ASSERT_UINT2_RETURN(atomTotalSizeCheck == atomTotalSize, atomTotalSizeCheck, atomTotalSize, true); | |||
| CARLA_SAFE_ASSERT_UINT2_RETURN(atomTotalSizeCheck == fBase64ReservedChunk.size(), | |||
| atomTotalSizeCheck, fBase64ReservedChunk.size(), true); | |||
| dspAtomReceived(index, atom); | |||
| return true; | |||
| } | |||
| if (std::strcmp(msg, "urid") == 0) | |||
| { | |||
| uint32_t urid, size; | |||
| const char* uri; | |||
| CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(urid), true); | |||
| CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(size), true); | |||
| CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(uri, false, size), true); | |||
| if (urid != 0) | |||
| dspURIDReceived(urid, uri); | |||
| return true; | |||
| } | |||
| if (std::strcmp(msg, "control") == 0) | |||
| { | |||
| uint32_t index; | |||
| @@ -181,46 +226,6 @@ bool CarlaBridgeFormat::msgReceived(const char* const msg) noexcept | |||
| return true; | |||
| } | |||
| if (std::strcmp(msg, "atom") == 0) | |||
| { | |||
| uint32_t index, atomTotalSize; | |||
| const char* base64atom; | |||
| CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(index), true); | |||
| CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(atomTotalSize), true); | |||
| CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(base64atom, false), true); | |||
| std::vector<uint8_t> chunk(carla_getChunkFromBase64String(base64atom)); | |||
| CARLA_SAFE_ASSERT_RETURN(chunk.size() >= sizeof(LV2_Atom), true); | |||
| #ifdef CARLA_PROPER_CPP11_SUPPORT | |||
| const LV2_Atom* const atom((const LV2_Atom*)chunk.data()); | |||
| #else | |||
| const LV2_Atom* const atom((const LV2_Atom*)&chunk.front()); | |||
| #endif | |||
| const uint32_t atomTotalSizeCheck(lv2_atom_total_size(atom)); | |||
| CARLA_SAFE_ASSERT_RETURN(atomTotalSizeCheck == atomTotalSize, true); | |||
| CARLA_SAFE_ASSERT_RETURN(atomTotalSizeCheck == chunk.size(), true); | |||
| dspAtomReceived(index, atom); | |||
| return true; | |||
| } | |||
| if (std::strcmp(msg, "urid") == 0) | |||
| { | |||
| uint32_t urid; | |||
| const char* uri; | |||
| CARLA_SAFE_ASSERT_RETURN(readNextLineAsUInt(urid), true); | |||
| CARLA_SAFE_ASSERT_RETURN(readNextLineAsString(uri, false), true); | |||
| if (urid != 0) | |||
| dspURIDReceived(urid, uri); | |||
| return true; | |||
| } | |||
| if (std::strcmp(msg, "uiOptions") == 0) | |||
| { | |||
| BridgeFormatOptions opts; | |||
| @@ -27,6 +27,8 @@ | |||
| #include "lv2/atom.h" | |||
| #include "lv2/urid.h" | |||
| #include <vector> | |||
| CARLA_BRIDGE_UI_START_NAMESPACE | |||
| /*! | |||
| @@ -161,6 +163,7 @@ protected: | |||
| lib_t fLib; | |||
| CarlaString fLibFilename; | |||
| std::vector<uint8_t> fBase64ReservedChunk; | |||
| /*! @internal */ | |||
| bool msgReceived(const char* const msg) noexcept override; | |||
| @@ -108,7 +108,7 @@ public: | |||
| // MacOS and Win32 have event-loops to run, so minimize sleep time | |||
| carla_msleep(1); | |||
| #else | |||
| carla_msleep(20); | |||
| carla_msleep(33); | |||
| #endif | |||
| } | |||
| } | |||
| @@ -60,15 +60,15 @@ bool isBase64Char(const char c) | |||
| // ----------------------------------------------------------------------- | |||
| static inline | |||
| std::vector<uint8_t> carla_getChunkFromBase64String(const char* const base64string) | |||
| void carla_getChunkFromBase64String_impl(std::vector<uint8_t>& vector, const char* const base64string) | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(base64string != nullptr, std::vector<uint8_t>()); | |||
| CARLA_SAFE_ASSERT_RETURN(base64string != nullptr,); | |||
| uint i=0, j=0; | |||
| uint charArray3[3], charArray4[4]; | |||
| std::vector<uint8_t> ret; | |||
| ret.reserve(std::strlen(base64string)*3/4 + 4); | |||
| vector.clear(); | |||
| vector.reserve(std::strlen(base64string)*3/4 + 4); | |||
| for (std::size_t l=0, len=std::strlen(base64string); l<len; ++l) | |||
| { | |||
| @@ -93,7 +93,7 @@ std::vector<uint8_t> carla_getChunkFromBase64String(const char* const base64stri | |||
| charArray3[2] = ((charArray4[2] & 0x3) << 6) + charArray4[3]; | |||
| for (i=0; i<3; ++i) | |||
| ret.push_back(static_cast<uint8_t>(charArray3[i])); | |||
| vector.push_back(static_cast<uint8_t>(charArray3[i])); | |||
| i = 0; | |||
| } | |||
| @@ -112,9 +112,16 @@ std::vector<uint8_t> carla_getChunkFromBase64String(const char* const base64stri | |||
| charArray3[2] = ((charArray4[2] & 0x3) << 6) + charArray4[3]; | |||
| for (j=0; i>0 && j<i-1; j++) | |||
| ret.push_back(static_cast<uint8_t>(charArray3[j])); | |||
| vector.push_back(static_cast<uint8_t>(charArray3[j])); | |||
| } | |||
| } | |||
| static inline | |||
| std::vector<uint8_t> carla_getChunkFromBase64String(const char* const base64string) | |||
| { | |||
| std::vector<uint8_t> ret; | |||
| carla_getChunkFromBase64String_impl(ret, base64string); | |||
| return ret; | |||
| } | |||
| @@ -659,10 +659,12 @@ void CarlaPipeCommon::idlePipe(const bool onlyOnce) noexcept | |||
| for (;;) | |||
| { | |||
| const char* const msg = _readline(true, readSucess); | |||
| const char* const msg = _readline(true, 0, readSucess); | |||
| if (msg == nullptr || ! readSucess) | |||
| if (! readSucess) | |||
| break; | |||
| if (msg == nullptr) | |||
| continue; | |||
| pData->isReading = true; | |||
| @@ -835,11 +837,14 @@ bool CarlaPipeCommon::readNextLineAsDouble(double& value) const noexcept | |||
| return false; | |||
| } | |||
| bool CarlaPipeCommon::readNextLineAsString(const char*& value, const bool allocateString) const noexcept | |||
| bool CarlaPipeCommon::readNextLineAsString(const char*& value, const bool allocateString, uint32_t size) const noexcept | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(pData->isReading, false); | |||
| if (const char* const msg = _readlineblock(allocateString)) | |||
| if (size >= 0xffff) | |||
| size = 0; | |||
| if (const char* const msg = _readlineblock(allocateString, static_cast<uint16_t>(size))) | |||
| { | |||
| value = msg; | |||
| return true; | |||
| @@ -1140,6 +1145,10 @@ void CarlaPipeCommon::writeLv2AtomMessage(const uint32_t index, const LV2_Atom* | |||
| if (! _writeMsgBuffer(tmpBuf, std::strlen(tmpBuf))) | |||
| return; | |||
| std::snprintf(tmpBuf, 0xfe, "%lu\n", static_cast<long unsigned>(base64atom.length())); | |||
| if (! _writeMsgBuffer(tmpBuf, std::strlen(tmpBuf))) | |||
| return; | |||
| if (! writeAndFixMessage(base64atom.buffer())) | |||
| return; | |||
| @@ -1163,6 +1172,10 @@ void CarlaPipeCommon::writeLv2UridMessage(const uint32_t urid, const char* const | |||
| if (! _writeMsgBuffer(tmpBuf, std::strlen(tmpBuf))) | |||
| return; | |||
| std::snprintf(tmpBuf, 0xfe, "%lu\n", static_cast<long unsigned>(std::strlen(uri))); | |||
| if (! _writeMsgBuffer(tmpBuf, std::strlen(tmpBuf))) | |||
| return; | |||
| if (! writeAndFixMessage(uri)) | |||
| return; | |||
| @@ -1172,7 +1185,7 @@ void CarlaPipeCommon::writeLv2UridMessage(const uint32_t urid, const char* const | |||
| // ------------------------------------------------------------------- | |||
| // internal | |||
| const char* CarlaPipeCommon::_readline(const bool allocReturn, bool& readSucess) const noexcept | |||
| const char* CarlaPipeCommon::_readline(const bool allocReturn, const uint16_t size, bool& readSucess) const noexcept | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(pData->pipeRecv != INVALID_PIPE_VALUE, nullptr); | |||
| @@ -1183,31 +1196,79 @@ const char* CarlaPipeCommon::_readline(const bool allocReturn, bool& readSucess) | |||
| pData->tmpStr.clear(); | |||
| for (int i=0; i<0xfffe; ++i) | |||
| if (size == 0 || size == 1) | |||
| { | |||
| try { | |||
| #ifdef CARLA_OS_WIN | |||
| ret = ReadFileWin32(pData->pipeRecv, pData->ovRecv, &c, 1); | |||
| #else | |||
| ret = ::read(pData->pipeRecv, &c, 1); | |||
| #endif | |||
| } CARLA_SAFE_EXCEPTION_BREAK("CarlaPipeCommon::readline() - read"); | |||
| for (int i=0; i<0xfffe; ++i) | |||
| { | |||
| try { | |||
| #ifdef CARLA_OS_WIN | |||
| ret = ReadFileWin32(pData->pipeRecv, pData->ovRecv, &c, 1); | |||
| #else | |||
| ret = ::read(pData->pipeRecv, &c, 1); | |||
| #endif | |||
| } CARLA_SAFE_EXCEPTION_BREAK("CarlaPipeCommon::readline() - read"); | |||
| if (ret != 1 || c == '\n') | |||
| break; | |||
| if (ret != 1 || c == '\n') | |||
| break; | |||
| if (c == '\r') | |||
| c = '\n'; | |||
| if (c == '\r') | |||
| c = '\n'; | |||
| *ptr++ = c; | |||
| *ptr++ = c; | |||
| if (i+1 == 0xfffe) | |||
| { | |||
| i = 0; | |||
| *ptr = '\0'; | |||
| tooBig = true; | |||
| pData->tmpStr += pData->tmpBuf; | |||
| ptr = pData->tmpBuf; | |||
| } | |||
| } | |||
| } | |||
| else | |||
| { | |||
| uint16_t remaining = size; | |||
| readSucess = false; | |||
| if (i+1 == 0xfffe) | |||
| for (;;) | |||
| { | |||
| i = 0; | |||
| try { | |||
| #ifdef CARLA_OS_WIN | |||
| ret = ReadFileWin32(pData->pipeRecv, pData->ovRecv, ptr, remaining); | |||
| #else | |||
| ret = ::read(pData->pipeRecv, ptr, remaining); | |||
| #endif | |||
| } CARLA_SAFE_EXCEPTION_RETURN("CarlaPipeCommon::readline() - read", nullptr); | |||
| if (ret == -1 && errno == EAGAIN) | |||
| continue; | |||
| CARLA_SAFE_ASSERT_INT2_RETURN(ret > 0, ret, remaining, nullptr); | |||
| CARLA_SAFE_ASSERT_INT2_RETURN(ret <= (ssize_t)remaining, ret, remaining, nullptr); | |||
| for (ssize_t i=0; i<ret; ++i) | |||
| { | |||
| if (ptr[i] == '\r') | |||
| ptr[i] = '\n'; | |||
| } | |||
| ptr += ret; | |||
| *ptr = '\0'; | |||
| tooBig = true; | |||
| pData->tmpStr += pData->tmpBuf; | |||
| ptr = pData->tmpBuf; | |||
| remaining = static_cast<uint16_t>(remaining - ret); | |||
| if (remaining != 0) | |||
| continue; | |||
| readSucess = true; | |||
| if (allocReturn) | |||
| { | |||
| pData->tmpStr = pData->tmpBuf; | |||
| return pData->tmpStr.releaseBufferPointer(); | |||
| } | |||
| return pData->tmpBuf; | |||
| } | |||
| } | |||
| @@ -1230,21 +1291,24 @@ const char* CarlaPipeCommon::_readline(const bool allocReturn, bool& readSucess) | |||
| return nullptr; | |||
| } | |||
| readSucess = true; | |||
| if (! allocReturn && ! tooBig) | |||
| return pData->tmpBuf; | |||
| readSucess = true; | |||
| return allocReturn ? pData->tmpStr.releaseBufferPointer() : pData->tmpStr.buffer(); | |||
| } | |||
| const char* CarlaPipeCommon::_readlineblock(const bool allocReturn, const uint32_t timeOutMilliseconds) const noexcept | |||
| const char* CarlaPipeCommon::_readlineblock(const bool allocReturn, | |||
| const uint16_t size, | |||
| const uint32_t timeOutMilliseconds) const noexcept | |||
| { | |||
| const uint32_t timeoutEnd = water::Time::getMillisecondCounter() + timeOutMilliseconds; | |||
| bool readSucess; | |||
| for (;;) | |||
| { | |||
| const char* const msg = _readline(allocReturn, readSucess); | |||
| const char* const msg = _readline(allocReturn, size, readSucess); | |||
| if (readSucess) | |||
| return msg; | |||
| @@ -1263,7 +1327,7 @@ const char* CarlaPipeCommon::_readlineblock(const bool allocReturn, const uint32 | |||
| for (;;) | |||
| { | |||
| const char* const msg = _readline(allocReturn, readSucess); | |||
| const char* const msg = _readline(allocReturn, size, readSucess); | |||
| if (readSucess) | |||
| return msg; | |||
| @@ -142,7 +142,7 @@ public: | |||
| * Read the next line as a string. | |||
| * @note: @a value must be deleted if valid. | |||
| */ | |||
| bool readNextLineAsString(const char*& value, bool allocateString) const noexcept; | |||
| bool readNextLineAsString(const char*& value, bool allocateString, uint32_t size = 0) const noexcept; | |||
| // ------------------------------------------------------------------- | |||
| // write messages, must be locked before calling | |||
| @@ -236,10 +236,10 @@ protected: | |||
| // ------------------------------------------------------------------- | |||
| /*! @internal */ | |||
| const char* _readline(bool allocReturn, bool& readSucess) const noexcept; | |||
| const char* _readline(bool allocReturn, uint16_t size, bool& readSucess) const noexcept; | |||
| /*! @internal */ | |||
| const char* _readlineblock(bool allocReturn, uint32_t timeOutMilliseconds = 50) const noexcept; | |||
| const char* _readlineblock(bool allocReturn, uint16_t size = 0, uint32_t timeOutMilliseconds = 50) const noexcept; | |||
| /*! @internal */ | |||
| bool _writeMsgBuffer(const char* msg, std::size_t size) const noexcept; | |||