Browse Source

Continue full check; Split List/RtList code; Revert some utils

tags/1.9.4
falkTX 11 years ago
parent
commit
5366a78f76
18 changed files with 704 additions and 724 deletions
  1. +13
    -2
      source/includes/CarlaDefines.hpp
  2. +9
    -9
      source/utils/CarlaLibCounter.hpp
  3. +59
    -4
      source/utils/CarlaLibUtils.hpp
  4. +8
    -8
      source/utils/CarlaLogThread.hpp
  5. +0
    -1
      source/utils/CarlaLv2Utils.hpp
  6. +2
    -2
      source/utils/CarlaMutex.hpp
  7. +1
    -1
      source/utils/CarlaOscUtils.hpp
  8. +4
    -4
      source/utils/CarlaRingBuffer.hpp
  9. +5
    -5
      source/utils/CarlaStateUtils.hpp
  10. +1
    -4
      source/utils/CarlaString.hpp
  11. +12
    -15
      source/utils/CarlaThread.hpp
  12. +133
    -29
      source/utils/CarlaUtils.hpp
  13. +0
    -2
      source/utils/CarlaVstUtils.hpp
  14. +4
    -4
      source/utils/JucePluginWindow.hpp
  15. +420
    -0
      source/utils/List.hpp
  16. +14
    -7
      source/utils/Lv2AtomQueue.hpp
  17. +19
    -414
      source/utils/RtList.hpp
  18. +0
    -213
      source/utils/Utils.cpp

+ 13
- 2
source/includes/CarlaDefines.hpp View File

@@ -24,8 +24,8 @@
#endif

// Set Version
#define CARLA_VERSION_HEX 0x01090
#define CARLA_VERSION_STRING "1.9.0"
#define CARLA_VERSION_HEX 0x01091
#define CARLA_VERSION_STRING "1.9.1"

// Check OS
#if defined(WIN64) || defined(_WIN64) || defined(__WIN64__)
@@ -68,6 +68,17 @@
# define nullptr (0)
#endif

// Common includes
#ifdef CARLA_OS_WIN
# include <winsock2.h>
# include <windows.h>
#else
# include <unistd.h>
# ifndef __cdecl
# define __cdecl
# endif
#endif

// Define various string format types
#if defined(CARLA_OS_WIN64)
# define P_INT64 "%I64i"


+ 9
- 9
source/utils/CarlaLibCounter.hpp View File

@@ -20,7 +20,7 @@

#include "CarlaLibUtils.hpp"
#include "CarlaMutex.hpp"
#include "RtList.hpp"
#include "List.hpp"

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

@@ -33,9 +33,9 @@ public:
{
CARLA_SAFE_ASSERT_RETURN(filename != nullptr, nullptr);

const CarlaMutex::ScopedLocker sl(mutex);
const CarlaMutex::ScopedLocker sl(fMutex);

for (NonRtList<Lib>::Itenerator it = libs.begin(); it.valid(); it.next())
for (List<Lib>::Itenerator it = fLibs.begin(); it.valid(); it.next())
{
Lib& lib(*it);
CARLA_ASSERT(lib.count > 0);
@@ -58,7 +58,7 @@ public:
lib.filename = carla_strdup(filename);
lib.count = 1;

libs.append(lib);
fLibs.append(lib);

return libPtr;
}
@@ -67,9 +67,9 @@ public:
{
CARLA_SAFE_ASSERT_RETURN(libPtr != nullptr, false);

const CarlaMutex::ScopedLocker sl(mutex);
const CarlaMutex::ScopedLocker sl(fMutex);

for (NonRtList<Lib>::Itenerator it = libs.begin(); it.valid(); it.next())
for (List<Lib>::Itenerator it = fLibs.begin(); it.valid(); it.next())
{
Lib& lib(*it);
CARLA_ASSERT(lib.count > 0);
@@ -89,7 +89,7 @@ public:
lib_close(lib.lib);
lib.lib = nullptr;

libs.remove(it);
fLibs.remove(it);
}

return true;
@@ -106,8 +106,8 @@ private:
int count;
};

CarlaMutex mutex;
NonRtList<Lib> libs;
List<Lib> fLibs;
CarlaMutex fMutex;
};

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


+ 59
- 4
source/utils/CarlaLibUtils.hpp View File

@@ -20,6 +20,10 @@

#include "CarlaUtils.hpp"

#ifndef CARLA_OS_WIN
# include <dlfcn.h>
#endif

// -----------------------------------------------------------------------
// library related calls

@@ -27,24 +31,75 @@
* Open 'filename' library (must not be null).
* May return null, in which case "lib_error" has the error.
*/
void* lib_open(const char* const filename);
static inline
void* lib_open(const char* const filename)
{
CARLA_SAFE_ASSERT_RETURN(filename != nullptr, nullptr);

#ifdef CARLA_OS_WIN
return (void*)LoadLibraryA(filename);
#else
return dlopen(filename, RTLD_NOW|RTLD_LOCAL);
#endif
}

/*
* Close a previously opened library (must not be null).
* If false is returned,"lib_error" has the error.
*/
bool lib_close(void* const lib);
static inline
bool lib_close(void* const lib)
{
CARLA_SAFE_ASSERT_RETURN(lib != nullptr, false);

#ifdef CARLA_OS_WIN
return FreeLibrary((HMODULE)lib);
#else
return (dlclose(lib) == 0);
#endif
}

/*
* Get a library symbol (must not be null).
* May return null if the symbol is not found.
*/
void* lib_symbol(void* const lib, const char* const symbol);
static inline
void* lib_symbol(void* const lib, const char* const symbol)
{
CARLA_SAFE_ASSERT_RETURN(lib != nullptr, nullptr);
CARLA_SAFE_ASSERT_RETURN(symbol != nullptr, nullptr);

#ifdef CARLA_OS_WIN
return (void*)GetProcAddress((HMODULE)lib, symbol);
#else
return dlsym(lib, symbol);
#endif
}

/*
* Return the last operation error ('filename' must not be null).
*/
const char* lib_error(const char* const filename);
static inline
const char* lib_error(const char* const filename)
{
CARLA_SAFE_ASSERT_RETURN(filename != nullptr, nullptr);

#ifdef CARLA_OS_WIN
static char libError[2048+1];
carla_zeroChar(libError, 2048+1);

LPVOID winErrorString;
DWORD winErrorCode = GetLastError();
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, winErrorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&winErrorString, 0, nullptr);

std::snprintf(libError, 2048, "%s: error code %li: %s", filename, winErrorCode, (const char*)winErrorString);
LocalFree(winErrorString);

return libError;
#else
return dlerror();
#endif
}

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



+ 8
- 8
source/utils/CarlaLogThread.hpp View File

@@ -20,8 +20,7 @@

#include "CarlaBackend.hpp"
#include "CarlaString.hpp"

#include "juce_core.h"
#include "CarlaThread.hpp"

#include <fcntl.h>

@@ -30,11 +29,11 @@ using CarlaBackend::CallbackFunc;
// -----------------------------------------------------------------------
// Log thread

class CarlaLogThread : public juce::Thread
class CarlaLogThread : public CarlaThread
{
public:
CarlaLogThread()
: Thread("CarlaLogThread"),
: CarlaThread("CarlaLogThread"),
fCallback(nullptr),
fCallbackPtr(nullptr)
{
@@ -50,7 +49,7 @@ public:

fcntl(fPipe[0], F_SETFL, O_NONBLOCK);

startThread(2);
start(2);
}

~CarlaLogThread()
@@ -58,7 +57,7 @@ public:
fCallback = nullptr;
fCallbackPtr = nullptr;

stopThread(5000);
stop(5000);

fflush(stdout);
fflush(stderr);
@@ -78,7 +77,7 @@ public:
protected:
void run()
{
while (! threadShouldExit())
while (! shouldExit())
{
size_t r, lastRead;
ssize_t r2; // to avoid sign/unsign conversions
@@ -142,7 +141,8 @@ private:
void* fCallbackPtr;
CarlaString fOldBuffer;

CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaLogThread)
CARLA_PREVENT_HEAP_ALLOCATION
CARLA_DECLARE_NON_COPY_CLASS(CarlaLogThread)
};

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


+ 0
- 1
source/utils/CarlaLv2Utils.hpp View File

@@ -406,7 +406,6 @@ private:
bool fNeedsInit;

CARLA_PREVENT_HEAP_ALLOCATION
CARLA_DECLARE_NON_COPY_CLASS(Lv2WorldClass)
};

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


+ 2
- 2
source/utils/CarlaMutex.hpp View File

@@ -18,7 +18,7 @@
#ifndef CARLA_MUTEX_HPP_INCLUDED
#define CARLA_MUTEX_HPP_INCLUDED

#include "CarlaJuceUtils.hpp"
#include "CarlaUtils.hpp"

#include <pthread.h>

@@ -39,7 +39,7 @@ public:
pthread_mutexattr_settype(&atts, PTHREAD_MUTEX_RECURSIVE);

pthread_mutex_init(&fMutex, &atts);
pthread_mutexattr_destroy (&atts);
pthread_mutexattr_destroy(&atts);
}

/*


+ 1
- 1
source/utils/CarlaOscUtils.hpp View File

@@ -18,7 +18,7 @@
#ifndef CARLA_OSC_UTILS_HPP_INCLUDED
#define CARLA_OSC_UTILS_HPP_INCLUDED

#include "CarlaJuceUtils.hpp"
#include "CarlaUtils.hpp"

#include <lo/lo.h>



+ 4
- 4
source/utils/CarlaRingBuffer.hpp View File

@@ -19,7 +19,7 @@
#ifndef CARLA_RING_BUFFER_HPP_INCLUDED
#define CARLA_RING_BUFFER_HPP_INCLUDED

#include "CarlaJuceUtils.hpp"
#include "CarlaUtils.hpp"

#ifndef RING_BUFFER_SIZE
# define RING_BUFFER_SIZE 2048
@@ -42,10 +42,10 @@ class RingBufferControl
{
public:
RingBufferControl(RingBuffer* const ringBuf)
: fRingBuf(nullptr)
: fRingBuf(ringBuf)
{
if (ringBuf != nullptr)
setRingBuffer(ringBuf, true);
clear();
}

void clear()
@@ -89,7 +89,7 @@ public:
}
}

bool dataAvailable() const
bool isDataAvailable() const
{
CARLA_SAFE_ASSERT_RETURN(fRingBuf != nullptr, false);



+ 5
- 5
source/utils/CarlaStateUtils.hpp View File

@@ -20,7 +20,7 @@

#include "CarlaBackendUtils.hpp"
#include "CarlaMIDI.h"
#include "RtList.hpp"
#include "List.hpp"

#include "juce_core.h"

@@ -93,11 +93,11 @@ struct StateCustomData {
CARLA_DECLARE_NON_COPY_STRUCT(StateCustomData)
};

typedef NonRtList<StateParameter*> StateParameterList;
typedef NonRtList<StateCustomData*> StateCustomDataList;
typedef List<StateParameter*> StateParameterList;
typedef List<StateCustomData*> StateCustomDataList;

typedef NonRtList<StateParameter*>::Itenerator StateParameterItenerator;
typedef NonRtList<StateCustomData*>::Itenerator StateCustomDataItenerator;
typedef List<StateParameter*>::Itenerator StateParameterItenerator;
typedef List<StateCustomData*>::Itenerator StateCustomDataItenerator;

struct SaveState {
const char* type;


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

@@ -18,9 +18,7 @@
#ifndef CARLA_STRING_HPP_INCLUDED
#define CARLA_STRING_HPP_INCLUDED

#include "CarlaJuceUtils.hpp"

#include <cstdio> // for *printf
#include "CarlaUtils.hpp"

// -----------------------------------------------------------------------
// CarlaString class
@@ -680,7 +678,6 @@ private:
}

CARLA_PREVENT_HEAP_ALLOCATION
CARLA_LEAK_DETECTOR(CarlaString)
};

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


+ 12
- 15
source/utils/CarlaThread.hpp View File

@@ -84,7 +84,7 @@ public:

fShouldExit = false;

if (pthread_create(const_cast<pthread_t*>(&fHandle), nullptr, _threadEntryPoint, this) == 0)
if (pthread_create(const_cast<pthread_t*>(&fHandle), nullptr, _entryPoint, this) == 0)
{
#if (__GLIBC__ * 1000 + __GLIBC_MINOR__) >= 2012
if (fName.isNotEmpty())
@@ -154,10 +154,10 @@ public:
}

private:
CarlaMutex fLock; // Thread lock
const CarlaString fName; // Thread name
volatile pthread_t fHandle; // Handle for this thread
volatile bool fShouldExit; // ...
const CarlaString fName; // Thread name
volatile CarlaMutex fLock; // Thread lock
volatile pthread_t fHandle; // Handle for this thread
volatile bool fShouldExit; // true if thread should exit

void _init() noexcept
{
@@ -169,17 +169,8 @@ private:
#endif
}

static void* _threadEntryPoint(void* userData)
void _runEntryPoint()
{
static_cast<CarlaThread*>(userData)->threadEntryPoint();
return nullptr;
}

void threadEntryPoint()
{
//if (fName.isNotEmpty())
// setCurrentThreadName(threadName);

// tell dad we're ready
fLock.unlock();

@@ -189,6 +180,12 @@ private:
_init();
}

static void* _entryPoint(void* userData)
{
static_cast<CarlaThread*>(userData)->_runEntryPoint();
return nullptr;
}

CARLA_PREVENT_HEAP_ALLOCATION
CARLA_DECLARE_NON_COPY_CLASS(CarlaThread)
};


+ 133
- 29
source/utils/CarlaUtils.hpp View File

@@ -20,7 +20,17 @@

#include "CarlaDefines.hpp"

#include <cstring> // for memcpy and memset
#include <cassert>
#include <cstdarg>
#include <cstdio>
#include <cstdlib>
#include <cstring>

#ifdef CARLA_PROPER_CPP11_SUPPORT
# include <cstdint>
#else
# include <stdint.h>
#endif

// -----------------------------------------------------------------------
// misc functions
@@ -28,7 +38,7 @@
/*
* Return "true" or "false" according to yesNo.
*/
inline
static inline
const char* bool2str(const bool yesNo) noexcept
{
return yesNo ? "true" : "false";
@@ -37,7 +47,7 @@ const char* bool2str(const bool yesNo) noexcept
/*
* Dummy function.
*/
inline
static inline
void pass() noexcept {}

// -----------------------------------------------------------------------
@@ -50,23 +60,57 @@ void pass() noexcept {}
#ifndef DEBUG
# define carla_debug(...)
#else
void carla_debug(const char* const fmt, ...);
static inline
void carla_debug(const char* const fmt, ...)
{
va_list args;
va_start(args, fmt);
std::fprintf(stdout, "\x1b[30;1m");
std::vfprintf(stdout, fmt, args);
std::fprintf(stdout, "\x1b[0m\n");
va_end(args);
}
#endif

/*
* Print a string to stdout with newline.
*/
void carla_stdout(const char* const fmt, ...);
static inline
void carla_stdout(const char* const fmt, ...)
{
va_list args;
va_start(args, fmt);
std::vfprintf(stdout, fmt, args);
std::fprintf(stdout, "\n");
va_end(args);
}

/*
* Print a string to stderr with newline.
*/
void carla_stderr(const char* const fmt, ...);
static inline
void carla_stderr(const char* const fmt, ...)
{
va_list args;
va_start(args, fmt);
std::vfprintf(stderr, fmt, args);
std::fprintf(stderr, "\n");
va_end(args);
}

/*
* Print a string to stderr with newline (red color).
*/
void carla_stderr2(const char* const fmt, ...);
static inline
void carla_stderr2(const char* const fmt, ...)
{
va_list args;
va_start(args, fmt);
std::fprintf(stderr, "\x1b[31m");
std::vfprintf(stderr, fmt, args);
std::fprintf(stderr, "\x1b[0m\n");
va_end(args);
}

// -----------------------------------------------------------------------
// carla_safe_assert*
@@ -74,7 +118,7 @@ void carla_stderr2(const char* const fmt, ...);
/*
* Print a safe assertion error message.
*/
inline
static inline
void carla_safe_assert(const char* const assertion, const char* const file, const int line)
{
carla_stderr2("Carla assertion failure: \"%s\" in file %s, line %i", assertion, file, line);
@@ -83,7 +127,7 @@ void carla_safe_assert(const char* const assertion, const char* const file, cons
/*
* Print a safe assertion error message, with 1 extra integer value.
*/
inline
static inline
void carla_safe_assert_int(const char* const assertion, const char* const file, const int line, const int value)
{
carla_stderr2("Carla assertion failure: \"%s\" in file %s, line %i, value %i", assertion, file, line, value);
@@ -92,7 +136,7 @@ void carla_safe_assert_int(const char* const assertion, const char* const file,
/*
* Print a safe assertion error message, with 2 extra integer values.
*/
inline
static inline
void carla_safe_assert_int2(const char* const assertion, const char* const file, const int line, const int v1, const int v2)
{
carla_stderr2("Carla assertion failure: \"%s\" in file %s, line %i, v1 %i, v2 %i", assertion, file, line, v1, v2);
@@ -104,12 +148,32 @@ void carla_safe_assert_int2(const char* const assertion, const char* const file,
/*
* Sleep for 'secs' seconds.
*/
void carla_sleep(const unsigned int secs);
static inline
void carla_sleep(const unsigned int secs)
{
CARLA_SAFE_ASSERT_RETURN(secs > 0,);

#ifdef CARLA_OS_WIN
Sleep(secs * 1000);
#else
sleep(secs);
#endif
}

/*
* Sleep for 'msecs' milliseconds.
*/
void carla_msleep(const unsigned int msecs);
static inline
void carla_msleep(const unsigned int msecs)
{
CARLA_SAFE_ASSERT_RETURN(msecs > 0,);

#ifdef CARLA_OS_WIN
Sleep(msecs);
#else
usleep(msecs * 1000);
#endif
}

// -----------------------------------------------------------------------
// carla_setenv
@@ -117,7 +181,18 @@ void carla_msleep(const unsigned int msecs);
/*
* Set environment variable 'key' to 'value'.
*/
void carla_setenv(const char* const key, const char* const value);
static inline
void carla_setenv(const char* const key, const char* const value)
{
CARLA_SAFE_ASSERT_RETURN(key != nullptr,);
CARLA_SAFE_ASSERT_RETURN(value != nullptr,);

#ifdef CARLA_OS_WIN
SetEnvironmentVariableA(key, value);
#else
setenv(key, value, 1);
#endif
}

// -----------------------------------------------------------------------
// carla_strdup
@@ -126,14 +201,34 @@ void carla_setenv(const char* const key, const char* const value);
* Custom 'strdup' function.
* Return value is always valid, and must be freed with "delete[] var".
*/
const char* carla_strdup(const char* const strBuf);
static inline
const char* carla_strdup(const char* const strBuf)
{
CARLA_SAFE_ASSERT(strBuf != nullptr);

const size_t bufferLen = (strBuf != nullptr) ? std::strlen(strBuf) : 0;
char* const buffer = new char[bufferLen+1];

if (strBuf != nullptr && bufferLen > 0)
std::strncpy(buffer, strBuf, bufferLen);

buffer[bufferLen] = '\0';

return buffer;
}

/*
* Custom 'strdup' function.
* Calls "std::free(strBuf)".
* Return value is always valid, and must be freed with "delete[] var".
*/
const char* carla_strdup_free(char* const strBuf);
static inline
const char* carla_strdup_free(char* const strBuf)
{
const char* const buffer(carla_strdup(strBuf));
std::free(strBuf);
return buffer;
}

// -----------------------------------------------------------------------
// math functions
@@ -141,7 +236,8 @@ const char* carla_strdup_free(char* const strBuf);
/*
* Return the lower of 2 values, with 'min' as the minimum possible value.
*/
template<typename T> inline
template<typename T>
static inline
const T& carla_min(const T& v1, const T& v2, const T& min) noexcept
{
return ((v1 <= min || v2 <= min) ? min : (v1 < v2 ? v1 : v2));
@@ -150,7 +246,8 @@ const T& carla_min(const T& v1, const T& v2, const T& min) noexcept
/*
* Return the higher of 2 values, with 'max' as the maximum possible value.
*/
template<typename T> inline
template<typename T>
static inline
const T& carla_max(const T& v1, const T& v2, const T& max) noexcept
{
return ((v1 >= max || v2 >= max) ? max : (v1 > v2 ? v1 : v2));
@@ -159,7 +256,8 @@ const T& carla_max(const T& v1, const T& v2, const T& max) noexcept
/*
* Fix bounds of 'value', between 'min' and 'max'.
*/
template<typename T> inline
template<typename T>
static inline
const T& carla_fixValue(const T& min, const T& max, const T& value)
{
CARLA_SAFE_ASSERT_RETURN(max > min, max);
@@ -174,7 +272,8 @@ const T& carla_fixValue(const T& min, const T& max, const T& value)
/*
* Add array values to another array.
*/
template<typename T> inline
template<typename T>
static inline
void carla_add(T* dataDst, T* dataSrc, const size_t size)
{
CARLA_SAFE_ASSERT_RETURN(dataDst != nullptr,);
@@ -188,7 +287,8 @@ void carla_add(T* dataDst, T* dataSrc, const size_t size)
/*
* Add array values to another array.
*/
template<typename T> inline
template<typename T>
static inline
void carla_add(T* dataDst, const T* dataSrc, const size_t size)
{
CARLA_SAFE_ASSERT_RETURN(dataDst != nullptr,);
@@ -202,7 +302,8 @@ void carla_add(T* dataDst, const T* dataSrc, const size_t size)
/*
* Fill an array with a fixed value.
*/
template<typename T> inline
template<typename T>
static inline
void carla_fill(T* data, const size_t size, const T v)
{
CARLA_SAFE_ASSERT_RETURN(data != nullptr,);
@@ -235,7 +336,8 @@ inline float
/*
* Clear a char array.
*/
template<typename C = char> inline
template<typename C = char>
static inline
void carla_zeroChar(C* const data, const size_t numChars)
{
CARLA_SAFE_ASSERT_RETURN(data != nullptr,);
@@ -247,7 +349,7 @@ void carla_zeroChar(C* const data, const size_t numChars)
/*
* Clear a memory location.
*/
inline
static inline
void carla_zeroMem(void* const memory, const size_t numBytes)
{
CARLA_SAFE_ASSERT_RETURN(memory != nullptr,);
@@ -259,7 +361,8 @@ void carla_zeroMem(void* const memory, const size_t numBytes)
/*
* Clear a single struct/class.
*/
template <typename T> inline
template <typename T>
static inline
void carla_zeroStruct(T& structure)
{
std::memset(&structure, 0, sizeof(T));
@@ -268,7 +371,8 @@ void carla_zeroStruct(T& structure)
/*
* Clear an array of struct/class.
*/
template <typename T> inline
template <typename T>
static inline
void carla_zeroStruct(T* const structure, const size_t count)
{
CARLA_SAFE_ASSERT_RETURN(structure != nullptr,);
@@ -277,12 +381,11 @@ void carla_zeroStruct(T* const structure, const size_t count)
std::memset(structure, 0, count*sizeof(T));
}

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

/*
* Copy a single struct/class.
*/
template <typename T> inline
template <typename T>
static inline
void carla_copyStruct(T& struct1, T& struct2)
{
std::memcpy(&struct1, &struct2, sizeof(T));
@@ -291,7 +394,8 @@ void carla_copyStruct(T& struct1, T& struct2)
/*
* Copy an array of struct/class.
*/
template <typename T> inline
template <typename T>
static inline
void carla_copyStruct(T* const struct1, T* const struct2, const size_t count)
{
CARLA_SAFE_ASSERT_RETURN(struct1 != nullptr,);


+ 0
- 2
source/utils/CarlaVstUtils.hpp View File

@@ -20,8 +20,6 @@

#include "CarlaUtils.hpp"

#include <cstring>

// -----------------------------------------------------------------------
// Include fixes



+ 4
- 4
source/utils/JucePluginWindow.hpp View File

@@ -24,10 +24,10 @@

namespace juce {

class JucePluginWindow : public DocumentWindow
class PluginWindow : public DocumentWindow
{
public:
JucePluginWindow()
PluginWindow()
: DocumentWindow("PluginWindow", Colour(50, 50, 200), DocumentWindow::closeButton, false),
fClosed(false)
{
@@ -75,12 +75,12 @@ protected:
private:
volatile bool fClosed;

JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(JucePluginWindow)
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PluginWindow)
};

} // namespace juce

using juce::JucePluginWindow;
typedef juce::PluginWindow JucePluginWindow;

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



+ 420
- 0
source/utils/List.hpp View File

@@ -0,0 +1,420 @@
/*
* High-level, templated, C++ doubly-linked list
* 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 doc/GPL.txt file.
*/

#ifndef LIST_HPP_INCLUDED
#define LIST_HPP_INCLUDED

#include "CarlaUtils.hpp"

#include <new>

extern "C" {
#include "rtmempool/list.h"
}

// Declare non copyable and prevent heap allocation
#ifdef CARLA_PROPER_CPP11_SUPPORT
# define LIST_DECLARATIONS(ClassName) \
ClassName(ClassName&) = delete; \
ClassName(const ClassName&) = delete; \
ClassName& operator=(const ClassName&) = delete; \
static void* operator new(size_t) = delete;
#else
# define LIST_DECLARATIONS(ClassName) \
ClassName(ClassName&); \
ClassName(const ClassName&); \
ClassName& operator=(const ClassName&);
#endif

typedef struct list_head k_list_head;

// -----------------------------------------------------------------------
// Abstract List class
// _allocate() and _deallocate are virtual calls provided by subclasses

template<typename T>
class AbstractList
{
protected:
struct Data {
T value;
k_list_head siblings;
};

AbstractList()
: fDataSize(sizeof(Data)),
fCount(0)
{
_init();
}

virtual ~AbstractList()
{
CARLA_ASSERT(fCount == 0);
}

public:
class Itenerator {
public:
Itenerator(const k_list_head* queue)
: fData(nullptr),
fEntry(queue->next),
fEntry2(fEntry->next),
fQueue(queue)
{
CARLA_ASSERT(fEntry != nullptr);
CARLA_ASSERT(fEntry2 != nullptr);
CARLA_ASSERT(fQueue != nullptr);
}

bool valid() const noexcept
{
return (fEntry != fQueue);
}

void next() noexcept
{
fEntry = fEntry2;
fEntry2 = fEntry->next;
}

T& operator*()
{
fData = list_entry(fEntry, Data, siblings);
CARLA_ASSERT(fData != nullptr);
return fData->value;
}

private:
Data* fData;
k_list_head* fEntry;
k_list_head* fEntry2;
const k_list_head* const fQueue;

friend class AbstractList;
};

Itenerator begin() const
{
return Itenerator(&fQueue);
}

void clear()
{
if (fCount != 0)
{
k_list_head* entry;
k_list_head* entry2;

list_for_each_safe(entry, entry2, &fQueue)
{
if (Data* data = list_entry(entry, Data, siblings))
{
data->~Data();
_deallocate(data);
}
}
}

_init();
}

size_t count() const noexcept
{
return fCount;
}

bool isEmpty() const noexcept
{
return (fCount == 0);
}

bool append(const T& value)
{
if (Data* const data = _allocate())
{
new(data)Data();
data->value = value;
list_add_tail(&data->siblings, &fQueue);
++fCount;
return true;
}

return false;
}

bool appendAt(const T& value, const Itenerator& it)
{
if (Data* const data = _allocate())
{
new(data)Data();
data->value = value;
list_add_tail(&data->siblings, it.fEntry->next);
++fCount;
return true;
}

return false;
}

bool insert(const T& value)
{
if (Data* const data = _allocate())
{
new(data)Data();
data->value = value;
list_add(&data->siblings, &fQueue);
++fCount;
return true;
}

return false;
}

bool insertAt(const T& value, const Itenerator& it)
{
if (Data* const data = _allocate())
{
new(data)Data();
data->value = value;
list_add(&data->siblings, it.fEntry->prev);
++fCount;
return true;
}

return false;
}

T& getAt(const size_t index, const bool remove = false)
{
if (fCount == 0 || index >= fCount)
return fRetValue;

size_t i = 0;
Data* data = nullptr;
k_list_head* entry;
k_list_head* entry2;

list_for_each_safe(entry, entry2, &fQueue)
{
if (index != i++)
continue;

data = list_entry(entry, Data, siblings);

if (data != nullptr)
fRetValue = data->value;

if (remove)
{
--fCount;
list_del(entry);

if (data != nullptr)
{
data->~Data();
_deallocate(data);
}
}

break;
}

return fRetValue;
}

T& getFirst(const bool remove = false)
{
return _getFirstOrLast(true, remove);
}

T& getLast(const bool remove = false)
{
return _getFirstOrLast(false, remove);
}

void remove(Itenerator& it)
{
CARLA_ASSERT(it.fEntry != nullptr);
CARLA_ASSERT(it.fData != nullptr);

if (it.fEntry != nullptr && it.fData != nullptr)
{
--fCount;
list_del(it.fEntry);

it.fData->~Data();
_deallocate(it.fData);
}
}

bool removeOne(const T& value)
{
Data* data = nullptr;
k_list_head* entry;
k_list_head* entry2;

list_for_each_safe(entry, entry2, &fQueue)
{
data = list_entry(entry, Data, siblings);

CARLA_SAFE_ASSERT_CONTINUE(data != nullptr);

if (data->value == value)
{
--fCount;
list_del(entry);

data->~Data();
_deallocate(data);
break;
}
}

return (data != nullptr);
}

void removeAll(const T& value)
{
Data* data;
k_list_head* entry;
k_list_head* entry2;

list_for_each_safe(entry, entry2, &fQueue)
{
data = list_entry(entry, Data, siblings);

CARLA_SAFE_ASSERT_CONTINUE(data != nullptr);

if (data->value == value)
{
--fCount;
list_del(entry);

data->~Data();
_deallocate(data);
}
}
}

void spliceAppend(AbstractList& list, const bool init = true)
{
if (init)
{
list_splice_tail_init(&fQueue, &list.fQueue);
list.fCount += fCount;
fCount = 0;
}
else
{
list_splice_tail(&fQueue, &list.fQueue);
list.fCount += fCount;
}
}

void spliceInsert(AbstractList& list, const bool init = true)
{
if (init)
{
list_splice_init(&fQueue, &list.fQueue);
list.fCount += fCount;
fCount = 0;
}
else
{
list_splice(&fQueue, &list.fQueue);
list.fCount += fCount;
}
}

protected:
const size_t fDataSize;
size_t fCount;
k_list_head fQueue;

virtual Data* _allocate() = 0;
virtual void _deallocate(Data*& dataPtr) = 0;

private:
T fRetValue;

void _init() noexcept
{
fCount = 0;
INIT_LIST_HEAD(&fQueue);
}

T& _getFirstOrLast(const bool first, const bool remove)
{
if (fCount == 0)
return fRetValue;

k_list_head* const entry = first ? fQueue.next : fQueue.prev;
Data* data = list_entry(entry, Data, siblings);

if (data != nullptr)
fRetValue = data->value;

if (remove)
{
--fCount;
list_del(entry);

if (data != nullptr)
{
data->~Data();
_deallocate(data);
}
}

return fRetValue;
}

LIST_DECLARATIONS(AbstractList)
};

// -----------------------------------------------------------------------
// List

template<typename T>
class List : public AbstractList<T>
{
public:
List()
{
}

private:
typename AbstractList<T>::Data* _allocate() override
{
return (typename AbstractList<T>::Data*)std::malloc(this->fDataSize);
}

void _deallocate(typename AbstractList<T>::Data*& dataPtr) override
{
CARLA_SAFE_ASSERT_RETURN(dataPtr != nullptr,);

std::free(dataPtr);
dataPtr = nullptr;
}

LIST_DECLARATIONS(List)
};

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

#endif // LIST_HPP_INCLUDED

+ 14
- 7
source/utils/Lv2AtomQueue.hpp View File

@@ -82,6 +82,9 @@ private:
} fRetAtom;

friend class Lv2AtomQueue;

CARLA_PREVENT_HEAP_ALLOCATION
CARLA_DECLARE_NON_COPY_CLASS(Lv2AtomRingBufferControl)
};

// -----------------------------------------------------------------------
@@ -93,7 +96,7 @@ public:
{
}

void copyDataFrom(Lv2AtomQueue& queue)
void copyDataFromQueue(Lv2AtomQueue& queue)
{
// lock queue
const CarlaMutex::ScopedLocker qsl(queue.fMutex);
@@ -104,21 +107,21 @@ public:
carla_copyStruct<RingBuffer>(fRingBufferCtrl.fBuffer, queue.fRingBufferCtrl.fBuffer);
}

// reset queque
fRingBufferCtrl.clear();
// reset queque - FIXME? no queue.?
queue.fRingBufferCtrl.clear();
}

void lock()
void lock() const noexcept
{
fMutex.lock();
}

bool tryLock()
bool tryLock() const noexcept
{
return fMutex.tryLock();
}

void unlock()
void unlock() const noexcept
{
fMutex.unlock();
}
@@ -127,6 +130,8 @@ public:
{
CARLA_SAFE_ASSERT_RETURN(atom != nullptr && atom->size > 0, false);

const CarlaMutex::ScopedLocker sl(fMutex);

return fRingBufferCtrl.writeAtom(atom, static_cast<int32_t>(portIndex));
}

@@ -134,7 +139,9 @@ public:
{
CARLA_SAFE_ASSERT_RETURN(atom != nullptr && portIndex != nullptr, false);

if (! fRingBufferCtrl.dataAvailable())
const CarlaMutex::ScopedLocker sl(fMutex);

if (! fRingBufferCtrl.isDataAvailable())
return false;

if (const LV2_Atom* retAtom = fRingBufferCtrl.readAtom(portIndex))


+ 19
- 414
source/utils/RtList.hpp View File

@@ -18,381 +18,17 @@
#ifndef RT_LIST_HPP_INCLUDED
#define RT_LIST_HPP_INCLUDED

#include "CarlaUtils.hpp"

#include <new>
#include "List.hpp"

extern "C" {
#include "rtmempool/list.h"
#include "rtmempool/rtmempool.h"
}

// Declare non copyable and prevent heap allocation
#ifdef CARLA_PROPER_CPP11_SUPPORT
# define LIST_DECLARATIONS(ClassName) \
ClassName(ClassName&) = delete; \
ClassName(const ClassName&) = delete; \
ClassName& operator=(const ClassName&) = delete; \
static void* operator new(size_t) = delete;
#else
# define LIST_DECLARATIONS(ClassName) \
ClassName(ClassName&); \
ClassName(const ClassName&); \
ClassName& operator=(const ClassName&);
#endif

typedef struct list_head k_list_head;

// -----------------------------------------------------------------------
// Abstract List class
// _allocate() and _deallocate are virtual calls provided by subclasses

template<typename T>
class List
{
protected:
struct Data {
T value;
k_list_head siblings;
};

List()
: fDataSize(sizeof(Data)),
fCount(0)
{
_init();
}

virtual ~List()
{
CARLA_ASSERT(fCount == 0);
}

public:
class Itenerator {
public:
Itenerator(const k_list_head* queue)
: fData(nullptr),
fEntry(queue->next),
fEntry2(fEntry->next),
fQueue(queue)
{
CARLA_ASSERT(fEntry != nullptr);
CARLA_ASSERT(fEntry2 != nullptr);
CARLA_ASSERT(fQueue != nullptr);
}

bool valid() const noexcept
{
return (fEntry != fQueue);
}

void next() noexcept
{
fEntry = fEntry2;
fEntry2 = fEntry->next;
}

T& operator*()
{
fData = list_entry(fEntry, Data, siblings);
CARLA_ASSERT(fData != nullptr);
return fData->value;
}

private:
Data* fData;
k_list_head* fEntry;
k_list_head* fEntry2;
const k_list_head* const fQueue;

friend class List;
};

Itenerator begin() const
{
return Itenerator(&fQueue);
}

void clear()
{
if (fCount != 0)
{
k_list_head* entry;
k_list_head* entry2;

list_for_each_safe(entry, entry2, &fQueue)
{
if (Data* data = list_entry(entry, Data, siblings))
{
data->~Data();
_deallocate(data);
}
}
}

_init();
}

size_t count() const noexcept
{
return fCount;
}

bool isEmpty() const noexcept
{
return (fCount == 0);
}

bool append(const T& value)
{
if (Data* const data = _allocate())
{
new(data)Data();
data->value = value;
list_add_tail(&data->siblings, &fQueue);
++fCount;
return true;
}

return false;
}

bool appendAt(const T& value, const Itenerator& it)
{
if (Data* const data = _allocate())
{
new(data)Data();
data->value = value;
list_add_tail(&data->siblings, it.fEntry->next);
++fCount;
return true;
}

return false;
}

bool insert(const T& value)
{
if (Data* const data = _allocate())
{
new(data)Data();
data->value = value;
list_add(&data->siblings, &fQueue);
++fCount;
return true;
}

return false;
}

bool insertAt(const T& value, const Itenerator& it)
{
if (Data* const data = _allocate())
{
new(data)Data();
data->value = value;
list_add(&data->siblings, it.fEntry->prev);
++fCount;
return true;
}

return false;
}

T& getAt(const size_t index, const bool remove = false)
{
if (fCount == 0 || index >= fCount)
return fRetValue;

size_t i = 0;
Data* data = nullptr;
k_list_head* entry;
k_list_head* entry2;

list_for_each_safe(entry, entry2, &fQueue)
{
if (index != i++)
continue;

data = list_entry(entry, Data, siblings);

if (data != nullptr)
fRetValue = data->value;

if (remove)
{
--fCount;
list_del(entry);

if (data != nullptr)
{
data->~Data();
_deallocate(data);
}
}

break;
}

return fRetValue;
}

T& getFirst(const bool remove = false)
{
return _getFirstOrLast(true, remove);
}

T& getLast(const bool remove = false)
{
return _getFirstOrLast(false, remove);
}

void remove(Itenerator& it)
{
CARLA_ASSERT(it.fEntry != nullptr);
CARLA_ASSERT(it.fData != nullptr);

if (it.fEntry != nullptr && it.fData != nullptr)
{
--fCount;
list_del(it.fEntry);

it.fData->~Data();
_deallocate(it.fData);
}
}

bool removeOne(const T& value)
{
Data* data = nullptr;
k_list_head* entry;
k_list_head* entry2;

list_for_each_safe(entry, entry2, &fQueue)
{
data = list_entry(entry, Data, siblings);

CARLA_SAFE_ASSERT_CONTINUE(data != nullptr);

if (data->value == value)
{
--fCount;
list_del(entry);

data->~Data();
_deallocate(data);
break;
}
}

return (data != nullptr);
}

void removeAll(const T& value)
{
Data* data;
k_list_head* entry;
k_list_head* entry2;

list_for_each_safe(entry, entry2, &fQueue)
{
data = list_entry(entry, Data, siblings);

CARLA_SAFE_ASSERT_CONTINUE(data != nullptr);

if (data->value == value)
{
--fCount;
list_del(entry);

data->~Data();
_deallocate(data);
}
}
}

void spliceAppend(List& list, const bool init = true)
{
if (init)
{
list_splice_tail_init(&fQueue, &list.fQueue);
list.fCount += fCount;
fCount = 0;
}
else
{
list_splice_tail(&fQueue, &list.fQueue);
list.fCount += fCount;
}
}

void spliceInsert(List& list, const bool init = true)
{
if (init)
{
list_splice_init(&fQueue, &list.fQueue);
list.fCount += fCount;
fCount = 0;
}
else
{
list_splice(&fQueue, &list.fQueue);
list.fCount += fCount;
}
}

protected:
const size_t fDataSize;
size_t fCount;
k_list_head fQueue;

virtual Data* _allocate() = 0;
virtual void _deallocate(Data*& dataPtr) = 0;

private:
T fRetValue;

void _init() noexcept
{
fCount = 0;
INIT_LIST_HEAD(&fQueue);
}

T& _getFirstOrLast(const bool first, const bool remove)
{
if (fCount == 0)
return fRetValue;

k_list_head* const entry = first ? fQueue.next : fQueue.prev;
Data* data = list_entry(entry, Data, siblings);

if (data != nullptr)
fRetValue = data->value;

if (remove)
{
--fCount;
list_del(entry);

if (data != nullptr)
{
data->~Data();
_deallocate(data);
}
}

return fRetValue;
}

LIST_DECLARATIONS(List)
};

// -----------------------------------------------------------------------
// Realtime safe list

template<typename T>
class RtList : public List<T>
class RtList : public AbstractList<T>
{
public:
// -------------------------------------------------------------------
@@ -403,7 +39,7 @@ public:
public:
Pool(const size_t minPreallocated, const size_t maxPreallocated)
: fHandle(nullptr),
fDataSize(sizeof(typename List<T>::Data))
fDataSize(sizeof(typename AbstractList<T>::Data))
{
resize(minPreallocated, maxPreallocated);
}
@@ -455,8 +91,8 @@ public:
}

private:
RtMemPool_Handle fHandle;
const size_t fDataSize;
mutable RtMemPool_Handle fHandle;
const size_t fDataSize;
};

// -------------------------------------------------------------------
@@ -469,23 +105,23 @@ public:

void append_sleepy(const T& value)
{
if (typename List<T>::Data* const data = _allocate_sleepy())
if (typename AbstractList<T>::Data* const data = _allocate_sleepy())
{
new(data)typename List<T>::Data();
new(data)typename AbstractList<T>::Data();
data->value = value;
list_add_tail(&data->siblings, &this->fQueue);
++this->fCount;
++(this->fCount);
}
}

void insert_sleepy(const T& value)
{
if (typename List<T>::Data* const data = _allocate_sleepy())
if (typename AbstractList<T>::Data* const data = _allocate_sleepy())
{
new(data)typename List<T>::Data();
new(data)typename AbstractList<T>::Data();
data->value = value;
list_add(&data->siblings, &this->fQueue);
++this->fCount;
++(this->fCount);
}
}

@@ -500,37 +136,33 @@ public:
{
CARLA_ASSERT(fMemPool == list.fMemPool);

List<T>::spliceAppend(list, init);
AbstractList<T>::spliceAppend(list, init);
}

void spliceInsert(RtList& list, const bool init = true)
{
CARLA_ASSERT(fMemPool == list.fMemPool);

List<T>::spliceInsert(list, init);
AbstractList<T>::spliceInsert(list, init);
}

private:
Pool& fMemPool;

typename List<T>::Data* _allocate() override
typename AbstractList<T>::Data* _allocate() override
{
return _allocate_atomic();
return (typename AbstractList<T>::Data*)fMemPool.allocate_atomic();
}

typename List<T>::Data* _allocate_atomic()
typename AbstractList<T>::Data* _allocate_sleepy()
{
return (typename List<T>::Data*)fMemPool.allocate_atomic();
return (typename AbstractList<T>::Data*)fMemPool.allocate_sleepy();
}

typename List<T>::Data* _allocate_sleepy()
void _deallocate(typename AbstractList<T>::Data*& dataPtr) override
{
return (typename List<T>::Data*)fMemPool.allocate_sleepy();
}
CARLA_SAFE_ASSERT_RETURN(dataPtr != nullptr,);

void _deallocate(typename List<T>::Data*& dataPtr) override
{
CARLA_ASSERT(dataPtr != nullptr);
fMemPool.deallocate(dataPtr);
dataPtr = nullptr;
}
@@ -538,33 +170,6 @@ private:
LIST_DECLARATIONS(RtList)
};

// -----------------------------------------------------------------------
// Non-Realtime list

template<typename T>
class NonRtList : public List<T>
{
public:
NonRtList()
{
}

private:
typename List<T>::Data* _allocate() override
{
return (typename List<T>::Data*)std::malloc(this->fDataSize);
}

void _deallocate(typename List<T>::Data*& dataPtr) override
{
CARLA_ASSERT(dataPtr != nullptr);
std::free(dataPtr);
dataPtr = nullptr;
}

LIST_DECLARATIONS(NonRtList)
};

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

#endif // RT_LIST_HPP_INCLUDED

+ 0
- 213
source/utils/Utils.cpp View File

@@ -1,213 +0,0 @@
/*
* Carla utils
* Copyright (C) 2011-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 doc/GPL.txt file.
*/

#include "CarlaDefines.hpp"

// IDE Helper
#ifndef REAL_BUILD
# include "CarlaUtils.hpp"
# include "CarlaLibUtils.hpp"
#endif

#include <cstdarg> // needed for va_*
#include <cstdio> // needed for *printf
#include <cstdlib> // needed for free
#include <cstring> // needed for str*

#ifdef CARLA_OS_WIN
# include <winsock2.h> // should be included before "windows.h"
# include <windows.h>
#else
# include <dlfcn.h>
# include <unistd.h>
#endif

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

#ifdef CARLA_UTILS_HPP_INCLUDED
// -----------------------------------------------------------------------
// string print functions

#ifdef DEBUG
void carla_debug(const char* const fmt, ...)
{
va_list args;
va_start(args, fmt);
std::fprintf(stdout, "\x1b[30;1m");
std::vfprintf(stdout, fmt, args);
std::fprintf(stdout, "\x1b[0m\n");
va_end(args);
}
#endif

void carla_stdout(const char* const fmt, ...)
{
va_list args;
va_start(args, fmt);
std::vfprintf(stdout, fmt, args);
std::fprintf(stdout, "\n");
va_end(args);
}

void carla_stderr(const char* const fmt, ...)
{
va_list args;
va_start(args, fmt);
std::vfprintf(stderr, fmt, args);
std::fprintf(stderr, "\n");
va_end(args);
}

void carla_stderr2(const char* const fmt, ...)
{
va_list args;
va_start(args, fmt);
std::fprintf(stderr, "\x1b[31m");
std::vfprintf(stderr, fmt, args);
std::fprintf(stderr, "\x1b[0m\n");
va_end(args);
}

// -----------------------------------------------------------------------
// carla_*sleep

void carla_sleep(const unsigned int secs)
{
CARLA_SAFE_ASSERT_RETURN(secs > 0,);

#ifdef CARLA_OS_WIN
Sleep(secs * 1000);
#else
sleep(secs);
#endif
}

void carla_msleep(const unsigned int msecs)
{
CARLA_SAFE_ASSERT_RETURN(msecs > 0,);

#ifdef CARLA_OS_WIN
Sleep(msecs);
#else
usleep(msecs * 1000);
#endif
}

// -----------------------------------------------------------------------
// carla_setenv

void carla_setenv(const char* const key, const char* const value)
{
CARLA_SAFE_ASSERT_RETURN(key != nullptr,);
CARLA_SAFE_ASSERT_RETURN(value != nullptr,);

#ifdef CARLA_OS_WIN
SetEnvironmentVariableA(key, value);
#else
setenv(key, value, 1);
#endif
}

// -----------------------------------------------------------------------
// carla_strdup

const char* carla_strdup(const char* const strBuf)
{
CARLA_SAFE_ASSERT(strBuf != nullptr);

const size_t bufferLen = (strBuf != nullptr) ? std::strlen(strBuf) : 0;
char* const buffer = new char[bufferLen+1];

if (strBuf != nullptr && bufferLen > 0)
std::strncpy(buffer, strBuf, bufferLen);

buffer[bufferLen] = '\0';

return buffer;
}

const char* carla_strdup_free(char* const strBuf)
{
const char* const buffer(carla_strdup(strBuf));
std::free(strBuf);
return buffer;
}
#endif // CARLA_UTILS_HPP_INCLUDED

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

#ifdef CARLA_LIB_UTILS_HPP_INCLUDED
// -----------------------------------------------------------------------
// library related calls

void* lib_open(const char* const filename)
{
CARLA_SAFE_ASSERT_RETURN(filename != nullptr, nullptr);

#ifdef CARLA_OS_WIN
return (void*)LoadLibraryA(filename);
#else
return dlopen(filename, RTLD_NOW|RTLD_LOCAL);
#endif
}

bool lib_close(void* const lib)
{
CARLA_SAFE_ASSERT_RETURN(lib != nullptr, false);

#ifdef CARLA_OS_WIN
return FreeLibrary((HMODULE)lib);
#else
return (dlclose(lib) == 0);
#endif
}

void* lib_symbol(void* const lib, const char* const symbol)
{
CARLA_SAFE_ASSERT_RETURN(lib != nullptr, nullptr);
CARLA_SAFE_ASSERT_RETURN(symbol != nullptr, nullptr);

#ifdef CARLA_OS_WIN
return (void*)GetProcAddress((HMODULE)lib, symbol);
#else
return dlsym(lib, symbol);
#endif
}

const char* lib_error(const char* const filename)
{
CARLA_SAFE_ASSERT_RETURN(filename != nullptr, nullptr);

#ifdef CARLA_OS_WIN
static char libError[2048+1];
carla_zeroChar(libError, 2048+1);

LPVOID winErrorString;
DWORD winErrorCode = GetLastError();
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, winErrorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&winErrorString, 0, nullptr);

std::snprintf(libError, 2048, "%s: error code %li: %s", filename, winErrorCode, (const char*)winErrorString);
LocalFree(winErrorString);

return libError;
#else
return dlerror();
#endif
}
#endif // CARLA_LIB_UTILS_HPP_INCLUDED

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

Loading…
Cancel
Save