@@ -55,8 +55,6 @@ BUILD_CXX_FLAGS += -DVESTIGE_HEADER | |||
# -------------------------------------------------------------- | |||
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) | |||
endif | |||
@@ -71,3 +69,14 @@ HAVE_PULSEAUDIO = $(shell pkg-config --exists libpulse-simple && echo true) | |||
endif | |||
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 |
@@ -19,7 +19,7 @@ | |||
#define __CARLA_ENGINE_HPP__ | |||
#include "carla_backend.hpp" | |||
#include "carla_utils.hpp" | |||
#include "carla_juce_utils.hpp" | |||
#ifndef BUILD_BRIDGE | |||
class QProcessEnvironment; | |||
@@ -27,6 +27,10 @@ class QProcessEnvironment; | |||
CARLA_BACKEND_START_NAMESPACE | |||
#if 0 | |||
} // Fix editor indentation | |||
#endif | |||
/*! | |||
* @defgroup CarlaBackendEngine Carla Backend Engine | |||
* | |||
@@ -45,19 +49,17 @@ enum CarlaEngineType { | |||
/*! | |||
* JACK engine type.\n | |||
* Provides single, multi-client, and rack processing modes. | |||
* Provides all processing modes. | |||
*/ | |||
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, | |||
/*! | |||
* 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 | |||
}; | |||
@@ -89,39 +91,39 @@ enum CarlaEnginePortType { | |||
}; | |||
/*! | |||
* The type of a control event. | |||
* The type of an engine control event. | |||
*/ | |||
enum CarlaEngineControlEventType { | |||
/*! | |||
* Null event type. | |||
* Null control event type. | |||
*/ | |||
CarlaEngineNullEvent = 0, | |||
CarlaEngineControlEventTypeNull = 0, | |||
/*! | |||
* Parameter change event.\n | |||
* \note Value uses a range of 0.0<->1.0. | |||
*/ | |||
CarlaEngineParameterChangeEvent = 1, | |||
CarlaEngineControlEventTypeParameterChange = 1, | |||
/*! | |||
* MIDI Bank change event. | |||
*/ | |||
CarlaEngineMidiBankChangeEvent = 2, | |||
CarlaEngineControlEventTypeMidiBankChange = 2, | |||
/*! | |||
* MIDI Program change event. | |||
*/ | |||
CarlaEngineMidiProgramChangeEvent = 3, | |||
CarlaEngineControlEventTypeMidiProgramChange = 3, | |||
/*! | |||
* All sound off event. | |||
*/ | |||
CarlaEngineAllSoundOffEvent = 4, | |||
CarlaEngineControlEventTypeAllSoundOff = 4, | |||
/*! | |||
* All notes off event. | |||
*/ | |||
CarlaEngineAllNotesOffEvent = 5 | |||
CarlaEngineControlEventTypeAllNotesOff = 5 | |||
}; | |||
/*! | |||
@@ -132,18 +134,16 @@ struct CarlaEngineControlEvent { | |||
uint32_t time; //!< frame offset | |||
uint8_t channel; //!< channel, used for MIDI-related events and ports | |||
uint16_t parameter; //!< parameter, used for parameter changes only | |||
double value; //!< value | |||
double value; | |||
CarlaEngineControlEvent() | |||
: type(CarlaEngineNullEvent), | |||
time(0), | |||
channel(0), | |||
parameter(0), | |||
value(0.0) {} | |||
{ | |||
clear(); | |||
} | |||
void clear() | |||
{ | |||
type = CarlaEngineNullEvent; | |||
type = CarlaEngineControlEventTypeNull; | |||
time = 0; | |||
channel = 0; | |||
parameter = 0; | |||
@@ -160,9 +160,9 @@ struct CarlaEngineMidiEvent { | |||
uint8_t data[3]; | |||
CarlaEngineMidiEvent() | |||
: time(0), | |||
size(0), | |||
data{0} {} | |||
{ | |||
clear(); | |||
} | |||
void clear() | |||
{ | |||
@@ -172,8 +172,6 @@ struct CarlaEngineMidiEvent { | |||
} | |||
}; | |||
// LATER - CarlaEngineExtendedMidiEvent | |||
/*! | |||
* Engine options. | |||
*/ | |||
@@ -221,9 +219,9 @@ struct CarlaEngineOptions { | |||
forceStereo(false), | |||
preferPluginBridges(false), | |||
preferUiBridges(true), | |||
#ifdef WANT_DSSI | |||
#ifdef WANT_DSSI | |||
useDssiVstChunks(false), | |||
#endif | |||
#endif | |||
maxParameters(MAX_DEFAULT_PARAMETERS), | |||
oscUiTimeout(4000), | |||
preferredBufferSize(512), | |||
@@ -287,7 +285,7 @@ public: | |||
/*! | |||
* The contructor.\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); | |||
@@ -310,6 +308,9 @@ protected: | |||
const bool isInput; | |||
const ProcessMode processMode; | |||
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. | |||
*/ | |||
virtual void initBuffer(CarlaEngine* const engine); | |||
private: | |||
CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineAudioPort) | |||
}; | |||
// ----------------------------------------------------------------------- | |||
@@ -398,6 +402,8 @@ public: | |||
private: | |||
const uint32_t m_maxEventCount; | |||
CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineControlPort) | |||
}; | |||
// ----------------------------------------------------------------------- | |||
@@ -453,6 +459,8 @@ public: | |||
private: | |||
const uint32_t m_maxEventCount; | |||
CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineMidiPort) | |||
}; | |||
// ----------------------------------------------------------------------- | |||
@@ -525,6 +533,8 @@ protected: | |||
private: | |||
bool m_active; | |||
uint32_t m_latency; | |||
CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineClient) | |||
}; | |||
// ----------------------------------------------------------------------- | |||
@@ -1007,10 +1017,13 @@ private: | |||
static const char* getRtAudioApiName(unsigned int index); | |||
#endif | |||
CarlaEnginePrivateData* const data; | |||
ScopedPointer<CarlaEnginePrivateData> const data; | |||
friend class CarlaEngineControlPort; | |||
friend class CarlaEngineMidiPort; | |||
private: | |||
CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngine) | |||
}; | |||
// ----------------------------------------------------------------------- | |||
@@ -1,6 +1,6 @@ | |||
/* | |||
* 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 | |||
* 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, | |||
* 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. | |||
* | |||
* 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 | |||
# include <cstddef> | |||
# include <cstdint> | |||
extern "C" { | |||
#else | |||
# include <stdbool.h> | |||
# include <stddef.h> | |||
# include <stdint.h> | |||
#endif | |||
#include <stddef.h> | |||
#include <stdint.h> | |||
/*! | |||
* @defgroup CarlaNativeAPI Carla Native API | |||
* | |||
@@ -38,9 +39,10 @@ extern "C" { | |||
typedef void* HostHandle; | |||
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_ENABLED = 1 << 1; | |||
@@ -106,14 +108,17 @@ typedef struct _MidiProgram { | |||
typedef struct _TimeInfoBBT { | |||
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; | |||
typedef struct _TimeInfo { | |||
@@ -129,12 +134,13 @@ typedef struct _HostDescriptor { | |||
uint32_t (*get_buffer_size)(HostHandle handle); | |||
double (*get_sample_rate)(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_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_closed)(HostHandle handle); | |||
} HostDescriptor; | |||
typedef struct _PluginDescriptor { | |||
@@ -152,6 +158,7 @@ typedef struct _PluginDescriptor { | |||
const char* const copyright; | |||
PluginHandle (*instantiate)(const struct _PluginDescriptor* _this_, HostDescriptor* host); | |||
void (*cleanup)(PluginHandle handle); | |||
uint32_t (*get_parameter_count)(PluginHandle handle); | |||
const Parameter* (*get_parameter_info)(PluginHandle handle, uint32_t index); | |||
@@ -174,7 +181,6 @@ typedef struct _PluginDescriptor { | |||
void (*activate)(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); | |||
} PluginDescriptor; | |||
@@ -206,4 +212,4 @@ void carla_register_native_plugin_zynaddsubfx(); | |||
} // extern "C" | |||
#endif | |||
#endif // CARLA_NATIVE_H | |||
#endif // __CARLA_NATIVE_H__ |
@@ -135,7 +135,7 @@ uint32_t CarlaEngineControlPort::getEventCount() | |||
for (unsigned short i=0; i < m_maxEventCount; i++, count++) | |||
{ | |||
if (events[i].type == CarlaEngineNullEvent) | |||
if (events[i].type == CarlaEngineControlEventTypeNull) | |||
break; | |||
} | |||
@@ -179,14 +179,14 @@ void CarlaEngineControlPort::writeEvent(const CarlaEngineControlEventType type, | |||
return; | |||
CARLA_ASSERT(buffer); | |||
CARLA_ASSERT(type != CarlaEngineNullEvent); | |||
CARLA_ASSERT(type != CarlaEngineControlEventTypeNull); | |||
CARLA_ASSERT(channel < 16); | |||
if (! buffer) | |||
return; | |||
if (type == CarlaEngineNullEvent) | |||
if (type == CarlaEngineControlEventTypeNull) | |||
return; | |||
if (type == CarlaEngineParameterChangeEvent) | |||
if (type == CarlaEngineControlEventTypeParameterChange) | |||
CARLA_ASSERT(! MIDI_IS_CONTROL_BANK_SELECT(parameter)); | |||
if (channel >= 16) | |||
return; | |||
@@ -198,7 +198,7 @@ void CarlaEngineControlPort::writeEvent(const CarlaEngineControlEventType type, | |||
for (unsigned short i=0; i < m_maxEventCount; i++) | |||
{ | |||
if (events[i].type != CarlaEngineNullEvent) | |||
if (events[i].type != CarlaEngineControlEventTypeNull) | |||
continue; | |||
events[i].type = type; | |||
@@ -49,7 +49,8 @@ HEADERS += \ | |||
HEADERS += \ | |||
../../utils/carla_utils.hpp \ | |||
../../utils/carla_backend_utils.hpp | |||
../../utils/carla_backend_utils.hpp \ | |||
../../utils/carla_juce_utils.hpp | |||
# HEADERS += \ | |||
# plugin/DistrhoPluginInfo.h | |||
@@ -77,18 +77,18 @@ const char* CarlaEngineControlEventType2Str(const CarlaEngineControlEventType ty | |||
{ | |||
switch (type) | |||
{ | |||
case CarlaEngineNullEvent: | |||
case CarlaEngineControlEventTypeNull: | |||
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); | |||
@@ -141,7 +141,7 @@ struct CarlaEnginePrivateData { | |||
CarlaEngineOsc osc; | |||
CarlaEngineThread thread; | |||
const CarlaOscData* oscData; | |||
ScopedPointer<const CarlaOscData> oscData; | |||
CallbackFunc callback; | |||
void* callbackPtr; | |||
@@ -19,6 +19,7 @@ | |||
#define __CARLA_ENGINE_OSC_HPP__ | |||
#include "carla_backend.hpp" | |||
#include "carla_juce_utils.hpp" | |||
#include "carla_osc_utils.hpp" | |||
#define CARLA_ENGINE_OSC_HANDLE_ARGS1 CarlaPlugin* const plugin | |||
@@ -162,6 +163,8 @@ private: | |||
return _this_->handleMessage(path, argc, argv, types, msg); | |||
return 1; | |||
} | |||
CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineOsc) | |||
}; | |||
CARLA_BACKEND_END_NAMESPACE | |||
@@ -19,7 +19,7 @@ | |||
#define __CARLA_ENGINE_THREAD_HPP__ | |||
#include "carla_backend.hpp" | |||
#include "carla_utils.hpp" | |||
#include "carla_juce_utils.hpp" | |||
#include <QtCore/QThread> | |||
@@ -72,6 +72,8 @@ private: | |||
CarlaMutex* const mutex; | |||
}; | |||
#endif | |||
CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineThread) | |||
}; | |||
CARLA_BACKEND_END_NAMESPACE | |||
@@ -25,6 +25,10 @@ | |||
CARLA_BACKEND_START_NAMESPACE | |||
#if 0 | |||
} // Fix editor indentation | |||
#endif | |||
// ------------------------------------------------------------------------------------------------------------------- | |||
// Engine port (JackAudio) | |||
@@ -76,6 +80,8 @@ public: | |||
private: | |||
jack_client_t* const m_client; | |||
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]; | |||
m_retEvent.type = CarlaEngineMidiBankChangeEvent; | |||
m_retEvent.type = CarlaEngineControlEventTypeMidiBankChange; | |||
m_retEvent.value = midiBank; | |||
} | |||
else if (midiControl == MIDI_CONTROL_ALL_SOUND_OFF) | |||
{ | |||
m_retEvent.type = CarlaEngineAllSoundOffEvent; | |||
m_retEvent.type = CarlaEngineControlEventTypeAllSoundOff; | |||
} | |||
else if (midiControl == MIDI_CONTROL_ALL_NOTES_OFF) | |||
{ | |||
m_retEvent.type = CarlaEngineAllNotesOffEvent; | |||
m_retEvent.type = CarlaEngineControlEventTypeAllNotesOff; | |||
} | |||
else | |||
{ | |||
const uint8_t midiValue = jackEvent.buffer[2]; | |||
m_retEvent.type = CarlaEngineParameterChangeEvent; | |||
m_retEvent.type = CarlaEngineControlEventTypeParameterChange; | |||
m_retEvent.parameter = midiControl; | |||
m_retEvent.value = double(midiValue)/127; | |||
} | |||
@@ -200,7 +206,7 @@ public: | |||
{ | |||
const uint8_t midiProgram = jackEvent.buffer[1]; | |||
m_retEvent.type = CarlaEngineMidiProgramChangeEvent; | |||
m_retEvent.type = CarlaEngineControlEventTypeMidiProgramChange; | |||
m_retEvent.value = midiProgram; | |||
return &m_retEvent; | |||
@@ -218,14 +224,14 @@ public: | |||
return; | |||
CARLA_ASSERT(buffer); | |||
CARLA_ASSERT(type != CarlaEngineNullEvent); | |||
CARLA_ASSERT(type != CarlaEngineControlEventTypeNull); | |||
CARLA_ASSERT(channel < 16); | |||
if (! buffer) | |||
return; | |||
if (type == CarlaEngineNullEvent) | |||
if (type == CarlaEngineControlEventTypeNull) | |||
return; | |||
if (type == CarlaEngineParameterChangeEvent) | |||
if (type == CarlaEngineControlEventTypeParameterChange) | |||
CARLA_ASSERT(! MIDI_IS_CONTROL_BANK_SELECT(parameter)); | |||
if (channel >= 16) | |||
return; | |||
@@ -235,31 +241,31 @@ public: | |||
switch (type) | |||
{ | |||
case CarlaEngineNullEvent: | |||
case CarlaEngineControlEventTypeNull: | |||
break; | |||
case CarlaEngineParameterChangeEvent: | |||
case CarlaEngineControlEventTypeParameterChange: | |||
data[0] = MIDI_STATUS_CONTROL_CHANGE + channel; | |||
data[1] = parameter; | |||
data[2] = value * 127; | |||
size = 3; | |||
break; | |||
case CarlaEngineMidiBankChangeEvent: | |||
case CarlaEngineControlEventTypeMidiBankChange: | |||
data[0] = MIDI_STATUS_CONTROL_CHANGE + channel; | |||
data[1] = MIDI_CONTROL_BANK_SELECT; | |||
data[2] = value; | |||
size = 3; | |||
break; | |||
case CarlaEngineMidiProgramChangeEvent: | |||
case CarlaEngineControlEventTypeMidiProgramChange: | |||
data[0] = MIDI_STATUS_PROGRAM_CHANGE + channel; | |||
data[1] = value; | |||
size = 2; | |||
break; | |||
case CarlaEngineAllSoundOffEvent: | |||
case CarlaEngineControlEventTypeAllSoundOff: | |||
data[0] = MIDI_STATUS_CONTROL_CHANGE + channel; | |||
data[1] = MIDI_CONTROL_ALL_SOUND_OFF; | |||
size = 2; | |||
break; | |||
case CarlaEngineAllNotesOffEvent: | |||
case CarlaEngineControlEventTypeAllNotesOff: | |||
data[0] = MIDI_STATUS_CONTROL_CHANGE + channel; | |||
data[1] = MIDI_CONTROL_ALL_NOTES_OFF; | |||
size = 2; | |||
@@ -275,6 +281,8 @@ private: | |||
jack_port_t* const m_port; | |||
CarlaEngineControlEvent m_retEvent; | |||
CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineJackControlPort) | |||
}; | |||
// ------------------------------------------------------------------------------------------------------------------- | |||
@@ -385,6 +393,8 @@ private: | |||
jack_port_t* const m_port; | |||
CarlaEngineMidiEvent m_retEvent; | |||
CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineJackMidiPort) | |||
}; | |||
// ------------------------------------------------------------------------------------------------------------------- | |||
@@ -504,6 +514,8 @@ public: | |||
private: | |||
jack_client_t* const m_client; | |||
const bool m_usesClient; | |||
CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineJackClient) | |||
}; | |||
// ------------------------------------------------------------------------------------------------------------------- | |||
@@ -567,6 +579,7 @@ public: | |||
{ | |||
qDebug("CarlaEngineJack::init(\"%s\")", clientName); | |||
#if 0 | |||
m_state = JackTransportStopped; | |||
m_freewheel = false; | |||
@@ -637,6 +650,8 @@ public: | |||
CarlaEngine::init(name); | |||
return true; | |||
#endif | |||
#endif | |||
return false; | |||
} | |||
bool close() | |||
@@ -644,6 +659,7 @@ public: | |||
qDebug("CarlaEngineJack::close()"); | |||
CarlaEngine::close(); | |||
#if 0 | |||
#ifdef BUILD_BRIDGE | |||
hasQuit = true; | |||
m_client = nullptr; | |||
@@ -675,6 +691,7 @@ public: | |||
setLastError("Failed to deactivate the JACK client"); | |||
m_client = nullptr; | |||
#endif | |||
#endif | |||
return false; | |||
} | |||
@@ -702,6 +719,7 @@ public: | |||
{ | |||
jack_client_t* client = nullptr; | |||
#if 0 | |||
#ifdef BUILD_BRIDGE | |||
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); | |||
} | |||
#endif | |||
#endif | |||
#ifdef BUILD_BRIDGE | |||
return new CarlaEngineJackClient(client, CarlaEngineTypeJack, PROCESS_MODE_MULTIPLE_CLIENTS); | |||
return new CarlaEngineJackClient(CarlaEngineTypeJack, PROCESS_MODE_MULTIPLE_CLIENTS, client); | |||
#else | |||
return new CarlaEngineJackClient(client, CarlaEngineTypeJack, options.processMode); | |||
return new CarlaEngineJackClient(CarlaEngineTypeJack, options.processMode, client); | |||
#endif | |||
} | |||
@@ -1190,6 +1209,8 @@ private: | |||
latencyPlugin(plugin, mode); | |||
} | |||
#endif | |||
CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineJack) | |||
}; | |||
// ----------------------------------------- | |||
@@ -26,6 +26,10 @@ | |||
CARLA_BACKEND_START_NAMESPACE | |||
#if 0 | |||
} // Fix editor indentation | |||
#endif | |||
// ------------------------------------------------------------------------------------------------------------------- | |||
// RtAudio Engine client | |||
@@ -60,6 +64,9 @@ public: | |||
qCritical("CarlaEngineRtAudioClient::addPort(%i, \"%s\", %s) - invalid type", portType, name, bool2str(isInput)); | |||
return nullptr; | |||
} | |||
private: | |||
CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaEngineRtAudioClient) | |||
}; | |||
// ------------------------------------------------------------------------------------------------------------------- | |||
@@ -9,13 +9,14 @@ | |||
* | |||
* 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 | |||
* 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 | |||
*/ | |||
#include "carla_backend.hpp" | |||
#include "carla_juce_utils.hpp" | |||
#include "carla_lib_utils.hpp" | |||
#include "carla_midi.h" | |||
@@ -1242,7 +1243,8 @@ void do_linuxsampler_check(const char* const filename, const char* const stype, | |||
using namespace LinuxSampler; | |||
class LinuxSamplerScopedEngine { | |||
class LinuxSamplerScopedEngine | |||
{ | |||
public: | |||
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: | |||
Engine* engine; | |||
InstrumentManager* ins; | |||
CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(LinuxSamplerScopedEngine) | |||
}; | |||
if (init) | |||
@@ -28,6 +28,7 @@ HEADERS = \ | |||
../includes/lv2_rdf.hpp \ | |||
../backend/carla_backend.hpp \ | |||
../utils/carla_utils.hpp \ | |||
../utils/carla_juce_utils.hpp \ | |||
../utils/carla_lib_utils.hpp \ | |||
../utils/carla_ladspa_utils.hpp \ | |||
../utils/carla_lv2_utils.hpp \ | |||
@@ -9,7 +9,7 @@ | |||
* | |||
* 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 | |||
* 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 | |||
@@ -9,7 +9,7 @@ | |||
* | |||
* 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 | |||
* 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 | |||
@@ -9,7 +9,7 @@ | |||
* | |||
* 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 | |||
* 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 | |||
@@ -0,0 +1 @@ | |||
../libs/pugl/ |
@@ -18,7 +18,7 @@ | |||
#ifndef __DISTRHO_UTILS_H__ | |||
#define __DISTRHO_UTILS_H__ | |||
#include "src/DistrhoDefines.h" | |||
#include "src/DistrhoMacros.h" | |||
#if DISTRHO_OS_WINDOWS | |||
# include <windows.h> | |||
@@ -9,48 +9,14 @@ | |||
* | |||
* 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 | |||
* 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_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__) | |||
# define DISTRHO_PLUGIN_EXPORT extern "C" __declspec (dllexport) | |||
@@ -87,10 +53,4 @@ | |||
# define USE_NAMESPACE_DISTRHO | |||
#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__ |
@@ -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__ |
@@ -213,7 +213,7 @@ public: | |||
const ParameterRanges& parameterRanges(uint32_t index) const | |||
{ | |||
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) | |||
@@ -0,0 +1 @@ | |||
../../pugl/ |
@@ -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 |
@@ -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__ |
@@ -18,7 +18,7 @@ | |||
#ifndef __CARLA_LV2_UTILS_HPP__ | |||
#define __CARLA_LV2_UTILS_HPP__ | |||
#include "carla_utils.hpp" | |||
#include "carla_juce_utils.hpp" | |||
#include "lv2/lv2.h" | |||
#include "lv2/atom.h" | |||
@@ -375,6 +375,8 @@ public: | |||
private: | |||
bool needInit; | |||
CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(Lv2WorldClass) | |||
}; | |||
// ----------------------------------------------------- | |||
@@ -18,7 +18,7 @@ | |||
#ifndef __CARLA_UTILS_HPP__ | |||
#define __CARLA_UTILS_HPP__ | |||
#include "carla_defines.hpp" | |||
#include "carla_juce_utils.hpp" | |||
#include <cstdio> | |||
#include <cstdlib> | |||
@@ -164,6 +164,24 @@ void carla_zeroFloat(float* data, const unsigned size) | |||
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 | |||
@@ -241,6 +259,9 @@ public: | |||
private: | |||
CarlaMutex* const mutex; | |||
CARLA_PREVENT_HEAP_ALLOCATION | |||
CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ScopedLocker) | |||
}; | |||
private: | |||
@@ -249,11 +270,16 @@ private: | |||
#else | |||
pthread_mutex_t pmutex; | |||
#endif | |||
CARLA_PREVENT_HEAP_ALLOCATION | |||
CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaMutex) | |||
}; | |||
// ------------------------------------------------- | |||
// CarlaString class | |||
// TODO - use "size_t bufferLen" | |||
class CarlaString | |||
{ | |||
public: | |||
@@ -263,16 +289,35 @@ public: | |||
explicit CarlaString() | |||
{ | |||
buffer = ::strdup(""); | |||
bufferLen = 0; | |||
} | |||
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) | |||
{ | |||
buffer = ::strdup(strBuf ? strBuf : ""); | |||
if (strBuf) | |||
{ | |||
buffer = ::strdup(strBuf); | |||
bufferLen = ::strlen(buffer); | |||
} | |||
else | |||
{ | |||
buffer = ::strdup(""); | |||
bufferLen = 0; | |||
} | |||
} | |||
explicit CarlaString(const int value) | |||
@@ -282,6 +327,7 @@ public: | |||
::snprintf(strBuf, strBufSize, "%d", value); | |||
buffer = ::strdup(strBuf); | |||
bufferLen = ::strlen(buffer); | |||
} | |||
explicit CarlaString(const unsigned int value, const bool hexadecimal = false) | |||
@@ -291,6 +337,7 @@ public: | |||
::snprintf(strBuf, strBufSize, hexadecimal ? "%u" : "0x%x", value); | |||
buffer = ::strdup(strBuf); | |||
bufferLen = ::strlen(buffer); | |||
} | |||
explicit CarlaString(const long int value) | |||
@@ -300,6 +347,7 @@ public: | |||
::snprintf(strBuf, strBufSize, "%ld", value); | |||
buffer = ::strdup(strBuf); | |||
bufferLen = ::strlen(buffer); | |||
} | |||
explicit CarlaString(const unsigned long int value, const bool hexadecimal = false) | |||
@@ -309,6 +357,7 @@ public: | |||
::snprintf(strBuf, strBufSize, hexadecimal ? "%lu" : "0x%lx", value); | |||
buffer = ::strdup(strBuf); | |||
bufferLen = ::strlen(buffer); | |||
} | |||
explicit CarlaString(const float value) | |||
@@ -317,6 +366,7 @@ public: | |||
::snprintf(strBuf, 0xff, "%f", value); | |||
buffer = ::strdup(strBuf); | |||
bufferLen = ::strlen(buffer); | |||
} | |||
explicit CarlaString(const double value) | |||
@@ -325,6 +375,7 @@ public: | |||
::snprintf(strBuf, 0xff, "%g", value); | |||
buffer = ::strdup(strBuf); | |||
bufferLen = ::strlen(buffer); | |||
} | |||
// --------------------------------------------- | |||
@@ -333,6 +384,7 @@ public: | |||
CarlaString(const CarlaString& str) | |||
{ | |||
buffer = ::strdup(str.buffer); | |||
bufferLen = ::strlen(buffer); | |||
} | |||
// --------------------------------------------- | |||
@@ -349,53 +401,53 @@ public: | |||
size_t length() const | |||
{ | |||
return ::strlen(buffer); | |||
return bufferLen; | |||
} | |||
bool isEmpty() const | |||
{ | |||
return (*buffer == 0); | |||
return (bufferLen == 0); | |||
} | |||
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 | |||
#endif | |||
{ | |||
if (! strBuf) | |||
return false; | |||
if (*strBuf == 0) | |||
if (bufferLen == 0) | |||
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 | |||
{ | |||
return contains(str.buffer); | |||
} | |||
#endif | |||
bool isDigit(const size_t pos) const | |||
{ | |||
if (pos >= length()) | |||
if (pos >= bufferLen) | |||
return false; | |||
return (buffer[pos] >= '0' && buffer[pos] <= '9'); | |||
@@ -408,22 +460,27 @@ public: | |||
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) | |||
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; | |||
} | |||
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') | |||
continue; | |||
@@ -440,7 +497,7 @@ public: | |||
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') | |||
buffer[i] += 32; | |||
@@ -449,7 +506,7 @@ public: | |||
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') | |||
buffer[i] -= 32; | |||
@@ -464,7 +521,7 @@ public: | |||
return buffer; | |||
} | |||
char& operator[](const unsigned int pos) | |||
char& operator[](const size_t pos) | |||
{ | |||
return buffer[pos]; | |||
} | |||
@@ -493,7 +550,16 @@ public: | |||
{ | |||
::free(buffer); | |||
buffer = ::strdup(strBuf ? strBuf : ""); | |||
if (strBuf) | |||
{ | |||
buffer = ::strdup(strBuf); | |||
bufferLen = ::strlen(buffer); | |||
} | |||
else | |||
{ | |||
buffer = ::strdup(""); | |||
bufferLen = 0; | |||
} | |||
return *this; | |||
} | |||
@@ -513,6 +579,7 @@ public: | |||
::free(buffer); | |||
buffer = ::strdup(newBuf); | |||
bufferLen = ::strlen(buffer); | |||
return *this; | |||
} | |||
@@ -541,7 +608,16 @@ public: | |||
// --------------------------------------------- | |||
private: | |||
char* buffer; | |||
char* buffer; | |||
size_t bufferLen; | |||
void _recalcLen() | |||
{ | |||
bufferLen = ::strlen(buffer); | |||
} | |||
CARLA_LEAK_DETECTOR(CarlaString) | |||
CARLA_PREVENT_HEAP_ALLOCATION | |||
}; | |||
static inline | |||
@@ -22,13 +22,11 @@ | |||
#include "lv2/atom.h" | |||
#include <cstring> // memcpy, memset | |||
#include <pthread.h> | |||
class Lv2AtomQueue | |||
{ | |||
public: | |||
Lv2AtomQueue() | |||
: mutex(PTHREAD_MUTEX_INITIALIZER) | |||
{ | |||
index = indexPool = 0; | |||
empty = true; | |||
@@ -77,17 +75,17 @@ public: | |||
bool lock() | |||
{ | |||
return (pthread_mutex_lock(&mutex) == 0); | |||
return mutex.lock(); | |||
} | |||
bool tryLock() | |||
{ | |||
return (pthread_mutex_trylock(&mutex) == 0); | |||
return mutex.tryLock(); | |||
} | |||
bool unlock() | |||
{ | |||
return (pthread_mutex_unlock(&mutex) == 0); | |||
return mutex.unlock(); | |||
} | |||
void put(const uint32_t portIndex, const LV2_Atom* const atom) | |||
@@ -186,7 +184,7 @@ private: | |||
unsigned short index, indexPool; | |||
bool empty, full; | |||
pthread_mutex_t mutex; | |||
CarlaMutex mutex; | |||
}; | |||
#endif // __LV2_ATOM_QUEUE_HPP__ |
@@ -24,6 +24,7 @@ extern "C" { | |||
} | |||
#include <cassert> | |||
#include <cstring> | |||
typedef struct list_head k_list_head; | |||
@@ -34,9 +35,9 @@ public: | |||
RtList(const size_t minPreallocated, const size_t maxPreallocated) | |||
{ | |||
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); | |||
} | |||
@@ -45,15 +46,15 @@ public: | |||
{ | |||
clear(); | |||
rtsafe_memory_pool_destroy(mempool); | |||
::rtsafe_memory_pool_destroy(mempool); | |||
} | |||
void resize(const size_t minPreallocated, const size_t maxPreallocated) | |||
{ | |||
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); | |||
} | |||
@@ -68,12 +69,12 @@ public: | |||
list_for_each(entry, &queue) | |||
{ | |||
data = list_entry(entry, RtListData, siblings); | |||
rtsafe_memory_pool_deallocate(mempool, data); | |||
::rtsafe_memory_pool_deallocate(mempool, data); | |||
} | |||
} | |||
qcount = 0; | |||
INIT_LIST_HEAD(&queue); | |||
::INIT_LIST_HEAD(&queue); | |||
} | |||
size_t count() const | |||
@@ -92,14 +93,14 @@ public: | |||
RtListData* data; | |||
if (sleepy) | |||
data = (RtListData*)rtsafe_memory_pool_allocate_sleepy(mempool); | |||
data = (RtListData*)::rtsafe_memory_pool_allocate_sleepy(mempool); | |||
else | |||
data = (RtListData*)rtsafe_memory_pool_allocate_atomic(mempool); | |||
data = (RtListData*)::rtsafe_memory_pool_allocate_atomic(mempool); | |||
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++; | |||
} | |||
@@ -137,8 +138,8 @@ public: | |||
if (data->value == value) | |||
{ | |||
qcount--; | |||
list_del(entry); | |||
rtsafe_memory_pool_deallocate(mempool, data); | |||
::list_del(entry); | |||
::rtsafe_memory_pool_deallocate(mempool, data); | |||
return true; | |||
} | |||
} | |||
@@ -159,8 +160,8 @@ public: | |||
if (data->value == value) | |||
{ | |||
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) | |||
{ | |||
reset = false; | |||
memset(&value, 0, sizeof(T)); | |||
::memset(&value, 0, sizeof(T)); | |||
} | |||
return value; | |||
@@ -200,8 +201,8 @@ private: | |||
if (data && doDelete) | |||
{ | |||
qcount--; | |||
list_del(entry); | |||
rtsafe_memory_pool_deallocate(mempool, data); | |||
::list_del(entry); | |||
::rtsafe_memory_pool_deallocate(mempool, data); | |||
} | |||
return ret; | |||
@@ -210,6 +211,10 @@ private: | |||
// Non-copyable | |||
RtList(const RtList&); | |||
RtList& operator= (const RtList&); | |||
// Prevent heap allocation | |||
static void* operator new (size_t); | |||
static void operator delete (void*); | |||
}; | |||
#endif // __RT_LIST_HPP__ |