source: trunk/src/winmm/waveout.cpp@ 7196

Last change on this file since 7196 was 7196, checked in by sandervl, 24 years ago

dynamically load MDM.DLL

File size: 16.5 KB
Line 
1/* $Id: waveout.cpp,v 1.22 2001-10-24 22:47:42 sandervl Exp $ */
2//#undef DEBUG
3/*
4 * Wave out MM apis
5 *
6 * Copyright 1998-2000 Sander van Leeuwen (sandervl@xs4all.nl)
7 *
8 * waveOutGetPosition partly based on Wine code (dll\winmm\wineoss\audio.c)
9 * Copyright 1994 Martin Ayotte
10 *
11 * Project Odin Software License can be found in LICENSE.TXT
12 *
13 */
14
15
16/****************************************************************************
17 * Includes *
18 ****************************************************************************/
19
20#include <os2win.h>
21#include <mmsystem.h>
22#include <odinwrap.h>
23
24#include <string.h>
25#include <stdio.h>
26#include <string.h>
27#include <unicode.h>
28
29#include "waveoutdart.h"
30#include "waveoutdaud.h"
31#include "misc.h"
32#include "winmm.h"
33#include "initwinmm.h"
34
35#define DBG_LOCALLOG DBG_waveout
36#include "dbglocal.h"
37
38ODINDEBUGCHANNEL(WINMM-WAVEOUT)
39
40
41/******************************************************************************/
42/******************************************************************************/
43
44//@@@PH 1999/12/28 this function needs the win32 tib FS selector for callback purposes
45// therefore, one cannot use ODINFUNCTION macro wrappers! The xxxFS
46// macro passes in USHORT selFS as first parameter.
47ODINFUNCTION6(MMRESULT, waveOutOpen,
48 LPHWAVEOUT, phwo,
49 UINT, uDeviceID,
50 const LPWAVEFORMATEX, pwfx,
51 DWORD, dwCallback,
52 DWORD, dwInstance,
53 DWORD, fdwOpen)
54{
55 MMRESULT rc;
56
57 if(fMMPMAvailable == FALSE) return MMSYSERR_NODRIVER;
58
59 if(pwfx == NULL)
60 return(WAVERR_BADFORMAT);
61
62 if(fdwOpen == WAVE_FORMAT_QUERY)
63 {
64 if(DartWaveOut::queryFormat(pwfx->wFormatTag, pwfx->nChannels, pwfx->nSamplesPerSec,
65 pwfx->wBitsPerSample) == TRUE) {
66 return(MMSYSERR_NOERROR);
67 }
68 else return(WAVERR_BADFORMAT);
69 }
70
71 if(phwo == NULL)
72 return(MMSYSERR_INVALPARAM);
73
74 if(DAudioWaveOut::isDirectAudioAvailable()) {
75 *phwo = (HWAVEOUT)new DAudioWaveOut(pwfx, fdwOpen, dwCallback, dwInstance);
76 }
77 else *phwo = (HWAVEOUT)new DartWaveOut(pwfx, fdwOpen, dwCallback, dwInstance);
78
79 if(*phwo == NULL) {
80 return(MMSYSERR_NODRIVER);
81 }
82
83 rc = ((WaveOut *)*phwo)->getError();
84 if(rc != MMSYSERR_NOERROR) {
85 delete (WaveOut *)*phwo;
86 return(rc);
87 }
88 return(MMSYSERR_NOERROR);
89}
90/******************************************************************************/
91/******************************************************************************/
92ODINFUNCTION3(MMRESULT, waveOutWrite,
93 HWAVEOUT, hwo,
94 LPWAVEHDR, pwh,
95 UINT, cbwh)
96{
97 WaveOut *dwave = (WaveOut *)hwo;
98
99 if(WaveOut::find(dwave) == TRUE)
100 {
101 if(!(pwh->dwFlags & WHDR_PREPARED) || pwh->lpData == NULL)
102 return WAVERR_UNPREPARED;
103
104 if(pwh->dwFlags & WHDR_INQUEUE)
105 return WAVERR_STILLPLAYING;
106
107 pwh->dwFlags |= WHDR_INQUEUE;
108 pwh->dwFlags &= ~WHDR_DONE;
109
110 dprintf(("waveOutWrite ptr %x size %d %x %x %x %x %x %x", pwh->lpData, pwh->dwBufferLength, pwh->dwBytesRecorded, pwh->dwUser, pwh->dwFlags, pwh->dwLoops, pwh->lpNext, pwh->reserved));
111 return(dwave->write(pwh, cbwh));
112 }
113 else return(MMSYSERR_INVALHANDLE);
114}
115/******************************************************************************/
116/******************************************************************************/
117ODINFUNCTION1(MMRESULT, waveOutReset,
118 HWAVEOUT, hwaveout)
119{
120 WaveOut *dwave = (WaveOut *)hwaveout;
121
122 if(WaveOut::find(dwave) == TRUE)
123 return(dwave->reset());
124 else return(MMSYSERR_INVALHANDLE);
125}
126/******************************************************************************/
127/******************************************************************************/
128ODINFUNCTION1(MMRESULT, waveOutBreakLoop,
129 HWAVEOUT, hwaveout)
130{
131 WaveOut *dwave = (WaveOut *)hwaveout;
132
133 dprintf(("WINMM:waveOutBreakLoop (implemented as reset) %X\n", hwaveout));
134 if(WaveOut::find(dwave) == TRUE)
135 return(dwave->reset());
136 else return(MMSYSERR_INVALHANDLE);
137}
138/******************************************************************************/
139/******************************************************************************/
140ODINFUNCTION1(MMRESULT, waveOutClose,
141 HWAVEOUT, hwaveout)
142{
143 WaveOut *dwave = (WaveOut *)hwaveout;
144
145 if(WaveOut::find(dwave) == TRUE)
146 {
147 if(dwave->getState() == STATE_PLAYING)
148 return(WAVERR_STILLPLAYING);
149
150 delete dwave;
151 return(MMSYSERR_NOERROR);
152 }
153 else return(MMSYSERR_INVALHANDLE);
154}
155/******************************************************************************/
156/******************************************************************************/
157ODINFUNCTION1(MMRESULT, waveOutPause,
158 HWAVEOUT, hwaveout)
159{
160 WaveOut *dwave = (WaveOut *)hwaveout;
161
162 if(WaveOut::find(dwave) == TRUE)
163 return(dwave->pause());
164 else return(MMSYSERR_INVALHANDLE);
165}
166/******************************************************************************/
167/******************************************************************************/
168ODINFUNCTION1(MMRESULT, waveOutRestart,
169 HWAVEOUT, hwaveout)
170{
171 WaveOut *dwave = (WaveOut *)hwaveout;
172
173 if(WaveOut::find(dwave) == TRUE)
174 return(dwave->restart());
175 else return(MMSYSERR_INVALHANDLE);
176}
177/******************************************************************************/
178/******************************************************************************/
179ODINFUNCTION3(MMRESULT, waveOutPrepareHeader,
180 HWAVEOUT, hwo,
181 LPWAVEHDR, pwh,
182 UINT, cbwh)
183{
184 WaveOut *dwave = (WaveOut *)hwo;
185
186 if(WaveOut::find(dwave) == TRUE)
187 {
188 if(pwh->dwFlags & WHDR_INQUEUE)
189 return WAVERR_STILLPLAYING;
190
191 pwh->dwFlags |= WHDR_PREPARED;
192 pwh->dwFlags &= ~WHDR_DONE;
193 pwh->lpNext = NULL;
194 return(MMSYSERR_NOERROR);
195 }
196 else return(MMSYSERR_INVALHANDLE);
197}
198/******************************************************************************/
199/******************************************************************************/
200ODINFUNCTION3(MMRESULT, waveOutUnprepareHeader,
201 HWAVEOUT, hwo,
202 LPWAVEHDR, pwh,
203 UINT, cbwh)
204{
205 WaveOut *dwave = (WaveOut *)hwo;
206
207 if(WaveOut::find(dwave) == TRUE)
208 {
209 if(pwh->dwFlags & WHDR_INQUEUE)
210 return WAVERR_STILLPLAYING;
211
212 pwh->dwFlags &= ~WHDR_PREPARED;
213 pwh->dwFlags |= WHDR_DONE;
214 return(MMSYSERR_NOERROR);
215 }
216 else return(MMSYSERR_INVALHANDLE);
217}
218/******************************************************************************/
219/******************************************************************************/
220ODINFUNCTION3(MMRESULT, waveOutGetPosition,
221 HWAVEOUT, hwo,
222 LPMMTIME, pmmt,
223 UINT, cbmmt)
224{
225 WaveOut *dwave = (WaveOut *)hwo;
226
227 if(pmmt == NULL)
228 return MMSYSERR_INVALPARAM;
229
230 if(WaveOut::find(dwave) == TRUE)
231 {
232 ULONG position;
233
234 position = dwave->getPosition();
235 if(position == -1) {
236 return MMSYSERR_HANDLEBUSY; //todo correct error value
237 }
238 switch (pmmt->wType) {
239 case TIME_BYTES:
240 pmmt->u.cb = position;
241 dprintf2(("WINMM:waveOutGetPosition: TIME_BYTES %d (%x)", position, GetCurrentTime()));
242 break;
243 case TIME_SAMPLES:
244 pmmt->u.sample = position * 8 / dwave->getBitsPerSample();
245 dprintf2(("WINMM:waveOutGetPosition: TIME_SAMPLES %d", pmmt->u.sample));
246 break;
247 case TIME_SMPTE:
248 {
249 ULONG timeval = position / (dwave->getAvgBytesPerSecond() / 1000);
250 pmmt->u.smpte.hour = timeval / 108000;
251 timeval -= pmmt->u.smpte.hour * 108000;
252 pmmt->u.smpte.min = timeval / 1800;
253 timeval -= pmmt->u.smpte.min * 1800;
254 pmmt->u.smpte.sec = timeval / 30;
255 timeval -= pmmt->u.smpte.sec * 30;
256 pmmt->u.smpte.frame = timeval;
257 pmmt->u.smpte.fps = 30;
258 dprintf2(("WINMM:waveOutGetPosition: TIME_SAMPLES %d", position));
259 break;
260 }
261 default:
262 dprintf(("waveOutGetPosition: Format %d not supported ! use TIME_MS !\n", pmmt->wType));
263 pmmt->wType = TIME_MS;
264 case TIME_MS:
265 pmmt->u.ms = position / (dwave->getAvgBytesPerSecond() / 1000);
266 dprintf2(("WINMM:waveOutGetPosition: TIME_MS pos=%d ms=%d time=%d", position, pmmt->u.ms, GetCurrentTime()));
267 break;
268 }
269 return MMSYSERR_NOERROR;
270 }
271 else return(MMSYSERR_INVALHANDLE);
272}
273/******************************************************************************/
274/******************************************************************************/
275ODINFUNCTION3(MMRESULT, waveOutGetDevCapsA,
276 UINT, uDeviceID,
277 LPWAVEOUTCAPSA, pwoc,
278 UINT, cbwoc)
279{
280 if(fMMPMAvailable == FALSE) return MMSYSERR_NODRIVER;
281
282 if(WaveOut::getNumDevices() == 0) {
283 memset(pwoc, 0, sizeof(*pwoc));
284 return MMSYSERR_NODRIVER;
285 }
286
287 // we have to fill in this thing
288 pwoc->wMid = 0; /* manufacturer ID */
289 pwoc->wPid = 0; /* product ID */
290 pwoc->vDriverVersion = 0x0001; /* version of the driver */
291 strcpy( pwoc->szPname, "OS/2 DART Wave Out" ); /* product name */
292 pwoc->dwFormats = WAVE_FORMAT_1M08 | WAVE_FORMAT_1S08 |
293 WAVE_FORMAT_1M16 | WAVE_FORMAT_1S16 |
294 WAVE_FORMAT_2M08 | WAVE_FORMAT_2S08 |
295 WAVE_FORMAT_2M16 | WAVE_FORMAT_2S16 |
296 WAVE_FORMAT_4M08 | WAVE_FORMAT_4S08 |
297 WAVE_FORMAT_4M16 | WAVE_FORMAT_4S16;
298
299 pwoc->wChannels = 2; /* number of sources supported */
300 pwoc->wReserved1 = 0; /* packing */
301 pwoc->dwSupport = WAVECAPS_LRVOLUME | WAVECAPS_VOLUME;
302
303 return MMSYSERR_NOERROR;
304}
305/******************************************************************************/
306/******************************************************************************/
307ODINFUNCTION3(MMRESULT, waveOutGetDevCapsW,
308 UINT, uDeviceID,
309 LPWAVEOUTCAPSW, pwoc,
310 UINT, cbwoc)
311{
312 if(fMMPMAvailable == FALSE) return MMSYSERR_NODRIVER;
313
314 if(WaveOut::getNumDevices() == 0) {
315 memset(pwoc, 0, sizeof(*pwoc));
316 return MMSYSERR_NODRIVER;
317 }
318 // we have to fill in this thing
319 pwoc->wMid = 0; /* manufacturer ID */
320 pwoc->wPid = 0; /* product ID */
321 pwoc->vDriverVersion = 0x0001; /* version of the driver */
322 lstrcpyW(pwoc->szPname, (LPCWSTR)L"OS/2 DART Wave Out"); /* product name */
323 pwoc->dwFormats = WAVE_FORMAT_1M08 | WAVE_FORMAT_1S08 |
324 WAVE_FORMAT_1M16 | WAVE_FORMAT_1S16 |
325 WAVE_FORMAT_2M08 | WAVE_FORMAT_2S08 |
326 WAVE_FORMAT_2M16 | WAVE_FORMAT_2S16 |
327 WAVE_FORMAT_4M08 | WAVE_FORMAT_4S08 |
328 WAVE_FORMAT_4M16 | WAVE_FORMAT_4S16;
329
330 pwoc->wChannels = 2; /* number of sources supported */
331 pwoc->wReserved1 = 0; /* packing */
332 pwoc->dwSupport = WAVECAPS_LRVOLUME | WAVECAPS_VOLUME;
333
334 return MMSYSERR_NOERROR;
335}
336/******************************************************************************/
337/******************************************************************************/
338ODINFUNCTION0(UINT, waveOutGetNumDevs)
339{
340 if(fMMPMAvailable == FALSE) return 0;
341
342 return WaveOut::getNumDevices();
343}
344/******************************************************************************/
345/******************************************************************************/
346ODINFUNCTION3(MMRESULT, waveOutGetErrorTextA,
347 MMRESULT, wError,
348 LPSTR, lpText,
349 UINT, cchText)
350{
351 char * theMsg = getWinmmMsg( wError );
352 if(theMsg) {
353 strncpy( lpText, theMsg, cchText );
354 }
355 else
356 {
357 char errMsg[100];
358 sprintf( errMsg, "Unknown error number %d", wError );
359 strncpy( lpText, errMsg, cchText );
360 }
361 return MMSYSERR_NOERROR;
362}
363/******************************************************************************/
364/******************************************************************************/
365ODINFUNCTION3(MMRESULT, waveOutGetErrorTextW,
366 MMRESULT, wError,
367 LPWSTR, lpText,
368 UINT, cchText)
369{
370 char * theMsg = getWinmmMsg( wError );
371 if(theMsg) {
372 AsciiToUnicode( theMsg, lpText );
373 }
374 else
375 {
376 char errMsg[100];
377 sprintf( errMsg, "Unknown error number %d", wError );
378 AsciiToUnicode( errMsg, lpText );
379 }
380 return MMSYSERR_NOERROR;
381}
382/******************************************************************************/
383/******************************************************************************/
384ODINFUNCTION2(MMRESULT, waveOutGetID,
385 HWAVEOUT, hwo,
386 LPUINT, puDeviceID)
387{
388 WaveOut *dwave = (WaveOut *)hwo;
389 if(WaveOut::find(dwave) == TRUE)
390 {
391 *puDeviceID = 1;
392 return MMSYSERR_NOERROR;
393 }
394 else return(MMSYSERR_INVALHANDLE);
395}
396/******************************************************************************/
397/******************************************************************************/
398ODINFUNCTION2(MMRESULT, waveOutGetPitch,
399 HWAVEOUT, hwo,
400 LPDWORD, pdwPitch)
401{
402 WaveOut *dwave = (WaveOut *)hwo;
403 if(WaveOut::find(dwave) == TRUE)
404 return MMSYSERR_NOTSUPPORTED;
405 else return(MMSYSERR_INVALHANDLE);
406}
407/******************************************************************************/
408/******************************************************************************/
409ODINFUNCTION2(MMRESULT, waveOutSetPitch,
410 HWAVEOUT, hwo,
411 DWORD, dwPitch)
412{
413 WaveOut *dwave = (WaveOut *)hwo;
414 if(WaveOut::find(dwave) == TRUE)
415 return MMSYSERR_NOTSUPPORTED;
416 else return(MMSYSERR_INVALHANDLE);
417}
418/******************************************************************************/
419/******************************************************************************/
420ODINFUNCTION2(MMRESULT, waveOutGetVolume,
421 HWAVEOUT, hwo,
422 LPDWORD, pdwVolume)
423{
424 WaveOut *dwave = (WaveOut *)hwo;
425 if(WaveOut::find(dwave) == TRUE)
426 {
427 if(pdwVolume!=NULL)
428 *pdwVolume=dwave->getVolume();
429 return MMSYSERR_NOERROR;
430 }
431 else
432 return MMSYSERR_NOERROR;
433// return(MMSYSERR_INVALHANDLE);
434}
435/******************************************************************************/
436/******************************************************************************/
437ODINFUNCTION2(MMRESULT, waveOutSetVolume,
438 HWAVEOUT, hwo,
439 DWORD, dwVolume)
440{
441 WaveOut *dwave = (WaveOut *)hwo;
442 if(WaveOut::find(dwave) == TRUE)
443 {
444 return(dwave->setVolume(dwVolume));
445 }
446 if(hwo == NULL) {
447 WaveOut::setDefaultVolume(dwVolume);
448 }
449 return MMSYSERR_NOERROR;
450// return(MMSYSERR_INVALHANDLE);
451}
452/******************************************************************************/
453/******************************************************************************/
454ODINFUNCTION2(MMRESULT, waveOutGetPlaybackRate,
455 HWAVEOUT, hwo,
456 LPDWORD, pdwRate)
457{
458 WaveOut *dwave = (WaveOut *)hwo;
459 if(WaveOut::find(dwave) == TRUE)
460 {
461 return MMSYSERR_NOTSUPPORTED;
462 }
463 else return(MMSYSERR_INVALHANDLE);
464}
465/******************************************************************************/
466/******************************************************************************/
467ODINFUNCTION2(MMRESULT, waveOutSetPlaybackRate,
468 HWAVEOUT, hwo,
469 DWORD, dwRate)
470{
471 WaveOut *dwave = (WaveOut *)hwo;
472 if(WaveOut::find(dwave) == TRUE)
473 {
474 return MMSYSERR_NOTSUPPORTED;
475 }
476 else return(MMSYSERR_INVALHANDLE);
477}
478/******************************************************************************/
479/******************************************************************************/
480ODINFUNCTION4(MMRESULT, waveOutMessage,
481 HWAVEOUT, hwo,
482 UINT, uMsg,
483 DWORD, dw1,
484 DWORD, dw2)
485{
486 WaveOut *dwave = (WaveOut *)hwo;
487 if(WaveOut::find(dwave) == TRUE)
488 {
489 return MMSYSERR_NOTSUPPORTED;
490 }
491 else
492 return(MMSYSERR_INVALHANDLE);
493}
494/******************************************************************************/
495/******************************************************************************/
496
497
Note: See TracBrowser for help on using the repository browser.