Browse Source

Implement juce support in discovery

tags/1.9.4
falkTX 11 years ago
parent
commit
90a8157572
8 changed files with 260 additions and 44 deletions
  1. +40
    -21
      source/discovery/Makefile
  2. +172
    -16
      source/discovery/carla-discovery.cpp
  3. +2
    -2
      source/modules/juce_audio_processors/AppConfig.h
  4. +24
    -2
      source/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp
  5. +1
    -1
      source/modules/juce_audio_processors/juce_audio_processors.cpp
  6. +4
    -0
      source/modules/juce_audio_processors/processors/juce_AudioProcessor.cpp
  7. +9
    -1
      source/modules/juce_audio_processors/processors/juce_AudioProcessor.h
  8. +8
    -1
      source/utils/CarlaVstUtils.hpp

+ 40
- 21
source/discovery/Makefile View File

@@ -8,49 +8,68 @@ include ../Makefile.mk

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

BUILD_CXX_FLAGS += -I../backend -I../includes -I../modules -I../utils
BUILD_CXX_FLAGS += -I../backend -I../includes -I../modules -I../utils -Wno-multichar

BUILD_CXX_FLAGS += $(QTCORE_FLAGS)
LINK_FLAGS += $(QTCORE_LIBS)

ifeq ($(HAVE_JUCE),true)
BUILD_CXX_FLAGS += $(JUCE_CORE_FLAGS) $(JUCE_AUDIO_BASICS_FLAGS) -DHAVE_JUCE
LINK_FLAGS += $(JUCE_CORE_LIBS) $(JUCE_AUDIO_BASICS_LIBS)
endif

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

BUILD_CXX_FLAGS += -DWANT_NATIVE

ifeq ($(CARLA_PLUGIN_SUPPORT),true)
BUILD_CXX_FLAGS += -DWANT_LADSPA -DWANT_DSSI -DWANT_LV2 -DWANT_VST
ifeq ($(CARLA_VESTIGE_HEADER),true)
ifeq ($(CARLA_VESTIGE_HEADER),true) # TODO: and not have juce
BUILD_CXX_FLAGS += -DVESTIGE_HEADER
endif
endif

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

ifeq ($(HAVE_CSOUND),true)
# ifeq ($(HAVE_CSOUND),true)
# NATIVE_FLAGS += $(shell pkg-config --cflags --libs sndfile) -lcsound64 -DWANT_CSOUND
# NATIVE_FLAGS += $(JUCE_CORE_FLAGS) $(JUCE_CORE_LIBS)
endif

ifeq ($(HAVE_FLUIDSYNTH),true)
NATIVE_FLAGS += $(shell pkg-config --cflags --libs fluidsynth) -DWANT_FLUIDSYNTH
endif

ifeq ($(HAVE_LINUXSAMPLER),true)
# endif
#
# ifeq ($(HAVE_FLUIDSYNTH),true)
# NATIVE_FLAGS += $(shell pkg-config --cflags --libs fluidsynth) -DWANT_FLUIDSYNTH
# endif
#
# ifeq ($(HAVE_LINUXSAMPLER),true)
# NATIVE_FLAGS += $(shell pkg-config --cflags --libs linuxsampler) -DWANT_LINUXSAMPLER
endif
# endif

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

ifeq ($(CARLA_PLUGIN_SUPPORT),true)
LIBS = ../modules/lilv.a
LIBS_posix32 = ../modules/lilv.posix32.a
LIBS_posix64 = ../modules/lilv.posix64.a
LIBS_win32 = ../modules/lilv.win32.a
LIBS_win64 = ../modules/lilv.win64.a
LINK_FLAGS += $(LILV_LIBS)
ifeq ($(HAVE_JUCE),true)
LIBS += ../modules/juce_core.a
LIBS_posix32 += ../modules/juce_core.posix32.a
LIBS_posix64 += ../modules/juce_core.posix64.a
LIBS_win32 += ../modules/juce_core.win32.a
LIBS_win64 += ../modules/juce_core.win64.a
LIBS += ../modules/juce_audio_basics.a
LIBS_posix32 += ../modules/juce_audio_basics.posix32.a
LIBS_posix64 += ../modules/juce_audio_basics.posix64.a
LIBS_win32 += ../modules/juce_audio_basics.win32.a
LIBS_win64 += ../modules/juce_audio_basics.win64.a
# LIBS += ../modules/juce_audio_processors.a
# LIBS_posix32 += ../modules/juce_audio_processors.posix32.a
# LIBS_posix64 += ../modules/juce_audio_processors.posix64.a
# LIBS_win32 += ../modules/juce_audio_processors.win32.a
# LIBS_win64 += ../modules/juce_audio_processors.win64.a
endif

ifeq ($(HAVE_CSOUND),true)
# LIBS = ../modules/juce_core.a
ifeq ($(CARLA_PLUGIN_SUPPORT),true)
LIBS += ../modules/lilv.a
LIBS_posix32 += ../modules/lilv.posix32.a
LIBS_posix64 += ../modules/lilv.posix64.a
LIBS_win32 += ../modules/lilv.win32.a
LIBS_win64 += ../modules/lilv.win64.a
LINK_FLAGS += $(LILV_LIBS)
endif

POSIX_BUILD_FLAGS = $(BUILD_CXX_FLAGS)


+ 172
- 16
source/discovery/carla-discovery.cpp View File

@@ -20,6 +20,16 @@
#include "CarlaString.hpp"
#include "CarlaMIDI.h"

#ifdef HAVE_JUCE
# define JUCE_PLUGIN_HOST_NO_UI
# undef WANT_VST
# undef WANT_AU
# include "juce_core.h"
# include "juce_audio_processors.h"
#else
# undef WANT_CSOUND
#endif

#ifdef WANT_LADSPA
# include "CarlaLadspaUtils.hpp"
#endif
@@ -27,26 +37,26 @@
# include "CarlaDssiUtils.hpp"
#endif
#ifdef WANT_LV2
# include <QtCore/QUrl>
# include "CarlaLv2Utils.hpp"
#endif
#ifdef WANT_VST
# include "CarlaVstUtils.hpp"
#endif
#ifdef WANT_CSOUND
# include "juce_core.h"
# include <csound/csound.hpp>
#endif
#ifdef WANT_FLUIDSYNTH
# include <fluidsynth.h>
#endif
#ifdef WANT_LINUXSAMPLER
# include <QtCore/QFileInfo>
# include "linuxsampler/EngineFactory.h"
#endif

#include <iostream>
# include <QtCore/QDir>

#include <QtCore/QDir>
#include <QtCore/QFileInfo>
#include <QtCore/QUrl>

#define DISCOVERY_OUT(x, y) std::cout << "\ncarla-discovery::" << x << "::" << y << std::endl;

@@ -263,6 +273,23 @@ intptr_t VSTCALLBACK vstHostCallback(AEffect* const effect, const int32_t opcode
}
#endif

#ifdef WANT_CSOUND
// --------------------------------------------------------------------------
// Csound stuff

static int csound_midiInOpen(CSOUND*, void**, const char*) { return 0; }
static int csound_midiRead(CSOUND*, void*, unsigned char*, int) { return 0; }
static int csound_midiInClose(CSOUND*, void*) { return 0; }

static int csound_midiOutOpen(CSOUND*, void**, const char*) { return 0; }
static int csound_midiWrite(CSOUND*, void*, const unsigned char*, int) { return 0; }
static int csound_midiOutClose(CSOUND*, void*) { return 0; }

# ifndef DEBUG
static void csound_silence(CSOUND*, int, const char*, va_list) {}
# endif
#endif

#ifdef WANT_LINUXSAMPLER
// --------------------------------------------------------------------------
// LinuxSampler stuff
@@ -1386,27 +1413,113 @@ void do_vst_check(void*& libHandle, const bool init)
#endif
}

#ifdef WANT_CSOUND
static int csound_midiInOpen(CSOUND*, void**, const char*) { return 0; }
static int csound_midiRead(CSOUND*, void*, unsigned char*, int) { return 0; }
static int csound_midiInClose(CSOUND*, void*) { return 0; }
void do_au_check(void*& libHandle, const bool init)
{
#if 0 //def WANT_AU
#else
DISCOVERY_OUT("error", "AU support not available");
return;

static int csound_midiOutOpen(CSOUND*, void**, const char*) { return 0; }
static int csound_midiWrite(CSOUND*, void*, const unsigned char*, int) { return 0; }
static int csound_midiOutClose(CSOUND*, void*) { return 0; }
// unused
(void)libHandle;
(void)init;
#endif
};

#if 1//ndef DEBUG
static void csound_silence(CSOUND*, int, const char*, va_list) {}
#ifdef HAVE_JUCE
void do_juce_check(const char* const filename, const char* const stype, const bool init)
{
using namespace juce;

ScopedPointer<AudioPluginFormat> pluginFormat;

if (stype == nullptr)
return;
#if JUCE_PLUGINHOST_AU && JUCE_MAC
else if (std::strcmp(stype, "au") == 0)
pluginFormat = new AudioUnitPluginFormat();
#endif
#if JUCE_PLUGINHOST_LADSPA && JUCE_LINUX
else if (std::strcmp(stype, "ladspa") == 0)
pluginFormat = new LADSPAPluginFormat();
#endif
#if JUCE_PLUGINHOST_VST
else if (std::strcmp(stype, "vst") == 0)
pluginFormat = new VSTPluginFormat();
#endif

if (pluginFormat == nullptr)
{
DISCOVERY_OUT("error", stype << " support not available");
return;
}

OwnedArray<PluginDescription> results;
pluginFormat->findAllTypesForFile(results, filename);

for (auto it = results.begin(), end = results.end(); it != end; ++it)
{
static int iv=0;
carla_stderr2("LOOKING FOR PLUGIN %i", iv++);
PluginDescription* desc(*it);

int hints = 0x0;
int audioIns = desc->numInputChannels;
int audioOuts = desc->numOutputChannels;
int midiIns = 0;
int midiOuts = 0;
int parameters = 0;
int programs = 0;

if (desc->isInstrument)
hints |= PLUGIN_IS_SYNTH;

// if (init)
// {
// if (AudioPluginInstance* const instance = pluginFormat->createInstanceFromDescription(*desc, kSampleRate, kBufferSize))
// {
// instance->refreshParameterList();
//
// parameters = instance->getNumParameters();
// programs = instance->getNumPrograms();
//
// if (instance->hasEditor())
// hints |= PLUGIN_HAS_CUSTOM_UI;
// if (instance->acceptsMidi())
// midiIns = 1;
// if (instance->producesMidi())
// midiOuts = 1;
//
// delete instance;
// }
// }

DISCOVERY_OUT("init", "-----------");
DISCOVERY_OUT("name", desc->name);
DISCOVERY_OUT("label", desc->descriptiveName);
DISCOVERY_OUT("maker", desc->manufacturerName);
DISCOVERY_OUT("copyright", desc->manufacturerName);
DISCOVERY_OUT("uniqueId", desc->uid);
DISCOVERY_OUT("hints", hints);
DISCOVERY_OUT("audio.ins", audioIns);
DISCOVERY_OUT("audio.outs", audioOuts);
DISCOVERY_OUT("midi.ins", midiIns);
DISCOVERY_OUT("midi.outs", midiOuts);
DISCOVERY_OUT("parameters.ins", parameters);
DISCOVERY_OUT("programs", programs);
DISCOVERY_OUT("build", BINARY_NATIVE);
DISCOVERY_OUT("end", "------------");
}
}
#endif

void do_csound_check(const char* const filename, const bool init)
{
#ifdef WANT_CSOUND
Csound csound;
#if 1//ndef DEBUG
# ifndef DEBUG
csound.SetMessageCallback(csound_silence);
#endif
# endif
csound.SetHostImplementedAudioIO(true, kBufferSize);
csound.SetHostImplementedMIDIIO(true);
csound.Reset();
@@ -1672,8 +1785,10 @@ int main(int argc, char* argv[])
{
case PLUGIN_LADSPA:
case PLUGIN_DSSI:
#ifndef HAVE_JUCE
case PLUGIN_VST:
case PLUGIN_AU:
#endif
openLib = true;
default:
break;
@@ -1737,10 +1852,18 @@ int main(int argc, char* argv[])
do_lv2_check(filename, doInit);
break;
case PLUGIN_VST:
#ifdef HAVE_JUCE
do_juce_check(filename, "vst", doInit);
#else
do_vst_check(handle, doInit);
#endif
break;
case PLUGIN_AU:
//do_au_check(handle, doInit);
#ifdef HAVE_JUCE
do_juce_check(filename, "au", doInit);
#else
do_au_check(handle, doInit);
#endif
break;
case PLUGIN_CSOUND:
do_csound_check(filename, doInit);
@@ -1763,3 +1886,36 @@ int main(int argc, char* argv[])

return 0;
}

#ifdef HAVE_JUCE
// --------------------------------------------------------------------------
// we want juce processors but without UI code
// this is copied from juce_audio_processors.cpp

#include "juce_core/native/juce_BasicNativeHeaders.h"

namespace juce
{

static inline
bool arrayContainsPlugin(const OwnedArray<PluginDescription>& list, const PluginDescription& desc)
{
for (int i = list.size(); --i >= 0;)
{
if (list.getUnchecked(i)->isDuplicateOf(desc))
return true;
}

return false;
}

#include "juce_audio_processors/format/juce_AudioPluginFormat.cpp"
#include "juce_audio_processors/processors/juce_AudioProcessor.cpp"
#include "juce_audio_processors/processors/juce_PluginDescription.cpp"
#include "juce_audio_processors/format_types/juce_AudioUnitPluginFormat.mm"
#include "juce_audio_processors/format_types/juce_LADSPAPluginFormat.cpp"
#include "juce_audio_processors/format_types/juce_VSTPluginFormat.cpp"
}
#endif

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

+ 2
- 2
source/modules/juce_audio_processors/AppConfig.h View File

@@ -19,13 +19,13 @@
@see VSTPluginFormat, AudioPluginFormat, AudioPluginFormatManager, JUCE_PLUGINHOST_AU
*/
#define JUCE_PLUGINHOST_VST 0
#define JUCE_PLUGINHOST_VST 1
/** Config: JUCE_PLUGINHOST_AU
Enables the AudioUnit plugin hosting classes. This is Mac-only, of course.
@see AudioUnitPluginFormat, AudioPluginFormat, AudioPluginFormatManager, JUCE_PLUGINHOST_VST
*/
#define JUCE_PLUGINHOST_AU 0
#define JUCE_PLUGINHOST_AU 1
#endif // CARLA_JUCE_AUDIO_PROCESSORS_APPCONFIG_H_INCLUDED

+ 24
- 2
source/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp View File

@@ -191,7 +191,11 @@ class IdleCallRecursionPreventer
{
public:
IdleCallRecursionPreventer()
#ifndef JUCE_PLUGIN_HOST_NO_UI
: isMessageThread (MessageManager::getInstance()->isThisTheMessageThread())
#else
: isMessageThread (false)
#endif
{
if (isMessageThread)
++insideVSTCallback;
@@ -237,7 +241,7 @@ static void* NewCFMFromMachO (void* const machofp) noexcept
#endif
//==============================================================================
#if JUCE_LINUX
#if JUCE_LINUX && ! defined(JUCE_PLUGIN_HOST_NO_UI)
extern Display* display;
extern XContext windowHandleXContext;
@@ -710,9 +714,13 @@ static const int defaultVSTBlockSizeValue = 512;
//==============================================================================
//==============================================================================
#ifndef JUCE_PLUGIN_HOST_NO_UI
class VSTPluginInstance : public AudioPluginInstance,
private Timer,
private AsyncUpdater
#else
class VSTPluginInstance : public AudioPluginInstance
#endif
{
public:
VSTPluginInstance (const ModuleHandle::Ptr& module_)
@@ -782,8 +790,10 @@ public:
UseResFile (module->resFileId);
#endif
#ifndef JUCE_PLUGIN_HOST_NO_UI
// Must delete any editors before deleting the plugin instance!
jassert (getActiveEditor() == 0);
#endif
_fpreset(); // some dodgy plugs fuck around with this
@@ -1088,7 +1098,9 @@ public:
//==============================================================================
bool hasEditor() const override { return effect != nullptr && (effect->flags & effFlagsHasEditor) != 0; }
#ifndef JUCE_PLUGIN_HOST_NO_UI
AudioProcessorEditor* createEditor() override;
#endif
//==============================================================================
const String getInputChannelName (int index) const override
@@ -1237,6 +1249,7 @@ public:
void setCurrentProgramStateInformation (const void* data, int size) override { loadFromFXBFile (data, size); }
//==============================================================================
#ifndef JUCE_PLUGIN_HOST_NO_UI
void timerCallback() override
{
if (dispatch (effIdle, 0, 0, 0, 0) == 0)
@@ -1248,6 +1261,7 @@ public:
// indicates that something about the plugin has changed..
updateHostDisplay();
}
#endif
VstIntPtr handleCallback (VstInt32 opcode, VstInt32 index, VstIntPtr value, void* ptr, float opt)
{
@@ -1265,6 +1279,7 @@ public:
#pragma warning (pop)
#endif
#ifndef JUCE_PLUGIN_HOST_NO_UI
case audioMasterIdle:
if (insideVSTCallback == 0 && MessageManager::getInstance()->isThisTheMessageThread())
{
@@ -1293,6 +1308,7 @@ public:
case audioMasterUpdateDisplay: triggerAsyncUpdate(); break;
case audioMasterIOChanged: setLatencySamples (effect->initialDelay); break;
case audioMasterNeedIdle: startTimer (50); break;
#endif
case audioMasterGetSampleRate: return (VstIntPtr) (getSampleRate() > 0 ? getSampleRate() : defaultVSTSampleRateValue);
case audioMasterGetBlockSize: return (VstIntPtr) (getBlockSize() > 0 ? getBlockSize() : defaultVSTBlockSizeValue);
@@ -1378,10 +1394,12 @@ public:
case audioMasterGetVendorString:
case audioMasterGetProductString:
{
String hostName ("Juce VST Host");
String hostName ("Carla");
#ifndef JUCE_PLUGIN_HOST_NO_UI
if (JUCEApplicationBase* app = JUCEApplicationBase::getInstance())
hostName = app->getApplicationName();
#endif
hostName.copyToUTF8 ((char*) ptr, (size_t) jmin (kVstMaxVendorStrLen, kVstMaxProductStrLen) - 1);
break;
@@ -1882,6 +1900,7 @@ private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (VSTPluginInstance)
};
#ifndef JUCE_PLUGIN_HOST_NO_UI
//==============================================================================
static Array <VSTPluginWindow*> activeVSTWindows;
@@ -2588,13 +2607,16 @@ private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (VSTPluginWindow)
};
#endif
#ifndef JUCE_PLUGIN_HOST_NO_UI
//==============================================================================
AudioProcessorEditor* VSTPluginInstance::createEditor()
{
return hasEditor() ? new VSTPluginWindow (*this)
: nullptr;
}
#endif
//==============================================================================
// entry point for all callbacks from the plugin


+ 1
- 1
source/modules/juce_audio_processors/juce_audio_processors.cpp View File

@@ -37,7 +37,7 @@
#include "../juce_core/native/juce_BasicNativeHeaders.h"
#include "juce_audio_processors.h"
#include "../juce_gui_extra/juce_gui_extra.h"
//#include "../juce_gui_extra/juce_gui_extra.h"
//==============================================================================
#if JUCE_MAC


+ 4
- 0
source/modules/juce_audio_processors/processors/juce_AudioProcessor.cpp View File

@@ -44,9 +44,11 @@ AudioProcessor::AudioProcessor()
AudioProcessor::~AudioProcessor()
{
#ifndef JUCE_PLUGIN_HOST_NO_UI
// ooh, nasty - the editor should have been deleted before the filter
// that it refers to is deleted..
jassert (activeEditor == nullptr);
#endif
#if JUCE_DEBUG
// This will fail if you've called beginParameterChangeGesture() for one
@@ -214,6 +216,7 @@ void AudioProcessor::suspendProcessing (const bool shouldBeSuspended)
void AudioProcessor::reset() {}
void AudioProcessor::processBlockBypassed (AudioSampleBuffer&, MidiBuffer&) {}
#ifndef JUCE_PLUGIN_HOST_NO_UI
//==============================================================================
void AudioProcessor::editorBeingDeleted (AudioProcessorEditor* const editor) noexcept
{
@@ -244,6 +247,7 @@ AudioProcessorEditor* AudioProcessor::createEditorIfNeeded()
return ed;
}
#endif
//==============================================================================
void AudioProcessor::getCurrentProgramStateInformation (juce::MemoryBlock& destData)


+ 9
- 1
source/modules/juce_audio_processors/processors/juce_AudioProcessor.h View File

@@ -331,6 +331,7 @@ public:
*/
void setNonRealtime (bool isNonRealtime) noexcept;
#ifndef JUCE_PLUGIN_HOST_NO_UI
//==============================================================================
/** Creates the filter's UI.
@@ -360,12 +361,14 @@ public:
@see hasEditor
*/
virtual AudioProcessorEditor* createEditor() = 0;
#endif
/** Your filter must override this and return true if it can create an editor component.
@see createEditor
*/
virtual bool hasEditor() const = 0;
#ifndef JUCE_PLUGIN_HOST_NO_UI
//==============================================================================
/** Returns the active editor, if there is one.
Bear in mind this can return nullptr, even if an editor has previously been opened.
@@ -376,6 +379,7 @@ public:
This may call createEditor() internally to create the component.
*/
AudioProcessorEditor* createEditorIfNeeded();
#endif
//==============================================================================
/** This must return the correct value immediately after the object has been
@@ -582,7 +586,7 @@ public:
//==============================================================================
/** LV2 specific calls, saving/restore as string. */
virtual String getStateInformationString () { return String::empty; }
virtual void setStateInformationString (const String& data) {}
virtual void setStateInformationString (const String&) {}
//==============================================================================
/** Adds a listener that will be called when an aspect of this processor changes. */
@@ -602,9 +606,11 @@ public:
/** This is called by the processor to specify its details before being played. */
void setPlayConfigDetails (int numIns, int numOuts, double sampleRate, int blockSize) noexcept;
#ifndef JUCE_PLUGIN_HOST_NO_UI
//==============================================================================
/** Not for public use - this is called before deleting an editor component. */
void editorBeingDeleted (AudioProcessorEditor*) noexcept;
#endif
/** Not for public use - this is called to initialise the processor before playing. */
void setSpeakerArrangement (const String& inputs, const String& outputs);
@@ -656,7 +662,9 @@ protected:
private:
Array<AudioProcessorListener*> listeners;
#ifndef JUCE_PLUGIN_HOST_NO_UI
Component::SafePointer<AudioProcessorEditor> activeEditor;
#endif
double sampleRate;
int blockSize, numInputChannels, numOutputChannels, latencySamples;
bool suspended, nonRealtime;


+ 8
- 1
source/utils/CarlaVstUtils.hpp View File

@@ -23,6 +23,13 @@
// -----------------------------------------------------------------------
// Include fixes

// Define __cdecl if needed
#ifndef CARLA_OS_WIN
# ifndef __cdecl
# define __cdecl
# endif
#endif

// Disable deprecated VST features (NOT)
#define VST_2_4_EXTENSIONS 1
#define VST_FORCE_DEPRECATED 0
@@ -106,7 +113,7 @@
#define kVstTransportChanged 1
#define kVstVersion 2400
#define DECLARE_VST_DEPRECATED(idx) idx
#define VSTCALLBACK
#define VSTCALLBACK __cdecl
struct ERect {
int16_t top, left, bottom, right;
};


Loading…
Cancel
Save