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

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

Rewrite for DirectAudio interface

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