mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-20 21:56:30 +01:00
AU support, plus changes in Plugin to make unique_id a string
git-svn-id: svn://localhost/ardour2/branches/2.0-ongoing@2754 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
c467d75306
commit
f3dd3e6b18
13 changed files with 709 additions and 144 deletions
|
|
@ -30,6 +30,8 @@
|
|||
|
||||
#include <ardour/plugin.h>
|
||||
|
||||
#include <AudioUnit/AudioUnit.h>
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
class CAComponent;
|
||||
|
|
@ -48,10 +50,10 @@ class AUPlugin : public ARDOUR::Plugin
|
|||
AUPlugin (AudioEngine& engine, Session& session, CAComponent* comp);
|
||||
virtual ~AUPlugin ();
|
||||
|
||||
uint32_t unique_id () const;
|
||||
std::string unique_id () const;
|
||||
const char * label () const;
|
||||
const char * name () const { return _info->name.c_str(); }
|
||||
const char * maker () const;
|
||||
const char * maker () const { return _info->creator.c_str(); }
|
||||
uint32_t parameter_count () const;
|
||||
float default_value (uint32_t port);
|
||||
nframes_t latency () const;
|
||||
|
|
@ -84,34 +86,63 @@ class AUPlugin : public ARDOUR::Plugin
|
|||
|
||||
bool has_editor () const;
|
||||
|
||||
bool fixed_io() const { return false; }
|
||||
int32_t can_support_input_configuration (int32_t in);
|
||||
int32_t compute_output_streams (int32_t nplugins);
|
||||
uint32_t output_streams() const;
|
||||
uint32_t input_streams() const;
|
||||
|
||||
CAAudioUnit* get_au () { return unit; }
|
||||
CAComponent* get_comp () { return comp; }
|
||||
|
||||
|
||||
OSStatus render_callback(AudioUnitRenderActionFlags *ioActionFlags,
|
||||
const AudioTimeStamp *inTimeStamp,
|
||||
UInt32 inBusNumber,
|
||||
UInt32 inNumberFrames,
|
||||
AudioBufferList* ioData);
|
||||
private:
|
||||
CAComponent* comp;
|
||||
CAAudioUnit* unit;
|
||||
|
||||
AudioBufferList* in_list;
|
||||
AudioBufferList* out_list;
|
||||
CAAudioUnit* unit;
|
||||
|
||||
AudioStreamBasicDescription streamFormat;
|
||||
bool initialized;
|
||||
AudioBufferList* buffers;
|
||||
|
||||
UInt32 global_elements;
|
||||
UInt32 output_elements;
|
||||
UInt32 input_elements;
|
||||
|
||||
int set_output_format ();
|
||||
int set_input_format ();
|
||||
int set_stream_format (int scope, uint32_t cnt);
|
||||
int _set_block_size (nframes_t nframes);
|
||||
|
||||
std::vector<std::pair<uint32_t, uint32_t> > parameter_map;
|
||||
uint32_t current_maxbuf;
|
||||
nframes_t current_offset;
|
||||
nframes_t cb_offset;
|
||||
vector<Sample*>* current_buffers;
|
||||
nframes_t frames_processed;
|
||||
};
|
||||
|
||||
|
||||
typedef boost::shared_ptr<AUPlugin> AUPluginPtr;
|
||||
|
||||
class AUPluginInfo : public PluginInfo {
|
||||
public:
|
||||
AUPluginInfo () { };
|
||||
AUPluginInfo (CAComponentDescription*);
|
||||
~AUPluginInfo ();
|
||||
|
||||
CAComponentDescription* desc;
|
||||
|
||||
static PluginInfoList discover ();
|
||||
PluginPtr load (Session& session);
|
||||
|
||||
static PluginInfoList discover ();
|
||||
static void get_names (CAComponentDescription&, std::string& name, Glib::ustring& maker);
|
||||
static std::string stringify_descriptor (const CAComponentDescription&);
|
||||
|
||||
private:
|
||||
static std::string get_name (CAComponentDescription&);
|
||||
void setup_nchannels (CAComponentDescription&);
|
||||
CAComponentDescription* descriptor;
|
||||
static void discover_music (PluginInfoList&);
|
||||
static void discover_fx (PluginInfoList&);
|
||||
static void discover_by_description (PluginInfoList&, CAComponentDescription&);
|
||||
};
|
||||
|
||||
typedef boost::shared_ptr<AUPluginInfo> AUPluginInfoPtr;
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ class LadspaPlugin : public ARDOUR::Plugin
|
|||
|
||||
/* Plugin interface */
|
||||
|
||||
uint32_t unique_id() const { return descriptor->UniqueID; }
|
||||
std::string unique_id() const;
|
||||
const char * label() const { return descriptor->Label; }
|
||||
const char * name() const { return descriptor->Name; }
|
||||
const char * maker() const { return descriptor->Maker; }
|
||||
|
|
|
|||
|
|
@ -67,11 +67,11 @@ class PluginInfo {
|
|||
string category;
|
||||
Glib::ustring creator;
|
||||
Glib::ustring path;
|
||||
uint32_t n_inputs;
|
||||
uint32_t n_outputs;
|
||||
int32_t n_inputs;
|
||||
int32_t n_outputs;
|
||||
ARDOUR::PluginType type;
|
||||
|
||||
long unique_id;
|
||||
std::string unique_id;
|
||||
|
||||
virtual PluginPtr load (Session& session) = 0;
|
||||
|
||||
|
|
@ -108,7 +108,7 @@ class Plugin : public PBD::StatefulDestructible
|
|||
bool max_unbound;
|
||||
};
|
||||
|
||||
virtual uint32_t unique_id() const = 0;
|
||||
virtual std::string unique_id() const = 0;
|
||||
virtual const char * label() const = 0;
|
||||
virtual const char * name() const = 0;
|
||||
virtual const char * maker() const = 0;
|
||||
|
|
@ -142,6 +142,12 @@ class Plugin : public PBD::StatefulDestructible
|
|||
virtual bool has_editor() const = 0;
|
||||
|
||||
sigc::signal<void,uint32_t,float> ParameterChanged;
|
||||
|
||||
virtual bool fixed_io() const { return true; }
|
||||
virtual int32_t can_support_input_configuration (int32_t in);
|
||||
virtual int32_t compute_output_streams (int32_t nplugins);
|
||||
virtual uint32_t output_streams() const;
|
||||
virtual uint32_t input_streams() const;
|
||||
|
||||
PBD::Controllable *get_nth_control (uint32_t, bool do_not_create = false);
|
||||
void make_nth_control (uint32_t, const XMLNode&);
|
||||
|
|
@ -186,7 +192,7 @@ class Plugin : public PBD::StatefulDestructible
|
|||
vector<PortControllable*> controls;
|
||||
};
|
||||
|
||||
PluginPtr find_plugin(ARDOUR::Session&, string name, long unique_id, ARDOUR::PluginType);
|
||||
PluginPtr find_plugin(ARDOUR::Session&, string unique_id, ARDOUR::PluginType);
|
||||
|
||||
} // namespace ARDOUR
|
||||
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ class PluginManager {
|
|||
|
||||
ARDOUR::PluginInfoList &vst_plugin_info () { return _vst_plugin_info; }
|
||||
ARDOUR::PluginInfoList &ladspa_plugin_info () { return _ladspa_plugin_info; }
|
||||
ARDOUR::PluginInfoList &au_plugin_info () { return _au_plugin_info; }
|
||||
|
||||
void refresh ();
|
||||
|
||||
|
|
@ -51,6 +52,8 @@ class PluginManager {
|
|||
private:
|
||||
ARDOUR::PluginInfoList _vst_plugin_info;
|
||||
ARDOUR::PluginInfoList _ladspa_plugin_info;
|
||||
ARDOUR::PluginInfoList _au_plugin_info;
|
||||
|
||||
std::map<uint32_t, std::string> rdf_type;
|
||||
|
||||
std::string ladspa_path;
|
||||
|
|
@ -64,6 +67,9 @@ class PluginManager {
|
|||
void add_vst_presets ();
|
||||
void add_presets (std::string domain);
|
||||
|
||||
int au_discover ();
|
||||
void au_refresh ();
|
||||
|
||||
int vst_discover_from_path (std::string path);
|
||||
int vst_discover (std::string path);
|
||||
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ class VSTPlugin : public ARDOUR::Plugin
|
|||
|
||||
/* Plugin interface */
|
||||
|
||||
uint32_t unique_id() const;
|
||||
std::string unique_id() const;
|
||||
const char * label() const;
|
||||
const char * name() const;
|
||||
const char * maker() const;
|
||||
|
|
|
|||
|
|
@ -18,10 +18,16 @@
|
|||
|
||||
*/
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include <pbd/transmitter.h>
|
||||
#include <pbd/xml++.h>
|
||||
#include <pbd/whitespace.h>
|
||||
|
||||
#include <glibmm/thread.h>
|
||||
|
||||
#include <ardour/audioengine.h>
|
||||
#include <ardour/io.h>
|
||||
#include <ardour/audio_unit.h>
|
||||
#include <ardour/session.h>
|
||||
#include <ardour/utils.h>
|
||||
|
|
@ -37,13 +43,31 @@ using namespace std;
|
|||
using namespace PBD;
|
||||
using namespace ARDOUR;
|
||||
|
||||
static OSStatus
|
||||
_render_callback(void *userData,
|
||||
AudioUnitRenderActionFlags *ioActionFlags,
|
||||
const AudioTimeStamp *inTimeStamp,
|
||||
UInt32 inBusNumber,
|
||||
UInt32 inNumberFrames,
|
||||
AudioBufferList* ioData)
|
||||
{
|
||||
return ((AUPlugin*)userData)->render_callback (ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, ioData);
|
||||
}
|
||||
|
||||
AUPlugin::AUPlugin (AudioEngine& engine, Session& session, CAComponent* _comp)
|
||||
:
|
||||
Plugin (engine, session),
|
||||
comp (_comp),
|
||||
unit (new CAAudioUnit)
|
||||
unit (new CAAudioUnit),
|
||||
initialized (false),
|
||||
buffers (0),
|
||||
current_maxbuf (0),
|
||||
current_offset (0),
|
||||
current_buffers (0),
|
||||
frames_processed (0)
|
||||
{
|
||||
OSErr err = CAAudioUnit::Open (*comp, *unit);
|
||||
|
||||
if (err != noErr) {
|
||||
error << _("AudioUnit: Could not convert CAComponent to CAAudioUnit") << endmsg;
|
||||
delete unit;
|
||||
|
|
@ -51,7 +75,42 @@ AUPlugin::AUPlugin (AudioEngine& engine, Session& session, CAComponent* _comp)
|
|||
throw failed_constructor ();
|
||||
}
|
||||
|
||||
unit->Initialize ();
|
||||
AURenderCallbackStruct renderCallbackInfo;
|
||||
|
||||
renderCallbackInfo.inputProc = _render_callback;
|
||||
renderCallbackInfo.inputProcRefCon = this;
|
||||
|
||||
if ((err = unit->SetProperty (kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input,
|
||||
0, (void*) &renderCallbackInfo, sizeof(renderCallbackInfo))) != 0) {
|
||||
cerr << "cannot install render callback (err = " << err << ')' << endl;
|
||||
delete unit;
|
||||
delete comp;
|
||||
throw failed_constructor();
|
||||
}
|
||||
|
||||
unit->GetElementCount (kAudioUnitScope_Input, input_elements);
|
||||
unit->GetElementCount (kAudioUnitScope_Output, output_elements);
|
||||
|
||||
// set up the basic stream format. these fields do not change
|
||||
|
||||
streamFormat.mSampleRate = session.frame_rate();
|
||||
streamFormat.mFormatID = kAudioFormatLinearPCM;
|
||||
streamFormat.mFormatFlags = kAudioFormatFlagIsFloat|kAudioFormatFlagIsPacked|kAudioFormatFlagIsNonInterleaved;
|
||||
streamFormat.mBitsPerChannel = 32;
|
||||
streamFormat.mFramesPerPacket = 1;
|
||||
|
||||
// subject to later modification as we discover channel counts
|
||||
|
||||
streamFormat.mBytesPerPacket = 4;
|
||||
streamFormat.mBytesPerFrame = 4;
|
||||
streamFormat.mChannelsPerFrame = 1;
|
||||
|
||||
if (_set_block_size (_session.get_block_size())) {
|
||||
error << _("AUPlugin: cannot set processing block size") << endmsg;
|
||||
delete unit;
|
||||
delete comp;
|
||||
throw failed_constructor();
|
||||
}
|
||||
}
|
||||
|
||||
AUPlugin::~AUPlugin ()
|
||||
|
|
@ -60,43 +119,26 @@ AUPlugin::~AUPlugin ()
|
|||
unit->Uninitialize ();
|
||||
delete unit;
|
||||
}
|
||||
|
||||
if (buffers) {
|
||||
free (buffers);
|
||||
}
|
||||
|
||||
if (comp) {
|
||||
delete comp;
|
||||
}
|
||||
|
||||
if (in_list) {
|
||||
delete in_list;
|
||||
}
|
||||
|
||||
if (out_list) {
|
||||
delete out_list;
|
||||
}
|
||||
}
|
||||
|
||||
AUPluginInfo::~AUPluginInfo ()
|
||||
{
|
||||
if (desc) {
|
||||
delete desc;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t
|
||||
string
|
||||
AUPlugin::unique_id () const
|
||||
{
|
||||
return 0;
|
||||
return AUPluginInfo::stringify_descriptor (comp->Desc());
|
||||
}
|
||||
|
||||
const char *
|
||||
AUPlugin::label () const
|
||||
{
|
||||
return "AUPlugin label";
|
||||
}
|
||||
|
||||
const char *
|
||||
AUPlugin::maker () const
|
||||
{
|
||||
return "AUplugin maker";
|
||||
return _info->name.c_str();
|
||||
}
|
||||
|
||||
uint32_t
|
||||
|
|
@ -121,7 +163,7 @@ AUPlugin::latency () const
|
|||
void
|
||||
AUPlugin::set_parameter (uint32_t which, float val)
|
||||
{
|
||||
unit->SetParameter (parameter_map[which].first, parameter_map[which].second, 0, val);
|
||||
// unit->SetParameter (parameter_map[which].first, parameter_map[which].second, 0, val);
|
||||
}
|
||||
|
||||
float
|
||||
|
|
@ -129,7 +171,7 @@ AUPlugin::get_parameter (uint32_t which) const
|
|||
{
|
||||
float outValue = 0.0;
|
||||
|
||||
unit->GetParameter(parameter_map[which].first, parameter_map[which].second, 0, outValue);
|
||||
// unit->GetParameter(parameter_map[which].first, parameter_map[which].second, 0, outValue);
|
||||
|
||||
return outValue;
|
||||
}
|
||||
|
|
@ -149,19 +191,168 @@ AUPlugin::nth_parameter (uint32_t which, bool& ok) const
|
|||
void
|
||||
AUPlugin::activate ()
|
||||
{
|
||||
unit->GlobalReset ();
|
||||
if (!initialized) {
|
||||
OSErr err;
|
||||
if ((err = unit->Initialize()) != noErr) {
|
||||
error << string_compose (_("AUPlugin: cannot initialize plugin (err = %1)"), err) << endmsg;
|
||||
} else {
|
||||
frames_processed = 0;
|
||||
initialized = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AUPlugin::deactivate ()
|
||||
{
|
||||
// not needed. GlobalReset () takes care of it.
|
||||
unit->GlobalReset ();
|
||||
}
|
||||
|
||||
void
|
||||
AUPlugin::set_block_size (nframes_t nframes)
|
||||
{
|
||||
_set_block_size (nframes);
|
||||
}
|
||||
|
||||
int
|
||||
AUPlugin::_set_block_size (nframes_t nframes)
|
||||
{
|
||||
bool was_initialized = initialized;
|
||||
UInt32 numFrames = nframes;
|
||||
OSErr err;
|
||||
|
||||
if (initialized) {
|
||||
unit->Uninitialize ();
|
||||
}
|
||||
|
||||
set_input_format ();
|
||||
set_output_format ();
|
||||
|
||||
if ((err = unit->SetProperty (kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global,
|
||||
0, &numFrames, sizeof (numFrames))) != noErr) {
|
||||
cerr << "cannot set max frames (err = " << err << ')' << endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (was_initialized) {
|
||||
activate ();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t
|
||||
AUPlugin::can_support_input_configuration (int32_t in)
|
||||
{
|
||||
streamFormat.mBytesPerPacket = 4 * in;
|
||||
streamFormat.mBytesPerFrame = 4 * in;
|
||||
streamFormat.mChannelsPerFrame = in;
|
||||
|
||||
if (set_input_format () == 0) {
|
||||
return 1;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
AUPlugin::set_input_format ()
|
||||
{
|
||||
return set_stream_format (kAudioUnitScope_Input, input_elements);
|
||||
}
|
||||
|
||||
int
|
||||
AUPlugin::set_output_format ()
|
||||
{
|
||||
return set_stream_format (kAudioUnitScope_Output, output_elements);
|
||||
}
|
||||
|
||||
int
|
||||
AUPlugin::set_stream_format (int scope, uint32_t cnt)
|
||||
{
|
||||
OSErr result;
|
||||
|
||||
for (uint32_t i = 0; i < cnt; ++i) {
|
||||
if ((result = unit->SetFormat (scope, i, streamFormat)) != 0) {
|
||||
error << string_compose (_("AUPlugin: could not set stream format for %1/%2"),
|
||||
(scope == kAudioUnitScope_Input ? "input" : "output"), i) << endmsg;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t
|
||||
AUPlugin::compute_output_streams (int32_t nplugins)
|
||||
{
|
||||
/* we will never replicate AU plugins - either they can do the I/O we need
|
||||
or not. thus, we can ignore nplugins entirely.
|
||||
*/
|
||||
|
||||
if (set_output_format() == 0) {
|
||||
|
||||
if (buffers) {
|
||||
free (buffers);
|
||||
buffers = 0;
|
||||
}
|
||||
|
||||
buffers = (AudioBufferList *) malloc (offsetof(AudioBufferList, mBuffers) +
|
||||
streamFormat.mChannelsPerFrame * sizeof(AudioBuffer));
|
||||
|
||||
Glib::Mutex::Lock em (_session.engine().process_lock());
|
||||
IO::MoreOutputs (streamFormat.mChannelsPerFrame);
|
||||
|
||||
return streamFormat.mChannelsPerFrame;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t
|
||||
AUPlugin::output_streams() const
|
||||
{
|
||||
if (!initialized) {
|
||||
warning << _("AUPlugin: output_streams() called without calling Initialize!") << endmsg;
|
||||
return 1;
|
||||
}
|
||||
return streamFormat.mChannelsPerFrame;
|
||||
}
|
||||
|
||||
|
||||
uint32_t
|
||||
AUPlugin::input_streams() const
|
||||
{
|
||||
if (!initialized) {
|
||||
warning << _("AUPlugin: input_streams() called without calling Initialize!") << endmsg;
|
||||
return 1;
|
||||
}
|
||||
return streamFormat.mChannelsPerFrame;
|
||||
}
|
||||
|
||||
OSStatus
|
||||
AUPlugin::render_callback(AudioUnitRenderActionFlags *ioActionFlags,
|
||||
const AudioTimeStamp *inTimeStamp,
|
||||
UInt32 inBusNumber,
|
||||
UInt32 inNumberFrames,
|
||||
AudioBufferList* ioData)
|
||||
{
|
||||
/* not much to do - the data is already in the buffers given to us in connect_and_run() */
|
||||
|
||||
if (current_maxbuf == 0) {
|
||||
error << _("AUPlugin: render callback called illegally!") << endmsg;
|
||||
return kAudioUnitErr_CannotDoInCurrentContext;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < current_maxbuf; ++i) {
|
||||
ioData->mBuffers[i].mNumberChannels = 1;
|
||||
ioData->mBuffers[i].mDataByteSize = sizeof (Sample) * inNumberFrames;
|
||||
ioData->mBuffers[i].mData = (*current_buffers)[i] + cb_offset + current_offset;
|
||||
}
|
||||
|
||||
cb_offset += inNumberFrames;
|
||||
|
||||
return noErr;
|
||||
}
|
||||
|
||||
int
|
||||
|
|
@ -169,17 +360,37 @@ AUPlugin::connect_and_run (vector<Sample*>& bufs, uint32_t maxbuf, int32_t& in,
|
|||
{
|
||||
AudioUnitRenderActionFlags flags = 0;
|
||||
AudioTimeStamp ts;
|
||||
|
||||
AudioBufferList abl;
|
||||
abl.mNumberBuffers = 1;
|
||||
abl.mBuffers[0].mNumberChannels = 1;
|
||||
abl.mBuffers[0].mDataByteSize = nframes * sizeof(Sample);
|
||||
abl.mBuffers[0].mData = &bufs[0];
|
||||
|
||||
|
||||
unit->Render (&flags, &ts, 0, 0, &abl);
|
||||
|
||||
return 0;
|
||||
|
||||
current_buffers = &bufs;
|
||||
current_maxbuf = maxbuf;
|
||||
current_offset = offset;
|
||||
cb_offset = 0;
|
||||
|
||||
buffers->mNumberBuffers = maxbuf;
|
||||
|
||||
for (uint32_t i = 0; i < maxbuf; ++i) {
|
||||
buffers->mBuffers[i].mNumberChannels = 1;
|
||||
buffers->mBuffers[i].mDataByteSize = nframes * sizeof (Sample);
|
||||
buffers->mBuffers[i].mData = 0;
|
||||
}
|
||||
|
||||
ts.mSampleTime = frames_processed;
|
||||
ts.mFlags = kAudioTimeStampSampleTimeValid;
|
||||
|
||||
if (unit->Render (&flags, &ts, 0, nframes, buffers) == noErr) {
|
||||
|
||||
current_maxbuf = 0;
|
||||
frames_processed += nframes;
|
||||
|
||||
for (uint32_t i = 0; i < maxbuf; ++i) {
|
||||
if (bufs[i] + offset != buffers->mBuffers[i].mData) {
|
||||
memcpy (bufs[i]+offset, buffers->mBuffers[i].mData, nframes * sizeof (Sample));
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
set<uint32_t>
|
||||
|
|
@ -229,8 +440,8 @@ AUPlugin::parameter_is_output (uint32_t) const
|
|||
XMLNode&
|
||||
AUPlugin::get_state()
|
||||
{
|
||||
XMLNode* root = new XMLNode (state_node_name());
|
||||
|
||||
XMLNode *root = new XMLNode (state_node_name());
|
||||
LocaleGuard lg (X_("POSIX"));
|
||||
return *root;
|
||||
}
|
||||
|
||||
|
|
@ -263,7 +474,22 @@ AUPlugin::get_presets ()
|
|||
bool
|
||||
AUPlugin::has_editor () const
|
||||
{
|
||||
return false;
|
||||
// even if the plugin doesn't have its own editor, the AU API can be used
|
||||
// to create one that looks native.
|
||||
return true;
|
||||
}
|
||||
|
||||
AUPluginInfo::AUPluginInfo (CAComponentDescription* d)
|
||||
: descriptor (d)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
AUPluginInfo::~AUPluginInfo ()
|
||||
{
|
||||
if (descriptor) {
|
||||
delete descriptor;
|
||||
}
|
||||
}
|
||||
|
||||
PluginPtr
|
||||
|
|
@ -272,7 +498,7 @@ AUPluginInfo::load (Session& session)
|
|||
try {
|
||||
PluginPtr plugin;
|
||||
|
||||
CAComponent* comp = new CAComponent(*desc);
|
||||
CAComponent* comp = new CAComponent(*descriptor);
|
||||
|
||||
if (!comp->IsValid()) {
|
||||
error << ("AudioUnit: not a valid Component") << endmsg;
|
||||
|
|
@ -294,6 +520,28 @@ AUPluginInfo::discover ()
|
|||
{
|
||||
PluginInfoList plugs;
|
||||
|
||||
discover_fx (plugs);
|
||||
discover_music (plugs);
|
||||
|
||||
return plugs;
|
||||
}
|
||||
|
||||
void
|
||||
AUPluginInfo::discover_music (PluginInfoList& plugs)
|
||||
{
|
||||
CAComponentDescription desc;
|
||||
desc.componentFlags = 0;
|
||||
desc.componentFlagsMask = 0;
|
||||
desc.componentSubType = 0;
|
||||
desc.componentManufacturer = 0;
|
||||
desc.componentType = kAudioUnitType_MusicEffect;
|
||||
|
||||
discover_by_description (plugs, desc);
|
||||
}
|
||||
|
||||
void
|
||||
AUPluginInfo::discover_fx (PluginInfoList& plugs)
|
||||
{
|
||||
CAComponentDescription desc;
|
||||
desc.componentFlags = 0;
|
||||
desc.componentFlagsMask = 0;
|
||||
|
|
@ -301,35 +549,145 @@ AUPluginInfo::discover ()
|
|||
desc.componentManufacturer = 0;
|
||||
desc.componentType = kAudioUnitType_Effect;
|
||||
|
||||
discover_by_description (plugs, desc);
|
||||
}
|
||||
|
||||
void
|
||||
AUPluginInfo::discover_by_description (PluginInfoList& plugs, CAComponentDescription& desc)
|
||||
{
|
||||
Component comp = 0;
|
||||
|
||||
comp = FindNextComponent (NULL, &desc);
|
||||
|
||||
while (comp != NULL) {
|
||||
CAComponentDescription temp;
|
||||
GetComponentInfo (comp, &temp, NULL, NULL, NULL);
|
||||
|
||||
AUPluginInfoPtr plug(new AUPluginInfo);
|
||||
plug->name = AUPluginInfo::get_name (temp);
|
||||
plug->type = ARDOUR::AudioUnit;
|
||||
plug->n_inputs = 0;
|
||||
plug->n_outputs = 0;
|
||||
// plug->setup_nchannels (temp);
|
||||
plug->category = "AudioUnit";
|
||||
plug->desc = new CAComponentDescription(temp);
|
||||
|
||||
plugs.push_back(plug);
|
||||
AUPluginInfoPtr info (new AUPluginInfo (new CAComponentDescription(temp)));
|
||||
|
||||
/* no panners, format converters or i/o AU's for our purposes
|
||||
*/
|
||||
|
||||
switch (info->descriptor->Type()) {
|
||||
case kAudioUnitType_Panner:
|
||||
case kAudioUnitType_OfflineEffect:
|
||||
case kAudioUnitType_FormatConverter:
|
||||
continue;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (info->descriptor->SubType()) {
|
||||
case kAudioUnitSubType_DefaultOutput:
|
||||
case kAudioUnitSubType_SystemOutput:
|
||||
case kAudioUnitSubType_GenericOutput:
|
||||
case kAudioUnitSubType_AUConverter:
|
||||
continue;
|
||||
break;
|
||||
|
||||
case kAudioUnitSubType_DLSSynth:
|
||||
info->category = "DLSSynth";
|
||||
break;
|
||||
|
||||
case kAudioUnitType_MusicEffect:
|
||||
info->category = "MusicEffect";
|
||||
break;
|
||||
|
||||
case kAudioUnitSubType_Varispeed:
|
||||
info->category = "Varispeed";
|
||||
break;
|
||||
|
||||
case kAudioUnitSubType_Delay:
|
||||
info->category = "Delay";
|
||||
break;
|
||||
|
||||
case kAudioUnitSubType_LowPassFilter:
|
||||
info->category = "LowPassFilter";
|
||||
break;
|
||||
|
||||
case kAudioUnitSubType_HighPassFilter:
|
||||
info->category = "HighPassFilter";
|
||||
break;
|
||||
|
||||
case kAudioUnitSubType_BandPassFilter:
|
||||
info->category = "BandPassFilter";
|
||||
break;
|
||||
|
||||
case kAudioUnitSubType_HighShelfFilter:
|
||||
info->category = "HighShelfFilter";
|
||||
break;
|
||||
|
||||
case kAudioUnitSubType_LowShelfFilter:
|
||||
info->category = "LowShelfFilter";
|
||||
break;
|
||||
|
||||
case kAudioUnitSubType_ParametricEQ:
|
||||
info->category = "ParametricEQ";
|
||||
break;
|
||||
|
||||
case kAudioUnitSubType_GraphicEQ:
|
||||
info->category = "GraphicEQ";
|
||||
break;
|
||||
|
||||
case kAudioUnitSubType_PeakLimiter:
|
||||
info->category = "PeakLimiter";
|
||||
break;
|
||||
|
||||
case kAudioUnitSubType_DynamicsProcessor:
|
||||
info->category = "DynamicsProcessor";
|
||||
break;
|
||||
|
||||
case kAudioUnitSubType_MultiBandCompressor:
|
||||
info->category = "MultiBandCompressor";
|
||||
break;
|
||||
|
||||
case kAudioUnitSubType_MatrixReverb:
|
||||
info->category = "MatrixReverb";
|
||||
break;
|
||||
|
||||
case kAudioUnitType_Mixer:
|
||||
info->category = "Mixer";
|
||||
break;
|
||||
|
||||
case kAudioUnitSubType_StereoMixer:
|
||||
info->category = "StereoMixer";
|
||||
break;
|
||||
|
||||
case kAudioUnitSubType_3DMixer:
|
||||
info->category = "3DMixer";
|
||||
break;
|
||||
|
||||
case kAudioUnitSubType_MatrixMixer:
|
||||
info->category = "MatrixMixer";
|
||||
break;
|
||||
|
||||
default:
|
||||
info->category = "";
|
||||
}
|
||||
|
||||
AUPluginInfo::get_names (temp, info->name, info->creator);
|
||||
|
||||
info->type = ARDOUR::AudioUnit;
|
||||
info->unique_id = stringify_descriptor (*info->descriptor);
|
||||
|
||||
/* mark the plugin as having flexible i/o */
|
||||
|
||||
info->n_inputs = -1;
|
||||
info->n_outputs = -1;
|
||||
|
||||
|
||||
plugs.push_back (info);
|
||||
|
||||
comp = FindNextComponent (comp, &desc);
|
||||
}
|
||||
|
||||
return plugs;
|
||||
}
|
||||
|
||||
string
|
||||
AUPluginInfo::get_name (CAComponentDescription& comp_desc)
|
||||
void
|
||||
AUPluginInfo::get_names (CAComponentDescription& comp_desc, std::string& name, Glib::ustring& maker)
|
||||
{
|
||||
CFStringRef itemName = NULL;
|
||||
// Marc Poirier -style item name
|
||||
|
||||
// Marc Poirier-style item name
|
||||
CAComponent auComponent (comp_desc);
|
||||
if (auComponent.IsValid()) {
|
||||
CAComponentDescription dummydesc;
|
||||
|
|
@ -363,23 +721,36 @@ AUPluginInfo::get_name (CAComponentDescription& comp_desc)
|
|||
CFRelease(compManufacturerString);
|
||||
}
|
||||
|
||||
return CFStringRefToStdString(itemName);
|
||||
}
|
||||
string str = CFStringRefToStdString(itemName);
|
||||
string::size_type colon = str.find (':');
|
||||
|
||||
void
|
||||
AUPluginInfo::setup_nchannels (CAComponentDescription& comp_desc)
|
||||
{
|
||||
CAAudioUnit unit;
|
||||
|
||||
CAAudioUnit::Open (comp_desc, unit);
|
||||
|
||||
if (unit.SupportsNumChannels()) {
|
||||
n_inputs = n_outputs = 0;
|
||||
if (colon) {
|
||||
name = str.substr (colon+1);
|
||||
maker = str.substr (0, colon);
|
||||
// strip_whitespace_edges (maker);
|
||||
// strip_whitespace_edges (name);
|
||||
} else {
|
||||
AUChannelInfo cinfo;
|
||||
size_t info_size = sizeof(cinfo);
|
||||
OSStatus err = AudioUnitGetProperty (unit.AU(), kAudioUnitProperty_SupportedNumChannels, kAudioUnitScope_Global,
|
||||
0, &cinfo, &info_size);
|
||||
name = str;
|
||||
maker = "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
// from CAComponentDescription.cpp (in libs/appleutility in ardour source)
|
||||
extern char *StringForOSType (OSType t, char *writeLocation);
|
||||
|
||||
std::string
|
||||
AUPluginInfo::stringify_descriptor (const CAComponentDescription& desc)
|
||||
{
|
||||
char str[24];
|
||||
stringstream s;
|
||||
|
||||
s << StringForOSType (desc.Type(), str);
|
||||
s << " - ";
|
||||
|
||||
s << StringForOSType (desc.SubType(), str);
|
||||
s << " - ";
|
||||
|
||||
s << StringForOSType (desc.Manu(), str);
|
||||
|
||||
return s.str();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
#include <unistd.h>
|
||||
#include <cerrno>
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
|
||||
#include <glibmm/timer.h>
|
||||
#include <pbd/pthread_utils.h>
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ PluginInsert::PluginInsert (Session& s, boost::shared_ptr<Plugin> plug, Placemen
|
|||
|
||||
init ();
|
||||
|
||||
{
|
||||
if (_plugins[0]->fixed_io()) {
|
||||
Glib::Mutex::Lock em (_session.engine().process_lock());
|
||||
IO::MoreOutputs (output_streams ());
|
||||
}
|
||||
|
|
@ -94,7 +94,7 @@ PluginInsert::PluginInsert (Session& s, const XMLNode& node)
|
|||
|
||||
_plugins[0]->ParameterChanged.connect (mem_fun (*this, &PluginInsert::parameter_changed));
|
||||
|
||||
{
|
||||
if (_plugins[0]->fixed_io()) {
|
||||
Glib::Mutex::Lock em (_session.engine().process_lock());
|
||||
IO::MoreOutputs (output_streams());
|
||||
}
|
||||
|
|
@ -182,13 +182,24 @@ PluginInsert::auto_state_changed (uint32_t which)
|
|||
uint32_t
|
||||
PluginInsert::output_streams() const
|
||||
{
|
||||
return _plugins[0]->get_info()->n_outputs * _plugins.size();
|
||||
int32_t out = _plugins[0]->get_info()->n_outputs;
|
||||
|
||||
if (out < 0) {
|
||||
return _plugins[0]->output_streams ();
|
||||
} else {
|
||||
return out * _plugins.size();
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t
|
||||
PluginInsert::input_streams() const
|
||||
{
|
||||
return _plugins[0]->get_info()->n_inputs * _plugins.size();
|
||||
int32_t in = _plugins[0]->get_info()->n_inputs;
|
||||
if (in < 0) {
|
||||
return _plugins[0]->input_streams ();
|
||||
} else {
|
||||
return in * _plugins.size();
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t
|
||||
|
|
@ -366,12 +377,17 @@ PluginInsert::run (vector<Sample *>& bufs, uint32_t nbufs, nframes_t nframes, nf
|
|||
uint32_t in = _plugins[0]->get_info()->n_inputs;
|
||||
uint32_t out = _plugins[0]->get_info()->n_outputs;
|
||||
|
||||
if (out > in) {
|
||||
|
||||
/* not active, but something has make up for any channel count increase */
|
||||
if (in < 0 || out < 0) {
|
||||
|
||||
for (uint32_t n = out - in; n < out; ++n) {
|
||||
memcpy (bufs[n], bufs[in - 1], sizeof (Sample) * nframes);
|
||||
} else {
|
||||
|
||||
if (out > in) {
|
||||
|
||||
/* not active, but something has make up for any channel count increase */
|
||||
|
||||
for (uint32_t n = out - in; n < out; ++n) {
|
||||
memcpy (bufs[n], bufs[in - 1], sizeof (Sample) * nframes);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -528,7 +544,14 @@ PluginInsert::plugin_factory (boost::shared_ptr<Plugin> other)
|
|||
int32_t
|
||||
PluginInsert::compute_output_streams (int32_t cnt) const
|
||||
{
|
||||
return _plugins[0]->get_info()->n_outputs * cnt;
|
||||
int32_t outputs;
|
||||
|
||||
if ((outputs = _plugins[0]->get_info()->n_outputs) < 0) {
|
||||
// have to ask the plugin itself, because it has flexible I/O
|
||||
return _plugins[0]->compute_output_streams (cnt);
|
||||
}
|
||||
|
||||
return outputs * cnt;
|
||||
}
|
||||
|
||||
int32_t
|
||||
|
|
@ -543,6 +566,12 @@ PluginInsert::can_support_input_configuration (int32_t in) const
|
|||
int32_t outputs = _plugins[0]->get_info()->n_outputs;
|
||||
int32_t inputs = _plugins[0]->get_info()->n_inputs;
|
||||
|
||||
if (outputs < 0 || inputs < 0) {
|
||||
/* have to ask the plugin because its got reconfigurable I/O
|
||||
*/
|
||||
return _plugins[0]->can_support_input_configuration (in);
|
||||
}
|
||||
|
||||
if (inputs == 0) {
|
||||
|
||||
/* instrument plugin, always legal, but it throws
|
||||
|
|
@ -591,13 +620,7 @@ PluginInsert::state (bool full)
|
|||
node->add_child_nocopy (Redirect::state (full));
|
||||
|
||||
node->add_property ("type", _plugins[0]->state_node_name());
|
||||
snprintf(buf, sizeof(buf), "%s", _plugins[0]->name());
|
||||
node->add_property("id", string(buf));
|
||||
if (_plugins[0]->state_node_name() == "ladspa") {
|
||||
char buf[32];
|
||||
snprintf (buf, sizeof (buf), "%ld", _plugins[0]->get_info()->unique_id);
|
||||
node->add_property("unique-id", string(buf));
|
||||
}
|
||||
node->add_property("unique-id", _plugins[0]->unique_id());
|
||||
node->add_property("count", string_compose("%1", _plugins.size()));
|
||||
node->add_child_nocopy (_plugins[0]->get_state());
|
||||
|
||||
|
|
@ -641,7 +664,6 @@ PluginInsert::set_state(const XMLNode& node)
|
|||
XMLNodeIterator niter;
|
||||
XMLPropertyList plist;
|
||||
const XMLProperty *prop;
|
||||
long unique = 0;
|
||||
ARDOUR::PluginType type;
|
||||
|
||||
if ((prop = node.property ("type")) == 0) {
|
||||
|
|
@ -653,6 +675,8 @@ PluginInsert::set_state(const XMLNode& node)
|
|||
type = ARDOUR::LADSPA;
|
||||
} else if (prop->value() == X_("vst")) {
|
||||
type = ARDOUR::VST;
|
||||
} else if (prop->value() == X_("audiounit")) {
|
||||
type = ARDOUR::AudioUnit;
|
||||
} else {
|
||||
error << string_compose (_("unknown plugin type %1 in plugin insert state"),
|
||||
prop->value())
|
||||
|
|
@ -661,22 +685,27 @@ PluginInsert::set_state(const XMLNode& node)
|
|||
}
|
||||
|
||||
prop = node.property ("unique-id");
|
||||
if (prop != 0) {
|
||||
unique = atol(prop->value().c_str());
|
||||
}
|
||||
if (prop == 0) {
|
||||
#ifdef VST_SUPPORT
|
||||
/* older sessions contain VST plugins with only an "id" field.
|
||||
*/
|
||||
|
||||
if (type == ARDOUR::VST) {
|
||||
if (prop = node.property ("id")) {
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* recheck */
|
||||
|
||||
if ((prop = node.property ("id")) == 0) {
|
||||
error << _("XML node describing insert is missing the `id' field") << endmsg;
|
||||
return -1;
|
||||
if (prop == 0) {
|
||||
error << _("Plugin has no unique ID field") << endmsg;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
boost::shared_ptr<Plugin> plugin;
|
||||
|
||||
if (unique != 0) {
|
||||
plugin = find_plugin (_session, "", unique, type);
|
||||
} else {
|
||||
plugin = find_plugin (_session, prop->value(), 0, type);
|
||||
}
|
||||
plugin = find_plugin (_session, prop->value(), type);
|
||||
|
||||
if (plugin == 0) {
|
||||
error << string_compose(_("Found a reference to a plugin (\"%1\") that is unknown.\n"
|
||||
|
|
|
|||
|
|
@ -157,6 +157,15 @@ LadspaPlugin::~LadspaPlugin ()
|
|||
}
|
||||
}
|
||||
|
||||
string
|
||||
LadspaPlugin::unique_id() const
|
||||
{
|
||||
char buf[32];
|
||||
snprintf (buf, sizeof (buf), "%u", descriptor->UniqueID);
|
||||
return string (buf);
|
||||
}
|
||||
|
||||
|
||||
float
|
||||
LadspaPlugin::default_value (uint32_t port)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -42,6 +42,10 @@
|
|||
#include <ardour/ladspa_plugin.h>
|
||||
#include <ardour/plugin_manager.h>
|
||||
|
||||
#ifdef HAVE_AUDIOUNITS
|
||||
#include <ardour/audio_unit.h>
|
||||
#endif
|
||||
|
||||
#include <pbd/stl_delete.h>
|
||||
|
||||
#include "i18n.h"
|
||||
|
|
@ -192,7 +196,21 @@ vector<string>
|
|||
Plugin::get_presets()
|
||||
{
|
||||
vector<string> labels;
|
||||
lrdf_uris* set_uris = lrdf_get_setting_uris(unique_id());
|
||||
uint32_t id;
|
||||
std::string unique (unique_id());
|
||||
|
||||
/* XXX problem: AU plugins don't have numeric ID's.
|
||||
Solution: they have a different method of providing presets.
|
||||
XXX sub-problem: implement it.
|
||||
*/
|
||||
|
||||
if (!isdigit (unique[0])) {
|
||||
return labels;
|
||||
}
|
||||
|
||||
id = atol (unique.c_str());
|
||||
|
||||
lrdf_uris* set_uris = lrdf_get_setting_uris(id);
|
||||
|
||||
if (set_uris) {
|
||||
for (uint32_t i = 0; i < (uint32_t) set_uris->count; ++i) {
|
||||
|
|
@ -234,6 +252,20 @@ Plugin::save_preset (string name, string domain)
|
|||
{
|
||||
lrdf_portvalue portvalues[parameter_count()];
|
||||
lrdf_defaults defaults;
|
||||
uint32_t id;
|
||||
std::string unique (unique_id());
|
||||
|
||||
/* XXX problem: AU plugins don't have numeric ID's.
|
||||
Solution: they have a different method of providing/saving presets.
|
||||
XXX sub-problem: implement it.
|
||||
*/
|
||||
|
||||
if (!isdigit (unique[0])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
id = atol (unique.c_str());
|
||||
|
||||
defaults.count = parameter_count();
|
||||
defaults.items = portvalues;
|
||||
|
||||
|
|
@ -252,7 +284,7 @@ Plugin::save_preset (string name, string domain)
|
|||
|
||||
string source(string_compose("file:%1/.%2/rdf/ardour-presets.n3", envvar, domain));
|
||||
|
||||
free(lrdf_add_preset(source.c_str(), name.c_str(), unique_id(), &defaults));
|
||||
free(lrdf_add_preset(source.c_str(), name.c_str(), id, &defaults));
|
||||
|
||||
string path = string_compose("%1/.%2", envvar, domain);
|
||||
if (g_mkdir_with_parents (path.c_str(), 0775)) {
|
||||
|
|
@ -275,7 +307,7 @@ Plugin::save_preset (string name, string domain)
|
|||
}
|
||||
|
||||
PluginPtr
|
||||
ARDOUR::find_plugin(Session& session, string name, long unique_id, PluginType type)
|
||||
ARDOUR::find_plugin(Session& session, string identifier, PluginType type)
|
||||
{
|
||||
PluginManager *mgr = PluginManager::the_manager();
|
||||
PluginInfoList plugs;
|
||||
|
|
@ -288,14 +320,12 @@ ARDOUR::find_plugin(Session& session, string name, long unique_id, PluginType ty
|
|||
#ifdef VST_SUPPORT
|
||||
case ARDOUR::VST:
|
||||
plugs = mgr->vst_plugin_info();
|
||||
unique_id = 0; // VST plugins don't have a unique id.
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_AUDIOUNITS
|
||||
case ARDOUR::AudioUnit:
|
||||
plugs = AUPluginInfo::discover ();
|
||||
unique_id = 0; // Neither do AU.
|
||||
plugs = mgr->au_plugin_info();
|
||||
break;
|
||||
#endif
|
||||
|
||||
|
|
@ -304,13 +334,49 @@ ARDOUR::find_plugin(Session& session, string name, long unique_id, PluginType ty
|
|||
}
|
||||
|
||||
PluginInfoList::iterator i;
|
||||
|
||||
for (i = plugs.begin(); i != plugs.end(); ++i) {
|
||||
if ((name == "" || (*i)->name == name) &&
|
||||
(unique_id == 0 || (*i)->unique_id == unique_id)) {
|
||||
return (*i)->load (session);
|
||||
if (identifier == (*i)->unique_id){
|
||||
return (*i)->load (session);
|
||||
}
|
||||
}
|
||||
|
||||
return PluginPtr ((Plugin*) 0);
|
||||
}
|
||||
int32_t
|
||||
Plugin::can_support_input_configuration (int32_t in)
|
||||
{
|
||||
/* LADSPA & VST should not get here because they do not
|
||||
return negative i/o counts.
|
||||
*/
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t
|
||||
Plugin::compute_output_streams (int32_t nplugins)
|
||||
{
|
||||
/* LADSPA & VST should not get here because they do not
|
||||
return negative i/o counts.
|
||||
*/
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
Plugin::output_streams () const
|
||||
{
|
||||
/* LADSPA & VST should not get here because they do not
|
||||
return negative i/o counts.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
Plugin::input_streams () const
|
||||
{
|
||||
/* LADSPA & VST should not get here because they do not
|
||||
return negative i/o counts.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -40,6 +40,10 @@
|
|||
#include <ardour/vst_plugin.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_AUDIOUNITS
|
||||
#include <ardour/audio_unit.h>
|
||||
#endif
|
||||
|
||||
#include <pbd/error.h>
|
||||
#include <pbd/stl_delete.h>
|
||||
|
||||
|
|
@ -109,6 +113,9 @@ PluginManager::refresh ()
|
|||
vst_refresh ();
|
||||
}
|
||||
#endif // VST_SUPPORT
|
||||
#ifdef HAVE_AUDIOUNITS
|
||||
au_refresh ();
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -123,6 +130,7 @@ PluginManager::ladspa_refresh ()
|
|||
ladspa_discover_from_path (ladspa_path);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
PluginManager::add_ladspa_directory (string path)
|
||||
{
|
||||
|
|
@ -273,7 +281,10 @@ PluginManager::ladspa_discover (string path)
|
|||
info->n_inputs = 0;
|
||||
info->n_outputs = 0;
|
||||
info->type = ARDOUR::LADSPA;
|
||||
info->unique_id = descriptor->UniqueID;
|
||||
|
||||
char buf[32];
|
||||
snprintf (buf, sizeof (buf), "%u", descriptor->UniqueID);
|
||||
info->unique_id = buf;
|
||||
|
||||
for (uint32_t n=0; n < descriptor->PortCount; ++n) {
|
||||
if ( LADSPA_IS_PORT_AUDIO (descriptor->PortDescriptors[n]) ) {
|
||||
|
|
@ -310,7 +321,7 @@ PluginManager::get_ladspa_category (uint32_t plugin_id)
|
|||
lrdf_statement* matches1 = lrdf_matches (&pattern);
|
||||
|
||||
if (!matches1) {
|
||||
return _("Unknown");
|
||||
return _("");
|
||||
}
|
||||
|
||||
pattern.subject = matches1->object;
|
||||
|
|
@ -322,7 +333,7 @@ PluginManager::get_ladspa_category (uint32_t plugin_id)
|
|||
lrdf_free_statements(matches1);
|
||||
|
||||
if (!matches2) {
|
||||
return _("Unknown");
|
||||
return _("");
|
||||
}
|
||||
|
||||
string label = matches2->object;
|
||||
|
|
@ -331,6 +342,22 @@ PluginManager::get_ladspa_category (uint32_t plugin_id)
|
|||
return label;
|
||||
}
|
||||
|
||||
#ifdef HAVE_AUDIOUNITS
|
||||
void
|
||||
PluginManager::au_refresh ()
|
||||
{
|
||||
au_discover();
|
||||
}
|
||||
|
||||
int
|
||||
PluginManager::au_discover ()
|
||||
{
|
||||
_au_plugin_info = AUPluginInfo::discover();
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef VST_SUPPORT
|
||||
|
||||
void
|
||||
|
|
@ -389,6 +416,7 @@ int
|
|||
PluginManager::vst_discover (string path)
|
||||
{
|
||||
FSTInfo* finfo;
|
||||
char buf[32];
|
||||
|
||||
if ((finfo = fst_get_info (const_cast<char *> (path.c_str()))) == 0) {
|
||||
warning << "Cannot get VST information from " << path << endmsg;
|
||||
|
|
@ -411,6 +439,9 @@ PluginManager::vst_discover (string path)
|
|||
info->name = finfo->name;
|
||||
}
|
||||
|
||||
|
||||
snprintf (buf, sizeof (buf), "%d", finfo->uniqueID);
|
||||
info->uniqueID = buf;
|
||||
info->category = "VST";
|
||||
info->path = path;
|
||||
// need to set info->creator but FST doesn't provide it
|
||||
|
|
|
|||
|
|
@ -1263,7 +1263,13 @@ Route::check_some_plugin_counts (list<InsertCount>& iclist, int32_t required_inp
|
|||
}
|
||||
|
||||
(*i).in = required_inputs;
|
||||
(*i).out = (*i).insert->compute_output_streams ((*i).cnt);
|
||||
|
||||
if (((*i).out = (*i).insert->compute_output_streams ((*i).cnt)) < 0) {
|
||||
if (err_streams) {
|
||||
*err_streams = required_inputs;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
required_inputs = (*i).out;
|
||||
}
|
||||
|
|
@ -1560,22 +1566,29 @@ Route::add_redirect_from_xml (const XMLNode& node)
|
|||
if ((prop = node.property ("type")) != 0) {
|
||||
|
||||
boost::shared_ptr<Insert> insert;
|
||||
bool have_insert = false;
|
||||
|
||||
if (prop->value() == "ladspa" || prop->value() == "Ladspa" || prop->value() == "vst") {
|
||||
|
||||
if (prop->value() == "ladspa" || prop->value() == "Ladspa" ||
|
||||
prop->value() == "vst" ||
|
||||
prop->value() == "audiounit") {
|
||||
|
||||
insert.reset (new PluginInsert(_session, node));
|
||||
have_insert = true;
|
||||
|
||||
} else if (prop->value() == "port") {
|
||||
|
||||
|
||||
insert.reset (new PortInsert (_session, node));
|
||||
have_insert = true;
|
||||
|
||||
} else {
|
||||
|
||||
error << string_compose(_("unknown Insert type \"%1\"; ignored"), prop->value()) << endmsg;
|
||||
}
|
||||
|
||||
add_redirect (insert, this);
|
||||
if (have_insert) {
|
||||
add_redirect (insert, this);
|
||||
}
|
||||
|
||||
} else {
|
||||
error << _("Insert XML node has no type property") << endmsg;
|
||||
|
|
|
|||
|
|
@ -141,7 +141,7 @@ VSTPlugin::get_state()
|
|||
{
|
||||
XMLNode *root = new XMLNode (state_node_name());
|
||||
LocaleGuard lg (X_("POSIX"));
|
||||
|
||||
|
||||
if (_plugin->flags & effFlagsProgramChunks) {
|
||||
|
||||
/* fetch the current chunk */
|
||||
|
|
@ -408,10 +408,12 @@ VSTPlugin::activate ()
|
|||
_plugin->dispatcher (_plugin, effMainsChanged, 0, 1, NULL, 0.0f);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
string
|
||||
VSTPlugin::unique_id() const
|
||||
{
|
||||
return _plugin->uniqueID;
|
||||
char buf[32];
|
||||
snprintf (buf, sizeof (buf), "%d", _plugin->uniqueID);
|
||||
return string (buf);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue