diff --git a/source/backend/plugin/CarlaPlugin.cpp b/source/backend/plugin/CarlaPlugin.cpp index eca386c3d..c0ea22955 100644 --- a/source/backend/plugin/CarlaPlugin.cpp +++ b/source/backend/plugin/CarlaPlugin.cpp @@ -636,12 +636,11 @@ const SaveState& CarlaPlugin::getSaveState() void* data = nullptr; const int32_t dataSize(chunkData(&data)); - if (data != nullptr && dataSize >= 4) + if (data != nullptr && dataSize > 0) { - CarlaString chunkStr; - chunkStr.importBinaryAsBase64((const uint8_t*)data, static_cast(dataSize)); + QByteArray chunk(QByteArray((char*)data, dataSize).toBase64()); - saveState.chunk = carla_strdup(chunkStr); + saveState.chunk = carla_strdup(chunk.constData()); // Don't save anything else if using chunks return saveState; diff --git a/source/backend/plugin/DssiPlugin.cpp b/source/backend/plugin/DssiPlugin.cpp index fc198b94a..c0c7fc389 100644 --- a/source/backend/plugin/DssiPlugin.cpp +++ b/source/backend/plugin/DssiPlugin.cpp @@ -39,8 +39,7 @@ public: fDssiDescriptor(nullptr), fAudioInBuffers(nullptr), fAudioOutBuffers(nullptr), - fParamBuffers(nullptr), - fLastChunk(nullptr) + fParamBuffers(nullptr) { carla_debug("DssiPlugin::DssiPlugin(%p, %i)", engine, id); @@ -91,12 +90,6 @@ public: fDssiDescriptor = nullptr; } - if (fLastChunk != nullptr) - { - delete[] fLastChunk; - fLastChunk = nullptr; - } - clearBuffers(); } @@ -319,21 +312,14 @@ public: if (fDssiDescriptor->set_custom_data == nullptr) return; - if (fLastChunk != nullptr) - { - delete[] fLastChunk; - fLastChunk = nullptr; - } - - const size_t size(CarlaString(stringData).exportAsBase64Binary(&fLastChunk)); + QByteArray chunk(QByteArray::fromBase64(stringData)); - CARLA_ASSERT(size > 0); - CARLA_ASSERT(fLastChunk != nullptr); + CARLA_ASSERT(chunk.size() > 0); - if (size > 0 && fLastChunk != nullptr) + if (chunk.size() > 0) { const ScopedSingleProcessLocker spl(this, true); - fDssiDescriptor->set_custom_data(fHandle, fLastChunk, static_cast(size)); + fDssiDescriptor->set_custom_data(fHandle, chunk.data(), chunk.size()); } } @@ -1920,10 +1906,9 @@ private: const LADSPA_Descriptor* fDescriptor; const DSSI_Descriptor* fDssiDescriptor; - float** fAudioInBuffers; - float** fAudioOutBuffers; - float* fParamBuffers; - uint8_t* fLastChunk; + float** fAudioInBuffers; + float** fAudioOutBuffers; + float* fParamBuffers; snd_seq_event_t fMidiEvents[MAX_MIDI_EVENTS]; CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(DssiPlugin) diff --git a/source/backend/plugin/VstPlugin.cpp b/source/backend/plugin/VstPlugin.cpp index 287aa05aa..02155caff 100644 --- a/source/backend/plugin/VstPlugin.cpp +++ b/source/backend/plugin/VstPlugin.cpp @@ -108,7 +108,7 @@ public: if (fLastChunk != nullptr) { - delete[] fLastChunk; + std::free(fLastChunk); fLastChunk = nullptr; } @@ -289,19 +289,21 @@ public: if (fLastChunk != nullptr) { - delete[] fLastChunk; + std::free(fLastChunk); fLastChunk = nullptr; } - const size_t size(CarlaString(stringData).exportAsBase64Binary(&fLastChunk)); + QByteArray chunk(QByteArray::fromBase64(stringData)); - CARLA_ASSERT(size > 0); - CARLA_ASSERT(fLastChunk != nullptr); + CARLA_ASSERT(chunk.size() > 0); - if (size > 0 && fLastChunk != nullptr) + if (chunk.size() > 0) { + fLastChunk = std::malloc(chunk.size()); + std::memcpy(fLastChunk, chunk.constData(), chunk.size()); + const ScopedSingleProcessLocker spl(this, true); - dispatcher(effSetChunk, 0 /* bank */, size, fLastChunk, 0.0f); + dispatcher(effSetChunk, 0 /* bank */, chunk.size(), fLastChunk, 0.0f); } } @@ -2258,7 +2260,7 @@ private: int fUnique1; AEffect* fEffect; - uint8_t* fLastChunk; + void* fLastChunk; uint32_t fMidiEventCount; VstMidiEvent fMidiEvents[MAX_MIDI_EVENTS*2]; VstTimeInfo_R fTimeInfo; diff --git a/source/backend/standalone/CarlaStandalone.cpp b/source/backend/standalone/CarlaStandalone.cpp index 14e7f411a..f849d3116 100644 --- a/source/backend/standalone/CarlaStandalone.cpp +++ b/source/backend/standalone/CarlaStandalone.cpp @@ -1091,9 +1091,10 @@ const char* carla_get_chunk_data(unsigned int pluginId) void* data = nullptr; const int32_t dataSize = plugin->chunkData(&data); - if (data != nullptr && dataSize >= 4) + if (data != nullptr && dataSize > 0) { - chunkData.importBinaryAsBase64((const uint8_t*)data, static_cast(dataSize)); + QByteArray chunk(QByteArray((char*)data, dataSize).toBase64()); + chunkData = chunk.constData(); return (const char*)chunkData; } else diff --git a/source/tests/Base64.cpp b/source/tests/Base64.cpp index 82cdb339b..2758dca4e 100644 --- a/source/tests/Base64.cpp +++ b/source/tests/Base64.cpp @@ -49,10 +49,12 @@ int main() int i; double d; void* ptr; + char pad[17]; int32_t i32; int64_t i64; bool b; - } blob; + }; + Blob blob; const size_t blobSize = sizeof(Blob); carla_zeroStruct(blob); @@ -66,6 +68,7 @@ int main() blob.i32 = 32; blob.i64 = 64; blob.b = true; + blob.pad[11] = 71; // binary -> base64 char blobEnc[carla_base64_encoded_len(blobSize) + 1]; @@ -90,6 +93,7 @@ int main() assert(blobTest.i32 == 32); assert(blobTest.i64 == 64); assert(blobTest.b == true); + assert(blobTest.pad[11] == 71); } { @@ -110,6 +114,7 @@ int main() assert(blobNew->i32 == 32); assert(blobNew->i64 == 64); assert(blobNew->b == true); + assert(blobNew->pad[11] == 71); delete blobNew; } diff --git a/source/utils/CarlaBase64Utils.hpp b/source/utils/CarlaBase64Utils.hpp deleted file mode 100644 index de91e4938..000000000 --- a/source/utils/CarlaBase64Utils.hpp +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Carla base64 utils imported from qemu source code - * Copyright (C) 2009 Michael Brown - * Copyright (C) 2013 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 GPL.txt file - */ - -#ifndef __CARLA_BASE64_UTILS_HPP__ -#define __CARLA_BASE64_UTILS_HPP__ - -#include "CarlaUtils.hpp" - -#include -#include - -static const char kBase64[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - -/** - * Calculate length of base64-encoded data - * - * @v rawLen Raw data length - * @ret encodedLen Encoded string length (excluding NUL) - */ -static inline -size_t carla_base64_encoded_len(const size_t rawLen) -{ - return (((rawLen + 3 - 1) / 3) * 4); -} - -/** - * Calculate maximum length of base64-decoded string - * - * @v encoded Encoded string - * @v maxRawLen Maximum length of raw data - * - * Note that the exact length of the raw data cannot be known until - * the string is decoded. - */ -static inline -size_t carla_base64_decoded_max_len(const char* const encoded) -{ - return (((std::strlen(encoded) + 4 - 1) / 4) * 3); -} - -/** - * Base64-encode data - * - * @v raw Raw data - * @v len Length of raw data - * @v encoded Buffer for encoded string - * - * The buffer must be the correct length for the encoded string. - * Use something like - * - * char buf[carla_base64_encoded_len(len) + 1]; - * - * (the +1 is for the terminating NUL) to provide a buffer of the correct size. - */ -static inline -void carla_base64_encode(const uint8_t* const raw, const size_t len, char* const encoded) -{ - const uint8_t* rawBytes = raw; - uint8_t* encodedBytes = (uint8_t*)encoded; - size_t rawBitLen = 8*len; - size_t bit, tmp; - - for (bit = 0; bit < rawBitLen; bit += 6) - { - tmp = static_cast((rawBytes[bit/8] << (bit % 8)) | (rawBytes[bit/8 + 1] >> (8 - (bit % 8)))); - tmp = static_cast((tmp >> 2) & 0x3f); - CARLA_ASSERT(tmp < 64); - - *(encodedBytes++) = static_cast(kBase64[tmp]); - } - - for (; (bit % 8) != 0; bit += 6) - *(encodedBytes++) = '='; - - *(encodedBytes++) = '\0'; - - carla_debug("Base64-encoded to \"%s\"\n", encoded); - CARLA_ASSERT(std::strlen(encoded) == carla_base64_encoded_len(len)); -} - -/** - * Base64-decode string - * - * @v encoded Encoded string - * @v raw Raw data - * @ret len Length of raw data, or 0 - * - * The buffer must be large enough to contain the decoded data. - * Use something like - * - * char buf[carla_base64_decoded_max_len(encoded)]; - * - * to provide a buffer of the correct size. - */ -static inline -unsigned int carla_base64_decode(const char* const encoded, uint8_t* const raw) -{ - const uint8_t* encodedBytes = (const uint8_t*)encoded; - uint8_t* rawBytes = raw; - uint8_t encodedByte; - unsigned int bit = 0; - unsigned int padCount = 0; - - /* Zero the raw data */ - carla_zeroMem(raw, carla_base64_decoded_max_len(encoded)); - - /* Decode string */ - while ((encodedByte = *(encodedBytes++)) > 0) - { - /* Ignore whitespace characters */ - if (std::isspace(encodedByte)) - continue; - - /* Process pad characters */ - if (encodedByte == '=') - { - if (padCount >= 2) - { - carla_debug("Base64-encoded string \"%s\" has too many pad characters", encoded); - return 0; - } - - padCount++; - bit -= 2; /* unused_bits = ( 2 * padCount ) */ - continue; - } - - if (padCount > 0) - { - carla_debug("Base64-encoded string \"%s\" has invalid pad sequence", encoded); - return 0; - } - - /* Process normal characters */ - const char* const match = std::strchr(kBase64, encodedByte); - - if (match == nullptr) - { - carla_debug("Base64-encoded string \"%s\" contains invalid character '%c'", encoded, encodedByte); - return 0; - } - - uint8_t decoded = static_cast(match - kBase64); - - /* Add to raw data */ - decoded <<= 2; - rawBytes[bit / 8] |= (decoded >> (bit % 8)); - rawBytes[bit / 8 + 1] |= (decoded << (8 - (bit % 8))); - bit += 6; - } - - /* Check that we decoded a whole number of bytes */ - if ((bit % 8) != 0) - { - carla_debug("Base64-encoded string \"%s\" has invalid bit length %d", encoded, bit); - return 0; - } - - unsigned int len = bit/8; - - carla_debug("Base64-decoded from \"%s\"", encoded); - CARLA_ASSERT(len <= carla_base64_decoded_max_len(encoded)); - - /* Return length in bytes */ - return len; -} - -#endif // __CARLA_BASE64_UTILS_HPP__ diff --git a/source/utils/CarlaString.hpp b/source/utils/CarlaString.hpp index 79e38dba2..c46a75e94 100644 --- a/source/utils/CarlaString.hpp +++ b/source/utils/CarlaString.hpp @@ -18,7 +18,6 @@ #ifndef __CARLA_STRING_HPP__ #define __CARLA_STRING_HPP__ -#include "CarlaBase64Utils.hpp" #include "CarlaJuceUtils.hpp" // ------------------------------------------------- @@ -251,96 +250,26 @@ public: void toLower() { - static const char charDiff = 'a' - 'A'; + static const char kCharDiff = 'a' - 'A'; for (size_t i=0; i < bufferLen; ++i) { if (buffer[i] >= 'A' && buffer[i] <= 'Z') - buffer[i] += charDiff; + buffer[i] += kCharDiff; } } void toUpper() { - static const char charDiff = 'a' - 'A'; + static const char kCharDiff = 'a' - 'A'; for (size_t i=0; i < bufferLen; ++i) { if (buffer[i] >= 'a' && buffer[i] <= 'z') - buffer[i] -= charDiff; + buffer[i] -= kCharDiff; } } - void toBase64() - { - importBinaryAsBase64((const uint8_t*)buffer, bufferLen); - } - - void fromBase64() - { - uint8_t buffer2[carla_base64_decoded_max_len(buffer)]; - - if (unsigned int len = carla_base64_decode(buffer, buffer2)) - { - char bufDecoded[len+1]; - std::strncpy(bufDecoded, (char*)buffer2, len); - bufDecoded[len] = '\0'; - _dup(bufDecoded, len); - } - else - clear(); - } - - void importBinaryAsBase64(const uint8_t* const raw, const size_t rawLen) - { - const size_t rawBufferSize = carla_base64_encoded_len(rawLen); - char rawBuffer[rawBufferSize+1]; - carla_base64_encode(raw, rawLen, rawBuffer); - - _dup(rawBuffer, rawBufferSize); - } - - template - void importBinaryAsBase64(const T* const t) - { - importBinaryAsBase64((const uint8_t*)t, sizeof(T)); - } - - size_t exportAsBase64Binary(uint8_t** const rawPtr) - { - uint8_t binaryBuffer[carla_base64_decoded_max_len(buffer)]; - - if (unsigned int len = carla_base64_decode(buffer, binaryBuffer)) - { - uint8_t* const binaryBufferHeap = new uint8_t[len]; - carla_copy(binaryBufferHeap, binaryBuffer, len); - - *rawPtr = binaryBufferHeap; - return len; - } - - *rawPtr = nullptr; - return 0; - } - - template - T* exportAsBase64Binary() - { - uint8_t binaryBuffer[carla_base64_decoded_max_len(buffer)]; - - if (unsigned int len = carla_base64_decode(buffer, binaryBuffer)) - { - CARLA_ASSERT_INT2(len == sizeof(T), len, sizeof(T)); - - T* const t = new T(); - std::memcpy(t, binaryBuffer, sizeof(T)); - - return t; - } - - return nullptr; - } - // --------------------------------------------- // public operators diff --git a/source/utils/CarlaThread.hpp b/source/utils/CarlaThread.hpp deleted file mode 100644 index 29b012de3..000000000 --- a/source/utils/CarlaThread.hpp +++ /dev/null @@ -1,274 +0,0 @@ -/* - * Carla Thread - * Copyright (C) 2013 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 GPL.txt file - */ - -#ifndef __CARLA_THREAD_HPP__ -#define __CARLA_THREAD_HPP__ - -#include "CarlaJuceUtils.hpp" - -#error This class is not ready for usage yet - -// #define CPP11_THREAD - -#ifdef CPP11_THREAD -# include -#else -# include -#endif - -// ------------------------------------------------- -// CarlaThread class - -class CarlaThread -{ -public: - CarlaThread() - : fStarted(false), - fFinished(false) - { -#ifdef CPP11_THREAD - cthread = nullptr; -#else - _zero(); - pthread_attr_init(&pthreadAttr); - pthread_attr_setdetachstate(&pthreadAttr, PTHREAD_CREATE_JOINABLE); -#endif - } - - ~CarlaThread() - { - CARLA_ASSERT(! isRunning()); - - if (isRunning()) - terminate(); - -#ifdef CPP11_THREAD - if (cthread != nullptr) - { - cthread->join(); - delete cthread; - } -#else - //if (! _isNull()) - // pthread_join(pthreadId, nullptr); - - pthread_attr_destroy(&pthreadAttr); -#endif - } - - bool start() - { - CARLA_ASSERT(! isRunning()); - - if (isRunning()) - return false; - - fStarted = false; - fFinished = false; - -#ifdef CPP11_THREAD - CARLA_ASSERT(cthread == nullptr); - - if (cthread != nullptr) - return false; - - cthread = new std::thread(_cthreadRoutine, this); - CARLA_ASSERT(cthread->joinable()); - - return true; -#else - CARLA_ASSERT(_isNull()); - - if (! _isNull()) - return false; - - return (pthread_create(&pthreadId, &pthreadAttr, _pthreadRoutine, this) == 0); -#endif - } - - bool stop(const unsigned int timeout = 0) - { - CARLA_ASSERT(isRunning()); - - if (! isRunning()) - return true; - -#ifdef CPP11_THREAD - if (cthread == nullptr) - return true; -#else - if (_isNull()) - return true; -#endif - - if (timeout == 0) - { -#ifdef CPP11_THREAD - cthread->join(); -#else - pthread_join(pthreadId, nullptr); -#endif - } - else - { - for (unsigned int i=0; i < timeout && ! fFinished; i++) - carla_msleep(1); - } - - if (! fFinished) - return false; - -#ifdef CPP11_THREAD - delete cthread; - cthread = nullptr; -#else - _zero(); -#endif - - return true; - } - - void terminate() - { - CARLA_ASSERT(isRunning()); - - if (fFinished) - return; - -#ifdef CPP11_THREAD - if (cthread == nullptr) - return; -#else - if (_isNull()) - return; -#endif - -#ifdef CPP11_THREAD - cthread->detach(); - //cthread->join(); - delete cthread; - cthread = nullptr; -#else - pthread_detach(pthreadId); - //pthread_join(pthreadId, nullptr); - pthread_cancel(pthreadId); - _zero(); -#endif - - fFinished = true; - } - - bool isRunning() - { - if (fStarted && ! fFinished) - return true; - - // take the chance to clear data -#ifdef CPP11_THREAD - if (cthread != nullptr) - { - cthread->join(); - delete cthread; - cthread = nullptr; - } -#else - if (! _isNull()) - { - //pthread_join(pthreadId, nullptr); - //_zero(); - } -#endif - return false; - } - - void waitForStarted(const unsigned int timeout = 0) // ms - { - if (fStarted) - return; - - if (timeout == 0) - { - while (! fStarted) - carla_msleep(1); - } - else - { - for (unsigned int i=0; i < timeout && ! fStarted; i++) - carla_msleep(1); - } - } - - void waitForFinished() - { - waitForStarted(); - stop(0); - } - -protected: - virtual void run() = 0; - -private: - bool fStarted; - bool fFinished; - - void handleRoutine() - { - fStarted = true; - run(); - fFinished = true; - } - -#ifdef CPP11_THREAD - std::thread* cthread; - - static void _cthreadRoutine(CarlaThread* const _this_) - { - _this_->handleRoutine(); - } -#else - pthread_t pthreadId; - pthread_attr_t pthreadAttr; - - static void* _pthreadRoutine(void* const _this_) - { - ((CarlaThread*)_this_)->handleRoutine(); - pthread_exit(nullptr); - return nullptr; - } - - bool _isNull() - { -#ifdef CARLA_OS_WIN - return (pthreadId.p == nullptr); -#else - return (pthreadId == 0); -#endif - } - - void _zero() - { - carla_zeroStruct(pthreadId); - } -#endif - - //CARLA_PREVENT_HEAP_ALLOCATION - CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaThread) -}; - -// ------------------------------------------------- - -#endif // __CARLA_THREAD_HPP__