source: trunk/src/dsound/new/OS2PrimBuff.cpp@ 3032

Last change on this file since 3032 was 3027, checked in by mike, 26 years ago

* empty log message *

File size: 15.9 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
49#include "dart.h"
50
51//******************************************************************************
52//******************************************************************************
53OS2PrimBuff::OS2PrimBuff(OS2IDirectSound *DSound, const DSBUFFERDESC *lpDSBufferDesc )
54{
55 LONG rc;
56
57 lpVtbl = &Vtbl;
58 Vtbl.AddRef = PrimBufAddRef;
59 Vtbl.Release = PrimBufRelease;
60 Vtbl.QueryInterface = PrimBufQueryInterface;
61 Vtbl.GetCaps = PrimBufGetCaps;
62 Vtbl.GetFormat = PrimBufGetFormat;
63 Vtbl.GetVolume = PrimBufGetVolume;
64 Vtbl.GetStatus = PrimBufGetStatus;
65 Vtbl.GetCurrentPosition = PrimBufGetCurrentPosition;
66 Vtbl.GetPan = PrimBufGetPan;
67 Vtbl.GetFrequency = PrimBufGetFrequency;
68 Vtbl.Initialize = PrimBufInitialize;
69 Vtbl.Restore = PrimBufRestore;
70 Vtbl.SetFormat = PrimBufSetFormat;
71 Vtbl.SetVolume = PrimBufSetVolume;
72 Vtbl.SetCurrentPosition = PrimBufSetCurrentPosition;
73 Vtbl.SetPan = PrimBufSetPan;
74 Vtbl.SetFrequency = PrimBufSetFrequency;
75 Vtbl.Lock = PrimBufLock;
76 Vtbl.Unlock = PrimBufUnlock;
77 Vtbl.Stop = PrimBufStop;
78 Vtbl.Play = PrimBufPlay;
79
80 dprintf(("DSOUND-PrimBuff: Constructor"));
81
82 parentDS = DSound;
83 fPlaying = FALSE;
84 playpos = 0;
85 fPrimary = TRUE;
86 Referenced = 0;
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 if (This == NULL) {
131 return DSERR_INVALIDPARAM;
132 }
133 *ppvObj = NULL;
134
135 if (!IsEqualGUID(riid, IID_IDirectSoundBuffer))
136 return E_NOINTERFACE;
137
138 *ppvObj = This;
139
140 PrimBufAddRef(This);
141 return DS_OK;
142}
143
144//******************************************************************************
145//******************************************************************************
146ULONG WIN32API PrimBufAddRef(THIS)
147{
148 OS2PrimBuff *me = (OS2PrimBuff *)This;
149
150 dprintf(("DSOUND-PrimBuff: AddRef %d", me->Referenced+1));
151
152 if (me == NULL) {
153 return DS_OK;
154 }
155 return ++me->Referenced;
156}
157
158//******************************************************************************
159//******************************************************************************
160ULONG WIN32API PrimBufRelease(THIS)
161{
162 OS2PrimBuff *me = (OS2PrimBuff *)This;
163
164 dprintf(("DSOUND-PrimBuff: Release %d", me->Referenced-1));
165
166 if (me == NULL) {
167 return DS_OK;
168 }
169 if (me->Referenced) {
170 me->Referenced--;
171 if (me->Referenced == 0) {
172 delete me;
173 return DS_OK;
174 }
175 else
176 return me->Referenced;
177 }
178 else
179 return DS_OK;
180}
181
182//******************************************************************************
183//******************************************************************************
184HRESULT __stdcall PrimBufGetCaps(THIS_ LPDSBCAPS lpDSCaps )
185{
186 OS2PrimBuff *me = (OS2PrimBuff *)This;
187
188 dprintf(("DSOUND-PrimBuff: GetCaps"));
189 if(me == NULL || lpDSCaps == NULL)
190 {
191 return DSERR_INVALIDPARAM;
192 }
193
194 lpDSCaps->dwFlags = DSBCAPS_PRIMARYBUFFER;
195 lpDSCaps->dwBufferBytes = BUFFER_SIZE;
196 lpDSCaps->dwUnlockTransferRate = 0;
197 lpDSCaps->dwPlayCpuOverhead = 0;
198
199 return DS_OK;
200}
201
202//******************************************************************************
203//******************************************************************************
204HRESULT __stdcall PrimBufGetCurrentPosition(THIS_ LPDWORD lpdwCurrentPlayCursor,LPDWORD lpdwCurrentWriteCursor )
205{
206 OS2PrimBuff *me = (OS2PrimBuff *)This;
207 LONG lDartPos;
208 LONG lBytesPerSec;
209
210 dprintf(("DSOUND-PrimBuff: GetCurrentPosition"));
211
212 if (me == NULL || lpdwCurrentPlayCursor == NULL || lpdwCurrentWriteCursor == NULL) {
213 return DSERR_INVALIDPARAM;
214 }
215
216 if (me->fPlaying == FALSE) {
217 *lpdwCurrentPlayCursor = 0;
218 *lpdwCurrentWriteCursor = 0;
219 return DS_OK;
220 }
221
222
223 Dart_GetPosition( me->usDeviceID, &lDartPos ); // Returns the Playing Buffer * 'Bytes Per Dart Bufer'
224
225 *lpdwCurrentPlayCursor = lDartPos;
226
227 // Calculate the Write Cursor as 15ms from the current play cursor.
228 // NOTE: This may need to be changed to insure that the write cursor is always beyond the
229 // point where the next buffer will read from.
230 *lpdwCurrentWriteCursor = (lDartPos + (me->rate * me->channels * (me->bps/8) * 15 / 1000) ) % BUFFER_SIZE;
231
232 return DS_OK;
233}
234
235
236//******************************************************************************
237//******************************************************************************
238HRESULT __stdcall PrimBufGetFormat(THIS_ LPWAVEFORMATEX lpfxFormat, DWORD dwSizeAllocated , LPDWORD lpdwSizeWritten )
239{
240 OS2PrimBuff *me = (OS2PrimBuff *)This;
241 long copysize;
242
243 dprintf(("DSOUND-PrimBuff: GetFormat"));
244
245 if( me == NULL || lpfxFormat == NULL || dwSizeAllocated == 0)
246 {
247 return DSERR_INVALIDPARAM;
248 }
249
250 copysize = min(dwSizeAllocated, (me->lpfxFormat->cbSize + sizeof(WAVEFORMATEX)));
251 memcpy(lpfxFormat, me->lpfxFormat, copysize);
252
253 if(lpdwSizeWritten)
254 {
255 *lpdwSizeWritten = copysize;
256 }
257 return DS_OK;
258}
259
260//******************************************************************************
261//******************************************************************************
262HRESULT __stdcall PrimBufGetVolume(THIS_ LPLONG )
263{
264 dprintf(("DSOUND-PrimBuff: GetVolume"));
265
266 return DSERR_INVALIDCALL;
267}
268
269//******************************************************************************
270//******************************************************************************
271HRESULT __stdcall PrimBufGetPan(THIS_ LPLONG )
272{
273 dprintf(("DSOUND-PrimBuff: GetPan"));
274
275 return DSERR_INVALIDCALL;
276}
277
278//******************************************************************************
279//******************************************************************************
280HRESULT __stdcall PrimBufGetFrequency(THIS_ LPDWORD )
281{
282 dprintf(("DSOUND-PrimBuff: GetGrequency"));
283
284 return DSERR_INVALIDCALL;
285}
286
287//******************************************************************************
288//******************************************************************************
289HRESULT __stdcall PrimBufGetStatus(THIS_ LPDWORD lpdwStatus )
290{
291 OS2PrimBuff *me = (OS2PrimBuff *)This;
292 dprintf(("DSOUND-PrimBuff: GetStatus"));
293
294 if (me == NULL || lpdwStatus == NULL) {
295 return(DSERR_INVALIDPARAM);
296 }
297
298 *lpdwStatus = DSBSTATUS_LOOPING /*| DSBSTATUS_LOCSOFTWARE*/;
299 if (me->fPlaying == TRUE)
300 *lpdwStatus |= DSBSTATUS_PLAYING;
301
302 return DS_OK;
303}
304
305//******************************************************************************
306//******************************************************************************
307HRESULT __stdcall PrimBufInitialize(THIS_ LPDIRECTSOUND, LPDSBUFFERDESC )
308{
309 OS2PrimBuff *me = (OS2PrimBuff *)This;
310 dprintf(("DSOUND-PrimBuff: Initialize"));
311
312 if (me == NULL) {
313 return DSERR_INVALIDPARAM;
314 }
315 return DSERR_ALREADYINITIALIZED; //todo: for future extensions (dx5/6 ??) ??
316}
317
318//******************************************************************************
319//******************************************************************************
320HRESULT __stdcall PrimBufLock(THIS_ DWORD dwWriteCursor, DWORD dwWriteBytes,
321 LPVOID lplpAudioPtr1, LPDWORD lpdwAudioBytes1,
322 LPVOID lplpAudioPtr2, LPDWORD lpdwAudioBytes2,
323 DWORD dwFlags)
324{
325 OS2PrimBuff *me = (OS2PrimBuff *)This;
326 DWORD dwCurPlayPos, dwCurWritePos;
327 LONG rc;
328
329 dprintf(("DSOUND-PrimBuff: Lock"));
330
331 if (me == NULL || !lplpAudioPtr1 || !lpdwAudioBytes1) {
332 return DSERR_INVALIDPARAM;
333 }
334 //not sure if this is an error, but it's certainly a smart thing to do (cond. == true)
335 if (dwWriteBytes > BUFFER_SIZE) {
336 dprintf(("SoundBufLock: dwWriteBytes > me->bufferdesc.dwBufferBytes"));
337 return DSERR_INVALIDPARAM;
338 }
339
340 if (me->fPlaying == FALSE) {
341 *(DWORD*)lplpAudioPtr1 = (DWORD)(me->lpBuffer);
342 *lpdwAudioBytes1 = dwWriteBytes;
343 if (lplpAudioPtr2 != NULL) {
344 *(DWORD*)lplpAudioPtr2 = NULL;
345 *lpdwAudioBytes2 = 0;
346 }
347 return DS_OK;
348 }
349
350 rc = PrimBufGetCurrentPosition( me, &dwCurPlayPos, &dwCurWritePos );
351 if (rc != DS_OK) {
352 return DSERR_GENERIC;
353 }
354
355 /* Debugging */
356 dprintf(("DSOUND-PrimBuff: CurPlay = %d, CurWrite = %d", dwCurPlayPos, dwCurWritePos));
357
358 if (dwFlags & DSBLOCK_FROMWRITECURSOR) {
359 dprintf(("DSOUND-PrimBuff: Locking FromCursor"));
360 dwWriteCursor = dwCurWritePos;
361 }
362
363 *(DWORD*)lplpAudioPtr1 = (DWORD)(me->lpBuffer + dwWriteCursor);
364
365 if (dwWriteCursor > dwCurPlayPos) {
366 if (dwWriteCursor + dwWriteBytes > BUFFER_SIZE) {
367 *lpdwAudioBytes1 = BUFFER_SIZE - dwWriteCursor;
368 if (lplpAudioPtr2!=NULL) {
369 *(DWORD*)lplpAudioPtr2 = (DWORD)me->lpBuffer;
370 if (dwWriteBytes - *lpdwAudioBytes1 > dwCurPlayPos) {
371 *lpdwAudioBytes2 = dwCurPlayPos;
372 } else {
373 *lpdwAudioBytes2 = dwWriteBytes - *lpdwAudioBytes1;
374 }
375 }
376 } else {
377 *lpdwAudioBytes1 = dwWriteBytes;
378 if (lplpAudioPtr2!=NULL) {
379 *(DWORD*)lplpAudioPtr2 = NULL;
380 *lpdwAudioBytes2 = 0;
381 }
382 }
383 } else { // The WriteCursor is behind of the PlayCursor
384 if (lplpAudioPtr2!=NULL) {
385 *(DWORD*)lplpAudioPtr2 = NULL;
386 *lpdwAudioBytes2 = 0;
387 }
388 if (dwWriteCursor + dwWriteBytes > dwCurPlayPos) {
389 *lpdwAudioBytes1 = dwWriteCursor - dwCurPlayPos;
390 } else {
391 *lpdwAudioBytes1 = dwWriteBytes;
392 }
393 }
394
395 return DS_OK;
396}
397
398//******************************************************************************
399//******************************************************************************
400HRESULT __stdcall PrimBufPlay(THIS_ DWORD dwRes1,DWORD dwRes2,DWORD dwFlags )
401{
402 long rc;
403 OS2PrimBuff *me = (OS2PrimBuff *)This;
404
405 if (me == NULL || !(dwFlags & DSBPLAY_LOOPING) ) {
406 return DSERR_INVALIDPARAM;
407 }
408
409 if (me->fPlaying)
410 return DS_OK;
411
412 dprintf(("DSOUND-PrimBuff: Play"));
413
414 rc = Dart_Play(me->usDeviceID, me->vpMixSetup, me->vpMixBuffer, me->fPlaying);
415 me->fPlaying = TRUE;
416 return rc;
417}
418
419//******************************************************************************
420//******************************************************************************
421HRESULT __stdcall PrimBufSetCurrentPosition(THIS_ DWORD )
422{
423 dprintf(("DSOUND-PrimBuff: SetCurrentPosition"));
424
425 return DSERR_INVALIDCALL;
426}
427
428//******************************************************************************
429//******************************************************************************
430HRESULT __stdcall PrimBufSetFormat(THIS_ LPWAVEFORMATEX lpfxFormat )
431{
432 dprintf(("DSOUND-PrimBuff: SetFormat"));
433 OS2PrimBuff *me = (OS2PrimBuff *)This;
434
435 if (me == NULL) {
436 return DSERR_INVALIDPARAM;
437 }
438
439 memcpy( me->lpfxFormat, lpfxFormat, sizeof(WAVEFORMATEX) );
440
441 me->bps = lpfxFormat->wBitsPerSample;
442 me->rate = lpfxFormat->nSamplesPerSec;
443 me->channels = lpfxFormat->nChannels;
444
445 dprintf(("DSOUND-PrimBuff: BPS = %d, Rate = %d, Ch = %d", me->bps, me->rate, me->channels));
446
447 Dart_SetFormat(&me->usDeviceID, me->vpMixSetup, me->vpBuffParms, me->vpMixBuffer, me->bps, me->rate, me->channels);
448
449 return DS_OK;
450}
451
452//******************************************************************************
453//******************************************************************************
454HRESULT __stdcall PrimBufSetVolume(THIS_ LONG )
455{
456 dprintf(("DSOUND-PrimBuff: SetVolume"));
457
458 return DSERR_CONTROLUNAVAIL;
459}
460
461//******************************************************************************
462//******************************************************************************
463HRESULT __stdcall PrimBufSetPan(THIS_ LONG )
464{
465 dprintf(("DSOUND-PrimBuff: SetPan"));
466
467 return DSERR_CONTROLUNAVAIL;
468}
469
470//******************************************************************************
471//******************************************************************************
472HRESULT __stdcall PrimBufSetFrequency(THIS_ DWORD )
473{
474 dprintf(("DSOUND-PrimBuff: SetFrequency"));
475
476 return DSERR_CONTROLUNAVAIL;
477}
478
479//******************************************************************************
480//******************************************************************************
481HRESULT __stdcall PrimBufStop(THIS )
482{
483 OS2PrimBuff *me = (OS2PrimBuff *)This;
484 dprintf(("DSOUND-PrimBuff: Stop"));
485
486 if (me == NULL) {
487 return DSERR_INVALIDPARAM;
488 }
489
490 if (!me->fPlaying)
491 return DS_OK;
492
493 me->fPlaying = FALSE;
494
495 return Dart_Stop(me->usDeviceID);
496}
497
498//******************************************************************************
499//******************************************************************************
500HRESULT __stdcall PrimBufUnlock(THIS_ LPVOID,DWORD,LPVOID,DWORD )
501{
502 // I don't think we really need any code here.. This may be a handly place to
503
504 dprintf(("DSOUND-PrimBuff: Unlock"));
505
506 return DS_OK;
507}
508
509//******************************************************************************
510//******************************************************************************
511HRESULT __stdcall PrimBufRestore(THIS )
512{
513 dprintf(("DSOUND-PrimBuff: Restore"));
514
515 return DS_OK;
516}
517
518
Note: See TracBrowser for help on using the repository browser.