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

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

Enabled DirectAudio wave playback interface (if present)

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