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

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

underrun changes (pause & restart properly)

File size: 16.3 KB
Line 
1/* $Id: waveout.cpp,v 1.19 2001-03-21 12:33:22 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 "dwaveout.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 if(fdwOpen == CALLBACK_WINDOW) {
70 *phwo = (HWAVEOUT)new DartWaveOut(pwfx, (HWND)dwCallback);
71 }
72 else
73 if(fdwOpen == CALLBACK_FUNCTION)
74 {
75 *phwo = (HWAVEOUT)new DartWaveOut(pwfx, dwCallback, dwInstance);
76 }
77 else *phwo = (HWAVEOUT)new DartWaveOut(pwfx);
78
79 if(*phwo == NULL) {
80 return(MMSYSERR_NODRIVER);
81 }
82
83 rc = ((DartWaveOut *)*phwo)->getError();
84 if(rc != MMSYSERR_NOERROR) {
85 delete (DartWaveOut *)*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 DartWaveOut *dwave = (DartWaveOut *)hwo;
98
99 if(DartWaveOut::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 DartWaveOut *dwave = (DartWaveOut *)hwaveout;
121
122 if(DartWaveOut::find(dwave) == TRUE)
123 return(dwave->reset());
124 else return(MMSYSERR_INVALHANDLE);
125}
126/******************************************************************************/
127/******************************************************************************/
128ODINFUNCTION1(MMRESULT, waveOutBreakLoop,
129 HWAVEOUT, hwaveout)
130{
131 DartWaveOut *dwave = (DartWaveOut *)hwaveout;
132
133 dprintf(("WINMM:waveOutBreakLoop (implemented as reset) %X\n", hwaveout));
134 if(DartWaveOut::find(dwave) == TRUE)
135 return(dwave->reset());
136 else return(MMSYSERR_INVALHANDLE);
137}
138/******************************************************************************/
139/******************************************************************************/
140ODINFUNCTION1(MMRESULT, waveOutClose,
141 HWAVEOUT, hwaveout)
142{
143 DartWaveOut *dwave = (DartWaveOut *)hwaveout;
144
145 if(DartWaveOut::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 DartWaveOut *dwave = (DartWaveOut *)hwaveout;
161
162 if(DartWaveOut::find(dwave) == TRUE)
163 return(dwave->pause());
164 else return(MMSYSERR_INVALHANDLE);
165}
166/******************************************************************************/
167/******************************************************************************/
168ODINFUNCTION1(MMRESULT, waveOutRestart,
169 HWAVEOUT, hwaveout)
170{
171 DartWaveOut *dwave = (DartWaveOut *)hwaveout;
172
173 if(DartWaveOut::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 DartWaveOut *dwave = (DartWaveOut *)hwo;
185
186 if(DartWaveOut::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 DartWaveOut *dwave = (DartWaveOut *)hwo;
206
207 if(DartWaveOut::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 DartWaveOut *dwave = (DartWaveOut *)hwo;
226
227 if(pmmt == NULL)
228 return MMSYSERR_INVALPARAM;
229
230 if(DartWaveOut::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(DartWaveOut::getNumDevices() == 0) {
281 memset(pwoc, 0, sizeof(*pwoc));
282 return MMSYSERR_NODRIVER;
283 }
284
285 // we have to fill in this thing
286 pwoc->wMid = 0; /* manufacturer ID */
287 pwoc->wPid = 0; /* product ID */
288 pwoc->vDriverVersion = 0x0001; /* version of the driver */
289 strcpy( pwoc->szPname, "OS/2 DART Wave Out" ); /* product name */
290 pwoc->dwFormats = WAVE_FORMAT_1M08 | WAVE_FORMAT_1S08 |
291 WAVE_FORMAT_1M16 | WAVE_FORMAT_1S16 |
292 WAVE_FORMAT_2M08 | WAVE_FORMAT_2S08 |
293 WAVE_FORMAT_2M16 | WAVE_FORMAT_2S16 |
294 WAVE_FORMAT_4M08 | WAVE_FORMAT_4S08 |
295 WAVE_FORMAT_4M16 | WAVE_FORMAT_4S16;
296
297 pwoc->wChannels = 2; /* number of sources supported */
298 pwoc->wReserved1 = 0; /* packing */
299 pwoc->dwSupport = WAVECAPS_LRVOLUME | WAVECAPS_VOLUME;
300
301 return MMSYSERR_NOERROR;
302}
303/******************************************************************************/
304/******************************************************************************/
305ODINFUNCTION3(MMRESULT, waveOutGetDevCapsW,
306 UINT, uDeviceID,
307 LPWAVEOUTCAPSW, pwoc,
308 UINT, cbwoc)
309{
310 if(DartWaveOut::getNumDevices() == 0) {
311 memset(pwoc, 0, sizeof(*pwoc));
312 return MMSYSERR_NODRIVER;
313 }
314 // we have to fill in this thing
315 pwoc->wMid = 0; /* manufacturer ID */
316 pwoc->wPid = 0; /* product ID */
317 pwoc->vDriverVersion = 0x0001; /* version of the driver */
318 lstrcpyW(pwoc->szPname, (LPCWSTR)L"OS/2 DART Wave Out"); /* product name */
319 pwoc->dwFormats = WAVE_FORMAT_1M08 | WAVE_FORMAT_1S08 |
320 WAVE_FORMAT_1M16 | WAVE_FORMAT_1S16 |
321 WAVE_FORMAT_2M08 | WAVE_FORMAT_2S08 |
322 WAVE_FORMAT_2M16 | WAVE_FORMAT_2S16 |
323 WAVE_FORMAT_4M08 | WAVE_FORMAT_4S08 |
324 WAVE_FORMAT_4M16 | WAVE_FORMAT_4S16;
325
326 pwoc->wChannels = 2; /* number of sources supported */
327 pwoc->wReserved1 = 0; /* packing */
328 pwoc->dwSupport = WAVECAPS_LRVOLUME | WAVECAPS_VOLUME;
329
330 return MMSYSERR_NOERROR;
331}
332/******************************************************************************/
333/******************************************************************************/
334ODINFUNCTION0(UINT, waveOutGetNumDevs)
335{
336 return DartWaveOut::getNumDevices();
337}
338/******************************************************************************/
339/******************************************************************************/
340ODINFUNCTION3(MMRESULT, waveOutGetErrorTextA,
341 MMRESULT, wError,
342 LPSTR, lpText,
343 UINT, cchText)
344{
345 char * theMsg = getWinmmMsg( wError );
346 if(theMsg) {
347 strncpy( lpText, theMsg, cchText );
348 }
349 else
350 {
351 char errMsg[100];
352 sprintf( errMsg, "Unknown error number %d", wError );
353 strncpy( lpText, errMsg, cchText );
354 }
355 return MMSYSERR_NOERROR;
356}
357/******************************************************************************/
358/******************************************************************************/
359ODINFUNCTION3(MMRESULT, waveOutGetErrorTextW,
360 MMRESULT, wError,
361 LPWSTR, lpText,
362 UINT, cchText)
363{
364 char * theMsg = getWinmmMsg( wError );
365 if(theMsg) {
366 AsciiToUnicode( theMsg, lpText );
367 }
368 else
369 {
370 char errMsg[100];
371 sprintf( errMsg, "Unknown error number %d", wError );
372 AsciiToUnicode( errMsg, lpText );
373 }
374 return MMSYSERR_NOERROR;
375}
376/******************************************************************************/
377/******************************************************************************/
378ODINFUNCTION2(MMRESULT, waveOutGetID,
379 HWAVEOUT, hwo,
380 LPUINT, puDeviceID)
381{
382 DartWaveOut *dwave = (DartWaveOut *)hwo;
383 if(DartWaveOut::find(dwave) == TRUE)
384 {
385 *puDeviceID = 1;
386 return MMSYSERR_NOERROR;
387 }
388 else return(MMSYSERR_INVALHANDLE);
389}
390/******************************************************************************/
391/******************************************************************************/
392ODINFUNCTION2(MMRESULT, waveOutGetPitch,
393 HWAVEOUT, hwo,
394 LPDWORD, pdwPitch)
395{
396 DartWaveOut *dwave = (DartWaveOut *)hwo;
397 if(DartWaveOut::find(dwave) == TRUE)
398 return MMSYSERR_NOTSUPPORTED;
399 else return(MMSYSERR_INVALHANDLE);
400}
401/******************************************************************************/
402/******************************************************************************/
403ODINFUNCTION2(MMRESULT, waveOutSetPitch,
404 HWAVEOUT, hwo,
405 DWORD, dwPitch)
406{
407 DartWaveOut *dwave = (DartWaveOut *)hwo;
408 if(DartWaveOut::find(dwave) == TRUE)
409 return MMSYSERR_NOTSUPPORTED;
410 else return(MMSYSERR_INVALHANDLE);
411}
412/******************************************************************************/
413/******************************************************************************/
414ODINFUNCTION2(MMRESULT, waveOutGetVolume,
415 HWAVEOUT, hwo,
416 LPDWORD, pdwVolume)
417{
418 DartWaveOut *dwave = (DartWaveOut *)hwo;
419 if(DartWaveOut::find(dwave) == TRUE)
420 {
421 if(pdwVolume!=NULL)
422 *pdwVolume=dwave->getVolume();
423 return MMSYSERR_NOERROR;
424 }
425 else
426 return MMSYSERR_NOERROR;
427// return(MMSYSERR_INVALHANDLE);
428}
429/******************************************************************************/
430/******************************************************************************/
431ODINFUNCTION2(MMRESULT, waveOutSetVolume,
432 HWAVEOUT, hwo,
433 DWORD, dwVolume)
434{
435 DartWaveOut *dwave = (DartWaveOut *)hwo;
436 if(DartWaveOut::find(dwave) == TRUE)
437 {
438 return(dwave->setVolume(dwVolume));
439 }
440 if(hwo == NULL) {
441 DartWaveOut::setDefaultVolume(dwVolume);
442 }
443 return MMSYSERR_NOERROR;
444// return(MMSYSERR_INVALHANDLE);
445}
446/******************************************************************************/
447/******************************************************************************/
448ODINFUNCTION2(MMRESULT, waveOutGetPlaybackRate,
449 HWAVEOUT, hwo,
450 LPDWORD, pdwRate)
451{
452 DartWaveOut *dwave = (DartWaveOut *)hwo;
453 if(DartWaveOut::find(dwave) == TRUE)
454 {
455 return MMSYSERR_NOTSUPPORTED;
456 }
457 else return(MMSYSERR_INVALHANDLE);
458}
459/******************************************************************************/
460/******************************************************************************/
461ODINFUNCTION2(MMRESULT, waveOutSetPlaybackRate,
462 HWAVEOUT, hwo,
463 DWORD, dwRate)
464{
465 DartWaveOut *dwave = (DartWaveOut *)hwo;
466 if(DartWaveOut::find(dwave) == TRUE)
467 {
468 return MMSYSERR_NOTSUPPORTED;
469 }
470 else return(MMSYSERR_INVALHANDLE);
471}
472/******************************************************************************/
473/******************************************************************************/
474ODINFUNCTION4(MMRESULT, waveOutMessage,
475 HWAVEOUT, hwo,
476 UINT, uMsg,
477 DWORD, dw1,
478 DWORD, dw2)
479{
480 DartWaveOut *dwave = (DartWaveOut *)hwo;
481 if(DartWaveOut::find(dwave) == TRUE)
482 {
483 return MMSYSERR_NOTSUPPORTED;
484 }
485 else
486 return(MMSYSERR_INVALHANDLE);
487}
488/******************************************************************************/
489/******************************************************************************/
490
491
Note: See TracBrowser for help on using the repository browser.