| @@ -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__ | |||