diff options
author | Paul Davis <paul@linuxaudiosystems.com> | 2008-05-15 00:52:54 +0000 |
---|---|---|
committer | Paul Davis <paul@linuxaudiosystems.com> | 2008-05-15 00:52:54 +0000 |
commit | cb78405ec29e8648839a25861179da9102b69c72 (patch) | |
tree | 7691ccd053acda822f3af5921da58a84a07282b1 /libs | |
parent | 3ecc9b4f75b6201efdf5550421423861191d79ec (diff) |
lots and lots of work to correctly deduce AU IO configurations and related issues
git-svn-id: svn://localhost/ardour2/branches/2.0-ongoing@3349 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs')
-rw-r--r-- | libs/appleutility/CAAudioUnit.cpp | 2 | ||||
-rw-r--r-- | libs/appleutility/CAAudioUnit.h | 1 | ||||
-rw-r--r-- | libs/ardour/ardour/audio_unit.h | 32 | ||||
-rw-r--r-- | libs/ardour/ardour/insert.h | 10 | ||||
-rw-r--r-- | libs/ardour/ardour/plugin.h | 7 | ||||
-rw-r--r-- | libs/ardour/audio_unit.cc | 477 | ||||
-rw-r--r-- | libs/ardour/globals.cc | 8 | ||||
-rw-r--r-- | libs/ardour/insert.cc | 96 | ||||
-rw-r--r-- | libs/ardour/plugin.cc | 53 | ||||
-rw-r--r-- | libs/ardour/plugin_manager.cc | 9 | ||||
-rw-r--r-- | libs/ardour/route.cc | 18 |
11 files changed, 480 insertions, 233 deletions
diff --git a/libs/appleutility/CAAudioUnit.cpp b/libs/appleutility/CAAudioUnit.cpp index 3d8a98476a..aaf57f233d 100644 --- a/libs/appleutility/CAAudioUnit.cpp +++ b/libs/appleutility/CAAudioUnit.cpp @@ -328,7 +328,7 @@ bool CAAudioUnit::CanDo ( int inChannelsIn, return ValidateChannelPair (inChannelsIn, inChannelsOut, info.mChanInfo, (dataSize / sizeof (AUChannelInfo))); } -int CAAudioUnit::GetChannelInfo (AUChannelInfo** chaninfo, uint32_t& cnt) +int CAAudioUnit::GetChannelInfo (AUChannelInfo** chaninfo, UInt32& cnt) { // this is the default assumption of an audio effect unit Boolean* isWritable = 0; diff --git a/libs/appleutility/CAAudioUnit.h b/libs/appleutility/CAAudioUnit.h index 6bc31bf30b..810b81be2f 100644 --- a/libs/appleutility/CAAudioUnit.h +++ b/libs/appleutility/CAAudioUnit.h @@ -218,6 +218,7 @@ public: bool HasChannelLayouts (AudioUnitScope inScope, AudioUnitElement inEl) const; + int GetChannelInfo (AUChannelInfo** chaninfo, UInt32& cnt); bool GetChannelLayouts (AudioUnitScope inScope, AudioUnitElement inEl, ChannelTagVector &outChannelVector) const; diff --git a/libs/ardour/ardour/audio_unit.h b/libs/ardour/ardour/audio_unit.h index 98bda912f7..07986782e2 100644 --- a/libs/ardour/ardour/audio_unit.h +++ b/libs/ardour/ardour/audio_unit.h @@ -99,11 +99,10 @@ 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); + int32_t can_do (int32_t in, int32_t& out); uint32_t output_streams() const; uint32_t input_streams() const; + int32_t configure_io (int32_t in, int32_t out); boost::shared_ptr<CAAudioUnit> get_au () { return unit; } boost::shared_ptr<CAComponent> get_comp () const { return comp; } @@ -117,18 +116,19 @@ class AUPlugin : public ARDOUR::Plugin boost::shared_ptr<CAComponent> comp; boost::shared_ptr<CAAudioUnit> unit; - AudioStreamBasicDescription streamFormat; bool initialized; - int format_set; + int32_t input_channels; + int32_t output_channels; + std::vector<std::pair<int,int> > io_configs; 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_output_format (AudioStreamBasicDescription&); + int set_input_format (AudioStreamBasicDescription&); + int set_stream_format (int scope, uint32_t cnt, AudioStreamBasicDescription&); int _set_block_size (nframes_t nframes); void discover_parameters (); @@ -156,23 +156,29 @@ class AUPluginInfo : public PluginInfo { PluginPtr load (Session& session); + AUPluginCachedInfo cache; + static PluginInfoList discover (); static void get_names (CAComponentDescription&, std::string& name, Glib::ustring& maker); static std::string stringify_descriptor (const CAComponentDescription&); + static int load_cached_info (); + private: boost::shared_ptr<CAComponentDescription> descriptor; + UInt32 version; static void discover_music (PluginInfoList&); static void discover_fx (PluginInfoList&); static void discover_by_description (PluginInfoList&, CAComponentDescription&); + static Glib::ustring au_cache_path (); - static std::map<std::string,AUPluginCachedInfo> cached_info; - - static bool cached_io_configuration (std::string, CAComponentDescription&, AUPluginCachedInfo&); - static void add_cached_info (AUPluginCachedInfo&); + typedef std::map<std::string,AUPluginCachedInfo> CachedInfoMap; + static CachedInfoMap cached_info; + + static bool cached_io_configuration (const std::string&, UInt32, CAComponent&, AUPluginCachedInfo&, const std::string& name); + static void add_cached_info (const std::string&, AUPluginCachedInfo&); static void save_cached_info (); - static int load_cached_info (); }; typedef boost::shared_ptr<AUPluginInfo> AUPluginInfoPtr; diff --git a/libs/ardour/ardour/insert.h b/libs/ardour/ardour/insert.h index dd2d06c06f..8691a292b1 100644 --- a/libs/ardour/ardour/insert.h +++ b/libs/ardour/ardour/insert.h @@ -53,9 +53,8 @@ class Insert : public Redirect virtual void activate () {} virtual void deactivate () {} - virtual int32_t can_support_input_configuration (int32_t in) const = 0; + virtual int32_t can_do (int32_t in, int32_t& out) = 0; virtual int32_t configure_io (int32_t magic, int32_t in, int32_t out) = 0; - virtual int32_t compute_output_streams (int32_t cnt) const = 0; }; class PortInsert : public Insert @@ -78,10 +77,8 @@ class PortInsert : public Insert uint32_t output_streams() const; uint32_t input_streams() const; - int32_t can_support_input_configuration (int32_t) const; + int32_t can_do (int32_t, int32_t& out); int32_t configure_io (int32_t magic, int32_t in, int32_t out); - int32_t compute_output_streams (int32_t cnt) const; - uint32_t bit_slot() const { return bitslot; } private: @@ -117,9 +114,8 @@ class PluginInsert : public Insert int set_count (uint32_t num); uint32_t get_count () const { return _plugins.size(); } - int32_t can_support_input_configuration (int32_t) const; + int32_t can_do (int32_t, int32_t& out); int32_t configure_io (int32_t magic, int32_t in, int32_t out); - int32_t compute_output_streams (int32_t cnt) const; bool is_generator() const; diff --git a/libs/ardour/ardour/plugin.h b/libs/ardour/ardour/plugin.h index 869a0f395c..abf2867dec 100644 --- a/libs/ardour/ardour/plugin.h +++ b/libs/ardour/ardour/plugin.h @@ -143,12 +143,11 @@ class Plugin : public PBD::StatefulDestructible 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 int32_t can_do (int32_t in, int32_t& out); virtual uint32_t output_streams() const; virtual uint32_t input_streams() const; - + virtual int32_t configure_io (int32_t in, int32_t out); + PBD::Controllable *get_nth_control (uint32_t, bool do_not_create = false); void make_nth_control (uint32_t, const XMLNode&); diff --git a/libs/ardour/audio_unit.cc b/libs/ardour/audio_unit.cc index 2e38f86be1..5544ba2e0e 100644 --- a/libs/ardour/audio_unit.cc +++ b/libs/ardour/audio_unit.cc @@ -24,7 +24,10 @@ #include <pbd/whitespace.h> #include <glibmm/thread.h> +#include <glibmm/fileutils.h> +#include <glibmm/miscutils.h> +#include <ardour/ardour.h> #include <ardour/audioengine.h> #include <ardour/io.h> #include <ardour/audio_unit.h> @@ -43,6 +46,8 @@ using namespace std; using namespace PBD; using namespace ARDOUR; +AUPluginInfo::CachedInfoMap AUPluginInfo::cached_info; + static OSStatus _render_callback(void *userData, AudioUnitRenderActionFlags *ioActionFlags, @@ -120,28 +125,12 @@ AUPlugin::init () 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; - -#ifdef __LITTLE_ENDIAN__ - /* relax */ -#else - streamFormat.mFormatFlags |= kAudioFormatFlagIsBigEndian; -#endif - - streamFormat.mBitsPerChannel = 32; - streamFormat.mFramesPerPacket = 1; - - // subject to later modification as we discover channel counts - - streamFormat.mBytesPerPacket = 4; - streamFormat.mBytesPerFrame = 4; - streamFormat.mChannelsPerFrame = 1; + /* these keep track of *configured* channel set up, + not potential set ups. + */ - format_set = 0; + input_channels = -1; + output_channels = -1; if (_set_block_size (_session.get_block_size())) { error << _("AUPlugin: cannot set processing block size") << endmsg; @@ -392,59 +381,227 @@ AUPlugin::_set_block_size (nframes_t nframes) return 0; } -int32_t -AUPlugin::can_support_input_configuration (int32_t in) -{ -#ifdef NEWSTUFF - CAChannelHelper ch_in; - CAChannelHelper ch_out; - - ch_in.nNumEls = input_elements; +int32_t +AUPlugin::configure_io (int32_t in, int32_t out) +{ + AudioStreamBasicDescription streamFormat; - for (uint32_t n = 0; n < input_elements; ++n) { - ch_in.mChans[n] = in; - } + streamFormat.mSampleRate = _session.frame_rate(); + streamFormat.mFormatID = kAudioFormatLinearPCM; + streamFormat.mFormatFlags = kAudioFormatFlagIsFloat|kAudioFormatFlagIsPacked|kAudioFormatFlagIsNonInterleaved; - /* don't check output */ +#ifdef __LITTLE_ENDIAN__ + /* relax */ +#else + streamFormat.mFormatFlags |= kAudioFormatFlagIsBigEndian; +#endif - ch_out.nNumEls = 0; + streamFormat.mBitsPerChannel = 32; + streamFormat.mFramesPerPacket = 1; - return unit->CanDo (ch_in, ch_out); - -#endif - streamFormat.mChannelsPerFrame = in; /* apple says that for non-interleaved data, these values always refer to a single channel. */ streamFormat.mBytesPerPacket = 4; streamFormat.mBytesPerFrame = 4; - if (set_input_format () == 0) { - return 1; - } else { + streamFormat.mChannelsPerFrame = in; + + if (set_input_format (streamFormat) != 0) { return -1; } + + streamFormat.mChannelsPerFrame = out; + + if (set_output_format (streamFormat) != 0) { + return -1; + } + + return Plugin::configure_io (in, out); +} + +int32_t +AUPlugin::can_do (int32_t in, int32_t& out) +{ + // XXX as of May 13th 2008, AU plugin support returns a count of either 1 or -1. We never + // attempt to multiply-instantiate plugins to meet io configurations. + + int32_t plugcnt = -1; + AUPluginInfoPtr pinfo = boost::dynamic_pointer_cast<AUPluginInfo>(get_info()); + + out = -1; + + vector<pair<int,int> >& io_configs = pinfo->cache.io_configs; + + for (vector<pair<int,int> >::iterator i = io_configs.begin(); i != io_configs.end(); ++i) { + + int32_t possible_in = i->first; + int32_t possible_out = i->second; + + if (possible_out == 0) { + warning << string_compose (_("AU %1 has zero outputs - configuration ignored"), name()) << endmsg; + continue; + } + + if (possible_in == 0) { + + /* instrument plugin, always legal but throws away inputs ... + */ + + if (possible_out == -1) { + /* out much match in (UNLIKELY!!) */ + out = in; + plugcnt = 1; + } else if (possible_out == -2) { + /* any configuration possible, pick matching */ + out = in; + plugcnt = 1; + } else if (possible_out < -2) { + /* explicit variable number of outputs, pick maximum */ + out = -possible_out; + plugcnt = 1; + } else { + /* exact number of outputs */ + out = possible_out; + plugcnt = 1; + } + } + + if (possible_in == -1) { + + /* wildcard for input */ + + if (possible_out == -1) { + /* out much match in */ + out = in; + plugcnt = 1; + } else if (possible_out == -2) { + /* any configuration possible, pick matching */ + out = in; + plugcnt = 1; + } else if (possible_out < -2) { + /* explicit variable number of outputs, pick maximum */ + out = -possible_out; + plugcnt = 1; + } else { + /* exact number of outputs */ + out = possible_out; + plugcnt = 1; + } + } + + if (possible_in == -2) { + + if (possible_out == -1) { + /* any configuration possible, pick matching */ + out = in; + plugcnt = 1; + } else if (possible_out == -2) { + error << string_compose (_("AU plugin %1 has illegal IO configuration (-2,-2)"), name()) + << endmsg; + plugcnt = -1; + } else if (possible_out < -2) { + /* explicit variable number of outputs, pick maximum */ + out = -possible_out; + plugcnt = 1; + } else { + /* exact number of outputs */ + out = possible_out; + plugcnt = 1; + } + } + + if (possible_in < -2) { + + /* explicit variable number of inputs */ + + if (in > -possible_in) { + /* request is too large */ + plugcnt = -1; + } + + if (possible_out == -1) { + /* out must match in */ + out = in; + plugcnt = 1; + } else if (possible_out == -2) { + error << string_compose (_("AU plugin %1 has illegal IO configuration (-2,-2)"), name()) + << endmsg; + plugcnt = -1; + } else if (possible_out < -2) { + /* explicit variable number of outputs, pick maximum */ + out = -possible_out; + plugcnt = 1; + } else { + /* exact number of outputs */ + out = possible_out; + plugcnt = 1; + } + } + + if (possible_in == in) { + + /* exact number of inputs ... must match obviously */ + + if (possible_out == -1) { + /* out must match in */ + out = in; + plugcnt = 1; + } else if (possible_out == -2) { + /* any output configuration, pick matching */ + out = in; + plugcnt = -1; + } else if (possible_out < -2) { + /* explicit variable number of outputs, pick maximum */ + out = -possible_out; + plugcnt = 1; + } else { + /* exact number of outputs */ + out = possible_out; + plugcnt = 1; + } + } + + } + + /* no fit */ + return plugcnt; } int -AUPlugin::set_input_format () +AUPlugin::set_input_format (AudioStreamBasicDescription& fmt) { - return set_stream_format (kAudioUnitScope_Input, input_elements); + return set_stream_format (kAudioUnitScope_Input, input_elements, fmt); } int -AUPlugin::set_output_format () +AUPlugin::set_output_format (AudioStreamBasicDescription& fmt) { - return set_stream_format (kAudioUnitScope_Output, output_elements); + if (set_stream_format (kAudioUnitScope_Output, output_elements, fmt) != 0) { + return -1; + } + + if (buffers) { + free (buffers); + buffers = 0; + } + + buffers = (AudioBufferList *) malloc (offsetof(AudioBufferList, mBuffers) + + fmt.mChannelsPerFrame * sizeof(AudioBuffer)); + + Glib::Mutex::Lock em (_session.engine().process_lock()); + IO::MoreOutputs (fmt.mChannelsPerFrame); + + return 0; } int -AUPlugin::set_stream_format (int scope, uint32_t cnt) +AUPlugin::set_stream_format (int scope, uint32_t cnt, AudioStreamBasicDescription& fmt) { OSErr result; for (uint32_t i = 0; i < cnt; ++i) { - if ((result = unit->SetFormat (scope, i, streamFormat)) != 0) { + if ((result = unit->SetFormat (scope, i, fmt)) != 0) { error << string_compose (_("AUPlugin: could not set stream format for %1/%2 (err = %3)"), (scope == kAudioUnitScope_Input ? "input" : "output"), i, result) << endmsg; return -1; @@ -452,60 +609,33 @@ AUPlugin::set_stream_format (int scope, uint32_t cnt) } if (scope == kAudioUnitScope_Input) { - format_set |= 0x1; + input_channels = fmt.mChannelsPerFrame; } else { - format_set |= 0x2; + output_channels = fmt.mChannelsPerFrame; } 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 +AUPlugin::input_streams() const { - if (!(format_set & 0x2)) { - warning << string_compose (_("AUPlugin: %1 output_streams() called without any format set!"), name()) << endmsg; + if (input_channels < 0) { + warning << string_compose (_("AUPlugin: %1 input_streams() called without any format set!"), name()) << endmsg; return 1; } - - return streamFormat.mChannelsPerFrame; + return input_channels; } uint32_t -AUPlugin::input_streams() const +AUPlugin::output_streams() const { - if (!(format_set & 0x1)) { - warning << _("AUPlugin: input_streams() called without any format set!") << endmsg; + if (output_channels < 0) { + warning << string_compose (_("AUPlugin: %1 output_streams() called without any format set!"), name()) << endmsg; return 1; } - return streamFormat.mChannelsPerFrame; + return output_channels; } OSStatus @@ -692,13 +822,25 @@ AUPluginInfo::load (Session& session) } catch (failed_constructor &err) { - return PluginPtr ((Plugin*) 0); + return PluginPtr (); } } +Glib::ustring +AUPluginInfo::au_cache_path () +{ + return Glib::build_filename (ARDOUR::get_user_ardour_path(), "au_cache"); +} + PluginInfoList AUPluginInfo::discover () { + XMLTree tree; + + if (!Glib::file_test (au_cache_path(), Glib::FILE_TEST_EXISTS)) { + ARDOUR::BootMessage (_("Discovering AudioUnit plugins (could take some time ...)")); + } + PluginInfoList plugs; discover_fx (plugs); @@ -851,44 +993,76 @@ AUPluginInfo::discover_by_description (PluginInfoList& plugs, CAComponentDescrip info->type = ARDOUR::AudioUnit; info->unique_id = stringify_descriptor (*info->descriptor); + + /* XXX not sure of the best way to handle plugin versioning yet + */ + + CAComponent cacomp (*info->descriptor); + + if (cacomp.GetResourceVersion (info->version) != noErr) { + info->version = 0; + } - AUPluginCachedInfo cinfo; + if (cached_io_configuration (info->unique_id, info->version, cacomp, info->cache, info->name)) { - if (cached_io_configuration (info->unique_id(), *info->descriptor, cinfo)) { + /* here we have to map apple's wildcard system to a simple pair + of values. + */ - info->n_inputs = cinfo->in; - info->n_outputs = cinfo->out; + info->n_inputs = info->cache.io_configs.front().first; + info->n_outputs = info->cache.io_configs.front().second; + + if (info->cache.io_configs.size() > 1) { + cerr << "ODD: variable IO config for " << info->unique_id << endl; + } + + plugs.push_back (info); } else { - - /* mark the plugin as having flexible i/o */ - - info->n_inputs = -1; - info->n_outputs = -1; + error << string_compose (_("Cannot get I/O configuration info for AU %1"), info->name) << endmsg; } - - plugs.push_back (info); comp = FindNextComponent (comp, &desc); } } bool -AUPluginInfo::cached_io_configuration (std::string unique_id, CAComponentDescriptor& descriptor, AUPluginCachedInfo& cinfo) +AUPluginInfo::cached_io_configuration (const std::string& unique_id, + UInt32 version, + CAComponent& comp, + AUPluginCachedInfo& cinfo, + const std::string& name) { - CachedInfoMap::iterator cim = cached_info.find (unique_id); + std::string id; + char buf[32]; + + /* concatenate unique ID with version to provide a key for cached info lookup. + this ensures we don't get stale information, or should if plugin developers + follow Apple "guidelines". + */ + + snprintf (buf, sizeof (buf), "%u", version); + id = unique_id; + id += '/'; + id += buf; + + CachedInfoMap::iterator cim = cached_info.find (id); if (cim != cached_info.end()) { - cinfo = *cim; + cinfo = cim->second; return true; } - CAComponent comp (descriptor); - CAAudioUnit unit (comp); + CAAudioUnit unit; AUChannelInfo* channel_info; - uint32_t cnt; + UInt32 cnt; int ret; - + + ARDOUR::BootMessage (string_compose (_("Checking AudioUnit: %1"), name)); + + if (CAAudioUnit::Open (comp, unit) != noErr) { + return false; + } if ((ret = unit.GetChannelInfo (&channel_info, cnt)) < 0) { return false; @@ -911,15 +1085,14 @@ AUPluginInfo::cached_io_configuration (std::string unique_id, CAComponentDescrip free (channel_info); } - - add_cached_info (unique_id, cinfo); + add_cached_info (id, cinfo); save_cached_info (); return true; } void -AUPluginInfo::add_cached_info (std::string id, AUPluginCachedInfo& cinfo) +AUPluginInfo::add_cached_info (const std::string& id, AUPluginCachedInfo& cinfo) { cached_info[id] = cinfo; } @@ -927,19 +1100,103 @@ AUPluginInfo::add_cached_info (std::string id, AUPluginCachedInfo& cinfo) void AUPluginInfo::save_cached_info () { + XMLNode* node; + + node = new XMLNode (X_("AudioUnitPluginCache")); + for (map<string,AUPluginCachedInfo>::iterator i = cached_info.begin(); i != cached_info.end(); ++i) { - cerr << i->first << ' '; + XMLNode* parent = new XMLNode (X_("plugin")); + parent->add_property ("id", i->first); + node->add_child_nocopy (*parent); + for (vector<pair<int, int> >::iterator j = i->second.io_configs.begin(); j != i->second.io_configs.end(); ++j) { - cerr << j->first << ' ' << j->second; + + XMLNode* child = new XMLNode (X_("io")); + char buf[32]; + + snprintf (buf, sizeof (buf), "%d", j->first); + child->add_property (X_("in"), buf); + snprintf (buf, sizeof (buf), "%d", j->second); + child->add_property (X_("out"), buf); + parent->add_child_nocopy (*child); } - cerr << endl; + + } + + Glib::ustring path = au_cache_path (); + XMLTree tree; + + tree.set_root (node); + + if (!tree.write (path)) { + error << string_compose (_("could not save AU cache to %1"), path) << endmsg; + unlink (path.c_str()); } } -void +int AUPluginInfo::load_cached_info () { + Glib::ustring path = au_cache_path (); + XMLTree tree; + + if (!Glib::file_test (path, Glib::FILE_TEST_EXISTS)) { + return 0; + } + + tree.read (path); + const XMLNode* root (tree.root()); + + if (root->name() != X_("AudioUnitPluginCache")) { + return -1; + } + + cached_info.clear (); + + const XMLNodeList children = root->children(); + + for (XMLNodeConstIterator iter = children.begin(); iter != children.end(); ++iter) { + + const XMLNode* child = *iter; + + if (child->name() == X_("plugin")) { + + const XMLNode* gchild; + const XMLNodeList gchildren = child->children(); + const XMLProperty* prop = child->property (X_("id")); + + if (!prop) { + continue; + } + std::string id = prop->value(); + + for (XMLNodeConstIterator giter = gchildren.begin(); giter != gchildren.end(); giter++) { + + gchild = *giter; + + if (gchild->name() == X_("io")) { + + int in; + int out; + const XMLProperty* iprop; + const XMLProperty* oprop; + + if (((iprop = gchild->property (X_("in"))) != 0) && + ((oprop = gchild->property (X_("out"))) != 0)) { + in = atoi (iprop->value()); + out = atoi (iprop->value()); + + AUPluginCachedInfo cinfo; + cinfo.io_configs.push_back (pair<int,int> (in, out)); + add_cached_info (id, cinfo); + } + } + } + } + } + + return 0; } void diff --git a/libs/ardour/globals.cc b/libs/ardour/globals.cc index 6938f86c87..c5f96d6764 100644 --- a/libs/ardour/globals.cc +++ b/libs/ardour/globals.cc @@ -31,6 +31,10 @@ #include <fst.h> #endif +#ifdef HAVE_AUDIOUNITS +#include <ardour/audio_unit.h> +#endif + #ifdef __SSE__ #include <xmmintrin.h> #endif @@ -328,6 +332,10 @@ ARDOUR::init (bool use_vst, bool try_optimization) return -1; } #endif + +#ifdef HAVE_AUDIOUNITS + AUPluginInfo::load_cached_info (); +#endif /* Make VAMP look in our library ahead of anything else */ diff --git a/libs/ardour/insert.cc b/libs/ardour/insert.cc index ce538fc960..90448661e8 100644 --- a/libs/ardour/insert.cc +++ b/libs/ardour/insert.cc @@ -80,11 +80,6 @@ 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 ()); - } - RedirectCreated (this); /* EMIT SIGNAL */ } @@ -98,11 +93,6 @@ PluginInsert::PluginInsert (Session& s, const XMLNode& node) set_automatable (); _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()); - } } PluginInsert::PluginInsert (const PluginInsert& other) @@ -200,6 +190,7 @@ uint32_t PluginInsert::input_streams() const { int32_t in = _plugins[0]->get_info()->n_inputs; + if (in < 0) { return _plugins[0]->input_streams (); } else { @@ -552,67 +543,28 @@ PluginInsert::plugin_factory (boost::shared_ptr<Plugin> other) } int32_t -PluginInsert::compute_output_streams (int32_t cnt) const +PluginInsert::configure_io (int32_t magic, int32_t in, int32_t out) { - int32_t outputs; + int32_t ret; - 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); + if ((ret = set_count (magic)) < 0) { + return ret; } - return outputs * cnt; -} + /* if we're running replicated plugins, each plugin has + the same i/o configuration and we may need to announce how many + output streams there are. -int32_t -PluginInsert::configure_io (int32_t magic, int32_t in, int32_t out) -{ - return set_count (magic); + if we running a single plugin, we need to configure it. + */ + + return _plugins[0]->configure_io (in, out); } int32_t -PluginInsert::can_support_input_configuration (int32_t in) const +PluginInsert::can_do (int32_t in, int32_t& out) { - 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 - away any existing active streams. - */ - - return 1; - } - - if (outputs == 1 && inputs == 1) { - /* mono plugin, replicate as needed */ - return in; - } - - if (inputs == in) { - /* exact match */ - return 1; - } - - if ((inputs < in) && (inputs % in == 0)) { - - /* number of inputs is a factor of the requested input - configuration, so we can replicate. - */ - - return in/inputs; - } - - /* sorry */ - - return -1; + return _plugins[0]->can_do (in, out); } XMLNode& @@ -1051,13 +1003,14 @@ PortInsert::latency() } int32_t -PortInsert::can_support_input_configuration (int32_t in) const +PortInsert::can_do (int32_t in, int32_t& out) { if (input_maximum() == -1 && output_maximum() == -1) { /* not configured yet */ - return in; /* we can support anything the first time we're asked */ + out = in; + return 1; } else { @@ -1066,7 +1019,8 @@ PortInsert::can_support_input_configuration (int32_t in) const */ if (output_maximum() == in) { - return in; + out = in; + return 1; } } @@ -1105,18 +1059,6 @@ PortInsert::configure_io (int32_t ignored_magic, int32_t in, int32_t out) return ensure_io (out, in, false, this); } -int32_t -PortInsert::compute_output_streams (int32_t cnt) const -{ - if (n_inputs() == 0) { - /* not configured yet */ - return cnt; - } - - /* puzzling, eh? think about it ... */ - return n_inputs (); -} - uint32_t PortInsert::output_streams() const { diff --git a/libs/ardour/plugin.cc b/libs/ardour/plugin.cc index 1160a0015b..de5c843013 100644 --- a/libs/ardour/plugin.cc +++ b/libs/ardour/plugin.cc @@ -362,21 +362,56 @@ ARDOUR::find_plugin(Session& session, string identifier, PluginType type) return PluginPtr ((Plugin*) 0); } -int32_t -Plugin::can_support_input_configuration (int32_t in) + +int32_t +Plugin::configure_io (int32_t in, int32_t out) { - /* LADSPA & VST should not get here because they do not - return negative i/o counts. + /* parent Plugin class assumes static output stream count. + Derived classes can override. */ - return -1; + + Glib::Mutex::Lock em (_session.engine().process_lock()); + IO::MoreOutputs (output_streams()); + + return 0; } int32_t -Plugin::compute_output_streams (int32_t nplugins) +Plugin::can_do (int32_t in, int32_t& out) { - /* LADSPA & VST should not get here because they do not - return negative i/o counts. - */ + int32_t outputs = get_info()->n_outputs; + int32_t inputs = get_info()->n_inputs; + + if (inputs == 0) { + + /* instrument plugin, always legal, but it throws + away any existing active streams. + */ + + return 1; + } + + if (outputs == 1 && inputs == 1) { + /* mono plugin, replicate as needed */ + return in; + } + + if (inputs == in) { + /* exact match */ + return 1; + } + + if ((inputs < in) && (inputs % in == 0)) { + + /* number of inputs is a factor of the requested input + configuration, so we can replicate. + */ + + return in/inputs; + } + + /* sorry */ + return -1; } diff --git a/libs/ardour/plugin_manager.cc b/libs/ardour/plugin_manager.cc index f5453e0ee1..5f0b9da343 100644 --- a/libs/ardour/plugin_manager.cc +++ b/libs/ardour/plugin_manager.cc @@ -51,6 +51,7 @@ #ifdef HAVE_AUDIOUNITS #include <ardour/audio_unit.h> +#include <Carbon/Carbon.h> #endif #include <pbd/error.h> @@ -71,6 +72,14 @@ PluginManager::PluginManager () load_favorites (); +#ifdef GTKOSX + ProcessSerialNumber psn = { 0, kCurrentProcess }; + OSStatus returnCode = TransformProcessType(& psn, kProcessTransformToForegroundApplication); + if( returnCode != 0) { + error << _("Cannot become GUI app") << endmsg; + } +#endif + if ((s = getenv ("LADSPA_RDF_PATH"))){ lrdf_path = s; } diff --git a/libs/ardour/route.cc b/libs/ardour/route.cc index 93b997a6f7..e56028833b 100644 --- a/libs/ardour/route.cc +++ b/libs/ardour/route.cc @@ -1133,7 +1133,7 @@ Route::_reset_plugin_counts (uint32_t* err_streams) uint32_t send_cnt = 0; map<Placement,list<InsertCount> > insert_map; RedirectList::iterator prev; - nframes_t initial_streams; + int32_t initial_streams; int ret = -1; redirect_max_outs = 0; @@ -1191,7 +1191,9 @@ Route::_reset_plugin_counts (uint32_t* err_streams) if (!insert_map[PreFader].empty()) { InsertCount& ic (insert_map[PreFader].back()); - initial_streams = ic.insert->compute_output_streams (ic.cnt); + if (ic.insert->can_do (n_inputs(), initial_streams) < 0) { + goto streamcount; + } } else { initial_streams = n_inputs (); } @@ -1268,8 +1270,8 @@ Route::check_some_plugin_counts (list<InsertCount>& iclist, int32_t required_inp list<InsertCount>::iterator i; for (i = iclist.begin(); i != iclist.end(); ++i) { - - if (((*i).cnt = (*i).insert->can_support_input_configuration (required_inputs)) < 0) { + + if (((*i).cnt = (*i).insert->can_do (required_inputs, (*i).out)) < 0) { if (err_streams) { *err_streams = required_inputs; } @@ -1277,14 +1279,6 @@ Route::check_some_plugin_counts (list<InsertCount>& iclist, int32_t required_inp } (*i).in = required_inputs; - - if (((*i).out = (*i).insert->compute_output_streams ((*i).cnt)) < 0) { - if (err_streams) { - *err_streams = required_inputs; - } - return -1; - } - required_inputs = (*i).out; } |