2 Copyright (C) 2006 Paul Davis
3 Written by Taybin Rutkin
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #include <pbd/transmitter.h>
22 #include <pbd/xml++.h>
24 #include <ardour/audioengine.h>
25 #include <ardour/audio_unit.h>
26 #include <ardour/session.h>
27 #include <ardour/utils.h>
29 #include <appleutility/CAAudioUnit.h>
31 #include <CoreServices/CoreServices.h>
32 #include <AudioUnit/AudioUnit.h>
38 using namespace ARDOUR;
40 AUPlugin::AUPlugin (AudioEngine& engine, Session& session, CAComponent* _comp)
42 Plugin (engine, session),
46 if (!unit->IsValid()) {
47 error << _("AudioUnit: Not a proper AudioUnit plugin") << endmsg;
48 throw failed_constructor ();
51 unit = new CAAudioUnit;
53 OSErr err = CAAudioUnit::Open (*comp, *unit);
55 error << _("AudioUnit: Could not convert CAComponent to CAAudioUnit") << endmsg;
58 throw failed_constructor ();
64 AUPlugin::~AUPlugin ()
67 unit->Uninitialize ();
76 AUPluginInfo::~AUPluginInfo ()
84 AUPlugin::unique_id () const
90 AUPlugin::label () const
96 AUPlugin::maker () const
102 AUPlugin::parameter_count () const
108 AUPlugin::default_value (uint32_t port)
114 AUPlugin::latency () const
120 AUPlugin::set_parameter (uint32_t which, float val)
126 AUPlugin::get_parameter (uint32_t which) const
132 AUPlugin::get_parameter_descriptor (uint32_t which, ParameterDescriptor&) const
138 AUPlugin::nth_parameter (uint32_t which, bool& ok) const
144 AUPlugin::activate ()
150 AUPlugin::deactivate ()
156 AUPlugin::set_block_size (jack_nframes_t nframes)
162 AUPlugin::connect_and_run (vector<Sample*>& bufs, uint32_t maxbuf, int32_t& in, int32_t& out, jack_nframes_t nframes, jack_nframes_t offset)
168 AUPlugin::automatable() const
170 set<uint32_t> automates;
176 AUPlugin::store_state (ARDOUR::PluginState&)
182 AUPlugin::restore_state (ARDOUR::PluginState&)
188 AUPlugin::describe_parameter (uint32_t)
194 AUPlugin::print_parameter (uint32_t, char*, uint32_t len) const
200 AUPlugin::parameter_is_audio (uint32_t) const
206 AUPlugin::parameter_is_control (uint32_t) const
212 AUPlugin::parameter_is_input (uint32_t) const
218 AUPlugin::parameter_is_output (uint32_t) const
224 AUPlugin::get_state()
226 XMLNode* root = new XMLNode (state_node_name());
232 AUPlugin::set_state(const XMLNode& node)
238 AUPlugin::save_preset (string name)
244 AUPlugin::load_preset (const string preset_label)
250 AUPlugin::get_presets ()
252 vector<string> presets;
258 AUPlugin::has_editor () const
264 AUPluginInfo::load (Session& session)
269 CAComponent* comp = new CAComponent(*desc);
271 if (!comp->IsValid()) {
272 error << ("AudioUnit: not a valid Component") << endmsg;
274 plugin.reset (new AUPlugin (session.engine(), session, comp));
277 plugin->set_info(PluginInfoPtr(new AUPluginInfo(*this)));
281 catch (failed_constructor &err) {
282 return PluginPtr ((Plugin*) 0);
287 AUPluginInfo::discover ()
289 PluginInfoList plugs;
291 int numTypes = 2; // this magic number was retrieved from the apple AUHost example.
293 CAComponentDescription desc;
294 desc.componentFlags = 0;
295 desc.componentFlagsMask = 0;
296 desc.componentSubType = 0;
297 desc.componentManufacturer = 0;
299 for (int i = 0; i < numTypes; ++i) {
301 desc.componentType = kAudioUnitType_MusicEffect;
303 desc.componentType = kAudioUnitType_Effect;
308 comp = FindNextComponent (NULL, &desc);
309 while (comp != NULL) {
310 CAComponentDescription temp;
311 GetComponentInfo (comp, &temp, NULL, NULL, NULL);
313 AUPluginInfoPtr plug(new AUPluginInfo);
314 plug->name = AUPluginInfo::get_name (temp);
315 plug->type = PluginInfo::AudioUnit;
318 plug->category = "AudioUnit";
319 plug->desc = new CAComponentDescription(temp);
321 plugs.push_back(plug);
323 comp = FindNextComponent (comp, &desc);
331 AUPluginInfo::get_name (CAComponentDescription& comp_desc)
333 CFStringRef itemName = NULL;
334 // Marc Poirier -style item name
335 CAComponent auComponent (comp_desc);
336 if (auComponent.IsValid()) {
337 CAComponentDescription dummydesc;
338 Handle nameHandle = NewHandle(sizeof(void*));
339 if (nameHandle != NULL) {
340 OSErr err = GetComponentInfo(auComponent.Comp(), &dummydesc, nameHandle, NULL, NULL);
342 ConstStr255Param nameString = (ConstStr255Param) (*nameHandle);
343 if (nameString != NULL) {
344 itemName = CFStringCreateWithPascalString(kCFAllocatorDefault, nameString, CFStringGetSystemEncoding());
347 DisposeHandle(nameHandle);
351 // if Marc-style fails, do the original way
352 if (itemName == NULL) {
353 CFStringRef compTypeString = UTCreateStringForOSType(comp_desc.componentType);
354 CFStringRef compSubTypeString = UTCreateStringForOSType(comp_desc.componentSubType);
355 CFStringRef compManufacturerString = UTCreateStringForOSType(comp_desc.componentManufacturer);
357 itemName = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@ - %@ - %@"),
358 compTypeString, compManufacturerString, compSubTypeString);
360 if (compTypeString != NULL)
361 CFRelease(compTypeString);
362 if (compSubTypeString != NULL)
363 CFRelease(compSubTypeString);
364 if (compManufacturerString != NULL)
365 CFRelease(compManufacturerString);
368 return CFStringRefToStdString(itemName);