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

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

WinPostMsg calls changed into PostMessageA

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