source: trunk/src/dsound/OS2PrimBuff.cpp

Last change on this file was 21479, checked in by dmik, 15 years ago

Get rid of dd_obj_base.h which duplicates obj_base.h creating unnecessary mess (symbol/define duplication) and conflicts when both the DDarw and other COM-related headers are included.

File size: 16.7 KB
RevLine 
[5285]1/* $Id: OS2PrimBuff.cpp,v 1.5 2001-03-06 20:11:16 mike Exp $ */
[3099]2/*
3 * DirectSound Primary Buffer
4 *
5 * Copyright 1999-2000 Kevin Langman
6 *
7 * Project Odin Software License can be found in LICENSE.TXT
8 *
9 *
10 */
11
12
13/* NOTES:
14
[3555]15 Here is how the buffers, GetPosition and Locking works:
16 Dart is allocated many little buffers. These buffers are filled
17 when dart has finished playing one of the buffer, from a 32kb buffer
[3099]18 that the Win32 program can write to. The GetPosition function will
19 determine what buffer is being played, and return the offset to the
[3925]20 end of this buffer.
[3099]21
[3555]22 The Lock function will call the GetCurrentPosition function to determine
23 where the end of the currently playing buffer is and allow the Win32
[3925]24 program to lock between that location and 15ms from there
[3555]25 (15ms should be past the next buffer).
26
[3099]27*/
28
29#define INCL_DOSMISC
30#include <os2win.h>
31#include <stdio.h>
32#include <stdlib.h>
33#include <string.h>
34
[21479]35#define CINTERFACE
[3099]36#include <dsound.h>
37
[3555]38//#include "DSound.h"
[3099]39#include "OS2DSound.h"
40#include "OS2SndBuffer.h"
41#include "OS2PrimBuff.h"
42#include "OS23DListener.h"
43
44#include "dart.h"
45
46#undef THIS
47#define THIS VOID*This
48
49#undef THIS_
50#define THIS_ VOID*This,
51
52//******************************************************************************
53//******************************************************************************
54OS2PrimBuff::OS2PrimBuff(OS2IDirectSound *DSound, const DSBUFFERDESC *lpDSBufferDesc )
55{
56 lpVtbl = &Vtbl;
[21479]57 Vtbl.fnAddRef = PrimBufAddRef;
58 Vtbl.fnRelease = PrimBufRelease;
59 Vtbl.fnQueryInterface = PrimBufQueryInterface;
60 Vtbl.fnGetCaps = PrimBufGetCaps;
61 Vtbl.fnGetFormat = PrimBufGetFormat;
62 Vtbl.fnGetVolume = PrimBufGetVolume;
63 Vtbl.fnGetStatus = PrimBufGetStatus;
64 Vtbl.fnGetCurrentPosition = PrimBufGetCurrentPosition;
65 Vtbl.fnGetPan = PrimBufGetPan;
66 Vtbl.fnGetFrequency = PrimBufGetFrequency;
67 Vtbl.fnInitialize = PrimBufInitialize;
68 Vtbl.fnRestore = PrimBufRestore;
69 Vtbl.fnSetFormat = PrimBufSetFormat;
70 Vtbl.fnSetVolume = PrimBufSetVolume;
71 Vtbl.fnSetCurrentPosition = PrimBufSetCurrentPosition;
72 Vtbl.fnSetPan = PrimBufSetPan;
73 Vtbl.fnSetFrequency = PrimBufSetFrequency;
74 Vtbl.fnLock = PrimBufLock;
75 Vtbl.fnUnlock = PrimBufUnlock;
76 Vtbl.fnStop = PrimBufStop;
77 Vtbl.fnPlay = PrimBufPlay;
[3099]78
79 dprintf(("DSOUND-PrimBuff: Constructor"));
80
81 parentDS = DSound;
82 fPlaying = FALSE;
83 playpos = 0;
84 fPrimary = TRUE;
85 Referenced = 0;
86 listener = NULL;
87
88 lpfxFormat = (WAVEFORMATEX *)malloc(/*bufferdesc.lpwfxFormat->cbSize +*/ sizeof(WAVEFORMATEX));
89 lpfxFormat->wBitsPerSample = bps = 16;
90 lpfxFormat->nChannels = channels = 2;
91 lpfxFormat->nSamplesPerSec = rate = 22500;
92
93 bufferdesc.dwBufferBytes = BUFFER_SIZE;
94
95 lastError = Dart_Open_Device(&usDeviceID, &vpMixBuffer, &vpMixSetup,
96 &vpBuffParms, (PVOID*)&lpBuffer );
97
98 if (lastError == DS_OK)
99 primary = this;
100}
101
102//******************************************************************************
103//******************************************************************************
104OS2PrimBuff::~OS2PrimBuff()
105{
106 dprintf(("DSOUND-PrimBuff: Destructor"));
107
108 if (fPlaying)
109 Dart_Stop(usDeviceID);
110
111 lastError = Dart_Close_Device(usDeviceID, vpMixBuffer, vpMixSetup,
112 vpBuffParms );
113
114 dprintf(("DSOUND-PrimBuff: Freeing Memory"));
115 free(lpfxFormat);
116 //free( *vpMixBuffer );
117 //free( *vpMixSetup );
118 //free( *vpBuffParms );
119 //free( vpGenericParms );
120
121 dprintf(("DSOUND-PrimBuff: Destructor Complete"));
122
123 primary = NULL;
124}
125
126//******************************************************************************
127//******************************************************************************
128HRESULT WIN32API PrimBufQueryInterface(THIS, REFIID riid, LPVOID * ppvObj)
129{
130 dprintf(("DSOUND-PrimBuff: QueryInterface"));
131
132 if (This == NULL) {
133 return DSERR_INVALIDPARAM;
134 }
135 *ppvObj = NULL;
136
[21479]137 if (IsEqualGUID(riid, &IID_IDirectSoundBuffer)) {
[3099]138 *ppvObj = This;
139 PrimBufAddRef(This);
140 return DS_OK;
141 }
142
143
[21479]144 if (IsEqualGUID(riid, &IID_IDirectSound3DListener)) {
[3099]145 OS2PrimBuff *me = (OS2PrimBuff *)This;
146 OS2IDirectSound3DListener *listener;
147
148 listener = new OS2IDirectSound3DListener(me);
149 *ppvObj = listener;
[21479]150 listener->Vtbl.fnAddRef((IDirectSound3DListener *)listener);
[3099]151 return DS_OK;
152 }
153
[3555]154 // I guess a Notify object should be creaed for the Primary Buffer also..
155 // Does windows DSound have a notify object for Primary buffer???
156
[3099]157 return E_NOINTERFACE;
158}
159
160//******************************************************************************
161//******************************************************************************
162ULONG WIN32API PrimBufAddRef(THIS)
163{
164 OS2PrimBuff *me = (OS2PrimBuff *)This;
165
166 dprintf(("DSOUND-PrimBuff: AddRef %d", me->Referenced+1));
167
168 if (me == NULL) {
169 return DS_OK;
170 }
171 return ++me->Referenced;
172}
173
174//******************************************************************************
175//******************************************************************************
176ULONG WIN32API PrimBufRelease(THIS)
177{
178 OS2PrimBuff *me = (OS2PrimBuff *)This;
179
180 dprintf(("DSOUND-PrimBuff: Release %d", me->Referenced-1));
181
182 if (me == NULL) {
183 return DS_OK;
184 }
185 if (me->Referenced) {
186 me->Referenced--;
187 if (me->Referenced == 0) {
188 delete me;
189 return DS_OK;
190 }
191 else
192 return me->Referenced;
193 }
194 else
195 return DS_OK;
196}
197
198//******************************************************************************
199//******************************************************************************
200HRESULT __stdcall PrimBufGetCaps(THIS_ LPDSBCAPS lpDSCaps )
201{
202 OS2PrimBuff *me = (OS2PrimBuff *)This;
203
204 dprintf(("DSOUND-PrimBuff: GetCaps"));
205 if(me == NULL || lpDSCaps == NULL)
206 {
207 return DSERR_INVALIDPARAM;
208 }
209
210 lpDSCaps->dwFlags = DSBCAPS_PRIMARYBUFFER;
211 lpDSCaps->dwBufferBytes = BUFFER_SIZE;
212 lpDSCaps->dwUnlockTransferRate = 0;
213 lpDSCaps->dwPlayCpuOverhead = 0;
214
215 return DS_OK;
216}
217
218//******************************************************************************
219//******************************************************************************
220HRESULT __stdcall PrimBufGetCurrentPosition(THIS_ LPDWORD lpdwCurrentPlayCursor,LPDWORD lpdwCurrentWriteCursor )
221{
222 OS2PrimBuff *me = (OS2PrimBuff *)This;
223 LONG lDartPos;
224
225 dprintf(("DSOUND-PrimBuff: GetCurrentPosition"));
226
227 if (me == NULL || lpdwCurrentPlayCursor == NULL || lpdwCurrentWriteCursor == NULL) {
228 return DSERR_INVALIDPARAM;
229 }
230
231 if (me->fPlaying == FALSE) {
232 *lpdwCurrentPlayCursor = 0;
233 *lpdwCurrentWriteCursor = 0;
234 return DS_OK;
235 }
236
237
238 Dart_GetPosition( me->usDeviceID, &lDartPos ); // Returns the Playing Buffer * 'Bytes Per Dart Bufer'
239
240 *lpdwCurrentPlayCursor = lDartPos;
241
242 // Calculate the Write Cursor as 15ms from the current play cursor.
243 // NOTE: This may need to be changed to insure that the write cursor is always beyond the
244 // point where the next buffer will read from.
245 *lpdwCurrentWriteCursor = (lDartPos + (me->rate * me->channels * (me->bps/8) * 15 / 1000) ) % BUFFER_SIZE;
246
247 return DS_OK;
248}
249
250
251//******************************************************************************
252//******************************************************************************
253HRESULT __stdcall PrimBufGetFormat(THIS_ LPWAVEFORMATEX lpfxFormat, DWORD dwSizeAllocated , LPDWORD lpdwSizeWritten )
254{
255 OS2PrimBuff *me = (OS2PrimBuff *)This;
256 long copysize;
257
258 dprintf(("DSOUND-PrimBuff: GetFormat"));
259
260 if( me == NULL || lpfxFormat == NULL || dwSizeAllocated == 0)
261 {
262 return DSERR_INVALIDPARAM;
263 }
264
[5285]265 copysize = MIN(dwSizeAllocated, (me->lpfxFormat->cbSize + sizeof(WAVEFORMATEX)));
[3099]266 memcpy(lpfxFormat, me->lpfxFormat, copysize);
267
268 if(lpdwSizeWritten)
269 {
270 *lpdwSizeWritten = copysize;
271 }
272 return DS_OK;
273}
274
275//******************************************************************************
276//******************************************************************************
277HRESULT __stdcall PrimBufGetVolume(THIS_ LPLONG )
278{
279 dprintf(("DSOUND-PrimBuff: GetVolume"));
280
281 return DSERR_INVALIDCALL;
282}
283
284//******************************************************************************
285//******************************************************************************
286HRESULT __stdcall PrimBufGetPan(THIS_ LPLONG )
287{
288 dprintf(("DSOUND-PrimBuff: GetPan"));
289
290 return DSERR_INVALIDCALL;
291}
292
293//******************************************************************************
294//******************************************************************************
295HRESULT __stdcall PrimBufGetFrequency(THIS_ LPDWORD )
296{
297 dprintf(("DSOUND-PrimBuff: GetGrequency"));
298
299 return DSERR_INVALIDCALL;
300}
301
302//******************************************************************************
303//******************************************************************************
304HRESULT __stdcall PrimBufGetStatus(THIS_ LPDWORD lpdwStatus )
305{
306 OS2PrimBuff *me = (OS2PrimBuff *)This;
307 dprintf(("DSOUND-PrimBuff: GetStatus"));
308
309 if (me == NULL || lpdwStatus == NULL) {
310 return(DSERR_INVALIDPARAM);
311 }
312
313 *lpdwStatus = DSBSTATUS_LOOPING /*| DSBSTATUS_LOCSOFTWARE*/;
314 if (me->fPlaying == TRUE)
315 *lpdwStatus |= DSBSTATUS_PLAYING;
316
317 return DS_OK;
318}
319
320//******************************************************************************
321//******************************************************************************
322HRESULT __stdcall PrimBufInitialize(THIS_ LPDIRECTSOUND, LPDSBUFFERDESC )
323{
324 OS2PrimBuff *me = (OS2PrimBuff *)This;
325 dprintf(("DSOUND-PrimBuff: Initialize"));
326
327 if (me == NULL) {
328 return DSERR_INVALIDPARAM;
329 }
330 return DSERR_ALREADYINITIALIZED; //todo: for future extensions (dx5/6 ??) ??
331}
332
333//******************************************************************************
334//******************************************************************************
335HRESULT __stdcall PrimBufLock(THIS_ DWORD dwWriteCursor, DWORD dwWriteBytes,
336 LPVOID lplpAudioPtr1, LPDWORD lpdwAudioBytes1,
337 LPVOID lplpAudioPtr2, LPDWORD lpdwAudioBytes2,
338 DWORD dwFlags)
339{
340 OS2PrimBuff *me = (OS2PrimBuff *)This;
341 DWORD dwCurPlayPos, dwCurWritePos;
342 LONG rc;
343
344 dprintf(("DSOUND-PrimBuff: Lock"));
345
346 if (me == NULL || !lplpAudioPtr1 || !lpdwAudioBytes1) {
347 return DSERR_INVALIDPARAM;
348 }
349 //not sure if this is an error, but it's certainly a smart thing to do (cond. == true)
350 if (dwWriteBytes > BUFFER_SIZE) {
351 dprintf(("SoundBufLock: dwWriteBytes > me->bufferdesc.dwBufferBytes"));
352 return DSERR_INVALIDPARAM;
353 }
354
355 if (me->fPlaying == FALSE) {
356 *(DWORD*)lplpAudioPtr1 = (DWORD)(me->lpBuffer);
357 *lpdwAudioBytes1 = dwWriteBytes;
358 if (lplpAudioPtr2 != NULL) {
359 *(DWORD*)lplpAudioPtr2 = NULL;
360 *lpdwAudioBytes2 = 0;
361 }
362 return DS_OK;
363 }
364
365 rc = PrimBufGetCurrentPosition( me, &dwCurPlayPos, &dwCurWritePos );
366 if (rc != DS_OK) {
367 return DSERR_GENERIC;
368 }
369
370 /* Debugging */
371 dprintf(("DSOUND-PrimBuff: CurPlay = %d, CurWrite = %d", dwCurPlayPos, dwCurWritePos));
372
373 if (dwFlags & DSBLOCK_FROMWRITECURSOR) {
374 dprintf(("DSOUND-PrimBuff: Locking FromCursor"));
375 dwWriteCursor = dwCurWritePos;
376 }
377
378 *(DWORD*)lplpAudioPtr1 = (DWORD)(me->lpBuffer + dwWriteCursor);
379
380 if (dwWriteCursor > dwCurPlayPos) {
381 if (dwWriteCursor + dwWriteBytes > BUFFER_SIZE) {
382 *lpdwAudioBytes1 = BUFFER_SIZE - dwWriteCursor;
383 if (lplpAudioPtr2!=NULL) {
384 *(DWORD*)lplpAudioPtr2 = (DWORD)me->lpBuffer;
385 if (dwWriteBytes - *lpdwAudioBytes1 > dwCurPlayPos) {
386 *lpdwAudioBytes2 = dwCurPlayPos;
387 } else {
388 *lpdwAudioBytes2 = dwWriteBytes - *lpdwAudioBytes1;
389 }
390 }
391 } else {
392 *lpdwAudioBytes1 = dwWriteBytes;
393 if (lplpAudioPtr2!=NULL) {
394 *(DWORD*)lplpAudioPtr2 = NULL;
395 *lpdwAudioBytes2 = 0;
396 }
397 }
398 } else { // The WriteCursor is behind of the PlayCursor
399 if (lplpAudioPtr2!=NULL) {
400 *(DWORD*)lplpAudioPtr2 = NULL;
401 *lpdwAudioBytes2 = 0;
402 }
403 if (dwWriteCursor + dwWriteBytes > dwCurPlayPos) {
404 *lpdwAudioBytes1 = dwWriteCursor - dwCurPlayPos;
405 } else {
406 *lpdwAudioBytes1 = dwWriteBytes;
407 }
408 }
409
410 return DS_OK;
411}
412
413//******************************************************************************
414//******************************************************************************
415HRESULT __stdcall PrimBufPlay(THIS_ DWORD dwRes1,DWORD dwRes2,DWORD dwFlags )
416{
417 long rc;
418 OS2PrimBuff *me = (OS2PrimBuff *)This;
419
420 if (me == NULL || !(dwFlags & DSBPLAY_LOOPING) ) {
421 return DSERR_INVALIDPARAM;
422 }
423
424 if (me->fPlaying)
425 return DS_OK;
426
427 dprintf(("DSOUND-PrimBuff: Play"));
428
429 rc = Dart_Play(me->usDeviceID, me->vpMixSetup, me->vpMixBuffer, me->fPlaying);
430 me->fPlaying = TRUE;
431 return rc;
432}
433
434//******************************************************************************
435//******************************************************************************
436HRESULT __stdcall PrimBufSetCurrentPosition(THIS_ DWORD )
437{
438 dprintf(("DSOUND-PrimBuff: SetCurrentPosition"));
439
440 return DSERR_INVALIDCALL;
441}
442
443//******************************************************************************
444//******************************************************************************
445HRESULT __stdcall PrimBufSetFormat(THIS_ LPWAVEFORMATEX lpfxFormat )
446{
447 dprintf(("DSOUND-PrimBuff: SetFormat"));
448 OS2PrimBuff *me = (OS2PrimBuff *)This;
449
[3100]450 if (me == NULL || lpfxFormat == NULL) {
[3099]451 return DSERR_INVALIDPARAM;
452 }
453
[3100]454 /* Note: the software mixer doesn't really support mono output but */
455 /* we can safely mix in stereo anyway */
456 if (lpfxFormat->nChannels == 1) {
457 if (me->parentDS->GetCoopLevel() != DSSCL_WRITEPRIMARY)
458 lpfxFormat->nChannels = 2;
459 }
460
[3099]461 memcpy( me->lpfxFormat, lpfxFormat, sizeof(WAVEFORMATEX) );
462
463 me->bps = lpfxFormat->wBitsPerSample;
464 me->rate = lpfxFormat->nSamplesPerSec;
465 me->channels = lpfxFormat->nChannels;
466
467 dprintf(("DSOUND-PrimBuff: BPS = %d, Rate = %d, Ch = %d", me->bps, me->rate, me->channels));
468
469 Dart_SetFormat(&me->usDeviceID, me->vpMixSetup, me->vpBuffParms, &me->vpMixBuffer, me->bps, me->rate, me->channels);
470
471 return DS_OK;
472}
473
474//******************************************************************************
475//******************************************************************************
476HRESULT __stdcall PrimBufSetVolume(THIS_ LONG )
477{
478 dprintf(("DSOUND-PrimBuff: SetVolume"));
479
480 return DSERR_CONTROLUNAVAIL;
481}
482
483//******************************************************************************
484//******************************************************************************
485HRESULT __stdcall PrimBufSetPan(THIS_ LONG )
486{
487 dprintf(("DSOUND-PrimBuff: SetPan"));
488
489 return DSERR_CONTROLUNAVAIL;
490}
491
492//******************************************************************************
493//******************************************************************************
494HRESULT __stdcall PrimBufSetFrequency(THIS_ DWORD )
495{
496 dprintf(("DSOUND-PrimBuff: SetFrequency"));
497
498 return DSERR_CONTROLUNAVAIL;
499}
500
501//******************************************************************************
502//******************************************************************************
503HRESULT __stdcall PrimBufStop(THIS )
504{
505 OS2PrimBuff *me = (OS2PrimBuff *)This;
506 dprintf(("DSOUND-PrimBuff: Stop"));
507
508 if (me == NULL) {
509 return DSERR_INVALIDPARAM;
510 }
511
512 if (!me->fPlaying)
513 return DS_OK;
514
515 me->fPlaying = FALSE;
516
517 return Dart_Stop(me->usDeviceID);
518}
519
520//******************************************************************************
521//******************************************************************************
522HRESULT __stdcall PrimBufUnlock(THIS_ LPVOID,DWORD,LPVOID,DWORD )
523{
[3925]524 // I don't think we really need any code here..
[3099]525
526 dprintf(("DSOUND-PrimBuff: Unlock"));
527
528 return DS_OK;
529}
530
531//******************************************************************************
532//******************************************************************************
533HRESULT __stdcall PrimBufRestore(THIS )
534{
[3555]535 // This maybe a good place to re-aquire the device if some other process
536 // has taken the audio focus, but before we do that we need to determine
537 // if we have lost the device and set the falg in the GetStatus method!
538
[3099]539 dprintf(("DSOUND-PrimBuff: Restore"));
540
541 return DS_OK;
542}
543
544
Note: See TracBrowser for help on using the repository browser.