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

Last change on this file since 2244 was 2244, checked in by sandervl, 26 years ago

MMPM/2 api wrappers

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