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

Last change on this file since 2971 was 2971, checked in by sandervl, 25 years ago

fix for getPosition (overflow)

File size: 16.0 KB
Line 
1/* $Id: waveout.cpp,v 1.12 2000-03-02 14:51:16 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.
45ODINFUNCTION6FS(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(phwo == NULL)
59 return(MMSYSERR_INVALPARAM);
60
61 if(fdwOpen == WAVE_FORMAT_QUERY) {
62 if(DartWaveOut::queryFormat(pwfx->wFormatTag, pwfx->nChannels,
63 pwfx->nSamplesPerSec, pwfx->nBlockAlign) == TRUE) {
64 return(MMSYSERR_NOERROR);
65 }
66 else return(WAVERR_BADFORMAT);
67 }
68
69 if(fdwOpen == CALLBACK_WINDOW) {
70 *phwo = (HWAVEOUT)new DartWaveOut(pwfx, (HWND)dwCallback);
71 }
72 else
73 if(fdwOpen == CALLBACK_FUNCTION)
74 {
75 //@@@PH 1999/12/28 save valid FS: to win32 TIB
76 *phwo = (HWAVEOUT)new DartWaveOut(pwfx, dwCallback, dwInstance, selFS);
77 }
78 else *phwo = (HWAVEOUT)new DartWaveOut(pwfx);
79
80 if(*phwo == NULL) {
81 return(MMSYSERR_NODRIVER);
82 }
83
84 rc = ((DartWaveOut *)*phwo)->getError();
85 if(rc != MMSYSERR_NOERROR) {
86 delete (DartWaveOut *)*phwo;
87 return(rc);
88 }
89 return(MMSYSERR_NOERROR);
90}
91/******************************************************************************/
92/******************************************************************************/
93ODINFUNCTION3(MMRESULT, waveOutWrite,
94 HWAVEOUT, hwo,
95 LPWAVEHDR, pwh,
96 UINT, cbwh)
97{
98 DartWaveOut *dwave = (DartWaveOut *)hwo;
99
100 if(DartWaveOut::find(dwave) == TRUE)
101 {
102 if(!(pwh->dwFlags & WHDR_PREPARED) || pwh->lpData == NULL)
103 return WAVERR_UNPREPARED;
104
105 if(pwh->dwFlags & WHDR_INQUEUE)
106 return WAVERR_STILLPLAYING;
107
108 pwh->dwFlags |= WHDR_INQUEUE;
109 pwh->dwFlags &= ~WHDR_DONE;
110
111 dprintf(("waveOutWrite %x %d %x", pwh->lpData, pwh->dwBufferLength, pwh->dwFlags));
112 return(dwave->write(pwh, cbwh));
113 }
114 else return(MMSYSERR_INVALHANDLE);
115}
116/******************************************************************************/
117/******************************************************************************/
118ODINFUNCTION1(MMRESULT, waveOutReset,
119 HWAVEOUT, hwaveout)
120{
121 DartWaveOut *dwave = (DartWaveOut *)hwaveout;
122
123 if(DartWaveOut::find(dwave) == TRUE)
124 return(dwave->reset());
125 else return(MMSYSERR_INVALHANDLE);
126}
127/******************************************************************************/
128/******************************************************************************/
129ODINFUNCTION1(MMRESULT, waveOutBreakLoop,
130 HWAVEOUT, hwaveout)
131{
132 DartWaveOut *dwave = (DartWaveOut *)hwaveout;
133
134 dprintf(("WINMM:waveOutBreakLoop (implemented as reset) %X\n", hwaveout));
135 if(DartWaveOut::find(dwave) == TRUE)
136 return(dwave->reset());
137 else return(MMSYSERR_INVALHANDLE);
138}
139/******************************************************************************/
140/******************************************************************************/
141ODINFUNCTION1(MMRESULT, waveOutClose,
142 HWAVEOUT, hwaveout)
143{
144 DartWaveOut *dwave = (DartWaveOut *)hwaveout;
145
146 if(DartWaveOut::find(dwave) == TRUE)
147 {
148 if(dwave->getState() == STATE_PLAYING)
149 return(WAVERR_STILLPLAYING);
150
151 delete dwave;
152 return(MMSYSERR_NOERROR);
153 }
154 else return(MMSYSERR_INVALHANDLE);
155}
156/******************************************************************************/
157/******************************************************************************/
158ODINFUNCTION1(MMRESULT, waveOutPause,
159 HWAVEOUT, hwaveout)
160{
161 DartWaveOut *dwave = (DartWaveOut *)hwaveout;
162
163 if(DartWaveOut::find(dwave) == TRUE)
164 return(dwave->pause());
165 else return(MMSYSERR_INVALHANDLE);
166}
167/******************************************************************************/
168/******************************************************************************/
169ODINFUNCTION1(MMRESULT, waveOutRestart,
170 HWAVEOUT, hwaveout)
171{
172 DartWaveOut *dwave = (DartWaveOut *)hwaveout;
173
174 if(DartWaveOut::find(dwave) == TRUE)
175 return(dwave->restart());
176 else return(MMSYSERR_INVALHANDLE);
177}
178/******************************************************************************/
179/******************************************************************************/
180ODINFUNCTION3(MMRESULT, waveOutPrepareHeader,
181 HWAVEOUT, hwo,
182 LPWAVEHDR, pwh,
183 UINT, cbwh)
184{
185 DartWaveOut *dwave = (DartWaveOut *)hwo;
186
187 if(DartWaveOut::find(dwave) == TRUE)
188 {
189 if(pwh->dwFlags & WHDR_INQUEUE)
190 return WAVERR_STILLPLAYING;
191
192 pwh->dwFlags |= WHDR_PREPARED;
193 pwh->dwFlags &= ~WHDR_DONE;
194 pwh->lpNext = NULL;
195 return(MMSYSERR_NOERROR);
196 }
197 else return(MMSYSERR_INVALHANDLE);
198}
199/******************************************************************************/
200/******************************************************************************/
201ODINFUNCTION3(MMRESULT, waveOutUnprepareHeader,
202 HWAVEOUT, hwo,
203 LPWAVEHDR, pwh,
204 UINT, cbwh)
205{
206 DartWaveOut *dwave = (DartWaveOut *)hwo;
207
208 if(DartWaveOut::find(dwave) == TRUE)
209 {
210 if(pwh->dwFlags & WHDR_INQUEUE)
211 return WAVERR_STILLPLAYING;
212
213 pwh->dwFlags &= ~WHDR_PREPARED;
214 pwh->dwFlags |= WHDR_DONE;
215 return(MMSYSERR_NOERROR);
216 }
217 else return(MMSYSERR_INVALHANDLE);
218}
219/******************************************************************************/
220/******************************************************************************/
221ODINFUNCTION3(MMRESULT, waveOutGetPosition,
222 HWAVEOUT, hwo,
223 LPMMTIME, pmmt,
224 UINT, cbmmt)
225{
226 DartWaveOut *dwave = (DartWaveOut *)hwo;
227
228 if(pmmt == NULL)
229 return MMSYSERR_INVALPARAM;
230
231 if(DartWaveOut::find(dwave) == TRUE)
232 {
233 ULONG position;
234
235 position = dwave->getPosition();
236 if(position == -1) {
237 return MMSYSERR_HANDLEBUSY; //todo correct error value
238 }
239 switch (pmmt->wType) {
240 case TIME_BYTES:
241 pmmt->u.cb = position;
242 break;
243 case TIME_SAMPLES:
244 pmmt->u.sample = position * 8 / dwave->getBitsPerSample();
245 break;
246 case TIME_SMPTE:
247 {
248 ULONG timeval = position / (dwave->getAvgBytesPerSecond() / 1000);
249 pmmt->u.smpte.hour = timeval / 108000;
250 timeval -= pmmt->u.smpte.hour * 108000;
251 pmmt->u.smpte.min = timeval / 1800;
252 timeval -= pmmt->u.smpte.min * 1800;
253 pmmt->u.smpte.sec = timeval / 30;
254 timeval -= pmmt->u.smpte.sec * 30;
255 pmmt->u.smpte.frame = timeval;
256 pmmt->u.smpte.fps = 30;
257 break;
258 }
259 default:
260 dprintf(("waveOutGetPosition: Format %d not supported ! use TIME_MS !\n", pmmt->wType));
261 pmmt->wType = TIME_MS;
262 case TIME_MS:
263 pmmt->u.ms = position / (dwave->getAvgBytesPerSecond() / 1000);
264 dprintf(("WINMM:waveOutGetPosition: TIME_MS pos=%d ms=%d time=%d", position, pmmt->u.ms, GetCurrentTime()));
265 break;
266 }
267 return MMSYSERR_NOERROR;
268 }
269 else return(MMSYSERR_INVALHANDLE);
270}
271/******************************************************************************/
272/******************************************************************************/
273ODINFUNCTION3(MMRESULT, waveOutGetDevCapsA,
274 UINT, uDeviceID,
275 LPWAVEOUTCAPSA, pwoc,
276 UINT, cbwoc)
277{
278 if(DartWaveOut::getNumDevices() == 0) {
279 memset(pwoc, 0, sizeof(*pwoc));
280 return MMSYSERR_NODRIVER;
281 }
282
283 // we have to fill in this thing
284 pwoc->wMid = 0; /* manufacturer ID */
285 pwoc->wPid = 0; /* product ID */
286 pwoc->vDriverVersion = 0x0001; /* version of the driver */
287 strcpy( pwoc->szPname, "OS/2 DART Wave Out" ); /* product name */
288 pwoc->dwFormats = WAVE_FORMAT_1M08 | WAVE_FORMAT_1S08 |
289 WAVE_FORMAT_1M16 | WAVE_FORMAT_1S16 |
290 WAVE_FORMAT_2M08 | WAVE_FORMAT_2S08 |
291 WAVE_FORMAT_2M16 | WAVE_FORMAT_2S16 |
292 WAVE_FORMAT_4M08 | WAVE_FORMAT_4S08 |
293 WAVE_FORMAT_4M16 | WAVE_FORMAT_4S16;
294
295 pwoc->wChannels = 2; /* number of sources supported */
296 pwoc->wReserved1 = 0; /* packing */
297 pwoc->dwSupport = WAVECAPS_LRVOLUME | WAVECAPS_VOLUME;
298
299 return MMSYSERR_NOERROR;
300}
301/******************************************************************************/
302/******************************************************************************/
303ODINFUNCTION3(MMRESULT, waveOutGetDevCapsW,
304 UINT, uDeviceID,
305 LPWAVEOUTCAPSW, pwoc,
306 UINT, cbwoc)
307{
308 dprintf(("WINMM:waveOutGetDevCapsW"));
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 AsciiToUnicode( "OS/2 DART Wave Out", pwoc->szPname ); /* 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 else
441 return MMSYSERR_NOERROR;
442// return(MMSYSERR_INVALHANDLE);
443}
444/******************************************************************************/
445/******************************************************************************/
446ODINFUNCTION2(MMRESULT, waveOutGetPlaybackRate,
447 HWAVEOUT, hwo,
448 LPDWORD, pdwRate)
449{
450 DartWaveOut *dwave = (DartWaveOut *)hwo;
451 if(DartWaveOut::find(dwave) == TRUE)
452 {
453 return MMSYSERR_NOTSUPPORTED;
454 }
455 else return(MMSYSERR_INVALHANDLE);
456}
457/******************************************************************************/
458/******************************************************************************/
459ODINFUNCTION2(MMRESULT, waveOutSetPlaybackRate,
460 HWAVEOUT, hwo,
461 DWORD, dwRate)
462{
463 DartWaveOut *dwave = (DartWaveOut *)hwo;
464 if(DartWaveOut::find(dwave) == TRUE)
465 {
466 return MMSYSERR_NOTSUPPORTED;
467 }
468 else return(MMSYSERR_INVALHANDLE);
469}
470/******************************************************************************/
471/******************************************************************************/
472ODINFUNCTION4(MMRESULT, waveOutMessage,
473 HWAVEOUT, hwo,
474 UINT, uMsg,
475 DWORD, dw1,
476 DWORD, dw2)
477{
478 DartWaveOut *dwave = (DartWaveOut *)hwo;
479 if(DartWaveOut::find(dwave) == TRUE)
480 {
481 return MMSYSERR_NOTSUPPORTED;
482 }
483 else
484 return(MMSYSERR_INVALHANDLE);
485}
486/******************************************************************************/
487/******************************************************************************/
488
489
Note: See TracBrowser for help on using the repository browser.