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

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

fixed bps check

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