Browse Source

Cleanup

tags/1.9.4
falkTX 11 years ago
parent
commit
d4a1437d0a
39 changed files with 185 additions and 4604 deletions
  1. +2
    -39
      Makefile
  2. +14
    -29
      source/Makefile.mk
  3. +13
    -11
      source/backend/CarlaEngine.hpp
  4. +36
    -167
      source/backend/CarlaStandalone.cpp
  5. +2
    -2
      source/backend/Makefile
  6. +3
    -3
      source/backend/Makefile.mk
  7. +36
    -48
      source/backend/engine/CarlaEngine.cpp
  8. +8
    -8
      source/backend/engine/CarlaEngineGraph.cpp
  9. +2
    -2
      source/backend/engine/CarlaEngineGraph.hpp
  10. +8
    -6
      source/backend/engine/CarlaEngineNative.cpp
  11. +0
    -4
      source/backend/engine/CarlaEngineRtAudio.cpp
  12. +5
    -3
      source/backend/engine/Makefile
  13. +1
    -1
      source/backend/plugin/AuPlugin.cpp
  14. +4
    -21
      source/backend/plugin/JucePlugin.cpp
  15. +1
    -1
      source/backend/plugin/Vst3Plugin.cpp
  16. +4
    -4
      source/backend/plugin/VstPlugin.cpp
  17. +4
    -3
      source/bridges/CarlaBridgePlugin.cpp
  18. +0
    -2
      source/bridges/CarlaBridgeUI-LV2.cpp
  19. +4
    -70
      source/bridges/Makefile
  20. +7
    -6
      source/discovery/Makefile
  21. +6
    -7
      source/modules/CarlaNative.h
  22. +1
    -1
      source/modules/juce_audio_devices/AppConfig.h
  23. +1
    -1
      source/modules/juce_core/AppConfig.h
  24. +2
    -2
      source/modules/juce_events.h
  25. +0
    -11
      source/modules/native-plugins/Makefile
  26. +0
    -14
      source/modules/native-plugins/_all.c
  27. +0
    -283
      source/modules/native-plugins/juce-patchbay.cpp
  28. +0
    -406
      source/modules/native-plugins/jucepluginhost/FilterGraph.cpp
  29. +0
    -120
      source/modules/native-plugins/jucepluginhost/FilterGraph.h
  30. +0
    -1127
      source/modules/native-plugins/jucepluginhost/GraphEditorPanel.cpp
  31. +0
    -154
      source/modules/native-plugins/jucepluginhost/GraphEditorPanel.h
  32. +0
    -408
      source/modules/native-plugins/jucepluginhost/MainHostWindow.cpp
  33. +0
    -103
      source/modules/native-plugins/jucepluginhost/MainHostWindow.h
  34. +0
    -893
      source/modules/native-plugins/jucepluginhost/juce_MidiKeyboardComponent.cpp
  35. +0
    -409
      source/modules/native-plugins/jucepluginhost/juce_MidiKeyboardComponent.h
  36. +2
    -2
      source/plugin/Makefile
  37. +19
    -100
      source/plugin/carla-native-lv2.cpp
  38. +0
    -1
      source/tests/CarlaUtils2.cpp
  39. +0
    -132
      source/utils/JuceInternalFilters.hpp

+ 2
- 39
Makefile View File

@@ -36,17 +36,13 @@ ALL_LIBS += source/backend/carla_engine.a
ALL_LIBS += source/backend/carla_engine_plugin.a
ALL_LIBS += source/backend/carla_plugin.a

ifeq ($(HAVE_AF_DEPS),true)
ALL_LIBS += source/modules/audio_decoder.a
endif

ALL_LIBS += source/modules/jackbridge.a

ALL_LIBS += source/modules/juce_audio_basics.a
ALL_LIBS += source/modules/juce_audio_formats.a
ALL_LIBS += source/modules/juce_core.a

ifeq ($(HAVE_JUCE_UI),true)
ifeq ($(MACOS_OR_WIN32),true)
ALL_LIBS += source/modules/juce_audio_devices.a
ALL_LIBS += source/modules/juce_audio_processors.a
ALL_LIBS += source/modules/juce_data_structures.a
@@ -458,14 +454,6 @@ ifeq ($(HAIKU),true)
USE_COLORS=false
endif

ifeq ($(MACOS),true)
USE_VST3=true
endif

ifeq ($(WIN32),true)
USE_VST3=true
endif

ifeq ($(USE_COLORS),true)
ANS_NO=\033[31m NO \033[0m
ANS_YES=\033[32m YES \033[0m
@@ -518,7 +506,7 @@ ifeq ($(CARLA_PLUGIN_SUPPORT),true)
@echo "DSSI: $(ANS_YES)"
@echo "LV2: $(ANS_YES)"
@echo "VST: $(ANS_YES)"
ifeq ($(USE_VST3),true)
ifeq ($(MACOS_OR_WIN32),true)
@echo "VST3: $(ANS_YES)"
else
@echo "VST3: $(ANS_NO) $(mZ)Windows and MacOS only$(mE)"
@@ -604,35 +592,10 @@ endif
@echo ""

@echo "$(tS)---> Internal plugins: $(tE)"
ifeq ($(HAVE_AF_DEPS),true)
ifeq ($(HAVE_FFMPEG),true)
@echo "AudioFile: $(ANS_YES) (with ffmpeg)"
else
@echo "AudioFile: $(ANS_YES) (without ffmpeg) $(mS)ffmpeg/libav missing$(mE)"
endif
else
@echo "AudioFile: $(ANS_NO) $(mS)libsndfile missing$(mE)"
endif
ifeq ($(HAVE_MF_DEPS),true)
@echo "MidiFile: $(ANS_YES)"
else
@echo "MidiFile: $(ANS_NO) $(mS)LibSMF missing$(mE)"
endif
ifeq ($(HAVE_PM_DEPS),true)
@echo "ProjectM: $(ANS_YES)"
else
@echo "ProjectM: $(ANS_NO) $(mS)ProjectM missing$(mE)"
endif
ifneq ($(WIN32),true)
@echo "Carla-Rack: $(ANS_YES)"
else
@echo "Carla-Rack: $(ANS_NO) $(mS)Not available for Windows$(mE)"
endif
@echo "DPF Stuff: $(ANS_YES)"
ifeq ($(HAVE_JUCE),true)
@echo "Juce Stuff: $(ANS_YES)"
else
@echo "Juce Stuff: $(ANS_NO) $(mS)Juce deps missing or unavailable$(mE)"
endif
ifeq ($(HAVE_ZYN_DEPS),true)
ifeq ($(HAVE_ZYN_UI_DEPS),true)


+ 14
- 29
source/Makefile.mk View File

@@ -144,9 +144,7 @@ endif
# --------------------------------------------------------------
# Check for optional libs (required by backend or bridges)

ifeq ($(MACOS_OR_WIN32),true)
HAVE_JUCE_UI = true
else
ifneq ($(MACOS_OR_WIN32),true)
HAVE_FFMPEG = $(shell pkg-config --exists libavcodec libavformat libavutil && echo true)
HAVE_GTK2 = $(shell pkg-config --exists gtk+-2.0 && echo true)
HAVE_GTK3 = $(shell pkg-config --exists gtk+-3.0 && echo true)
@@ -154,7 +152,6 @@ HAVE_QT4 = $(shell pkg-config --exists QtCore QtGui && echo true)
HAVE_QT5 = $(shell pkg-config --exists Qt5Core Qt5Gui Qt5Widgets && echo true)
ifeq ($(LINUX),true)
HAVE_ALSA = $(shell pkg-config --exists alsa && echo true)
HAVE_JUCE_UI = $(shell pkg-config --exists x11 xinerama xext xcursor freetype2 TODO && echo true)
HAVE_PULSEAUDIO = $(shell pkg-config --exists libpulse-simple && echo true)
HAVE_X11 = $(shell pkg-config --exists x11 && echo true)
endif
@@ -211,16 +208,12 @@ endif
# --------------------------------------------------------------
# Check for optional libs (required by internal plugins)

HAVE_ZYN_DEPS = $(shell pkg-config --exists fftw3 mxml zlib && echo true)
HAVE_ZYN_UI_DEPS = $(shell pkg-config --exists ntk_images ntk && echo true)
HAVE_ZYN_DEPS = $(shell pkg-config --exists fftw3 mxml zlib && echo true)
HAVE_ZYN_UI_DEPS = $(shell pkg-config --exists ntk_images ntk && echo true)

# --------------------------------------------------------------
# Set base defines

ifeq ($(HAVE_JUCE_UI),true)
BASE_FLAGS += -DHAVE_JUCE_UI
endif

ifeq ($(HAVE_X11),true)
BASE_FLAGS += -DHAVE_X11
endif
@@ -228,8 +221,8 @@ endif
# --------------------------------------------------------------
# Set libs stuff (part 1)

LIBLO_FLAGS = $(shell pkg-config --cflags liblo)
LIBLO_LIBS = $(shell pkg-config --libs liblo)
LIBLO_FLAGS = $(shell pkg-config --cflags liblo)
LIBLO_LIBS = $(shell pkg-config --libs liblo)

ifeq ($(HAVE_FLUIDSYNTH),true)
FLUIDSYNTH_FLAGS = $(shell pkg-config --cflags fluidsynth)
@@ -261,26 +254,18 @@ RTMEMPOOL_LIBS = -lpthread
endif

ifeq ($(LINUX),true)
JACKBRIDGE_LIBS = -ldl -lpthread -lrt
JUCE_CORE_LIBS = -ldl -lpthread -lrt
ifeq ($(HAVE_JUCE_UI),true)
JUCE_EVENTS_FLAGS = $(shell pkg-config --cflags x11)
JUCE_EVENTS_LIBS = $(shell pkg-config --libs x11)
JUCE_GRAPHICS_FLAGS = $(shell pkg-config --cflags x11 xinerama xext freetype2)
JUCE_GRAPHICS_LIBS = $(shell pkg-config --libs x11 xinerama xext freetype2)
JUCE_GUI_BASICS_FLAGS = $(shell pkg-config --cflags x11 xinerama xext xcursor)
JUCE_GUI_BASICS_LIBS = $(shell pkg-config --libs x11 xinerama xext xcursor)
endif
LILV_LIBS = -ldl -lm -lrt
JACKBRIDGE_LIBS = -ldl -lpthread -lrt
JUCE_CORE_LIBS = -ldl -lpthread -lrt
LILV_LIBS = -ldl -lm -lrt
ifeq ($(HAVE_ALSA),true)
RTAUDIO_FLAGS += $(shell pkg-config --cflags alsa) -D__LINUX_ALSA__
RTAUDIO_LIBS += $(shell pkg-config --libs alsa) -lpthread
RTMIDI_FLAGS += $(shell pkg-config --cflags alsa) -D__LINUX_ALSA__
RTMIDI_LIBS += $(shell pkg-config --libs alsa)
RTAUDIO_FLAGS += $(shell pkg-config --cflags alsa) -D__LINUX_ALSA__
RTAUDIO_LIBS += $(shell pkg-config --libs alsa) -lpthread
RTMIDI_FLAGS += $(shell pkg-config --cflags alsa) -D__LINUX_ALSA__
RTMIDI_LIBS += $(shell pkg-config --libs alsa)
endif
ifeq ($(HAVE_PULSEAUDIO),true)
RTAUDIO_FLAGS += $(shell pkg-config --cflags libpulse-simple) -D__LINUX_PULSE__
RTAUDIO_LIBS += $(shell pkg-config --libs libpulse-simple)
RTAUDIO_FLAGS += $(shell pkg-config --cflags libpulse-simple) -D__LINUX_PULSE__
RTAUDIO_LIBS += $(shell pkg-config --libs libpulse-simple)
endif
endif



+ 13
- 11
source/backend/CarlaEngine.hpp View File

@@ -1118,23 +1118,25 @@ public:
// JACK
static CarlaEngine* newJack();

#ifndef BUILD_BRIDGE
// RtAudio
static CarlaEngine* newRtAudio(const AudioApi api);
static uint getRtAudioApiCount();
static const char* getRtAudioApiName(const uint index);
static const char* const* getRtAudioApiDeviceNames(const uint index);
static const EngineDriverDeviceInfo* getRtAudioDeviceInfo(const uint index, const char* const deviceName);

#ifdef BUILD_BRIDGE
// Bridge
static CarlaEngine* newBridge(const char* const audioBaseName, const char* const controlBaseName, const char* const timeBaseName);
#else
# if defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN)
// Juce
static CarlaEngine* newJuce(const AudioApi api);
static uint getJuceApiCount();
static const char* getJuceApiName(const uint index);
static const char* const* getJuceApiDeviceNames(const uint index);
static const EngineDriverDeviceInfo* getJuceDeviceInfo(const uint index, const char* const deviceName);
#else
// Bridge
static CarlaEngine* newBridge(const char* const audioBaseName, const char* const controlBaseName, const char* const timeBaseName);
# else
// RtAudio
static CarlaEngine* newRtAudio(const AudioApi api);
static uint getRtAudioApiCount();
static const char* getRtAudioApiName(const uint index);
static const char* const* getRtAudioApiDeviceNames(const uint index);
static const EngineDriverDeviceInfo* getRtAudioDeviceInfo(const uint index, const char* const deviceName);
# endif
#endif

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


+ 36
- 167
source/backend/CarlaStandalone.cpp View File

@@ -27,90 +27,16 @@

#include "CarlaBackendUtils.hpp"
#include "CarlaOscUtils.hpp"
#include "CarlaThread.hpp"

#include "juce_audio_formats.h"

#ifdef BUILD_BRIDGE
# undef HAVE_JUCE_UI
#endif

#ifdef HAVE_JUCE_UI
#if defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN)
# include "juce_gui_basics.h"
using juce::initialiseJuce_GUI;
using juce::shutdownJuce_GUI;
using juce::MessageManager;
using juce::Thread;
#endif

namespace CB = CarlaBackend;
using CB::EngineOptions;

using juce::AudioFormat;
using juce::AudioFormatManager;
using juce::String;
using juce::StringArray;

// -------------------------------------------------------------------------------------------------------------------
// Juce Message Thread

#if defined(HAVE_JUCE_UI) && defined(CARLA_OS_LINUX)

class JuceMessageThread : public Thread
{
public:
JuceMessageThread()
: Thread("JuceMessageThread"),
fInitialised(false)
{
}

~JuceMessageThread() override
{
stop();
}

void start()
{
CARLA_SAFE_ASSERT_RETURN(! fInitialised,);

fInitialised = false;

startThread(7);

while (! fInitialised)
sleep(1);
}

void stop()
{
signalThreadShouldExit();
waitForThreadToExit(5000);
}

protected:
void run() override
{
MessageManager* const msgMgr(MessageManager::getInstance());
CARLA_SAFE_ASSERT_RETURN(msgMgr != nullptr,);

msgMgr->setCurrentThreadAsMessageThread();
fInitialised = true;

while ((! threadShouldExit()) && MessageManager::getInstance()->runDispatchLoopUntil(250))
{}

fInitialised = false;
}

private:
volatile bool fInitialised;

CARLA_DECLARE_NON_COPY_CLASS(JuceMessageThread)
};

#endif // defined(HAVE_JUCE_UI) && defined(CARLA_OS_LINUX)

// -------------------------------------------------------------------------------------------------------------------
// Single, standalone engine

@@ -125,10 +51,6 @@ struct CarlaBackendStandalone {

CarlaString lastError;

#if defined(HAVE_JUCE_UI) && defined(CARLA_OS_LINUX)
JuceMessageThread juceMsgThread;
#endif

CarlaBackendStandalone()
: engine(nullptr),
engineCallback(nullptr),
@@ -143,61 +65,16 @@ struct CarlaBackendStandalone {
engineOptions.preferPluginBridges = false;
engineOptions.preferUiBridges = false;
#else
if (std::getenv("LADISH_APP_NAME") != nullptr || std::getenv("NSM_URL") != nullptr)
return;

CarlaThread::setCurrentThreadName("Carla");
if (std::getenv("LADISH_APP_NAME") == nullptr && std::getenv("NSM_URL") == nullptr)
juce::Thread::setCurrentThreadName("Carla");
#endif
}

~CarlaBackendStandalone()
{
CARLA_SAFE_ASSERT(engine == nullptr);
#ifdef HAVE_JUCE_UI
CARLA_SAFE_ASSERT(MessageManager::getInstanceWithoutCreating() == nullptr);
#endif
}

#ifdef HAVE_JUCE_UI
void init()
{
JUCE_AUTORELEASEPOOL
{
initialiseJuce_GUI();
# ifdef CARLA_OS_LINUX
juceMsgThread.start();
# else
if (MessageManager* const msgMgr = MessageManager::getInstance())
msgMgr->setCurrentThreadAsMessageThread();
# endif
}
}

void close()
{
JUCE_AUTORELEASEPOOL
{
# ifdef CARLA_OS_LINUX
juceMsgThread.stop();
# else
MessageManager::deleteInstance();
# endif
shutdownJuce_GUI();
}
}

# ifndef CARLA_OS_LINUX
void idle()
{
JUCE_AUTORELEASEPOOL
{
if (MessageManager* const msgMgr = MessageManager::getInstanceWithoutCreating())
msgMgr->runDispatchLoopUntil(5);
}
}
# endif
#endif

CARLA_PREVENT_HEAP_ALLOCATION
CARLA_DECLARE_NON_COPY_STRUCT(CarlaBackendStandalone)
};
@@ -619,20 +496,12 @@ const char* carla_get_complete_license_text()
// end
text4 += "</ul>";

// code snippets
text5 += "<p>Additionally, Carla uses code snippets from the following projects:</p>";
text5 += "<ul>";
text5 += "<li>Pointer and data leak utils from JUCE, http://www.rawmaterialsoftware.com/juce.php</li>";
text5 += "<li>Shared memory utils from dssi-vst, http://www.breakfastquay.com/dssi-vst/</li>";
text5 += "<li>Real-time memory pool, by Nedko Arnaudov</li>";
text5 += "</ul>";

#ifdef WANT_LINUXSAMPLER
// LinuxSampler GPL exception
text5 += "<p>(*) Using LinuxSampler code in commercial hardware or software products is not allowed without prior written authorization by the authors.</p>";
text4 += "<p>(*) Using LinuxSampler code in commercial hardware or software products is not allowed without prior written authorization by the authors.</p>";
#endif

retText = text1 + text2 + text3 + text4 + text5;
retText = text1 + text2 + text3 + text4;
}

return retText;
@@ -658,15 +527,19 @@ const char* carla_get_supported_file_extensions()
#endif

// Audio files
AudioFormatManager afm;
afm.registerBasicFormats();

for (AudioFormat **it=afm.begin(), **end=afm.end(); it != end; ++it)
{
const StringArray& exts((*it)->getFileExtensions());
using namespace juce;

AudioFormatManager afm;
afm.registerBasicFormats();

for (String *eit=exts.begin(), *eend=exts.end(); eit != eend; ++eit)
retText += String(";*" + (*eit)).toRawUTF8();
for (AudioFormat **it=afm.begin(), **end=afm.end(); it != end; ++it)
{
const StringArray& exts((*it)->getFileExtensions());

for (String *eit=exts.begin(), *eend=exts.end(); eit != eend; ++eit)
retText += String(";*" + (*eit)).toRawUTF8();
}
}

// MIDI files
@@ -683,28 +556,28 @@ const char* carla_get_supported_file_extensions()

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

unsigned int carla_get_engine_driver_count()
uint carla_get_engine_driver_count()
{
carla_debug("carla_get_engine_driver_count()");

return CarlaEngine::getDriverCount();
}

const char* carla_get_engine_driver_name(unsigned int index)
const char* carla_get_engine_driver_name(uint index)
{
carla_debug("carla_get_engine_driver_name(%i)", index);

return CarlaEngine::getDriverName(index);
}

const char* const* carla_get_engine_driver_device_names(unsigned int index)
const char* const* carla_get_engine_driver_device_names(uint index)
{
carla_debug("carla_get_engine_driver_device_names(%i)", index);

return CarlaEngine::getDriverDeviceNames(index);
}

const EngineDriverDeviceInfo* carla_get_engine_driver_device_info(unsigned int index, const char* name)
const EngineDriverDeviceInfo* carla_get_engine_driver_device_info(uint index, const char* name)
{
CARLA_SAFE_ASSERT_RETURN(name != nullptr && name[0] != '\0', nullptr);
carla_debug("carla_get_engine_driver_device_info(%i, \"%s\")", index, name);
@@ -726,18 +599,18 @@ const EngineDriverDeviceInfo* carla_get_engine_driver_device_info(unsigned int i

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

unsigned int carla_get_internal_plugin_count()
uint carla_get_internal_plugin_count()
{
carla_debug("carla_get_internal_plugin_count()");

#ifdef WANT_NATIVE
return static_cast<unsigned int>(CarlaPlugin::getNativePluginCount());
return static_cast<uint>(CarlaPlugin::getNativePluginCount());
#else
return 0;
#endif
}

const CarlaNativePluginInfo* carla_get_internal_plugin_info(unsigned int index)
const CarlaNativePluginInfo* carla_get_internal_plugin_info(uint index)
{
carla_debug("carla_get_internal_plugin_info(%i)", index);

@@ -874,10 +747,10 @@ bool carla_engine_init(const char* driverName, const char* clientName)

if (gStandalone.engine->init(clientName))
{
gStandalone.lastError = "No error";
#ifdef HAVE_JUCE_UI
gStandalone.init();
#if defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN)
juce::initialiseJuce_GUI();
#endif
gStandalone.lastError = "No error";
return true;
}
else
@@ -944,10 +817,10 @@ bool carla_engine_init_bridge(const char audioBaseName[6+1], const char controlB

if (gStandalone.engine->init(clientName))
{
gStandalone.lastError = "No error";
#ifdef HAVE_JUCE_UI
gStandalone.init();
#if defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN)
juce::initialiseJuce_GUI();
#endif
gStandalone.lastError = "No error";
return true;
}
else
@@ -979,10 +852,9 @@ bool carla_engine_close()
if (! closed)
gStandalone.lastError = gStandalone.engine->getLastError();

#ifdef HAVE_JUCE_UI
gStandalone.close();
#if defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN)
juce::shutdownJuce_GUI();
#endif

delete gStandalone.engine;
gStandalone.engine = nullptr;

@@ -994,9 +866,6 @@ void carla_engine_idle()
CARLA_SAFE_ASSERT_RETURN(gStandalone.engine != nullptr,);

gNSM.idle();
#if defined(HAVE_JUCE_UI) && ! defined(CARLA_OS_LINUX)
gStandalone.idle();
#endif
gStandalone.engine->idle();
}

@@ -1070,27 +939,27 @@ void carla_set_engine_option(EngineOption option, int value, const char* valueSt

case CB::ENGINE_OPTION_MAX_PARAMETERS:
CARLA_SAFE_ASSERT_RETURN(value >= 0,);
gStandalone.engineOptions.maxParameters = static_cast<unsigned int>(value);
gStandalone.engineOptions.maxParameters = static_cast<uint>(value);
break;

case CB::ENGINE_OPTION_UI_BRIDGES_TIMEOUT:
CARLA_SAFE_ASSERT_RETURN(value >= 0,);
gStandalone.engineOptions.uiBridgesTimeout = static_cast<unsigned int>(value);
gStandalone.engineOptions.uiBridgesTimeout = static_cast<uint>(value);
break;

case CB::ENGINE_OPTION_AUDIO_NUM_PERIODS:
CARLA_SAFE_ASSERT_RETURN(value >= 2 && value <= 3,);
gStandalone.engineOptions.audioNumPeriods = static_cast<unsigned int>(value);
gStandalone.engineOptions.audioNumPeriods = static_cast<uint>(value);
break;

case CB::ENGINE_OPTION_AUDIO_BUFFER_SIZE:
CARLA_SAFE_ASSERT_RETURN(value >= 8,);
gStandalone.engineOptions.audioBufferSize = static_cast<unsigned int>(value);
gStandalone.engineOptions.audioBufferSize = static_cast<uint>(value);
break;

case CB::ENGINE_OPTION_AUDIO_SAMPLE_RATE:
CARLA_SAFE_ASSERT_RETURN(value >= 22050,);
gStandalone.engineOptions.audioSampleRate = static_cast<unsigned int>(value);
gStandalone.engineOptions.audioSampleRate = static_cast<uint>(value);
break;

case CB::ENGINE_OPTION_AUDIO_DEVICE:


+ 2
- 2
source/backend/Makefile View File

@@ -25,7 +25,7 @@ ifeq ($(CARLA_PLUGIN_SUPPORT),true)
STANDALONE_LIBS += ../modules/lilv.a
endif

ifeq ($(HAVE_JUCE_UI),true)
ifeq ($(MACOS_OR_WIN32),true)
STANDALONE_LIBS += ../modules/juce_audio_devices.a
STANDALONE_LIBS += ../modules/juce_audio_processors.a
STANDALONE_LIBS += ../modules/juce_data_structures.a
@@ -59,7 +59,7 @@ ifeq ($(HAVE_LINUXSAMPLER),true)
STANDALONE_FLAGS += $(LINUXSAMPLER_LIBS)
endif

ifeq ($(HAVE_JUCE_UI),true)
ifeq ($(MACOS_OR_WIN32),true)
STANDALONE_FLAGS += $(JUCE_AUDIO_DEVICES_LIBS)
STANDALONE_FLAGS += $(JUCE_AUDIO_PROCESSORS_LIBS)
STANDALONE_FLAGS += $(JUCE_DATA_STRUCTURES_LIBS)


+ 3
- 3
source/backend/Makefile.mk View File

@@ -22,12 +22,12 @@ BUILD_CXX_FLAGS += -DWANT_NATIVE

ifeq ($(CARLA_PLUGIN_SUPPORT),true)
BUILD_CXX_FLAGS += -DWANT_LADSPA -DWANT_DSSI -DWANT_LV2 -DWANT_VST
ifeq ($(MACOS),true)
BUILD_CXX_FLAGS += -DWANT_AU
endif
ifeq ($(MACOS_OR_WIN32),true)
BUILD_CXX_FLAGS += -DWANT_VST3
endif
ifeq ($(MACOS),true)
BUILD_CXX_FLAGS += -DWANT_AU
endif
ifeq ($(CARLA_VESTIGE_HEADER),true)
BUILD_CXX_FLAGS += -DVESTIGE_HEADER
endif


+ 36
- 48
source/backend/engine/CarlaEngine.cpp View File

@@ -73,9 +73,10 @@ uint CarlaEngine::getDriverCount()
count += 1;

#ifndef BUILD_BRIDGE
count += getRtAudioApiCount();
# ifdef HAVE_JUCE_UI
# if defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN)
count += getJuceApiCount();
# else
count += getRtAudioApiCount();
# endif
#endif

@@ -92,19 +93,19 @@ const char* CarlaEngine::getDriverName(const uint index2)
return "JACK";

#ifndef BUILD_BRIDGE
if (const uint count = getRtAudioApiCount())
# if defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN)
if (const uint count = getJuceApiCount())
{
if (index < count)
return getRtAudioApiName(index);
return getJuceApiName(index);
index -= count;
}

# ifdef HAVE_JUCE_UI
# else
if (const uint count = getRtAudioApiCount())
{
if (index < count)
return getJuceApiName(index);
//index -= count;
return getRtAudioApiName(index);
index -= count;
}
# endif
#endif
@@ -126,19 +127,19 @@ const char* const* CarlaEngine::getDriverDeviceNames(const uint index2)
}

#ifndef BUILD_BRIDGE
if (const uint count = getRtAudioApiCount())
# if defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN)
if (const uint count = getJuceApiCount())
{
if (index < count)
return getRtAudioApiDeviceNames(index);
return getJuceApiDeviceNames(index);
index -= count;
}

# ifdef HAVE_JUCE_UI
# else
if (const uint count = getRtAudioApiCount())
{
if (index < count)
return getJuceApiDeviceNames(index);
//index -= count;
return getRtAudioApiDeviceNames(index);
index -= count;
}
# endif
#endif
@@ -164,19 +165,19 @@ const EngineDriverDeviceInfo* CarlaEngine::getDriverDeviceInfo(const uint index2
}

#ifndef BUILD_BRIDGE
if (const uint count = getRtAudioApiCount())
# if defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN)
if (const uint count = getJuceApiCount())
{
if (index < count)
return getRtAudioDeviceInfo(index, deviceName);
return getJuceDeviceInfo(index, deviceName);
index -= count;
}

# ifdef HAVE_JUCE_UI
# else
if (const uint count = getRtAudioApiCount())
{
if (index < count)
return getJuceDeviceInfo(index, deviceName);
//index -= count;
return getRtAudioDeviceInfo(index, deviceName);
index -= count;
}
# endif
#endif
@@ -194,6 +195,21 @@ CarlaEngine* CarlaEngine::newDriverByName(const char* const driverName)
return newJack();

#ifndef BUILD_BRIDGE
# if defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN)
// -------------------------------------------------------------------
// macos

if (std::strcmp(driverName, "CoreAudio") == 0)
return newJuce(AUDIO_API_CORE);

// -------------------------------------------------------------------
// windows

if (std::strcmp(driverName, "ASIO") == 0)
return newJuce(AUDIO_API_ASIO);
if (std::strcmp(driverName, "DirectSound") == 0)
return newJuce(AUDIO_API_DS);
#else
// -------------------------------------------------------------------
// common

@@ -204,39 +220,11 @@ CarlaEngine* CarlaEngine::newDriverByName(const char* const driverName)
// linux

if (std::strcmp(driverName, "ALSA") == 0)
//return newJuce(AUDIO_API_ALSA);
return newRtAudio(AUDIO_API_ALSA);

if (std::strcmp(driverName, "OSS") == 0)
return newRtAudio(AUDIO_API_OSS);
if (std::strcmp(driverName, "PulseAudio") == 0)
return newRtAudio(AUDIO_API_PULSE);

// -------------------------------------------------------------------
// macos

if (std::strcmp(driverName, "CoreAudio") == 0)
# ifdef HAVE_JUCE_UI
return newJuce(AUDIO_API_CORE);
# else
return newRtAudio(AUDIO_API_DS);
# endif

// -------------------------------------------------------------------
// windows

if (std::strcmp(driverName, "ASIO") == 0)
# ifdef HAVE_JUCE_UI
return newJuce(AUDIO_API_ASIO);
# else
return newRtAudio(AUDIO_API_DS);
# endif

if (std::strcmp(driverName, "DirectSound") == 0)
# ifdef HAVE_JUCE_UI
return newJuce(AUDIO_API_DS);
# else
return newRtAudio(AUDIO_API_DS);
# endif
#endif



+ 8
- 8
source/backend/engine/CarlaEngineGraph.cpp View File

@@ -22,7 +22,7 @@
#include "CarlaMathUtils.hpp"
#include "CarlaMIDI.h"

#ifdef HAVE_JUCE_UI
#if 0
using juce::AudioPluginInstance;
using juce::AudioProcessor;
using juce::AudioProcessorEditor;
@@ -729,7 +729,7 @@ void RackGraph::processHelper(CarlaEngine::ProtectedData* const data, const floa
}
}

#ifdef HAVE_JUCE_UI
#if 0
// -----------------------------------------------------------------------

class CarlaPluginInstance : public AudioPluginInstance
@@ -1073,7 +1073,7 @@ void EngineInternalGraph::create(const bool isRack, const double sampleRate, con
CARLA_SAFE_ASSERT_RETURN(fRack == nullptr,);
fRack = new RackGraph(bufferSize, inputs, outputs);
}
#ifdef HAVE_JUCE_UI
#if 0
else
{
CARLA_SAFE_ASSERT_RETURN(fPatchbay == nullptr,);
@@ -1103,7 +1103,7 @@ void EngineInternalGraph::destroy() noexcept
delete fRack;
fRack = nullptr;
}
#ifdef HAVE_JUCE_UI
#if 0
else
{
CARLA_SAFE_ASSERT_RETURN(fPatchbay != nullptr,);
@@ -1122,7 +1122,7 @@ void EngineInternalGraph::setBufferSize(const uint32_t bufferSize)
CARLA_SAFE_ASSERT_RETURN(fRack != nullptr,);
fRack->setBufferSize(bufferSize);
}
#ifdef HAVE_JUCE_UI
#if 0
else
{
CARLA_SAFE_ASSERT_RETURN(fPatchbay != nullptr,);
@@ -1139,7 +1139,7 @@ void EngineInternalGraph::setSampleRate(const double sampleRate)
{
CARLA_SAFE_ASSERT_RETURN(fRack != nullptr,);
}
#ifdef HAVE_JUCE_UI
#if 0
else
{
CARLA_SAFE_ASSERT_RETURN(fPatchbay != nullptr,);
@@ -1160,7 +1160,7 @@ void EngineInternalGraph::setOffline(const bool offline)
CARLA_SAFE_ASSERT_RETURN(fRack != nullptr,);
fRack->setOffline(offline);
}
#ifdef HAVE_JUCE_UI
#if 0
else
{
CARLA_SAFE_ASSERT_RETURN(fPatchbay != nullptr,);
@@ -1195,7 +1195,7 @@ void EngineInternalGraph::process(CarlaEngine::ProtectedData* const data, const
CARLA_SAFE_ASSERT_RETURN(fRack != nullptr,);
fRack->processHelper(data, inBuf, outBuf, frames);
}
#ifdef HAVE_JUCE_UI
#if 0
else
{
CARLA_SAFE_ASSERT_RETURN(fPatchbay != nullptr,);


+ 2
- 2
source/backend/engine/CarlaEngineGraph.hpp View File

@@ -23,7 +23,7 @@
#include "CarlaPatchbayUtils.hpp"
#include "CarlaStringList.hpp"

#ifdef HAVE_JUCE_UI
#if 0
# include "juce_audio_processors.h"
using juce::AudioProcessorGraph;
using juce::AudioSampleBuffer;
@@ -105,7 +105,7 @@ struct RackGraph {
void processHelper(CarlaEngine::ProtectedData* const data, const float* const* const inBuf, float* const* const outBuf, const uint32_t frames);
};

#ifdef HAVE_JUCE_UI
#if 0
// -----------------------------------------------------------------------
// PatchbayGraph



+ 8
- 6
source/backend/engine/CarlaEngineNative.cpp View File

@@ -1654,17 +1654,19 @@ CARLA_BACKEND_START_NAMESPACE

CarlaEngine* CarlaEngine::newJack() { return nullptr; }

CarlaEngine* CarlaEngine::newRtAudio(const AudioApi) { return nullptr; }
uint CarlaEngine::getRtAudioApiCount() { return 0; }
const char* CarlaEngine::getRtAudioApiName(const uint) { return nullptr; }
const char* const* CarlaEngine::getRtAudioApiDeviceNames(const uint) { return nullptr; }
const EngineDriverDeviceInfo* CarlaEngine::getRtAudioDeviceInfo(const uint, const char* const) { return nullptr; }

# if defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN)
CarlaEngine* CarlaEngine::newJuce(const AudioApi) { return nullptr; }
uint CarlaEngine::getJuceApiCount() { return 0; }
const char* CarlaEngine::getJuceApiName(const uint) { return nullptr; }
const char* const* CarlaEngine::getJuceApiDeviceNames(const uint) { return nullptr; }
const EngineDriverDeviceInfo* CarlaEngine::getJuceDeviceInfo(const uint, const char* const) { return nullptr; }
# else
CarlaEngine* CarlaEngine::newRtAudio(const AudioApi) { return nullptr; }
uint CarlaEngine::getRtAudioApiCount() { return 0; }
const char* CarlaEngine::getRtAudioApiName(const uint) { return nullptr; }
const char* const* CarlaEngine::getRtAudioApiDeviceNames(const uint) { return nullptr; }
const EngineDriverDeviceInfo* CarlaEngine::getRtAudioDeviceInfo(const uint, const char* const) { return nullptr; }
# endif

CARLA_BACKEND_END_NAMESPACE



+ 0
- 4
source/backend/engine/CarlaEngineRtAudio.cpp View File

@@ -59,16 +59,12 @@ static void initRtAudioAPIsIfNeeded()
{
const RtAudio::Api& api(*it);

//if (api == RtAudio::LINUX_ALSA)
// continue;
#ifdef HAVE_JUCE_UI
if (api == RtAudio::MACOSX_CORE)
continue;
if (api == RtAudio::WINDOWS_ASIO)
continue;
if (api == RtAudio::WINDOWS_DS)
continue;
#endif
if (api == RtAudio::UNIX_JACK && ! jackbridge_is_ok())
continue;



+ 5
- 3
source/backend/engine/Makefile View File

@@ -20,12 +20,14 @@ OBJS = \
CarlaEngineThread.cpp.o

OBJSa = $(OBJS) \
CarlaEngineJack.cpp.o \
CarlaEngineRtAudio.cpp.o
CarlaEngineJack.cpp.o

ifeq ($(HAVE_JUCE_UI),true)
ifeq ($(MACOS_OR_WIN32),true)
OBJSa += \
CarlaEngineJuce.cpp.o
else
OBJSa += \
CarlaEngineRtAudio.cpp.o
endif

ifneq ($(WIN32),true)


+ 1
- 1
source/backend/plugin/AuPlugin.cpp View File

@@ -25,7 +25,7 @@ CarlaPlugin* CarlaPlugin::newAU(const Initializer& init)
{
carla_debug("CarlaPlugin::newAU({%p, \"%s\", \"%s\", " P_INT64 "})", init.engine, init.filename, init.name, init.uniqueId);

#if defined(WANT_AU) && defined(HAVE_JUCE_UI)
#if defined(WANT_AU) && defined(CARLA_OS_MAC)
return newJuce(init, "AU");
#else
init.engine->setLastError("AU support not available");


+ 4
- 21
source/backend/plugin/JucePlugin.cpp View File

@@ -18,24 +18,7 @@
#include "CarlaPluginInternal.hpp"
#include "CarlaEngine.hpp"

#ifdef HAVE_JUCE_UI

#if defined(CARLA_OS_MAC)
/*
* Missing functions in OSX.
*/
namespace std {
inline float
fmin(float __x, float __y)
{ return __builtin_fminf(__x, __y); }
inline float
fmax(float __x, float __y)
{ return __builtin_fmaxf(__x, __y); }
inline float
rint(float __x)
{ return __builtin_rintf(__x); }
}
#endif
#if (defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN))

#include "CarlaBackendUtils.hpp"
#include "JucePluginWindow.hpp"
@@ -983,7 +966,7 @@ public:

void* getNativeHandle() const noexcept override
{
return (fInstance != nullptr) ? fInstance-> /* TODO */ : nullptr;
return (fInstance != nullptr) ? fInstance->getPlatformSpecificData() : nullptr;
}

// -------------------------------------------------------------------
@@ -1144,7 +1127,7 @@ private:

CARLA_BACKEND_END_NAMESPACE

#endif // HAVE_JUCE_UI
#endif // defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN)

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

@@ -1154,7 +1137,7 @@ CarlaPlugin* CarlaPlugin::newJuce(const Initializer& init, const char* const for
{
carla_debug("CarlaPlugin::newJuce({%p, \"%s\", \"%s\", \"%s\", " P_INT64 "}, %s)", init.engine, init.filename, init.name, init.label, init.uniqueId, format);

#ifdef HAVE_JUCE_UI
#if (defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN))
JucePlugin* const plugin(new JucePlugin(init.engine, init.id));

if (! plugin->init(init.filename, init.name, /*init.label,*/ init.uniqueId, format))


+ 1
- 1
source/backend/plugin/Vst3Plugin.cpp View File

@@ -25,7 +25,7 @@ CarlaPlugin* CarlaPlugin::newVST3(const Initializer& init)
{
carla_debug("CarlaPlugin::newVST3({%p, \"%s\", \"%s\", " P_INT64 "})", init.engine, init.filename, init.name, init.uniqueId);

#if defined(WANT_VST) && defined(HAVE_JUCE_UI)
#if defined(WANT_VST) && (defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN))
return newJuce(init, "VST3");
#else
init.engine->setLastError("VST3 support not available");


+ 4
- 4
source/backend/plugin/VstPlugin.cpp View File

@@ -18,13 +18,13 @@
#include "CarlaPluginInternal.hpp"
#include "CarlaEngine.hpp"

#if defined(CARLA_OS_LINUX) || defined(VESTIGE_HEADER)
#if defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN)
# define USE_JUCE_FOR_VST 0
#else
# define USE_JUCE_FOR_VST 1
#endif

#if defined(WANT_VST) && ! (defined(HAVE_JUCE_UI) && USE_JUCE_FOR_VST)
#if defined(WANT_VST) && ! USE_JUCE_FOR_VST

#include "CarlaVstUtils.hpp"

@@ -2528,7 +2528,7 @@ VstPlugin* VstPlugin::sLastVstPlugin = nullptr;

CARLA_BACKEND_END_NAMESPACE

#endif // WANT_VST && ! (defined(HAVE_JUCE_UI) && USE_JUCE_FOR_VST)
#endif // WANT_VST && ! USE_JUCE_FOR_VST

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

@@ -2539,7 +2539,7 @@ CarlaPlugin* CarlaPlugin::newVST(const Initializer& init)
carla_debug("CarlaPlugin::newVST({%p, \"%s\", \"%s\", " P_INT64 "})", init.engine, init.filename, init.name, init.uniqueId);

#ifdef WANT_VST
# if defined(HAVE_JUCE_UI) && USE_JUCE_FOR_VST
# if USE_JUCE_FOR_VST
return newJuce(init, "VST");
# else
VstPlugin* const plugin(new VstPlugin(init.engine, init.id));


+ 4
- 3
source/bridges/CarlaBridgePlugin.cpp View File

@@ -29,7 +29,8 @@
# include <signal.h>
#endif

#ifdef HAVE_JUCE_UI
// TODO
#if 0
# include "juce_gui_basics.h"
using juce::JUCEApplication;
using juce::JUCEApplicationBase;
@@ -214,7 +215,7 @@ public:
}
}

#ifndef HAVE_JUCE_UI
#if 1
void idle()
{
CARLA_SAFE_ASSERT_RETURN(fEngine != nullptr,);
@@ -243,7 +244,7 @@ public:

void exec(int argc, char* argv[])
{
#ifdef HAVE_JUCE_UI
#if 0
gBridgeClient = this;
JUCEApplicationBase::createInstance = &juce_CreateApplication;
JUCEApplicationBase::main(JUCE_MAIN_FUNCTION_ARGS);


+ 0
- 2
source/bridges/CarlaBridgeUI-LV2.cpp View File

@@ -15,8 +15,6 @@
* For a full copy of the GNU General Public License see the GPL.txt file
*/

#undef HAVE_JUCE

#include "CarlaBridgeClient.hpp"
#include "CarlaBase64Utils.hpp"
#include "CarlaLv2Utils.hpp"


+ 4
- 70
source/bridges/Makefile View File

@@ -35,7 +35,7 @@ BUILD_PLUGIN_FLAGS += -DVESTIGE_HEADER
endif
endif

ifeq ($(HAVE_JUCE_UI),true)
ifeq ($(MACOS_OR_WIN32),true)
LINK_PLUGIN_FLAGS += $(JUCE_AUDIO_PROCESSORS_LIBS)
LINK_PLUGIN_FLAGS += $(JUCE_DATA_STRUCTURES_LIBS)
LINK_PLUGIN_FLAGS += $(JUCE_EVENTS_LIBS)
@@ -383,67 +383,6 @@ OBJS_UI_LV2_QT5 = CarlaBridgeUI-LV2__lv2-qt5.o \
# --------------------------------------------------------------
# native

OBJS_PLUGIN = \
jackplugin/CarlaJackPlugin__plugin.o \
CarlaBridgeClient__plugin.o \
CarlaBridgeOsc__plugin.o \
../backend/engine/CarlaEngine__native.o \
../backend/engine/CarlaEngineData__native.o \
../backend/engine/CarlaEngineInternal__native.o \
../backend/engine/CarlaEngineOsc__native.o \
../backend/engine/CarlaEngineThread__native.o \
../backend/engine/CarlaEngineJack__native.o \
../backend/engine/CarlaEngineBridge__native.o \
../backend/plugin/CarlaPlugin__native.o \
../backend/plugin/CarlaPluginInternal__native.o \
../backend/plugin/CarlaPluginThread__native.o \
../backend/plugin/CarlaPluginUi__native.o \
../backend/plugin/NativePlugin__native.o \
../backend/plugin/LadspaPlugin__native.o \
../backend/plugin/DssiPlugin__native.o \
../backend/plugin/Lv2Plugin__native.o \
../backend/plugin/VstPlugin__native.o \
../backend/plugin/Vst3Plugin__native.o \
../backend/plugin/AuPlugin__native.o \
../backend/plugin/JucePlugin__native.o \
../backend/plugin/FluidSynthPlugin__native.o \
../backend/plugin/LinuxSamplerPlugin__native.o \
../backend/CarlaStandalone__native.o

LIBS_PLUGIN = \
../modules/jackbridge.a \
../modules/juce_audio_basics.a \
../modules/juce_audio_formats.a \
../modules/juce_events.a \
../modules/juce_core.a \
../modules/rtmempool.a

ifeq ($(HAVE_JUCE_UI),true)
LIBS_PLUGIN += \
../modules/juce_audio_processors.a \
../modules/juce_data_structures.a \
../modules/juce_data_structures.a \
../modules/juce_graphics.a \
../modules/juce_gui_basics.a \
../modules/juce_gui_extra.a
endif

ifeq ($(CARLA_PLUGIN_SUPPORT),true)
LIBS_PLUGIN += \
../modules/lilv.a
endif

jackplugin/libjack.so.0: $(OBJS_PLUGIN) $(LIBS_PLUGIN)
$(CXX) $(OBJS_PLUGIN) -Wl,--start-group $(LIBS_PLUGIN) -Wl,--end-group $(NATIVE_LINK_FLAGS) -shared -o $@

%__plugin.o: %.cpp
$(CXX) $< $(NATIVE_BUILD_FLAGS) -DBRIDGE_JACK -DJACKBRIDGE_EXPORT -c -o $@

# $(NATIVE_LINK_FLAGS)

# --------------------------------------------------------------
# native

OBJS_NATIVE = CarlaBridgePlugin__native.o \
CarlaBridgeClient__native.o CarlaBridgeOsc__native.o

@@ -490,11 +429,10 @@ LIBS_NATIVE = \
../modules/juce_core.a \
../modules/rtmempool.a

ifeq ($(HAVE_JUCE_UI),true)
ifeq ($(MACOS_OR_WIN32),true)
LIBS_NATIVE += \
../modules/juce_audio_processors.a \
../modules/juce_data_structures.a \
../modules/juce_data_structures.a \
../modules/juce_events.a \
../modules/juce_graphics.a \
../modules/juce_gui_basics.a \
@@ -553,7 +491,7 @@ LIBS_POSIX32 = \
../modules/lilv.posix32.a \
../modules/rtmempool.posix32.a

ifeq ($(HAVE_JUCE),true)
ifeq ($(MACOS),true)
LIBS_POSIX32 += \
../modules/juce_audio_basics.posix32.a \
../modules/juce_audio_processors.posix32.a \
@@ -611,7 +549,7 @@ LIBS_POSIX64 = \
../modules/lilv.posix64.a \
../modules/rtmempool.posix64.a

ifeq ($(HAVE_JUCE),true)
ifeq ($(MACOS),true)
LIBS_POSIX64 += \
../modules/juce_audio_basics.posix64.a \
../modules/juce_audio_processors.posix64.a \
@@ -669,7 +607,6 @@ LIBS_WIN32 = \
../modules/lilv.win32.a \
../modules/rtmempool.win32.a

ifeq ($(HAVE_JUCE),true)
LIBS_WIN32 += \
../modules/juce_audio_basics.win32.a \
../modules/juce_audio_processors.win32.a \
@@ -678,7 +615,6 @@ LIBS_WIN32 += \
../modules/juce_events.win32.a \
../modules/juce_graphics.win32.a \
../modules/juce_gui_basics.win32.a
endif

../../bin/carla-bridge-win32.exe: $(OBJS_WIN32) $(LIBS_WIN32) ../modules/jackbridge-win32.dll
$(CXX) $(OBJS_WIN32) -Wl,--start-group $(LIBS_WIN32) -Wl,--end-group $(WIN_LINK_FLAGS) $(WIN_32BIT_FLAGS) -ljackbridge-win32 -o $@
@@ -727,7 +663,6 @@ LIBS_WIN64 = \
../modules/lilv.win64.a \
../modules/rtmempool.win64.a

ifeq ($(HAVE_JUCE),true)
LIBS_WIN64 += \
../modules/juce_audio_basics.win64.a \
../modules/juce_audio_processors.win64.a \
@@ -736,7 +671,6 @@ LIBS_WIN64 += \
../modules/juce_events.win64.a \
../modules/juce_graphics.win64.a \
../modules/juce_gui_basics.win64.a
endif

../../bin/carla-bridge-win64.exe: $(OBJS_WIN64) $(LIBS_WIN64) ../modules/jackbridge-win64.dll
$(CXX) $(OBJS_WIN64) -Wl,--start-group $(LIBS_WIN64) -Wl,--end-group $(WIN_LINK_FLAGS) $(WIN_64BIT_FLAGS) -ljackbridge-win64 -o $@


+ 7
- 6
source/discovery/Makefile View File

@@ -10,9 +10,10 @@ include ../Makefile.mk
# --------------------------------------------------------------

BUILD_CXX_FLAGS += -I../backend -I../includes -I../utils -isystem ../modules
BUILD_CXX_FLAGS += -I../includes/ladspa -I../includes/vst -I../includes/vst3
#-Wno-multichar

BUILD_CXX_FLAGS += -I../includes/ladspa -I../includes/vst
ifeq ($(MACOS_OR_WIN32),true)
BUILD_CXX_FLAGS += -I../includes/vst3
endif
ifeq ($(MACOS),true)
BUILD_CXX_FLAGS += -ObjC++
endif
@@ -21,12 +22,12 @@ endif

ifeq ($(CARLA_PLUGIN_SUPPORT),true)
BUILD_CXX_FLAGS += -DWANT_LADSPA -DWANT_DSSI -DWANT_LV2 -DWANT_VST
ifeq ($(MACOS),true)
BUILD_CXX_FLAGS += -DWANT_AU
endif
ifeq ($(MACOS_OR_WIN32),true)
BUILD_CXX_FLAGS += -DWANT_VST3
endif
ifeq ($(MACOS),true)
BUILD_CXX_FLAGS += -DWANT_AU
endif
ifeq ($(CARLA_VESTIGE_HEADER),true)
BUILD_CXX_FLAGS += -DVESTIGE_HEADER
endif


+ 6
- 7
source/modules/CarlaNative.h View File

@@ -58,13 +58,12 @@ typedef enum {
PLUGIN_HAS_UI = 1 << 2,
PLUGIN_NEEDS_FIXED_BUFFERS = 1 << 3,
PLUGIN_NEEDS_SINGLE_THREAD = 1 << 4,
PLUGIN_NEEDS_UI_JUCE = 1 << 5,
PLUGIN_NEEDS_UI_OPEN_SAVE = 1 << 6,
PLUGIN_USES_MULTI_PROGS = 1 << 7, // has 1 patch per midi channel
PLUGIN_USES_PANNING = 1 << 8, // uses stereo balance if unset (default)
PLUGIN_USES_STATE = 1 << 9,
PLUGIN_USES_TIME = 1 << 10,
PLUGIN_USES_PARENT_ID = 1 << 11 // can set transient hint to parent
PLUGIN_NEEDS_UI_OPEN_SAVE = 1 << 5,
PLUGIN_USES_MULTI_PROGS = 1 << 6, // has 1 patch per midi channel
PLUGIN_USES_PANNING = 1 << 7, // uses stereo balance if unset (default)
PLUGIN_USES_STATE = 1 << 8,
PLUGIN_USES_TIME = 1 << 9,
PLUGIN_USES_PARENT_ID = 1 << 10 // can set transient hint to parent
} NativePluginHints;

typedef enum {


+ 1
- 1
source/modules/juce_audio_devices/AppConfig.h View File

@@ -45,7 +45,7 @@
/** Config: JUCE_ALSA
Enables ALSA audio devices (Linux only).
*/
#if JUCE_LINUX
#if 0 //JUCE_LINUX
#define JUCE_ALSA 1
#define JUCE_ALSA_MIDI_INPUT_NAME "Carla"
#define JUCE_ALSA_MIDI_OUTPUT_NAME "Carla"


+ 1
- 1
source/modules/juce_core/AppConfig.h View File

@@ -81,7 +81,7 @@
#define JUCE_MODULE_AVAILABLE_juce_video 0
// conditional
#ifdef HAVE_JUCE_UI
#if JUCE_MAC || JUCE_WINDOWS
# define JUCE_MODULE_AVAILABLE_juce_audio_devices 1
# define JUCE_MODULE_AVAILABLE_juce_audio_processors 1
# define JUCE_MODULE_AVAILABLE_juce_data_structures 1


+ 2
- 2
source/modules/juce_events.h View File

@@ -18,8 +18,8 @@
#ifndef CARLA_JUCE_EVENTS_H_INCLUDED
#define CARLA_JUCE_EVENTS_H_INCLUDED

#ifndef HAVE_JUCE_UI
# error Can't have juce_events with the current setup
#if ! (JUCE_MAC || JUCE_WINDOWS)
# error Don't want juce_events with the current setup
#endif

#include "juce_core.h"


+ 0
- 11
source/modules/native-plugins/Makefile View File

@@ -66,14 +66,6 @@ OBJS += \
notes.cpp.o
endif

ifeq ($(HAVE_JUCE_UI),true)
# --------------------------------------------------------------
# JUCE based plugins

OBJS += \
juce-patchbay.cpp.o
endif

# --------------------------------------------------------------
# ZynAddSubFX

@@ -163,9 +155,6 @@ audio-file.cpp.o: audio-file.cpp $(CXXDEPS)
bigmeter.cpp.o: bigmeter.cpp $(CXXDEPS) ../CarlaNativeExtUI.hpp
$(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@

juce-patchbay.cpp.o: juce-patchbay.cpp
$(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@

midi-file.cpp.o: midi-file.cpp midi-base.hpp $(CXXDEPS)
$(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@



+ 0
- 14
source/modules/native-plugins/_all.c View File

@@ -41,13 +41,6 @@ extern void carla_register_native_plugin_bigmeter();
extern void carla_register_native_plugin_notes();
#endif

#ifdef HAVE_JUCE_UI
// JUCE based plugins
extern void carla_register_native_plugin_jucepatchbay();
extern void carla_register_native_plugin_vex_fx();
extern void carla_register_native_plugin_vex_synth();
#endif

#ifdef WANT_ZYNADDSUBFX
// ZynAddSubFX
extern void carla_register_native_plugin_zynaddsubfx_fx();
@@ -80,13 +73,6 @@ void carla_register_all_plugins()
carla_register_native_plugin_notes();
#endif

#ifdef HAVE_JUCE_UI
// JUCE based plugins
carla_register_native_plugin_jucepatchbay();
carla_register_native_plugin_vex_fx();
carla_register_native_plugin_vex_synth();
#endif

#ifdef WANT_ZYNADDSUBFX
// ZynAddSubFX
carla_register_native_plugin_zynaddsubfx_fx();


+ 0
- 283
source/modules/native-plugins/juce-patchbay.cpp View File

@@ -1,283 +0,0 @@
/*
* Carla Native Plugins
* Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* For a full copy of the GNU General Public License see the doc/GPL.txt file.
*/

#include "CarlaNative.hpp"

#include "JuceInternalFilters.hpp"
#include "juce_gui_extra.h"

#ifdef HAVE_X11
# include <X11/Xlib.h>
# undef KeyPress
#endif

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

namespace juce {
#include "jucepluginhost/juce_MidiKeyboardComponent.h"
#include "jucepluginhost/juce_MidiKeyboardComponent.cpp"

#include "jucepluginhost/FilterGraph.h"
#include "jucepluginhost/GraphEditorPanel.h"
#include "jucepluginhost/MainHostWindow.h"

#include "jucepluginhost/FilterGraph.cpp"
#include "jucepluginhost/GraphEditorPanel.cpp"
#include "jucepluginhost/MainHostWindow.cpp"

#ifdef HAVE_X11
extern Display* display;
#endif
}

using namespace juce;

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

class JucePatchbayPlugin : public NativePluginClass
{
public:
JucePatchbayPlugin(const NativeHostDescriptor* const host)
: NativePluginClass(host),
fFormatManager(),
fGraph(fFormatManager),
fMidiKeyState(nullptr)
{
PropertiesFile::Options options;
options.applicationName = "Juce Audio Plugin Host";
options.filenameSuffix = "settings";
options.osxLibrarySubFolder = "Preferences";

fAppProperties = new ApplicationProperties();
fAppProperties->setStorageParameters(options);

fFormatManager.addDefaultFormats();
fFormatManager.addFormat(new InternalPluginFormat());
fGraph.ready(fAppProperties);

fGraph.getGraph().setPlayConfigDetails(2, 2, getSampleRate(), static_cast<int>(getBufferSize()));

fMidiBuffer.ensureSize(512*2);
fMidiBuffer.clear();
}

~JucePatchbayPlugin() override
{
fGraph.clear();
fAppProperties = nullptr;
}

protected:
// -------------------------------------------------------------------
// Plugin process calls

void activate() override
{
fGraph.getGraph().prepareToPlay(getSampleRate(), static_cast<int>(getBufferSize()));

fAudioBuffer.setSize(2, static_cast<int>(getBufferSize()));

{
const ScopedLock csl(fMidiKeyMutex);

if (fMidiKeyState != nullptr)
fMidiKeyState->reset();
}
}

void deactivate() override
{
fGraph.getGraph().releaseResources();
}

void process(float** inBuffer, float** const outBuffer, const uint32_t frames, const NativeMidiEvent* const midiEvents, const uint32_t midiEventCount) override
{
fMidiBuffer.clear();

for (uint32_t i=0; i < midiEventCount; ++i)
{
const NativeMidiEvent* const midiEvent(&midiEvents[i]);
fMidiBuffer.addEvent(midiEvent->data, midiEvent->size, midiEvent->time);
}

{
const ScopedLock csl(fMidiKeyMutex);

if (fMidiKeyState != nullptr)
fMidiKeyState->processNextMidiBuffer(fMidiBuffer, 0, static_cast<int>(frames), true);
}

FloatVectorOperations::copy(outBuffer[0], inBuffer[0], static_cast<int>(frames));
FloatVectorOperations::copy(outBuffer[1], inBuffer[1], static_cast<int>(frames));
AudioSampleBuffer audioBuf(outBuffer, 2, static_cast<int>(frames));

fGraph.getGraph().processBlock(audioBuf, fMidiBuffer);

const uint8_t* midiData;
int numBytes;
int sampleNumber;

NativeMidiEvent tmpEvent;
tmpEvent.port = 0;

for (MidiBuffer::Iterator outBufferIterator(fMidiBuffer); outBufferIterator.getNextEvent(midiData, numBytes, sampleNumber);)
{
if (numBytes <= 0 || numBytes > 4)
continue;

tmpEvent.size = numBytes;
tmpEvent.time = sampleNumber;

std::memcpy(tmpEvent.data, midiData, sizeof(uint8_t)*tmpEvent.size);
writeMidiEvent(&tmpEvent);
}
}

// -------------------------------------------------------------------
// Plugin UI calls

void uiShow(const bool show) override
{
const MessageManagerLock mmLock;

if (show)
{
if (fWindow == nullptr)
{
fWindow = new MainHostWindow(fFormatManager, fGraph, *fAppProperties);
fWindow->setName(getUiName());
#ifdef HAVE_X11
::Window thisWinId = (::Window)fWindow->getWindowHandle();
::Window hostWinId = (::Window)getUiParentId();

if (display != nullptr && thisWinId != 0 && hostWinId != 0)
XSetTransientForHint(display, thisWinId, hostWinId);
#endif
}
{
const ScopedLock csl(fMidiKeyMutex);
fMidiKeyState = fWindow->getMidiState();
}
fWindow->toFront(true);
}
else if (fWindow != nullptr)
{
{
const ScopedLock csl(fMidiKeyMutex);
fMidiKeyState = nullptr;
}
fWindow->setVisible(false);
fWindow = nullptr;
}
}

void uiIdle() override
{
if (fWindow == nullptr)
return;

if (fWindow->wasClosedByUser())
{
uiShow(false);
uiClosed();
}
}

// -------------------------------------------------------------------
// Plugin state calls

char* getState() const override
{
ScopedPointer<XmlElement> xml(fGraph.createXml());

MemoryOutputStream stream;
xml->writeToStream(stream, String::empty);

return strdup(stream.toUTF8().toRawUTF8());
}

void setState(const char* const data) override
{
CARLA_SAFE_ASSERT_RETURN(data != nullptr,);

String sdata(data);
XmlDocument doc(sdata);
ScopedPointer<XmlElement> xml(doc.getDocumentElement());

if (xml != nullptr && xml->hasTagName("FILTERGRAPH"))
fGraph.restoreFromXml(*xml);
}

// -------------------------------------------------------------------
// Plugin dispatcher calls

void uiNameChanged(const char* const uiName) override
{
CARLA_SAFE_ASSERT_RETURN(uiName != nullptr,);

if (fWindow == nullptr)
return;

const MessageManagerLock mmLock;
fWindow->setName(uiName);
}

private:
AudioPluginFormatManager fFormatManager;
FilterGraph fGraph;

AudioSampleBuffer fAudioBuffer;
MidiBuffer fMidiBuffer;

ScopedPointer<ApplicationProperties> fAppProperties;
ScopedPointer<MainHostWindow> fWindow;

MidiKeyboardState* fMidiKeyState;
CriticalSection fMidiKeyMutex;

PluginClassEND(JucePatchbayPlugin)
CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(JucePatchbayPlugin)
};

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

static const NativePluginDescriptor jucepatchbayDesc = {
/* category */ PLUGIN_CATEGORY_UTILITY,
/* hints */ static_cast<NativePluginHints>(PLUGIN_IS_SYNTH|PLUGIN_HAS_UI|PLUGIN_NEEDS_FIXED_BUFFERS|PLUGIN_NEEDS_UI_JUCE|PLUGIN_USES_STATE/*|PLUGIN_USES_TIME*/|PLUGIN_USES_PARENT_ID),
/* supports */ static_cast<NativePluginSupports>(0x0),
/* audioIns */ 2,
/* audioOuts */ 2,
/* midiIns */ 1,
/* midiOuts */ 1,
/* paramIns */ 0,
/* paramOuts */ 0,
/* name */ "Juce Patchbay",
/* label */ "jucepatchbay",
/* maker */ "falkTX, Raw Material Software Ltd.",
/* copyright */ "GNU GPL v2+",
PluginDescriptorFILL(JucePatchbayPlugin)
};

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

CARLA_EXPORT
void carla_register_native_plugin_jucepatchbay()
{
carla_register_native_plugin(&jucepatchbayDesc);
}

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

+ 0
- 406
source/modules/native-plugins/jucepluginhost/FilterGraph.cpp View File

@@ -1,406 +0,0 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
Permission is granted to use this software under the terms of either:
a) the GPL v2 (or any later version)
b) the Affero GPL v3
Details of these licenses can be found at: www.gnu.org/licenses
JUCE 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.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.juce.com for more information.
==============================================================================
*/
#include "FilterGraph.h"
#include "InternalFilters.h"
#include "GraphEditorPanel.h"
//==============================================================================
const int FilterGraph::midiChannelNumber = 0x1000;
FilterGraph::FilterGraph (AudioPluginFormatManager& formatManager_)
: FileBasedDocument (filenameSuffix,
filenameWildcard,
"Load a filter graph",
"Save a filter graph"),
formatManager (formatManager_), lastUID (0), appProperties (nullptr), panel (nullptr)
{
setChangedFlag (false);
}
FilterGraph::~FilterGraph()
{
graph.clear();
}
void FilterGraph::ready(ApplicationProperties* ap)
{
appProperties = ap;
InternalPluginFormat internalFormat;
addFilter (internalFormat.getDescriptionFor (InternalPluginFormat::audioInputFilter), 0.5f, 0.1f);
addFilter (internalFormat.getDescriptionFor (InternalPluginFormat::midiInputFilter), 0.25f, 0.1f);
addFilter (internalFormat.getDescriptionFor (InternalPluginFormat::audioOutputFilter), 0.5f, 0.9f);
addFilter (internalFormat.getDescriptionFor (InternalPluginFormat::midiOutputFilter), 0.25f, 0.9f);
}
void FilterGraph::setPanel(GraphEditorPanel* p)
{
panel = p;
}
uint32 FilterGraph::getNextUID() noexcept
{
return ++lastUID;
}
//==============================================================================
int FilterGraph::getNumFilters() const noexcept
{
return graph.getNumNodes();
}
const AudioProcessorGraph::Node::Ptr FilterGraph::getNode (const int index) const noexcept
{
return graph.getNode (index);
}
const AudioProcessorGraph::Node::Ptr FilterGraph::getNodeForId (const uint32 uid) const noexcept
{
return graph.getNodeForId (uid);
}
void FilterGraph::addFilter (const PluginDescription* desc, double x, double y)
{
if (desc != nullptr)
{
AudioProcessorGraph::Node* node = nullptr;
String errorMessage;
if (AudioPluginInstance* instance = formatManager.createPluginInstance (*desc, graph.getSampleRate(), graph.getBlockSize(), errorMessage))
node = graph.addNode (instance);
if (node != nullptr)
{
node->properties.set ("x", x);
node->properties.set ("y", y);
changed();
}
else
{
AlertWindow::showMessageBox (AlertWindow::WarningIcon,
TRANS("Couldn't create filter"),
errorMessage);
}
}
}
void FilterGraph::removeFilter (const uint32 id)
{
if (panel != nullptr)
panel->closeCurrentlyOpenWindowsFor (id);
if (graph.removeNode (id))
changed();
}
void FilterGraph::disconnectFilter (const uint32 id)
{
if (graph.disconnectNode (id))
changed();
}
void FilterGraph::removeIllegalConnections()
{
if (graph.removeIllegalConnections())
changed();
}
void FilterGraph::setNodePosition (const int nodeId, double x, double y)
{
const AudioProcessorGraph::Node::Ptr n (graph.getNodeForId (nodeId));
if (n != nullptr)
{
n->properties.set ("x", jlimit (0.0, 1.0, x));
n->properties.set ("y", jlimit (0.0, 1.0, y));
}
}
void FilterGraph::getNodePosition (const int nodeId, double& x, double& y) const
{
x = y = 0;
const AudioProcessorGraph::Node::Ptr n (graph.getNodeForId (nodeId));
if (n != nullptr)
{
x = (double) n->properties ["x"];
y = (double) n->properties ["y"];
}
}
//==============================================================================
int FilterGraph::getNumConnections() const noexcept
{
return graph.getNumConnections();
}
const AudioProcessorGraph::Connection* FilterGraph::getConnection (const int index) const noexcept
{
return graph.getConnection (index);
}
const AudioProcessorGraph::Connection* FilterGraph::getConnectionBetween (uint32 sourceFilterUID, int sourceFilterChannel,
uint32 destFilterUID, int destFilterChannel) const noexcept
{
return graph.getConnectionBetween (sourceFilterUID, sourceFilterChannel,
destFilterUID, destFilterChannel);
}
bool FilterGraph::canConnect (uint32 sourceFilterUID, int sourceFilterChannel,
uint32 destFilterUID, int destFilterChannel) const noexcept
{
return graph.canConnect (sourceFilterUID, sourceFilterChannel,
destFilterUID, destFilterChannel);
}
bool FilterGraph::addConnection (uint32 sourceFilterUID, int sourceFilterChannel,
uint32 destFilterUID, int destFilterChannel)
{
const bool result = graph.addConnection (sourceFilterUID, sourceFilterChannel,
destFilterUID, destFilterChannel);
if (result)
changed();
return result;
}
void FilterGraph::removeConnection (const int index)
{
graph.removeConnection (index);
changed();
}
void FilterGraph::removeConnection (uint32 sourceFilterUID, int sourceFilterChannel,
uint32 destFilterUID, int destFilterChannel)
{
if (graph.removeConnection (sourceFilterUID, sourceFilterChannel,
destFilterUID, destFilterChannel))
changed();
}
void FilterGraph::clear()
{
if (panel != nullptr)
panel->closeAllCurrentlyOpenWindows();
graph.clear();
changed();
}
void FilterGraph::clearKeepingInternals()
{
if (panel != nullptr)
panel->closeAllCurrentlyOpenWindows();
graph.clear();
InternalPluginFormat internalFormat;
addFilter (internalFormat.getDescriptionFor (InternalPluginFormat::audioInputFilter), 0.5f, 0.1f);
addFilter (internalFormat.getDescriptionFor (InternalPluginFormat::midiInputFilter), 0.25f, 0.1f);
addFilter (internalFormat.getDescriptionFor (InternalPluginFormat::audioOutputFilter), 0.5f, 0.9f);
addFilter (internalFormat.getDescriptionFor (InternalPluginFormat::midiOutputFilter), 0.25f, 0.9f);
changed();
}
//==============================================================================
String FilterGraph::getDocumentTitle()
{
if (! getFile().exists())
return "Unnamed";
return getFile().getFileNameWithoutExtension();
}
Result FilterGraph::loadDocument (const File& file)
{
XmlDocument doc (file);
ScopedPointer<XmlElement> xml (doc.getDocumentElement());
if (xml == nullptr || ! xml->hasTagName ("FILTERGRAPH"))
return Result::fail ("Not a valid filter graph file");
restoreFromXml (*xml);
return Result::ok();
}
Result FilterGraph::saveDocument (const File& file)
{
ScopedPointer<XmlElement> xml (createXml());
if (! xml->writeToFile (file, String::empty))
return Result::fail ("Couldn't write to the file");
return Result::ok();
}
File FilterGraph::getLastDocumentOpened()
{
if (appProperties == nullptr)
return File();
RecentlyOpenedFilesList recentFiles;
recentFiles.restoreFromString (appProperties->getUserSettings()
->getValue ("recentFilterGraphFiles"));
return recentFiles.getFile (0);
}
void FilterGraph::setLastDocumentOpened (const File& file)
{
if (appProperties == nullptr)
return;
RecentlyOpenedFilesList recentFiles;
recentFiles.restoreFromString (appProperties->getUserSettings()
->getValue ("recentFilterGraphFiles"));
recentFiles.addFile (file);
appProperties->getUserSettings()
->setValue ("recentFilterGraphFiles", recentFiles.toString());
}
//==============================================================================
static XmlElement* createNodeXml (AudioProcessorGraph::Node* const node) noexcept
{
AudioPluginInstance* plugin = dynamic_cast <AudioPluginInstance*> (node->getProcessor());
if (plugin == nullptr)
{
jassertfalse
return nullptr;
}
XmlElement* e = new XmlElement ("FILTER");
e->setAttribute ("uid", (int) node->nodeId);
e->setAttribute ("x", node->properties ["x"].toString());
e->setAttribute ("y", node->properties ["y"].toString());
e->setAttribute ("uiLastX", node->properties ["uiLastX"].toString());
e->setAttribute ("uiLastY", node->properties ["uiLastY"].toString());
PluginDescription pd;
plugin->fillInPluginDescription (pd);
e->addChildElement (pd.createXml());
XmlElement* state = new XmlElement ("STATE");
MemoryBlock m;
node->getProcessor()->getStateInformation (m);
state->addTextElement (m.toBase64Encoding());
e->addChildElement (state);
return e;
}
void FilterGraph::createNodeFromXml (const XmlElement& xml)
{
PluginDescription pd;
forEachXmlChildElement (xml, e)
{
if (pd.loadFromXml (*e))
break;
}
String errorMessage;
AudioPluginInstance* instance = formatManager.createPluginInstance (pd, graph.getSampleRate(), graph.getBlockSize(), errorMessage);
if (instance == nullptr)
{
// xxx handle ins + outs
}
if (instance == nullptr)
return;
AudioProcessorGraph::Node::Ptr node (graph.addNode (instance, xml.getIntAttribute ("uid")));
if (const XmlElement* const state = xml.getChildByName ("STATE"))
{
MemoryBlock m;
m.fromBase64Encoding (state->getAllSubText());
node->getProcessor()->setStateInformation (m.getData(), (int) m.getSize());
}
node->properties.set ("x", xml.getDoubleAttribute ("x"));
node->properties.set ("y", xml.getDoubleAttribute ("y"));
node->properties.set ("uiLastX", xml.getIntAttribute ("uiLastX"));
node->properties.set ("uiLastY", xml.getIntAttribute ("uiLastY"));
}
XmlElement* FilterGraph::createXml() const
{
XmlElement* xml = new XmlElement ("FILTERGRAPH");
for (int i = 0; i < graph.getNumNodes(); ++i)
xml->addChildElement (createNodeXml (graph.getNode (i)));
for (int i = 0; i < graph.getNumConnections(); ++i)
{
const AudioProcessorGraph::Connection* const fc = graph.getConnection(i);
XmlElement* e = new XmlElement ("CONNECTION");
e->setAttribute ("srcFilter", (int) fc->sourceNodeId);
e->setAttribute ("srcChannel", fc->sourceChannelIndex);
e->setAttribute ("dstFilter", (int) fc->destNodeId);
e->setAttribute ("dstChannel", fc->destChannelIndex);
xml->addChildElement (e);
}
return xml;
}
void FilterGraph::restoreFromXml (const XmlElement& xml)
{
clear();
forEachXmlChildElementWithTagName (xml, e, "FILTER")
{
createNodeFromXml (*e);
changed();
}
forEachXmlChildElementWithTagName (xml, e, "CONNECTION")
{
addConnection ((uint32) e->getIntAttribute ("srcFilter"),
e->getIntAttribute ("srcChannel"),
(uint32) e->getIntAttribute ("dstFilter"),
e->getIntAttribute ("dstChannel"));
}
graph.removeIllegalConnections();
}

+ 0
- 120
source/modules/native-plugins/jucepluginhost/FilterGraph.h View File

@@ -1,120 +0,0 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
Permission is granted to use this software under the terms of either:
a) the GPL v2 (or any later version)
b) the Affero GPL v3
Details of these licenses can be found at: www.gnu.org/licenses
JUCE 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.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.juce.com for more information.
==============================================================================
*/
#ifndef __FILTERGRAPH_JUCEHEADER__
#define __FILTERGRAPH_JUCEHEADER__
class FilterInGraph;
class FilterGraph;
class GraphEditorPanel;
const char* const filenameSuffix = ".filtergraph";
const char* const filenameWildcard = "*.filtergraph";
//==============================================================================
/**
A collection of filters and some connections between them.
*/
class FilterGraph : public FileBasedDocument
{
public:
//==============================================================================
FilterGraph (AudioPluginFormatManager& formatManager);
~FilterGraph();
void ready(ApplicationProperties* appProperties);
void setPanel(GraphEditorPanel* panel);
//==============================================================================
AudioProcessorGraph& getGraph() noexcept { return graph; }
int getNumFilters() const noexcept;
const AudioProcessorGraph::Node::Ptr getNode (const int index) const noexcept;
const AudioProcessorGraph::Node::Ptr getNodeForId (const uint32 uid) const noexcept;
void addFilter (const PluginDescription* desc, double x, double y);
void removeFilter (const uint32 filterUID);
void disconnectFilter (const uint32 filterUID);
void removeIllegalConnections();
void setNodePosition (const int nodeId, double x, double y);
void getNodePosition (const int nodeId, double& x, double& y) const;
//==============================================================================
int getNumConnections() const noexcept;
const AudioProcessorGraph::Connection* getConnection (const int index) const noexcept;
const AudioProcessorGraph::Connection* getConnectionBetween (uint32 sourceFilterUID, int sourceFilterChannel,
uint32 destFilterUID, int destFilterChannel) const noexcept;
bool canConnect (uint32 sourceFilterUID, int sourceFilterChannel,
uint32 destFilterUID, int destFilterChannel) const noexcept;
bool addConnection (uint32 sourceFilterUID, int sourceFilterChannel,
uint32 destFilterUID, int destFilterChannel);
void removeConnection (const int index);
void removeConnection (uint32 sourceFilterUID, int sourceFilterChannel,
uint32 destFilterUID, int destFilterChannel);
void clear();
void clearKeepingInternals();
//==============================================================================
XmlElement* createXml() const;
void restoreFromXml (const XmlElement& xml);
//==============================================================================
String getDocumentTitle();
Result loadDocument (const File& file);
Result saveDocument (const File& file);
File getLastDocumentOpened();
void setLastDocumentOpened (const File& file);
/** The special channel index used to refer to a filter's midi channel.
*/
static const int midiChannelNumber;
private:
//==============================================================================
AudioPluginFormatManager& formatManager;
AudioProcessorGraph graph;
uint32 lastUID;
uint32 getNextUID() noexcept;
void createNodeFromXml (const XmlElement& xml);
ApplicationProperties* appProperties;
GraphEditorPanel* panel;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FilterGraph)
};
#endif // __FILTERGRAPH_JUCEHEADER__

+ 0
- 1127
source/modules/native-plugins/jucepluginhost/GraphEditorPanel.cpp
File diff suppressed because it is too large
View File


+ 0
- 154
source/modules/native-plugins/jucepluginhost/GraphEditorPanel.h View File

@@ -1,154 +0,0 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
Permission is granted to use this software under the terms of either:
a) the GPL v2 (or any later version)
b) the Affero GPL v3
Details of these licenses can be found at: www.gnu.org/licenses
JUCE 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.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.juce.com for more information.
==============================================================================
*/
#ifndef __GRAPHEDITORPANEL_JUCEHEADER__
#define __GRAPHEDITORPANEL_JUCEHEADER__
#include "FilterGraph.h"
class FilterComponent;
class ConnectorComponent;
class PinComponent;
class GraphEditorPanel;
//==============================================================================
/** A desktop window containing a plugin's UI. */
class PluginWindow : public DocumentWindow
{
public:
enum WindowFormatType
{
Normal = 0,
Generic,
Programs,
Parameters
};
PluginWindow (GraphEditorPanel* const panel, Component* pluginEditor, AudioProcessorGraph::Node*, WindowFormatType);
~PluginWindow();
void moved() override;
void closeButtonPressed() override;
private:
AudioProcessorGraph::Node* owner;
WindowFormatType type;
float getDesktopScaleFactor() const override { return 1.0f; }
GraphEditorPanel* const panel;
friend class GraphEditorPanel;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PluginWindow)
};
//==============================================================================
/**
A panel that displays and edits a FilterGraph.
*/
class GraphEditorPanel : public Component,
public ChangeListener
{
public:
GraphEditorPanel (FilterGraph& graph);
~GraphEditorPanel();
void paint (Graphics& g);
void mouseDown (const MouseEvent& e);
void createNewPlugin (const PluginDescription* desc, int x, int y);
FilterComponent* getComponentForFilter (uint32 filterID) const;
ConnectorComponent* getComponentForConnection (const AudioProcessorGraph::Connection& conn) const;
PinComponent* findPinAt (int x, int y) const;
void resized();
void changeListenerCallback (ChangeBroadcaster*);
void updateComponents();
//==============================================================================
void beginConnectorDrag (uint32 sourceFilterID, int sourceFilterChannel,
uint32 destFilterID, int destFilterChannel,
const MouseEvent& e);
void dragConnector (const MouseEvent& e);
void endDraggingConnector (const MouseEvent& e);
//==============================================================================
Array <PluginWindow*> activePluginWindows;
PluginWindow* getWindowFor (AudioProcessorGraph::Node*, PluginWindow::WindowFormatType);
void closeCurrentlyOpenWindowsFor (const uint32 nodeId);
void closeAllCurrentlyOpenWindows();
//==============================================================================
private:
FilterGraph& graph;
ScopedPointer<ConnectorComponent> draggingConnector;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (GraphEditorPanel)
};
//==============================================================================
/**
A panel that embeds a GraphEditorPanel with a midi keyboard at the bottom.
It also manages the graph itself, and plays it.
*/
class GraphDocumentComponent : public Component
{
public:
//==============================================================================
GraphDocumentComponent (FilterGraph& graph);
~GraphDocumentComponent();
//==============================================================================
void createNewPlugin (const PluginDescription* desc, int x, int y);
//==============================================================================
FilterGraph& graph;
//==============================================================================
void resized();
//==============================================================================
void closeAllCurrentlyOpenWindows();
MidiKeyboardState* getMidiState() noexcept;
private:
//==============================================================================
MidiKeyboardState keyState;
GraphEditorPanel* graphPanel;
Component* keyboardComp;
Component* statusBar;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (GraphDocumentComponent)
};
#endif // __GRAPHEDITORPANEL_JUCEHEADER__

+ 0
- 408
source/modules/native-plugins/jucepluginhost/MainHostWindow.cpp View File

@@ -1,408 +0,0 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
Permission is granted to use this software under the terms of either:
a) the GPL v2 (or any later version)
b) the Affero GPL v3
Details of these licenses can be found at: www.gnu.org/licenses
JUCE 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.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.juce.com for more information.
==============================================================================
*/
#include "MainHostWindow.h"
#include "InternalFilters.h"
//==============================================================================
class MainHostWindow::PluginListWindow : public DocumentWindow
{
public:
PluginListWindow (MainHostWindow& owner_, AudioPluginFormatManager& formatManager)
: DocumentWindow ("Available Plugins", Colours::white,
DocumentWindow::minimiseButton | DocumentWindow::closeButton),
owner (owner_)
{
const File deadMansPedalFile (owner.appProperties.getUserSettings()
->getFile().getSiblingFile ("RecentlyCrashedPluginsList"));
setContentOwned (new PluginListComponent (formatManager,
owner.knownPluginList,
deadMansPedalFile,
owner.appProperties.getUserSettings()), true);
setOpaque (true);
setResizable (true, false);
setResizeLimits (300, 400, 800, 1500);
setTopLeftPosition (60, 60);
restoreWindowStateFromString (owner.appProperties.getUserSettings()->getValue ("listWindowPos"));
setUsingNativeTitleBar (true);
setVisible (true);
}
~PluginListWindow()
{
owner.appProperties.getUserSettings()->setValue ("listWindowPos", getWindowStateAsString());
clearContentComponent();
}
void closeButtonPressed()
{
owner.pluginListWindow = nullptr;
}
private:
MainHostWindow& owner;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PluginListWindow)
};
//==============================================================================
MainHostWindow::MainHostWindow (AudioPluginFormatManager& fm, FilterGraph& graph, ApplicationProperties& ap)
: DocumentWindow ("Juce Patchbay", Colours::lightgrey, DocumentWindow::allButtons),
formatManager (fm),
appProperties (ap),
closed (false)
{
LookAndFeel::setDefaultLookAndFeel (&lookAndFeel);
setOpaque (true);
setResizable (true, false);
setResizeLimits (500, 400, 10000, 10000);
centreWithSize (800, 600);
setContentOwned (new GraphDocumentComponent (graph), false);
setUsingNativeTitleBar (true);
restoreWindowStateFromString (appProperties.getUserSettings()->getValue ("mainWindowPos"));
setVisible (true);
ScopedPointer<XmlElement> savedPluginList (appProperties.getUserSettings()->getXmlValue ("pluginList"));
if (savedPluginList != nullptr)
knownPluginList.recreateFromXml (*savedPluginList);
pluginSortMethod = (KnownPluginList::SortMethod) appProperties.getUserSettings()
->getIntValue ("pluginSortMethod", KnownPluginList::sortByManufacturer);
knownPluginList.addChangeListener (this);
addKeyListener (commandManager.getKeyMappings());
//Process::setPriority (Process::HighPriority);
setMenuBar (this);
commandManager.setFirstCommandTarget (this);
commandManager.registerAllCommandsForTarget (this);
menuItemsChanged();
}
MainHostWindow::~MainHostWindow()
{
pluginListWindow = nullptr;
setMenuBar (nullptr);
knownPluginList.removeChangeListener (this);
appProperties.getUserSettings()->setValue ("mainWindowPos", getWindowStateAsString());
clearContentComponent();
LookAndFeel::setDefaultLookAndFeel (nullptr);
}
void MainHostWindow::closeButtonPressed()
{
getGraphEditor()->closeAllCurrentlyOpenWindows();
closed = true;
}
void MainHostWindow::changeListenerCallback (ChangeBroadcaster*)
{
menuItemsChanged();
// save the plugin list every time it gets chnaged, so that if we're scanning
// and it crashes, we've still saved the previous ones
ScopedPointer<XmlElement> savedPluginList (knownPluginList.createXml());
if (savedPluginList != nullptr)
{
appProperties.getUserSettings()->setValue ("pluginList", savedPluginList);
appProperties.saveIfNeeded();
}
}
StringArray MainHostWindow::getMenuBarNames()
{
const char* const names[] = { "File", "Plugins", "Options", nullptr };
return StringArray (names);
}
PopupMenu MainHostWindow::getMenuForIndex (int topLevelMenuIndex, const String& /*menuName*/)
{
PopupMenu menu;
if (topLevelMenuIndex == 0)
{
// "File" menu
menu.addCommandItem (&commandManager, CommandIDs::open);
RecentlyOpenedFilesList recentFiles;
recentFiles.restoreFromString (appProperties.getUserSettings()
->getValue ("recentFilterGraphFiles"));
PopupMenu recentFilesMenu;
recentFiles.createPopupMenuItems (recentFilesMenu, 100, true, true);
menu.addSubMenu ("Open recent file", recentFilesMenu);
menu.addCommandItem (&commandManager, CommandIDs::save);
menu.addCommandItem (&commandManager, CommandIDs::saveAs);
}
else if (topLevelMenuIndex == 1)
{
// "Plugins" menu
PopupMenu pluginsMenu;
addPluginsToMenu (pluginsMenu);
menu.addSubMenu ("Create plugin", pluginsMenu);
menu.addSeparator();
menu.addItem (250, "Delete all plugins");
}
else if (topLevelMenuIndex == 2)
{
// "Options" menu
menu.addCommandItem (&commandManager, CommandIDs::showPluginListEditor);
PopupMenu sortTypeMenu;
sortTypeMenu.addItem (200, "List plugins in default order", true, pluginSortMethod == KnownPluginList::defaultOrder);
sortTypeMenu.addItem (201, "List plugins in alphabetical order", true, pluginSortMethod == KnownPluginList::sortAlphabetically);
sortTypeMenu.addItem (202, "List plugins by category", true, pluginSortMethod == KnownPluginList::sortByCategory);
sortTypeMenu.addItem (203, "List plugins by manufacturer", true, pluginSortMethod == KnownPluginList::sortByManufacturer);
sortTypeMenu.addItem (204, "List plugins based on the directory structure", true, pluginSortMethod == KnownPluginList::sortByFileSystemLocation);
menu.addSubMenu ("Plugin menu type", sortTypeMenu);
}
return menu;
}
void MainHostWindow::menuItemSelected (int menuItemID, int /*topLevelMenuIndex*/)
{
GraphDocumentComponent* const graphEditor = getGraphEditor();
if (menuItemID == 250)
{
if (graphEditor != nullptr)
graphEditor->graph.clearKeepingInternals();
}
else if (menuItemID >= 100 && menuItemID < 200)
{
RecentlyOpenedFilesList recentFiles;
recentFiles.restoreFromString (appProperties.getUserSettings()
->getValue ("recentFilterGraphFiles"));
if (graphEditor != nullptr && graphEditor->graph.saveIfNeededAndUserAgrees() == FileBasedDocument::savedOk)
graphEditor->graph.loadFrom (recentFiles.getFile (menuItemID - 100), true);
}
else if (menuItemID >= 200 && menuItemID < 210)
{
if (menuItemID == 200) pluginSortMethod = KnownPluginList::defaultOrder;
else if (menuItemID == 201) pluginSortMethod = KnownPluginList::sortAlphabetically;
else if (menuItemID == 202) pluginSortMethod = KnownPluginList::sortByCategory;
else if (menuItemID == 203) pluginSortMethod = KnownPluginList::sortByManufacturer;
else if (menuItemID == 204) pluginSortMethod = KnownPluginList::sortByFileSystemLocation;
appProperties.getUserSettings()->setValue ("pluginSortMethod", (int) pluginSortMethod);
menuItemsChanged();
}
else
{
createPlugin (getChosenType (menuItemID),
proportionOfWidth (0.3f + Random::getSystemRandom().nextFloat() * 0.6f),
proportionOfHeight (0.3f + Random::getSystemRandom().nextFloat() * 0.6f));
}
}
void MainHostWindow::createPlugin (const PluginDescription* desc, int x, int y)
{
GraphDocumentComponent* const graphEditor = getGraphEditor();
if (graphEditor != nullptr)
graphEditor->createNewPlugin (desc, x, y);
}
void MainHostWindow::addPluginsToMenu (PopupMenu& m) const
{
knownPluginList.addToMenu (m, pluginSortMethod);
}
const PluginDescription* MainHostWindow::getChosenType (const int menuID) const
{
return knownPluginList.getType (knownPluginList.getIndexChosenByMenu (menuID));
}
//==============================================================================
ApplicationCommandTarget* MainHostWindow::getNextCommandTarget()
{
return findFirstTargetParentComponent();
}
void MainHostWindow::getAllCommands (Array <CommandID>& commands)
{
// this returns the set of all commands that this target can perform..
const CommandID ids[] = { CommandIDs::open,
CommandIDs::save,
CommandIDs::saveAs,
CommandIDs::showPluginListEditor
};
commands.addArray (ids, numElementsInArray (ids));
}
void MainHostWindow::getCommandInfo (const CommandID commandID, ApplicationCommandInfo& result)
{
const String category ("General");
switch (commandID)
{
case CommandIDs::open:
result.setInfo ("Open...",
"Opens a filter graph file",
category, 0);
result.defaultKeypresses.add (KeyPress ('o', ModifierKeys::commandModifier, 0));
break;
case CommandIDs::save:
result.setInfo ("Save",
"Saves the current graph to a file",
category, 0);
result.defaultKeypresses.add (KeyPress ('s', ModifierKeys::commandModifier, 0));
break;
case CommandIDs::saveAs:
result.setInfo ("Save As...",
"Saves a copy of the current graph to a file",
category, 0);
result.defaultKeypresses.add (KeyPress ('s', ModifierKeys::shiftModifier | ModifierKeys::commandModifier, 0));
break;
case CommandIDs::showPluginListEditor:
result.setInfo ("Edit the list of available plug-Ins...", String::empty, category, 0);
result.addDefaultKeypress ('p', ModifierKeys::commandModifier);
break;
default:
break;
}
}
bool MainHostWindow::perform (const InvocationInfo& info)
{
GraphDocumentComponent* const graphEditor = getGraphEditor();
switch (info.commandID)
{
case CommandIDs::open:
if (graphEditor != nullptr && graphEditor->graph.saveIfNeededAndUserAgrees() == FileBasedDocument::savedOk)
graphEditor->graph.loadFromUserSpecifiedFile (true);
break;
case CommandIDs::save:
if (graphEditor != nullptr)
graphEditor->graph.save (true, true);
break;
case CommandIDs::saveAs:
if (graphEditor != nullptr)
graphEditor->graph.saveAs (File::nonexistent, true, true, true);
break;
case CommandIDs::showPluginListEditor:
if (pluginListWindow == nullptr)
pluginListWindow = new PluginListWindow (*this, formatManager);
pluginListWindow->toFront (true);
break;
default:
return false;
}
return true;
}
bool MainHostWindow::isInterestedInFileDrag (const StringArray&)
{
return true;
}
void MainHostWindow::fileDragEnter (const StringArray&, int, int)
{
}
void MainHostWindow::fileDragMove (const StringArray&, int, int)
{
}
void MainHostWindow::fileDragExit (const StringArray&)
{
}
void MainHostWindow::filesDropped (const StringArray& files, int x, int y)
{
GraphDocumentComponent* const graphEditor = getGraphEditor();
if (graphEditor != nullptr)
{
if (files.size() == 1 && File (files[0]).hasFileExtension (filenameSuffix))
{
if (graphEditor->graph.saveIfNeededAndUserAgrees() == FileBasedDocument::savedOk)
graphEditor->graph.loadFrom (File (files[0]), true);
}
else
{
OwnedArray <PluginDescription> typesFound;
knownPluginList.scanAndAddDragAndDroppedFiles (formatManager, files, typesFound);
Point<int> pos (graphEditor->getLocalPoint (this, Point<int> (x, y)));
for (int i = 0; i < jmin (5, typesFound.size()); ++i)
createPlugin (typesFound.getUnchecked(i), pos.getX(), pos.getY());
}
}
}
GraphDocumentComponent* MainHostWindow::getGraphEditor() const
{
return dynamic_cast <GraphDocumentComponent*> (getContentComponent());
}
MidiKeyboardState* MainHostWindow::getMidiState() noexcept
{
return getGraphEditor()->getMidiState();
}
bool MainHostWindow::wasClosedByUser() const noexcept
{
return closed;
}

+ 0
- 103
source/modules/native-plugins/jucepluginhost/MainHostWindow.h View File

@@ -1,103 +0,0 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
Permission is granted to use this software under the terms of either:
a) the GPL v2 (or any later version)
b) the Affero GPL v3
Details of these licenses can be found at: www.gnu.org/licenses
JUCE 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.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.juce.com for more information.
==============================================================================
*/
#ifndef __MAINHOSTWINDOW_JUCEHEADER__
#define __MAINHOSTWINDOW_JUCEHEADER__
#include "FilterGraph.h"
#include "GraphEditorPanel.h"
//==============================================================================
namespace CommandIDs
{
static const int open = 0x30000;
static const int save = 0x30001;
static const int saveAs = 0x30002;
static const int showPluginListEditor = 0x30100;
}
//==============================================================================
/**
*/
class MainHostWindow : public DocumentWindow,
public MenuBarModel,
public ApplicationCommandTarget,
public ChangeListener,
public FileDragAndDropTarget
{
public:
//==============================================================================
MainHostWindow (AudioPluginFormatManager& formatManager, FilterGraph& graph, ApplicationProperties& appProperties);
~MainHostWindow();
//==============================================================================
void closeButtonPressed();
void changeListenerCallback (ChangeBroadcaster*);
bool isInterestedInFileDrag (const StringArray& files);
void fileDragEnter (const StringArray& files, int, int);
void fileDragMove (const StringArray& files, int, int);
void fileDragExit (const StringArray& files);
void filesDropped (const StringArray& files, int, int);
StringArray getMenuBarNames();
PopupMenu getMenuForIndex (int topLevelMenuIndex, const String& menuName);
void menuItemSelected (int menuItemID, int topLevelMenuIndex);
ApplicationCommandTarget* getNextCommandTarget();
void getAllCommands (Array <CommandID>& commands);
void getCommandInfo (CommandID commandID, ApplicationCommandInfo& result);
bool perform (const InvocationInfo& info);
void createPlugin (const PluginDescription* desc, int x, int y);
void addPluginsToMenu (PopupMenu& m) const;
const PluginDescription* getChosenType (const int menuID) const;
GraphDocumentComponent* getGraphEditor() const;
MidiKeyboardState* getMidiState() noexcept;
bool wasClosedByUser() const noexcept;
private:
//==============================================================================
AudioPluginFormatManager& formatManager;
KnownPluginList knownPluginList;
KnownPluginList::SortMethod pluginSortMethod;
class PluginListWindow;
ScopedPointer <PluginListWindow> pluginListWindow;
ApplicationCommandManager commandManager;
ApplicationProperties& appProperties;
LookAndFeel_V3 lookAndFeel;
volatile bool closed;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainHostWindow)
};
#endif // __MAINHOSTWINDOW_JUCEHEADER__

+ 0
- 893
source/modules/native-plugins/jucepluginhost/juce_MidiKeyboardComponent.cpp View File

@@ -1,893 +0,0 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
Permission is granted to use this software under the terms of either:
a) the GPL v2 (or any later version)
b) the Affero GPL v3
Details of these licenses can be found at: www.gnu.org/licenses
JUCE 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.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.juce.com for more information.
==============================================================================
*/
class MidiKeyboardUpDownButton : public Button
{
public:
MidiKeyboardUpDownButton (MidiKeyboardComponent& comp, const int d)
: Button (String::empty),
owner (comp),
delta (d)
{
setOpaque (true);
}
void clicked() override
{
int note = owner.getLowestVisibleKey();
if (delta < 0)
note = (note - 1) / 12;
else
note = note / 12 + 1;
owner.setLowestVisibleKey (note * 12);
}
void paintButton (Graphics& g, bool isMouseOverButton, bool isButtonDown) override
{
owner.drawUpDownButton (g, getWidth(), getHeight(),
isMouseOverButton, isButtonDown,
delta > 0);
}
private:
MidiKeyboardComponent& owner;
const int delta;
JUCE_DECLARE_NON_COPYABLE (MidiKeyboardUpDownButton)
};
//==============================================================================
MidiKeyboardComponent::MidiKeyboardComponent (MidiKeyboardState& s,
const Orientation o)
: state (s),
xOffset (0),
blackNoteLength (1),
keyWidth (16.0f),
orientation (o),
midiChannel (1),
midiInChannelMask (0xffff),
velocity (1.0f),
shouldCheckState (false),
rangeStart (0),
rangeEnd (127),
firstKey (12 * 4.0f),
canScroll (true),
useMousePositionForVelocity (true),
shouldCheckMousePos (false),
keyMappingOctave (6),
octaveNumForMiddleC (3)
{
addChildComponent (scrollDown = new MidiKeyboardUpDownButton (*this, -1));
addChildComponent (scrollUp = new MidiKeyboardUpDownButton (*this, 1));
// initialise with a default set of querty key-mappings..
const char* const keymap = "awsedftgyhujkolp;";
for (int i = 0; keymap[i] != 0; ++i)
setKeyPressForNote (KeyPress (keymap[i], 0, 0), i);
mouseOverNotes.insertMultiple (0, -1, 32);
mouseDownNotes.insertMultiple (0, -1, 32);
setOpaque (true);
setWantsKeyboardFocus (true);
state.addListener (this);
startTimer (1000 / 20);
}
MidiKeyboardComponent::~MidiKeyboardComponent()
{
state.removeListener (this);
}
//==============================================================================
void MidiKeyboardComponent::setKeyWidth (const float widthInPixels)
{
keyWidth = widthInPixels;
resized();
}
void MidiKeyboardComponent::setOrientation (const Orientation newOrientation)
{
if (orientation != newOrientation)
{
orientation = newOrientation;
resized();
}
}
void MidiKeyboardComponent::setAvailableRange (const int lowestNote,
const int highestNote)
{
jassert (lowestNote >= 0 && lowestNote <= 127);
jassert (highestNote >= 0 && highestNote <= 127);
jassert (lowestNote <= highestNote);
if (rangeStart != lowestNote || rangeEnd != highestNote)
{
rangeStart = jlimit (0, 127, lowestNote);
rangeEnd = jlimit (0, 127, highestNote);
firstKey = jlimit ((float) rangeStart, (float) rangeEnd, firstKey);
resized();
}
}
void MidiKeyboardComponent::setLowestVisibleKey (int noteNumber)
{
setLowestVisibleKeyFloat ((float) noteNumber);
}
void MidiKeyboardComponent::setLowestVisibleKeyFloat (float noteNumber)
{
noteNumber = jlimit ((float) rangeStart, (float) rangeEnd, noteNumber);
if (noteNumber != firstKey)
{
const bool hasMoved = (((int) firstKey) != (int) noteNumber);
firstKey = noteNumber;
if (hasMoved)
sendChangeMessage();
resized();
}
}
void MidiKeyboardComponent::setScrollButtonsVisible (const bool newCanScroll)
{
if (canScroll != newCanScroll)
{
canScroll = newCanScroll;
resized();
}
}
void MidiKeyboardComponent::colourChanged()
{
repaint();
}
//==============================================================================
void MidiKeyboardComponent::setMidiChannel (const int midiChannelNumber)
{
jassert (midiChannelNumber > 0 && midiChannelNumber <= 16);
if (midiChannel != midiChannelNumber)
{
resetAnyKeysInUse();
midiChannel = jlimit (1, 16, midiChannelNumber);
}
}
void MidiKeyboardComponent::setMidiChannelsToDisplay (const int midiChannelMask)
{
midiInChannelMask = midiChannelMask;
shouldCheckState = true;
}
void MidiKeyboardComponent::setVelocity (const float v, const bool useMousePosition)
{
velocity = jlimit (0.0f, 1.0f, v);
useMousePositionForVelocity = useMousePosition;
}
//==============================================================================
void MidiKeyboardComponent::getKeyPosition (int midiNoteNumber, const float keyWidth_, int& x, int& w) const
{
jassert (midiNoteNumber >= 0 && midiNoteNumber < 128);
static const float blackNoteWidth = 0.7f;
static const float notePos[] = { 0.0f, 1 - blackNoteWidth * 0.6f,
1.0f, 2 - blackNoteWidth * 0.4f,
2.0f,
3.0f, 4 - blackNoteWidth * 0.7f,
4.0f, 5 - blackNoteWidth * 0.5f,
5.0f, 6 - blackNoteWidth * 0.3f,
6.0f };
const int octave = midiNoteNumber / 12;
const int note = midiNoteNumber % 12;
x = roundToInt (octave * 7.0f * keyWidth_ + notePos [note] * keyWidth_);
w = roundToInt (MidiMessage::isMidiNoteBlack (note) ? blackNoteWidth * keyWidth_ : keyWidth_);
}
void MidiKeyboardComponent::getKeyPos (int midiNoteNumber, int& x, int& w) const
{
getKeyPosition (midiNoteNumber, keyWidth, x, w);
int rx, rw;
getKeyPosition (rangeStart, keyWidth, rx, rw);
x -= xOffset + rx;
}
Rectangle<int> MidiKeyboardComponent::getWhiteNotePos (int noteNum) const
{
int x, w;
getKeyPos (noteNum, x, w);
Rectangle<int> pos;
switch (orientation)
{
case horizontalKeyboard: pos.setBounds (x, 0, w, getHeight()); break;
case verticalKeyboardFacingLeft: pos.setBounds (0, x, getWidth(), w); break;
case verticalKeyboardFacingRight: pos.setBounds (0, getHeight() - x - w, getWidth(), w); break;
default: break;
}
return pos;
}
int MidiKeyboardComponent::getKeyStartPosition (const int midiNoteNumber) const
{
int x, w;
getKeyPos (midiNoteNumber, x, w);
return x;
}
int MidiKeyboardComponent::getNoteAtPosition (Point<int> p)
{
float v;
return xyToNote (p, v);
}
const uint8 MidiKeyboardComponent::whiteNotes[] = { 0, 2, 4, 5, 7, 9, 11 };
const uint8 MidiKeyboardComponent::blackNotes[] = { 1, 3, 6, 8, 10 };
int MidiKeyboardComponent::xyToNote (Point<int> pos, float& mousePositionVelocity)
{
if (! reallyContains (pos, false))
return -1;
Point<int> p (pos);
if (orientation != horizontalKeyboard)
{
p = Point<int> (p.y, p.x);
if (orientation == verticalKeyboardFacingLeft)
p = Point<int> (p.x, getWidth() - p.y);
else
p = Point<int> (getHeight() - p.x, p.y);
}
return remappedXYToNote (p + Point<int> (xOffset, 0), mousePositionVelocity);
}
int MidiKeyboardComponent::remappedXYToNote (Point<int> pos, float& mousePositionVelocity) const
{
if (pos.getY() < blackNoteLength)
{
for (int octaveStart = 12 * (rangeStart / 12); octaveStart <= rangeEnd; octaveStart += 12)
{
for (int i = 0; i < 5; ++i)
{
const int note = octaveStart + blackNotes [i];
if (note >= rangeStart && note <= rangeEnd)
{
int kx, kw;
getKeyPos (note, kx, kw);
kx += xOffset;
if (pos.x >= kx && pos.x < kx + kw)
{
mousePositionVelocity = pos.y / (float) blackNoteLength;
return note;
}
}
}
}
}
for (int octaveStart = 12 * (rangeStart / 12); octaveStart <= rangeEnd; octaveStart += 12)
{
for (int i = 0; i < 7; ++i)
{
const int note = octaveStart + whiteNotes [i];
if (note >= rangeStart && note <= rangeEnd)
{
int kx, kw;
getKeyPos (note, kx, kw);
kx += xOffset;
if (pos.x >= kx && pos.x < kx + kw)
{
const int whiteNoteLength = (orientation == horizontalKeyboard) ? getHeight() : getWidth();
mousePositionVelocity = pos.y / (float) whiteNoteLength;
return note;
}
}
}
}
mousePositionVelocity = 0;
return -1;
}
//==============================================================================
void MidiKeyboardComponent::repaintNote (const int noteNum)
{
if (noteNum >= rangeStart && noteNum <= rangeEnd)
repaint (getWhiteNotePos (noteNum));
}
void MidiKeyboardComponent::paint (Graphics& g)
{
g.fillAll (Colours::white.overlaidWith (findColour (whiteNoteColourId)));
const Colour lineColour (findColour (keySeparatorLineColourId));
const Colour textColour (findColour (textLabelColourId));
int octave;
for (octave = 0; octave < 128; octave += 12)
{
for (int white = 0; white < 7; ++white)
{
const int noteNum = octave + whiteNotes [white];
if (noteNum >= rangeStart && noteNum <= rangeEnd)
{
const Rectangle<int> pos (getWhiteNotePos (noteNum));
drawWhiteNote (noteNum, g, pos.getX(), pos.getY(), pos.getWidth(), pos.getHeight(),
state.isNoteOnForChannels (midiInChannelMask, noteNum),
mouseOverNotes.contains (noteNum), lineColour, textColour);
}
}
}
float x1 = 0.0f, y1 = 0.0f, x2 = 0.0f, y2 = 0.0f;
const int width = getWidth();
const int height = getHeight();
if (orientation == verticalKeyboardFacingLeft)
{
x1 = width - 1.0f;
x2 = width - 5.0f;
}
else if (orientation == verticalKeyboardFacingRight)
x2 = 5.0f;
else
y2 = 5.0f;
int x, w;
getKeyPos (rangeEnd, x, w);
x += w;
const Colour shadowCol (findColour (shadowColourId));
g.setGradientFill (ColourGradient (shadowCol, x1, y1, shadowCol.withAlpha (0.0f), x2, y2, false));
switch (orientation)
{
case horizontalKeyboard: g.fillRect (0, 0, x, 5); break;
case verticalKeyboardFacingLeft: g.fillRect (width - 5, 0, 5, x); break;
case verticalKeyboardFacingRight: g.fillRect (0, 0, 5, x); break;
default: break;
}
g.setColour (lineColour);
switch (orientation)
{
case horizontalKeyboard: g.fillRect (0, height - 1, x, 1); break;
case verticalKeyboardFacingLeft: g.fillRect (0, 0, 1, x); break;
case verticalKeyboardFacingRight: g.fillRect (width - 1, 0, 1, x); break;
default: break;
}
const Colour blackNoteColour (findColour (blackNoteColourId));
for (octave = 0; octave < 128; octave += 12)
{
for (int black = 0; black < 5; ++black)
{
const int noteNum = octave + blackNotes [black];
if (noteNum >= rangeStart && noteNum <= rangeEnd)
{
getKeyPos (noteNum, x, w);
Rectangle<int> pos;
switch (orientation)
{
case horizontalKeyboard: pos.setBounds (x, 0, w, blackNoteLength); break;
case verticalKeyboardFacingLeft: pos.setBounds (width - blackNoteLength, x, blackNoteLength, w); break;
case verticalKeyboardFacingRight: pos.setBounds (0, height - x - w, blackNoteLength, w); break;
default: break;
}
drawBlackNote (noteNum, g, pos.getX(), pos.getY(), pos.getWidth(), pos.getHeight(),
state.isNoteOnForChannels (midiInChannelMask, noteNum),
mouseOverNotes.contains (noteNum), blackNoteColour);
}
}
}
}
void MidiKeyboardComponent::drawWhiteNote (int midiNoteNumber,
Graphics& g, int x, int y, int w, int h,
bool isDown, bool isOver,
const Colour& lineColour,
const Colour& textColour)
{
Colour c (Colours::transparentWhite);
if (isDown) c = findColour (keyDownOverlayColourId);
if (isOver) c = c.overlaidWith (findColour (mouseOverKeyOverlayColourId));
g.setColour (c);
g.fillRect (x, y, w, h);
const String text (getWhiteNoteText (midiNoteNumber));
if (text.isNotEmpty())
{
g.setColour (textColour);
g.setFont (Font (jmin (12.0f, keyWidth * 0.9f)).withHorizontalScale (0.8f));
switch (orientation)
{
case horizontalKeyboard: g.drawFittedText (text, x + 1, y, w - 1, h - 2, Justification::centredBottom, 1); break;
case verticalKeyboardFacingLeft: g.drawFittedText (text, x + 2, y + 2, w - 4, h - 4, Justification::centredLeft, 1); break;
case verticalKeyboardFacingRight: g.drawFittedText (text, x + 2, y + 2, w - 4, h - 4, Justification::centredRight, 1); break;
default: break;
}
}
g.setColour (lineColour);
switch (orientation)
{
case horizontalKeyboard: g.fillRect (x, y, 1, h); break;
case verticalKeyboardFacingLeft: g.fillRect (x, y, w, 1); break;
case verticalKeyboardFacingRight: g.fillRect (x, y + h - 1, w, 1); break;
default: break;
}
if (midiNoteNumber == rangeEnd)
{
switch (orientation)
{
case horizontalKeyboard: g.fillRect (x + w, y, 1, h); break;
case verticalKeyboardFacingLeft: g.fillRect (x, y + h, w, 1); break;
case verticalKeyboardFacingRight: g.fillRect (x, y - 1, w, 1); break;
default: break;
}
}
}
void MidiKeyboardComponent::drawBlackNote (int /*midiNoteNumber*/,
Graphics& g, int x, int y, int w, int h,
bool isDown, bool isOver,
const Colour& noteFillColour)
{
Colour c (noteFillColour);
if (isDown) c = c.overlaidWith (findColour (keyDownOverlayColourId));
if (isOver) c = c.overlaidWith (findColour (mouseOverKeyOverlayColourId));
g.setColour (c);
g.fillRect (x, y, w, h);
if (isDown)
{
g.setColour (noteFillColour);
g.drawRect (x, y, w, h);
}
else
{
g.setColour (c.brighter());
const int xIndent = jmax (1, jmin (w, h) / 8);
switch (orientation)
{
case horizontalKeyboard: g.fillRect (x + xIndent, y, w - xIndent * 2, 7 * h / 8); break;
case verticalKeyboardFacingLeft: g.fillRect (x + w / 8, y + xIndent, w - w / 8, h - xIndent * 2); break;
case verticalKeyboardFacingRight: g.fillRect (x, y + xIndent, 7 * w / 8, h - xIndent * 2); break;
default: break;
}
}
}
void MidiKeyboardComponent::setOctaveForMiddleC (const int octaveNum)
{
octaveNumForMiddleC = octaveNum;
repaint();
}
String MidiKeyboardComponent::getWhiteNoteText (const int midiNoteNumber)
{
if (keyWidth > 11.0f && midiNoteNumber % 12 == 0)
return MidiMessage::getMidiNoteName (midiNoteNumber, true, true, octaveNumForMiddleC);
return String::empty;
}
void MidiKeyboardComponent::drawUpDownButton (Graphics& g, int w, int h,
const bool mouseOver,
const bool buttonDown,
const bool movesOctavesUp)
{
g.fillAll (findColour (upDownButtonBackgroundColourId));
float angle;
switch (orientation)
{
case horizontalKeyboard: angle = movesOctavesUp ? 0.0f : 0.5f; break;
case verticalKeyboardFacingLeft: angle = movesOctavesUp ? 0.25f : 0.75f; break;
case verticalKeyboardFacingRight: angle = movesOctavesUp ? 0.75f : 0.25f; break;
default: jassertfalse; angle = 0; break;
}
Path path;
path.addTriangle (0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.5f);
path.applyTransform (AffineTransform::rotation (float_Pi * 2.0f * angle, 0.5f, 0.5f));
g.setColour (findColour (upDownButtonArrowColourId)
.withAlpha (buttonDown ? 1.0f : (mouseOver ? 0.6f : 0.4f)));
g.fillPath (path, path.getTransformToScaleToFit (1.0f, 1.0f, w - 2.0f, h - 2.0f, true));
}
void MidiKeyboardComponent::resized()
{
int w = getWidth();
int h = getHeight();
if (w > 0 && h > 0)
{
if (orientation != horizontalKeyboard)
std::swap (w, h);
blackNoteLength = roundToInt (h * 0.7f);
int kx2, kw2;
getKeyPos (rangeEnd, kx2, kw2);
kx2 += kw2;
if ((int) firstKey != rangeStart)
{
int kx1, kw1;
getKeyPos (rangeStart, kx1, kw1);
if (kx2 - kx1 <= w)
{
firstKey = (float) rangeStart;
sendChangeMessage();
repaint();
}
}
scrollDown->setVisible (canScroll && firstKey > (float) rangeStart);
xOffset = 0;
if (canScroll)
{
const int scrollButtonW = jmin (12, w / 2);
Rectangle<int> r (getLocalBounds());
if (orientation == horizontalKeyboard)
{
scrollDown->setBounds (r.removeFromLeft (scrollButtonW));
scrollUp ->setBounds (r.removeFromRight (scrollButtonW));
}
else if (orientation == verticalKeyboardFacingLeft)
{
scrollDown->setBounds (r.removeFromTop (scrollButtonW));
scrollUp ->setBounds (r.removeFromBottom (scrollButtonW));
}
else
{
scrollDown->setBounds (r.removeFromBottom (scrollButtonW));
scrollUp ->setBounds (r.removeFromTop (scrollButtonW));
}
int endOfLastKey, kw;
getKeyPos (rangeEnd, endOfLastKey, kw);
endOfLastKey += kw;
float mousePositionVelocity;
const int spaceAvailable = w;
const int lastStartKey = remappedXYToNote (Point<int> (endOfLastKey - spaceAvailable, 0), mousePositionVelocity) + 1;
if (lastStartKey >= 0 && ((int) firstKey) > lastStartKey)
{
firstKey = (float) jlimit (rangeStart, rangeEnd, lastStartKey);
sendChangeMessage();
}
int newOffset = 0;
getKeyPos ((int) firstKey, newOffset, kw);
xOffset = newOffset;
}
else
{
firstKey = (float) rangeStart;
}
getKeyPos (rangeEnd, kx2, kw2);
scrollUp->setVisible (canScroll && kx2 > w);
repaint();
}
}
//==============================================================================
void MidiKeyboardComponent::handleNoteOn (MidiKeyboardState*, int /*midiChannel*/, int /*midiNoteNumber*/, float /*velocity*/)
{
shouldCheckState = true; // (probably being called from the audio thread, so avoid blocking in here)
}
void MidiKeyboardComponent::handleNoteOff (MidiKeyboardState*, int /*midiChannel*/, int /*midiNoteNumber*/)
{
shouldCheckState = true; // (probably being called from the audio thread, so avoid blocking in here)
}
//==============================================================================
void MidiKeyboardComponent::resetAnyKeysInUse()
{
if (! keysPressed.isZero())
{
for (int i = 128; --i >= 0;)
if (keysPressed[i])
state.noteOff (midiChannel, i);
keysPressed.clear();
}
for (int i = mouseDownNotes.size(); --i >= 0;)
{
const int noteDown = mouseDownNotes.getUnchecked(i);
if (noteDown >= 0)
{
state.noteOff (midiChannel, noteDown);
mouseDownNotes.set (i, -1);
}
mouseOverNotes.set (i, -1);
}
}
void MidiKeyboardComponent::updateNoteUnderMouse (const MouseEvent& e, bool isDown)
{
updateNoteUnderMouse (e.getPosition(), isDown, e.source.getIndex());
}
void MidiKeyboardComponent::updateNoteUnderMouse (Point<int> pos, bool isDown, int fingerNum)
{
float mousePositionVelocity = 0.0f;
const int newNote = xyToNote (pos, mousePositionVelocity);
const int oldNote = mouseOverNotes.getUnchecked (fingerNum);
if (oldNote != newNote)
{
repaintNote (oldNote);
repaintNote (newNote);
mouseOverNotes.set (fingerNum, newNote);
}
int oldNoteDown = mouseDownNotes.getUnchecked (fingerNum);
if (isDown)
{
if (newNote != oldNoteDown)
{
if (oldNoteDown >= 0)
{
mouseDownNotes.set (fingerNum, -1);
if (! mouseDownNotes.contains (oldNoteDown))
state.noteOff (midiChannel, oldNoteDown);
}
if (newNote >= 0)
{
if (! useMousePositionForVelocity)
mousePositionVelocity = 1.0f;
state.noteOn (midiChannel, newNote, mousePositionVelocity * velocity);
mouseDownNotes.set (fingerNum, newNote);
}
}
}
else if (oldNoteDown >= 0)
{
mouseDownNotes.set (fingerNum, -1);
if (! mouseDownNotes.contains (oldNoteDown))
state.noteOff (midiChannel, oldNoteDown);
}
}
void MidiKeyboardComponent::mouseMove (const MouseEvent& e)
{
updateNoteUnderMouse (e, false);
shouldCheckMousePos = false;
}
void MidiKeyboardComponent::mouseDrag (const MouseEvent& e)
{
float mousePositionVelocity;
const int newNote = xyToNote (e.getPosition(), mousePositionVelocity);
if (newNote >= 0)
mouseDraggedToKey (newNote, e);
updateNoteUnderMouse (e, true);
}
bool MidiKeyboardComponent::mouseDownOnKey (int, const MouseEvent&) { return true; }
void MidiKeyboardComponent::mouseDraggedToKey (int, const MouseEvent&) {}
void MidiKeyboardComponent::mouseUpOnKey (int, const MouseEvent&) {}
void MidiKeyboardComponent::mouseDown (const MouseEvent& e)
{
float mousePositionVelocity;
const int newNote = xyToNote (e.getPosition(), mousePositionVelocity);
if (newNote >= 0 && mouseDownOnKey (newNote, e))
{
updateNoteUnderMouse (e, true);
shouldCheckMousePos = true;
}
}
void MidiKeyboardComponent::mouseUp (const MouseEvent& e)
{
updateNoteUnderMouse (e, false);
shouldCheckMousePos = false;
float mousePositionVelocity;
const int note = xyToNote (e.getPosition(), mousePositionVelocity);
if (note >= 0)
mouseUpOnKey (note, e);
}
void MidiKeyboardComponent::mouseEnter (const MouseEvent& e)
{
updateNoteUnderMouse (e, false);
}
void MidiKeyboardComponent::mouseExit (const MouseEvent& e)
{
updateNoteUnderMouse (e, false);
}
void MidiKeyboardComponent::mouseWheelMove (const MouseEvent&, const MouseWheelDetails& wheel)
{
const float amount = (orientation == horizontalKeyboard && wheel.deltaX != 0)
? wheel.deltaX : (orientation == verticalKeyboardFacingLeft ? wheel.deltaY
: -wheel.deltaY);
setLowestVisibleKeyFloat (firstKey - amount * keyWidth);
}
void MidiKeyboardComponent::timerCallback()
{
if (shouldCheckState)
{
shouldCheckState = false;
for (int i = rangeStart; i <= rangeEnd; ++i)
{
if (keysCurrentlyDrawnDown[i] != state.isNoteOnForChannels (midiInChannelMask, i))
{
keysCurrentlyDrawnDown.setBit (i, state.isNoteOnForChannels (midiInChannelMask, i));
repaintNote (i);
}
}
}
if (shouldCheckMousePos)
{
const Array<MouseInputSource>& mouseSources = Desktop::getInstance().getMouseSources();
for (MouseInputSource* mi = mouseSources.begin(), * const e = mouseSources.end(); mi != e; ++mi)
updateNoteUnderMouse (getLocalPoint (nullptr, mi->getScreenPosition()).roundToInt(), mi->isDragging(), mi->getIndex());
}
}
//==============================================================================
void MidiKeyboardComponent::clearKeyMappings()
{
resetAnyKeysInUse();
keyPressNotes.clear();
keyPresses.clear();
}
void MidiKeyboardComponent::setKeyPressForNote (const KeyPress& key,
const int midiNoteOffsetFromC)
{
removeKeyPressForNote (midiNoteOffsetFromC);
keyPressNotes.add (midiNoteOffsetFromC);
keyPresses.add (key);
}
void MidiKeyboardComponent::removeKeyPressForNote (const int midiNoteOffsetFromC)
{
for (int i = keyPressNotes.size(); --i >= 0;)
{
if (keyPressNotes.getUnchecked (i) == midiNoteOffsetFromC)
{
keyPressNotes.remove (i);
keyPresses.remove (i);
}
}
}
void MidiKeyboardComponent::setKeyPressBaseOctave (const int newOctaveNumber)
{
jassert (newOctaveNumber >= 0 && newOctaveNumber <= 10);
keyMappingOctave = newOctaveNumber;
}
bool MidiKeyboardComponent::keyStateChanged (const bool /*isKeyDown*/)
{
bool keyPressUsed = false;
for (int i = keyPresses.size(); --i >= 0;)
{
const int note = 12 * keyMappingOctave + keyPressNotes.getUnchecked (i);
if (keyPresses.getReference(i).isCurrentlyDown())
{
if (! keysPressed [note])
{
keysPressed.setBit (note);
state.noteOn (midiChannel, note, velocity);
keyPressUsed = true;
}
}
else
{
if (keysPressed [note])
{
keysPressed.clearBit (note);
state.noteOff (midiChannel, note);
keyPressUsed = true;
}
}
}
return keyPressUsed;
}
void MidiKeyboardComponent::focusLost (FocusChangeType)
{
resetAnyKeysInUse();
}

+ 0
- 409
source/modules/native-plugins/jucepluginhost/juce_MidiKeyboardComponent.h View File

@@ -1,409 +0,0 @@
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
Permission is granted to use this software under the terms of either:
a) the GPL v2 (or any later version)
b) the Affero GPL v3
Details of these licenses can be found at: www.gnu.org/licenses
JUCE 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.
------------------------------------------------------------------------------
To release a closed-source product which uses JUCE, commercial licenses are
available: visit www.juce.com for more information.
==============================================================================
*/
#ifndef JUCE_MIDIKEYBOARDCOMPONENT_H_INCLUDED
#define JUCE_MIDIKEYBOARDCOMPONENT_H_INCLUDED
//==============================================================================
/**
A component that displays a piano keyboard, whose notes can be clicked on.
This component will mimic a physical midi keyboard, showing the current state of
a MidiKeyboardState object. When the on-screen keys are clicked on, it will play these
notes by calling the noteOn() and noteOff() methods of its MidiKeyboardState object.
Another feature is that the computer keyboard can also be used to play notes. By
default it maps the top two rows of a standard querty keyboard to the notes, but
these can be remapped if needed. It will only respond to keypresses when it has
the keyboard focus, so to disable this feature you can call setWantsKeyboardFocus (false).
The component is also a ChangeBroadcaster, so if you want to be informed when the
keyboard is scrolled, you can register a ChangeListener for callbacks.
@see MidiKeyboardState
*/
class JUCE_API MidiKeyboardComponent : public Component,
public MidiKeyboardStateListener,
public ChangeBroadcaster,
private Timer
{
public:
//==============================================================================
/** The direction of the keyboard.
@see setOrientation
*/
enum Orientation
{
horizontalKeyboard,
verticalKeyboardFacingLeft,
verticalKeyboardFacingRight,
};
/** Creates a MidiKeyboardComponent.
@param state the midi keyboard model that this component will represent
@param orientation whether the keyboard is horizonal or vertical
*/
MidiKeyboardComponent (MidiKeyboardState& state,
Orientation orientation);
/** Destructor. */
~MidiKeyboardComponent();
//==============================================================================
/** Changes the velocity used in midi note-on messages that are triggered by clicking
on the component.
Values are 0 to 1.0, where 1.0 is the heaviest.
@see setMidiChannel
*/
void setVelocity (float velocity, bool useMousePositionForVelocity);
/** Changes the midi channel number that will be used for events triggered by clicking
on the component.
The channel must be between 1 and 16 (inclusive). This is the channel that will be
passed on to the MidiKeyboardState::noteOn() method when the user clicks the component.
Although this is the channel used for outgoing events, the component can display
incoming events from more than one channel - see setMidiChannelsToDisplay()
@see setVelocity
*/
void setMidiChannel (int midiChannelNumber);
/** Returns the midi channel that the keyboard is using for midi messages.
@see setMidiChannel
*/
int getMidiChannel() const noexcept { return midiChannel; }
/** Sets a mask to indicate which incoming midi channels should be represented by
key movements.
The mask is a set of bits, where bit 0 = midi channel 1, bit 1 = midi channel 2, etc.
If the MidiKeyboardState has a key down for any of the channels whose bits are set
in this mask, the on-screen keys will also go down.
By default, this mask is set to 0xffff (all channels displayed).
@see setMidiChannel
*/
void setMidiChannelsToDisplay (int midiChannelMask);
/** Returns the current set of midi channels represented by the component.
This is the value that was set with setMidiChannelsToDisplay().
*/
int getMidiChannelsToDisplay() const noexcept { return midiInChannelMask; }
//==============================================================================
/** Changes the width used to draw the white keys. */
void setKeyWidth (float widthInPixels);
/** Returns the width that was set by setKeyWidth(). */
float getKeyWidth() const noexcept { return keyWidth; }
/** Changes the keyboard's current direction. */
void setOrientation (Orientation newOrientation);
/** Returns the keyboard's current direction. */
Orientation getOrientation() const noexcept { return orientation; }
/** Sets the range of midi notes that the keyboard will be limited to.
By default the range is 0 to 127 (inclusive), but you can limit this if you
only want a restricted set of the keys to be shown.
Note that the values here are inclusive and must be between 0 and 127.
*/
void setAvailableRange (int lowestNote,
int highestNote);
/** Returns the first note in the available range.
@see setAvailableRange
*/
int getRangeStart() const noexcept { return rangeStart; }
/** Returns the last note in the available range.
@see setAvailableRange
*/
int getRangeEnd() const noexcept { return rangeEnd; }
/** If the keyboard extends beyond the size of the component, this will scroll
it to show the given key at the start.
Whenever the keyboard's position is changed, this will use the ChangeBroadcaster
base class to send a callback to any ChangeListeners that have been registered.
*/
void setLowestVisibleKey (int noteNumber);
/** Returns the number of the first key shown in the component.
@see setLowestVisibleKey
*/
int getLowestVisibleKey() const noexcept { return (int) firstKey; }
/** Returns the length of the black notes.
This will be their vertical or horizontal length, depending on the keyboard's orientation.
*/
int getBlackNoteLength() const noexcept { return blackNoteLength; }
/** If set to true, then scroll buttons will appear at either end of the keyboard
if there are too many notes to fit them all in the component at once.
*/
void setScrollButtonsVisible (bool canScroll);
//==============================================================================
/** A set of colour IDs to use to change the colour of various aspects of the keyboard.
These constants can be used either via the Component::setColour(), or LookAndFeel::setColour()
methods.
@see Component::setColour, Component::findColour, LookAndFeel::setColour, LookAndFeel::findColour
*/
enum ColourIds
{
whiteNoteColourId = 0x1005000,
blackNoteColourId = 0x1005001,
keySeparatorLineColourId = 0x1005002,
mouseOverKeyOverlayColourId = 0x1005003, /**< This colour will be overlaid on the normal note colour. */
keyDownOverlayColourId = 0x1005004, /**< This colour will be overlaid on the normal note colour. */
textLabelColourId = 0x1005005,
upDownButtonBackgroundColourId = 0x1005006,
upDownButtonArrowColourId = 0x1005007,
shadowColourId = 0x1005008
};
/** Returns the position within the component of the left-hand edge of a key.
Depending on the keyboard's orientation, this may be a horizontal or vertical
distance, in either direction.
*/
int getKeyStartPosition (int midiNoteNumber) const;
/** Returns the key at a given coordinate. */
int getNoteAtPosition (Point<int> position);
//==============================================================================
/** Deletes all key-mappings.
@see setKeyPressForNote
*/
void clearKeyMappings();
/** Maps a key-press to a given note.
@param key the key that should trigger the note
@param midiNoteOffsetFromC how many semitones above C the triggered note should
be. The actual midi note that gets played will be
this value + (12 * the current base octave). To change
the base octave, see setKeyPressBaseOctave()
*/
void setKeyPressForNote (const KeyPress& key,
int midiNoteOffsetFromC);
/** Removes any key-mappings for a given note.
For a description of what the note number means, see setKeyPressForNote().
*/
void removeKeyPressForNote (int midiNoteOffsetFromC);
/** Changes the base note above which key-press-triggered notes are played.
The set of key-mappings that trigger notes can be moved up and down to cover
the entire scale using this method.
The value passed in is an octave number between 0 and 10 (inclusive), and
indicates which C is the base note to which the key-mapped notes are
relative.
*/
void setKeyPressBaseOctave (int newOctaveNumber);
/** This sets the octave number which is shown as the octave number for middle C.
This affects only the default implementation of getWhiteNoteText(), which
passes this octave number to MidiMessage::getMidiNoteName() in order to
get the note text. See MidiMessage::getMidiNoteName() for more info about
the parameter.
By default this value is set to 3.
@see getOctaveForMiddleC
*/
void setOctaveForMiddleC (int octaveNumForMiddleC);
/** This returns the value set by setOctaveForMiddleC().
@see setOctaveForMiddleC
*/
int getOctaveForMiddleC() const noexcept { return octaveNumForMiddleC; }
//==============================================================================
/** @internal */
void paint (Graphics&) override;
/** @internal */
void resized() override;
/** @internal */
void mouseMove (const MouseEvent&) override;
/** @internal */
void mouseDrag (const MouseEvent&) override;
/** @internal */
void mouseDown (const MouseEvent&) override;
/** @internal */
void mouseUp (const MouseEvent&) override;
/** @internal */
void mouseEnter (const MouseEvent&) override;
/** @internal */
void mouseExit (const MouseEvent&) override;
/** @internal */
void mouseWheelMove (const MouseEvent&, const MouseWheelDetails&) override;
/** @internal */
void timerCallback() override;
/** @internal */
bool keyStateChanged (bool isKeyDown) override;
/** @internal */
void focusLost (FocusChangeType) override;
/** @internal */
void handleNoteOn (MidiKeyboardState*, int midiChannel, int midiNoteNumber, float velocity) override;
/** @internal */
void handleNoteOff (MidiKeyboardState*, int midiChannel, int midiNoteNumber) override;
/** @internal */
void colourChanged() override;
protected:
//==============================================================================
/** Draws a white note in the given rectangle.
isOver indicates whether the mouse is over the key, isDown indicates whether the key is
currently pressed down.
When doing this, be sure to note the keyboard's orientation.
*/
virtual void drawWhiteNote (int midiNoteNumber,
Graphics& g,
int x, int y, int w, int h,
bool isDown, bool isOver,
const Colour& lineColour,
const Colour& textColour);
/** Draws a black note in the given rectangle.
isOver indicates whether the mouse is over the key, isDown indicates whether the key is
currently pressed down.
When doing this, be sure to note the keyboard's orientation.
*/
virtual void drawBlackNote (int midiNoteNumber,
Graphics& g,
int x, int y, int w, int h,
bool isDown, bool isOver,
const Colour& noteFillColour);
/** Allows text to be drawn on the white notes.
By default this is used to label the C in each octave, but could be used for other things.
@see setOctaveForMiddleC
*/
virtual String getWhiteNoteText (const int midiNoteNumber);
/** Draws the up and down buttons that change the base note. */
virtual void drawUpDownButton (Graphics& g, int w, int h,
const bool isMouseOver,
const bool isButtonPressed,
const bool movesOctavesUp);
/** Callback when the mouse is clicked on a key.
You could use this to do things like handle right-clicks on keys, etc.
Return true if you want the click to trigger the note, or false if you
want to handle it yourself and not have the note played.
@see mouseDraggedToKey
*/
virtual bool mouseDownOnKey (int midiNoteNumber, const MouseEvent& e);
/** Callback when the mouse is dragged from one key onto another.
@see mouseDownOnKey
*/
virtual void mouseDraggedToKey (int midiNoteNumber, const MouseEvent& e);
/** Callback when the mouse is released from a key.
@see mouseDownOnKey
*/
virtual void mouseUpOnKey (int midiNoteNumber, const MouseEvent& e);
/** Calculates the positon of a given midi-note.
This can be overridden to create layouts with custom key-widths.
@param midiNoteNumber the note to find
@param keyWidth the desired width in pixels of one key - see setKeyWidth()
@param x the x position of the left-hand edge of the key (this method
always works in terms of a horizontal keyboard)
@param w the width of the key
*/
virtual void getKeyPosition (int midiNoteNumber, float keyWidth,
int& x, int& w) const;
private:
//==============================================================================
friend class MidiKeyboardUpDownButton;
MidiKeyboardState& state;
int xOffset, blackNoteLength;
float keyWidth;
Orientation orientation;
int midiChannel, midiInChannelMask;
float velocity;
Array<int> mouseOverNotes, mouseDownNotes;
BigInteger keysPressed, keysCurrentlyDrawnDown;
bool shouldCheckState;
int rangeStart, rangeEnd;
float firstKey;
bool canScroll, useMousePositionForVelocity, shouldCheckMousePos;
ScopedPointer<Button> scrollDown, scrollUp;
Array<KeyPress> keyPresses;
Array<int> keyPressNotes;
int keyMappingOctave, octaveNumForMiddleC;
static const uint8 whiteNotes[];
static const uint8 blackNotes[];
void getKeyPos (int midiNoteNumber, int& x, int& w) const;
int xyToNote (Point<int>, float& mousePositionVelocity);
int remappedXYToNote (Point<int>, float& mousePositionVelocity) const;
void resetAnyKeysInUse();
void updateNoteUnderMouse (Point<int>, bool isDown, int fingerNum);
void updateNoteUnderMouse (const MouseEvent&, bool isDown);
void repaintNote (const int midiNoteNumber);
void setLowestVisibleKeyFloat (float noteNumber);
Rectangle<int> getWhiteNotePos (int noteNumber) const;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MidiKeyboardComponent)
};
#endif // JUCE_MIDIKEYBOARDCOMPONENT_H_INCLUDED

+ 2
- 2
source/plugin/Makefile View File

@@ -44,7 +44,7 @@ endif
# --------------------------------------------------------------
# Coomon

ifeq ($(HAVE_JUCE_UI),true)
ifeq ($(MACOS_OR_WIN32),true)
LINK_FLAGS += $(JUCE_AUDIO_PROCESSORS_LIBS)
LINK_FLAGS += $(JUCE_DATA_STRUCTURES_LIBS)
LINK_FLAGS += $(JUCE_EVENTS_LIBS)
@@ -75,7 +75,7 @@ LIBS += ../modules/juce_audio_formats.a
LIBS += ../modules/juce_core.a
LIBS += ../modules/rtmempool.a

ifeq ($(HAVE_JUCE_UI),true)
ifeq ($(MACOS_OR_WIN32),true)
LIBS += ../modules/juce_audio_processors.a
LIBS += ../modules/juce_data_structures.a
LIBS += ../modules/juce_events.a


+ 19
- 100
source/plugin/carla-native-lv2.cpp View File

@@ -18,7 +18,7 @@
#define CARLA_NATIVE_PLUGIN_LV2
#include "carla-native-base.cpp"

#include "CarlaMathUtils.hpp"
// #include "CarlaMathUtils.hpp"
#include "CarlaString.hpp"

#include "lv2/atom.h"
@@ -37,68 +37,11 @@
#include "juce_audio_basics.h"
using juce::FloatVectorOperations;

#ifdef HAVE_JUCE_UI

#include "juce_gui_basics.h"

using juce::Array;
using juce::JUCEApplicationBase;
using juce::MessageManager;
//using juce::MessageManagerLock;
using juce::Thread;

using juce::initialiseJuce_GUI;
using juce::shutdownJuce_GUI;

static Array<void*> gActivePlugins;

# ifdef CARLA_OS_LINUX
// -----------------------------------------------------------------------
// Juce Message Thread

class JuceMessageThread : public Thread
{
public:
JuceMessageThread()
: Thread("JuceMessageThread"),
fInitialised(false)
{
startThread(7);

while (! fInitialised)
sleep(1);
}

~JuceMessageThread()
{
signalThreadShouldExit();
JUCEApplicationBase::quit();
waitForThreadToExit(5000);
clearSingletonInstance();
}

void run() override
{
initialiseJuce_GUI();

MessageManager::getInstance()->setCurrentThreadAsMessageThread();
fInitialised = true;

while ((! threadShouldExit()) && MessageManager::getInstance()->runDispatchLoopUntil(250))
{}
}

juce_DeclareSingleton(JuceMessageThread, false);

private:
bool fInitialised;
};

juce_ImplementSingleton(JuceMessageThread)
# endif
#if defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN)
# include "juce_gui_basics.h"
static juce::Array<void*> gActivePlugins;
#endif


// -----------------------------------------------------------------------
// LV2 descriptor functions

@@ -111,9 +54,6 @@ public:
: fHandle(nullptr),
fDescriptor(desc),
fMidiEventCount(0),
#ifdef HAVE_JUCE_UI
fUiWasShown(false),
#endif
fIsProcessing(false),
fVolume(1.0f),
fDryWet(1.0f),
@@ -149,6 +89,12 @@ public:
fHost.ui_save_file = host_ui_save_file;
fHost.dispatcher = host_dispatcher;

#if defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN)
if (gActivePlugins.size() == 0)
juce::initialiseJuce_GUI();
gActivePlugins.add(this);
#endif

const LV2_Options_Option* options = nullptr;
const LV2_URID_Map* uridMap = nullptr;
const LV2_URID_Unmap* uridUnmap = nullptr;
@@ -208,15 +154,20 @@ public:
~NativePlugin()
{
CARLA_ASSERT(fHandle == nullptr);
#ifdef HAVE_JUCE_UI
CARLA_ASSERT(! fUiWasShown);
#endif

if (fHost.resourceDir != nullptr)
{
delete[] fHost.resourceDir;
fHost.resourceDir = nullptr;
}

#if defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN)
jassert(gActivePlugins.contains(this));
gActivePlugins.removeFirstMatchingValue(this);

if (gActivePlugins.size() == 0)
juce::shutdownJuce_GUI();
#endif
}

bool init()
@@ -276,20 +227,6 @@ public:
fDescriptor->cleanup(fHandle);

fHandle = nullptr;

#ifdef HAVE_JUCE_UI
if (fUiWasShown)
{
CARLA_SAFE_ASSERT_RETURN(gActivePlugins.contains(this),);

gActivePlugins.removeFirstMatchingValue(this);

if (gActivePlugins.size() == 0)
JuceMessageThread::deleteInstance();

fUiWasShown = false;
}
#endif
}

void lv2_run(const uint32_t frames)
@@ -729,22 +666,7 @@ protected:
void handleUiShow()
{
if (fDescriptor->ui_show != nullptr)
{
#ifdef HAVE_JUCE_UI
if (fDescriptor->hints & PLUGIN_NEEDS_UI_JUCE)
{
if (gActivePlugins.size() == 0)
JuceMessageThread::getInstance();

fDescriptor->ui_show(fHandle, true);

fUiWasShown = true;
gActivePlugins.add(this);
}
else
#endif
fDescriptor->ui_show(fHandle, true);
}
fDescriptor->ui_show(fHandle, true);

fUI.isVisible = true;
}
@@ -908,9 +830,6 @@ private:
NativeMidiEvent fMidiEvents[kMaxMidiEvents*2];
NativeTimeInfo fTimeInfo;

#ifdef HAVE_JUCE_UI
bool fUiWasShown;
#endif
bool fIsProcessing;
float fVolume;
float fDryWet;


+ 0
- 1
source/tests/CarlaUtils2.cpp View File

@@ -19,7 +19,6 @@
# error Build this file with debug ON please
#endif

#define HAVE_JUCE
#define VESTIGE_HEADER

#include "CarlaUtils.hpp"


+ 0
- 132
source/utils/JuceInternalFilters.hpp View File

@@ -1,132 +0,0 @@
/*
* Juce Internal Filters
* Copyright (c) 2013 Raw Material Software Ltd.
* Copyright (C) 2014 Filipe Coelho <falktx@falktx.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* For a full copy of the GNU General Public License see the doc/GPL.txt file.
*/
#ifndef JUCE_INTERNAL_FILTERS_HPP_INCLUDED
#define JUCE_INTERNAL_FILTERS_HPP_INCLUDED
#include "juce_audio_processors.h"
// -----------------------------------------------------------------------
namespace juce {
class InternalPluginFormat : public AudioPluginFormat
{
public:
enum InternalFilterType
{
audioInputFilter = 0,
audioOutputFilter,
midiInputFilter,
midiOutputFilter,
endOfFilterTypes
};
InternalPluginFormat()
{
{
AudioProcessorGraph::AudioGraphIOProcessor p(AudioProcessorGraph::AudioGraphIOProcessor::audioOutputNode);
p.fillInPluginDescription(audioOutDesc);
}
{
AudioProcessorGraph::AudioGraphIOProcessor p(AudioProcessorGraph::AudioGraphIOProcessor::audioInputNode);
p.fillInPluginDescription(audioInDesc);
}
{
AudioProcessorGraph::AudioGraphIOProcessor p(AudioProcessorGraph::AudioGraphIOProcessor::midiInputNode);
p.fillInPluginDescription(midiInDesc);
}
{
AudioProcessorGraph::AudioGraphIOProcessor p(AudioProcessorGraph::AudioGraphIOProcessor::midiOutputNode);
p.fillInPluginDescription(midiOutDesc);
}
}
// -------------------------------------------------------------------
const PluginDescription* getDescriptionFor(const InternalFilterType type)
{
switch (type)
{
case audioInputFilter:
return &audioInDesc;
case audioOutputFilter:
return &audioOutDesc;
case midiInputFilter:
return &midiInDesc;
case midiOutputFilter:
return &midiOutDesc;
default:
return nullptr;
}
}
void getAllTypes(OwnedArray <PluginDescription>& results) override
{
for (int i = 0; i < (int) endOfFilterTypes; ++i)
results.add(new PluginDescription(*getDescriptionFor((InternalFilterType)i)));
}
AudioPluginInstance* createInstanceFromDescription(const PluginDescription& desc, double, int) override
{
if (desc.name == audioOutDesc.name)
return new AudioProcessorGraph::AudioGraphIOProcessor(AudioProcessorGraph::AudioGraphIOProcessor::audioOutputNode);
if (desc.name == audioInDesc.name)
return new AudioProcessorGraph::AudioGraphIOProcessor(AudioProcessorGraph::AudioGraphIOProcessor::audioInputNode);
if (desc.name == midiInDesc.name)
return new AudioProcessorGraph::AudioGraphIOProcessor(AudioProcessorGraph::AudioGraphIOProcessor::midiInputNode);
if (desc.name == midiOutDesc.name)
return new AudioProcessorGraph::AudioGraphIOProcessor(AudioProcessorGraph::AudioGraphIOProcessor::midiOutputNode);
return nullptr;
}
// -------------------------------------------------------------------
String getName() const override { return "Internal"; }
bool fileMightContainThisPluginType(const String&) override { return false; }
FileSearchPath getDefaultLocationsToSearch() override { return FileSearchPath(); }
bool canScanForPlugins() const override { return false; }
bool doesPluginStillExist(const PluginDescription&) override { return true; }
String getNameOfPluginFromIdentifier(const String& fileOrIdentifier) override { return fileOrIdentifier; }
bool pluginNeedsRescanning(const PluginDescription&) override { return false; }
StringArray searchPathsForPlugins(const FileSearchPath&, bool) override { return StringArray(); }
void findAllTypesForFile(OwnedArray <PluginDescription>&, const String&) override {}
// -------------------------------------------------------------------
private:
PluginDescription audioInDesc;
PluginDescription audioOutDesc;
PluginDescription midiInDesc;
PluginDescription midiOutDesc;
};
} // namespace juce
typedef juce::InternalPluginFormat JuceInternalPluginFormat;
// -----------------------------------------------------------------------
#endif // JUCE_INTERNAL_FILTERS_HPP_INCLUDED

Loading…
Cancel
Save