- Implement IDirectSoundCaptureBuffer8::Lock, IDirectSoundCaptureBuffer8::Unlock
[reactos.git] / reactos / dll / directx / dsound_new / primary.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Configuration of network devices
4 * FILE: dll/directx/dsound_new/primary.c
5 * PURPOSE: Primary IDirectSoundBuffer8 implementation
6 *
7 * PROGRAMMERS: Johannes Anderwald (janderwald@reactos.org)
8 */
9
10
11 #include "precomp.h"
12
13 typedef struct
14 {
15 const IDirectSoundBuffer8Vtbl *lpVtbl;
16 LONG ref;
17
18 LPFILTERINFO Filter;
19 DWORD dwLevel;
20 WAVEFORMATEX Format;
21 HANDLE hPin;
22 CRITICAL_SECTION Lock;
23 KSSTATE State;
24 }CDirectSoundBuffer, *LPCDirectSoundBuffer;
25
26 HRESULT
27 WINAPI
28 PrimaryDirectSoundBuffer8Impl_fnQueryInterface(
29 LPDIRECTSOUNDBUFFER8 iface,
30 IN REFIID riid,
31 LPVOID* ppobj)
32 {
33 LPOLESTR pStr;
34 LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl);
35
36 if (IsEqualIID(riid, &IID_IUnknown) ||
37 IsEqualIID(riid, &IID_IDirectSoundBuffer) ||
38 IsEqualIID(riid, &IID_IDirectSoundBuffer8))
39 {
40 *ppobj = (LPVOID)&This->lpVtbl;
41 InterlockedIncrement(&This->ref);
42 return S_OK;
43 }
44
45 if (SUCCEEDED(StringFromIID(riid, &pStr)))
46 {
47 DPRINT("No Interface for class %s\n", pStr);
48 CoTaskMemFree(pStr);
49 }
50 return E_NOINTERFACE;
51 }
52
53 ULONG
54 WINAPI
55 PrimaryDirectSoundBuffer8Impl_fnAddRef(
56 LPDIRECTSOUNDBUFFER8 iface)
57 {
58 ULONG ref;
59 LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl);
60
61 ref = InterlockedIncrement(&This->ref);
62
63 return ref;
64
65 }
66
67 ULONG
68 WINAPI
69 PrimaryDirectSoundBuffer8Impl_fnRelease(
70 LPDIRECTSOUNDBUFFER8 iface)
71 {
72 ULONG ref;
73 LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl);
74
75 ref = InterlockedDecrement(&(This->ref));
76
77 if (!ref)
78 {
79 if (This->hPin)
80 {
81 /* close pin handle */
82 CloseHandle(This->hPin);
83 }
84 /* free primary buffer */
85 HeapFree(GetProcessHeap(), 0, This);
86 }
87
88 return ref;
89 }
90
91 HRESULT
92 WINAPI
93 PrimaryDirectSoundBuffer8Impl_fnGetCaps(
94 LPDIRECTSOUNDBUFFER8 iface,
95 LPDSBCAPS pDSBufferCaps)
96 {
97 UNIMPLEMENTED
98 return DSERR_INVALIDPARAM;
99 }
100
101 HRESULT
102 WINAPI
103 PrimaryDirectSoundBuffer8Impl_fnGetCurrentPosition(
104 LPDIRECTSOUNDBUFFER8 iface,
105 LPDWORD pdwCurrentPlayCursor,
106 LPDWORD pdwCurrentWriteCursor)
107 {
108 UNIMPLEMENTED
109 return DSERR_INVALIDPARAM;
110 }
111
112 HRESULT
113 WINAPI
114 PrimaryDirectSoundBuffer8Impl_fnGetFormat(
115 LPDIRECTSOUNDBUFFER8 iface,
116 LPWAVEFORMATEX pwfxFormat,
117 DWORD dwSizeAllocated,
118 LPDWORD pdwSizeWritten)
119 {
120 DWORD FormatSize;
121 LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl);
122
123 FormatSize = sizeof(WAVEFORMATEX) + This->Format.cbSize;
124
125 if (!pwfxFormat && !pdwSizeWritten)
126 {
127 /* invalid parameter */
128 return DSERR_INVALIDPARAM;
129 }
130
131 if (!pwfxFormat)
132 {
133 /* return required format size */
134 *pdwSizeWritten = FormatSize;
135 return DS_OK;
136 }
137 else
138 {
139 if (dwSizeAllocated >= FormatSize)
140 {
141 /* copy format */
142 CopyMemory(pwfxFormat, &This->Format, FormatSize);
143
144 if (pdwSizeWritten)
145 *pdwSizeWritten = FormatSize;
146
147 return DS_OK;
148 }
149 /* buffer too small */
150 if (pdwSizeWritten)
151 *pdwSizeWritten = 0;
152
153 return DSERR_INVALIDPARAM;
154 }
155 }
156
157 HRESULT
158 WINAPI
159 PrimaryDirectSoundBuffer8Impl_fnGetVolume(
160 LPDIRECTSOUNDBUFFER8 iface,
161 LPLONG plVolume)
162 {
163 UNIMPLEMENTED
164 return DSERR_INVALIDPARAM;
165 }
166
167 HRESULT
168 WINAPI
169 PrimaryDirectSoundBuffer8Impl_fnGetPan(
170 LPDIRECTSOUNDBUFFER8 iface,
171 LPLONG plPan)
172 {
173 UNIMPLEMENTED
174 return DSERR_INVALIDPARAM;
175 }
176
177 HRESULT
178 WINAPI
179 PrimaryDirectSoundBuffer8Impl_fnGetFrequency(
180 LPDIRECTSOUNDBUFFER8 iface,
181 LPDWORD pdwFrequency)
182 {
183 UNIMPLEMENTED
184 return DSERR_INVALIDPARAM;
185 }
186
187 HRESULT
188 WINAPI
189 PrimaryDirectSoundBuffer8Impl_fnGetStatus(
190 LPDIRECTSOUNDBUFFER8 iface,
191 LPDWORD pdwStatus)
192 {
193 UNIMPLEMENTED
194 return DSERR_INVALIDPARAM;
195 }
196
197 HRESULT
198 WINAPI
199 PrimaryDirectSoundBuffer8Impl_fnInitialize(
200 LPDIRECTSOUNDBUFFER8 iface,
201 LPDIRECTSOUND pDirectSound,
202 LPCDSBUFFERDESC pcDSBufferDesc)
203 {
204 UNIMPLEMENTED
205 return DSERR_INVALIDPARAM;
206 }
207
208 HRESULT
209 WINAPI
210 PrimaryDirectSoundBuffer8Impl_fnLock(
211 LPDIRECTSOUNDBUFFER8 iface,
212 DWORD dwOffset,
213 DWORD dwBytes,
214 LPVOID *ppvAudioPtr1,
215 LPDWORD pdwAudioBytes1,
216 LPVOID *ppvAudioPtr2,
217 LPDWORD pdwAudioBytes2,
218 DWORD dwFlags)
219 {
220 UNIMPLEMENTED
221 return DSERR_INVALIDPARAM;
222 }
223
224 HRESULT
225 WINAPI
226 PrimaryDirectSoundBuffer8Impl_fnPlay(
227 LPDIRECTSOUNDBUFFER8 iface,
228 DWORD dwReserved1,
229 DWORD dwPriority,
230 DWORD dwFlags)
231 {
232 UNIMPLEMENTED
233 return DSERR_INVALIDPARAM;
234 }
235
236 HRESULT
237 WINAPI
238 PrimaryDirectSoundBuffer8Impl_fnSetCurrentPosition(
239 LPDIRECTSOUNDBUFFER8 iface,
240 DWORD dwNewPosition)
241 {
242 UNIMPLEMENTED
243 return DSERR_INVALIDPARAM;
244 }
245
246 HRESULT
247 WINAPI
248 PrimaryDirectSoundBuffer8Impl_fnSetFormat(
249 LPDIRECTSOUNDBUFFER8 iface,
250 LPCWAVEFORMATEX pcfxFormat)
251 {
252 LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl);
253
254 if (This->dwLevel == DSSCL_NORMAL)
255 {
256 /* can't change format with this level */
257 return DSERR_PRIOLEVELNEEDED;
258 }
259
260 ASSERT(pcfxFormat->cbSize == 0);
261
262
263 DPRINT("This %p Format: Tag %x nChannels %u nSamplesPerSec %u nAvgBytesPerSec %u nBlockAlign %u wBitsPerSample %u cbSize %u\n", This,
264 pcfxFormat->wFormatTag, pcfxFormat->nChannels, pcfxFormat->nSamplesPerSec, pcfxFormat->nAvgBytesPerSec, pcfxFormat->nBlockAlign, pcfxFormat->wBitsPerSample, pcfxFormat->cbSize);
265
266 CopyMemory(&This->Format, pcfxFormat, sizeof(WAVEFORMATEX));
267
268 return DS_OK;
269 }
270
271 HRESULT
272 WINAPI
273 PrimaryDirectSoundBuffer8Impl_fnSetVolume(
274 LPDIRECTSOUNDBUFFER8 iface,
275 LONG lVolume)
276 {
277 UNIMPLEMENTED
278 return DSERR_INVALIDPARAM;
279 }
280
281 HRESULT
282 WINAPI
283 PrimaryDirectSoundBuffer8Impl_fnSetPan(
284 LPDIRECTSOUNDBUFFER8 iface,
285 LONG lPan)
286 {
287 UNIMPLEMENTED
288 return DSERR_INVALIDPARAM;
289 }
290
291 HRESULT
292 WINAPI
293 PrimaryDirectSoundBuffer8Impl_fnSetFrequency(
294 LPDIRECTSOUNDBUFFER8 iface,
295 DWORD dwFrequency)
296 {
297 UNIMPLEMENTED
298 return DSERR_INVALIDPARAM;
299 }
300
301 HRESULT
302 WINAPI
303 PrimaryDirectSoundBuffer8Impl_fnStop(
304 LPDIRECTSOUNDBUFFER8 iface)
305 {
306 UNIMPLEMENTED
307 return DSERR_INVALIDPARAM;
308 }
309
310
311 HRESULT
312 WINAPI
313 PrimaryDirectSoundBuffer8Impl_fnUnlock(
314 LPDIRECTSOUNDBUFFER8 iface,
315 LPVOID pvAudioPtr1,
316 DWORD dwAudioBytes1,
317 LPVOID pvAudioPtr2,
318 DWORD dwAudioBytes2)
319 {
320 UNIMPLEMENTED
321 return DSERR_INVALIDPARAM;
322 }
323
324
325
326
327 HRESULT
328 WINAPI
329 PrimaryDirectSoundBuffer8Impl_fnRestore(
330 LPDIRECTSOUNDBUFFER8 iface)
331 {
332 UNIMPLEMENTED
333 return DSERR_INVALIDPARAM;
334 }
335
336
337 HRESULT
338 WINAPI
339 PrimaryDirectSoundBuffer8Impl_fnSetFX(
340 LPDIRECTSOUNDBUFFER8 iface,
341 DWORD dwEffectsCount,
342 LPDSEFFECTDESC pDSFXDesc,
343 LPDWORD pdwResultCodes)
344 {
345 UNIMPLEMENTED
346 return DSERR_INVALIDPARAM;
347 }
348
349 HRESULT
350 WINAPI
351 PrimaryDirectSoundBuffer8Impl_fnAcquireResources(
352 LPDIRECTSOUNDBUFFER8 iface,
353 DWORD dwFlags,
354 DWORD dwEffectsCount,
355 LPDWORD pdwResultCodes)
356 {
357 UNIMPLEMENTED
358 return DSERR_INVALIDPARAM;
359 }
360
361 HRESULT
362 WINAPI
363 PrimaryDirectSoundBuffer8Impl_fnGetObjectInPath(
364 LPDIRECTSOUNDBUFFER8 iface,
365 REFGUID rguidObject,
366 DWORD dwIndex,
367 REFGUID rguidInterface,
368 LPVOID *ppObject)
369 {
370 UNIMPLEMENTED
371 return DSERR_INVALIDPARAM;
372 }
373
374 static IDirectSoundBuffer8Vtbl vt_DirectSoundBuffer8 =
375 {
376 /* IUnknown methods */
377 PrimaryDirectSoundBuffer8Impl_fnQueryInterface,
378 PrimaryDirectSoundBuffer8Impl_fnAddRef,
379 PrimaryDirectSoundBuffer8Impl_fnRelease,
380 /* IDirectSoundBuffer methods */
381 PrimaryDirectSoundBuffer8Impl_fnGetCaps,
382 PrimaryDirectSoundBuffer8Impl_fnGetCurrentPosition,
383 PrimaryDirectSoundBuffer8Impl_fnGetFormat,
384 PrimaryDirectSoundBuffer8Impl_fnGetVolume,
385 PrimaryDirectSoundBuffer8Impl_fnGetPan,
386 PrimaryDirectSoundBuffer8Impl_fnGetFrequency,
387 PrimaryDirectSoundBuffer8Impl_fnGetStatus,
388 PrimaryDirectSoundBuffer8Impl_fnInitialize,
389 PrimaryDirectSoundBuffer8Impl_fnLock,
390 PrimaryDirectSoundBuffer8Impl_fnPlay,
391 PrimaryDirectSoundBuffer8Impl_fnSetCurrentPosition,
392 PrimaryDirectSoundBuffer8Impl_fnSetFormat,
393 PrimaryDirectSoundBuffer8Impl_fnSetVolume,
394 PrimaryDirectSoundBuffer8Impl_fnSetPan,
395 PrimaryDirectSoundBuffer8Impl_fnSetFrequency,
396 PrimaryDirectSoundBuffer8Impl_fnStop,
397 PrimaryDirectSoundBuffer8Impl_fnUnlock,
398 PrimaryDirectSoundBuffer8Impl_fnRestore,
399 /* IDirectSoundBuffer8 methods */
400 PrimaryDirectSoundBuffer8Impl_fnSetFX,
401 PrimaryDirectSoundBuffer8Impl_fnAcquireResources,
402 PrimaryDirectSoundBuffer8Impl_fnGetObjectInPath
403 };
404
405 DWORD
406 PrimaryDirectSoundBuffer_Write(
407 LPDIRECTSOUNDBUFFER8 iface,
408 LPVOID Buffer,
409 DWORD BufferSize)
410 {
411 KSSTREAM_HEADER Header;
412 DWORD Result, BytesTransferred;
413 OVERLAPPED Overlapped;
414
415 LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl);
416
417 ZeroMemory(&Overlapped, sizeof(OVERLAPPED));
418 Overlapped.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
419
420
421 ASSERT(This->hPin);
422 ZeroMemory(&Header, sizeof(KSSTREAM_HEADER));
423
424 Header.FrameExtent = BufferSize;
425 Header.DataUsed = BufferSize;
426 Header.Data = Buffer;
427 Header.Size = sizeof(KSSTREAM_HEADER);
428 Header.PresentationTime.Numerator = 1;
429 Header.PresentationTime.Denominator = 1;
430
431 Result = DeviceIoControl(This->hPin, IOCTL_KS_WRITE_STREAM, NULL, 0, &Header, sizeof(KSSTREAM_HEADER), &BytesTransferred, &Overlapped);
432
433 if (Result != ERROR_SUCCESS)
434 return 0;
435
436 return BytesTransferred;
437 }
438
439 VOID
440 PrimaryDirectSoundBuffer_SetState(
441 LPDIRECTSOUNDBUFFER8 iface,
442 KSSTATE State)
443 {
444 KSPROPERTY Property;
445 DWORD Result, BytesTransferred;
446 LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl);
447
448 if (This->State == State)
449 return;
450
451 Property.Set = KSPROPSETID_Connection;
452 Property.Id = KSPROPERTY_CONNECTION_STATE;
453 Property.Flags = KSPROPERTY_TYPE_SET;
454
455 Result = SyncOverlappedDeviceIoControl(This->hPin, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSPROPERTY), (PVOID)&State, sizeof(KSSTATE), &BytesTransferred);
456 if (Result == ERROR_SUCCESS)
457 {
458 This->State = State;
459 }
460 }
461
462 HRESULT
463 PrimaryDirectSoundBuffer_GetPosition(
464 LPDIRECTSOUNDBUFFER8 iface,
465 LPDWORD pdwCurrentPlayCursor,
466 LPDWORD pdwCurrentWriteCursor)
467 {
468 KSAUDIO_POSITION Position;
469 KSPROPERTY Request;
470 DWORD Result;
471
472 LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl);
473
474 if (!This->hPin)
475 {
476 if (pdwCurrentPlayCursor)
477 *pdwCurrentPlayCursor = 0;
478
479 if (pdwCurrentWriteCursor)
480 *pdwCurrentWriteCursor = 0;
481
482 DPRINT("No Audio Pin\n");
483 return DS_OK;
484 }
485
486 /* setup audio position property request */
487 Request.Id = KSPROPERTY_AUDIO_POSITION;
488 Request.Set = KSPROPSETID_Audio;
489 Request.Flags = KSPROPERTY_TYPE_GET;
490
491
492 Result = SyncOverlappedDeviceIoControl(This->hPin, IOCTL_KS_PROPERTY, (PVOID)&Request, sizeof(KSPROPERTY), (PVOID)&Position, sizeof(KSAUDIO_POSITION), NULL);
493
494 if (Result != ERROR_SUCCESS)
495 {
496 DPRINT("GetPosition failed with %x\n", Result);
497 return DSERR_UNSUPPORTED;
498 }
499
500 //DPRINT("Play %I64u Write %I64u \n", Position.PlayOffset, Position.WriteOffset);
501
502 if (pdwCurrentPlayCursor)
503 *pdwCurrentPlayCursor = (DWORD)Position.PlayOffset;
504
505 if (pdwCurrentWriteCursor)
506 *pdwCurrentWriteCursor = (DWORD)Position.WriteOffset;
507
508 return DS_OK;
509 }
510
511 HRESULT
512 PrimaryDirectSoundBuffer_SetFormat(
513 LPDIRECTSOUNDBUFFER8 iface,
514 LPWAVEFORMATEX pcfxFormat,
515 BOOL bLooped)
516 {
517 ULONG PinId, DeviceId = 0, Result;
518 LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl);
519
520 if (This->hPin)
521 {
522 /* fixme change format */
523 ASSERT(0);
524 }
525
526 do
527 {
528 /* try all available recording pins on that filter */
529 PinId = GetPinIdFromFilter(This->Filter, FALSE, DeviceId);
530 DPRINT("PinId %u DeviceId %u\n", PinId, DeviceId);
531
532 if (PinId == ULONG_MAX)
533 break;
534
535 Result = OpenPin(This->Filter->hFilter, PinId, (LPWAVEFORMATEX)pcfxFormat, &This->hPin, bLooped);
536 DPRINT("PinId %u Result %u\n", PinId, Result);
537 if (Result == ERROR_SUCCESS)
538 break;
539
540 This->hPin = NULL;
541 DeviceId++;
542 }while(TRUE);
543
544 if (!This->hPin)
545 {
546 DPRINT("PrimaryDirectSoundBuffer8Impl_fnSetFormat failed\n");
547 return DSERR_INVALIDPARAM;
548 }
549
550 DPRINT("PrimaryDirectSoundBuffer8Impl_fnSetFormat success\n");
551 return DS_OK;
552 }
553
554 VOID
555 PrimaryDirectSoundBuffer_AcquireLock(
556 LPDIRECTSOUNDBUFFER8 iface)
557 {
558 LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl);
559
560 EnterCriticalSection(&This->Lock);
561
562
563 }
564
565 VOID
566 PrimaryDirectSoundBuffer_ReleaseLock(
567 LPDIRECTSOUNDBUFFER8 iface)
568 {
569 LPCDirectSoundBuffer This = (LPCDirectSoundBuffer)CONTAINING_RECORD(iface, CDirectSoundBuffer, lpVtbl);
570
571 LeaveCriticalSection(&This->Lock);
572
573 }
574
575
576 HRESULT
577 NewPrimarySoundBuffer(
578 LPDIRECTSOUNDBUFFER8 *OutBuffer,
579 LPFILTERINFO Filter,
580 DWORD dwLevel)
581 {
582 LPCDirectSoundBuffer This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CDirectSoundBuffer));
583
584 if (!This)
585 {
586 /* not enough memory */
587 return DSERR_OUTOFMEMORY;
588 }
589
590 This->ref = 1;
591 This->lpVtbl = &vt_DirectSoundBuffer8;
592 This->Filter = Filter;
593 This->dwLevel = dwLevel;
594 This->hPin = NULL;
595
596 InitializeCriticalSection(&This->Lock);
597
598 *OutBuffer = (LPDIRECTSOUNDBUFFER8)&This->lpVtbl;
599 return DS_OK;
600 }
601