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