source: trunk/src/winmm/dwaveout.cpp@ 1462

Last change on this file since 1462 was 1462, checked in by phaller, 26 years ago

Fix: invalid callback check fixed

File size: 20.9 KB
Line 
1/* $Id: dwaveout.cpp,v 1.9 1999-10-26 22:44:15 phaller Exp $ */
2
3/*
4 * Wave playback class
5 *
6 * Copyright 1998 Sander van Leeuwen (sandervl@xs4all.nl)
7 *
8 *
9 * Project Odin Software License can be found in LICENSE.TXT
10 *
11 */
12
13
14/****************************************************************************
15 * Includes *
16 ****************************************************************************/
17
18
19
20#define INCL_BASE
21#define INCL_OS2MM
22#include <os2wrap.h> //Odin32 OS/2 api wrappers
23#include <os2me.h>
24#include <stdlib.h>
25#include <string.h>
26#define OS2_ONLY
27#include "win32type.h"
28#include <wprocess.h>
29
30#include "misc.h"
31#include "dwaveout.h"
32
33#ifndef min
34#define min(a, b) ((a > b) ? b : a)
35#endif
36
37//SvL: 23/09/99: WinPostMsg no longer works, as win32 window handles are no longer PM handles
38BOOL WIN32API PostMessageA(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
39
40LONG APIENTRY WaveOutHandler(ULONG ulStatus, PMCI_MIX_BUFFER pBuffer, ULONG ulFlags);
41
42//TODO: mulaw, alaw & adpcm
43/******************************************************************************/
44/******************************************************************************/
45DartWaveOut::DartWaveOut(LPWAVEFORMATEX pwfx)
46{
47 Init(pwfx);
48}
49/******************************************************************************/
50/******************************************************************************/
51DartWaveOut::DartWaveOut(LPWAVEFORMATEX pwfx, ULONG nCallback, ULONG dwInstance)
52{
53 Init(pwfx);
54
55 mthdCallback = (LPDRVCALLBACK)nCallback;
56 this->dwInstance = dwInstance;
57
58 if(!ulError)
59 callback((ULONG)this, WOM_OPEN, dwInstance, 0, 0);
60}
61/******************************************************************************/
62/******************************************************************************/
63DartWaveOut::DartWaveOut(LPWAVEFORMATEX pwfx, HWND hwndCallback)
64{
65 Init(pwfx);
66
67 this->hwndCallback = hwndCallback;
68
69 if(!ulError)
70 PostMessageA(hwndCallback, WOM_OPEN, 0, 0);
71}
72/******************************************************************************/
73/******************************************************************************/
74void DartWaveOut::callback(HDRVR h, UINT uMessage, DWORD dwUser, DWORD dw1, DWORD dw2)
75{
76 USHORT selTIB = SetWin32TIB();
77 mthdCallback(h,uMessage,dwUser,dw1,dw2);
78 SetFS(selTIB);
79}
80/******************************************************************************/
81/******************************************************************************/
82void DartWaveOut::Init(LPWAVEFORMATEX pwfx)
83{
84 MCI_GENERIC_PARMS GenericParms;
85 MCI_AMP_OPEN_PARMS AmpOpenParms;
86 APIRET rc;
87
88 curPlayBuf = curFillBuf = curFillPos = curPlayPos = 0;
89
90 fMixerSetup = FALSE;
91 next = NULL;
92 wavehdr = NULL;
93 curhdr = NULL;
94 mthdCallback = NULL;
95 hwndCallback = 0;
96 dwInstance = 0;
97 ulError = 0;
98 State = STATE_STOPPED;
99
100 MixBuffer = (MCI_MIX_BUFFER *)malloc(PREFILLBUF_DART*sizeof(MCI_MIX_BUFFER));
101 MixSetupParms = (MCI_MIXSETUP_PARMS *)malloc(sizeof(MCI_MIXSETUP_PARMS));
102 BufferParms = (MCI_BUFFER_PARMS *)malloc(sizeof(MCI_BUFFER_PARMS));
103
104 switch(pwfx->nBlockAlign) {
105 case 1://8 bits mono
106 BitsPerSample = 8;
107 break;
108 case 2://16 bits mono or 8 bits stereo
109 if(nChannels == 1)
110 BitsPerSample = 16;
111 else BitsPerSample = 8;
112 break;
113 case 4://16 bits stereo
114 BitsPerSample = 16;
115 break;
116 }
117 SampleRate = pwfx->nSamplesPerSec;
118 this->nChannels = pwfx->nChannels;
119 ulBufSize = DART_BUFSIZE;
120
121 // Setup the open structure, pass the playlist and tell MCI_OPEN to use it
122 memset(&AmpOpenParms,0,sizeof(AmpOpenParms));
123
124 AmpOpenParms.usDeviceID = ( USHORT ) 0;
125 AmpOpenParms.pszDeviceType = ( PSZ ) MCI_DEVTYPE_AUDIO_AMPMIX;
126
127 rc = mciSendCommand(0, MCI_OPEN,
128 MCI_WAIT | MCI_OPEN_TYPE_ID | MCI_OPEN_SHAREABLE,
129 (PVOID) &AmpOpenParms,
130 0);
131 DeviceId = AmpOpenParms.usDeviceID;
132 if(rc) {
133#ifdef DEBUG
134 WriteLog("MCI_OPEN failed\n");
135#endif
136 mciError(rc);
137 ulError = MMSYSERR_NODRIVER;
138 }
139 if(rc == 0) {
140 //Grab exclusive rights to device instance (NOT entire device)
141 GenericParms.hwndCallback = 0; //Not needed, so set to 0
142 rc = mciSendCommand(DeviceId, MCI_ACQUIREDEVICE, MCI_EXCLUSIVE_INSTANCE,
143 (PVOID)&GenericParms, 0);
144 if(rc) {
145#ifdef DEBUG
146 WriteLog("MCI_ACQUIREDEVICE failed\n");
147#endif
148 mciError(rc);
149 ulError = MMSYSERR_NOTENABLED;
150 }
151 }
152 State = STATE_STOPPED;
153
154 wmutex = new VMutex();
155 if(wmutex == NULL) {
156 ulError = MMSYSERR_NOTSUPPORTED;
157 }
158 if(wmutex)
159 wmutex->enter(VMUTEX_WAIT_FOREVER);
160
161 if(waveout == NULL) {
162 waveout = this;
163 }
164 else {
165 DartWaveOut *dwave = waveout;
166
167 while(dwave->next) {
168 dwave = dwave->next;
169 }
170 dwave->next = this;
171 }
172
173 if(wmutex)
174 wmutex->leave();
175}
176/******************************************************************************/
177/******************************************************************************/
178DartWaveOut::~DartWaveOut()
179{
180 MCI_GENERIC_PARMS GenericParms;
181
182 if(!ulError) {
183 // Generic parameters
184 GenericParms.hwndCallback = 0; //hwndFrame
185
186 // Stop the playback.
187 mciSendCommand(DeviceId, MCI_STOP,MCI_WAIT, (PVOID)&GenericParms,0);
188
189 mciSendCommand(DeviceId,
190 MCI_BUFFER,
191 MCI_WAIT | MCI_DEALLOCATE_MEMORY,
192 (PVOID)&BufferParms,
193 0);
194
195 // Generic parameters
196 GenericParms.hwndCallback = 0; //hwndFrame
197
198 // Close the device
199 mciSendCommand(DeviceId, MCI_CLOSE, MCI_WAIT, (PVOID)&GenericParms, 0);
200 }
201
202 if(wmutex)
203 wmutex->enter(VMUTEX_WAIT_FOREVER);
204
205 State = STATE_STOPPED;
206
207 if(waveout == this) {
208 waveout = this->next;
209 }
210 else {
211 DartWaveOut *dwave = waveout;
212
213 while(dwave->next != this) {
214 dwave = dwave->next;
215 }
216 dwave->next = this->next;
217 }
218 if(wmutex)
219 wmutex->leave();
220
221 if(!ulError) {
222 if(mthdCallback) {
223 callback((ULONG)this, WOM_CLOSE, dwInstance, 0, 0);
224 }
225 else
226 if(hwndCallback)
227 PostMessageA(hwndCallback, WOM_CLOSE, 0, 0);
228 }
229
230 if(wmutex)
231 delete wmutex;
232
233 if(MixBuffer)
234 free(MixBuffer);
235 if(MixSetupParms)
236 free(MixSetupParms);
237 if(BufferParms)
238 free(BufferParms);
239}
240/******************************************************************************/
241/******************************************************************************/
242MMRESULT DartWaveOut::getError()
243{
244 return(ulError);
245}
246/******************************************************************************/
247/******************************************************************************/
248int DartWaveOut::getNumDevices()
249{
250 MCI_GENERIC_PARMS GenericParms;
251 MCI_AMP_OPEN_PARMS AmpOpenParms;
252 APIRET rc;
253
254 // Setup the open structure, pass the playlist and tell MCI_OPEN to use it
255 memset(&AmpOpenParms,0,sizeof(AmpOpenParms));
256
257 AmpOpenParms.usDeviceID = ( USHORT ) 0;
258 AmpOpenParms.pszDeviceType = ( PSZ ) MCI_DEVTYPE_AUDIO_AMPMIX;
259
260 rc = mciSendCommand(0, MCI_OPEN,
261 MCI_WAIT | MCI_OPEN_TYPE_ID | MCI_OPEN_SHAREABLE,
262 (PVOID) &AmpOpenParms,
263 0);
264
265 if(rc) {
266 return 0; //no devices present
267 }
268
269 // Generic parameters
270 GenericParms.hwndCallback = 0; //hwndFrame
271
272 // Close the device
273 mciSendCommand(AmpOpenParms.usDeviceID, MCI_CLOSE, MCI_WAIT, (PVOID)&GenericParms, 0);
274
275 return 1;
276}
277/******************************************************************************/
278/******************************************************************************/
279MMRESULT DartWaveOut::write(LPWAVEHDR pwh, UINT cbwh)
280{
281 MCI_GENERIC_PARMS GenericParms = {0};
282 APIRET rc;
283 int i, buflength;
284
285 if(fMixerSetup == FALSE) {
286#ifdef DEBUG
287 WriteLog("device acquired\n");
288#endif
289 /* Set the MixSetupParms data structure to match the loaded file.
290 * This is a global that is used to setup the mixer.
291 */
292 memset(MixSetupParms, 0, sizeof( MCI_MIXSETUP_PARMS ) );
293
294 MixSetupParms->ulBitsPerSample = BitsPerSample;
295 MixSetupParms->ulSamplesPerSec = SampleRate;
296 MixSetupParms->ulFormatTag = MCI_WAVE_FORMAT_PCM;
297 MixSetupParms->ulChannels = nChannels;
298
299#ifdef DEBUG
300 WriteLog("bps %d, sps %d chan %d\n", BitsPerSample, SampleRate, nChannels);
301#endif
302
303 /* Setup the mixer for playback of wave data
304 */
305 MixSetupParms->ulFormatMode = MCI_PLAY;
306 MixSetupParms->ulDeviceType = MCI_DEVTYPE_WAVEFORM_AUDIO;
307 MixSetupParms->pmixEvent = WaveOutHandler;
308
309 rc = mciSendCommand(DeviceId,
310 MCI_MIXSETUP,
311 MCI_WAIT | MCI_MIXSETUP_INIT,
312 (PVOID)MixSetupParms,
313 0);
314
315 if ( rc != MCIERR_SUCCESS ) {
316 mciError(rc);
317 mciSendCommand(DeviceId, MCI_RELEASEDEVICE, MCI_WAIT,
318 (PVOID)&GenericParms, 0);
319 return(MMSYSERR_NOTSUPPORTED);
320 }
321
322 /*
323 * Set up the BufferParms data structure and allocate
324 * device buffers from the Amp-Mixer
325 */
326#ifdef DEBUG
327 WriteLog("mix setup %d, %d\n", pwh->dwBufferLength, pwh->dwBufferLength);
328#endif
329#if 1
330 ulBufSize = pwh->dwBufferLength/2;
331#else
332 if(pwh->dwBufferLength >= 512 && pwh->dwBufferLength <= 1024)
333 ulBufSize = pwh->dwBufferLength;
334 else ulBufSize = 1024;
335#endif
336
337 MixSetupParms->ulBufferSize = ulBufSize;
338
339 BufferParms->ulNumBuffers = PREFILLBUF_DART;
340 BufferParms->ulBufferSize = MixSetupParms->ulBufferSize;
341 BufferParms->pBufList = MixBuffer;
342
343 for(i=0;i<PREFILLBUF_DART;i++) {
344 MixBuffer[i].ulUserParm = (ULONG)this;
345 }
346
347 rc = mciSendCommand(DeviceId,
348 MCI_BUFFER,
349 MCI_WAIT | MCI_ALLOCATE_MEMORY,
350 (PVOID)BufferParms,
351 0);
352
353 if(ULONG_LOWD(rc) != MCIERR_SUCCESS) {
354 mciError(rc);
355 mciSendCommand(DeviceId, MCI_RELEASEDEVICE, MCI_WAIT,
356 (PVOID)&GenericParms, 0);
357 return(MMSYSERR_NOTSUPPORTED);
358 }
359
360 wmutex->enter(VMUTEX_WAIT_FOREVER);
361 fMixerSetup = TRUE;
362
363 curPlayBuf = curFillBuf = curFillPos = curPlayPos = 0;
364
365 for(i=0;i<PREFILLBUF_DART;i++) {
366 memset(MixBuffer[i].pBuffer, 0, MixBuffer[i].ulBufferLength);
367 }
368#ifdef DEBUG
369 WriteLog("Dart opened, bufsize = %d\n", MixBuffer[i].ulBufferLength);
370#endif
371
372 wavehdr = pwh;
373 curhdr = pwh;
374 pwh->lpNext = NULL;
375
376 while(TRUE) {
377 buflength = min((ULONG)MixBuffer[curFillBuf].ulBufferLength - curPlayPos,
378 (ULONG)wavehdr->dwBufferLength - curFillPos);
379#ifdef DEBUG
380 WriteLog("Copying %d data; curPlayPos = %d curFillPos = %d\n", buflength, curPlayPos, curFillPos);
381#endif
382 memcpy((char *)MixBuffer[curFillBuf].pBuffer + curPlayPos,
383 wavehdr->lpData + curFillPos,
384 buflength);
385
386 curPlayPos += buflength;
387 curFillPos += buflength;
388 if(curFillPos == wavehdr->dwBufferLength) {
389#ifdef DEBUG
390 WriteLog("Processed first win32 buffer\n");
391#endif
392 curFillPos = 0;
393 wavehdr->dwFlags |= WHDR_DONE;
394 curhdr = NULL;
395 }
396 if(curPlayPos == MixBuffer[curPlayBuf].ulBufferLength) {
397 if(++curPlayBuf == PREFILLBUF_DART) {
398 curPlayBuf = 0;
399 break;
400 }
401 curPlayPos = 0;
402 }
403 if(curFillPos == 0)
404 break;
405 }
406#ifdef DEBUG
407 WriteLog("MixSetupParms = %X\n", MixSetupParms);
408#endif
409 State = STATE_PLAYING;
410 wmutex->leave();
411
412 MixSetupParms->pmixWrite(MixSetupParms->ulMixHandle,
413 MixBuffer,
414 PREFILLBUF_DART);
415#ifdef DEBUG
416 WriteLog("Dart playing\n");
417#endif
418 }
419 else {
420 wmutex->enter(VMUTEX_WAIT_FOREVER);
421 pwh->lpNext = NULL;
422 if(wavehdr) {
423 WAVEHDR *chdr = wavehdr;
424 while(chdr->lpNext) {
425 chdr = chdr->lpNext;
426 }
427 chdr->lpNext = pwh;
428 }
429 else wavehdr = pwh;
430 wmutex->leave();
431 if(State != STATE_PLAYING) {//continue playback
432 restart();
433 }
434 }
435
436 return(MMSYSERR_NOERROR);
437}
438/******************************************************************************/
439/******************************************************************************/
440MMRESULT DartWaveOut::pause()
441{
442 MCI_GENERIC_PARMS Params;
443
444 if(State != STATE_PLAYING)
445 return(MMSYSERR_HANDLEBUSY);
446
447 wmutex->enter(VMUTEX_WAIT_FOREVER);
448 State = STATE_PAUSED;
449 wmutex->leave();
450
451 memset(&Params, 0, sizeof(Params));
452
453 // Stop the playback.
454 mciSendCommand(DeviceId, MCI_PAUSE, MCI_WAIT, (PVOID)&Params, 0);
455
456 return(MMSYSERR_NOERROR);
457}
458/******************************************************************************/
459/******************************************************************************/
460MMRESULT DartWaveOut::reset()
461{
462 MCI_GENERIC_PARMS Params;
463
464 dprintf(("DartWaveOut::reset %s", (State == STATE_PLAYING) ? "playing" : "stopped"));
465 if(State != STATE_PLAYING)
466 return(MMSYSERR_HANDLEBUSY);
467
468 memset(&Params, 0, sizeof(Params));
469
470 // Stop the playback.
471 mciSendCommand(DeviceId, MCI_STOP, MCI_WAIT, (PVOID)&Params, 0);
472
473#ifdef DEBUG
474 WriteLog("Nr of threads blocked on mutex = %d\n", wmutex->getNrBlocked());
475#endif
476
477 wmutex->enter(VMUTEX_WAIT_FOREVER);
478 while(wavehdr) {
479 wavehdr->dwFlags |= WHDR_DONE;
480 wmutex->leave();
481 if(mthdCallback) {
482 callback((ULONG)this, WOM_DONE, dwInstance, wavehdr->dwUser, (ULONG)wavehdr);
483 }
484 else
485 if(hwndCallback)
486 PostMessageA(hwndCallback, WOM_DONE, wavehdr->dwUser, (ULONG)wavehdr);
487
488 wmutex->enter(VMUTEX_WAIT_FOREVER);
489 wavehdr = wavehdr->lpNext;
490 }
491 wavehdr = NULL;
492 State = STATE_STOPPED;
493
494 wmutex->leave();
495 return(MMSYSERR_NOERROR);
496}
497/******************************************************************************/
498/******************************************************************************/
499MMRESULT DartWaveOut::restart()
500{
501 dprintf(("DartWaveOut::restart"));
502 wmutex->enter(VMUTEX_WAIT_FOREVER);
503 State = STATE_PLAYING;
504 wmutex->leave();
505 MixSetupParms->pmixWrite(MixSetupParms->ulMixHandle,
506 &MixBuffer[curPlayBuf],
507 PREFILLBUF_DART);
508 return(MMSYSERR_NOERROR);
509}
510/******************************************************************************/
511/******************************************************************************/
512BOOL DartWaveOut::queryFormat(ULONG formatTag, ULONG nChannels,
513 ULONG nSamplesPerSec, ULONG sampleSize)
514{
515 MCI_WAVE_GETDEVCAPS_PARMS mciAudioCaps;
516 MCI_GENERIC_PARMS GenericParms;
517 MCI_OPEN_PARMS mciOpenParms; /* open parms for MCI_OPEN */
518 int i, freqbits = 0;
519 ULONG rc, DeviceId;
520 BOOL winrc;
521
522 memset(&mciOpenParms, /* Object to fill with zeros. */
523 0, /* Value to place into the object. */
524 sizeof( mciOpenParms ) ); /* How many zero's to use. */
525
526 mciOpenParms.pszDeviceType = (PSZ)MCI_DEVTYPE_WAVEFORM_AUDIO;
527
528 rc = mciSendCommand( (USHORT) 0,
529 MCI_OPEN,
530 MCI_WAIT | MCI_OPEN_TYPE_ID,
531 (PVOID) &mciOpenParms,
532 0);
533 if (rc != 0) {
534 return(FALSE);
535 }
536 DeviceId = mciOpenParms.usDeviceID;
537
538 memset( &mciAudioCaps , 0, sizeof(MCI_WAVE_GETDEVCAPS_PARMS));
539
540 switch(sampleSize) {
541 case 1:
542 mciAudioCaps.ulBitsPerSample = 8;
543 break;
544 case 2:
545 if(nChannels == 1)
546 mciAudioCaps.ulBitsPerSample = 16;
547 else mciAudioCaps.ulBitsPerSample = 8;
548 break;
549 case 4:
550 mciAudioCaps.ulBitsPerSample = 16;
551 break;
552 }
553 mciAudioCaps.ulFormatTag = DATATYPE_WAVEFORM;
554 mciAudioCaps.ulSamplesPerSec = nSamplesPerSec;
555 mciAudioCaps.ulChannels = nChannels;
556 mciAudioCaps.ulFormatMode = MCI_PLAY;
557 mciAudioCaps.ulItem = MCI_GETDEVCAPS_WAVE_FORMAT;
558
559 rc = mciSendCommand(DeviceId, /* Device ID */
560 MCI_GETDEVCAPS,
561 MCI_WAIT | MCI_GETDEVCAPS_EXTENDED | MCI_GETDEVCAPS_ITEM,
562 (PVOID) &mciAudioCaps,
563 0);
564 if((rc & 0xFFFF) != MCIERR_SUCCESS) {
565 mciError(rc);
566 winrc = FALSE;
567 }
568 // Close the device
569 mciSendCommand(DeviceId,MCI_CLOSE,MCI_WAIT,(PVOID)&GenericParms,0);
570 return(winrc);
571}
572/******************************************************************************/
573/******************************************************************************/
574void DartWaveOut::mciError(ULONG ulError)
575{
576#ifdef DEBUG
577 char szError[256] = "";
578
579 mciGetErrorString(ulError, szError, sizeof(szError));
580 WriteLog("WINMM: DartWaveOut: %s\n", szError);
581#endif
582}
583//******************************************************************************
584//******************************************************************************
585BOOL DartWaveOut::find(DartWaveOut *dwave)
586{
587 DartWaveOut *curwave = waveout;
588
589 while(curwave) {
590 if(dwave == curwave) {
591 return(TRUE);
592 }
593 curwave = curwave->next;
594 }
595
596#ifdef DEBUG
597 WriteLog("WINMM:DartWaveOut not found!\n");
598#endif
599 return(FALSE);
600}
601/******************************************************************************/
602/******************************************************************************/
603void DartWaveOut::handler(ULONG ulStatus, PMCI_MIX_BUFFER pBuffer, ULONG ulFlags)
604{
605 ULONG buflength;
606 WAVEHDR *whdr = wavehdr, *prevhdr = NULL;
607
608#ifdef DEBUG1
609 WriteLog("WINMM: handler %d\n", curPlayBuf);
610#endif
611 if(ulFlags == MIX_STREAM_ERROR) {
612 if(ulStatus == ERROR_DEVICE_UNDERRUN) {
613 dprintf(("WINMM: WaveOut handler UNDERRUN!\n"));
614 pause(); //out of buffers, so pause playback
615 return;
616 }
617 dprintf(("WINMM: WaveOut handler, Unknown error %X\n", ulStatus));
618 return;
619 }
620 wmutex->enter(VMUTEX_WAIT_FOREVER);
621
622 while(whdr) {
623 if(whdr->dwFlags & WHDR_DONE) {
624#ifdef DEBUG1
625 WriteLog("WINMM: handler buf %X done\n", whdr);
626#endif
627 whdr->dwFlags &= ~WHDR_INQUEUE;
628
629 if(prevhdr == NULL)
630 wavehdr = whdr->lpNext;
631 else prevhdr->lpNext = whdr->lpNext;
632
633 whdr->lpNext = NULL;
634 wmutex->leave();
635
636 dprintf(("WINMM:DartWaveOut::handler callback=%08xh\n",
637 callback));
638 if(mthdCallback) {
639 callback((ULONG)this, WOM_DONE, dwInstance, whdr->dwUser, (ULONG)whdr);
640 }
641 else
642 if(hwndCallback)
643 PostMessageA(hwndCallback, WOM_DONE, whdr->dwUser, (ULONG)whdr);
644
645 wmutex->enter(VMUTEX_WAIT_FOREVER);
646 }
647 prevhdr = whdr;
648 whdr = whdr->lpNext;
649 }
650
651 if(curhdr == NULL)
652 curhdr = wavehdr;
653
654#ifdef DEBUG1
655 WriteLog("WINMM: handler cur (%d,%d), fill (%d,%d)\n", curPlayBuf, curPlayPos, curFillBuf, curFillPos);
656#endif
657
658 while(curhdr) {
659 buflength = min((ULONG)MixBuffer[curFillBuf].ulBufferLength - curPlayPos,
660 (ULONG)curhdr->dwBufferLength - curFillPos);
661 memcpy((char *)MixBuffer[curFillBuf].pBuffer + curPlayPos,
662 curhdr->lpData + curFillPos,
663 buflength);
664 curPlayPos += buflength;
665 curFillPos += buflength;
666#ifdef DEBUG1
667 WriteLog("WINMM: copied %d bytes, cufFillPos = %d, dwBufferLength = %d\n", buflength, curFillPos, curhdr->dwBufferLength);
668#endif
669 if(curFillPos == curhdr->dwBufferLength) {
670#ifdef DEBUG1
671 WriteLog("Buffer %d done\n", curFillBuf);
672#endif
673 curFillPos = 0;
674 curhdr->dwFlags |= WHDR_DONE;
675 //search for next unprocessed buffer
676 while(curhdr && curhdr->dwFlags & WHDR_DONE)
677 curhdr = curhdr->lpNext;
678 }
679 if(curPlayPos == MixBuffer[curFillBuf].ulBufferLength) {
680 curPlayPos = 0;
681 if(++curFillBuf == PREFILLBUF_DART) {
682 curFillBuf = 0;
683 }
684 if(curFillBuf == curPlayBuf)
685 break; //no more room left
686 }
687 }
688
689 if(curPlayBuf == PREFILLBUF_DART-1)
690 curPlayBuf = 0;
691 else curPlayBuf++;
692
693 wmutex->leave();
694 //Transfer buffer to DART
695 MixSetupParms->pmixWrite(MixSetupParms->ulMixHandle, &MixBuffer[curPlayBuf], 1);
696}
697/******************************************************************************/
698/******************************************************************************/
699LONG APIENTRY WaveOutHandler(ULONG ulStatus, PMCI_MIX_BUFFER pBuffer,
700 ULONG ulFlags)
701{
702 DartWaveOut *dwave;
703 PTIB ptib;
704 PPIB ppib;
705
706 DosGetInfoBlocks(&ptib, &ppib);
707// dprintf(("WaveOutHandler: thread %d prio %X", ptib->tib_ptib2->tib2_ultid, ptib->tib_ptib2->tib2_ulpri));
708 if(pBuffer && pBuffer->ulUserParm) {
709 dwave = (DartWaveOut *)pBuffer->ulUserParm;
710 dwave->handler(ulStatus, pBuffer, ulFlags);
711 }
712 return(TRUE);
713}
714/******************************************************************************/
715/******************************************************************************/
716DartWaveOut *DartWaveOut::waveout = NULL;
717
Note: See TracBrowser for help on using the repository browser.