/[svn]/linuxsampler/trunk/src/hostplugins/au/PluginAU.cpp
ViewVC logotype

Contents of /linuxsampler/trunk/src/hostplugins/au/PluginAU.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2197 - (show annotations) (download)
Sat Jul 2 09:55:42 2011 UTC (12 years, 9 months ago) by persson
File size: 14515 byte(s)
* AU: changed number of output channels from one stereo to 16 stereo
* VST: made it possible to build the VST plugin for Mac
* AU: link AU plugin dynamically if --disable-shared isn't specified
* minor Makefile fix for building lscpparser when build and source
  directories are separate

1 /***************************************************************************
2 * *
3 * LinuxSampler - modular, streaming capable sampler *
4 * *
5 * Copyright (C) 2009 - 2011 Grigor Iliev *
6 * *
7 * This program is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation; either version 2 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program; if not, write to the Free Software *
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
20 * MA 02111-1307 USA *
21 ***************************************************************************/
22
23 #include "PluginAU.h"
24
25 #include "../../drivers/audio/AudioChannel.h"
26
27 #if AU_DEBUG_DISPATCHER
28 #include <AUDebugDispatcher.h>
29 #endif
30
31 COMPONENT_ENTRY(PluginAU)
32
33 //namespace LinuxSampler {
34
35 const midi_chan_t PluginAU::midiChns[16] = {
36 midi_chan_1, midi_chan_2, midi_chan_3, midi_chan_4, midi_chan_5,
37 midi_chan_6, midi_chan_7, midi_chan_8, midi_chan_9, midi_chan_10,
38 midi_chan_11, midi_chan_12, midi_chan_13, midi_chan_14, midi_chan_15,
39 midi_chan_16
40 };
41
42 AUPreset PluginAU::factoryPresets[kFactoryPresetCount] = {
43 { kOneSamplerChannel, CFSTR("LS: 1 Channel") },
44 { k16SamplerChannels, CFSTR("LS: 16 Channels") }
45 };
46
47 PluginAU::PluginAU(ComponentInstance inComponentInstance)
48 : MusicDeviceBase(inComponentInstance, 0, 16), Plugin(false) {
49 #if AU_DEBUG_DISPATCHER
50 mDebugDispatcher = new AUDebugDispatcher(this);
51 #endif
52 charBufSize = 512;
53 charBuf = new char[charBufSize];
54 InstallListeners();
55
56 SetAFactoryPresetAsCurrent(factoryPresets[kDefaultPreset]);
57 }
58
59 PluginAU::~PluginAU() {
60 #if AU_DEBUG_DISPATCHER
61 delete mDebugDispatcher;
62 #endif
63 delete [] charBuf;
64 UninstallListeners();
65 }
66
67 void PluginAU::InstallListeners() {
68 AddPropertyListener(kAudioUnitProperty_ContextName, PropertyListenerCallback, this);
69
70 }
71
72 void PluginAU::UninstallListeners() {
73 RemovePropertyListener(kAudioUnitProperty_ContextName, PropertyListenerCallback, this, true);
74 }
75
76 void PluginAU::PropertyListenerCallback (
77 void* inRefCon,
78 AudioUnit ci,
79 AudioUnitPropertyID inID,
80 AudioUnitScope inScope,
81 AudioUnitElement inElement
82 ) {
83 ((PluginAU*)inRefCon)->PropertyChanged(inID, inScope, inElement);
84 }
85
86 void PluginAU::PropertyChanged (
87 AudioUnitPropertyID inID,
88 AudioUnitScope inScope,
89 AudioUnitElement inElement
90 ) {
91 switch (inID) {
92 case kAudioUnitProperty_ContextName:
93 // TODO:
94 //GetStr(mContextName);
95 break;
96 }
97 }
98
99 ComponentResult PluginAU::GetPropertyInfo (
100 AudioUnitPropertyID inID,
101 AudioUnitScope inScope,
102 AudioUnitElement inElement,
103 UInt32& outDataSize,
104 Boolean& outWritable
105 ) {
106 // TODO:
107 return MusicDeviceBase::GetPropertyInfo(inID, inScope, inElement, outDataSize, outWritable);
108 }
109
110 ComponentResult PluginAU::GetProperty (
111 AudioUnitPropertyID inID,
112 AudioUnitScope inScope,
113 AudioUnitElement inElement,
114 void* outData
115 ) {
116 // TODO:
117 return MusicDeviceBase::GetProperty(inID, inScope, inElement, outData);
118 }
119
120 ComponentResult PluginAU::SetProperty (
121 AudioUnitPropertyID inID,
122 AudioUnitScope inScope,
123 AudioUnitElement inElement,
124 const void* inData,
125 UInt32 inDataSize
126 ) {
127 switch (inID) {
128 case kAudioUnitProperty_AUHostIdentifier:
129 if(inData != NULL) {
130 AUHostIdentifier* host = (AUHostIdentifier*)inData;
131 hostName = GetHostNameByID(GetStr(host->hostName));
132 }
133 break;
134 }
135 return MusicDeviceBase::SetProperty(inID, inScope, inElement, inData, inDataSize);
136 }
137
138 ComponentResult PluginAU::GetPresets(CFArrayRef* outData) const {
139 if (outData == NULL) return noErr;
140
141 CFMutableArrayRef presetsArray = CFArrayCreateMutable (
142 NULL, kFactoryPresetCount, NULL
143 );
144
145 for (int i = 0; i < kFactoryPresetCount; i++) {
146 CFArrayAppendValue(presetsArray, &factoryPresets[i] );
147 }
148
149 *outData = (CFArrayRef)presetsArray;
150 return noErr;
151 }
152
153 OSStatus PluginAU::NewFactoryPresetSet(const AUPreset& inNewFactoryPreset) {
154 if(global == NULL) return noErr;
155
156 switch(inNewFactoryPreset.presetNumber) {
157 case kOneSamplerChannel:
158 AddSamplerChannel("GIG", midi_chan_1);
159 break;
160 case k16SamplerChannels:
161 Set16SamplerChannelsPreset();
162 break;
163 default:
164 return kAudioUnitErr_InvalidProperty;
165 }
166
167 SetAFactoryPresetAsCurrent(inNewFactoryPreset);
168 return noErr;
169 }
170
171 UInt32 PluginAU::SupportedNumChannels(const AUChannelInfo** outInfo) {
172 static AUChannelInfo plugChannelInfo = { 0, 2 };
173 if (outInfo != NULL) *outInfo = &plugChannelInfo;
174 return 1;
175 }
176
177 ComponentResult PluginAU::Initialize() {
178 // format validation: current LS engines only support stereo
179 // buses
180 int busCount = Outputs().GetNumberOfElements();
181 for (int i = 0 ; i < busCount ; i++) {
182 if (GetOutput(i)->GetStreamFormat().mChannelsPerFrame != 2) {
183 return kAudioUnitErr_FormatNotSupported;
184 }
185 }
186
187 MusicDeviceBase::Initialize();
188
189 // The timeconsuming tasks delayed until the plugin is to be used
190 PreInit();
191
192 if(pAudioDevice) {
193 RemoveChannels();
194 DestroyDevice(pAudioDevice);
195 pAudioDevice = NULL;
196 }
197
198 if(pMidiDevice) {
199 DestroyDevice(pMidiDevice);
200 pMidiDevice = NULL;
201 }
202
203 int srate = (int)GetStreamFormat(kAudioUnitScope_Output, 0).mSampleRate;
204 int chnNum = 0;
205 for (int i = 0 ; i < busCount ; i++) {
206 chnNum += GetOutput(i)->GetStreamFormat().mChannelsPerFrame;
207 }
208
209 Init(srate, GetMaxFramesPerSlice(), chnNum);
210
211 if(hostName.empty()) {
212 hostName = GetHostNameByID(GetHostBundleID());
213 }
214
215 if(!hostName.empty()) {
216 for(int i = 0; i < pMidiDevice->PortCount(); i++) {
217 DeviceRuntimeParameter* param;
218 param = pMidiDevice->GetPort(i)->PortParameters()["NAME"];
219 if(param != NULL) param->SetValue(hostName + " " + ToString(i + 1));
220
221 }
222 }
223
224 if(!hostName.empty()) {
225 for(int i = 0; i < pAudioDevice->ChannelCount(); i++) {
226 DeviceRuntimeParameter* param;
227 param = pAudioDevice->Channel(i)->ChannelParameters()["NAME"];
228 if(param != NULL) param->SetValue(hostName + " " + ToString(i + 1));
229
230 }
231 }
232
233 NewFactoryPresetSet(factoryPresets[kDefaultPreset]);
234
235 /*AudioChannelLayout* pLayout = CAAudioChannelLayout::Create(chnNum);
236 if(pLayout != NULL) {
237 for(int i = 0; i < chnNum; i++) {
238 pLayout->mChannelDescriptions[i].mChannelLabel =
239 }
240 SetAudioChannelLayout(kAudioUnitScope_Output, 0, pLayout);
241 }*/
242
243 return noErr;
244 }
245
246 bool PluginAU::StreamFormatWritable(AudioUnitScope scope, AudioUnitElement element) {
247 return IsInitialized() ? false : true;
248 }
249
250 OSStatus PluginAU::HandleMidiEvent (
251 UInt8 inStatus, UInt8 inChannel,
252 UInt8 inData1, UInt8 inData2,
253 UInt32 inStartFrame
254 ) {
255 if(!IsInitialized()) return kAudioUnitErr_Uninitialized;
256 MidiInputPort* port = pMidiDevice->Port();
257
258 switch (inStatus) {
259 case 0x90:
260 if(inData1 >= 0x80) break;
261
262 if(inData2) {
263 port->DispatchNoteOn (
264 inData1, inData2, inChannel, inStartFrame
265 );
266 } else {
267 port->DispatchNoteOff (
268 inData1, inData2, inChannel, inStartFrame
269 );
270 }
271 break;
272 case 0x80:
273 if(inData1 >= 0x80) break;
274 port->DispatchNoteOff (
275 inData1, inData2, inChannel, inStartFrame
276 );
277 break;
278 case 0xB0:
279 if(inData1 == 0) {
280 port->DispatchBankSelectMsb(inData2, inChannel);
281 } else if(inData1 == 32) {
282 port->DispatchBankSelectLsb(inData2, inChannel);
283 }
284
285 port->DispatchControlChange (
286 inData1, inData2, inChannel, inStartFrame
287 );
288 break;
289 case 0xC0:
290 if(inData1 < 0x80) port->DispatchProgramChange(inData1, inChannel);
291 break;
292 case 0xE0:
293 port->DispatchPitchbend((inData1 | inData2 << 7) - 8192, inChannel, inStartFrame);
294 break;
295 case 0xD0:
296 port->DispatchControlChange(128, inData1, inChannel);
297 break;
298 }
299
300 return noErr;
301 }
302
303 ComponentResult PluginAU::Render (
304 AudioUnitRenderActionFlags& ioActionFlags,
305 const AudioTimeStamp& inTimeStamp,
306 UInt32 inNumberFrames
307 ) {
308 int i = 0;
309 int busCount = Outputs().GetNumberOfElements();
310 for (int bus = 0 ; bus < busCount ; bus++) {
311 AudioBufferList& list = GetOutput(bus)->PrepareBuffer(inNumberFrames);
312 int chnCount = list.mNumberBuffers;
313 for (int chn = 0; chn < chnCount; chn++) {
314 float* buf = static_cast<float*>(list.mBuffers[chn].mData);
315 pAudioDevice->Channel(i)->SetBuffer(buf);
316 i++;
317 }
318 }
319
320 pAudioDevice->Render(inNumberFrames);
321 return noErr;
322 }
323
324 void PluginAU::Set16SamplerChannelsPreset() {
325 RemoveChannels();
326 for(int i = 0; i < 16; i++) {
327 AddSamplerChannel("GIG", midiChns[i]);
328 }
329 }
330
331 void PluginAU::AddSamplerChannel(const char* engine, midi_chan_t midiChn) {
332 SamplerChannel* channel = global->pSampler->AddSamplerChannel();
333 channel->SetEngineType(engine);
334 channel->SetAudioOutputDevice(pAudioDevice);
335 channel->SetMidiInputDevice(pMidiDevice);
336 channel->SetMidiInputChannel(midiChn);
337 }
338
339 OSStatus PluginAU::GetInstrumentCount(UInt32 &outInstCount) const {
340 // TODO:
341 return MusicDeviceBase::GetInstrumentCount(outInstCount);
342 }
343
344 std::string PluginAU::GetHostNameByID(std::string Identifier) {
345 std::string name;
346 if(Identifier == "com.apple.logic.pro") {
347 name = "Logic Pro";
348 } else if(Identifier == "com.apple.garageband") {
349 name = "GarageBand";
350 } else if(Identifier == "com.ableton.live") {
351 name = "Ableton Live";
352 } else if(Identifier == "com.apple.audio.aulab") {
353 name = "AULab";
354 }
355
356 return name;
357 }
358
359 std::string PluginAU::GetHostBundleID() {
360 std::string id;
361 CFStringRef identifier;
362 CFBundleRef mainBundle = CFBundleGetMainBundle();
363 if (mainBundle) {
364 identifier = CFBundleGetIdentifier(mainBundle);
365 id = GetStr(identifier);
366 }
367
368 return id;
369 }
370
371 std::string PluginAU::GetStr(CFStringRef s) {
372 if(s == NULL) return std::string("");
373
374 CFRetain(s);
375 CFIndex len = CFStringGetLength(s) + 1;
376 if(charBufSize < len) {
377 delete [] charBuf;
378 charBufSize *= 2;
379 if(charBufSize < len) charBufSize = len;
380 charBuf = new char[charBufSize];
381 }
382
383 std::string s2;
384 if(CFStringGetCString(s, charBuf, charBufSize, kCFStringEncodingASCII)) {
385 s2 = charBuf;
386 }
387 CFRelease(s);
388
389 return s2;
390 }
391
392 ComponentResult PluginAU::SaveState(CFPropertyListRef* outData) {
393 ComponentResult result = AUBase::SaveState(outData);
394 if(global == NULL || result != noErr) return result;
395
396 void** d = const_cast<void**> (outData);
397 CFMutableDictionaryRef dict = static_cast<CFMutableDictionaryRef> (*d);
398
399 std::string s = GetState();
400 CFStringRef cfsState = CFStringCreateWithCString(NULL, s.c_str(), kCFStringEncodingASCII);
401
402 CFDictionarySetValue(dict, CFSTR("org.linuxsampler.LinuxSamplerPluginAU"), cfsState);
403 CFRelease(cfsState);
404
405 return noErr;
406 }
407
408 ComponentResult PluginAU::RestoreState(CFPropertyListRef inData) {
409 ComponentResult result = AUBase::RestoreState(inData);
410 if(global == NULL || result != noErr) return result;
411
412 CFDictionaryRef dict = static_cast<CFDictionaryRef>(inData);
413
414 const void* d = CFDictionaryGetValue (
415 dict, CFSTR("org.linuxsampler.LinuxSamplerPluginAU")
416 );
417
418 CFStringRef str = static_cast<CFStringRef>(d);
419 if(str != NULL) SetState(GetStr(str));
420
421 return noErr;
422 }
423
424 //} // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC