Browse Source

Get rid of our own base64 code, use Qt instead

Working in Qt5 as well
tags/1.9.4
falkTX 11 years ago
parent
commit
d883f73f4e
8 changed files with 34 additions and 570 deletions
  1. +3
    -4
      source/backend/plugin/CarlaPlugin.cpp
  2. +8
    -23
      source/backend/plugin/DssiPlugin.cpp
  3. +10
    -8
      source/backend/plugin/VstPlugin.cpp
  4. +3
    -2
      source/backend/standalone/CarlaStandalone.cpp
  5. +6
    -1
      source/tests/Base64.cpp
  6. +0
    -183
      source/utils/CarlaBase64Utils.hpp
  7. +4
    -75
      source/utils/CarlaString.hpp
  8. +0
    -274
      source/utils/CarlaThread.hpp

+ 3
- 4
source/backend/plugin/CarlaPlugin.cpp View File

@@ -636,12 +636,11 @@ const SaveState& CarlaPlugin::getSaveState()
void* data = nullptr; void* data = nullptr;
const int32_t dataSize(chunkData(&data)); 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<size_t>(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 // Don't save anything else if using chunks
return saveState; return saveState;


+ 8
- 23
source/backend/plugin/DssiPlugin.cpp View File

@@ -39,8 +39,7 @@ public:
fDssiDescriptor(nullptr), fDssiDescriptor(nullptr),
fAudioInBuffers(nullptr), fAudioInBuffers(nullptr),
fAudioOutBuffers(nullptr), fAudioOutBuffers(nullptr),
fParamBuffers(nullptr),
fLastChunk(nullptr)
fParamBuffers(nullptr)
{ {
carla_debug("DssiPlugin::DssiPlugin(%p, %i)", engine, id); carla_debug("DssiPlugin::DssiPlugin(%p, %i)", engine, id);


@@ -91,12 +90,6 @@ public:
fDssiDescriptor = nullptr; fDssiDescriptor = nullptr;
} }


if (fLastChunk != nullptr)
{
delete[] fLastChunk;
fLastChunk = nullptr;
}

clearBuffers(); clearBuffers();
} }


@@ -319,21 +312,14 @@ public:
if (fDssiDescriptor->set_custom_data == nullptr) if (fDssiDescriptor->set_custom_data == nullptr)
return; 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); const ScopedSingleProcessLocker spl(this, true);
fDssiDescriptor->set_custom_data(fHandle, fLastChunk, static_cast<unsigned long>(size));
fDssiDescriptor->set_custom_data(fHandle, chunk.data(), chunk.size());
} }
} }


@@ -1920,10 +1906,9 @@ private:
const LADSPA_Descriptor* fDescriptor; const LADSPA_Descriptor* fDescriptor;
const DSSI_Descriptor* fDssiDescriptor; 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]; snd_seq_event_t fMidiEvents[MAX_MIDI_EVENTS];


CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(DssiPlugin) CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(DssiPlugin)


+ 10
- 8
source/backend/plugin/VstPlugin.cpp View File

@@ -108,7 +108,7 @@ public:


if (fLastChunk != nullptr) if (fLastChunk != nullptr)
{ {
delete[] fLastChunk;
std::free(fLastChunk);
fLastChunk = nullptr; fLastChunk = nullptr;
} }


@@ -289,19 +289,21 @@ public:


if (fLastChunk != nullptr) if (fLastChunk != nullptr)
{ {
delete[] fLastChunk;
std::free(fLastChunk);
fLastChunk = nullptr; 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); 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; int fUnique1;
AEffect* fEffect; AEffect* fEffect;


uint8_t* fLastChunk;
void* fLastChunk;
uint32_t fMidiEventCount; uint32_t fMidiEventCount;
VstMidiEvent fMidiEvents[MAX_MIDI_EVENTS*2]; VstMidiEvent fMidiEvents[MAX_MIDI_EVENTS*2];
VstTimeInfo_R fTimeInfo; VstTimeInfo_R fTimeInfo;


+ 3
- 2
source/backend/standalone/CarlaStandalone.cpp View File

@@ -1091,9 +1091,10 @@ const char* carla_get_chunk_data(unsigned int pluginId)
void* data = nullptr; void* data = nullptr;
const int32_t dataSize = plugin->chunkData(&data); 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<size_t>(dataSize));
QByteArray chunk(QByteArray((char*)data, dataSize).toBase64());
chunkData = chunk.constData();
return (const char*)chunkData; return (const char*)chunkData;
} }
else else


+ 6
- 1
source/tests/Base64.cpp View File

@@ -49,10 +49,12 @@ int main()
int i; int i;
double d; double d;
void* ptr; void* ptr;
char pad[17];
int32_t i32; int32_t i32;
int64_t i64; int64_t i64;
bool b; bool b;
} blob;
};
Blob blob;


const size_t blobSize = sizeof(Blob); const size_t blobSize = sizeof(Blob);
carla_zeroStruct<Blob>(blob); carla_zeroStruct<Blob>(blob);
@@ -66,6 +68,7 @@ int main()
blob.i32 = 32; blob.i32 = 32;
blob.i64 = 64; blob.i64 = 64;
blob.b = true; blob.b = true;
blob.pad[11] = 71;


// binary -> base64 // binary -> base64
char blobEnc[carla_base64_encoded_len(blobSize) + 1]; char blobEnc[carla_base64_encoded_len(blobSize) + 1];
@@ -90,6 +93,7 @@ int main()
assert(blobTest.i32 == 32); assert(blobTest.i32 == 32);
assert(blobTest.i64 == 64); assert(blobTest.i64 == 64);
assert(blobTest.b == true); assert(blobTest.b == true);
assert(blobTest.pad[11] == 71);
} }


{ {
@@ -110,6 +114,7 @@ int main()
assert(blobNew->i32 == 32); assert(blobNew->i32 == 32);
assert(blobNew->i64 == 64); assert(blobNew->i64 == 64);
assert(blobNew->b == true); assert(blobNew->b == true);
assert(blobNew->pad[11] == 71);


delete blobNew; delete blobNew;
} }


+ 0
- 183
source/utils/CarlaBase64Utils.hpp View File

@@ -1,183 +0,0 @@
/*
* Carla base64 utils imported from qemu source code
* Copyright (C) 2009 Michael Brown <mbrown@fensystems.co.uk>
* Copyright (C) 2013 Filipe Coelho <falktx@falktx.com>
*
* 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 <cctype>
#include <cstdint>

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<size_t>((rawBytes[bit/8] << (bit % 8)) | (rawBytes[bit/8 + 1] >> (8 - (bit % 8))));
tmp = static_cast<size_t>((tmp >> 2) & 0x3f);
CARLA_ASSERT(tmp < 64);

*(encodedBytes++) = static_cast<uint8_t>(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<uint8_t>(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__

+ 4
- 75
source/utils/CarlaString.hpp View File

@@ -18,7 +18,6 @@
#ifndef __CARLA_STRING_HPP__ #ifndef __CARLA_STRING_HPP__
#define __CARLA_STRING_HPP__ #define __CARLA_STRING_HPP__


#include "CarlaBase64Utils.hpp"
#include "CarlaJuceUtils.hpp" #include "CarlaJuceUtils.hpp"


// ------------------------------------------------- // -------------------------------------------------
@@ -251,96 +250,26 @@ public:


void toLower() void toLower()
{ {
static const char charDiff = 'a' - 'A';
static const char kCharDiff = 'a' - 'A';


for (size_t i=0; i < bufferLen; ++i) for (size_t i=0; i < bufferLen; ++i)
{ {
if (buffer[i] >= 'A' && buffer[i] <= 'Z') if (buffer[i] >= 'A' && buffer[i] <= 'Z')
buffer[i] += charDiff;
buffer[i] += kCharDiff;
} }
} }


void toUpper() void toUpper()
{ {
static const char charDiff = 'a' - 'A';
static const char kCharDiff = 'a' - 'A';


for (size_t i=0; i < bufferLen; ++i) for (size_t i=0; i < bufferLen; ++i)
{ {
if (buffer[i] >= 'a' && buffer[i] <= 'z') 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<typename T>
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<uint8_t>(binaryBufferHeap, binaryBuffer, len);

*rawPtr = binaryBufferHeap;
return len;
}

*rawPtr = nullptr;
return 0;
}

template<typename T>
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 // public operators




+ 0
- 274
source/utils/CarlaThread.hpp View File

@@ -1,274 +0,0 @@
/*
* Carla Thread
* Copyright (C) 2013 Filipe Coelho <falktx@falktx.com>
*
* 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 <thread>
#else
# include <pthread.h>
#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<pthread_t>(pthreadId);
}
#endif

//CARLA_PREVENT_HEAP_ALLOCATION
CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaThread)
};

// -------------------------------------------------

#endif // __CARLA_THREAD_HPP__

Loading…
Cancel
Save