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

Last change on this file since 3100 was 3100, checked in by sandervl, 25 years ago

* empty log message *

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