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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2197 - (hide 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 iliev 1845 /***************************************************************************
2     * *
3     * LinuxSampler - modular, streaming capable sampler *
4     * *
5 persson 2197 * Copyright (C) 2009 - 2011 Grigor Iliev *
6 iliev 1845 * *
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 persson 2197 : MusicDeviceBase(inComponentInstance, 0, 16), Plugin(false) {
49 iliev 1845 #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 persson 2197 static AUChannelInfo plugChannelInfo = { 0, 2 };
173 iliev 1845 if (outInfo != NULL) *outInfo = &plugChannelInfo;
174     return 1;
175     }
176    
177     ComponentResult PluginAU::Initialize() {
178 persson 2197 // 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 iliev 1845 MusicDeviceBase::Initialize();
188    
189 persson 2197 // The timeconsuming tasks delayed until the plugin is to be used
190 iliev 1845 PreInit();
191    
192     if(pAudioDevice) {
193     RemoveChannels();
194 iliev 1992 DestroyDevice(pAudioDevice);
195 iliev 1845 pAudioDevice = NULL;
196     }
197    
198     if(pMidiDevice) {
199 iliev 1992 DestroyDevice(pMidiDevice);
200 iliev 1845 pMidiDevice = NULL;
201     }
202    
203     int srate = (int)GetStreamFormat(kAudioUnitScope_Output, 0).mSampleRate;
204 persson 2197 int chnNum = 0;
205     for (int i = 0 ; i < busCount ; i++) {
206     chnNum += GetOutput(i)->GetStreamFormat().mChannelsPerFrame;
207     }
208 iliev 1845
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 iliev 1846 if(inData1 >= 0x80) break;
261    
262 iliev 1845 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 iliev 1846 if(inData1 >= 0x80) break;
274 iliev 1845 port->DispatchNoteOff (
275     inData1, inData2, inChannel, inStartFrame
276     );
277     break;
278     case 0xB0:
279 iliev 1846 if(inData1 == 0) {
280     port->DispatchBankSelectMsb(inData2, inChannel);
281     } else if(inData1 == 32) {
282     port->DispatchBankSelectLsb(inData2, inChannel);
283     }
284    
285 iliev 1845 port->DispatchControlChange (
286     inData1, inData2, inChannel, inStartFrame
287     );
288     break;
289     case 0xC0:
290 iliev 1846 if(inData1 < 0x80) port->DispatchProgramChange(inData1, inChannel);
291 iliev 1845 break;
292     case 0xE0:
293 persson 1887 port->DispatchPitchbend((inData1 | inData2 << 7) - 8192, inChannel, inStartFrame);
294 iliev 1845 break;
295     case 0xD0:
296 iliev 1846 port->DispatchControlChange(128, inData1, inChannel);
297 iliev 1845 break;
298     }
299    
300     return noErr;
301     }
302    
303     ComponentResult PluginAU::Render (
304     AudioUnitRenderActionFlags& ioActionFlags,
305     const AudioTimeStamp& inTimeStamp,
306     UInt32 inNumberFrames
307     ) {
308 persson 2197 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 iliev 1845 }
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