/[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 1846 - (hide annotations) (download)
Thu Feb 26 22:43:45 2009 UTC (15 years, 1 month ago) by iliev
File size: 13911 byte(s)
* AU plugin, work in progress:
* added build files
* fixes in MIDI event handling

1 iliev 1845 /***************************************************************************
2     * *
3     * LinuxSampler - modular, streaming capable sampler *
4     * *
5     * Copyright (C) 2009 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, 1), Plugin(false) {
49    
50     #if AU_DEBUG_DISPATCHER
51     mDebugDispatcher = new AUDebugDispatcher(this);
52     #endif
53     charBufSize = 512;
54     charBuf = new char[charBufSize];
55     InstallListeners();
56    
57     SetAFactoryPresetAsCurrent(factoryPresets[kDefaultPreset]);
58     }
59    
60     PluginAU::~PluginAU() {
61     #if AU_DEBUG_DISPATCHER
62     delete mDebugDispatcher;
63     #endif
64     delete [] charBuf;
65     UninstallListeners();
66     }
67    
68     void PluginAU::InstallListeners() {
69     AddPropertyListener(kAudioUnitProperty_ContextName, PropertyListenerCallback, this);
70    
71     }
72    
73     void PluginAU::UninstallListeners() {
74     RemovePropertyListener(kAudioUnitProperty_ContextName, PropertyListenerCallback, this, true);
75     }
76    
77     void PluginAU::PropertyListenerCallback (
78     void* inRefCon,
79     AudioUnit ci,
80     AudioUnitPropertyID inID,
81     AudioUnitScope inScope,
82     AudioUnitElement inElement
83     ) {
84     ((PluginAU*)inRefCon)->PropertyChanged(inID, inScope, inElement);
85     }
86    
87     void PluginAU::PropertyChanged (
88     AudioUnitPropertyID inID,
89     AudioUnitScope inScope,
90     AudioUnitElement inElement
91     ) {
92     switch (inID) {
93     case kAudioUnitProperty_ContextName:
94     // TODO:
95     //GetStr(mContextName);
96     break;
97     }
98     }
99    
100     ComponentResult PluginAU::GetPropertyInfo (
101     AudioUnitPropertyID inID,
102     AudioUnitScope inScope,
103     AudioUnitElement inElement,
104     UInt32& outDataSize,
105     Boolean& outWritable
106     ) {
107     // TODO:
108     return MusicDeviceBase::GetPropertyInfo(inID, inScope, inElement, outDataSize, outWritable);
109     }
110    
111     ComponentResult PluginAU::GetProperty (
112     AudioUnitPropertyID inID,
113     AudioUnitScope inScope,
114     AudioUnitElement inElement,
115     void* outData
116     ) {
117     // TODO:
118     return MusicDeviceBase::GetProperty(inID, inScope, inElement, outData);
119     }
120    
121     ComponentResult PluginAU::SetProperty (
122     AudioUnitPropertyID inID,
123     AudioUnitScope inScope,
124     AudioUnitElement inElement,
125     const void* inData,
126     UInt32 inDataSize
127     ) {
128     switch (inID) {
129     case kAudioUnitProperty_AUHostIdentifier:
130     if(inData != NULL) {
131     AUHostIdentifier* host = (AUHostIdentifier*)inData;
132     hostName = GetHostNameByID(GetStr(host->hostName));
133     }
134     break;
135     }
136     return MusicDeviceBase::SetProperty(inID, inScope, inElement, inData, inDataSize);
137     }
138    
139     ComponentResult PluginAU::GetPresets(CFArrayRef* outData) const {
140     if (outData == NULL) return noErr;
141    
142     CFMutableArrayRef presetsArray = CFArrayCreateMutable (
143     NULL, kFactoryPresetCount, NULL
144     );
145    
146     for (int i = 0; i < kFactoryPresetCount; i++) {
147     CFArrayAppendValue(presetsArray, &factoryPresets[i] );
148     }
149    
150     *outData = (CFArrayRef)presetsArray;
151     return noErr;
152     }
153    
154     OSStatus PluginAU::NewFactoryPresetSet(const AUPreset& inNewFactoryPreset) {
155     if(global == NULL) return noErr;
156    
157     switch(inNewFactoryPreset.presetNumber) {
158     case kOneSamplerChannel:
159     AddSamplerChannel("GIG", midi_chan_1);
160     break;
161     case k16SamplerChannels:
162     Set16SamplerChannelsPreset();
163     break;
164     default:
165     return kAudioUnitErr_InvalidProperty;
166     }
167    
168     SetAFactoryPresetAsCurrent(inNewFactoryPreset);
169     return noErr;
170     }
171    
172     UInt32 PluginAU::SupportedNumChannels(const AUChannelInfo** outInfo) {
173     static AUChannelInfo plugChannelInfo = { 0, -1 };
174     if (outInfo != NULL) *outInfo = &plugChannelInfo;
175     return 1;
176     }
177    
178     ComponentResult PluginAU::Initialize() {
179     MusicDeviceBase::Initialize();
180    
181     // The timeconsuming tasks delayed until the pluging is to be used
182     PreInit();
183    
184     if(pAudioDevice) {
185     RemoveChannels();
186     global->pSampler->DestroyAudioOutputDevice(pAudioDevice);
187     pAudioDevice = NULL;
188     }
189    
190     if(pMidiDevice) {
191     global->pSampler->DestroyMidiInputDevice(pMidiDevice);
192     pMidiDevice = NULL;
193     }
194    
195     int srate = (int)GetStreamFormat(kAudioUnitScope_Output, 0).mSampleRate;
196     int chnNum = GetStreamFormat(kAudioUnitScope_Output, 0).NumberChannels();
197    
198     Init(srate, GetMaxFramesPerSlice(), chnNum);
199    
200     if(hostName.empty()) {
201     hostName = GetHostNameByID(GetHostBundleID());
202     }
203    
204     if(!hostName.empty()) {
205     for(int i = 0; i < pMidiDevice->PortCount(); i++) {
206     DeviceRuntimeParameter* param;
207     param = pMidiDevice->GetPort(i)->PortParameters()["NAME"];
208     if(param != NULL) param->SetValue(hostName + " " + ToString(i + 1));
209    
210     }
211     }
212    
213     if(!hostName.empty()) {
214     for(int i = 0; i < pAudioDevice->ChannelCount(); i++) {
215     DeviceRuntimeParameter* param;
216     param = pAudioDevice->Channel(i)->ChannelParameters()["NAME"];
217     if(param != NULL) param->SetValue(hostName + " " + ToString(i + 1));
218    
219     }
220     }
221    
222     NewFactoryPresetSet(factoryPresets[kDefaultPreset]);
223    
224     /*AudioChannelLayout* pLayout = CAAudioChannelLayout::Create(chnNum);
225     if(pLayout != NULL) {
226     for(int i = 0; i < chnNum; i++) {
227     pLayout->mChannelDescriptions[i].mChannelLabel =
228     }
229     SetAudioChannelLayout(kAudioUnitScope_Output, 0, pLayout);
230     }*/
231    
232     return noErr;
233     }
234    
235     bool PluginAU::StreamFormatWritable(AudioUnitScope scope, AudioUnitElement element) {
236     return IsInitialized() ? false : true;
237     }
238    
239     OSStatus PluginAU::HandleMidiEvent (
240     UInt8 inStatus, UInt8 inChannel,
241     UInt8 inData1, UInt8 inData2,
242     UInt32 inStartFrame
243     ) {
244     if(!IsInitialized()) return kAudioUnitErr_Uninitialized;
245     MidiInputPort* port = pMidiDevice->Port();
246    
247     switch (inStatus) {
248     case 0x90:
249 iliev 1846 if(inData1 >= 0x80) break;
250    
251 iliev 1845 if(inData2) {
252     port->DispatchNoteOn (
253     inData1, inData2, inChannel, inStartFrame
254     );
255     } else {
256     port->DispatchNoteOff (
257     inData1, inData2, inChannel, inStartFrame
258     );
259     }
260     break;
261     case 0x80:
262 iliev 1846 if(inData1 >= 0x80) break;
263 iliev 1845 port->DispatchNoteOff (
264     inData1, inData2, inChannel, inStartFrame
265     );
266     break;
267     case 0xB0:
268 iliev 1846 if(inData1 == 0) {
269     port->DispatchBankSelectMsb(inData2, inChannel);
270     } else if(inData1 == 32) {
271     port->DispatchBankSelectLsb(inData2, inChannel);
272     }
273    
274 iliev 1845 port->DispatchControlChange (
275     inData1, inData2, inChannel, inStartFrame
276     );
277     break;
278     case 0xC0:
279 iliev 1846 if(inData1 < 0x80) port->DispatchProgramChange(inData1, inChannel);
280 iliev 1845 break;
281     case 0xE0:
282 iliev 1846 port->DispatchPitchbend(inData1, inChannel, inStartFrame);
283 iliev 1845 break;
284     case 0xD0:
285 iliev 1846 port->DispatchControlChange(128, inData1, inChannel);
286 iliev 1845 break;
287     }
288    
289     return noErr;
290     }
291    
292     ComponentResult PluginAU::Render (
293     AudioUnitRenderActionFlags& ioActionFlags,
294     const AudioTimeStamp& inTimeStamp,
295     UInt32 inNumberFrames
296     ) {
297     float* buf;
298     int chnCount = GetOutput(0)->GetBufferList().mNumberBuffers;
299     for(int i = 0; i < chnCount; i++) {
300     buf = (float*)GetOutput(0)->GetBufferList().mBuffers[i].mData;
301     pAudioDevice->Channel(i)->SetBuffer(buf);
302     }
303    
304     pAudioDevice->Render(inNumberFrames);
305     return noErr;
306     }
307    
308     void PluginAU::Set16SamplerChannelsPreset() {
309     RemoveChannels();
310     for(int i = 0; i < 16; i++) {
311     AddSamplerChannel("GIG", midiChns[i]);
312     }
313     }
314    
315     void PluginAU::AddSamplerChannel(const char* engine, midi_chan_t midiChn) {
316     SamplerChannel* channel = global->pSampler->AddSamplerChannel();
317     channel->SetEngineType(engine);
318     channel->SetAudioOutputDevice(pAudioDevice);
319     channel->SetMidiInputDevice(pMidiDevice);
320     channel->SetMidiInputChannel(midiChn);
321     }
322    
323     OSStatus PluginAU::GetInstrumentCount(UInt32 &outInstCount) const {
324     // TODO:
325     return MusicDeviceBase::GetInstrumentCount(outInstCount);
326     }
327    
328     std::string PluginAU::GetHostNameByID(std::string Identifier) {
329     std::string name;
330     if(Identifier == "com.apple.logic.pro") {
331     name = "Logic Pro";
332     } else if(Identifier == "com.apple.garageband") {
333     name = "GarageBand";
334     } else if(Identifier == "com.ableton.live") {
335     name = "Ableton Live";
336     } else if(Identifier == "com.apple.audio.aulab") {
337     name = "AULab";
338     }
339    
340     return name;
341     }
342    
343     std::string PluginAU::GetHostBundleID() {
344     std::string id;
345     CFStringRef identifier;
346     CFBundleRef mainBundle = CFBundleGetMainBundle();
347     if (mainBundle) {
348     identifier = CFBundleGetIdentifier(mainBundle);
349     id = GetStr(identifier);
350     }
351    
352     return id;
353     }
354    
355     std::string PluginAU::GetStr(CFStringRef s) {
356     if(s == NULL) return std::string("");
357    
358     CFRetain(s);
359     CFIndex len = CFStringGetLength(s) + 1;
360     if(charBufSize < len) {
361     delete [] charBuf;
362     charBufSize *= 2;
363     if(charBufSize < len) charBufSize = len;
364     charBuf = new char[charBufSize];
365     }
366    
367     std::string s2;
368     if(CFStringGetCString(s, charBuf, charBufSize, kCFStringEncodingASCII)) {
369     s2 = charBuf;
370     }
371     CFRelease(s);
372    
373     return s2;
374     }
375    
376     ComponentResult PluginAU::SaveState(CFPropertyListRef* outData) {
377     ComponentResult result = AUBase::SaveState(outData);
378     if(global == NULL || result != noErr) return result;
379    
380     void** d = const_cast<void**> (outData);
381     CFMutableDictionaryRef dict = static_cast<CFMutableDictionaryRef> (*d);
382    
383     std::string s = GetState();
384     CFStringRef cfsState = CFStringCreateWithCString(NULL, s.c_str(), kCFStringEncodingASCII);
385    
386     CFDictionarySetValue(dict, CFSTR("org.linuxsampler.LinuxSamplerPluginAU"), cfsState);
387     CFRelease(cfsState);
388    
389     return noErr;
390     }
391    
392     ComponentResult PluginAU::RestoreState(CFPropertyListRef inData) {
393     ComponentResult result = AUBase::RestoreState(inData);
394     if(global == NULL || result != noErr) return result;
395    
396     CFDictionaryRef dict = static_cast<CFDictionaryRef>(inData);
397    
398     const void* d = CFDictionaryGetValue (
399     dict, CFSTR("org.linuxsampler.LinuxSamplerPluginAU")
400     );
401    
402     CFStringRef str = static_cast<CFStringRef>(d);
403     if(str != NULL) SetState(GetStr(str));
404    
405     return noErr;
406     }
407    
408     //} // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC