xref: /reactos/dll/directx/dsound_new/capture.c (revision 3e1f4074)
1 /*
2  * COPYRIGHT:       See COPYING in the top level directory
3  * PROJECT:         ReactOS Configuration of network devices
4  * FILE:            dll/directx/dsound_new/capture.c
5  * PURPOSE:         Implement IDirectSoundCapture
6  *
7  * PROGRAMMERS:     Johannes Anderwald (johannes.anderwald@reactos.org)
8  */
9 
10 #include "precomp.h"
11 
12 typedef struct
13 {
14     IDirectSoundCaptureVtbl *lpVtbl;
15     LONG ref;
16     GUID DeviceGUID;
17     BOOL bInitialized;
18     LPFILTERINFO Filter;
19 }CDirectSoundCaptureImpl, *LPCDirectSoundCaptureImpl;
20 
21 HRESULT
22 WINAPI
23 CDirectSoundCapture_fnQueryInterface(
24     LPDIRECTSOUNDCAPTURE8 iface,
25     REFIID riid,
26     LPVOID * ppobj)
27 {
28     LPOLESTR pStr;
29     LPCDirectSoundCaptureImpl This = (LPCDirectSoundCaptureImpl)CONTAINING_RECORD(iface, CDirectSoundCaptureImpl, lpVtbl);
30 
31     /* check if the interface is supported */
32     if (IsEqualIID(riid, &IID_IUnknown) ||
33         IsEqualIID(riid, &IID_IDirectSoundCapture))
34     {
35         *ppobj = (LPVOID)&This->lpVtbl;
36         InterlockedIncrement(&This->ref);
37         return S_OK;
38     }
39 
40     /* unsupported interface */
41     if (SUCCEEDED(StringFromIID(riid, &pStr)))
42     {
43         DPRINT("No Interface for class %s\n", pStr);
44         CoTaskMemFree(pStr);
45     }
46     return E_NOINTERFACE;
47 }
48 
49 ULONG
50 WINAPI
51 CDirectSoundCapture_fnAddRef(
52     LPDIRECTSOUNDCAPTURE8 iface)
53 {
54     ULONG ref;
55     LPCDirectSoundCaptureImpl This = (LPCDirectSoundCaptureImpl)CONTAINING_RECORD(iface, CDirectSoundCaptureImpl, lpVtbl);
56 
57     /* increment reference count */
58     ref = InterlockedIncrement(&This->ref);
59 
60     return ref;
61 }
62 
63 ULONG
64 WINAPI
65 CDirectSoundCapture_fnRelease(
66     LPDIRECTSOUNDCAPTURE8 iface)
67 {
68     ULONG ref;
69     LPCDirectSoundCaptureImpl This = (LPCDirectSoundCaptureImpl)CONTAINING_RECORD(iface, CDirectSoundCaptureImpl, lpVtbl);
70 
71     /* release reference count */
72     ref = InterlockedDecrement(&(This->ref));
73 
74     if (!ref)
75     {
76         HeapFree(GetProcessHeap(), 0, This);
77     }
78 
79     return ref;
80 }
81 
82 
83 HRESULT
84 WINAPI
85 CDirectSoundCapture_fnCreateCaptureBuffer(
86     LPDIRECTSOUNDCAPTURE8 iface,
87     LPCDSCBUFFERDESC lpcDSBufferDesc,
88     LPDIRECTSOUNDCAPTUREBUFFER *ppDSCBuffer,
89     LPUNKNOWN pUnkOuter)
90 {
91     HRESULT hResult;
92     LPCDirectSoundCaptureImpl This = (LPCDirectSoundCaptureImpl)CONTAINING_RECORD(iface, CDirectSoundCaptureImpl, lpVtbl);
93 
94     if (!This->bInitialized)
95     {
96         /* object not yet initialized */
97         return DSERR_UNINITIALIZED;
98     }
99 
100     if (!lpcDSBufferDesc  || !ppDSCBuffer || pUnkOuter != NULL)
101     {
102         /* invalid param */
103         return DSERR_INVALIDPARAM;
104     }
105 
106     /* check buffer description */
107     if ((lpcDSBufferDesc->dwSize != sizeof(DSCBUFFERDESC) && lpcDSBufferDesc->dwSize != sizeof(DSCBUFFERDESC1)) ||
108         lpcDSBufferDesc->dwReserved != 0 || lpcDSBufferDesc->dwBufferBytes == 0 || lpcDSBufferDesc->lpwfxFormat == NULL)
109     {
110         /* invalid buffer description */
111         return DSERR_INVALIDPARAM;
112     }
113 
114     DPRINT("This %p wFormatTag %x nChannels %u nSamplesPerSec %u nAvgBytesPerSec %u NBlockAlign %u wBitsPerSample %u cbSize %u\n",
115            This, lpcDSBufferDesc->lpwfxFormat->wFormatTag, lpcDSBufferDesc->lpwfxFormat->nChannels, lpcDSBufferDesc->lpwfxFormat->nSamplesPerSec, lpcDSBufferDesc->lpwfxFormat->nAvgBytesPerSec, lpcDSBufferDesc->lpwfxFormat->nBlockAlign, lpcDSBufferDesc->lpwfxFormat->wBitsPerSample, lpcDSBufferDesc->lpwfxFormat->cbSize);
116 
117     hResult = NewDirectSoundCaptureBuffer((LPDIRECTSOUNDCAPTUREBUFFER8*)ppDSCBuffer, This->Filter, lpcDSBufferDesc);
118     return hResult;
119 }
120 
121 
122 HRESULT
123 WINAPI
124 CDirectSoundCapture_fnGetCaps(
125     LPDIRECTSOUNDCAPTURE8 iface,
126     LPDSCCAPS pDSCCaps)
127 {
128     WAVEINCAPSW Caps;
129     MMRESULT Result;
130     LPCDirectSoundCaptureImpl This = (LPCDirectSoundCaptureImpl)CONTAINING_RECORD(iface, CDirectSoundCaptureImpl, lpVtbl);
131 
132     if (!This->bInitialized)
133     {
134         /* object not yet initialized */
135         return DSERR_UNINITIALIZED;
136     }
137 
138     if (!pDSCCaps)
139     {
140         /* invalid param */
141         return DSERR_INVALIDPARAM;
142     }
143 
144     if (pDSCCaps->dwSize != sizeof(DSCCAPS))
145     {
146         /* invalid param */
147         return DSERR_INVALIDPARAM;
148     }
149 
150 
151     /* We are certified ;) */
152     pDSCCaps->dwFlags = DSCCAPS_CERTIFIED;
153 
154     ASSERT(This->Filter);
155 
156     Result = waveInGetDevCapsW(This->Filter->MappedId[0], &Caps, sizeof(WAVEINCAPSW));
157     if (Result != MMSYSERR_NOERROR)
158     {
159         /* failed */
160         DPRINT("waveInGetDevCapsW for device %u failed with %x\n", This->Filter->MappedId[0], Result);
161         return DSERR_UNSUPPORTED;
162     }
163 
164     pDSCCaps->dwFormats = Caps.dwFormats;
165     pDSCCaps->dwChannels = Caps.wChannels;
166 
167     return DS_OK;
168 }
169 
170 
171 HRESULT
172 WINAPI
173 CDirectSoundCapture_fnInitialize(
174     LPDIRECTSOUNDCAPTURE8 iface,
175     LPCGUID pcGuidDevice)
176 {
177     GUID DeviceGuid;
178     LPOLESTR pGuidStr;
179     LPCDirectSoundCaptureImpl This = (LPCDirectSoundCaptureImpl)CONTAINING_RECORD(iface, CDirectSoundCaptureImpl, lpVtbl);
180 
181     /* sanity check */
182     ASSERT(RootInfo);
183 
184     if (This->bInitialized)
185     {
186         /* object has already been initialized */
187         return DSERR_ALREADYINITIALIZED;
188     }
189 
190     /* fixme mutual exclusion */
191 
192     if (pcGuidDevice == NULL || IsEqualGUID(pcGuidDevice, &GUID_NULL))
193     {
194         /* use default playback device id */
195         pcGuidDevice = &DSDEVID_DefaultCapture;
196     }
197 
198     if (IsEqualIID(pcGuidDevice, &DSDEVID_DefaultVoicePlayback) || IsEqualIID(pcGuidDevice, &DSDEVID_DefaultPlayback))
199     {
200         /* this has to be a winetest */
201         return DSERR_NODRIVER;
202     }
203 
204     /* now verify the guid */
205     if (GetDeviceID(pcGuidDevice, &DeviceGuid) != DS_OK)
206     {
207         if (SUCCEEDED(StringFromIID(pcGuidDevice, &pGuidStr)))
208         {
209             DPRINT("IDirectSound8_fnInitialize: Unknown GUID %ws\n", pGuidStr);
210             CoTaskMemFree(pGuidStr);
211         }
212         return DSERR_INVALIDPARAM;
213     }
214 
215     if (FindDeviceByGuid(&DeviceGuid, &This->Filter))
216     {
217         This->bInitialized = TRUE;
218         return DS_OK;
219     }
220 
221     DPRINT("Failed to find device\n");
222     return DSERR_INVALIDPARAM;
223 }
224 
225 static IDirectSoundCaptureVtbl vt_DirectSoundCapture =
226 {
227     /* IUnknown methods */
228     CDirectSoundCapture_fnQueryInterface,
229     CDirectSoundCapture_fnAddRef,
230     CDirectSoundCapture_fnRelease,
231     CDirectSoundCapture_fnCreateCaptureBuffer,
232     CDirectSoundCapture_fnGetCaps,
233     CDirectSoundCapture_fnInitialize
234 };
235 
236 HRESULT
237 InternalDirectSoundCaptureCreate(
238     LPCGUID lpcGUID,
239     LPDIRECTSOUNDCAPTURE8 *ppDS,
240     IUnknown *pUnkOuter)
241 {
242     LPCDirectSoundCaptureImpl This;
243     HRESULT hr;
244 
245     if (!ppDS || pUnkOuter != NULL)
246     {
247         /* invalid parameter passed */
248         return DSERR_INVALIDPARAM;
249     }
250 
251     /* allocate CDirectSoundCaptureImpl struct */
252     This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CDirectSoundCaptureImpl));
253     if (!This)
254     {
255         /* not enough memory */
256         return DSERR_OUTOFMEMORY;
257     }
258 
259     /* initialize IDirectSoundCapture object */
260     This->ref = 1;
261     This->lpVtbl = &vt_DirectSoundCapture;
262 
263 
264     /* initialize direct sound interface */
265     hr = IDirectSoundCapture_Initialize((LPDIRECTSOUNDCAPTURE8)&This->lpVtbl, lpcGUID);
266 
267     /* check for success */
268     if (!SUCCEEDED(hr))
269     {
270         /* failed */
271         DPRINT("Failed to initialize DirectSoundCapture object with %x\n", hr);
272         IDirectSoundCapture_Release((LPDIRECTSOUND8)&This->lpVtbl);
273         return hr;
274     }
275 
276     /* store result */
277     *ppDS = (LPDIRECTSOUNDCAPTURE8)&This->lpVtbl;
278     DPRINT("DirectSoundCapture object %p\n", *ppDS);
279     return DS_OK;
280 }
281 
282 HRESULT
283 CALLBACK
284 NewDirectSoundCapture(
285     IUnknown* pUnkOuter,
286     REFIID riid,
287     LPVOID* ppvObject)
288 {
289     LPOLESTR pStr;
290     LPCDirectSoundCaptureImpl This;
291 
292     /* check requested interface */
293     if (!IsEqualIID(riid, &IID_IUnknown) && !IsEqualIID(riid, &IID_IDirectSoundCapture) && !IsEqualIID(riid, &IID_IDirectSoundCapture8))
294     {
295         *ppvObject = 0;
296         StringFromIID(riid, &pStr);
297         DPRINT("NewDirectSoundCapture does not support Interface %ws\n", pStr);
298         CoTaskMemFree(pStr);
299         return E_NOINTERFACE;
300     }
301 
302     /* allocate CDirectSoundCaptureImpl struct */
303     This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CDirectSoundCaptureImpl));
304     if (!This)
305     {
306         /* not enough memory */
307         return DSERR_OUTOFMEMORY;
308     }
309 
310     /* initialize object */
311     This->ref = 1;
312     This->lpVtbl = &vt_DirectSoundCapture;
313     This->bInitialized = FALSE;
314     *ppvObject = (LPVOID)&This->lpVtbl;
315 
316     return S_OK;
317 }
318 
319 
320 HRESULT
321 WINAPI
322 DirectSoundCaptureCreate(
323     LPCGUID lpcGUID,
324     LPDIRECTSOUNDCAPTURE *ppDSC,
325     LPUNKNOWN pUnkOuter)
326 {
327     return InternalDirectSoundCaptureCreate(lpcGUID, (LPDIRECTSOUNDCAPTURE8*)ppDSC, pUnkOuter);
328 }
329 
330 HRESULT
331 WINAPI
332 DirectSoundCaptureCreate8(
333     LPCGUID lpcGUID,
334     LPDIRECTSOUNDCAPTURE8 *ppDSC8,
335     LPUNKNOWN pUnkOuter)
336 {
337     return InternalDirectSoundCaptureCreate(lpcGUID, ppDSC8, pUnkOuter);
338 }
339