source: trunk/src/winmm/dwavein.cpp@ 5272

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

Added preliminary wavein support

File size: 23.2 KB
Line 
1/* $Id: dwavein.cpp,v 1.1 2001-02-27 21:13:59 sandervl Exp $ */
2
3/*
4 * Wave record class
5 *
6 * Copyright 2001 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/****************************************************************************
16 * Includes *
17 ****************************************************************************/
18
19
20
21#define INCL_BASE
22#define INCL_OS2MM
23#include <os2wrap.h> //Odin32 OS/2 api wrappers
24#include <os2mewrap.h> //Odin32 OS/2 MMPM/2 api wrappers
25#include <stdlib.h>
26#include <string.h>
27#define OS2_ONLY
28#include <win32api.h>
29#include <wprocess.h>
30
31#include "misc.h"
32#include "dwavein.h"
33
34#define DBG_LOCALLOG DBG_dwavein
35#include "dbglocal.h"
36
37#ifndef min
38#define min(a, b) ((a > b) ? b : a)
39#endif
40
41#ifndef max
42#define max(a, b) ((a > b) ? a : b)
43#endif
44
45LONG APIENTRY WaveInHandler(ULONG ulStatus, PMCI_MIX_BUFFER pBuffer, ULONG ulFlags);
46
47//TODO: mulaw, alaw & adpcm
48/******************************************************************************/
49/******************************************************************************/
50DartWaveIn::DartWaveIn(LPWAVEFORMATEX pwfx)
51{
52 Init(pwfx);
53}
54/******************************************************************************/
55/******************************************************************************/
56DartWaveIn::DartWaveIn(LPWAVEFORMATEX pwfx, ULONG nCallback, ULONG dwInstance, USHORT usSel)
57{
58 Init(pwfx);
59
60 mthdCallback = (LPDRVCALLBACK)nCallback; // callback function
61 selCallback = usSel; // callback win32 tib selector
62 this->dwInstance = dwInstance;
63 fOverrun = FALSE;
64
65 if(!ulError)
66 callback((ULONG)this, WIM_OPEN, dwInstance, 0, 0);
67}
68/******************************************************************************/
69/******************************************************************************/
70DartWaveIn::DartWaveIn(LPWAVEFORMATEX pwfx, HWND hwndCallback)
71{
72 Init(pwfx);
73
74 this->hwndCallback = hwndCallback;
75
76 if(!ulError)
77 PostMessageA(hwndCallback, WIM_OPEN, 0, 0);
78}
79/******************************************************************************/
80/******************************************************************************/
81void DartWaveIn::callback(HDRVR h, UINT uMessage, DWORD dwUser, DWORD dw1, DWORD dw2)
82{
83 USHORT selTIB = GetFS(); // save current FS selector
84
85 dprintf(("WINMM:DartWaveIn::callback(HDRVR h=%08xh, UINT uMessage=%08xh, DWORD dwUser=%08xh, DWORD dw1=%08xh, DWORD dw2=%08xh)\n",
86 h, uMessage, dwUser, dw1, dw2));
87
88 if (selCallback != 0)
89 SetFS(selCallback); // switch to callback win32 tib selector (stored in waveInOpen)
90 else
91 dprintf(("WINMM:DartWaveIn::callback - selCallback is invalid"));
92
93 //@@@PH 1999/12/28 Shockwave Flashes seem to make assumptions on a
94 // specific stack layout. Do we have the correct calling convention here?
95 mthdCallback(h,uMessage,dwUser,dw1,dw2);
96 SetFS(selTIB); // switch back to the saved FS selector
97}
98/******************************************************************************/
99/******************************************************************************/
100void DartWaveIn::Init(LPWAVEFORMATEX pwfx)
101{
102 MCI_GENERIC_PARMS GenericParms;
103 MCI_AMP_OPEN_PARMS AmpOpenParms;
104 APIRET rc;
105
106 fMixerSetup = FALSE;
107 next = NULL;
108 wavehdr = NULL;
109 mthdCallback = NULL;
110 hwndCallback = 0;
111 selCallback = 0;
112 dwInstance = 0;
113 ulError = 0;
114 selCallback = 0;
115 State = STATE_STOPPED;
116
117 MixBuffer = (MCI_MIX_BUFFER *)malloc(PREFILLBUF_DART_REC*sizeof(MCI_MIX_BUFFER));
118 MixSetupParms = (MCI_MIXSETUP_PARMS *)malloc(sizeof(MCI_MIXSETUP_PARMS));
119 BufferParms = (MCI_BUFFER_PARMS *)malloc(sizeof(MCI_BUFFER_PARMS));
120
121 BitsPerSample = pwfx->wBitsPerSample;
122 SampleRate = pwfx->nSamplesPerSec;
123 this->nChannels = pwfx->nChannels;
124 ulBufSize = DART_BUFSIZE_REC;
125
126 dprintf(("waveInOpen: samplerate %d, numChan %d bps %d (%d), format %x", SampleRate, nChannels, BitsPerSample, pwfx->nBlockAlign, pwfx->wFormatTag));
127 // Setup the open structure, pass the playlist and tell MCI_OPEN to use it
128 memset(&AmpOpenParms,0,sizeof(AmpOpenParms));
129
130 AmpOpenParms.usDeviceID = ( USHORT ) 0;
131 AmpOpenParms.pszDeviceType = ( PSZ ) MCI_DEVTYPE_AUDIO_AMPMIX;
132
133 rc = mciSendCommand(0, MCI_OPEN,
134 MCI_WAIT | MCI_OPEN_TYPE_ID | MCI_OPEN_SHAREABLE,
135 (PVOID) &AmpOpenParms,
136 0);
137 DeviceId = AmpOpenParms.usDeviceID;
138 if(rc) {
139 dprintf(("MCI_OPEN failed\n"));
140 mciError(rc);
141 ulError = MMSYSERR_NODRIVER;
142 }
143 if(rc == 0) {
144 //Grab exclusive rights to device instance (NOT entire device)
145 GenericParms.hwndCallback = 0; //Not needed, so set to 0
146 rc = mciSendCommand(DeviceId, MCI_ACQUIREDEVICE, MCI_EXCLUSIVE_INSTANCE,
147 (PVOID)&GenericParms, 0);
148 if(rc) {
149 dprintf(("MCI_ACQUIREDEVICE failed\n"));
150 mciError(rc);
151 ulError = MMSYSERR_NOTENABLED;
152 }
153 }
154 State = STATE_STOPPED;
155
156 wmutex = new VMutex();
157 if(wmutex == NULL) {
158 DebugInt3();
159 ulError = MMSYSERR_NOTSUPPORTED;
160 }
161 if(wmutex)
162 wmutex->enter(VMUTEX_WAIT_FOREVER);
163
164 if(wavein == NULL) {
165 wavein = this;
166 }
167 else {
168 DartWaveIn *dwave = wavein;
169
170 while(dwave->next) {
171 dwave = dwave->next;
172 }
173 dwave->next = this;
174 }
175
176 if(wmutex)
177 wmutex->leave();
178}
179/******************************************************************************/
180/******************************************************************************/
181DartWaveIn::~DartWaveIn()
182{
183 MCI_GENERIC_PARMS GenericParms;
184
185 if(!ulError)
186 {
187 // Generic parameters
188 GenericParms.hwndCallback = 0; //hwndFrame
189
190 // Stop recording.
191 mciSendCommand(DeviceId, MCI_STOP,MCI_WAIT, (PVOID)&GenericParms,0);
192
193 mciSendCommand(DeviceId,
194 MCI_BUFFER,
195 MCI_WAIT | MCI_DEALLOCATE_MEMORY,
196 (PVOID)&BufferParms,
197 0);
198
199 // Generic parameters
200 GenericParms.hwndCallback = 0; //hwndFrame
201
202 // Close the device
203 mciSendCommand(DeviceId, MCI_CLOSE, MCI_WAIT, (PVOID)&GenericParms, 0);
204 }
205
206 if(wmutex)
207 wmutex->enter(VMUTEX_WAIT_FOREVER);
208
209 State = STATE_STOPPED;
210
211 if(wavein == this) {
212 wavein = this->next;
213 }
214 else {
215 DartWaveIn *dwave = wavein;
216
217 while(dwave->next != this) {
218 dwave = dwave->next;
219 }
220 dwave->next = this->next;
221 }
222 if(wmutex)
223 wmutex->leave();
224
225 if(!ulError) {
226 if(mthdCallback) {
227 callback((ULONG)this, WIM_CLOSE, dwInstance, 0, 0);
228 }
229 else
230 if(hwndCallback)
231 PostMessageA(hwndCallback, WIM_CLOSE, 0, 0);
232 }
233
234 if(wmutex)
235 delete wmutex;
236
237 if(MixBuffer)
238 free(MixBuffer);
239 if(MixSetupParms)
240 free(MixSetupParms);
241 if(BufferParms)
242 free(BufferParms);
243}
244/******************************************************************************/
245/******************************************************************************/
246MMRESULT DartWaveIn::getError()
247{
248 return(ulError);
249}
250/******************************************************************************/
251/******************************************************************************/
252int DartWaveIn::getNumDevices()
253{
254 MCI_GENERIC_PARMS GenericParms;
255 MCI_AMP_OPEN_PARMS AmpOpenParms;
256 APIRET rc;
257
258 // Setup the open structure, pass the playlist and tell MCI_OPEN to use it
259 memset(&AmpOpenParms,0,sizeof(AmpOpenParms));
260
261 //TODO: correct for recording??
262 AmpOpenParms.usDeviceID = ( USHORT ) 0;
263 AmpOpenParms.pszDeviceType = ( PSZ ) MCI_DEVTYPE_AUDIO_AMPMIX;
264
265 rc = mciSendCommand(0, MCI_OPEN,
266 MCI_WAIT | MCI_OPEN_TYPE_ID | MCI_OPEN_SHAREABLE,
267 (PVOID) &AmpOpenParms,
268 0);
269
270 if(rc) {
271 return 0; //no devices present
272 }
273
274 // Generic parameters
275 GenericParms.hwndCallback = 0; //hwndFrame
276
277 // Close the device
278 mciSendCommand(AmpOpenParms.usDeviceID, MCI_CLOSE, MCI_WAIT, (PVOID)&GenericParms, 0);
279 return 1;
280}
281/******************************************************************************/
282/******************************************************************************/
283MMRESULT DartWaveIn::start()
284{
285 MCI_GENERIC_PARMS GenericParms = {0};
286 MCI_AMP_OPEN_PARMS AmpOpenParms;
287 MCI_CONNECTOR_PARMS ConnectorParms;
288 MCI_AMP_SET_PARMS AmpSetParms ;
289 APIRET rc;
290 int i, curbuf, buflength;
291
292 dprintf(("DartWaveIn::start"));
293 if(State == STATE_RECORDING)
294 return(MMSYSERR_NOERROR);
295
296 if(fMixerSetup == FALSE)
297 {
298 dprintf(("device acquired\n"));
299 /* Set the MixSetupParms data structure to match the loaded file.
300 * This is a global that is used to setup the mixer.
301 */
302 memset(MixSetupParms, 0, sizeof( MCI_MIXSETUP_PARMS ) );
303
304 MixSetupParms->ulBitsPerSample = BitsPerSample;
305 MixSetupParms->ulSamplesPerSec = SampleRate;
306 MixSetupParms->ulFormatTag = MCI_WAVE_FORMAT_PCM;
307 MixSetupParms->ulChannels = nChannels;
308
309 dprintf(("bps %d, sps %d chan %d\n", BitsPerSample, SampleRate, nChannels));
310
311 /* Setup the mixer for recording of wave data
312 */
313 MixSetupParms->ulFormatMode = MCI_RECORD;
314 MixSetupParms->ulDeviceType = MCI_DEVTYPE_WAVEFORM_AUDIO;
315 MixSetupParms->pmixEvent = WaveInHandler;
316
317 rc = mciSendCommand(DeviceId,
318 MCI_MIXSETUP,
319 MCI_WAIT | MCI_MIXSETUP_INIT,
320 (PVOID)MixSetupParms,
321 0);
322
323 if ( rc != MCIERR_SUCCESS ) {
324 mciError(rc);
325 mciSendCommand(DeviceId, MCI_RELEASEDEVICE, MCI_WAIT,
326 (PVOID)&GenericParms, 0);
327 return(MMSYSERR_NOTSUPPORTED);
328 }
329
330 /*
331 * Set up the BufferParms data structure and allocate
332 * device buffers from the Amp-Mixer
333 */
334
335 int consumerate = getAvgBytesPerSecond();
336 //SvL: Recording usually isn't as sensitive to timing as playback
337 // Dividing by 8 instead of 32 here. Change if necessary.
338 int minbufsize = consumerate/8;
339
340 LPWAVEHDR pwh = wavehdr;
341 if(pwh) {
342 dprintf(("mix setup %d, %d\n", pwh->dwBufferLength, pwh->dwBufferLength));
343
344 ulBufSize = pwh->dwBufferLength/2;
345 if(ulBufSize < minbufsize) {
346 dprintf(("set buffer size to %d bytes (org size = %d)", minbufsize, pwh->dwBufferLength));
347 ulBufSize = minbufsize;
348 }
349 }
350 else ulBufSize = minbufsize;
351
352 MixSetupParms->ulBufferSize = ulBufSize;
353
354 BufferParms->ulNumBuffers = PREFILLBUF_DART_REC;
355 BufferParms->ulBufferSize = MixSetupParms->ulBufferSize;
356 BufferParms->pBufList = MixBuffer;
357
358 for(i=0;i<PREFILLBUF_DART_REC;i++) {
359 MixBuffer[i].ulUserParm = (ULONG)this;
360 }
361
362 rc = mciSendCommand(DeviceId,
363 MCI_BUFFER,
364 MCI_WAIT | MCI_ALLOCATE_MEMORY,
365 (PVOID)BufferParms,
366 0);
367
368 if(ULONG_LOWD(rc) != MCIERR_SUCCESS) {
369 mciError(rc);
370 mciSendCommand(DeviceId, MCI_RELEASEDEVICE, MCI_WAIT,
371 (PVOID)&GenericParms, 0);
372 return(MMSYSERR_NOTSUPPORTED);
373 }
374
375 //TODO: don't do this here. Select line or mic depending on aux settings
376 //(until we really support the mixer extensions anyway)
377 /* Set the connector to 'line in' */
378 memset( &ConnectorParms, '\0', sizeof( MCI_CONNECTOR_PARMS ) );
379 ConnectorParms.ulConnectorType = MCI_LINE_IN_CONNECTOR;
380 rc = mciSendCommand( DeviceId,
381 MCI_CONNECTOR,
382 MCI_WAIT |
383 MCI_ENABLE_CONNECTOR |
384 MCI_CONNECTOR_TYPE,
385 ( PVOID ) &ConnectorParms,
386 0 );
387
388 /* Allow the user to hear what is being recorded
389 * by turning the monitor on
390 */
391 memset( &AmpSetParms, '\0', sizeof( MCI_AMP_SET_PARMS ) );
392 AmpSetParms.ulItem = MCI_AMP_SET_MONITOR;
393 rc = mciSendCommand(DeviceId,
394 MCI_SET,
395 MCI_WAIT | MCI_SET_ON | MCI_SET_ITEM,
396 ( PVOID ) &AmpSetParms,
397 0 );
398
399 wmutex->enter(VMUTEX_WAIT_FOREVER);
400 fMixerSetup = TRUE;
401 }
402
403 for(i=0;i<PREFILLBUF_DART_REC;i++) {
404 memset(MixBuffer[i].pBuffer, 0, MixBuffer[i].ulBufferLength);
405 }
406 dprintf(("Dart opened, bufsize = %d\n", MixBuffer[0].ulBufferLength));
407
408 dprintf(("MixSetupParms = %X\n", MixSetupParms));
409 State = STATE_RECORDING;
410 fOverrun = FALSE;
411 wmutex->leave();
412
413 dprintf(("Dart recording"));
414
415 // Start recording.
416 USHORT selTIB = GetFS(); // save current FS selector
417 MixSetupParms->pmixRead( MixSetupParms->ulMixHandle,
418 &MixBuffer[0],
419 PREFILLBUF_DART_REC);
420 SetFS(selTIB); // switch back to the saved FS selector
421
422 return(MMSYSERR_NOERROR);
423}
424/******************************************************************************/
425/******************************************************************************/
426MMRESULT DartWaveIn::stop()
427{
428 MCI_GENERIC_PARMS Params;
429
430 wmutex->enter(VMUTEX_WAIT_FOREVER);
431 if(State != STATE_RECORDING) {
432 State = STATE_STOPPED;
433 wmutex->leave();
434 return(MMSYSERR_NOERROR);
435 }
436
437 State = STATE_STOPPED;
438 wmutex->leave();
439
440 memset(&Params, 0, sizeof(Params));
441
442 // Stop recording.
443 mciSendCommand(DeviceId, MCI_STOP, MCI_WAIT, (PVOID)&Params, 0);
444
445 return(MMSYSERR_NOERROR);
446}
447/******************************************************************************/
448/******************************************************************************/
449MMRESULT DartWaveIn::reset()
450{
451 MCI_GENERIC_PARMS Params;
452
453 dprintf(("DartWaveIn::reset %s", (State == STATE_RECORDING) ? "recording" : "stopped"));
454 if(State != STATE_RECORDING)
455 return(MMSYSERR_HANDLEBUSY);
456
457 memset(&Params, 0, sizeof(Params));
458
459 // Stop recording
460 mciSendCommand(DeviceId, MCI_STOP, MCI_WAIT, (PVOID)&Params, 0);
461
462 dprintf(("Nr of threads blocked on mutex = %d\n", wmutex->getNrBlocked()));
463
464 wmutex->enter(VMUTEX_WAIT_FOREVER);
465 while(wavehdr)
466 {
467 wavehdr->dwFlags |= WHDR_DONE;
468 wavehdr->dwFlags &= ~WHDR_INQUEUE;
469 wavehdr = wavehdr->lpNext;
470 wavehdr->lpNext = NULL;
471
472 wmutex->leave();
473 if(mthdCallback) {
474 callback((ULONG)this, WIM_DATA, dwInstance, (ULONG)wavehdr, 0);
475 }
476 else
477 if(hwndCallback) {
478 dprintf(("Callback (msg) for buffer %x", wavehdr));
479 PostMessageA(hwndCallback, WIM_DATA, (WPARAM)this, (ULONG)wavehdr);
480 }
481 wmutex->enter(VMUTEX_WAIT_FOREVER);
482 }
483 wavehdr = NULL;
484 State = STATE_STOPPED;
485 fOverrun = FALSE;
486
487 wmutex->leave();
488 return(MMSYSERR_NOERROR);
489}
490/******************************************************************************/
491/******************************************************************************/
492MMRESULT DartWaveIn::addBuffer(LPWAVEHDR pwh, UINT cbwh)
493{
494 int i;
495
496 wmutex->enter(VMUTEX_WAIT_FOREVER);
497 pwh->lpNext = NULL;
498 pwh->dwBytesRecorded = 0;
499 if(wavehdr) {
500 WAVEHDR *chdr = wavehdr;
501 while(chdr->lpNext) {
502 chdr = chdr->lpNext;
503 }
504 chdr->lpNext = pwh;
505 }
506 else wavehdr = pwh;
507 wmutex->leave();
508
509 return(MMSYSERR_NOERROR);
510}
511/******************************************************************************/
512/******************************************************************************/
513ULONG DartWaveIn::getPosition()
514{
515 MCI_STATUS_PARMS mciStatus = {0};
516 ULONG rc, nrbytes;
517
518 mciStatus.ulItem = MCI_STATUS_POSITION;
519 rc = mciSendCommand(DeviceId, MCI_STATUS, MCI_STATUS_ITEM|MCI_WAIT, (PVOID)&mciStatus, 0);
520 if((rc & 0xFFFF) == MCIERR_SUCCESS) {
521 nrbytes = (mciStatus.ulReturn * (getAvgBytesPerSecond()/1000));
522 return nrbytes;;
523 }
524 mciError(rc);
525 return 0xFFFFFFFF;
526}
527/******************************************************************************/
528/******************************************************************************/
529BOOL DartWaveIn::queryFormat(ULONG formatTag, ULONG nChannels,
530 ULONG nSamplesPerSec, ULONG wBitsPerSample)
531{
532 MCI_WAVE_GETDEVCAPS_PARMS mciAudioCaps;
533 MCI_GENERIC_PARMS GenericParms;
534 MCI_OPEN_PARMS mciOpenParms; /* open parms for MCI_OPEN */
535 int i, freqbits = 0;
536 ULONG rc, DeviceId;
537 BOOL winrc;
538
539 dprintf(("DartWaveIn::queryFormat %x srate=%d, nchan=%d, bps=%d", formatTag, nSamplesPerSec, nChannels, wBitsPerSample));
540
541 memset(&mciOpenParms, /* Object to fill with zeros. */
542 0, /* Value to place into the object. */
543 sizeof( mciOpenParms ) ); /* How many zero's to use. */
544
545 mciOpenParms.pszDeviceType = (PSZ)MCI_DEVTYPE_WAVEFORM_AUDIO;
546
547 rc = mciSendCommand( (USHORT) 0,
548 MCI_OPEN,
549 MCI_WAIT | MCI_OPEN_TYPE_ID,
550 (PVOID) &mciOpenParms,
551 0);
552 if((rc & 0xFFFF) != MCIERR_SUCCESS) {
553 mciError(rc);
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_RECORD;
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 DartWaveIn::mciError(ULONG ulError)
585{
586#ifdef DEBUG
587 char szError[256] = "";
588
589 mciGetErrorString(ulError, szError, sizeof(szError));
590 dprintf(("WINMM: DartWaveIn: %s\n", szError));
591#endif
592}
593//******************************************************************************
594//******************************************************************************
595BOOL DartWaveIn::find(DartWaveIn *dwave)
596{
597 DartWaveIn *curwave = wavein;
598
599 while(curwave) {
600 if(dwave == curwave) {
601 return(TRUE);
602 }
603 curwave = curwave->next;
604 }
605
606#ifdef DEBUG
607// WriteLog("WINMM:DartWaveIn not found!\n");
608#endif
609 return(FALSE);
610}
611/******************************************************************************/
612//Simple implementation of recording. We fill up buffers queued by the application
613//until we run out of data or buffers. If we run out of buffers, the recorded data
614//is thrown away. We will continue when when the applications adds more buffers.
615/******************************************************************************/
616void DartWaveIn::handler(ULONG ulStatus, PMCI_MIX_BUFFER pBuffer, ULONG ulFlags)
617{
618 ULONG buflength, bufpos, bytestocopy;
619 WAVEHDR *whdr, *prevhdr = NULL;
620
621#ifdef DEBUG1
622 dprintf(("WINMM: DartWaveIn handler %x\n", pBuffer));
623#endif
624 if(ulFlags == MIX_STREAM_ERROR) {
625 if(ulStatus == ERROR_DEVICE_OVERRUN) {
626 dprintf(("WINMM: ERROR: WaveIn handler ERROR_DEVICE_OVERRUN!\n"));
627 if(State == STATE_RECORDING) {
628 fOverrun = TRUE;
629 stop(); //out of buffers, so pause playback
630 }
631 return;
632 }
633 dprintf(("WINMM: WaveIn handler, Unknown error %X\n", ulStatus));
634 return;
635 }
636 wmutex->enter(VMUTEX_WAIT_FOREVER);
637
638 whdr = wavehdr;
639 if(whdr == NULL) {
640 wmutex->leave();
641 //last buffer recorded -> no new ones -> overrun
642 //Windows doesn't care -> just continue
643 dprintf(("WINMM: WARNING: WaveIn handler OVERRUN!\n"));
644 return;
645 }
646
647#ifdef DEBUG1
648 dprintf(("WINMM: DartWaveIn handler cur (%d,%d), fill (%d,%d)\n", curPlayBuf, curPlayPos, curFillBuf, curFillPos));
649#endif
650
651 buflength = pBuffer->ulBufferLength;
652 bufpos = 0;
653 while(buflength) {
654 if(wavehdr) {
655 bytestocopy = min(buflength, wavehdr->dwBufferLength - wavehdr->dwBytesRecorded);
656 if(bytestocopy) {
657 memcpy(wavehdr->lpData + wavehdr->dwBytesRecorded, (char *)pBuffer->pBuffer + bufpos, bytestocopy);
658 }
659 else DebugInt3(); //should never happen
660
661 bufpos += bytestocopy;
662 wavehdr->dwBytesRecorded += bytestocopy;
663 buflength -= bytestocopy;
664
665 if(wavehdr->dwBytesRecorded == wavehdr->dwBufferLength) {
666#ifdef DEBUG1
667 dprintf(("WINMM: DartWaveIn handler buf %X done\n", whdr));
668#endif
669 whdr->dwFlags |= WHDR_DONE;
670 whdr->dwFlags &= ~WHDR_INQUEUE;
671
672 wavehdr = whdr->lpNext;
673 whdr->lpNext = NULL;
674 wmutex->leave();
675
676 if(mthdCallback) {
677 callback((ULONG)this, WIM_DATA, dwInstance, (ULONG)whdr, 0);
678 }
679 else
680 if(hwndCallback) {
681 dprintf(("Callback (msg) for buffer %x", whdr));
682 PostMessageA(hwndCallback, WIM_DATA, (WPARAM)this, (ULONG)whdr);
683 }
684 wmutex->enter(VMUTEX_WAIT_FOREVER);
685 }
686 }
687 else break;
688 }
689 wmutex->leave();
690
691 //Transfer buffer to DART
692 // MCI_MIXSETUP_PARMS->pMixWrite does alter FS: selector!
693 USHORT selTIB = GetFS(); // save current FS selector
694 MixSetupParms->pmixWrite(MixSetupParms->ulMixHandle, pBuffer, 1);
695 SetFS(selTIB); // switch back to the saved FS selector
696}
697/******************************************************************************/
698/******************************************************************************/
699LONG APIENTRY WaveInHandler(ULONG ulStatus,
700 PMCI_MIX_BUFFER pBuffer,
701 ULONG ulFlags)
702{
703 // PTIB ptib;
704 // PPIB ppib;
705 // DosGetInfoBlocks(&ptib, &ppib);
706 // dprintf(("WaveInHandler: thread %d prio %X", ptib->tib_ptib2->tib2_ultid, ptib->tib_ptib2->tib2_ulpri));
707
708 DartWaveIn *dwave;
709
710 if(pBuffer && pBuffer->ulUserParm)
711 {
712 dwave = (DartWaveIn *)pBuffer->ulUserParm;
713 dwave->handler(ulStatus, pBuffer, ulFlags);
714 }
715 return(TRUE);
716}
717/******************************************************************************/
718/******************************************************************************/
719DartWaveIn *DartWaveIn::wavein = NULL;
720
Note: See TracBrowser for help on using the repository browser.