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

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

callback + buffer size fixes

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