Browse Source

More work

tags/1.9.4
falkTX 11 years ago
parent
commit
391f5a0d60
27 changed files with 758 additions and 198 deletions
  1. +11
    -2
      source/Makefile.mk
  2. +43
    -30
      source/backend/carla_engine.hpp
  3. +27
    -21
      source/backend/carla_native.h
  4. +5
    -5
      source/backend/engine/carla_engine.cpp
  5. +2
    -1
      source/backend/engine/carla_engine.pro
  6. +12
    -12
      source/backend/engine/carla_engine_internal.hpp
  7. +3
    -0
      source/backend/engine/carla_engine_osc.hpp
  8. +3
    -1
      source/backend/engine/carla_engine_thread.hpp
  9. +37
    -16
      source/backend/engine/jack.cpp
  10. +7
    -0
      source/backend/engine/rtaudio.cpp
  11. +6
    -2
      source/discovery/carla-discovery.cpp
  12. +1
    -0
      source/discovery/carla-discovery.pro
  13. +1
    -1
      source/includes/carla_midi.h
  14. +1
    -1
      source/includes/ladspa_rdf.hpp
  15. +1
    -1
      source/includes/lv2_rdf.hpp
  16. +1
    -0
      source/includes/pugl
  17. +1
    -1
      source/libs/distrho-plugin-toolkit/DistrhoUtils.h
  18. +4
    -44
      source/libs/distrho-plugin-toolkit/src/DistrhoDefines.h
  19. +62
    -0
      source/libs/distrho-plugin-toolkit/src/DistrhoMacros.h
  20. +1
    -1
      source/libs/distrho-plugin-toolkit/src/DistrhoPluginInternal.h
  21. +1
    -0
      source/libs/distrho-plugin-toolkit/src/pugl
  22. +30
    -0
      source/libs/distrho-plugin-toolkit/src/pugl.cpp
  23. +358
    -0
      source/utils/carla_juce_utils.hpp
  24. +3
    -1
      source/utils/carla_lv2_utils.hpp
  25. +110
    -34
      source/utils/carla_utils.hpp
  26. +4
    -6
      source/utils/lv2_atom_queue.hpp
  27. +23
    -18
      source/utils/rt_list.hpp

+ 11
- 2
source/Makefile.mk View File

@@ -55,8 +55,6 @@ BUILD_CXX_FLAGS += -DVESTIGE_HEADER
# -------------------------------------------------------------- # --------------------------------------------------------------


ifeq ($(CARLA_PLUGIN_SUPPORT),true) ifeq ($(CARLA_PLUGIN_SUPPORT),true)
BUILD_C_FLAGS += -DWANT_LV2
BUILD_CXX_FLAGS += -DWANT_LADSPA -DWANT_DSSI -DWANT_LV2 -DWANT_VST
HAVE_SUIL = $(shell pkg-config --exists suil-0 && echo true) HAVE_SUIL = $(shell pkg-config --exists suil-0 && echo true)
endif endif


@@ -71,3 +69,14 @@ HAVE_PULSEAUDIO = $(shell pkg-config --exists libpulse-simple && echo true)
endif endif


HAVE_ZYN_DEPS = $(shell pkg-config --exists fftw3 mxml && echo true) HAVE_ZYN_DEPS = $(shell pkg-config --exists fftw3 mxml && echo true)

# --------------------------------------------------------------

ifeq ($(CARLA_PLUGIN_SUPPORT),true)
BUILD_C_FLAGS += -DWANT_LV2
BUILD_CXX_FLAGS += -DWANT_LADSPA -DWANT_DSSI -DWANT_LV2 -DWANT_VST
endif

ifeq ($(HAVE_ZYN_DEPS),true)
BUILD_CXX_FLAGS += -DWANT_ZYNADDSUBFX
endif

+ 43
- 30
source/backend/carla_engine.hpp View File

@@ -19,7 +19,7 @@
#define __CARLA_ENGINE_HPP__ #define __CARLA_ENGINE_HPP__


#include "carla_backend.hpp" #include "carla_backend.hpp"
#include "carla_utils.hpp"
#include "carla_juce_utils.hpp"


#ifndef BUILD_BRIDGE #ifndef BUILD_BRIDGE
class QProcessEnvironment; class QProcessEnvironment;
@@ -27,6 +27,10 @@ class QProcessEnvironment;


CARLA_BACKEND_START_NAMESPACE CARLA_BACKEND_START_NAMESPACE


#if 0
} // Fix editor indentation
#endif

/*! /*!
* @defgroup CarlaBackendEngine Carla Backend Engine * @defgroup CarlaBackendEngine Carla Backend Engine
* *
@@ -45,19 +49,17 @@ enum CarlaEngineType {


/*! /*!
* JACK engine type.\n * JACK engine type.\n
* Provides single, multi-client, and rack processing modes.
* Provides all processing modes.
*/ */
CarlaEngineTypeJack = 1, CarlaEngineTypeJack = 1,


/*! /*!
* RtAudio engine type, used to provide Native Audio and Midi support.\n
* Provides rack mode processing only.
* RtAudio engine type, used to provide Native Audio and MIDI support.
*/ */
CarlaEngineTypeRtAudio = 2, CarlaEngineTypeRtAudio = 2,


/*! /*!
* Plugin engine type, used to export the engine as a plugin (DSSI, LV2 and VST) via the DISTRHO Plugin Toolkit.\n
* Works in rack mode only.
* Plugin engine type, used to export the engine as a plugin (DSSI, LV2 and VST) via the DISTRHO Plugin Toolkit.
*/ */
CarlaEngineTypePlugin = 3 CarlaEngineTypePlugin = 3
}; };
@@ -89,39 +91,39 @@ enum CarlaEnginePortType {
}; };


/*! /*!
* The type of a control event.
* The type of an engine control event.
*/ */
enum CarlaEngineControlEventType { enum CarlaEngineControlEventType {
/*! /*!
* Null event type.
* Null control event type.
*/ */
CarlaEngineNullEvent = 0,
CarlaEngineControlEventTypeNull = 0,


/*! /*!
* Parameter change event.\n * Parameter change event.\n
* \note Value uses a range of 0.0<->1.0. * \note Value uses a range of 0.0<->1.0.
*/ */
CarlaEngineParameterChangeEvent = 1,
CarlaEngineControlEventTypeParameterChange = 1,


/*! /*!
* MIDI Bank change event. * MIDI Bank change event.
*/ */
CarlaEngineMidiBankChangeEvent = 2,
CarlaEngineControlEventTypeMidiBankChange = 2,


/*! /*!
* MIDI Program change event. * MIDI Program change event.
*/ */
CarlaEngineMidiProgramChangeEvent = 3,
CarlaEngineControlEventTypeMidiProgramChange = 3,


/*! /*!
* All sound off event. * All sound off event.
*/ */
CarlaEngineAllSoundOffEvent = 4,
CarlaEngineControlEventTypeAllSoundOff = 4,


/*! /*!
* All notes off event. * All notes off event.
*/ */
CarlaEngineAllNotesOffEvent = 5
CarlaEngineControlEventTypeAllNotesOff = 5
}; };


/*! /*!
@@ -132,18 +134,16 @@ struct CarlaEngineControlEvent {
uint32_t time; //!< frame offset uint32_t time; //!< frame offset
uint8_t channel; //!< channel, used for MIDI-related events and ports uint8_t channel; //!< channel, used for MIDI-related events and ports
uint16_t parameter; //!< parameter, used for parameter changes only uint16_t parameter; //!< parameter, used for parameter changes only
double value; //!< value
double value;


CarlaEngineControlEvent() CarlaEngineControlEvent()
: type(CarlaEngineNullEvent),
time(0),
channel(0),
parameter(0),
value(0.0) {}
{
clear();
}


void clear() void clear()
{ {
type = CarlaEngineNullEvent;
type = CarlaEngineControlEventTypeNull;
time = 0; time = 0;
channel = 0; channel = 0;
parameter = 0; parameter = 0;
@@ -160,9 +160,9 @@ struct CarlaEngineMidiEvent {
uint8_t data[3]; uint8_t data[3];


CarlaEngineMidiEvent() CarlaEngineMidiEvent()
: time(0),
size(0),
data{0} {}
{
clear();
}


void clear() void clear()
{ {
@@ -172,8 +172,6 @@ struct CarlaEngineMidiEvent {
} }
}; };


// LATER - CarlaEngineExtendedMidiEvent

/*! /*!
* Engine options. * Engine options.
*/ */
@@ -221,9 +219,9 @@ struct CarlaEngineOptions {
forceStereo(false), forceStereo(false),
preferPluginBridges(false), preferPluginBridges(false),
preferUiBridges(true), preferUiBridges(true),
#ifdef WANT_DSSI
#ifdef WANT_DSSI
useDssiVstChunks(false), useDssiVstChunks(false),
#endif
#endif
maxParameters(MAX_DEFAULT_PARAMETERS), maxParameters(MAX_DEFAULT_PARAMETERS),
oscUiTimeout(4000), oscUiTimeout(4000),
preferredBufferSize(512), preferredBufferSize(512),
@@ -287,7 +285,7 @@ public:
/*! /*!
* The contructor.\n * The contructor.\n
* Param \a isInput defines wherever this is an input port or not (output otherwise).\n * Param \a isInput defines wherever this is an input port or not (output otherwise).\n
* Input/output state and process mode is constant for the lifetime of the port.
* Input/output state and process mode are constant for the lifetime of the port.
*/ */
CarlaEnginePort(const bool isInput, const ProcessMode processMode); CarlaEnginePort(const bool isInput, const ProcessMode processMode);


@@ -310,6 +308,9 @@ protected:
const bool isInput; const bool isInput;
const ProcessMode processMode; const ProcessMode processMode;
void* buffer; void* buffer;

private:
CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEnginePort)
}; };


// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
@@ -343,6 +344,9 @@ public:
* Initialize the port's internal buffer for \a engine. * Initialize the port's internal buffer for \a engine.
*/ */
virtual void initBuffer(CarlaEngine* const engine); virtual void initBuffer(CarlaEngine* const engine);

private:
CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineAudioPort)
}; };


// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
@@ -398,6 +402,8 @@ public:


private: private:
const uint32_t m_maxEventCount; const uint32_t m_maxEventCount;

CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineControlPort)
}; };


// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
@@ -453,6 +459,8 @@ public:


private: private:
const uint32_t m_maxEventCount; const uint32_t m_maxEventCount;

CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineMidiPort)
}; };


// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
@@ -525,6 +533,8 @@ protected:
private: private:
bool m_active; bool m_active;
uint32_t m_latency; uint32_t m_latency;

CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineClient)
}; };


// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
@@ -1007,10 +1017,13 @@ private:
static const char* getRtAudioApiName(unsigned int index); static const char* getRtAudioApiName(unsigned int index);
#endif #endif


CarlaEnginePrivateData* const data;
ScopedPointer<CarlaEnginePrivateData> const data;


friend class CarlaEngineControlPort; friend class CarlaEngineControlPort;
friend class CarlaEngineMidiPort; friend class CarlaEngineMidiPort;

private:
CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngine)
}; };


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


+ 27
- 21
source/backend/carla_native.h View File

@@ -1,6 +1,6 @@
/* /*
* Carla Native Plugin API * Carla Native Plugin API
* Copyright (C) 2012 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2012-2013 Filipe Coelho <falktx@falktx.com>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -9,24 +9,25 @@
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* For a full copy of the GNU General Public License see the COPYING file * For a full copy of the GNU General Public License see the COPYING file
*/ */


#ifndef CARLA_NATIVE_H
#define CARLA_NATIVE_H
#ifndef __CARLA_NATIVE_H__
#define __CARLA_NATIVE_H__


#ifdef __cplusplus #ifdef __cplusplus
# include <cstddef>
# include <cstdint>
extern "C" { extern "C" {
#else #else
# include <stdbool.h> # include <stdbool.h>
# include <stddef.h>
# include <stdint.h>
#endif #endif


#include <stddef.h>
#include <stdint.h>

/*! /*!
* @defgroup CarlaNativeAPI Carla Native API * @defgroup CarlaNativeAPI Carla Native API
* *
@@ -38,9 +39,10 @@ extern "C" {
typedef void* HostHandle; typedef void* HostHandle;
typedef void* PluginHandle; typedef void* PluginHandle;


const uint32_t PLUGIN_IS_SYNTH = 1 << 0;
const uint32_t PLUGIN_HAS_GUI = 1 << 1;
const uint32_t PLUGIN_USES_SINGLE_THREAD = 1 << 2;
const uint32_t PLUGIN_IS_RTSAFE = 1 << 0;
const uint32_t PLUGIN_IS_SYNTH = 1 << 1;
const uint32_t PLUGIN_HAS_GUI = 1 << 2;
const uint32_t PLUGIN_USES_SINGLE_THREAD = 1 << 3;


const uint32_t PARAMETER_IS_OUTPUT = 1 << 0; const uint32_t PARAMETER_IS_OUTPUT = 1 << 0;
const uint32_t PARAMETER_IS_ENABLED = 1 << 1; const uint32_t PARAMETER_IS_ENABLED = 1 << 1;
@@ -106,14 +108,17 @@ typedef struct _MidiProgram {


typedef struct _TimeInfoBBT { typedef struct _TimeInfoBBT {
bool valid; bool valid;
int32_t bar;
int32_t beat;
int32_t tick;
double bar_start_tick;
float beats_per_bar;
float beat_type;
double ticks_per_beat;
double beats_per_minute;

int32_t bar; //!< current bar
int32_t beat; //!< current beat-within-bar
int32_t tick; //!< current tick-within-beat
double barStartTick;

float beatsPerBar; //!< time signature "numerator"
float beatType; //!< time signature "denominator"

double ticksPerBeat;
double beatsPerMinute;
} TimeInfoBBT; } TimeInfoBBT;


typedef struct _TimeInfo { typedef struct _TimeInfo {
@@ -129,12 +134,13 @@ typedef struct _HostDescriptor {
uint32_t (*get_buffer_size)(HostHandle handle); uint32_t (*get_buffer_size)(HostHandle handle);
double (*get_sample_rate)(HostHandle handle); double (*get_sample_rate)(HostHandle handle);
const TimeInfo* (*get_time_info)(HostHandle handle); const TimeInfo* (*get_time_info)(HostHandle handle);
bool (*write_midi_event)(HostHandle handle, MidiEvent* event);
bool (*write_midi_event)(HostHandle handle, const MidiEvent* event);


void (*ui_parameter_changed)(HostHandle handle, uint32_t index, float value); void (*ui_parameter_changed)(HostHandle handle, uint32_t index, float value);
void (*ui_midi_program_changed)(HostHandle handle, uint32_t bank, uint32_t program); void (*ui_midi_program_changed)(HostHandle handle, uint32_t bank, uint32_t program);
void (*ui_custom_data_changed)(HostHandle handle, const char* key, const char* value); void (*ui_custom_data_changed)(HostHandle handle, const char* key, const char* value);
void (*ui_closed)(HostHandle handle); void (*ui_closed)(HostHandle handle);

} HostDescriptor; } HostDescriptor;


typedef struct _PluginDescriptor { typedef struct _PluginDescriptor {
@@ -152,6 +158,7 @@ typedef struct _PluginDescriptor {
const char* const copyright; const char* const copyright;


PluginHandle (*instantiate)(const struct _PluginDescriptor* _this_, HostDescriptor* host); PluginHandle (*instantiate)(const struct _PluginDescriptor* _this_, HostDescriptor* host);
void (*cleanup)(PluginHandle handle);


uint32_t (*get_parameter_count)(PluginHandle handle); uint32_t (*get_parameter_count)(PluginHandle handle);
const Parameter* (*get_parameter_info)(PluginHandle handle, uint32_t index); const Parameter* (*get_parameter_info)(PluginHandle handle, uint32_t index);
@@ -174,7 +181,6 @@ typedef struct _PluginDescriptor {


void (*activate)(PluginHandle handle); void (*activate)(PluginHandle handle);
void (*deactivate)(PluginHandle handle); void (*deactivate)(PluginHandle handle);
void (*cleanup)(PluginHandle handle);
void (*process)(PluginHandle handle, float** inBuffer, float** outBuffer, uint32_t frames, uint32_t midiEventCount, const MidiEvent* midiEvents); void (*process)(PluginHandle handle, float** inBuffer, float** outBuffer, uint32_t frames, uint32_t midiEventCount, const MidiEvent* midiEvents);


} PluginDescriptor; } PluginDescriptor;
@@ -206,4 +212,4 @@ void carla_register_native_plugin_zynaddsubfx();
} // extern "C" } // extern "C"
#endif #endif


#endif // CARLA_NATIVE_H
#endif // __CARLA_NATIVE_H__

+ 5
- 5
source/backend/engine/carla_engine.cpp View File

@@ -135,7 +135,7 @@ uint32_t CarlaEngineControlPort::getEventCount()


for (unsigned short i=0; i < m_maxEventCount; i++, count++) for (unsigned short i=0; i < m_maxEventCount; i++, count++)
{ {
if (events[i].type == CarlaEngineNullEvent)
if (events[i].type == CarlaEngineControlEventTypeNull)
break; break;
} }


@@ -179,14 +179,14 @@ void CarlaEngineControlPort::writeEvent(const CarlaEngineControlEventType type,
return; return;


CARLA_ASSERT(buffer); CARLA_ASSERT(buffer);
CARLA_ASSERT(type != CarlaEngineNullEvent);
CARLA_ASSERT(type != CarlaEngineControlEventTypeNull);
CARLA_ASSERT(channel < 16); CARLA_ASSERT(channel < 16);


if (! buffer) if (! buffer)
return; return;
if (type == CarlaEngineNullEvent)
if (type == CarlaEngineControlEventTypeNull)
return; return;
if (type == CarlaEngineParameterChangeEvent)
if (type == CarlaEngineControlEventTypeParameterChange)
CARLA_ASSERT(! MIDI_IS_CONTROL_BANK_SELECT(parameter)); CARLA_ASSERT(! MIDI_IS_CONTROL_BANK_SELECT(parameter));
if (channel >= 16) if (channel >= 16)
return; return;
@@ -198,7 +198,7 @@ void CarlaEngineControlPort::writeEvent(const CarlaEngineControlEventType type,


for (unsigned short i=0; i < m_maxEventCount; i++) for (unsigned short i=0; i < m_maxEventCount; i++)
{ {
if (events[i].type != CarlaEngineNullEvent)
if (events[i].type != CarlaEngineControlEventTypeNull)
continue; continue;


events[i].type = type; events[i].type = type;


+ 2
- 1
source/backend/engine/carla_engine.pro View File

@@ -49,7 +49,8 @@ HEADERS += \


HEADERS += \ HEADERS += \
../../utils/carla_utils.hpp \ ../../utils/carla_utils.hpp \
../../utils/carla_backend_utils.hpp
../../utils/carla_backend_utils.hpp \
../../utils/carla_juce_utils.hpp


# HEADERS += \ # HEADERS += \
# plugin/DistrhoPluginInfo.h # plugin/DistrhoPluginInfo.h


+ 12
- 12
source/backend/engine/carla_engine_internal.hpp View File

@@ -77,18 +77,18 @@ const char* CarlaEngineControlEventType2Str(const CarlaEngineControlEventType ty
{ {
switch (type) switch (type)
{ {
case CarlaEngineNullEvent:
case CarlaEngineControlEventTypeNull:
return "CarlaEngineNullEvent"; return "CarlaEngineNullEvent";
case CarlaEngineParameterChangeEvent:
return "CarlaEngineParameterChangeEvent";
case CarlaEngineMidiBankChangeEvent:
return "CarlaEngineMidiBankChangeEvent";
case CarlaEngineMidiProgramChangeEvent:
return "CarlaEngineMidiProgramChangeEvent";
case CarlaEngineAllSoundOffEvent:
return "CarlaEngineAllSoundOffEvent";
case CarlaEngineAllNotesOffEvent:
return "CarlaEngineAllNotesOffEvent";
case CarlaEngineControlEventTypeParameterChange:
return "CarlaEngineControlEventTypeParameterChange";
case CarlaEngineControlEventTypeMidiBankChange:
return "CarlaEngineControlEventTypeMidiBankChange";
case CarlaEngineControlEventTypeMidiProgramChange:
return "CarlaEngineControlEventTypeMidiProgramChange";
case CarlaEngineControlEventTypeAllSoundOff:
return "CarlaEngineControlEventTypeAllSoundOff";
case CarlaEngineControlEventTypeAllNotesOff:
return "CarlaEngineControlEventTypeAllNotesOff";
} }


qWarning("CarlaBackend::CarlaEngineControlEventType2Str(%i) - invalid type", type); qWarning("CarlaBackend::CarlaEngineControlEventType2Str(%i) - invalid type", type);
@@ -141,7 +141,7 @@ struct CarlaEnginePrivateData {
CarlaEngineOsc osc; CarlaEngineOsc osc;
CarlaEngineThread thread; CarlaEngineThread thread;


const CarlaOscData* oscData;
ScopedPointer<const CarlaOscData> oscData;


CallbackFunc callback; CallbackFunc callback;
void* callbackPtr; void* callbackPtr;


+ 3
- 0
source/backend/engine/carla_engine_osc.hpp View File

@@ -19,6 +19,7 @@
#define __CARLA_ENGINE_OSC_HPP__ #define __CARLA_ENGINE_OSC_HPP__


#include "carla_backend.hpp" #include "carla_backend.hpp"
#include "carla_juce_utils.hpp"
#include "carla_osc_utils.hpp" #include "carla_osc_utils.hpp"


#define CARLA_ENGINE_OSC_HANDLE_ARGS1 CarlaPlugin* const plugin #define CARLA_ENGINE_OSC_HANDLE_ARGS1 CarlaPlugin* const plugin
@@ -162,6 +163,8 @@ private:
return _this_->handleMessage(path, argc, argv, types, msg); return _this_->handleMessage(path, argc, argv, types, msg);
return 1; return 1;
} }

CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineOsc)
}; };


CARLA_BACKEND_END_NAMESPACE CARLA_BACKEND_END_NAMESPACE


+ 3
- 1
source/backend/engine/carla_engine_thread.hpp View File

@@ -19,7 +19,7 @@
#define __CARLA_ENGINE_THREAD_HPP__ #define __CARLA_ENGINE_THREAD_HPP__


#include "carla_backend.hpp" #include "carla_backend.hpp"
#include "carla_utils.hpp"
#include "carla_juce_utils.hpp"


#include <QtCore/QThread> #include <QtCore/QThread>


@@ -72,6 +72,8 @@ private:
CarlaMutex* const mutex; CarlaMutex* const mutex;
}; };
#endif #endif

CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineThread)
}; };


CARLA_BACKEND_END_NAMESPACE CARLA_BACKEND_END_NAMESPACE


+ 37
- 16
source/backend/engine/jack.cpp View File

@@ -25,6 +25,10 @@


CARLA_BACKEND_START_NAMESPACE CARLA_BACKEND_START_NAMESPACE


#if 0
} // Fix editor indentation
#endif

// ------------------------------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------------------------------
// Engine port (JackAudio) // Engine port (JackAudio)


@@ -76,6 +80,8 @@ public:
private: private:
jack_client_t* const m_client; jack_client_t* const m_client;
jack_port_t* const m_port; jack_port_t* const m_port;

CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineJackAudioPort)
}; };


// ------------------------------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------------------------------
@@ -173,22 +179,22 @@ public:
{ {
const uint8_t midiBank = jackEvent.buffer[2]; const uint8_t midiBank = jackEvent.buffer[2];


m_retEvent.type = CarlaEngineMidiBankChangeEvent;
m_retEvent.type = CarlaEngineControlEventTypeMidiBankChange;
m_retEvent.value = midiBank; m_retEvent.value = midiBank;
} }
else if (midiControl == MIDI_CONTROL_ALL_SOUND_OFF) else if (midiControl == MIDI_CONTROL_ALL_SOUND_OFF)
{ {
m_retEvent.type = CarlaEngineAllSoundOffEvent;
m_retEvent.type = CarlaEngineControlEventTypeAllSoundOff;
} }
else if (midiControl == MIDI_CONTROL_ALL_NOTES_OFF) else if (midiControl == MIDI_CONTROL_ALL_NOTES_OFF)
{ {
m_retEvent.type = CarlaEngineAllNotesOffEvent;
m_retEvent.type = CarlaEngineControlEventTypeAllNotesOff;
} }
else else
{ {
const uint8_t midiValue = jackEvent.buffer[2]; const uint8_t midiValue = jackEvent.buffer[2];


m_retEvent.type = CarlaEngineParameterChangeEvent;
m_retEvent.type = CarlaEngineControlEventTypeParameterChange;
m_retEvent.parameter = midiControl; m_retEvent.parameter = midiControl;
m_retEvent.value = double(midiValue)/127; m_retEvent.value = double(midiValue)/127;
} }
@@ -200,7 +206,7 @@ public:
{ {
const uint8_t midiProgram = jackEvent.buffer[1]; const uint8_t midiProgram = jackEvent.buffer[1];


m_retEvent.type = CarlaEngineMidiProgramChangeEvent;
m_retEvent.type = CarlaEngineControlEventTypeMidiProgramChange;
m_retEvent.value = midiProgram; m_retEvent.value = midiProgram;


return &m_retEvent; return &m_retEvent;
@@ -218,14 +224,14 @@ public:
return; return;


CARLA_ASSERT(buffer); CARLA_ASSERT(buffer);
CARLA_ASSERT(type != CarlaEngineNullEvent);
CARLA_ASSERT(type != CarlaEngineControlEventTypeNull);
CARLA_ASSERT(channel < 16); CARLA_ASSERT(channel < 16);


if (! buffer) if (! buffer)
return; return;
if (type == CarlaEngineNullEvent)
if (type == CarlaEngineControlEventTypeNull)
return; return;
if (type == CarlaEngineParameterChangeEvent)
if (type == CarlaEngineControlEventTypeParameterChange)
CARLA_ASSERT(! MIDI_IS_CONTROL_BANK_SELECT(parameter)); CARLA_ASSERT(! MIDI_IS_CONTROL_BANK_SELECT(parameter));
if (channel >= 16) if (channel >= 16)
return; return;
@@ -235,31 +241,31 @@ public:


switch (type) switch (type)
{ {
case CarlaEngineNullEvent:
case CarlaEngineControlEventTypeNull:
break; break;
case CarlaEngineParameterChangeEvent:
case CarlaEngineControlEventTypeParameterChange:
data[0] = MIDI_STATUS_CONTROL_CHANGE + channel; data[0] = MIDI_STATUS_CONTROL_CHANGE + channel;
data[1] = parameter; data[1] = parameter;
data[2] = value * 127; data[2] = value * 127;
size = 3; size = 3;
break; break;
case CarlaEngineMidiBankChangeEvent:
case CarlaEngineControlEventTypeMidiBankChange:
data[0] = MIDI_STATUS_CONTROL_CHANGE + channel; data[0] = MIDI_STATUS_CONTROL_CHANGE + channel;
data[1] = MIDI_CONTROL_BANK_SELECT; data[1] = MIDI_CONTROL_BANK_SELECT;
data[2] = value; data[2] = value;
size = 3; size = 3;
break; break;
case CarlaEngineMidiProgramChangeEvent:
case CarlaEngineControlEventTypeMidiProgramChange:
data[0] = MIDI_STATUS_PROGRAM_CHANGE + channel; data[0] = MIDI_STATUS_PROGRAM_CHANGE + channel;
data[1] = value; data[1] = value;
size = 2; size = 2;
break; break;
case CarlaEngineAllSoundOffEvent:
case CarlaEngineControlEventTypeAllSoundOff:
data[0] = MIDI_STATUS_CONTROL_CHANGE + channel; data[0] = MIDI_STATUS_CONTROL_CHANGE + channel;
data[1] = MIDI_CONTROL_ALL_SOUND_OFF; data[1] = MIDI_CONTROL_ALL_SOUND_OFF;
size = 2; size = 2;
break; break;
case CarlaEngineAllNotesOffEvent:
case CarlaEngineControlEventTypeAllNotesOff:
data[0] = MIDI_STATUS_CONTROL_CHANGE + channel; data[0] = MIDI_STATUS_CONTROL_CHANGE + channel;
data[1] = MIDI_CONTROL_ALL_NOTES_OFF; data[1] = MIDI_CONTROL_ALL_NOTES_OFF;
size = 2; size = 2;
@@ -275,6 +281,8 @@ private:
jack_port_t* const m_port; jack_port_t* const m_port;


CarlaEngineControlEvent m_retEvent; CarlaEngineControlEvent m_retEvent;

CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineJackControlPort)
}; };


// ------------------------------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------------------------------
@@ -385,6 +393,8 @@ private:
jack_port_t* const m_port; jack_port_t* const m_port;


CarlaEngineMidiEvent m_retEvent; CarlaEngineMidiEvent m_retEvent;

CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineJackMidiPort)
}; };


// ------------------------------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------------------------------
@@ -504,6 +514,8 @@ public:
private: private:
jack_client_t* const m_client; jack_client_t* const m_client;
const bool m_usesClient; const bool m_usesClient;

CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineJackClient)
}; };


// ------------------------------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------------------------------
@@ -567,6 +579,7 @@ public:
{ {
qDebug("CarlaEngineJack::init(\"%s\")", clientName); qDebug("CarlaEngineJack::init(\"%s\")", clientName);


#if 0
m_state = JackTransportStopped; m_state = JackTransportStopped;
m_freewheel = false; m_freewheel = false;


@@ -637,6 +650,8 @@ public:
CarlaEngine::init(name); CarlaEngine::init(name);
return true; return true;
#endif #endif
#endif
return false;
} }


bool close() bool close()
@@ -644,6 +659,7 @@ public:
qDebug("CarlaEngineJack::close()"); qDebug("CarlaEngineJack::close()");
CarlaEngine::close(); CarlaEngine::close();


#if 0
#ifdef BUILD_BRIDGE #ifdef BUILD_BRIDGE
hasQuit = true; hasQuit = true;
m_client = nullptr; m_client = nullptr;
@@ -675,6 +691,7 @@ public:
setLastError("Failed to deactivate the JACK client"); setLastError("Failed to deactivate the JACK client");


m_client = nullptr; m_client = nullptr;
#endif
#endif #endif
return false; return false;
} }
@@ -702,6 +719,7 @@ public:
{ {
jack_client_t* client = nullptr; jack_client_t* client = nullptr;


#if 0
#ifdef BUILD_BRIDGE #ifdef BUILD_BRIDGE
client = m_client = jackbridge_client_open(plugin->name(), JackNullOption, nullptr); client = m_client = jackbridge_client_open(plugin->name(), JackNullOption, nullptr);


@@ -726,11 +744,12 @@ public:
jackbridge_set_latency_callback(client, carla_jack_latency_callback_plugin, plugin); jackbridge_set_latency_callback(client, carla_jack_latency_callback_plugin, plugin);
} }
#endif #endif
#endif


#ifdef BUILD_BRIDGE #ifdef BUILD_BRIDGE
return new CarlaEngineJackClient(client, CarlaEngineTypeJack, PROCESS_MODE_MULTIPLE_CLIENTS);
return new CarlaEngineJackClient(CarlaEngineTypeJack, PROCESS_MODE_MULTIPLE_CLIENTS, client);
#else #else
return new CarlaEngineJackClient(client, CarlaEngineTypeJack, options.processMode);
return new CarlaEngineJackClient(CarlaEngineTypeJack, options.processMode, client);
#endif #endif
} }


@@ -1190,6 +1209,8 @@ private:
latencyPlugin(plugin, mode); latencyPlugin(plugin, mode);
} }
#endif #endif

CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineJack)
}; };


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


+ 7
- 0
source/backend/engine/rtaudio.cpp View File

@@ -26,6 +26,10 @@


CARLA_BACKEND_START_NAMESPACE CARLA_BACKEND_START_NAMESPACE


#if 0
} // Fix editor indentation
#endif

// ------------------------------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------------------------------
// RtAudio Engine client // RtAudio Engine client


@@ -60,6 +64,9 @@ public:
qCritical("CarlaEngineRtAudioClient::addPort(%i, \"%s\", %s) - invalid type", portType, name, bool2str(isInput)); qCritical("CarlaEngineRtAudioClient::addPort(%i, \"%s\", %s) - invalid type", portType, name, bool2str(isInput));
return nullptr; return nullptr;
} }

private:
CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineRtAudioClient)
}; };


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


+ 6
- 2
source/discovery/carla-discovery.cpp View File

@@ -9,13 +9,14 @@
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* For a full copy of the GNU General Public License see the COPYING file * For a full copy of the GNU General Public License see the COPYING file
*/ */


#include "carla_backend.hpp" #include "carla_backend.hpp"
#include "carla_juce_utils.hpp"
#include "carla_lib_utils.hpp" #include "carla_lib_utils.hpp"
#include "carla_midi.h" #include "carla_midi.h"


@@ -1242,7 +1243,8 @@ void do_linuxsampler_check(const char* const filename, const char* const stype,


using namespace LinuxSampler; using namespace LinuxSampler;


class LinuxSamplerScopedEngine {
class LinuxSamplerScopedEngine
{
public: public:
LinuxSamplerScopedEngine(const char* const filename, const char* const stype) LinuxSamplerScopedEngine(const char* const filename, const char* const stype)
{ {
@@ -1325,6 +1327,8 @@ void do_linuxsampler_check(const char* const filename, const char* const stype,
private: private:
Engine* engine; Engine* engine;
InstrumentManager* ins; InstrumentManager* ins;

CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(LinuxSamplerScopedEngine)
}; };


if (init) if (init)


+ 1
- 0
source/discovery/carla-discovery.pro View File

@@ -28,6 +28,7 @@ HEADERS = \
../includes/lv2_rdf.hpp \ ../includes/lv2_rdf.hpp \
../backend/carla_backend.hpp \ ../backend/carla_backend.hpp \
../utils/carla_utils.hpp \ ../utils/carla_utils.hpp \
../utils/carla_juce_utils.hpp \
../utils/carla_lib_utils.hpp \ ../utils/carla_lib_utils.hpp \
../utils/carla_ladspa_utils.hpp \ ../utils/carla_ladspa_utils.hpp \
../utils/carla_lv2_utils.hpp \ ../utils/carla_lv2_utils.hpp \


+ 1
- 1
source/includes/carla_midi.h View File

@@ -9,7 +9,7 @@
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* For a full copy of the GNU General Public License see the COPYING file * For a full copy of the GNU General Public License see the COPYING file


+ 1
- 1
source/includes/ladspa_rdf.hpp View File

@@ -9,7 +9,7 @@
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* For a full copy of the GNU General Public License see the COPYING file * For a full copy of the GNU General Public License see the COPYING file


+ 1
- 1
source/includes/lv2_rdf.hpp View File

@@ -9,7 +9,7 @@
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* For a full copy of the GNU General Public License see the COPYING file * For a full copy of the GNU General Public License see the COPYING file


+ 1
- 0
source/includes/pugl View File

@@ -0,0 +1 @@
../libs/pugl/

+ 1
- 1
source/libs/distrho-plugin-toolkit/DistrhoUtils.h View File

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


#include "src/DistrhoDefines.h"
#include "src/DistrhoMacros.h"


#if DISTRHO_OS_WINDOWS #if DISTRHO_OS_WINDOWS
# include <windows.h> # include <windows.h>


+ 4
- 44
source/libs/distrho-plugin-toolkit/src/DistrhoDefines.h View File

@@ -9,48 +9,14 @@
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* For a full copy of the license see the GPL.txt file * For a full copy of the license see the GPL.txt file
*/ */


#ifndef __DISTRHO_DEFINES_H__
#define __DISTRHO_DEFINES_H__

#include "DistrhoPluginInfo.h"

#ifndef DISTRHO_PLUGIN_NAME
# error DISTRHO_PLUGIN_NAME undefined!
#endif

#ifndef DISTRHO_PLUGIN_HAS_UI
# error DISTRHO_PLUGIN_HAS_UI undefined!
#endif

#ifndef DISTRHO_PLUGIN_IS_SYNTH
# error DISTRHO_PLUGIN_IS_SYNTH undefined!
#endif

#ifndef DISTRHO_PLUGIN_NUM_INPUTS
# error DISTRHO_PLUGIN_NUM_INPUTS undefined!
#endif

#ifndef DISTRHO_PLUGIN_NUM_OUTPUTS
# error DISTRHO_PLUGIN_NUM_OUTPUTS undefined!
#endif

#ifndef DISTRHO_PLUGIN_WANT_LATENCY
# error DISTRHO_PLUGIN_WANT_LATENCY undefined!
#endif

#ifndef DISTRHO_PLUGIN_WANT_PROGRAMS
# error DISTRHO_PLUGIN_WANT_PROGRAMS undefined!
#endif

#ifndef DISTRHO_PLUGIN_WANT_STATE
# error DISTRHO_PLUGIN_WANT_STATE undefined!
#endif
#ifndef __DISTRHO_DEFINES_HPP__
#define __DISTRHO_DEFINES_HPP__


#if defined(__WIN32__) || defined(__WIN64__) #if defined(__WIN32__) || defined(__WIN64__)
# define DISTRHO_PLUGIN_EXPORT extern "C" __declspec (dllexport) # define DISTRHO_PLUGIN_EXPORT extern "C" __declspec (dllexport)
@@ -87,10 +53,4 @@
# define USE_NAMESPACE_DISTRHO # define USE_NAMESPACE_DISTRHO
#endif #endif


#ifndef DISTRHO_UI_QT4
# define DISTRHO_UI_OPENGL
#endif

#define DISTRHO_UI_URI DISTRHO_PLUGIN_URI "#UI"

#endif // __DISTRHO_DEFINES_H__
#endif // __DISTRHO_DEFINES_HPP__

+ 62
- 0
source/libs/distrho-plugin-toolkit/src/DistrhoMacros.h View File

@@ -0,0 +1,62 @@
/*
* DISTRHO Plugin Toolkit (DPT)
* Copyright (C) 2012-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 license see the GPL.txt file
*/

#ifndef __DISTRHO_MACROS_HPP__
#define __DISTRHO_MACROS_HPP__

#include "DistrhoDefines.h"
#include "DistrhoPluginInfo.h"

#ifndef DISTRHO_PLUGIN_NAME
# error DISTRHO_PLUGIN_NAME undefined!
#endif

#ifndef DISTRHO_PLUGIN_HAS_UI
# error DISTRHO_PLUGIN_HAS_UI undefined!
#endif

#ifndef DISTRHO_PLUGIN_IS_SYNTH
# error DISTRHO_PLUGIN_IS_SYNTH undefined!
#endif

#ifndef DISTRHO_PLUGIN_NUM_INPUTS
# error DISTRHO_PLUGIN_NUM_INPUTS undefined!
#endif

#ifndef DISTRHO_PLUGIN_NUM_OUTPUTS
# error DISTRHO_PLUGIN_NUM_OUTPUTS undefined!
#endif

#ifndef DISTRHO_PLUGIN_WANT_LATENCY
# error DISTRHO_PLUGIN_WANT_LATENCY undefined!
#endif

#ifndef DISTRHO_PLUGIN_WANT_PROGRAMS
# error DISTRHO_PLUGIN_WANT_PROGRAMS undefined!
#endif

#ifndef DISTRHO_PLUGIN_WANT_STATE
# error DISTRHO_PLUGIN_WANT_STATE undefined!
#endif

#ifndef DISTRHO_UI_QT4
# define DISTRHO_UI_OPENGL
#endif

#define DISTRHO_UI_URI DISTRHO_PLUGIN_URI "#UI"

#endif // __DISTRHO_MACROS_HPP__

+ 1
- 1
source/libs/distrho-plugin-toolkit/src/DistrhoPluginInternal.h View File

@@ -213,7 +213,7 @@ public:
const ParameterRanges& parameterRanges(uint32_t index) const const ParameterRanges& parameterRanges(uint32_t index) const
{ {
assert(data && index < data->parameterCount); assert(data && index < data->parameterCount);
return (data && index < data->parameterCount) ? &data->parameters[index].ranges : fallbackRanges;
return (data && index < data->parameterCount) ? data->parameters[index].ranges : fallbackRanges;
} }


float parameterValue(uint32_t index) float parameterValue(uint32_t index)


+ 1
- 0
source/libs/distrho-plugin-toolkit/src/pugl View File

@@ -0,0 +1 @@
../../pugl/

+ 30
- 0
source/libs/distrho-plugin-toolkit/src/pugl.cpp View File

@@ -0,0 +1,30 @@
/*
* DISTRHO Plugin Toolkit (DPT)
* Copyright (C) 2012-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 license see the GPL.txt file
*/

#include "DistrhoDefines.h"

#if DISTRHO_OS_WINDOWS
# include "pugl/pugl_win.cpp"
#elif DISTRHO_OS_MAC
# include "pugl/pugl_osx.m"
#elif DISTRHO_OS_LINUX
extern "C" {
# include "pugl/pugl_x11.c"
}
#else
# error Unsupported platform!
#endif

+ 358
- 0
source/utils/carla_juce_utils.hpp View File

@@ -0,0 +1,358 @@
/*
* Carla misc utils imported from Juce source code
* Copyright (C) 2013 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2004-11 Raw Material Software Ltd.
*
* 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 COPYING file
*/

#ifndef __CARLA_JUCE_UTILS_HPP__
#define __CARLA_JUCE_UTILS_HPP__

#include "carla_defines.hpp"

#include <cassert>

#define CARLA_DECLARE_NON_COPYABLE(className) \
className (const className&);\
className& operator= (const className&);

/** This is a shorthand way of writing both a CARLA_DECLARE_NON_COPYABLE and
CARLA_LEAK_DETECTOR macro for a class.
*/
#define CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(className) \
CARLA_DECLARE_NON_COPYABLE(className) \
CARLA_LEAK_DETECTOR(className)

/** This macro can be added to class definitions to disable the use of new/delete to
allocate the object on the heap, forcing it to only be used as a stack or member variable.
*/
#define CARLA_PREVENT_HEAP_ALLOCATION \
private: \
static void* operator new (size_t); \
static void operator delete (void*);

/** A good old-fashioned C macro concatenation helper.
This combines two items (which may themselves be macros) into a single string,
avoiding the pitfalls of the ## macro operator.
*/
#define CARLA_JOIN_MACRO_HELPER(a, b) a ## b
#define CARLA_JOIN_MACRO(item1, item2) CARLA_JOIN_MACRO_HELPER (item1, item2)


//==============================================================================
/**
Embedding an instance of this class inside another class can be used as a low-overhead
way of detecting leaked instances.

This class keeps an internal static count of the number of instances that are
active, so that when the app is shutdown and the static destructors are called,
it can check whether there are any left-over instances that may have been leaked.

To use it, use the CARLA_LEAK_DETECTOR macro as a simple way to put one in your
class declaration. Have a look through the juce codebase for examples, it's used
in most of the classes.
*/
template <class OwnerClass>
class LeakedObjectDetector
{
public:
//==============================================================================
LeakedObjectDetector()
{
++(getCounter().numObjects);
}

LeakedObjectDetector(const LeakedObjectDetector&)
{
++(getCounter().numObjects);
}

~LeakedObjectDetector()
{
if (--(getCounter().numObjects) < 0)
{
qWarning("*** Dangling pointer deletion! Class: '%s'", getLeakedObjectClassName());

/** If you hit this, then you've managed to delete more instances of this class than you've
created.. That indicates that you're deleting some dangling pointers.

Note that although this assertion will have been triggered during a destructor, it might
not be this particular deletion that's at fault - the incorrect one may have happened
at an earlier point in the program, and simply not been detected until now.

Most errors like this are caused by using old-fashioned, non-RAII techniques for
your object management. Tut, tut. Always, always use ScopedPointers, OwnedArrays,
ReferenceCountedObjects, etc, and avoid the 'delete' operator at all costs!
*/
assert(false);
}
}

private:
//==============================================================================
class LeakCounter
{
public:
LeakCounter()
{
numObjects = 0;
}

~LeakCounter()
{
if (numObjects > 0)
{
qWarning("*** Leaked objects detected: %i instance(s) of class '%s'", numObjects, getLeakedObjectClassName());

/** If you hit this, then you've leaked one or more objects of the type specified by
the 'OwnerClass' template parameter - the name should have been printed by the line above.

If you're leaking, it's probably because you're using old-fashioned, non-RAII techniques for
your object management. Tut, tut. Always, always use ScopedPointers, OwnedArrays,
ReferenceCountedObjects, etc, and avoid the 'delete' operator at all costs!
*/
assert(false);
}
}

int numObjects;
};

static const char* getLeakedObjectClassName()
{
return OwnerClass::getLeakedObjectClassName();
}

static LeakCounter& getCounter()
{
static LeakCounter counter;
return counter;
}
};

#define CARLA_LEAK_DETECTOR(OwnerClass) \
friend class LeakedObjectDetector<OwnerClass>; \
static const char* getLeakedObjectClassName() { return #OwnerClass; } \
LeakedObjectDetector<OwnerClass> CARLA_JOIN_MACRO (leakDetector, __LINE__);


//==============================================================================
/**
This class holds a pointer which is automatically deleted when this object goes
out of scope.

Once a pointer has been passed to a ScopedPointer, it will make sure that the pointer
gets deleted when the ScopedPointer is deleted. Using the ScopedPointer on the stack or
as member variables is a good way to use RAII to avoid accidentally leaking dynamically
created objects.

A ScopedPointer can be used in pretty much the same way that you'd use a normal pointer
to an object. If you use the assignment operator to assign a different object to a
ScopedPointer, the old one will be automatically deleted.

Important note: The class is designed to hold a pointer to an object, NOT to an array!
It calls delete on its payload, not delete[], so do not give it an array to hold! For
that kind of purpose, you should be using HeapBlock or Array instead.

A const ScopedPointer is guaranteed not to lose ownership of its object or change the
object to which it points during its lifetime. This means that making a copy of a const
ScopedPointer is impossible, as that would involve the new copy taking ownership from the
old one.

If you need to get a pointer out of a ScopedPointer without it being deleted, you
can use the release() method.

Something to note is the main difference between this class and the std::auto_ptr class,
which is that ScopedPointer provides a cast-to-object operator, wheras std::auto_ptr
requires that you always call get() to retrieve the pointer. The advantages of providing
the cast is that you don't need to call get(), so can use the ScopedPointer in pretty much
exactly the same way as a raw pointer. The disadvantage is that the compiler is free to
use the cast in unexpected and sometimes dangerous ways - in particular, it becomes difficult
to return a ScopedPointer as the result of a function. To avoid this causing errors,
ScopedPointer contains an overloaded constructor that should cause a syntax error in these
circumstances, but it does mean that instead of returning a ScopedPointer from a function,
you'd need to return a raw pointer (or use a std::auto_ptr instead).
*/
template <class ObjectType>
class ScopedPointer
{
public:
//==============================================================================
/** Creates a ScopedPointer containing a null pointer. */
ScopedPointer()
: object(nullptr)
{
}

/** Creates a ScopedPointer that owns the specified object. */
ScopedPointer(ObjectType* const objectToTakePossessionOf)
: object(objectToTakePossessionOf)
{
}

/** Creates a ScopedPointer that takes its pointer from another ScopedPointer.

Because a pointer can only belong to one ScopedPointer, this transfers
the pointer from the other object to this one, and the other object is reset to
be a null pointer.
*/
ScopedPointer(ScopedPointer& objectToTransferFrom)
: object(objectToTransferFrom.object)
{
objectToTransferFrom.object = nullptr;
}

/** Destructor.
This will delete the object that this ScopedPointer currently refers to.
*/
~ScopedPointer()
{
delete object;
}

/** Changes this ScopedPointer to point to a new object.

Because a pointer can only belong to one ScopedPointer, this transfers
the pointer from the other object to this one, and the other object is reset to
be a null pointer.

If this ScopedPointer already points to an object, that object
will first be deleted.
*/
ScopedPointer& operator=(ScopedPointer& objectToTransferFrom)
{
if (this != objectToTransferFrom.getAddress())
{
// Two ScopedPointers should never be able to refer to the same object - if
// this happens, you must have done something dodgy!
assert(object == nullptr || object != objectToTransferFrom.object);

ObjectType* const oldObject = object;
object = objectToTransferFrom.object;
objectToTransferFrom.object = nullptr;
delete oldObject;
}

return *this;
}

/** Changes this ScopedPointer to point to a new object.

If this ScopedPointer already points to an object, that object
will first be deleted.

The pointer that you pass in may be a nullptr.
*/
ScopedPointer& operator=(ObjectType* const newObjectToTakePossessionOf)
{
if (object != newObjectToTakePossessionOf)
{
ObjectType* const oldObject = object;
object = newObjectToTakePossessionOf;
delete oldObject;
}

return *this;
}

//==============================================================================
/** Returns the object that this ScopedPointer refers to. */
operator ObjectType*() const { return object; }

/** Returns the object that this ScopedPointer refers to. */
ObjectType* get() const { return object; }

/** Returns the object that this ScopedPointer refers to. */
ObjectType& operator*() const { return *object; }

/** Lets you access methods and properties of the object that this ScopedPointer refers to. */
ObjectType* operator->() const { return object; }

//==============================================================================
/** Removes the current object from this ScopedPointer without deleting it.
This will return the current object, and set the ScopedPointer to a null pointer.
*/
ObjectType* release()
{
ObjectType* const o = object;
object = nullptr;
return o;
}

//==============================================================================
/** Swaps this object with that of another ScopedPointer.
The two objects simply exchange their pointers.
*/
void swapWith(ScopedPointer<ObjectType>& other)
{
// Two ScopedPointers should never be able to refer to the same object - if
// this happens, you must have done something dodgy!
assert(object != other.object || this == other.getAddress());

std::swap(object, other.object);
}

private:
//==============================================================================
ObjectType* object;

// (Required as an alternative to the overloaded & operator).
const ScopedPointer* getAddress() const
{
return this;
}

#if ! defined(Q_CC_MSVC) // (MSVC can't deal with multiple copy constructors)
/* These are private to stop people accidentally copying a const ScopedPointer (the compiler
would let you do so by implicitly casting the source to its raw object pointer).

A side effect of this is that you may hit a puzzling compiler error when you write something
like this:

ScopedPointer<MyClass> m = new MyClass(); // Compile error: copy constructor is private.

Even though the compiler would normally ignore the assignment here, it can't do so when the
copy constructor is private. It's very easy to fix though - just write it like this:

ScopedPointer<MyClass> m (new MyClass()); // Compiles OK

It's good practice to always use the latter form when writing your object declarations anyway,
rather than writing them as assignments and assuming (or hoping) that the compiler will be
smart enough to replace your construction + assignment with a single constructor.
*/
ScopedPointer(const ScopedPointer&);
ScopedPointer& operator=(const ScopedPointer&);
#endif
};

//==============================================================================
/** Compares a ScopedPointer with another pointer.
This can be handy for checking whether this is a null pointer.
*/
template <class ObjectType>
bool operator==(const ScopedPointer<ObjectType>& pointer1, ObjectType* const pointer2) noexcept
{
return static_cast<ObjectType*>(pointer1) == pointer2;
}

/** Compares a ScopedPointer with another pointer.
This can be handy for checking whether this is a null pointer.
*/
template <class ObjectType>
bool operator!=(const ScopedPointer<ObjectType>& pointer1, ObjectType* const pointer2) noexcept
{
return static_cast<ObjectType*>(pointer1) != pointer2;
}

#endif // __CARLA_JUCE_UTILS_HPP__

+ 3
- 1
source/utils/carla_lv2_utils.hpp View File

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


#include "carla_utils.hpp"
#include "carla_juce_utils.hpp"


#include "lv2/lv2.h" #include "lv2/lv2.h"
#include "lv2/atom.h" #include "lv2/atom.h"
@@ -375,6 +375,8 @@ public:


private: private:
bool needInit; bool needInit;

CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(Lv2WorldClass)
}; };


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


+ 110
- 34
source/utils/carla_utils.hpp View File

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


#include "carla_defines.hpp"
#include "carla_juce_utils.hpp"


#include <cstdio> #include <cstdio>
#include <cstdlib> #include <cstdlib>
@@ -164,6 +164,24 @@ void carla_zeroFloat(float* data, const unsigned size)
carla_fill<float>(data, size, 0.0f); carla_fill<float>(data, size, 0.0f);
} }


// -------------------------------------------------
// memory functions

static inline
void carla_zeroMem(void* const memory, const size_t numBytes)
{
CARLA_ASSERT(memory);

memset(memory, 0, numBytes);
}

template <typename T>
static inline
void carla_zeroStruct(T& structure)
{
memset(&structure, 0, sizeof(T));
}

// ------------------------------------------------- // -------------------------------------------------
// other misc functions // other misc functions


@@ -241,6 +259,9 @@ public:


private: private:
CarlaMutex* const mutex; CarlaMutex* const mutex;

CARLA_PREVENT_HEAP_ALLOCATION
CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ScopedLocker)
}; };


private: private:
@@ -249,11 +270,16 @@ private:
#else #else
pthread_mutex_t pmutex; pthread_mutex_t pmutex;
#endif #endif

CARLA_PREVENT_HEAP_ALLOCATION
CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaMutex)
}; };


// ------------------------------------------------- // -------------------------------------------------
// CarlaString class // CarlaString class


// TODO - use "size_t bufferLen"

class CarlaString class CarlaString
{ {
public: public:
@@ -263,16 +289,35 @@ public:
explicit CarlaString() explicit CarlaString()
{ {
buffer = ::strdup(""); buffer = ::strdup("");
bufferLen = 0;
} }


explicit CarlaString(char* const strBuf) explicit CarlaString(char* const strBuf)
{ {
buffer = ::strdup(strBuf ? strBuf : "");
if (strBuf)
{
buffer = ::strdup(strBuf);
bufferLen = ::strlen(buffer);
}
else
{
buffer = ::strdup("");
bufferLen = 0;
}
} }


explicit CarlaString(const char* const strBuf) explicit CarlaString(const char* const strBuf)
{ {
buffer = ::strdup(strBuf ? strBuf : "");
if (strBuf)
{
buffer = ::strdup(strBuf);
bufferLen = ::strlen(buffer);
}
else
{
buffer = ::strdup("");
bufferLen = 0;
}
} }


explicit CarlaString(const int value) explicit CarlaString(const int value)
@@ -282,6 +327,7 @@ public:
::snprintf(strBuf, strBufSize, "%d", value); ::snprintf(strBuf, strBufSize, "%d", value);


buffer = ::strdup(strBuf); buffer = ::strdup(strBuf);
bufferLen = ::strlen(buffer);
} }


explicit CarlaString(const unsigned int value, const bool hexadecimal = false) explicit CarlaString(const unsigned int value, const bool hexadecimal = false)
@@ -291,6 +337,7 @@ public:
::snprintf(strBuf, strBufSize, hexadecimal ? "%u" : "0x%x", value); ::snprintf(strBuf, strBufSize, hexadecimal ? "%u" : "0x%x", value);


buffer = ::strdup(strBuf); buffer = ::strdup(strBuf);
bufferLen = ::strlen(buffer);
} }


explicit CarlaString(const long int value) explicit CarlaString(const long int value)
@@ -300,6 +347,7 @@ public:
::snprintf(strBuf, strBufSize, "%ld", value); ::snprintf(strBuf, strBufSize, "%ld", value);


buffer = ::strdup(strBuf); buffer = ::strdup(strBuf);
bufferLen = ::strlen(buffer);
} }


explicit CarlaString(const unsigned long int value, const bool hexadecimal = false) explicit CarlaString(const unsigned long int value, const bool hexadecimal = false)
@@ -309,6 +357,7 @@ public:
::snprintf(strBuf, strBufSize, hexadecimal ? "%lu" : "0x%lx", value); ::snprintf(strBuf, strBufSize, hexadecimal ? "%lu" : "0x%lx", value);


buffer = ::strdup(strBuf); buffer = ::strdup(strBuf);
bufferLen = ::strlen(buffer);
} }


explicit CarlaString(const float value) explicit CarlaString(const float value)
@@ -317,6 +366,7 @@ public:
::snprintf(strBuf, 0xff, "%f", value); ::snprintf(strBuf, 0xff, "%f", value);


buffer = ::strdup(strBuf); buffer = ::strdup(strBuf);
bufferLen = ::strlen(buffer);
} }


explicit CarlaString(const double value) explicit CarlaString(const double value)
@@ -325,6 +375,7 @@ public:
::snprintf(strBuf, 0xff, "%g", value); ::snprintf(strBuf, 0xff, "%g", value);


buffer = ::strdup(strBuf); buffer = ::strdup(strBuf);
bufferLen = ::strlen(buffer);
} }


// --------------------------------------------- // ---------------------------------------------
@@ -333,6 +384,7 @@ public:
CarlaString(const CarlaString& str) CarlaString(const CarlaString& str)
{ {
buffer = ::strdup(str.buffer); buffer = ::strdup(str.buffer);
bufferLen = ::strlen(buffer);
} }


// --------------------------------------------- // ---------------------------------------------
@@ -349,53 +401,53 @@ public:


size_t length() const size_t length() const
{ {
return ::strlen(buffer);
return bufferLen;
} }


bool isEmpty() const bool isEmpty() const
{ {
return (*buffer == 0);
return (bufferLen == 0);
} }


bool isNotEmpty() const bool isNotEmpty() const
{ {
return (*buffer != 0);
return (bufferLen != 0);
} }


#ifdef __USE_GNU
bool contains(const char* const strBuf, const bool ignoreCase = false) const
#else
bool contains(const char* const strBuf) const bool contains(const char* const strBuf) const
#endif
{ {
if (! strBuf) if (! strBuf)
return false; return false;
if (*strBuf == 0)
if (bufferLen == 0)
return false; return false;


// FIXME - use strstr

size_t thisLen = ::strlen(buffer);
size_t thatLen = ::strlen(strBuf)-1;

for (size_t i=0, j=0; i < thisLen; i++)
{
if (buffer[i] == strBuf[j])
j++;
else
j = 0;

if (j == thatLen)
return true;
}

return false;
#ifdef __USE_GNU
if (ignoreCase)
return (::strcasestr(buffer, strBuf) != nullptr);
else
#endif
return (::strstr(buffer, strBuf) != nullptr);
} }


#ifdef __USE_GNU
bool contains(const CarlaString& str, const bool ignoreCase = false) const
{
return contains(str.buffer, ignoreCase);
}
#else
bool contains(const CarlaString& str) const bool contains(const CarlaString& str) const
{ {
return contains(str.buffer); return contains(str.buffer);
} }
#endif


bool isDigit(const size_t pos) const bool isDigit(const size_t pos) const
{ {
if (pos >= length())
if (pos >= bufferLen)
return false; return false;


return (buffer[pos] >= '0' && buffer[pos] <= '9'); return (buffer[pos] >= '0' && buffer[pos] <= '9');
@@ -408,22 +460,27 @@ public:


void replace(const char before, const char after) void replace(const char before, const char after)
{ {
for (size_t i=0, len = ::strlen(buffer); i < len; i++)
if (after == 0)
return;

for (size_t i=0; i < bufferLen; i++)
{ {
if (buffer[i] == before) if (buffer[i] == before)
buffer[i] = after; buffer[i] = after;
else if (buffer[i] == 0)
break;
} }
} }


void truncate(const unsigned int n)
void truncate(const size_t n)
{ {
for (size_t i=n, len = ::strlen(buffer); i < len; i++)
for (size_t i=n; i < bufferLen; i++)
buffer[i] = 0; buffer[i] = 0;
} }


void toBasic() void toBasic()
{ {
for (size_t i=0, len = ::strlen(buffer); i < len; i++)
for (size_t i=0; i < bufferLen; i++)
{ {
if (buffer[i] >= '0' && buffer[i] <= '9') if (buffer[i] >= '0' && buffer[i] <= '9')
continue; continue;
@@ -440,7 +497,7 @@ public:


void toLower() void toLower()
{ {
for (size_t i=0, len = ::strlen(buffer); i < len; 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] += 32; buffer[i] += 32;
@@ -449,7 +506,7 @@ public:


void toUpper() void toUpper()
{ {
for (size_t i=0, len = ::strlen(buffer); i < len; 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] -= 32; buffer[i] -= 32;
@@ -464,7 +521,7 @@ public:
return buffer; return buffer;
} }


char& operator[](const unsigned int pos)
char& operator[](const size_t pos)
{ {
return buffer[pos]; return buffer[pos];
} }
@@ -493,7 +550,16 @@ public:
{ {
::free(buffer); ::free(buffer);


buffer = ::strdup(strBuf ? strBuf : "");
if (strBuf)
{
buffer = ::strdup(strBuf);
bufferLen = ::strlen(buffer);
}
else
{
buffer = ::strdup("");
bufferLen = 0;
}


return *this; return *this;
} }
@@ -513,6 +579,7 @@ public:
::free(buffer); ::free(buffer);


buffer = ::strdup(newBuf); buffer = ::strdup(newBuf);
bufferLen = ::strlen(buffer);


return *this; return *this;
} }
@@ -541,7 +608,16 @@ public:
// --------------------------------------------- // ---------------------------------------------


private: private:
char* buffer;
char* buffer;
size_t bufferLen;

void _recalcLen()
{
bufferLen = ::strlen(buffer);
}

CARLA_LEAK_DETECTOR(CarlaString)
CARLA_PREVENT_HEAP_ALLOCATION
}; };


static inline static inline


+ 4
- 6
source/utils/lv2_atom_queue.hpp View File

@@ -22,13 +22,11 @@
#include "lv2/atom.h" #include "lv2/atom.h"


#include <cstring> // memcpy, memset #include <cstring> // memcpy, memset
#include <pthread.h>


class Lv2AtomQueue class Lv2AtomQueue
{ {
public: public:
Lv2AtomQueue() Lv2AtomQueue()
: mutex(PTHREAD_MUTEX_INITIALIZER)
{ {
index = indexPool = 0; index = indexPool = 0;
empty = true; empty = true;
@@ -77,17 +75,17 @@ public:


bool lock() bool lock()
{ {
return (pthread_mutex_lock(&mutex) == 0);
return mutex.lock();
} }


bool tryLock() bool tryLock()
{ {
return (pthread_mutex_trylock(&mutex) == 0);
return mutex.tryLock();
} }


bool unlock() bool unlock()
{ {
return (pthread_mutex_unlock(&mutex) == 0);
return mutex.unlock();
} }


void put(const uint32_t portIndex, const LV2_Atom* const atom) void put(const uint32_t portIndex, const LV2_Atom* const atom)
@@ -186,7 +184,7 @@ private:
unsigned short index, indexPool; unsigned short index, indexPool;
bool empty, full; bool empty, full;


pthread_mutex_t mutex;
CarlaMutex mutex;
}; };


#endif // __LV2_ATOM_QUEUE_HPP__ #endif // __LV2_ATOM_QUEUE_HPP__

+ 23
- 18
source/utils/rt_list.hpp View File

@@ -24,6 +24,7 @@ extern "C" {
} }


#include <cassert> #include <cassert>
#include <cstring>


typedef struct list_head k_list_head; typedef struct list_head k_list_head;


@@ -34,9 +35,9 @@ public:
RtList(const size_t minPreallocated, const size_t maxPreallocated) RtList(const size_t minPreallocated, const size_t maxPreallocated)
{ {
qcount = 0; qcount = 0;
INIT_LIST_HEAD(&queue);
::INIT_LIST_HEAD(&queue);


rtsafe_memory_pool_create(&mempool, nullptr, sizeof(RtListData), minPreallocated, maxPreallocated);
::rtsafe_memory_pool_create(&mempool, nullptr, sizeof(RtListData), minPreallocated, maxPreallocated);


assert(mempool); assert(mempool);
} }
@@ -45,15 +46,15 @@ public:
{ {
clear(); clear();


rtsafe_memory_pool_destroy(mempool);
::rtsafe_memory_pool_destroy(mempool);
} }


void resize(const size_t minPreallocated, const size_t maxPreallocated) void resize(const size_t minPreallocated, const size_t maxPreallocated)
{ {
clear(); clear();


rtsafe_memory_pool_destroy(mempool);
rtsafe_memory_pool_create(&mempool, nullptr, sizeof(RtListData), minPreallocated, maxPreallocated);
::rtsafe_memory_pool_destroy(mempool);
::rtsafe_memory_pool_create(&mempool, nullptr, sizeof(RtListData), minPreallocated, maxPreallocated);


assert(mempool); assert(mempool);
} }
@@ -68,12 +69,12 @@ public:
list_for_each(entry, &queue) list_for_each(entry, &queue)
{ {
data = list_entry(entry, RtListData, siblings); data = list_entry(entry, RtListData, siblings);
rtsafe_memory_pool_deallocate(mempool, data);
::rtsafe_memory_pool_deallocate(mempool, data);
} }
} }


qcount = 0; qcount = 0;
INIT_LIST_HEAD(&queue);
::INIT_LIST_HEAD(&queue);
} }


size_t count() const size_t count() const
@@ -92,14 +93,14 @@ public:
RtListData* data; RtListData* data;


if (sleepy) if (sleepy)
data = (RtListData*)rtsafe_memory_pool_allocate_sleepy(mempool);
data = (RtListData*)::rtsafe_memory_pool_allocate_sleepy(mempool);
else else
data = (RtListData*)rtsafe_memory_pool_allocate_atomic(mempool);
data = (RtListData*)::rtsafe_memory_pool_allocate_atomic(mempool);


if (data) if (data)
{ {
memcpy(&data->value, &value, sizeof(T));
list_add_tail(&data->siblings, &queue);
::memcpy(&data->value, &value, sizeof(T));
::list_add_tail(&data->siblings, &queue);


qcount++; qcount++;
} }
@@ -137,8 +138,8 @@ public:
if (data->value == value) if (data->value == value)
{ {
qcount--; qcount--;
list_del(entry);
rtsafe_memory_pool_deallocate(mempool, data);
::list_del(entry);
::rtsafe_memory_pool_deallocate(mempool, data);
return true; return true;
} }
} }
@@ -159,8 +160,8 @@ public:
if (data->value == value) if (data->value == value)
{ {
qcount--; qcount--;
list_del(entry);
rtsafe_memory_pool_deallocate(mempool, data);
::list_del(entry);
::rtsafe_memory_pool_deallocate(mempool, data);
} }
} }
} }
@@ -186,7 +187,7 @@ private:
if (reset) if (reset)
{ {
reset = false; reset = false;
memset(&value, 0, sizeof(T));
::memset(&value, 0, sizeof(T));
} }


return value; return value;
@@ -200,8 +201,8 @@ private:
if (data && doDelete) if (data && doDelete)
{ {
qcount--; qcount--;
list_del(entry);
rtsafe_memory_pool_deallocate(mempool, data);
::list_del(entry);
::rtsafe_memory_pool_deallocate(mempool, data);
} }


return ret; return ret;
@@ -210,6 +211,10 @@ private:
// Non-copyable // Non-copyable
RtList(const RtList&); RtList(const RtList&);
RtList& operator= (const RtList&); RtList& operator= (const RtList&);

// Prevent heap allocation
static void* operator new (size_t);
static void operator delete (void*);
}; };


#endif // __RT_LIST_HPP__ #endif // __RT_LIST_HPP__

Loading…
Cancel
Save