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
));