2 * Wine Driver for CoreAudio / AudioUnit
4 * Copyright 2005, 2006 Emmanuel Maillard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #define ULONG CoreFoundation_ULONG
24 #define HRESULT CoreFoundation_HRESULT
25 #ifndef HAVE_AUDIOUNIT_AUDIOCOMPONENT_H
26 #include <CoreServices/CoreServices.h>
28 #include <AudioUnit/AudioUnit.h>
29 #include <AudioToolbox/AudioToolbox.h>
34 #undef STDMETHODCALLTYPE
35 #include "coreaudio.h"
36 #include "wine/debug.h"
38 #ifndef HAVE_AUDIOUNIT_AUDIOCOMPONENT_H
39 /* Define new AudioComponent Manager functions for compatibility's sake */
40 typedef Component AudioComponent;
41 typedef ComponentDescription AudioComponentDescription;
42 typedef ComponentInstance AudioComponentInstance;
44 static inline AudioComponent AudioComponentFindNext(AudioComponent ac, AudioComponentDescription *desc)
46 return FindNextComponent(ac, desc);
49 static inline OSStatus AudioComponentInstanceNew(AudioComponent ac, AudioComponentInstance *aci)
51 return OpenAComponent(ac, aci);
54 static inline OSStatus AudioComponentInstanceDispose(AudioComponentInstance aci)
56 return CloseComponent(aci);
60 #ifndef HAVE_AUGRAPHADDNODE
61 static inline OSStatus AUGraphAddNode(AUGraph graph, const AudioComponentDescription *desc, AUNode *node)
63 return AUGraphNewNode(graph, desc, 0, NULL, node);
66 static inline OSStatus AUGraphNodeInfo(AUGraph graph, AUNode node, AudioComponentDescription *desc, AudioUnit *au)
68 return AUGraphGetNodeInfo(graph, node, desc, 0, NULL, au);
72 WINE_DEFAULT_DEBUG_CHANNEL(wave);
73 WINE_DECLARE_DEBUG_CHANNEL(midi);
75 static const char *streamDescription(const AudioStreamBasicDescription* stream)
77 return wine_dbg_sprintf("\n mSampleRate : %f\n mFormatID : %s\n mFormatFlags : %lX\n mBytesPerPacket : %lu\n mFramesPerPacket : %lu\n mBytesPerFrame : %lu\n mChannelsPerFrame : %lu\n mBitsPerChannel : %lu\n",
79 wine_dbgstr_fourcc(stream->mFormatID),
81 stream->mBytesPerPacket,
82 stream->mFramesPerPacket,
83 stream->mBytesPerFrame,
84 stream->mChannelsPerFrame,
85 stream->mBitsPerChannel);
88 int AudioUnit_CloseAudioUnit(AudioUnit au)
90 OSStatus err = AudioComponentInstanceDispose(au);
91 return (err == noErr);
94 int AudioUnit_InitializeWithStreamDescription(AudioUnit au, AudioStreamBasicDescription *stream)
98 TRACE("input format: %s\n", streamDescription(stream));
100 err = AudioUnitSetProperty(au, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input,
101 0, stream, sizeof(*stream));
105 ERR("AudioUnitSetProperty return an error %s\n", wine_dbgstr_fourcc(err));
109 err = AudioUnitInitialize(au);
112 ERR("AudioUnitInitialize return an error %s\n", wine_dbgstr_fourcc(err));
118 int AudioUnit_SetVolume(AudioUnit au, float left, float right)
120 OSStatus err = noErr;
123 if (!once++) FIXME("independent left/right volume not implemented (%f, %f)\n", left, right);
125 err = AudioUnitSetParameter(au, kHALOutputParam_Volume, kAudioUnitParameterFlag_Output, 0, left, 0);
129 ERR("AudioUnitSetParameter return an error %s\n", wine_dbgstr_fourcc(err));
135 int AudioUnit_GetVolume(AudioUnit au, float *left, float *right)
137 OSStatus err = noErr;
140 if (!once++) FIXME("independent left/right volume not implemented\n");
142 err = AudioUnitGetParameter(au, kHALOutputParam_Volume, kAudioUnitParameterFlag_Output, 0, left);
145 ERR("AudioUnitGetParameter return an error %s\n", wine_dbgstr_fourcc(err));
153 /* FIXME: implement sample rate conversion on input */
154 int AudioUnit_GetInputDeviceSampleRate(void)
156 AudioDeviceID defaultInputDevice;
158 AudioObjectPropertyAddress propertyAddress;
162 param = sizeof(defaultInputDevice);
163 propertyAddress.mSelector = kAudioHardwarePropertyDefaultInputDevice;
164 propertyAddress.mScope = kAudioObjectPropertyScopeGlobal;
165 propertyAddress.mElement = kAudioObjectPropertyElementMaster;
166 err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &propertyAddress, 0, NULL, ¶m, &defaultInputDevice);
167 if (err != noErr || defaultInputDevice == kAudioDeviceUnknown)
169 ERR("Couldn't get the default audio input device ID: %08lx\n", err);
173 param = sizeof(sampleRate);
174 propertyAddress.mSelector = kAudioDevicePropertyNominalSampleRate;
175 propertyAddress.mScope = kAudioDevicePropertyScopeInput;
176 err = AudioObjectGetPropertyData(defaultInputDevice, &propertyAddress, 0, NULL, ¶m, &sampleRate);
179 ERR("Couldn't get the device sample rate: %08lx\n", err);
189 int SynthUnit_CreateDefaultSynthUnit(AUGraph *graph, AudioUnit *synth)
192 AudioComponentDescription desc;
196 err = NewAUGraph(graph);
199 ERR_(midi)("NewAUGraph return %s\n", wine_dbgstr_fourcc(err));
203 desc.componentManufacturer = kAudioUnitManufacturer_Apple;
204 desc.componentFlags = 0;
205 desc.componentFlagsMask = 0;
207 /* create synth node */
208 desc.componentType = kAudioUnitType_MusicDevice;
209 desc.componentSubType = kAudioUnitSubType_DLSSynth;
211 err = AUGraphAddNode(*graph, &desc, &synthNode);
214 ERR_(midi)("AUGraphAddNode cannot create synthNode : %s\n", wine_dbgstr_fourcc(err));
218 /* create out node */
219 desc.componentType = kAudioUnitType_Output;
220 desc.componentSubType = kAudioUnitSubType_DefaultOutput;
222 err = AUGraphAddNode(*graph, &desc, &outNode);
225 ERR_(midi)("AUGraphAddNode cannot create outNode %s\n", wine_dbgstr_fourcc(err));
229 err = AUGraphOpen(*graph);
232 ERR_(midi)("AUGraphOpen return %s\n", wine_dbgstr_fourcc(err));
236 /* connecting the nodes */
237 err = AUGraphConnectNodeInput(*graph, synthNode, 0, outNode, 0);
240 ERR_(midi)("AUGraphConnectNodeInput cannot connect synthNode to outNode : %s\n", wine_dbgstr_fourcc(err));
244 /* Get the synth unit */
245 err = AUGraphNodeInfo(*graph, synthNode, 0, synth);
248 ERR_(midi)("AUGraphNodeInfo return %s\n", wine_dbgstr_fourcc(err));
255 int SynthUnit_Initialize(AudioUnit synth, AUGraph graph)
257 OSStatus err = noErr;
259 err = AUGraphInitialize(graph);
262 ERR_(midi)("AUGraphInitialize(%p) return %s\n", graph, wine_dbgstr_fourcc(err));
266 err = AUGraphStart(graph);
269 ERR_(midi)("AUGraphStart(%p) return %s\n", graph, wine_dbgstr_fourcc(err));
276 int SynthUnit_Close(AUGraph graph)
278 OSStatus err = noErr;
280 err = AUGraphStop(graph);
283 ERR_(midi)("AUGraphStop(%p) return %s\n", graph, wine_dbgstr_fourcc(err));
287 err = DisposeAUGraph(graph);
290 ERR_(midi)("DisposeAUGraph(%p) return %s\n", graph, wine_dbgstr_fourcc(err));