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),
44 unit (new CAAudioUnit)
46 OSErr err = CAAudioUnit::Open (*comp, *unit);
48 error << _("AudioUnit: Could not convert CAComponent to CAAudioUnit") << endmsg;
51 throw failed_constructor ();
57 AUPlugin::~AUPlugin ()
60 unit->Uninitialize ();
77 AUPluginInfo::~AUPluginInfo ()
85 AUPlugin::unique_id () const
91 AUPlugin::label () const
93 return "AUPlugin label";
97 AUPlugin::maker () const
99 return "AUplugin maker";
103 AUPlugin::parameter_count () const
109 AUPlugin::default_value (uint32_t port)
111 // AudioUnits don't have default values. Maybe presets though?
116 AUPlugin::signal_latency () const
119 return _user_latency;
122 return unit->Latency ();
126 AUPlugin::set_parameter (uint32_t which, float val)
128 unit->SetParameter (parameter_map[which].first, parameter_map[which].second, 0, val);
132 AUPlugin::get_parameter (uint32_t which) const
134 float outValue = 0.0;
136 unit->GetParameter(parameter_map[which].first, parameter_map[which].second, 0, outValue);
142 AUPlugin::get_parameter_descriptor (uint32_t which, ParameterDescriptor&) const
148 AUPlugin::nth_parameter (uint32_t which, bool& ok) const
154 AUPlugin::activate ()
156 unit->GlobalReset ();
160 AUPlugin::deactivate ()
162 // not needed. GlobalReset () takes care of it.
166 AUPlugin::set_block_size (nframes_t nframes)
172 AUPlugin::connect_and_run (vector<Sample*>& bufs, uint32_t maxbuf, int32_t& in, int32_t& out, nframes_t nframes, nframes_t offset)
174 AudioUnitRenderActionFlags flags = 0;
178 abl.mNumberBuffers = 1;
179 abl.mBuffers[0].mNumberChannels = 1;
180 abl.mBuffers[0].mDataByteSize = nframes * sizeof(Sample);
181 abl.mBuffers[0].mData = &bufs[0];
184 unit->Render (&flags, &ts, 0, 0, &abl);
190 AUPlugin::automatable() const
192 set<uint32_t> automates;
198 AUPlugin::store_state (ARDOUR::PluginState&)
204 AUPlugin::restore_state (ARDOUR::PluginState&)
210 AUPlugin::describe_parameter (uint32_t)
216 AUPlugin::print_parameter (uint32_t, char*, uint32_t len) const
222 AUPlugin::parameter_is_audio (uint32_t) const
228 AUPlugin::parameter_is_control (uint32_t) const
234 AUPlugin::parameter_is_input (uint32_t) const
240 AUPlugin::parameter_is_output (uint32_t) const
246 AUPlugin::get_state()
248 XMLNode* root = new XMLNode (state_node_name());
254 AUPlugin::set_state(const XMLNode& node)
260 AUPlugin::save_preset (string name)
266 AUPlugin::load_preset (const string preset_label)
272 AUPlugin::get_presets ()
274 vector<string> presets;
280 AUPlugin::has_editor () const
286 AUPluginInfo::load (Session& session)
291 CAComponent* comp = new CAComponent(*desc);
293 if (!comp->IsValid()) {
294 error << ("AudioUnit: not a valid Component") << endmsg;
296 plugin.reset (new AUPlugin (session.engine(), session, comp));
299 plugin->set_info(PluginInfoPtr(new AUPluginInfo(*this)));
303 catch (failed_constructor &err) {
304 return PluginPtr ((Plugin*) 0);
309 AUPluginInfo::discover ()
311 PluginInfoList plugs;
313 CAComponentDescription desc;
314 desc.componentFlags = 0;
315 desc.componentFlagsMask = 0;
316 desc.componentSubType = 0;
317 desc.componentManufacturer = 0;
318 desc.componentType = kAudioUnitType_Effect;
322 comp = FindNextComponent (NULL, &desc);
323 while (comp != NULL) {
324 CAComponentDescription temp;
325 GetComponentInfo (comp, &temp, NULL, NULL, NULL);
327 AUPluginInfoPtr plug(new AUPluginInfo);
328 plug->name = AUPluginInfo::get_name (temp);
329 plug->type = ARDOUR::AudioUnit;
332 // plug->setup_nchannels (temp);
333 plug->category = "AudioUnit";
334 plug->desc = new CAComponentDescription(temp);
336 plugs.push_back(plug);
338 comp = FindNextComponent (comp, &desc);
345 AUPluginInfo::get_name (CAComponentDescription& comp_desc)
347 CFStringRef itemName = NULL;
348 // Marc Poirier -style item name
349 CAComponent auComponent (comp_desc);
350 if (auComponent.IsValid()) {
351 CAComponentDescription dummydesc;
352 Handle nameHandle = NewHandle(sizeof(void*));
353 if (nameHandle != NULL) {
354 OSErr err = GetComponentInfo(auComponent.Comp(), &dummydesc, nameHandle, NULL, NULL);
356 ConstStr255Param nameString = (ConstStr255Param) (*nameHandle);
357 if (nameString != NULL) {
358 itemName = CFStringCreateWithPascalString(kCFAllocatorDefault, nameString, CFStringGetSystemEncoding());
361 DisposeHandle(nameHandle);
365 // if Marc-style fails, do the original way
366 if (itemName == NULL) {
367 CFStringRef compTypeString = UTCreateStringForOSType(comp_desc.componentType);
368 CFStringRef compSubTypeString = UTCreateStringForOSType(comp_desc.componentSubType);
369 CFStringRef compManufacturerString = UTCreateStringForOSType(comp_desc.componentManufacturer);
371 itemName = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@ - %@ - %@"),
372 compTypeString, compManufacturerString, compSubTypeString);
374 if (compTypeString != NULL)
375 CFRelease(compTypeString);
376 if (compSubTypeString != NULL)
377 CFRelease(compSubTypeString);
378 if (compManufacturerString != NULL)
379 CFRelease(compManufacturerString);
382 return CFStringRefToStdString(itemName);
386 AUPluginInfo::setup_nchannels (CAComponentDescription& comp_desc)
390 CAAudioUnit::Open (comp_desc, unit);
392 if (unit.SupportsNumChannels()) {
393 n_inputs = n_outputs = 0;
396 size_t info_size = sizeof(cinfo);
397 OSStatus err = AudioUnitGetProperty (unit.AU(), kAudioUnitProperty_SupportedNumChannels, kAudioUnitScope_Global,
398 0, &cinfo, &info_size);