35 #include <glibmm/threads.h>
36 #include <glibmm/fileutils.h>
37 #include <glibmm/miscutils.h>
38 #include <glib/gstdio.h>
43 #include "ardour/debug.h"
51 #include "ardour/utils.h"
53 #include "appleutility/CAAudioUnit.h"
54 #include "appleutility/CAAUParameter.h"
56 #include <CoreFoundation/CoreFoundation.h>
57 #include <CoreServices/CoreServices.h>
58 #include <AudioUnit/AudioUnit.h>
59 #include <AudioToolbox/AudioUnitUtilities.h>
61 #include <Carbon/Carbon.h>
75 FILE * AUPluginInfo::_crashlog_fd = NULL;
81 FILE * blacklist_fd = NULL;
82 if (! (blacklist_fd = fopen(fn.c_str(),
"a"))) {
83 PBD::error <<
"Cannot append to AU blacklist for '"<<
id <<
"'\n";
86 assert(
id.find(
"\n") == string::npos);
87 fprintf(blacklist_fd,
"%s\n",
id.c_str());
88 ::fclose(blacklist_fd);
94 if (!Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
95 PBD::warning <<
"Expected Blacklist file does not exist.\n";
100 std::ifstream ifs(fn.c_str());
101 bl.assign ((std::istreambuf_iterator<char>(ifs)), (std::istreambuf_iterator<char>()));
102 ::g_unlink(fn.c_str());
104 assert(
id.find(
"\n") == string::npos);
107 const size_t rpl = bl.find(
id);
108 if (rpl != string::npos) {
109 bl.replace(rpl,
id.size(),
"");
115 FILE * blacklist_fd = NULL;
116 if (! (blacklist_fd = fopen(fn.c_str(),
"w"))) {
120 fprintf(blacklist_fd,
"%s", bl.c_str());
121 ::fclose(blacklist_fd);
127 if (!Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
131 std::ifstream ifs(fn.c_str());
132 bl.assign ((std::istreambuf_iterator<char>(ifs)), (std::istreambuf_iterator<char>()));
134 assert(
id.find(
"\n") == string::npos);
137 const size_t rpl = bl.find(
id);
138 if (rpl != string::npos) {
148 AudioUnitRenderActionFlags *ioActionFlags,
149 const AudioTimeStamp *inTimeStamp,
151 UInt32 inNumberFrames,
152 AudioBufferList* ioData)
155 return ((
AUPlugin*)userData)->render_callback (ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, ioData);
162 Float64* outCurrentBeat,
163 Float64* outCurrentTempo)
166 return ((
AUPlugin*)userData)->get_beat_and_tempo_callback (outCurrentBeat, outCurrentTempo);
174 UInt32 * outDeltaSampleOffsetToNextBeat,
175 Float32 * outTimeSig_Numerator,
176 UInt32 * outTimeSig_Denominator,
177 Float64 * outCurrentMeasureDownBeat)
180 return ((
AUPlugin*)userData)->get_musical_time_location_callback (outDeltaSampleOffsetToNextBeat,
181 outTimeSig_Numerator,
182 outTimeSig_Denominator,
183 outCurrentMeasureDownBeat);
190 Boolean* outIsPlaying,
191 Boolean* outTransportStateChanged,
192 Float64* outCurrentSampleInTimeLine,
193 Boolean* outIsCycling,
194 Float64* outCycleStartBeat,
195 Float64* outCycleEndBeat)
198 return ((
AUPlugin*)userData)->get_transport_state_callback (
199 outIsPlaying, outTransportStateChanged,
200 outCurrentSampleInTimeLine, outIsCycling,
201 outCycleStartBeat, outCycleEndBeat);
216 xmlData = CFPropertyListCreateXMLData( kCFAllocatorDefault, propertyList);
219 error <<
_(
"Could not create XML version of property list") <<
endmsg;
225 fd = open (path.c_str(), O_WRONLY|O_CREAT|O_EXCL, 0664);
227 if (errno == EEXIST) {
232 path, strerror (errno)) <<
endmsg;
238 size_t cnt = CFDataGetLength (xmlData);
240 if (write (fd, CFDataGetBytePtr (xmlData), cnt) != (ssize_t) cnt) {
251 static CFPropertyListRef
255 CFPropertyListRef propertyList = 0;
257 CFStringRef errorString;
261 if ((fd = open (path.c_str(), O_RDONLY)) < 0) {
266 off_t len = lseek (fd, 0, SEEK_END);
267 char* buf =
new char[len];
268 lseek (fd, 0, SEEK_SET);
270 if (read (fd, buf, len) != len) {
278 xmlData = CFDataCreateWithBytesNoCopy (kCFAllocatorDefault, (UInt8*) buf, len, kCFAllocatorNull);
282 propertyList = CFPropertyListCreateFromXMLData( kCFAllocatorDefault,
284 kCFPropertyListImmutable,
300 CFStringRef pn = CFStringCreateWithCString (kCFAllocatorDefault, preset_name.c_str(), kCFStringEncodingUTF8);
302 if (CFGetTypeID (plist) == CFDictionaryGetTypeID()) {
303 CFDictionarySetValue ((CFMutableDictionaryRef)plist, CFSTR(kAUPresetNameKey), pn);
319 if (CFGetTypeID (plist) == CFDictionaryGetTypeID()) {
320 const void *p = CFDictionaryGetValue ((CFMutableDictionaryRef)plist, CFSTR(kAUPresetNameKey));
322 CFStringRef str = (CFStringRef) p;
323 int len = CFStringGetLength(str);
325 char local_buffer[len];
326 if (CFStringGetCString (str, local_buffer, len, kCFStringEncodingUTF8)) {
337 Boolean
ComponentDescriptionsMatch_General(
const ComponentDescription * inComponentDescription1,
const ComponentDescription * inComponentDescription2, Boolean inIgnoreType);
340 if ( (inComponentDescription1 == NULL) || (inComponentDescription2 == NULL) )
343 if ( (inComponentDescription1->componentSubType == inComponentDescription2->componentSubType)
344 && (inComponentDescription1->componentManufacturer == inComponentDescription2->componentManufacturer) )
350 else if (inComponentDescription1->componentType == inComponentDescription2->componentType)
364 ComponentDescription desc;
366 if ( (inComponent == NULL) || (inComponentDescription == NULL) )
370 status = GetComponentInfo(inComponent, &desc, NULL, NULL, NULL);
382 Boolean
ComponentDescriptionsMatch(
const ComponentDescription * inComponentDescription1,
const ComponentDescription * inComponentDescription2)
410 :
Plugin (engine, session)
412 , unit (new CAAudioUnit)
413 , initialized (false)
414 , _current_block_size (0)
415 , _requires_fixed_size_buffers (false)
420 , frames_processed (0)
421 , _parameter_listener (0)
422 , _parameter_listener_arg (0)
423 , last_transport_rolling (false)
424 , last_transport_speed (0.0)
427 Glib::ustring p = Glib::get_home_dir();
428 p +=
"/Library/Audio/Presets:";
441 , comp (other.get_comp())
442 , unit (new CAAudioUnit)
443 , initialized (false)
444 , _current_block_size (0)
446 , _requires_fixed_size_buffers (false)
451 , frames_processed (0)
452 , _parameter_listener (0)
453 , _parameter_listener_arg (0)
468 unit->Uninitialize ();
484 if ((err =
unit->GetPropertyInfo (kAudioUnitProperty_FactoryPresets, kAudioUnitScope_Global, 0, &dataSize, &isWritable)) != 0) {
489 assert (dataSize ==
sizeof (presets));
491 if ((err =
unit->GetProperty (kAudioUnitProperty_FactoryPresets, kAudioUnitScope_Global, 0, (
void*) &presets, &dataSize)) != 0) {
500 CFIndex cnt = CFArrayGetCount (presets);
502 for (CFIndex i = 0; i < cnt; ++i) {
503 AUPreset* preset = (AUPreset*) CFArrayGetValueAtIndex (presets, i);
505 string name = CFStringRefToStdString (preset->presetName);
517 CFStringRef itemName;
526 CAComponentDescription temp;
527 GetComponentInfo (
comp.
get()->Comp(), &temp, NULL, NULL, NULL);
528 CFStringRef compTypeString = UTCreateStringForOSType(temp.componentType);
529 CFStringRef compSubTypeString = UTCreateStringForOSType(temp.componentSubType);
530 CFStringRef compManufacturerString = UTCreateStringForOSType(temp.componentManufacturer);
531 itemName = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR(
"%@ - %@ - %@"),
532 compTypeString, compManufacturerString, compSubTypeString);
533 if (compTypeString != NULL) CFRelease(compTypeString);
534 if (compSubTypeString != NULL) CFRelease(compSubTypeString);
535 if (compManufacturerString != NULL) CFRelease(compManufacturerString);
544 error <<
_(
"Exception thrown during AudioUnit plugin loading - plugin ignored") <<
endmsg;
549 error <<
_(
"AudioUnit: Could not convert CAComponent to CAAudioUnit") <<
endmsg;
564 AURenderCallbackStruct renderCallbackInfo;
567 renderCallbackInfo.inputProcRefCon =
this;
570 if ((err =
unit->SetProperty (kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input,
571 0, (
void*) &renderCallbackInfo,
sizeof(renderCallbackInfo))) != 0) {
579 HostCallbackInfo
info;
580 memset (&info, 0,
sizeof (HostCallbackInfo));
581 info.hostUserData =
this;
588 unit->SetProperty (kAudioUnitProperty_HostCallbacks,
589 kAudioUnitScope_Global,
592 sizeof (HostCallbackInfo));
595 error <<
_(
"AUPlugin: cannot set processing block size") <<
endmsg;
606 if (itemName != NULL) CFRelease(itemName);
614 AudioUnitScope scopes[] = {
615 kAudioUnitScope_Global,
616 kAudioUnitScope_Output,
617 kAudioUnitScope_Input
622 for (uint32_t i = 0; i <
sizeof (scopes) /
sizeof (scopes[0]); ++i) {
624 AUParamInfo param_info (
unit->AU(),
false,
true, scopes[i]);
626 for (uint32_t i = 0; i < param_info.NumParams(); ++i) {
630 d.
id = param_info.ParamID (i);
632 const CAAUParameter* param = param_info.GetParamInfo (d.
id);
633 const AudioUnitParameterInfo&
info (param->ParamInfo());
635 const int len = CFStringGetLength (param->GetName());;
636 char local_buffer[len*2];
637 Boolean good = CFStringGetCString(param->GetName(),local_buffer,len*2,kCFStringEncodingMacRoman);
641 d.
label = local_buffer;
644 d.
scope = param_info.GetScope ();
645 d.
element = param_info.GetElement ();
701 d.
toggled = (
info.unit == kAudioUnitParameterUnit_Boolean) ||
705 !(
info.flags & kAudioUnitParameterFlag_NonRealTime) &&
706 (
info.flags & kAudioUnitParameterFlag_IsWritable);
708 d.
logarithmic = (
info.flags & kAudioUnitParameterFlag_DisplayLogarithmic);
711 case kAudioUnitParameterUnit_Decibels:
714 case kAudioUnitParameterUnit_MIDINoteNumber:
717 case kAudioUnitParameterUnit_Hertz:
742 return ((n[0] << 24) + (n[1] << 16) + (n[2] << 8) + n[3]);
748 if (isdigit (
id[0])) {
760 unsigned char nascent[4];
761 const char* cstr =
id.c_str();
762 const char* estr = cstr +
id.size();
773 while (*cstr && next_int < 4) {
777 if (estr - cstr < 3) {
787 if (cstr[1] ==
'x' && isxdigit (cstr[2]) && isxdigit (cstr[3])) {
791 memcpy (short_buf, &cstr[2], 2);
792 nascent[in] = strtol (short_buf, NULL, 16);
812 if (in && (in % 4 == 0)) {
832 s << n[0] <<
'-' << n[1] <<
'-' << n[2];
891 AudioUnitEvent theEvent;
893 theEvent.mEventType = kAudioUnitEvent_ParameterValueChange;
894 theEvent.mArgument.mParameter.mAudioUnit =
unit->AU();
895 theEvent.mArgument.mParameter.mParameterID = d.
id;
896 theEvent.mArgument.mParameter.mScope = d.
scope;
897 theEvent.mArgument.mParameter.mElement = d.
element;
900 AUEventListenerNotify (NULL, NULL, &theEvent);
944 if ((err =
unit->Initialize()) != noErr) {
957 unit->Uninitialize ();
965 unit->GlobalReset ();
979 UInt32 numFrames = nframes;
987 if ((err =
unit->SetProperty (kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Global,
988 0, &numFrames, sizeof (numFrames))) != noErr) {
993 if (was_initialized) {
1005 AudioStreamBasicDescription streamFormat;
1007 int32_t audio_in = in.
n_audio();
1008 int32_t audio_out = out.
n_audio();
1022 streamFormat.mFormatID = kAudioFormatLinearPCM;
1023 streamFormat.mFormatFlags = kAudioFormatFlagIsFloat|kAudioFormatFlagIsPacked|kAudioFormatFlagIsNonInterleaved;
1025 #ifdef __LITTLE_ENDIAN__
1028 streamFormat.mFormatFlags |= kAudioFormatFlagIsBigEndian;
1031 streamFormat.mBitsPerChannel = 32;
1032 streamFormat.mFramesPerPacket = 1;
1037 streamFormat.mBytesPerPacket = 4;
1038 streamFormat.mBytesPerFrame = 4;
1040 streamFormat.mChannelsPerFrame = audio_in;
1046 streamFormat.mChannelsPerFrame = audio_out;
1057 if (was_initialized) {
1105 int32_t audio_in = in.
n_audio();
1118 vector<pair<int,int> >&
io_configs = pinfo->cache.io_configs;
1121 name(), io_configs.size(), in, out));
1128 if (in.
n_midi() > 0 && audio_in == 0) {
1131 audio_out = audio_in;
1134 for (vector<pair<int,int> >::iterator i = io_configs.begin(); i != io_configs.end(); ++i) {
1136 int32_t possible_in = i->first;
1137 int32_t possible_out = i->second;
1139 if ((possible_in == audio_in) && (possible_out == audio_out)) {
1141 possible_in, possible_out,
1155 for (vector<pair<int,int> >::iterator i = io_configs.begin(); i != io_configs.end(); ++i) {
1157 int32_t possible_in = i->first;
1158 int32_t possible_out = i->second;
1162 if (possible_out == 0) {
1168 if (possible_in == 0) {
1173 if (possible_out == -1) {
1177 }
else if (possible_out == -2) {
1183 }
else if (possible_out < -2) {
1195 audio_out = master->
input()->n_ports().n_audio();
1202 audio_out = possible_out;
1207 if (possible_in == -1) {
1211 if (possible_out == -1) {
1213 audio_out = audio_in;
1215 }
else if (possible_out == -2) {
1217 audio_out = audio_in;
1219 }
else if (possible_out < -2) {
1221 audio_out = -possible_out;
1225 audio_out = possible_out;
1230 if (possible_in == -2) {
1232 if (possible_out == -1) {
1234 audio_out = audio_in;
1236 }
else if (possible_out == -2) {
1240 audio_out = audio_in;
1242 }
else if (possible_out < -2) {
1244 audio_out = -possible_out;
1248 audio_out = possible_out;
1253 if (possible_in < -2) {
1257 if (audio_in > -possible_in) {
1262 if (possible_out == -1) {
1266 }
else if (possible_out == -2) {
1272 }
else if (possible_out < -2) {
1284 audio_out = master->
input()->n_ports().n_audio();
1291 audio_out = possible_out;
1296 if (possible_in && (possible_in == audio_in)) {
1300 if (possible_out == -1) {
1304 }
else if (possible_out == -2) {
1311 }
else if (possible_out < -2) {
1313 audio_out = -possible_out;
1317 audio_out = possible_out;
1359 buffers = (AudioBufferList *) malloc (offsetof(AudioBufferList, mBuffers) +
1370 for (uint32_t i = 0; i < cnt; ++i) {
1372 (scope == kAudioUnitScope_Input ?
"input" :
"output"),
1374 if ((result =
unit->SetFormat (scope, i, fmt)) != 0) {
1376 (scope == kAudioUnitScope_Input ?
"input" :
"output"), i, result) <<
endmsg;
1381 if (scope == kAudioUnitScope_Input) {
1392 const AudioTimeStamp*,
1394 UInt32 inNumberFrames,
1395 AudioBufferList* ioData)
1403 error <<
_(
"AUPlugin: render callback called illegally!") <<
endmsg;
1404 return kAudioUnitErr_CannotDoInCurrentContext;
1406 uint32_t limit = min ((uint32_t) ioData->mNumberBuffers,
input_maxbuf);
1408 for (uint32_t i = 0; i < limit; ++i) {
1409 ioData->mBuffers[i].mNumberChannels = 1;
1410 ioData->mBuffers[i].mDataByteSize =
sizeof (
Sample) * inNumberFrames;
1430 AudioUnitRenderActionFlags flags = 0;
1435 unit->GlobalReset();
1457 buffers->mBuffers[i].mNumberChannels = 1;
1458 buffers->mBuffers[i].mDataByteSize = nframes *
sizeof (
Sample);
1466 buffers->mBuffers[i].mData = 0;
1473 for (uint32_t i = 0; i < nmidi; ++i) {
1483 const uint8_t* b = ev.
buffer();
1485 unit->MIDIEvent (b[0], b[1], b[2], ev.
time());
1497 ts.mFlags = kAudioTimeStampSampleTimeValid;
1502 if ((err =
unit->Render (&flags, &ts, 0, nframes,
buffers)) == noErr) {
1508 name(),
buffers->mNumberBuffers, output_channels));
1510 int32_t limit = min ((int32_t)
buffers->mNumberBuffers, output_channels);
1513 for (i = 0; i < limit; ++i) {
1515 if (expected_buffer_address !=
buffers->mBuffers[i].mData) {
1518 memcpy (expected_buffer_address,
buffers->mBuffers[i].mData, nframes * sizeof (
Sample));
1539 Float64* outCurrentTempo)
1550 if (tmap.n_tempos() > 1 || tmap.n_meters() > 1) {
1551 return kAudioUnitErr_CannotDoInCurrentContext;
1554 Timecode::BBT_Time bbt;
1558 if (outCurrentBeat) {
1562 beat += bbt.ticks / Timecode::BBT_Time::ticks_per_beat;
1563 *outCurrentBeat = beat;
1566 if (outCurrentTempo) {
1576 Float32* outTimeSig_Numerator,
1577 UInt32* outTimeSig_Denominator,
1578 Float64* outCurrentMeasureDownBeat)
1589 if (tmap.n_tempos() > 1 || tmap.n_meters() > 1) {
1590 return kAudioUnitErr_CannotDoInCurrentContext;
1593 Timecode::BBT_Time bbt;
1597 if (outDeltaSampleOffsetToNextBeat) {
1598 if (bbt.ticks == 0) {
1600 *outDeltaSampleOffsetToNextBeat = 0;
1602 *outDeltaSampleOffsetToNextBeat = (UInt32)
1603 floor (((Timecode::BBT_Time::ticks_per_beat - bbt.ticks)/Timecode::BBT_Time::ticks_per_beat) *
1608 if (outTimeSig_Numerator) {
1611 if (outTimeSig_Denominator) {
1615 if (outCurrentMeasureDownBeat) {
1632 Boolean* outTransportStateChanged,
1633 Float64* outCurrentSampleInTimeLine,
1634 Boolean* outIsCycling,
1635 Float64* outCycleStartBeat,
1636 Float64* outCycleEndBeat)
1650 if (outTransportStateChanged) {
1652 *outTransportStateChanged =
true;
1654 *outTransportStateChanged =
true;
1656 *outTransportStateChanged =
false;
1660 if (outCurrentSampleInTimeLine) {
1672 if (*outIsCycling) {
1674 if (outCycleStartBeat || outCycleEndBeat) {
1682 if (tmap.n_meters() > 1) {
1683 return kAudioUnitErr_CannotDoInCurrentContext;
1686 Timecode::BBT_Time bbt;
1688 if (outCycleStartBeat) {
1695 beat += bbt.ticks / Timecode::BBT_Time::ticks_per_beat;
1697 *outCycleStartBeat = beat;
1700 if (outCycleEndBeat) {
1707 beat += bbt.ticks / Timecode::BBT_Time::ticks_per_beat;
1709 *outCycleEndBeat = beat;
1721 set<Evoral::Parameter>
1724 set<Evoral::Parameter> automates;
1726 for (uint32_t i = 0; i <
descriptors.size(); ++i) {
1777 return (
descriptors[param].scope == kAudioUnitScope_Input ||
descriptors[param].scope == kAudioUnitScope_Global);
1787 return (
descriptors[param].scope == kAudioUnitScope_Output);
1795 CFPropertyListRef propertyList;
1798 if (
unit->GetAUPreset (propertyList) != noErr) {
1804 xmlData = CFPropertyListCreateXMLData( kCFAllocatorDefault, propertyList);
1807 error <<
_(
"Could not create XML version of property list") <<
endmsg;
1817 if (t.
read_buffer (string ((
const char*) CFDataGetBytePtr (xmlData), CFDataGetLength (xmlData)))) {
1823 CFRelease (xmlData);
1824 CFRelease (propertyList);
1831 CFPropertyListRef propertyList;
1835 error <<
_(
"Bad node sent to AUPlugin::set_state") <<
endmsg;
1839 #ifndef NO_PLUGIN_STATE
1851 CFDataRef xmlData = CFDataCreateWithBytesNoCopy (kCFAllocatorDefault, (UInt8*) xml.data(), xml.length(), kCFAllocatorNull);
1852 CFStringRef errorString;
1854 propertyList = CFPropertyListCreateFromXMLData( kCFAllocatorDefault,
1856 kCFPropertyListImmutable,
1859 CFRelease (xmlData);
1863 if (
unit->SetAUPreset (propertyList) == noErr) {
1868 AudioUnitParameter changedUnit;
1869 changedUnit.mAudioUnit =
unit->AU();
1870 changedUnit.mParameterID = kAUParameterListener_AnyParameter;
1871 AUParameterListenerNotify (NULL, NULL, &changedUnit);
1873 CFRelease (propertyList);
1887 CFPropertyListRef propertyList;
1889 UserPresetMap::iterator ux;
1890 FactoryPresetMap::iterator fx;
1898 if (
unit->SetAUPreset (propertyList) == noErr) {
1903 AudioUnitParameter changedUnit;
1904 changedUnit.mAudioUnit =
unit->AU();
1905 changedUnit.mParameterID = kAUParameterListener_AnyParameter;
1906 AUParameterListenerNotify (NULL, NULL, &changedUnit);
1908 CFRelease(propertyList);
1915 preset.presetNumber = fx->second;
1916 preset.presetName = CFStringCreateWithCString (kCFAllocatorDefault, fx->first.c_str(), kCFStringEncodingUTF8);
1920 if (
unit->SetPresentPreset (preset) == 0) {
1925 AudioUnitParameter changedUnit;
1926 changedUnit.mAudioUnit =
unit->AU();
1927 changedUnit.mParameterID = kAUParameterListener_AnyParameter;
1928 AUParameterListenerNotify (NULL, NULL, &changedUnit);
1943 CFPropertyListRef propertyList;
1944 vector<Glib::ustring> v;
1945 Glib::ustring user_preset_path;
1947 std::string m =
maker();
1948 std::string n =
name();
1953 v.push_back (Glib::get_home_dir());
1954 v.push_back (
"Library");
1955 v.push_back (
"Audio");
1956 v.push_back (
"Presets");
1960 user_preset_path = Glib::build_filename (v);
1962 if (g_mkdir_with_parents (user_preset_path.c_str(), 0775) < 0) {
1968 if (
unit->GetAUPreset (propertyList) != noErr) {
1978 user_preset_path = Glib::build_filename (v);
1987 CFRelease(propertyList);
1993 return string (
"file:///") + user_preset_path;
2001 CFNumberRef cfNumber;
2002 SInt32 numberValue = 0;
2003 Boolean dummySuccess;
2005 if (outSuccess == NULL)
2006 outSuccess = &dummySuccess;
2007 if ( (inAUStateDictionary == NULL) || (inDictionaryKey == NULL) )
2009 *outSuccess = FALSE;
2013 cfNumber = (CFNumberRef) CFDictionaryGetValue(inAUStateDictionary, inDictionaryKey);
2014 if (cfNumber == NULL)
2016 *outSuccess = FALSE;
2019 *outSuccess = CFNumberGetValue(cfNumber, kCFNumberSInt32Type, &numberValue);
2029 CFDictionaryRef auStateDictionary;
2030 ComponentDescription tempDesc = {0,0,0,0,0};
2031 SInt32 versionValue;
2034 if ( (inAUStateData == NULL) || (outComponentDescription == NULL) )
2038 if (CFGetTypeID(inAUStateData) != CFDictionaryGetTypeID()) {
2039 return kAudioUnitErr_InvalidPropertyValue;
2042 auStateDictionary = (CFDictionaryRef)inAUStateData;
2049 return kAudioUnitErr_InvalidPropertyValue;
2051 #define kCurrentSavedStateVersion 0
2053 return kAudioUnitErr_InvalidPropertyValue;
2058 tempDesc.componentSubType = (OSType)
GetDictionarySInt32Value(auStateDictionary, CFSTR(kAUPresetSubtypeKey), NULL);
2059 tempDesc.componentManufacturer = (OSType)
GetDictionarySInt32Value(auStateDictionary, CFSTR(kAUPresetManufacturerKey), NULL);
2061 if ( (tempDesc.componentType == 0) || (tempDesc.componentSubType == 0) || (tempDesc.componentManufacturer == 0) )
2062 return kAudioUnitErr_InvalidPropertyValue;
2064 *outComponentDescription = tempDesc;
2085 string match = p->
maker();
2089 ret = str.find (match) != string::npos;
2092 string m = p->
maker ();
2093 string n = p->
name ();
2100 ret = str.find (match) != string::npos;
2111 CFPropertyListRef plist;
2112 ComponentDescription presetDesc;
2125 if (status == noErr) {
2130 if (CFGetTypeID(plist) == CFDictionaryGetTypeID()) {
2132 const void* psk = CFDictionaryGetValue ((CFMutableDictionaryRef)plist, CFSTR(kAUPresetNameKey));
2136 const char* p = CFStringGetCStringPtr ((CFStringRef) psk, kCFStringEncodingUTF8);
2141 if (CFStringGetCString ((CFStringRef)psk, buf,
sizeof (buf), kCFStringEncodingUTF8)) {
2160 CFPropertyListRef propertyList;
2163 if (
unit->GetAUPreset (propertyList) == noErr) {
2165 CFRelease(propertyList);
2174 vector<string> preset_files;
2180 if (preset_files.empty()) {
2185 for (vector<string>::iterator x = preset_files.begin(); x != preset_files.end(); ++x) {
2192 preset_name = Glib::path_get_basename (path);
2193 preset_name = preset_name.substr (0, preset_name.find_last_of (
'.'));
2254 if (!comp->IsValid()) {
2255 error << (
"AudioUnit: not a valid Component") <<
endmsg;
2284 if (!Glib::file_test (
au_cache_path(), Glib::FILE_TEST_EXISTS)) {
2308 CAComponentDescription desc;
2309 desc.componentFlags = 0;
2310 desc.componentFlagsMask = 0;
2311 desc.componentSubType = 0;
2312 desc.componentManufacturer = 0;
2313 desc.componentType = kAudioUnitType_MusicEffect;
2321 CAComponentDescription desc;
2322 desc.componentFlags = 0;
2323 desc.componentFlagsMask = 0;
2324 desc.componentSubType = 0;
2325 desc.componentManufacturer = 0;
2326 desc.componentType = kAudioUnitType_Effect;
2334 CAComponentDescription desc;
2335 desc.componentFlags = 0;
2336 desc.componentFlagsMask = 0;
2337 desc.componentSubType = 0;
2338 desc.componentManufacturer = 0;
2339 desc.componentType = kAudioUnitType_Generator;
2347 CAComponentDescription desc;
2348 desc.componentFlags = 0;
2349 desc.componentFlagsMask = 0;
2350 desc.componentSubType = 0;
2351 desc.componentManufacturer = 0;
2352 desc.componentType = kAudioUnitType_MusicDevice;
2362 if (!Glib::file_test (fn, Glib::FILE_TEST_EXISTS)) {
2365 std::ifstream ifs(fn.c_str());
2366 msg.assign ((std::istreambuf_iterator<char>(ifs)), (std::istreambuf_iterator<char>()));
2378 PBD::error <<
"Cannot create AU error-log" << fn <<
"\n";
2379 cerr <<
"Cannot create AU error-log" << fn <<
"\n";
2391 ::g_unlink(fn.c_str());
2400 fprintf(stderr,
"AU: %s\n", msg.c_str());
2413 comp = FindNextComponent (NULL, &desc);
2415 while (comp != NULL) {
2416 CAComponentDescription temp;
2417 GetComponentInfo (comp, &temp, NULL, NULL, NULL);
2418 CFStringRef itemName = NULL;
2421 if (itemName != NULL) CFRelease(itemName);
2422 CFStringRef compTypeString = UTCreateStringForOSType(temp.componentType);
2423 CFStringRef compSubTypeString = UTCreateStringForOSType(temp.componentSubType);
2424 CFStringRef compManufacturerString = UTCreateStringForOSType(temp.componentManufacturer);
2425 itemName = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR(
"%@ - %@ - %@"),
2426 compTypeString, compManufacturerString, compSubTypeString);
2428 if (compTypeString != NULL)
2429 CFRelease(compTypeString);
2430 if (compSubTypeString != NULL)
2431 CFRelease(compSubTypeString);
2432 if (compManufacturerString != NULL)
2433 CFRelease(compManufacturerString);
2438 comp = FindNextComponent (comp, &desc);
2454 switch (info->descriptor->Type()) {
2455 case kAudioUnitType_Panner:
2456 case kAudioUnitType_OfflineEffect:
2457 case kAudioUnitType_FormatConverter:
2458 comp = FindNextComponent (comp, &desc);
2461 case kAudioUnitType_Output:
2462 info->category =
_(
"AudioUnit Outputs");
2464 case kAudioUnitType_MusicDevice:
2465 info->category =
_(
"AudioUnit Instruments");
2467 case kAudioUnitType_MusicEffect:
2468 info->category =
_(
"AudioUnit MusicEffects");
2470 case kAudioUnitType_Effect:
2471 info->category =
_(
"AudioUnit Effects");
2473 case kAudioUnitType_Mixer:
2474 info->category =
_(
"AudioUnit Mixers");
2476 case kAudioUnitType_Generator:
2477 info->category =
_(
"AudioUnit Generators");
2480 info->category =
_(
"AudioUnit (Unknown)");
2495 CAComponent cacomp (*info->descriptor);
2497 if (cacomp.GetResourceVersion (info->version) != noErr) {
2516 int32_t possible_in = info->cache.io_configs.front().first;
2517 int32_t possible_out = info->cache.io_configs.front().second;
2519 if (possible_in > 0) {
2525 if (possible_out > 0) {
2532 info->name.c_str(), info->cache.io_configs.size(), info->unique_id));
2534 plugs.push_back (info);
2542 comp = FindNextComponent (comp, &desc);
2543 if (itemName != NULL) CFRelease(itemName); itemName = NULL;
2553 const std::string&
name)
2563 snprintf (buf,
sizeof (buf),
"%u", (uint32_t) version);
2568 CachedInfoMap::iterator cim =
cached_info.find (
id);
2571 cinfo = cim->second;
2576 AUChannelInfo* channel_info;
2584 if (CAAudioUnit::Open (comp, unit) != noErr) {
2596 if ((ret = unit.GetChannelInfo (&channel_info, cnt)) < 0) {
2606 cinfo.
io_configs.push_back (pair<int,int> (-1, -1));
2612 for (uint32_t n = 0; n < cnt; ++n) {
2613 cinfo.
io_configs.push_back (pair<int,int> (channel_info[n].inChannels,
2614 channel_info[n].outChannels));
2617 free (channel_info);
2632 #define AU_CACHE_VERSION "2.0"
2639 node =
new XMLNode (
X_(
"AudioUnitPluginCache"));
2647 for (vector<pair<int, int> >::iterator j = i->second.io_configs.begin(); j != i->second.io_configs.end(); ++j) {
2652 snprintf (buf,
sizeof (buf),
"%d", j->first);
2654 snprintf (buf,
sizeof (buf),
"%d", j->second);
2666 if (!tree.
write (path)) {
2668 g_unlink (path.c_str());
2678 if (!Glib::file_test (path, Glib::FILE_TEST_EXISTS)) {
2682 if ( !tree.
read (path) ) {
2683 error <<
"au_cache is not a valid XML file. AU plugins will be re-scanned" <<
endmsg;
2689 if (root->name() !=
X_(
"AudioUnitPluginCache")) {
2696 error <<
"au_cache is not correct version. AU plugins will be re-scanned" <<
endmsg;
2708 if (child->
name() ==
X_(
"plugin")) {
2718 string id = prop->
value();
2722 string::size_type slash =
id.find_last_of (
'/');
2724 if (slash == string::npos) {
2728 version =
id.substr (slash);
2729 id =
id.substr (0, slash);
2732 if (fixed.empty()) {
2733 error <<
string_compose (
_(
"Your AudioUnit configuration cache contains an AU plugin whose ID cannot be understood - ignored (%1)"),
id) <<
endmsg;
2746 if (gchild->
name() ==
X_(
"io")) {
2753 if (((iprop = gchild->
property (
X_(
"in"))) != 0) &&
2754 ((oprop = gchild->
property (
X_(
"out"))) != 0)) {
2758 cinfo.
io_configs.push_back (pair<int,int> (in, out));
2775 CFStringRef itemName = NULL;
2778 CAComponent auComponent (comp_desc);
2779 if (auComponent.IsValid()) {
2780 CAComponentDescription dummydesc;
2781 Handle nameHandle = NewHandle(
sizeof(
void*));
2782 if (nameHandle != NULL) {
2783 OSErr err = GetComponentInfo(auComponent.Comp(), &dummydesc, nameHandle, NULL, NULL);
2785 ConstStr255Param nameString = (ConstStr255Param) (*nameHandle);
2786 if (nameString != NULL) {
2787 itemName = CFStringCreateWithPascalString(kCFAllocatorDefault, nameString, CFStringGetSystemEncoding());
2790 DisposeHandle(nameHandle);
2795 if (itemName == NULL) {
2796 CFStringRef compTypeString = UTCreateStringForOSType(comp_desc.componentType);
2797 CFStringRef compSubTypeString = UTCreateStringForOSType(comp_desc.componentSubType);
2798 CFStringRef compManufacturerString = UTCreateStringForOSType(comp_desc.componentManufacturer);
2800 itemName = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR(
"%@ - %@ - %@"),
2801 compTypeString, compManufacturerString, compSubTypeString);
2803 if (compTypeString != NULL)
2804 CFRelease(compTypeString);
2805 if (compSubTypeString != NULL)
2806 CFRelease(compSubTypeString);
2807 if (compManufacturerString != NULL)
2808 CFRelease(compManufacturerString);
2811 string str = CFStringRefToStdString(itemName);
2812 string::size_type colon = str.find (
':');
2815 name = str.substr (colon+1);
2816 maker = str.substr (0, colon);
2838 s << desc.SubType();
2889 CFRunLoopRef run_loop = (CFRunLoopRef) GetCFRunLoopFromEventLoop(GetCurrentEventLoop());
2891 CFRunLoopRef run_loop = CFRunLoopGetCurrent();
2893 CFStringRef loop_mode = kCFRunLoopDefaultMode;
2895 if (AUEventListenerCreate (cb, arg, run_loop, loop_mode, interval_secs, interval_secs, &
_parameter_listener) != noErr) {
2907 AudioUnitEvent event;
2913 event.mEventType = kAudioUnitEvent_ParameterValueChange;
2914 event.mArgument.mParameter.mAudioUnit =
unit->AU();
2915 event.mArgument.mParameter.mParameterID =
descriptors[param_id].id;
2916 event.mArgument.mParameter.mScope =
descriptors[param_id].scope;
2917 event.mArgument.mParameter.mElement =
descriptors[param_id].element;
2923 event.mEventType = kAudioUnitEvent_BeginParameterChangeGesture;
2924 event.mArgument.mParameter.mAudioUnit =
unit->AU();
2925 event.mArgument.mParameter.mParameterID =
descriptors[param_id].id;
2926 event.mArgument.mParameter.mScope =
descriptors[param_id].scope;
2927 event.mArgument.mParameter.mElement =
descriptors[param_id].element;
2933 event.mEventType = kAudioUnitEvent_EndParameterChangeGesture;
2934 event.mArgument.mParameter.mAudioUnit =
unit->AU();
2935 event.mArgument.mParameter.mParameterID =
descriptors[param_id].id;
2936 event.mArgument.mParameter.mScope =
descriptors[param_id].scope;
2937 event.mArgument.mParameter.mElement =
descriptors[param_id].element;
2949 AudioUnitEvent event;
2955 event.mEventType = kAudioUnitEvent_ParameterValueChange;
2956 event.mArgument.mParameter.mAudioUnit =
unit->AU();
2957 event.mArgument.mParameter.mParameterID =
descriptors[param_id].id;
2958 event.mArgument.mParameter.mScope =
descriptors[param_id].scope;
2959 event.mArgument.mParameter.mElement =
descriptors[param_id].element;
2965 event.mEventType = kAudioUnitEvent_BeginParameterChangeGesture;
2966 event.mArgument.mParameter.mAudioUnit =
unit->AU();
2967 event.mArgument.mParameter.mParameterID =
descriptors[param_id].id;
2968 event.mArgument.mParameter.mScope =
descriptors[param_id].scope;
2969 event.mArgument.mParameter.mElement =
descriptors[param_id].element;
2975 event.mEventType = kAudioUnitEvent_EndParameterChangeGesture;
2976 event.mArgument.mParameter.mAudioUnit =
unit->AU();
2977 event.mArgument.mParameter.mParameterID =
descriptors[param_id].id;
2978 event.mArgument.mParameter.mScope =
descriptors[param_id].scope;
2979 event.mArgument.mParameter.mElement =
descriptors[param_id].element;
2991 ((
AUPlugin*) arg)->parameter_change_listener (arg, src, event, host_time, new_value);
2997 ParameterMap::iterator i;
3003 switch (event->mEventType) {
3004 case kAudioUnitEvent_BeginParameterChangeGesture:
3007 case kAudioUnitEvent_EndParameterChangeGesture:
3010 case kAudioUnitEvent_ParameterValueChange:
bool transport_rolling() const
void add_state(XMLNode *) const
int set_output_format(AudioStreamBasicDescription &)
static std::string stringify_descriptor(const CAComponentDescription &)
bool parameter_is_input(uint32_t) const
bool load_preset(PresetRecord)
static void discover_music(PluginInfoList &)
int atoi(const string &s)
UserPresetMap user_preset_map
OSStatus get_transport_state_callback(Boolean *outIsPlaying, Boolean *outTransportStateChanged, Float64 *outCurrentSampleInTimeLine, Boolean *outIsCycling, Float64 *outCycleStartBeat, Float64 *outCycleEndBeat)
virtual int set_state(const XMLNode &, int version)
float lower
Minimum value (in Hz, for frequencies)
MidiBuffer & get_midi(size_t i)
float normal
Default value.
static bool au_preset_filter(const string &str, void *arg)
int set_state(const XMLNode &node, int)
int connect_and_run(BufferSet &bufs, ChanMapping in, ChanMapping out, pframes_t nframes, framecnt_t offset)
int create_parameter_listener(AUEventListenerProc callback, void *arg, float interval_secs)
Location * auto_loop_location() const
BufferSet * input_buffers
void bbt_time(framepos_t when, Timecode::BBT_Time &)
Boolean ComponentDescriptionsMatch_General(const ComponentDescription *inComponentDescription1, const ComponentDescription *inComponentDescription2, Boolean inIgnoreType)
static void discover_generators(PluginInfoList &)
const std::string & value() const
uint32_t parameter_count() const
const Meter & meter() const
double transport_speed() const
static unsigned int four_ints_to_four_byte_literal(unsigned char n[4])
Boolean ComponentAndDescriptionMatch_General(Component inComponent, const ComponentDescription *inComponentDescription, Boolean inIgnoreType)
static OSStatus _get_beat_and_tempo_callback(void *userData, Float64 *outCurrentBeat, Float64 *outCurrentTempo)
AUPluginInfo(boost::shared_ptr< CAComponentDescription >)
virtual void set_parameter(uint32_t which, float val)
std::vector< std::pair< int, int > > io_configs
static bool preset_search_path_initialized
bool last_transport_rolling
bool is_channel_event() const
static std::string get_preset_name_in_plist(CFPropertyListRef plist)
bool get_play_loop() const
shared_ptr< T > dynamic_pointer_cast(shared_ptr< U > const &r)
const std::string & write_buffer() const
ChanCount input_streams() const
void discover_factory_presets()
const std::string & name() const
PBD::Signal1< void, uint32_t > EndTouch
uint32_t nth_parameter(uint32_t which, bool &ok) const
static std::string maybe_fix_broken_au_id(const std::string &)
bool check_and_get_preset_name(Component component, const string &pathstr, string &preset_name)
bool _requires_fixed_size_buffers
AUEventListenerRef _parameter_listener
XMLNode * add_child_copy(const XMLNode &)
std::string current_preset() const
bool is_effect_without_midi_input() const
LIBPBD_API Transmitter error
LIBPBD_API Transmitter warning
const XMLNodeList & children(const std::string &str=std::string()) const
void * _parameter_listener_arg
int set_stream_format(int scope, uint32_t cnt, AudioStreamBasicDescription &)
std::map< std::string, AUPluginCachedInfo > CachedInfoMap
const char * name() const
const char * maker() const
std::ostream & endmsg(std::ostream &ostr)
bool is_instrument() const
framecnt_t frame_rate() const
LIBPBD_API void strip_whitespace_edges(std::string &str)
PBD::Signal2< void, uint32_t, float > ParameterChanged
static bool au_get_crashlog(std::string &msg)
AudioBuffer & get_audio(size_t i)
bool read_buffer(const std::string &)
int listen_to_parameter(uint32_t param_id)
#define kCurrentSavedStateVersion
boost::shared_ptr< CAComponentDescription > descriptor
OSStatus get_musical_time_location_callback(UInt32 *outDeltaSampleOffsetToNextBeat, Float32 *outTimeSig_Numerator, UInt32 *outTimeSig_Denominator, Float64 *outCurrentMeasureDownBeat)
float last_transport_speed
static void discover_fx(PluginInfoList &)
void do_remove_preset(std::string)
static int load_cached_info()
virtual int connect_and_run(BufferSet &bufs, ChanMapping in, ChanMapping out, pframes_t nframes, framecnt_t offset)
static int save_property_list(CFPropertyListRef propertyList, Glib::ustring path)
std::vector< AUParameterDescriptor > descriptors
std::list< XMLNode * > XMLNodeList
void print_parameter(uint32_t, char *, uint32_t len) const
double frames_per_beat(framecnt_t sr) const
void discover_parameters()
int set_input_format(AudioStreamBasicDescription &)
LIBARDOUR_API std::string user_config_directory(int version=-1)
static Glib::ustring au_cache_path()
boost::shared_ptr< Plugin > PluginPtr
LIBARDOUR_API uint64_t PluginManager
bool parameter_is_output(uint32_t) const
static string preset_suffix
std::string state_node_name() const
XMLProperty * property(const char *)
static OSStatus _get_transport_state_callback(void *userData, Boolean *outIsPlaying, Boolean *outTransportStateChanged, Float64 *outCurrentSampleInTimeLine, Boolean *outIsCycling, Float64 *outCycleStartBeat, Float64 *outCycleEndBeat)
float upper
Maximum value (in Hz, for frequencies)
static void au_remove_crashlog(void)
OSStatus get_beat_and_tempo_callback(Float64 *outCurrentBeat, Float64 *outCurrentTempo)
bool is_effect_with_midi_input() const
XMLNode * set_root(XMLNode *n)
float get_parameter(uint32_t which) const
AudioUnitParameterUnit au_unit
framepos_t transport_frame() const
boost::shared_ptr< Route > master_out() const
boost::shared_ptr< CAComponent > comp
virtual const char * maker() const =0
std::map< std::string, PresetRecord > _presets
const PBD::ID & id() const
static void set_preset_name_in_plist(CFPropertyListRef plist, string preset_name)
bool parameter_is_control(uint32_t) const
PluginPtr load(Session &session)
bool configure_io(ChanCount in, ChanCount out)
ChanCount output_streams() const
#define DEBUG_TRACE(bits, str)
static string preset_search_path
static void add_cached_info(const std::string &, AUPluginCachedInfo &)
float default_value(uint32_t port)
static void au_crashlog(std::string)
bool can_support_io_configuration(const ChanCount &in, ChanCount &out)
double note_divisor() const
Boolean ComponentDescriptionsMatch_Loose(const ComponentDescription *inComponentDescription1, const ComponentDescription *inComponentDescription2)
static void au_unblacklist(std::string id)
static bool cached_io_configuration(const std::string &, UInt32, CAComponent &, AUPluginCachedInfo &, const std::string &name)
LIBARDOUR_API std::string user_cache_directory()
LIBPBD_API Transmitter info
pframes_t _current_block_size
static void save_cached_info()
PluginInfoPtr get_info() const
double beats_per_minute() const
int set_block_size(pframes_t nframes)
static CFPropertyListRef load_property_list(Glib::ustring path)
std::set< Evoral::Parameter > automatable() const
boost::shared_ptr< CAComponent > get_comp() const
bool parameter_is_audio(uint32_t) const
XMLProperty * add_property(const char *name, const std::string &value)
int get_parameter_descriptor(uint32_t which, ParameterDescriptor &) const
std::string do_save_preset(std::string name)
void parameter_change_listener(void *, void *, const AudioUnitEvent *event, UInt64 host_time, Float32 new_value)
ParameterMap parameter_map
void add_child_nocopy(XMLNode &)
static CachedInfoMap cached_info
framecnt_t frames_processed
pframes_t get_block_size() const
static void au_blacklist(std::string id)
Boolean ComponentDescriptionsMatch(const ComponentDescription *inComponentDescription1, const ComponentDescription *inComponentDescription2)
bool toggled
True iff parameter is boolean.
Boolean ComponentAndDescriptionMatch(Component inComponent, const ComponentDescription *inComponentDescription)
OSStatus render_callback(AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData)
void set_info(PluginInfoPtr)
static FILE * _crashlog_fd
const ChanCount & count() const
void set(DataType t, uint32_t count)
LIBARDOUR_API PBD::Signal1< void, std::string > BootMessage
ARDOUR::Session & _session
const Tempo & tempo() const
virtual const char * name() const =0
static SInt32 GetDictionarySInt32Value(CFDictionaryRef inAUStateDictionary, CFStringRef inDictionaryKey, Boolean *outSuccess)
PBD::Signal1< void, uint32_t > StartTouch
const ChanCount & available() const
double divisions_per_bar() const
boost::shared_ptr< IO > input() const
AudioBufferList * buffers
LIBARDOUR_API uint64_t AudioUnits
AUPlugin(AudioEngine &engine, Session &session, boost::shared_ptr< CAComponent > comp)
FactoryPresetMap factory_preset_map
void set_parameter(uint32_t which, float val)
LIBARDOUR_API PBD::Signal3< void, std::string, std::string, bool > PluginScanMessage
static void au_start_crashlog(void)
const char * label() const
static bool is_blacklisted(std::string id)
std::string unique_id() const
const uint8_t * buffer() const
boost::shared_ptr< CAAudioUnit > unit
static OSStatus _render_callback(void *userData, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData)
static void discover_instruments(PluginInfoList &)
std::list< PluginInfoPtr > PluginInfoList
const Sample * data(framecnt_t offset=0) const
Boolean ComponentAndDescriptionMatch_Loosely(Component inComponent, const ComponentDescription *inComponentDescription)
void find_files_matching_filter(vector< string > &result, const Searchpath &paths, bool(*filter)(const string &, void *), void *arg, bool pass_fullpath, bool return_fullpath, bool recurse)
std::vector< std::pair< int, int > > io_configs
XMLNodeList::const_iterator XMLNodeConstIterator
static void get_names(CAComponentDescription &, std::string &name, std::string &maker)
framecnt_t signal_latency() const
static OSStatus _get_musical_time_location_callback(void *userData, UInt32 *outDeltaSampleOffsetToNextBeat, Float32 *outTimeSig_Numerator, UInt32 *outTimeSig_Denominator, Float64 *outCurrentMeasureDownBeat)
static OSStatus GetAUComponentDescriptionFromStateData(CFPropertyListRef inAUStateData, ComponentDescription *outComponentDescription)
bool requires_fixed_size_buffers() const
virtual bool load_preset(PresetRecord)
virtual void set_info(const PluginInfoPtr inf)
static PluginInfoList * discover()
static void _parameter_change_listener(void *, void *, const AudioUnitEvent *event, UInt64 host_time, Float32 new_value)
std::string string_compose(const std::string &fmt, const T1 &o1)
int end_listen_to_parameter(uint32_t param_id)
static void discover_by_description(PluginInfoList &, CAComponentDescription &)
std::string describe_parameter(Evoral::Parameter)