Create a macro to write a value to a subkey.
[wine] / dlls / dsound / duplex.c
1 /*              DirectSoundFullDuplex
2  *
3  * Copyright 1998 Marcus Meissner
4  * Copyright 1998 Rob Riggs
5  * Copyright 2000-2001 TransGaming Technologies, Inc.
6  * Copyright 2005 Robert Reif
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22 /*
23  * TODO:
24  *      Implement DirectSoundFullDuplex support.
25  */
26
27 #include <stdarg.h>
28
29 #define NONAMELESSSTRUCT
30 #define NONAMELESSUNION
31 #include "windef.h"
32 #include "winbase.h"
33 #include "mmsystem.h"
34 #include "mmddk.h"
35 #include "winreg.h"
36 #include "winternl.h"
37 #include "winnls.h"
38 #include "wine/debug.h"
39 #include "dsound.h"
40 #include "dsdriver.h"
41 #include "dsound_private.h"
42
43 WINE_DEFAULT_DEBUG_CHANNEL(dsound);
44
45 static HRESULT WINAPI IDirectSoundFullDuplexImpl_Initialize(
46     LPDIRECTSOUNDFULLDUPLEX iface,
47     LPCGUID pCaptureGuid,
48     LPCGUID pRendererGuid,
49     LPCDSCBUFFERDESC lpDscBufferDesc,
50     LPCDSBUFFERDESC lpDsBufferDesc,
51     HWND hWnd,
52     DWORD dwLevel,
53     LPLPDIRECTSOUNDCAPTUREBUFFER8 lplpDirectSoundCaptureBuffer8,
54     LPLPDIRECTSOUNDBUFFER8 lplpDirectSoundBuffer8 );
55
56 static const IDirectSoundFullDuplexVtbl dsfdvt;
57
58 /***************************************************************************
59  * DirectSoundFullDuplexCreate [DSOUND.10]
60  *
61  * Create and initialize a DirectSoundFullDuplex interface.
62  *
63  * PARAMS
64  *    pcGuidCaptureDevice [I] Address of sound capture device GUID.
65  *    pcGuidRenderDevice  [I] Address of sound render device GUID.
66  *    pcDSCBufferDesc     [I] Address of capture buffer description.
67  *    pcDSBufferDesc      [I] Address of  render buffer description.
68  *    hWnd                [I] Handle to application window.
69  *    dwLevel             [I] Cooperative level.
70  *    ppDSFD              [O] Address where full duplex interface returned.
71  *    ppDSCBuffer8        [0] Address where capture buffer interface returned.
72  *    ppDSBuffer8         [0] Address where render buffer interface returned.
73  *    pUnkOuter           [I] Must be NULL.
74  *
75  * RETURNS
76  *    Success: DS_OK
77  *    Failure: DSERR_NOAGGREGATION, DSERR_ALLOCATED, DSERR_INVALIDPARAM,
78  *             DSERR_OUTOFMEMORY DSERR_INVALIDCALL DSERR_NODRIVER
79  */
80 HRESULT WINAPI
81 DirectSoundFullDuplexCreate(
82     LPCGUID pcGuidCaptureDevice,
83     LPCGUID pcGuidRenderDevice,
84     LPCDSCBUFFERDESC pcDSCBufferDesc,
85     LPCDSBUFFERDESC pcDSBufferDesc,
86     HWND hWnd,
87     DWORD dwLevel,
88     LPDIRECTSOUNDFULLDUPLEX *ppDSFD,
89     LPDIRECTSOUNDCAPTUREBUFFER8 *ppDSCBuffer8,
90     LPDIRECTSOUNDBUFFER8 *ppDSBuffer8,
91     LPUNKNOWN pUnkOuter)
92 {
93     IDirectSoundFullDuplexImpl** ippDSFD=(IDirectSoundFullDuplexImpl**)ppDSFD;
94     TRACE("(%s,%s,%p,%p,%p,%lx,%p,%p,%p,%p)\n", debugstr_guid(pcGuidCaptureDevice),
95         debugstr_guid(pcGuidRenderDevice), pcDSCBufferDesc, pcDSBufferDesc,
96         hWnd, dwLevel, ppDSFD, ppDSCBuffer8, ppDSBuffer8, pUnkOuter);
97
98     if ( pUnkOuter ) {
99         WARN("pUnkOuter != 0\n");
100         return DSERR_NOAGGREGATION;
101     }
102
103     *ippDSFD = HeapAlloc(GetProcessHeap(),
104         HEAP_ZERO_MEMORY, sizeof(IDirectSoundFullDuplexImpl));
105
106     if (*ippDSFD == NULL) {
107         WARN("out of memory\n");
108         return DSERR_OUTOFMEMORY;
109     } else {
110         HRESULT hres;
111         IDirectSoundFullDuplexImpl *This = (IDirectSoundFullDuplexImpl *)*ippDSFD;
112
113         This->ref = 1;
114         This->lpVtbl = &dsfdvt;
115
116         InitializeCriticalSection( &(This->lock) );
117         This->lock.DebugInfo->Spare[0] = (DWORD_PTR)"DSDUPLEX_lock";
118
119         hres = IDirectSoundFullDuplexImpl_Initialize( (LPDIRECTSOUNDFULLDUPLEX)This,
120                                                       pcGuidCaptureDevice, pcGuidRenderDevice,
121                                                       pcDSCBufferDesc, pcDSBufferDesc,
122                                                       hWnd, dwLevel, ppDSCBuffer8, ppDSBuffer8);
123         if (hres != DS_OK)
124             WARN("IDirectSoundFullDuplexImpl_Initialize failed\n");
125         return hres;
126     }
127 }
128
129 static HRESULT WINAPI
130 IDirectSoundFullDuplexImpl_QueryInterface(
131     LPDIRECTSOUNDFULLDUPLEX iface,
132     REFIID riid,
133     LPVOID* ppobj )
134 {
135     IDirectSoundFullDuplexImpl *This = (IDirectSoundFullDuplexImpl *)iface;
136     TRACE( "(%p,%s,%p)\n", This, debugstr_guid(riid), ppobj );
137
138     if (ppobj == NULL) {
139         WARN("invalid parameter\n");
140         return E_INVALIDARG;
141     }
142
143     *ppobj = NULL;
144     return E_NOINTERFACE;
145 }
146
147 static ULONG WINAPI
148 IDirectSoundFullDuplexImpl_AddRef( LPDIRECTSOUNDFULLDUPLEX iface )
149 {
150     IDirectSoundFullDuplexImpl *This = (IDirectSoundFullDuplexImpl *)iface;
151     ULONG ref = InterlockedIncrement(&(This->ref));
152     TRACE("(%p) ref was %ld\n", This, ref - 1);
153     return ref;
154 }
155
156 static ULONG WINAPI
157 IDirectSoundFullDuplexImpl_Release( LPDIRECTSOUNDFULLDUPLEX iface )
158 {
159     IDirectSoundFullDuplexImpl *This = (IDirectSoundFullDuplexImpl *)iface;
160     ULONG ref = InterlockedDecrement(&(This->ref));
161     TRACE("(%p) ref was %ld\n", This, ref - 1);
162
163     if (!ref) {
164         This->lock.DebugInfo->Spare[0] = 0;
165         DeleteCriticalSection( &(This->lock) );
166         HeapFree( GetProcessHeap(), 0, This );
167         TRACE("(%p) released\n", This);
168     }
169     return ref;
170 }
171
172 static HRESULT WINAPI
173 IDirectSoundFullDuplexImpl_Initialize(
174     LPDIRECTSOUNDFULLDUPLEX iface,
175     LPCGUID pCaptureGuid,
176     LPCGUID pRendererGuid,
177     LPCDSCBUFFERDESC lpDscBufferDesc,
178     LPCDSBUFFERDESC lpDsBufferDesc,
179     HWND hWnd,
180     DWORD dwLevel,
181     LPLPDIRECTSOUNDCAPTUREBUFFER8 lplpDirectSoundCaptureBuffer8,
182     LPLPDIRECTSOUNDBUFFER8 lplpDirectSoundBuffer8 )
183 {
184     IDirectSoundFullDuplexImpl *This = (IDirectSoundFullDuplexImpl *)iface;
185     IDirectSoundCaptureBufferImpl** ippdscb=(IDirectSoundCaptureBufferImpl**)lplpDirectSoundCaptureBuffer8;
186     IDirectSoundBufferImpl** ippdsc=(IDirectSoundBufferImpl**)lplpDirectSoundBuffer8;
187
188     FIXME( "(%p,%s,%s,%p,%p,%p,%lx,%p,%p) stub!\n", This, debugstr_guid(pCaptureGuid),
189         debugstr_guid(pRendererGuid), lpDscBufferDesc, lpDsBufferDesc, hWnd, dwLevel,
190         ippdscb, ippdsc);
191
192     return E_FAIL;
193 }
194
195 static const IDirectSoundFullDuplexVtbl dsfdvt =
196 {
197     /* IUnknown methods */
198     IDirectSoundFullDuplexImpl_QueryInterface,
199     IDirectSoundFullDuplexImpl_AddRef,
200     IDirectSoundFullDuplexImpl_Release,
201
202     /* IDirectSoundFullDuplex methods */
203     IDirectSoundFullDuplexImpl_Initialize
204 };
205
206 /*******************************************************************************
207  * DirectSoundFullDuplex ClassFactory
208  */
209
210 static HRESULT WINAPI
211 DSFDCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj)
212 {
213     IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
214
215     FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj);
216     return E_NOINTERFACE;
217 }
218
219 static ULONG WINAPI
220 DSFDCF_AddRef(LPCLASSFACTORY iface)
221 {
222     IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
223     TRACE("(%p) ref was %ld\n", This, This->ref);
224     return InterlockedIncrement(&(This->ref));
225 }
226
227 static ULONG WINAPI
228 DSFDCF_Release(LPCLASSFACTORY iface)
229 {
230     IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
231     /* static class, won't be  freed */
232     TRACE("(%p) ref was %ld\n", This, This->ref);
233     return InterlockedDecrement(&(This->ref));
234 }
235
236 static HRESULT WINAPI
237 DSFDCF_CreateInstance(
238     LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj )
239 {
240     IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
241
242     TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
243
244     if (pOuter) {
245         WARN("aggregation not supported\n");
246         return CLASS_E_NOAGGREGATION;
247     }
248
249     if (ppobj == NULL) {
250         WARN("invalid parameter\n");
251         return E_INVALIDARG;
252     }
253
254     *ppobj = NULL;
255
256     if ( IsEqualGUID( &IID_IDirectSoundFullDuplex, riid ) ) {
257         /* FIXME: how do we do this one ? */
258         FIXME("not implemented\n");
259         return E_NOINTERFACE;
260     }
261
262     WARN("(%p,%p,%s,%p) Interface not found!\n",This,pOuter,debugstr_guid(riid),ppobj); 
263     return E_NOINTERFACE;
264 }
265
266 static HRESULT WINAPI
267 DSFDCF_LockServer(LPCLASSFACTORY iface,BOOL dolock)
268 {
269     IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
270     FIXME("(%p)->(%d),stub!\n",This,dolock);
271     return S_OK;
272 }
273
274 static const IClassFactoryVtbl DSFDCF_Vtbl =
275 {
276     DSFDCF_QueryInterface,
277     DSFDCF_AddRef,
278     DSFDCF_Release,
279     DSFDCF_CreateInstance,
280     DSFDCF_LockServer
281 };
282
283 IClassFactoryImpl DSOUND_FULLDUPLEX_CF = { &DSFDCF_Vtbl, 1 };