@@ -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; | ||||
@@ -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) | ||||
@@ -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; | ||||
@@ -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 | ||||
@@ -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; | ||||
} | } | ||||
@@ -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__ |
@@ -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 | ||||
@@ -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__ |