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

Last change on this file since 10367 was 10173, checked in by sandervl, 22 years ago

KOM: fixed potential buffer overflows in *GetErrorString functions

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