source: trunk/src/dsound/OS2PrimBuff.cpp@ 21479

Last change on this file since 21479 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
Line 
1/* $Id: OS2PrimBuff.cpp,v 1.5 2001-03-06 20:11:16 mike Exp $ */
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
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
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
20 end of this buffer.
21
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
24 program to lock between that location and 15ms from there
25 (15ms should be past the next buffer).
26
27*/
28
29#define INCL_DOSMISC
30#include <os2win.h>
31#include <stdio.h>
32#include <stdlib.h>
33#include <string.h>
34
35#define CINTERFACE
36#include <dsound.h>
37
38//#include "DSound.h"
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;
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;
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
137 if (IsEqualGUID(riid, &IID_IDirectSoundBuffer)) {
138 *ppvObj = This;
139 PrimBufAddRef(This);
140 return DS_OK;
141 }
142
143
144 if (IsEqualGUID(riid, &IID_IDirectSound3DListener)) {
145 OS2PrimBuff *me = (OS2PrimBuff *)This;
146 OS2IDirectSound3DListener *listener;
147
148 listener = new OS2IDirectSound3DListener(me);
149 *ppvObj = listener;
150 listener->Vtbl.fnAddRef((IDirectSound3DListener *)listener);
151 return DS_OK;
152 }
153
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
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
265 copysize = MIN(dwSizeAllocated, (me->lpfxFormat->cbSize + sizeof(WAVEFORMATEX)));
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
450 if (me == NULL || lpfxFormat == NULL) {
451 return DSERR_INVALIDPARAM;
452 }
453
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
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{
524 // I don't think we really need any code here..
525
526 dprintf(("DSOUND-PrimBuff: Unlock"));
527
528 return DS_OK;
529}
530
531//******************************************************************************
532//******************************************************************************
533HRESULT __stdcall PrimBufRestore(THIS )
534{
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
539 dprintf(("DSOUND-PrimBuff: Restore"));
540
541 return DS_OK;
542}
543
544
Note: See TracBrowser for help on using the repository browser.