Release 950122
[wine/multimedia.git] / multimedia / audio.c
blob84b8fb3635e01f573c97cbcf1fbf849862f92baf
1 /*
2 * Sample Wine Driver for Linux
4 * Copyright 1994 Martin Ayotte
6 static char Copyright[] = "Copyright Martin Ayotte, 1994";
7 */
8 #ifndef WINELIB
9 #define BUILTIN_MMSYSTEM
10 #endif
12 #ifdef BUILTIN_MMSYSTEM
14 #define EMULATE_SB16
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <unistd.h>
19 #include <fcntl.h>
20 #include <sys/ioctl.h>
21 #include "windows.h"
22 #include "user.h"
23 #include "driver.h"
24 #include "mmsystem.h"
26 #ifdef linux
27 #include <linux/soundcard.h>
28 #endif
30 #include "stddebug.h"
31 #include "debug.h"
33 #ifdef linux
34 #define SOUND_DEV "/dev/dsp"
36 #ifdef SOUND_VERSION
37 #define IOCTL(a,b,c) ioctl(a,b,&c)
38 #else
39 #define IOCTL(a,b,c) (c = ioctl(a,b,c) )
40 #endif
42 #define MAX_WAVOUTDRV 2
43 #define MAX_WAVINDRV 2
44 #define MAX_MCIWAVDRV 2
46 typedef struct {
47 int unixdev;
48 int state;
49 DWORD bufsize;
50 WAVEOPENDESC waveDesc;
51 WORD wFlags;
52 PCMWAVEFORMAT Format;
53 LPWAVEHDR lpQueueHdr;
54 DWORD dwTotalPlayed;
55 } LINUX_WAVEOUT;
57 typedef struct {
58 int unixdev;
59 int state;
60 DWORD bufsize; /* Linux '/dev/dsp' give us that size */
61 WAVEOPENDESC waveDesc;
62 WORD wFlags;
63 PCMWAVEFORMAT Format;
64 LPWAVEHDR lpQueueHdr;
65 DWORD dwTotalRecorded;
66 } LINUX_WAVEIN;
68 typedef struct {
69 int nUseCount; /* Incremented for each shared open */
70 BOOL fShareable; /* TRUE if first open was shareable */
71 WORD wNotifyDeviceID; /* MCI device ID with a pending notification */
72 HANDLE hCallback; /* Callback handle for pending notification */
73 HMMIO hFile; /* mmio file handle open as Element */
74 MCI_WAVE_OPEN_PARMS openParms;
75 PCMWAVEFORMAT WaveFormat;
76 WAVEHDR WaveHdr;
77 } LINUX_MCIWAVE;
79 static LINUX_WAVEOUT WOutDev[MAX_WAVOUTDRV];
80 static LINUX_WAVEIN WInDev[MAX_WAVOUTDRV];
81 static LINUX_MCIWAVE MCIWavDev[MAX_MCIWAVDRV];
82 #endif
84 DWORD WAVE_mciOpen(DWORD dwFlags, LPMCI_WAVE_OPEN_PARMS lpParms);
85 DWORD WAVE_mciClose(UINT wDevID, DWORD dwParam, LPMCI_GENERIC_PARMS lpParms);
86 DWORD WAVE_mciPlay(UINT wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms);
87 DWORD WAVE_mciRecord(UINT wDevID, DWORD dwFlags, LPMCI_RECORD_PARMS lpParms);
88 DWORD WAVE_mciStop(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms);
89 DWORD WAVE_mciPause(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms);
90 DWORD WAVE_mciResume(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms);
91 DWORD WAVE_mciSet(UINT wDevID, DWORD dwFlags, LPMCI_SET_PARMS lpParms);
92 DWORD WAVE_mciStatus(UINT wDevID, DWORD dwFlags, LPMCI_STATUS_PARMS lpParms);
93 DWORD WAVE_mciGetDevCaps(UINT wDevID, DWORD dwFlags, LPMCI_GETDEVCAPS_PARMS lpParms);
94 DWORD WAVE_mciInfo(UINT wDevID, DWORD dwFlags, LPMCI_INFO_PARMS lpParms);
96 DWORD wodGetDevCaps(WORD wDevID, LPWAVEOUTCAPS lpCaps, DWORD dwSize);
97 DWORD wodOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags);
98 DWORD wodClose(WORD wDevID);
99 DWORD wodWrite(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize);
100 DWORD wodPrepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize);
101 DWORD wodUnprepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize);
104 /**************************************************************************
105 * WAVE_NotifyClient [internal]
107 DWORD WAVE_NotifyClient(UINT wDevID, WORD wMsg,
108 DWORD dwParam1, DWORD dwParam2)
110 #ifdef linux
111 if (WInDev[wDevID].wFlags != DCB_NULL && !DriverCallback(
112 WInDev[wDevID].waveDesc.dwCallBack, WInDev[wDevID].wFlags,
113 WInDev[wDevID].waveDesc.hWave, wMsg,
114 WInDev[wDevID].waveDesc.dwInstance, dwParam1, dwParam2)) {
115 fprintf(stderr,"WAVE_NotifyClient // can't notify client !\n");
116 return MMSYSERR_NOERROR;
118 return 0;
119 #else
120 return MMSYSERR_NOTENABLED;
121 #endif
125 /**************************************************************************
126 * AUDIO_DriverProc [sample driver]
128 LRESULT WAVE_DriverProc(DWORD dwDevID, HDRVR hDriv, WORD wMsg,
129 DWORD dwParam1, DWORD dwParam2)
131 #ifdef linux
132 switch(wMsg) {
133 case DRV_LOAD:
134 return (LRESULT)1L;
135 case DRV_FREE:
136 return (LRESULT)1L;
137 case DRV_OPEN:
138 return (LRESULT)1L;
139 case DRV_CLOSE:
140 return (LRESULT)1L;
141 case DRV_ENABLE:
142 return (LRESULT)1L;
143 case DRV_DISABLE:
144 return (LRESULT)1L;
145 case DRV_QUERYCONFIGURE:
146 return (LRESULT)1L;
147 case DRV_CONFIGURE:
148 MessageBox((HWND)NULL, "Sample MultiMedia Linux Driver !",
149 "MMLinux Driver", MB_OK);
150 return (LRESULT)1L;
151 case DRV_INSTALL:
152 return (LRESULT)DRVCNF_RESTART;
153 case DRV_REMOVE:
154 return (LRESULT)DRVCNF_RESTART;
155 case MCI_OPEN_DRIVER:
156 case MCI_OPEN:
157 return WAVE_mciOpen(dwParam1, (LPMCI_WAVE_OPEN_PARMS)dwParam2);
158 case MCI_CLOSE_DRIVER:
159 case MCI_CLOSE:
160 return WAVE_mciClose(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)dwParam2);
161 case MCI_PLAY:
162 return WAVE_mciPlay(dwDevID, dwParam1, (LPMCI_PLAY_PARMS)dwParam2);
163 case MCI_RECORD:
164 return WAVE_mciRecord(dwDevID, dwParam1, (LPMCI_RECORD_PARMS)dwParam2);
165 case MCI_STOP:
166 return WAVE_mciStop(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)dwParam2);
167 case MCI_SET:
168 return WAVE_mciSet(dwDevID, dwParam1, (LPMCI_SET_PARMS)dwParam2);
169 case MCI_PAUSE:
170 return WAVE_mciPause(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)dwParam2);
171 case MCI_RESUME:
172 return WAVE_mciResume(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)dwParam2);
173 case MCI_STATUS:
174 return WAVE_mciStatus(dwDevID, dwParam1, (LPMCI_STATUS_PARMS)dwParam2);
175 case MCI_GETDEVCAPS:
176 return WAVE_mciGetDevCaps(dwDevID, dwParam1, (LPMCI_GETDEVCAPS_PARMS)dwParam2);
177 case MCI_INFO:
178 return WAVE_mciInfo(dwDevID, dwParam1, (LPMCI_INFO_PARMS)dwParam2);
179 default:
180 return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);
182 #else
183 return MMSYSERR_NOTENABLED;
184 #endif
187 /**************************************************************************
188 * WAVE_mciOpen */
189 DWORD WAVE_mciOpen(DWORD dwFlags, LPMCI_WAVE_OPEN_PARMS lpParms)
191 #ifdef linux
192 UINT wDevID;
193 LPPCMWAVEFORMAT lpWaveFormat;
194 WAVEOPENDESC WaveDesc;
195 DWORD dwRet;
196 char str[128];
198 dprintf_mciwave(stddeb,"WAVE_mciOpen(%08lX, %p)\n", dwFlags, lpParms);
199 if (lpParms == NULL) return MCIERR_INTERNAL;
200 wDevID = lpParms->wDeviceID;
201 if (MCIWavDev[wDevID].nUseCount > 0) {
202 /* The driver already open on this channel */
203 /* If the driver was opened shareable before and this open specifies */
204 /* shareable then increment the use count */
205 if (MCIWavDev[wDevID].fShareable && (dwFlags & MCI_OPEN_SHAREABLE))
206 ++MCIWavDev[wDevID].nUseCount;
207 else
208 return MCIERR_MUST_USE_SHAREABLE;
210 else {
211 MCIWavDev[wDevID].nUseCount = 1;
212 MCIWavDev[wDevID].fShareable = dwFlags & MCI_OPEN_SHAREABLE;
214 if (dwFlags & MCI_OPEN_ELEMENT) {
215 dprintf_mciwave(stddeb,"WAVE_mciOpen // MCI_OPEN_ELEMENT '%s' !\n",
216 lpParms->lpstrElementName);
217 /* printf("WAVE_mciOpen // cdw='%s'\n", DOS_GetCurrentDir(DOS_GetDefaultDrive())); */
218 if (strlen(lpParms->lpstrElementName) > 0) {
219 strcpy(str, lpParms->lpstrElementName);
220 AnsiUpper(str);
221 MCIWavDev[wDevID].hFile = mmioOpen(str, NULL,
222 MMIO_ALLOCBUF | MMIO_READWRITE | MMIO_EXCLUSIVE);
223 if (MCIWavDev[wDevID].hFile == 0) {
224 fprintf(stderr,"WAVE_mciOpen // can't find file='%s' !\n", str);
225 return MCIERR_FILE_NOT_FOUND;
228 else
229 MCIWavDev[wDevID].hFile = 0;
231 dprintf_mciwave(stddeb,"WAVE_mciOpen // hFile=%u\n", MCIWavDev[wDevID].hFile);
232 memcpy(&MCIWavDev[wDevID].openParms, lpParms, sizeof(MCI_WAVE_OPEN_PARMS));
233 MCIWavDev[wDevID].wNotifyDeviceID = lpParms->wDeviceID;
234 lpWaveFormat = &MCIWavDev[wDevID].WaveFormat;
235 WaveDesc.hWave = 0;
236 WaveDesc.lpFormat = (LPWAVEFORMAT)lpWaveFormat;
237 lpWaveFormat->wf.wFormatTag = WAVE_FORMAT_PCM;
238 lpWaveFormat->wBitsPerSample = 8;
239 lpWaveFormat->wf.nChannels = 1;
240 lpWaveFormat->wf.nSamplesPerSec = 11025;
241 lpWaveFormat->wf.nAvgBytesPerSec = 11025;
242 lpWaveFormat->wf.nBlockAlign = 1;
243 if (MCIWavDev[wDevID].hFile != 0) {
244 MMCKINFO mmckInfo;
245 MMCKINFO ckMainRIFF;
246 if (mmioDescend(MCIWavDev[wDevID].hFile, &ckMainRIFF, NULL, 0) != 0) {
247 return MCIERR_INTERNAL;
249 dprintf_mciwave(stddeb,
250 "WAVE_mciOpen // ParentChunk ckid=%.4s fccType=%.4s cksize=%08lX \n",
251 (LPSTR)&ckMainRIFF.ckid, (LPSTR)&ckMainRIFF.fccType,
252 ckMainRIFF.cksize);
253 if ((ckMainRIFF.ckid != FOURCC_RIFF) ||
254 (ckMainRIFF.fccType != mmioFOURCC('W', 'A', 'V', 'E'))) {
255 return MCIERR_INTERNAL;
257 mmckInfo.ckid = mmioFOURCC('f', 'm', 't', ' ');
258 if (mmioDescend(MCIWavDev[wDevID].hFile, &mmckInfo, &ckMainRIFF, MMIO_FINDCHUNK) != 0) {
259 return MCIERR_INTERNAL;
261 dprintf_mciwave(stddeb,
262 "WAVE_mciOpen // Chunk Found ckid=%.4s fccType=%.4s cksize=%08lX \n",
263 (LPSTR)&mmckInfo.ckid, (LPSTR)&mmckInfo.fccType,
264 mmckInfo.cksize);
265 if (mmioRead(MCIWavDev[wDevID].hFile, (HPSTR) lpWaveFormat,
266 (long) sizeof(PCMWAVEFORMAT)) != (long) sizeof(PCMWAVEFORMAT)) {
267 return MCIERR_INTERNAL;
269 mmckInfo.ckid = mmioFOURCC('d', 'a', 't', 'a');
270 if (mmioDescend(MCIWavDev[wDevID].hFile, &mmckInfo, &ckMainRIFF, MMIO_FINDCHUNK) != 0) {
271 return MCIERR_INTERNAL;
273 dprintf_mciwave(stddeb,
274 "WAVE_mciOpen // Chunk Found ckid=%.4s fccType=%.4s cksize=%08lX \n",
275 (LPSTR)&mmckInfo.ckid, (LPSTR)&mmckInfo.fccType,
276 mmckInfo.cksize);
277 dprintf_mciwave(stddeb,
278 "WAVE_mciOpen // nChannels=%d nSamplesPerSec=%ld\n",
279 lpWaveFormat->wf.nChannels, lpWaveFormat->wf.nSamplesPerSec);
280 lpWaveFormat->wBitsPerSample = 0;
282 lpWaveFormat->wf.nAvgBytesPerSec =
283 lpWaveFormat->wf.nSamplesPerSec * lpWaveFormat->wf.nBlockAlign;
284 dwRet = wodMessage(0, WODM_OPEN, 0, (DWORD)&WaveDesc, CALLBACK_NULL);
285 dwRet = widMessage(0, WIDM_OPEN, 0, (DWORD)&WaveDesc, CALLBACK_NULL);
286 return 0;
287 #else
288 return MMSYSERR_NOTENABLED;
289 #endif
292 /**************************************************************************
293 * WAVE_mciClose [internal]
295 DWORD WAVE_mciClose(UINT wDevID, DWORD dwParam, LPMCI_GENERIC_PARMS lpParms)
297 #ifdef linux
298 DWORD dwRet;
299 dprintf_mciwave(stddeb,
300 "WAVE_mciClose(%u, %08lX, %p);\n", wDevID, dwParam, lpParms);
301 MCIWavDev[wDevID].nUseCount--;
302 if (MCIWavDev[wDevID].nUseCount == 0) {
303 if (MCIWavDev[wDevID].hFile != 0) {
304 mmioClose(MCIWavDev[wDevID].hFile, 0);
305 MCIWavDev[wDevID].hFile = 0;
307 dwRet = wodMessage(0, WODM_CLOSE, 0, 0L, 0L);
308 if (dwRet != MMSYSERR_NOERROR) return MCIERR_INTERNAL;
309 dwRet = widMessage(0, WIDM_CLOSE, 0, 0L, 0L);
310 if (dwRet != MMSYSERR_NOERROR) return MCIERR_INTERNAL;
312 return 0;
313 #else
314 return 0;
315 #endif
319 /**************************************************************************
320 * WAVE_mciPlay [internal]
322 DWORD WAVE_mciPlay(UINT wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms)
324 #ifdef linux
325 int count;
326 int start, end;
327 LPWAVEHDR lpWaveHdr;
328 DWORD dwRet;
329 dprintf_mciwave(stddeb,
330 "WAVE_mciPlay(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
331 if (MCIWavDev[wDevID].hFile == 0) {
332 fprintf(stderr,"WAVE_mciPlay // can't find file='%s' !\n",
333 MCIWavDev[wDevID].openParms.lpstrElementName);
334 return MCIERR_FILE_NOT_FOUND;
336 start = 1; end = 99999;
337 if (dwFlags & MCI_FROM) {
338 start = lpParms->dwFrom;
339 dprintf_mciwave(stddeb,
340 "WAVE_mciPlay // MCI_FROM=%d \n", start);
342 if (dwFlags & MCI_TO) {
343 end = lpParms->dwTo;
344 dprintf_mciwave(stddeb,"WAVE_mciPlay // MCI_TO=%d \n", end);
346 /**/
347 if (dwFlags & MCI_NOTIFY) {
348 dprintf_mciwave(stddeb,
349 "WAVE_mciPlay // MCI_NOTIFY %08lX !\n", lpParms->dwCallback);
350 switch(fork()) {
351 case -1:
352 fprintf(stderr,
353 "WAVE_mciPlay // Can't 'fork' process !\n");
354 break;
355 case 0:
356 break;
357 default:
358 dprintf_mciwave(stddeb,"WAVE_mciPlay // process started ! return to caller...\n");
359 return 0;
362 /**/
363 lpWaveHdr = &MCIWavDev[wDevID].WaveHdr;
364 lpWaveHdr->lpData = (LPSTR) malloc(64000);
365 lpWaveHdr->dwBufferLength = 32000;
366 lpWaveHdr->dwUser = 0L;
367 lpWaveHdr->dwFlags = 0L;
368 lpWaveHdr->dwLoops = 0L;
369 dwRet = wodMessage(0, WODM_PREPARE, 0, (DWORD)lpWaveHdr, sizeof(WAVEHDR));
370 /* printf("WAVE_mciPlay // after WODM_PREPARE \n"); */
371 while(TRUE) {
372 count = mmioRead(MCIWavDev[wDevID].hFile, lpWaveHdr->lpData, lpWaveHdr->dwBufferLength);
373 if (count < 1) break;
374 lpWaveHdr->dwBytesRecorded = count;
375 dprintf_mciwave(stddeb,"WAVE_mciPlay // before WODM_WRITE lpWaveHdr=%p dwBytesRecorded=%lu\n",
376 lpWaveHdr, lpWaveHdr->dwBytesRecorded);
377 dwRet = wodMessage(0, WODM_WRITE, 0, (DWORD)lpWaveHdr, sizeof(WAVEHDR));
379 dwRet = wodMessage(0, WODM_UNPREPARE, 0, (DWORD)lpWaveHdr, sizeof(WAVEHDR));
380 if (lpWaveHdr->lpData != NULL) {
381 free(lpWaveHdr->lpData);
382 lpWaveHdr->lpData = NULL;
384 if (dwFlags & MCI_NOTIFY) {
385 dprintf_mciwave(stddeb,"WAVE_mciPlay // MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
386 mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
387 MCIWavDev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
388 exit(0);
390 return 0;
391 #else
392 return MMSYSERR_NOTENABLED;
393 #endif
397 /**************************************************************************
398 * WAVE_mciRecord [internal]
400 DWORD WAVE_mciRecord(UINT wDevID, DWORD dwFlags, LPMCI_RECORD_PARMS lpParms)
402 #ifdef linux
403 int start, end;
404 LPWAVEHDR lpWaveHdr;
405 DWORD dwRet;
407 dprintf_mciwave(stddeb,
408 "WAVE_mciRecord(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
409 if (MCIWavDev[wDevID].hFile == 0) {
410 fprintf(stderr,"WAVE_mciRecord // can't find file='%s' !\n",
411 MCIWavDev[wDevID].openParms.lpstrElementName);
412 return MCIERR_FILE_NOT_FOUND;
414 start = 1; end = 99999;
415 if (dwFlags & MCI_FROM) {
416 start = lpParms->dwFrom;
417 dprintf_mciwave(stddeb,
418 "WAVE_mciRecord // MCI_FROM=%d \n", start);
420 if (dwFlags & MCI_TO) {
421 end = lpParms->dwTo;
422 dprintf_mciwave(stddeb,"WAVE_mciRecord // MCI_TO=%d \n", end);
424 lpWaveHdr = &MCIWavDev[wDevID].WaveHdr;
425 lpWaveHdr->lpData = (LPSTR) malloc(64000);
426 lpWaveHdr->dwBufferLength = 32000;
427 lpWaveHdr->dwUser = 0L;
428 lpWaveHdr->dwFlags = 0L;
429 lpWaveHdr->dwLoops = 0L;
430 dwRet = widMessage(0, WIDM_PREPARE, 0, (DWORD)lpWaveHdr, sizeof(WAVEHDR));
431 dprintf_mciwave(stddeb,"WAVE_mciRecord // after WIDM_PREPARE \n");
432 while(TRUE) {
433 lpWaveHdr->dwBytesRecorded = 0;
434 dwRet = widMessage(0, WIDM_START, 0, 0L, 0L);
435 dprintf_mciwave(stddeb,
436 "WAVE_mciRecord // after WIDM_START lpWaveHdr=%p dwBytesRecorded=%lu\n",
437 lpWaveHdr, lpWaveHdr->dwBytesRecorded);
438 if (lpWaveHdr->dwBytesRecorded == 0) break;
440 dprintf_mciwave(stddeb,"WAVE_mciRecord // before WIDM_UNPREPARE \n");
441 dwRet = widMessage(0, WIDM_UNPREPARE, 0, (DWORD)lpWaveHdr, sizeof(WAVEHDR));
442 dprintf_mciwave(stddeb,"WAVE_mciRecord // after WIDM_UNPREPARE \n");
443 if (lpWaveHdr->lpData != NULL) {
444 free(lpWaveHdr->lpData);
445 lpWaveHdr->lpData = NULL;
447 if (dwFlags & MCI_NOTIFY) {
448 dprintf_mciwave(stddeb,"WAVE_mciRecord // MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
449 mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
450 MCIWavDev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
452 return 0;
453 #else
454 return MMSYSERR_NOTENABLED;
455 #endif
459 /**************************************************************************
460 * WAVE_mciStop [internal]
462 DWORD WAVE_mciStop(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
464 #ifdef linux
465 dprintf_mciwave(stddeb,
466 "WAVE_mciStop(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
467 if (lpParms == NULL) return MCIERR_INTERNAL;
468 return 0;
469 #else
470 return MCIERR_INTERNAL;
471 #endif
475 /**************************************************************************
476 * WAVE_mciPause [internal]
478 DWORD WAVE_mciPause(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
480 #ifdef linux
481 dprintf_mciwave(stddeb,
482 "WAVE_mciPause(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
483 if (lpParms == NULL) return MCIERR_INTERNAL;
484 return 0;
485 #else
486 return MCIERR_INTERNAL;
487 #endif
491 /**************************************************************************
492 * WAVE_mciResume [internal]
494 DWORD WAVE_mciResume(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
496 #ifdef linux
497 dprintf_mciwave(stddeb,
498 "WAVE_mciResume(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
499 if (lpParms == NULL) return MCIERR_INTERNAL;
500 return 0;
501 #else
502 return MCIERR_INTERNAL;
503 #endif
507 /**************************************************************************
508 * WAVE_mciSet [internal]
510 DWORD WAVE_mciSet(UINT wDevID, DWORD dwFlags, LPMCI_SET_PARMS lpParms)
512 #ifdef linux
513 dprintf_mciwave(stddeb,
514 "WAVE_mciSet(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
515 if (lpParms == NULL) return MCIERR_INTERNAL;
516 dprintf_mciwave(stddeb,
517 "WAVE_mciSet // dwTimeFormat=%08lX\n", lpParms->dwTimeFormat);
518 dprintf_mciwave(stddeb,
519 "WAVE_mciSet // dwAudio=%08lX\n", lpParms->dwAudio);
520 if (dwFlags & MCI_SET_TIME_FORMAT) {
521 switch (lpParms->dwTimeFormat) {
522 case MCI_FORMAT_MILLISECONDS:
523 dprintf_mciwave(stddeb,
524 "WAVE_mciSet // MCI_FORMAT_MILLISECONDS !\n");
525 break;
526 case MCI_FORMAT_BYTES:
527 dprintf_mciwave(stddeb,
528 "WAVE_mciSet // MCI_FORMAT_BYTES !\n");
529 break;
530 case MCI_FORMAT_SAMPLES:
531 dprintf_mciwave(stddeb,
532 "WAVE_mciSet // MCI_FORMAT_SAMPLES !\n");
533 break;
534 default:
535 fprintf(stderr,
536 "WAVE_mciSet // bad time format !\n");
537 return MCIERR_BAD_TIME_FORMAT;
540 if (dwFlags & MCI_SET_VIDEO) return MCIERR_UNSUPPORTED_FUNCTION;
541 if (dwFlags & MCI_SET_DOOR_OPEN) return MCIERR_UNSUPPORTED_FUNCTION;
542 if (dwFlags & MCI_SET_DOOR_CLOSED) return MCIERR_UNSUPPORTED_FUNCTION;
543 if (dwFlags & MCI_SET_AUDIO)
544 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_SET_AUDIO !\n");
545 if (dwFlags && MCI_SET_ON) {
546 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_SET_ON !\n");
547 if (dwFlags && MCI_SET_AUDIO_LEFT)
548 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_SET_AUDIO_LEFT !\n");
549 if (dwFlags && MCI_SET_AUDIO_RIGHT)
550 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_SET_AUDIO_RIGHT !\n");
552 if (dwFlags & MCI_SET_OFF)
553 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_SET_OFF !\n");
554 if (dwFlags & MCI_WAVE_INPUT)
555 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_WAVE_INPUT !\n");
556 if (dwFlags & MCI_WAVE_OUTPUT)
557 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_WAVE_OUTPUT !\n");
558 if (dwFlags & MCI_WAVE_SET_ANYINPUT)
559 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_WAVE_SET_ANYINPUT !\n");
560 if (dwFlags & MCI_WAVE_SET_ANYOUTPUT)
561 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_WAVE_SET_ANYOUTPUT !\n");
562 if (dwFlags & MCI_WAVE_SET_AVGBYTESPERSEC)
563 dprintf_mciwave(stddeb,
564 "WAVE_mciSet // MCI_WAVE_SET_AVGBYTESPERSEC !\n");
565 if (dwFlags & MCI_WAVE_SET_BITSPERSAMPLE)
566 dprintf_mciwave(stddeb,
567 "WAVE_mciSet // MCI_WAVE_SET_BITSPERSAMPLE !\n");
568 if (dwFlags & MCI_WAVE_SET_BLOCKALIGN)
569 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_WAVE_SET_BLOCKALIGN !\n");
570 if (dwFlags & MCI_WAVE_SET_CHANNELS)
571 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_WAVE_SET_CHANNELS !\n");
572 if (dwFlags & MCI_WAVE_SET_FORMATTAG)
573 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_WAVE_SET_FORMATTAG !\n");
574 if (dwFlags & MCI_WAVE_SET_SAMPLESPERSEC)
575 dprintf_mciwave(stddeb,
576 "WAVE_mciSet // MCI_WAVE_SET_SAMPLESPERSEC !\n");
577 return 0;
578 #else
579 return MCIERR_INTERNAL;
580 #endif
584 /**************************************************************************
585 * WAVE_mciStatus [internal]
587 DWORD WAVE_mciStatus(UINT wDevID, DWORD dwFlags, LPMCI_STATUS_PARMS lpParms)
589 #ifdef linux
590 dprintf_mciwave(stddeb,
591 "WAVE_mciStatus(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
592 if (lpParms == NULL) return MCIERR_INTERNAL;
593 if (dwFlags & MCI_STATUS_ITEM) {
594 switch(lpParms->dwItem) {
595 case MCI_STATUS_CURRENT_TRACK:
596 lpParms->dwReturn = 1;
597 break;
598 case MCI_STATUS_LENGTH:
599 lpParms->dwReturn = 5555;
600 if (dwFlags & MCI_TRACK) {
601 lpParms->dwTrack = 1;
602 lpParms->dwReturn = 2222;
604 break;
605 case MCI_STATUS_MODE:
606 lpParms->dwReturn = MCI_MODE_STOP;
607 break;
608 case MCI_STATUS_MEDIA_PRESENT:
609 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_STATUS_MEDIA_PRESENT !\n");
610 lpParms->dwReturn = TRUE;
611 break;
612 case MCI_STATUS_NUMBER_OF_TRACKS:
613 lpParms->dwReturn = 1;
614 break;
615 case MCI_STATUS_POSITION:
616 lpParms->dwReturn = 3333;
617 if (dwFlags & MCI_STATUS_START) {
618 lpParms->dwItem = 1;
620 if (dwFlags & MCI_TRACK) {
621 lpParms->dwTrack = 1;
622 lpParms->dwReturn = 777;
624 break;
625 case MCI_STATUS_READY:
626 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_STATUS_READY !\n");
627 lpParms->dwReturn = TRUE;
628 break;
629 case MCI_STATUS_TIME_FORMAT:
630 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_STATUS_TIME_FORMAT !\n");
631 lpParms->dwReturn = MCI_FORMAT_MILLISECONDS;
632 break;
633 case MCI_WAVE_INPUT:
634 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_INPUT !\n");
635 lpParms->dwReturn = 0;
636 break;
637 case MCI_WAVE_OUTPUT:
638 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_OUTPUT !\n");
639 lpParms->dwReturn = 0;
640 break;
641 case MCI_WAVE_STATUS_AVGBYTESPERSEC:
642 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_STATUS_AVGBYTESPERSEC !\n");
643 lpParms->dwReturn = 22050;
644 break;
645 case MCI_WAVE_STATUS_BITSPERSAMPLE:
646 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_STATUS_BITSPERSAMPLE !\n");
647 lpParms->dwReturn = 8;
648 break;
649 case MCI_WAVE_STATUS_BLOCKALIGN:
650 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_STATUS_BLOCKALIGN !\n");
651 lpParms->dwReturn = 1;
652 break;
653 case MCI_WAVE_STATUS_CHANNELS:
654 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_STATUS_CHANNELS !\n");
655 lpParms->dwReturn = 1;
656 break;
657 case MCI_WAVE_STATUS_FORMATTAG:
658 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_FORMATTAG !\n");
659 lpParms->dwReturn = WAVE_FORMAT_PCM;
660 break;
661 case MCI_WAVE_STATUS_LEVEL:
662 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_STATUS_LEVEL !\n");
663 lpParms->dwReturn = 0xAAAA5555;
664 break;
665 case MCI_WAVE_STATUS_SAMPLESPERSEC:
666 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_STATUS_SAMPLESPERSEC !\n");
667 lpParms->dwReturn = 22050;
668 break;
669 default:
670 fprintf(stderr,"WAVE_mciStatus // unknown command %08lX !\n", lpParms->dwItem);
671 return MCIERR_UNRECOGNIZED_COMMAND;
674 if (dwFlags & MCI_NOTIFY) {
675 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
676 mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
677 MCIWavDev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
679 return 0;
680 #else
681 return MCIERR_INTERNAL;
682 #endif
685 /**************************************************************************
686 * WAVE_mciGetDevCaps [internal]
688 DWORD WAVE_mciGetDevCaps(UINT wDevID, DWORD dwFlags,
689 LPMCI_GETDEVCAPS_PARMS lpParms)
691 #ifdef linux
692 dprintf_mciwave(stddeb,
693 "WAVE_mciGetDevCaps(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
694 if (lpParms == NULL) return MCIERR_INTERNAL;
695 if (dwFlags & MCI_GETDEVCAPS_ITEM) {
696 switch(lpParms->dwItem) {
697 case MCI_GETDEVCAPS_CAN_RECORD:
698 lpParms->dwReturn = TRUE;
699 break;
700 case MCI_GETDEVCAPS_HAS_AUDIO:
701 lpParms->dwReturn = TRUE;
702 break;
703 case MCI_GETDEVCAPS_HAS_VIDEO:
704 lpParms->dwReturn = FALSE;
705 break;
706 case MCI_GETDEVCAPS_DEVICE_TYPE:
707 lpParms->dwReturn = MCI_DEVTYPE_WAVEFORM_AUDIO;
708 break;
709 case MCI_GETDEVCAPS_USES_FILES:
710 lpParms->dwReturn = TRUE;
711 break;
712 case MCI_GETDEVCAPS_COMPOUND_DEVICE:
713 lpParms->dwReturn = TRUE;
714 break;
715 case MCI_GETDEVCAPS_CAN_EJECT:
716 lpParms->dwReturn = FALSE;
717 break;
718 case MCI_GETDEVCAPS_CAN_PLAY:
719 lpParms->dwReturn = TRUE;
720 break;
721 case MCI_GETDEVCAPS_CAN_SAVE:
722 lpParms->dwReturn = TRUE;
723 break;
724 case MCI_WAVE_GETDEVCAPS_INPUTS:
725 lpParms->dwReturn = 1;
726 break;
727 case MCI_WAVE_GETDEVCAPS_OUTPUTS:
728 lpParms->dwReturn = 1;
729 break;
730 default:
731 return MCIERR_UNRECOGNIZED_COMMAND;
734 return 0;
735 #else
736 return MCIERR_INTERNAL;
737 #endif
740 /**************************************************************************
741 * WAVE_mciInfo [internal]
743 DWORD WAVE_mciInfo(UINT wDevID, DWORD dwFlags, LPMCI_INFO_PARMS lpParms)
745 #ifdef linux
746 dprintf_mciwave(stddeb,
747 "WAVE_mciInfo(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
748 if (lpParms == NULL) return MCIERR_INTERNAL;
749 lpParms->lpstrReturn = NULL;
750 switch(dwFlags) {
751 case MCI_INFO_PRODUCT:
752 lpParms->lpstrReturn = "Linux Sound System 0.5";
753 break;
754 case MCI_INFO_FILE:
755 lpParms->lpstrReturn =
756 (LPSTR)MCIWavDev[wDevID].openParms.lpstrElementName;
757 break;
758 case MCI_WAVE_INPUT:
759 lpParms->lpstrReturn = "Linux Sound System 0.5";
760 break;
761 case MCI_WAVE_OUTPUT:
762 lpParms->lpstrReturn = "Linux Sound System 0.5";
763 break;
764 default:
765 return MCIERR_UNRECOGNIZED_COMMAND;
767 if (lpParms->lpstrReturn != NULL)
768 lpParms->dwRetSize = strlen(lpParms->lpstrReturn);
769 else
770 lpParms->dwRetSize = 0;
771 return 0;
772 #else
773 return MCIERR_INTERNAL;
774 #endif
778 /*-----------------------------------------------------------------------*/
781 /**************************************************************************
782 * wodGetDevCaps [internal]
784 DWORD wodGetDevCaps(WORD wDevID, LPWAVEOUTCAPS lpCaps, DWORD dwSize)
786 #ifdef linux
787 int audio;
788 int smplrate;
789 int samplesize = 16;
790 int dsp_stereo = 1;
791 int bytespersmpl;
792 dprintf_mciwave(stddeb,
793 "wodGetDevCaps(%u, %p, %lu);\n", wDevID, lpCaps, dwSize);
794 if (lpCaps == NULL) return MMSYSERR_NOTENABLED;
795 audio = open (SOUND_DEV, O_WRONLY, 0);
796 if (audio == -1) return MMSYSERR_NOTENABLED;
797 #ifdef EMULATE_SB16
798 lpCaps->wMid = 0x0002;
799 lpCaps->wPid = 0x0104;
800 strcpy(lpCaps->szPname, "SB16 Wave Out");
801 #else
802 lpCaps->wMid = 0x00FF; /* Manufac ID */
803 lpCaps->wPid = 0x0001; /* Product ID */
804 strcpy(lpCaps->szPname, "Linux WAVOUT Driver");
805 #endif
806 lpCaps->dwFormats = 0x00000000;
807 lpCaps->dwSupport = WAVECAPS_VOLUME;
808 lpCaps->wChannels = (IOCTL(audio, SNDCTL_DSP_STEREO, dsp_stereo) != 0) ? 1 : 2;
809 if (lpCaps->wChannels > 1) lpCaps->dwSupport |= WAVECAPS_LRVOLUME;
810 bytespersmpl = (IOCTL(audio, SNDCTL_DSP_SAMPLESIZE, samplesize) != 0) ? 1 : 2;
811 smplrate = 44100;
812 if (IOCTL(audio, SNDCTL_DSP_SPEED, smplrate) == 0) {
813 lpCaps->dwFormats |= WAVE_FORMAT_4M08;
814 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_4S08;
815 if (bytespersmpl > 1) {
816 lpCaps->dwFormats |= WAVE_FORMAT_4M16;
817 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_4S16;
820 smplrate = 22050;
821 if (IOCTL(audio, SNDCTL_DSP_SPEED, smplrate) == 0) {
822 lpCaps->dwFormats |= WAVE_FORMAT_2M08;
823 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_2S08;
824 if (bytespersmpl > 1) {
825 lpCaps->dwFormats |= WAVE_FORMAT_2M16;
826 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_2S16;
829 smplrate = 11025;
830 if (IOCTL(audio, SNDCTL_DSP_SPEED, smplrate) == 0) {
831 lpCaps->dwFormats |= WAVE_FORMAT_1M08;
832 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_1S08;
833 if (bytespersmpl > 1) {
834 lpCaps->dwFormats |= WAVE_FORMAT_1M16;
835 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_1S16;
838 close(audio);
839 dprintf_mciwave(stddeb,
840 "wodGetDevCaps // dwFormats = %08lX\n", lpCaps->dwFormats);
841 return MMSYSERR_NOERROR;
842 #else
843 return MMSYSERR_NOTENABLED;
844 #endif
848 /**************************************************************************
849 * wodOpen [internal]
851 DWORD wodOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
853 #ifdef linux
854 int audio;
855 int abuf_size;
856 int smplrate;
857 int samplesize;
858 int dsp_stereo;
859 dprintf_mciwave(stddeb,
860 "wodOpen(%u, %p, %08lX);\n", wDevID, lpDesc, dwFlags);
861 if (lpDesc == NULL) {
862 fprintf(stderr,"Linux 'wodOpen' // Invalid Parameter !\n");
863 return MMSYSERR_INVALPARAM;
865 if (wDevID >= MAX_WAVOUTDRV) {
866 fprintf(stderr,"Linux 'wodOpen' // MAX_WAVOUTDRV reached !\n");
867 return MMSYSERR_ALLOCATED;
869 WOutDev[wDevID].unixdev = 0;
870 audio = open (SOUND_DEV, O_WRONLY, 0);
871 if (audio == -1) {
872 fprintf(stderr,"Linux 'wodOpen' // can't open !\n");
873 return MMSYSERR_NOTENABLED;
875 IOCTL(audio, SNDCTL_DSP_GETBLKSIZE, abuf_size);
876 if (abuf_size < 4096 || abuf_size > 65536) {
877 if (abuf_size == -1)
878 fprintf(stderr,"Linux 'wodOpen' // IOCTL can't 'SNDCTL_DSP_GETBLKSIZE' !\n");
879 else
880 fprintf(stderr,"Linux 'wodOpen' // SNDCTL_DSP_GETBLKSIZE Invalid bufsize !\n");
881 return MMSYSERR_NOTENABLED;
883 WOutDev[wDevID].wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
884 switch(WOutDev[wDevID].wFlags) {
885 case DCB_NULL:
886 fprintf(stderr,"Linux 'wodOpen' // CALLBACK_NULL !\n");
887 break;
888 case DCB_WINDOW:
889 dprintf_mciwave(stddeb,
890 "Linux 'wodOpen' // CALLBACK_WINDOW !\n");
891 break;
892 case DCB_TASK:
893 dprintf_mciwave(stddeb,
894 "Linux 'wodOpen' // CALLBACK_TASK !\n");
895 break;
896 case DCB_FUNCTION:
897 dprintf_mciwave(stddeb,
898 "Linux 'wodOpen' // CALLBACK_FUNCTION !\n");
899 break;
901 WOutDev[wDevID].lpQueueHdr = NULL;
902 WOutDev[wDevID].unixdev = audio;
903 WOutDev[wDevID].dwTotalPlayed = 0;
904 WOutDev[wDevID].bufsize = abuf_size;
905 memcpy(&WOutDev[wDevID].waveDesc, lpDesc, sizeof(WAVEOPENDESC));
906 if (lpDesc->lpFormat->wFormatTag != WAVE_FORMAT_PCM) {
907 fprintf(stderr,"Linux 'wodOpen' // Bad format %04X !\n",
908 lpDesc->lpFormat->wFormatTag);
909 return WAVERR_BADFORMAT;
911 memcpy(&WOutDev[wDevID].Format, lpDesc->lpFormat, sizeof(PCMWAVEFORMAT));
912 if (WOutDev[wDevID].Format.wf.nChannels == 0) return WAVERR_BADFORMAT;
913 if (WOutDev[wDevID].Format.wf.nSamplesPerSec == 0) return WAVERR_BADFORMAT;
914 if (WOutDev[wDevID].Format.wBitsPerSample == 0) {
915 WOutDev[wDevID].Format.wBitsPerSample = 8 *
916 (WOutDev[wDevID].Format.wf.nAvgBytesPerSec /
917 WOutDev[wDevID].Format.wf.nSamplesPerSec) /
918 WOutDev[wDevID].Format.wf.nChannels;
920 samplesize = WOutDev[wDevID].Format.wBitsPerSample;
921 smplrate = WOutDev[wDevID].Format.wf.nSamplesPerSec;
922 dsp_stereo = (WOutDev[wDevID].Format.wf.nChannels > 1) ? TRUE : FALSE;
923 IOCTL(audio, SNDCTL_DSP_SPEED, smplrate);
924 IOCTL(audio, SNDCTL_DSP_SAMPLESIZE, samplesize);
925 IOCTL(audio, SNDCTL_DSP_STEREO, dsp_stereo);
926 dprintf_mciwave(stddeb,"Linux 'wodOpen' // wBitsPerSample=%u !\n",
927 WOutDev[wDevID].Format.wBitsPerSample);
928 dprintf_mciwave(stddeb,"Linux 'wodOpen' // nSamplesPerSec=%lu !\n",
929 WOutDev[wDevID].Format.wf.nSamplesPerSec);
930 dprintf_mciwave(stddeb,"Linux 'wodOpen' // nChannels=%u !\n",
931 WOutDev[wDevID].Format.wf.nChannels);
932 if (WAVE_NotifyClient(wDevID, WOM_OPEN, 0L, 0L) != MMSYSERR_NOERROR) {
933 fprintf(stderr,"Linux 'wodOpen' // can't notify client !\n");
934 return MMSYSERR_INVALPARAM;
936 return MMSYSERR_NOERROR;
937 #else
938 return MMSYSERR_NOTENABLED;
939 #endif
942 /**************************************************************************
943 * wodClose [internal]
945 DWORD wodClose(WORD wDevID)
947 #ifdef linux
948 dprintf_mciwave(stddeb,"wodClose(%u);\n", wDevID);
949 if (WOutDev[wDevID].unixdev == 0) {
950 fprintf(stderr,"Linux 'wodClose' // can't close !\n");
951 return MMSYSERR_NOTENABLED;
953 close(WOutDev[wDevID].unixdev);
954 WOutDev[wDevID].unixdev = 0;
955 WOutDev[wDevID].bufsize = 0;
956 if (WAVE_NotifyClient(wDevID, WOM_CLOSE, 0L, 0L) != MMSYSERR_NOERROR) {
957 fprintf(stderr,"Linux 'wodClose' // can't notify client !\n");
958 return MMSYSERR_INVALPARAM;
960 return MMSYSERR_NOERROR;
961 #else
962 return MMSYSERR_NOTENABLED;
963 #endif
966 /**************************************************************************
967 * wodWrite [internal]
969 DWORD wodWrite(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
971 #ifdef linux
972 dprintf_mciwave(stddeb,"wodWrite(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
973 if (WOutDev[wDevID].unixdev == 0) {
974 fprintf(stderr,"Linux 'wodWrite' // can't play !\n");
975 return MMSYSERR_NOTENABLED;
977 if (lpWaveHdr->lpData == NULL) return WAVERR_UNPREPARED;
978 if (!(lpWaveHdr->dwFlags & WHDR_PREPARED)) return WAVERR_UNPREPARED;
979 if (lpWaveHdr->dwFlags & WHDR_INQUEUE) return WAVERR_STILLPLAYING;
980 lpWaveHdr->dwFlags &= ~WHDR_DONE;
981 lpWaveHdr->dwFlags |= WHDR_INQUEUE;
982 dprintf_mciwave(stddeb,
983 "wodWrite() // dwBytesRecorded %lu !\n", lpWaveHdr->dwBytesRecorded);
984 if (write (WOutDev[wDevID].unixdev, lpWaveHdr->lpData,
985 lpWaveHdr->dwBytesRecorded) != lpWaveHdr->dwBytesRecorded) {
986 return MMSYSERR_NOTENABLED;
988 lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
989 lpWaveHdr->dwFlags |= WHDR_DONE;
990 if (WAVE_NotifyClient(wDevID, WOM_DONE, 0L, 0L) != MMSYSERR_NOERROR) {
991 fprintf(stderr,"Linux 'wodWrite' // can't notify client !\n");
992 return MMSYSERR_INVALPARAM;
994 return MMSYSERR_NOERROR;
995 #else
996 return MMSYSERR_NOTENABLED;
997 #endif
1000 /**************************************************************************
1001 * wodPrepare [internal]
1003 DWORD wodPrepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
1005 #ifdef linux
1006 dprintf_mciwave(stddeb,
1007 "wodPrepare(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
1008 if (WOutDev[wDevID].unixdev == 0) {
1009 fprintf(stderr,"Linux 'wodPrepare' // can't prepare !\n");
1010 return MMSYSERR_NOTENABLED;
1012 if (WOutDev[wDevID].lpQueueHdr != NULL) {
1013 fprintf(stderr,"Linux 'wodPrepare' // already prepare !\n");
1014 return MMSYSERR_NOTENABLED;
1016 WOutDev[wDevID].dwTotalPlayed = 0;
1017 WOutDev[wDevID].lpQueueHdr = lpWaveHdr;
1018 if (lpWaveHdr->dwFlags & WHDR_INQUEUE) return WAVERR_STILLPLAYING;
1019 lpWaveHdr->dwFlags |= WHDR_PREPARED;
1020 lpWaveHdr->dwFlags &= ~WHDR_DONE;
1021 return MMSYSERR_NOERROR;
1022 #else
1023 return MMSYSERR_NOTENABLED;
1024 #endif
1027 /**************************************************************************
1028 * wodUnprepare [internal]
1030 DWORD wodUnprepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
1032 #ifdef linux
1033 dprintf_mciwave(stddeb,
1034 "wodUnprepare(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
1035 if (WOutDev[wDevID].unixdev == 0) {
1036 fprintf(stderr,"Linux 'wodUnprepare' // can't unprepare !\n");
1037 return MMSYSERR_NOTENABLED;
1039 return MMSYSERR_NOERROR;
1040 #else
1041 return MMSYSERR_NOTENABLED;
1042 #endif
1045 /**************************************************************************
1046 * wodRestart [internal]
1048 DWORD wodRestart(WORD wDevID)
1050 #ifdef linux
1051 dprintf_mciwave(stddeb,"wodRestart(%u);\n", wDevID);
1052 if (WOutDev[wDevID].unixdev == 0) {
1053 fprintf(stderr,"Linux 'wodRestart' // can't restart !\n");
1054 return MMSYSERR_NOTENABLED;
1056 return MMSYSERR_NOERROR;
1057 #else
1058 return MMSYSERR_NOTENABLED;
1059 #endif
1062 /**************************************************************************
1063 * wodReset [internal]
1065 DWORD wodReset(WORD wDevID)
1067 #ifdef linux
1068 dprintf_mciwave(stddeb,"wodReset(%u);\n", wDevID);
1069 if (WOutDev[wDevID].unixdev == 0) {
1070 fprintf(stderr,"Linux 'wodReset' // can't reset !\n");
1071 return MMSYSERR_NOTENABLED;
1073 return MMSYSERR_NOERROR;
1074 #else
1075 return MMSYSERR_NOTENABLED;
1076 #endif
1080 /**************************************************************************
1081 * wodGetPosition [internal]
1083 DWORD wodGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize)
1085 #ifdef linux
1086 int time;
1087 dprintf_mciwave(stddeb,"wodGetPosition(%u, %p, %lu);\n", wDevID, lpTime, uSize);
1088 if (WOutDev[wDevID].unixdev == 0) {
1089 fprintf(stderr,"Linux 'wodGetPosition' // can't get pos !\n");
1090 return MMSYSERR_NOTENABLED;
1092 if (lpTime == NULL) return MMSYSERR_INVALPARAM;
1093 TryAGAIN:
1094 switch(lpTime->wType) {
1095 case TIME_BYTES:
1096 lpTime->u.cb = WOutDev[wDevID].dwTotalPlayed;
1097 dprintf_mciwave(stddeb,"wodGetPosition // TIME_BYTES=%lu\n", lpTime->u.cb);
1098 break;
1099 case TIME_SAMPLES:
1100 lpTime->u.sample = WOutDev[wDevID].dwTotalPlayed * 8 /
1101 WOutDev[wDevID].Format.wBitsPerSample;
1102 dprintf_mciwave(stddeb,"wodGetPosition // TIME_SAMPLES=%lu\n", lpTime->u.sample);
1103 break;
1104 case TIME_MS:
1105 lpTime->u.ms = WOutDev[wDevID].dwTotalPlayed /
1106 (WOutDev[wDevID].Format.wf.nAvgBytesPerSec / 1000);
1107 dprintf_mciwave(stddeb,"wodGetPosition // TIME_MS=%lu\n", lpTime->u.ms);
1108 break;
1109 case TIME_SMPTE:
1110 time = WOutDev[wDevID].dwTotalPlayed /
1111 (WOutDev[wDevID].Format.wf.nAvgBytesPerSec / 1000);
1112 lpTime->u.smpte.hour = time / 108000;
1113 time -= lpTime->u.smpte.hour * 108000;
1114 lpTime->u.smpte.min = time / 1800;
1115 time -= lpTime->u.smpte.min * 1800;
1116 lpTime->u.smpte.sec = time / 30;
1117 time -= lpTime->u.smpte.sec * 30;
1118 lpTime->u.smpte.frame = time;
1119 lpTime->u.smpte.fps = 30;
1120 dprintf_mciwave(stddeb,
1121 "wodGetPosition // TIME_SMPTE=%02u:%02u:%02u:%02u\n",
1122 lpTime->u.smpte.hour, lpTime->u.smpte.min,
1123 lpTime->u.smpte.sec, lpTime->u.smpte.frame);
1124 break;
1125 default:
1126 fprintf(stderr,"wodGetPosition() format not supported ! use TIME_MS !\n");
1127 lpTime->wType = TIME_MS;
1128 goto TryAGAIN;
1130 return MMSYSERR_NOERROR;
1131 #else
1132 return MMSYSERR_NOTENABLED;
1133 #endif
1136 /**************************************************************************
1137 * wodGetVolume [internal]
1139 DWORD wodGetVolume(WORD wDevID, LPDWORD lpdwVol)
1141 #ifdef linux
1142 int mixer;
1143 int volume;
1144 dprintf_mciwave(stddeb,"wodGetVolume(%u, %p);\n", wDevID, lpdwVol);
1145 if (lpdwVol == NULL) return MMSYSERR_NOTENABLED;
1146 if (WOutDev[wDevID].unixdev == 0) {
1147 fprintf(stderr,"Linux 'wodGetVolume' // can't read volume !\n");
1148 return MMSYSERR_NOTENABLED;
1150 if ((mixer = open("/dev/mixer", O_RDONLY)) < 0) {
1151 fprintf(stderr, "Linux 'wodGetVolume' // mixer device not available !\n");
1152 return MMSYSERR_NOTENABLED;
1154 if (ioctl(mixer, SOUND_MIXER_READ_PCM, &volume) == -1) {
1155 fprintf(stderr,"Linux 'wodGetVolume' // unable read mixer !\n");
1156 return MMSYSERR_NOTENABLED;
1158 close(mixer);
1159 *lpdwVol = MAKELONG(volume, volume);
1160 return MMSYSERR_NOERROR;
1161 #else
1162 return MMSYSERR_NOTENABLED;
1163 #endif
1167 /**************************************************************************
1168 * wodSetVolume [internal]
1170 DWORD wodSetVolume(WORD wDevID, DWORD dwParam)
1172 #ifdef linux
1173 int mixer;
1174 int volume;
1175 dprintf_mciwave(stddeb,"wodSetVolume(%u, %08lX);\n", wDevID, dwParam);
1176 volume = LOWORD(dwParam);
1177 if (WOutDev[wDevID].unixdev == 0) {
1178 fprintf(stderr,"Linux 'wodSetVolume' // can't set volume !\n");
1179 return MMSYSERR_NOTENABLED;
1181 if ((mixer = open("/dev/mixer", O_WRONLY)) < 0) {
1182 fprintf(stderr, "Linux 'wodSetVolume' // mixer device not available !\n");
1183 return MMSYSERR_NOTENABLED;
1185 if (ioctl(mixer, SOUND_MIXER_WRITE_PCM, &volume) == -1) {
1186 fprintf(stderr,"Linux 'wodSetVolume' // unable set mixer !\n");
1187 return MMSYSERR_NOTENABLED;
1189 close(mixer);
1190 return MMSYSERR_NOERROR;
1191 #else
1192 return MMSYSERR_NOTENABLED;
1193 #endif
1197 /**************************************************************************
1198 * wodMessage [sample driver]
1200 DWORD wodMessage(WORD wDevID, WORD wMsg, DWORD dwUser,
1201 DWORD dwParam1, DWORD dwParam2)
1203 dprintf_mciwave(stddeb,"wodMessage(%u, %04X, %08lX, %08lX, %08lX);\n",
1204 wDevID, wMsg, dwUser, dwParam1, dwParam2);
1205 switch(wMsg) {
1206 case WODM_OPEN:
1207 return wodOpen(wDevID, (LPWAVEOPENDESC)dwParam1, dwParam2);
1208 case WODM_CLOSE:
1209 return wodClose(wDevID);
1210 case WODM_WRITE:
1211 return wodWrite(wDevID, (LPWAVEHDR)dwParam1, dwParam2);
1212 case WODM_PAUSE:
1213 return 0L;
1214 case WODM_GETPOS:
1215 return wodGetPosition(wDevID, (LPMMTIME)dwParam1, dwParam2);
1216 case WODM_BREAKLOOP:
1217 return 0L;
1218 case WODM_PREPARE:
1219 return wodPrepare(wDevID, (LPWAVEHDR)dwParam1, dwParam2);
1220 case WODM_UNPREPARE:
1221 return wodUnprepare(wDevID, (LPWAVEHDR)dwParam1, dwParam2);
1222 case WODM_GETDEVCAPS:
1223 return wodGetDevCaps(wDevID, (LPWAVEOUTCAPS)dwParam1, dwParam2);
1224 case WODM_GETNUMDEVS:
1225 return 1L;
1226 case WODM_GETPITCH:
1227 return 0L;
1228 case WODM_SETPITCH:
1229 return 0L;
1230 case WODM_GETPLAYBACKRATE:
1231 return 0L;
1232 case WODM_SETPLAYBACKRATE:
1233 return 0L;
1234 case WODM_GETVOLUME:
1235 return wodGetVolume(wDevID, (LPDWORD)dwParam1);
1236 case WODM_SETVOLUME:
1237 return wodSetVolume(wDevID, dwParam1);
1238 case WODM_RESTART:
1239 return wodRestart(wDevID);
1240 case WODM_RESET:
1241 return wodReset(wDevID);
1243 return MMSYSERR_NOTSUPPORTED;
1247 /*-----------------------------------------------------------------------*/
1249 /**************************************************************************
1250 * widGetDevCaps [internal]
1252 DWORD widGetDevCaps(WORD wDevID, LPWAVEINCAPS lpCaps, DWORD dwSize)
1254 #ifdef linux
1255 int audio;
1256 int smplrate;
1257 int samplesize = 16;
1258 int dsp_stereo = 1;
1259 int bytespersmpl;
1260 dprintf_mciwave(stddeb,
1261 "widGetDevCaps(%u, %p, %lu);\n", wDevID, lpCaps, dwSize);
1262 if (lpCaps == NULL) return MMSYSERR_NOTENABLED;
1263 audio = open (SOUND_DEV, O_RDONLY, 0);
1264 if (audio == -1) return MMSYSERR_NOTENABLED;
1265 #ifdef EMULATE_SB16
1266 lpCaps->wMid = 0x0002;
1267 lpCaps->wPid = 0x0004;
1268 strcpy(lpCaps->szPname, "SB16 Wave Out");
1269 #else
1270 lpCaps->wMid = 0x00FF; /* Manufac ID */
1271 lpCaps->wPid = 0x0001; /* Product ID */
1272 strcpy(lpCaps->szPname, "Linux WAVIN Driver");
1273 #endif
1274 lpCaps->dwFormats = 0x00000000;
1275 lpCaps->wChannels = (IOCTL(audio, SNDCTL_DSP_STEREO, dsp_stereo) != 0) ? 1 : 2;
1276 bytespersmpl = (IOCTL(audio, SNDCTL_DSP_SAMPLESIZE, samplesize) != 0) ? 1 : 2;
1277 smplrate = 44100;
1278 if (IOCTL(audio, SNDCTL_DSP_SPEED, smplrate) == 0) {
1279 lpCaps->dwFormats |= WAVE_FORMAT_4M08;
1280 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_4S08;
1281 if (bytespersmpl > 1) {
1282 lpCaps->dwFormats |= WAVE_FORMAT_4M16;
1283 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_4S16;
1286 smplrate = 22050;
1287 if (IOCTL(audio, SNDCTL_DSP_SPEED, smplrate) == 0) {
1288 lpCaps->dwFormats |= WAVE_FORMAT_2M08;
1289 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_2S08;
1290 if (bytespersmpl > 1) {
1291 lpCaps->dwFormats |= WAVE_FORMAT_2M16;
1292 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_2S16;
1295 smplrate = 11025;
1296 if (IOCTL(audio, SNDCTL_DSP_SPEED, smplrate) == 0) {
1297 lpCaps->dwFormats |= WAVE_FORMAT_1M08;
1298 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_1S08;
1299 if (bytespersmpl > 1) {
1300 lpCaps->dwFormats |= WAVE_FORMAT_1M16;
1301 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_1S16;
1304 close(audio);
1305 dprintf_mciwave(stddeb,
1306 "widGetDevCaps // dwFormats = %08lX\n", lpCaps->dwFormats);
1307 return MMSYSERR_NOERROR;
1308 #else
1309 return MMSYSERR_NOTENABLED;
1310 #endif
1314 /**************************************************************************
1315 * widOpen [internal]
1317 DWORD widOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
1319 #ifdef linux
1320 int audio;
1321 int abuf_size;
1322 int smplrate;
1323 int samplesize;
1324 int dsp_stereo;
1325 dprintf_mciwave(stddeb,
1326 "widOpen(%u, %p, %08lX);\n", wDevID, lpDesc, dwFlags);
1327 if (lpDesc == NULL) {
1328 fprintf(stderr,"Linux 'widOpen' // Invalid Parameter !\n");
1329 return MMSYSERR_INVALPARAM;
1331 if (wDevID >= MAX_WAVINDRV) {
1332 fprintf(stderr,"Linux 'widOpen' // MAX_WAVINDRV reached !\n");
1333 return MMSYSERR_ALLOCATED;
1335 WInDev[wDevID].unixdev = 0;
1336 audio = open (SOUND_DEV, O_RDONLY, 0);
1337 if (audio == -1) {
1338 fprintf(stderr,"Linux 'widOpen' // can't open !\n");
1339 return MMSYSERR_NOTENABLED;
1341 IOCTL(audio, SNDCTL_DSP_GETBLKSIZE, abuf_size);
1342 if (abuf_size < 4096 || abuf_size > 65536) {
1343 if (abuf_size == -1)
1344 fprintf(stderr,"Linux 'widOpen' // IOCTL can't 'SNDCTL_DSP_GETBLKSIZE' !\n");
1345 else
1346 fprintf(stderr,"Linux 'widOpen' // SNDCTL_DSP_GETBLKSIZE Invalid bufsize !\n");
1347 return MMSYSERR_NOTENABLED;
1349 WInDev[wDevID].wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
1350 switch(WInDev[wDevID].wFlags) {
1351 case DCB_NULL:
1352 dprintf_mciwave(stddeb,
1353 "Linux 'widOpen' // CALLBACK_NULL !\n");
1354 break;
1355 case DCB_WINDOW:
1356 dprintf_mciwave(stddeb,
1357 "Linux 'widOpen' // CALLBACK_WINDOW !\n");
1358 break;
1359 case DCB_TASK:
1360 dprintf_mciwave(stddeb,
1361 "Linux 'widOpen' // CALLBACK_TASK !\n");
1362 break;
1363 case DCB_FUNCTION:
1364 dprintf_mciwave(stddeb,
1365 "Linux 'widOpen' // CALLBACK_FUNCTION !\n");
1366 break;
1368 WInDev[wDevID].lpQueueHdr = NULL;
1369 WInDev[wDevID].unixdev = audio;
1370 WInDev[wDevID].bufsize = abuf_size;
1371 WInDev[wDevID].dwTotalRecorded = 0;
1372 memcpy(&WInDev[wDevID].waveDesc, lpDesc, sizeof(WAVEOPENDESC));
1373 if (lpDesc->lpFormat->wFormatTag != WAVE_FORMAT_PCM) {
1374 fprintf(stderr,"Linux 'widOpen' // Bad format %04X !\n",
1375 lpDesc->lpFormat->wFormatTag);
1376 return WAVERR_BADFORMAT;
1378 memcpy(&WInDev[wDevID].Format, lpDesc->lpFormat, sizeof(PCMWAVEFORMAT));
1379 WInDev[wDevID].Format.wBitsPerSample = 8; /* <-------------- */
1380 if (WInDev[wDevID].Format.wf.nChannels == 0) return WAVERR_BADFORMAT;
1381 if (WInDev[wDevID].Format.wf.nSamplesPerSec == 0) return WAVERR_BADFORMAT;
1382 if (WInDev[wDevID].Format.wBitsPerSample == 0) {
1383 WInDev[wDevID].Format.wBitsPerSample = 8 *
1384 (WInDev[wDevID].Format.wf.nAvgBytesPerSec /
1385 WInDev[wDevID].Format.wf.nSamplesPerSec) /
1386 WInDev[wDevID].Format.wf.nChannels;
1388 samplesize = WInDev[wDevID].Format.wBitsPerSample;
1389 smplrate = WInDev[wDevID].Format.wf.nSamplesPerSec;
1390 dsp_stereo = (WInDev[wDevID].Format.wf.nChannels > 1) ? TRUE : FALSE;
1391 IOCTL(audio, SNDCTL_DSP_SPEED, smplrate);
1392 IOCTL(audio, SNDCTL_DSP_SAMPLESIZE, samplesize);
1393 IOCTL(audio, SNDCTL_DSP_STEREO, dsp_stereo);
1394 dprintf_mciwave(stddeb,"Linux 'widOpen' // wBitsPerSample=%u !\n",
1395 WInDev[wDevID].Format.wBitsPerSample);
1396 dprintf_mciwave(stddeb,"Linux 'widOpen' // nSamplesPerSec=%lu !\n",
1397 WInDev[wDevID].Format.wf.nSamplesPerSec);
1398 dprintf_mciwave(stddeb,"Linux 'widOpen' // nChannels=%u !\n",
1399 WInDev[wDevID].Format.wf.nChannels);
1400 dprintf_mciwave(stddeb,"Linux 'widOpen' // nAvgBytesPerSec=%lu\n",
1401 WInDev[wDevID].Format.wf.nAvgBytesPerSec);
1402 if (WAVE_NotifyClient(wDevID, WIM_OPEN, 0L, 0L) != MMSYSERR_NOERROR) {
1403 fprintf(stderr,"Linux 'widOpen' // can't notify client !\n");
1404 return MMSYSERR_INVALPARAM;
1406 return MMSYSERR_NOERROR;
1407 #else
1408 return MMSYSERR_NOTENABLED;
1409 #endif
1412 /**************************************************************************
1413 * widClose [internal]
1415 DWORD widClose(WORD wDevID)
1417 #ifdef linux
1418 dprintf_mciwave(stddeb,"widClose(%u);\n", wDevID);
1419 if (WInDev[wDevID].unixdev == 0) {
1420 fprintf(stderr,"Linux 'widClose' // can't close !\n");
1421 return MMSYSERR_NOTENABLED;
1423 close(WInDev[wDevID].unixdev);
1424 WInDev[wDevID].unixdev = 0;
1425 WInDev[wDevID].bufsize = 0;
1426 if (WAVE_NotifyClient(wDevID, WIM_CLOSE, 0L, 0L) != MMSYSERR_NOERROR) {
1427 fprintf(stderr,"Linux 'widClose' // can't notify client !\n");
1428 return MMSYSERR_INVALPARAM;
1430 return MMSYSERR_NOERROR;
1431 #else
1432 return MMSYSERR_NOTENABLED;
1433 #endif
1436 /**************************************************************************
1437 * widAddBuffer [internal]
1439 DWORD widAddBuffer(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
1441 #ifdef linux
1442 int count = 1;
1443 LPWAVEHDR lpWIHdr;
1444 dprintf_mciwave(stddeb,
1445 "widAddBuffer(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
1446 if (WInDev[wDevID].unixdev == 0) {
1447 fprintf(stderr,"Linux 'widAddBuffer' // can't do it !\n");
1448 return MMSYSERR_NOTENABLED;
1450 if (WInDev[wDevID].lpQueueHdr == NULL ||
1451 !(lpWaveHdr->dwFlags & WHDR_PREPARED)) {
1452 fprintf(stderr,
1453 "Linux 'widAddBuffer' // never been prepared !\n");
1454 return WAVERR_UNPREPARED;
1456 if ((lpWaveHdr->dwFlags & WHDR_INQUEUE) &&
1457 (WInDev[wDevID].lpQueueHdr != lpWaveHdr)) {
1458 /* except if it's the one just prepared ... */
1459 fprintf(stderr,
1460 "Linux 'widAddBuffer' // header already in use !\n");
1461 return WAVERR_STILLPLAYING;
1463 lpWaveHdr->dwFlags |= WHDR_PREPARED;
1464 lpWaveHdr->dwFlags |= WHDR_INQUEUE;
1465 lpWaveHdr->dwFlags &= ~WHDR_DONE;
1466 lpWaveHdr->dwBytesRecorded = 0;
1467 /* added to the queue, except if it's the one just prepared ... */
1468 if (WInDev[wDevID].lpQueueHdr != lpWaveHdr) {
1469 lpWIHdr = WInDev[wDevID].lpQueueHdr;
1470 while (lpWIHdr->lpNext != NULL) {
1471 lpWIHdr = lpWIHdr->lpNext;
1472 count++;
1474 lpWIHdr->lpNext = lpWaveHdr;
1475 count++;
1477 dprintf_mciwave(stddeb,
1478 "widAddBuffer // buffer added ! (now %u in queue)\n", count);
1479 return MMSYSERR_NOERROR;
1480 #else
1481 return MMSYSERR_NOTENABLED;
1482 #endif
1485 /**************************************************************************
1486 * widPrepare [internal]
1488 DWORD widPrepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
1490 #ifdef linux
1491 dprintf_mciwave(stddeb,
1492 "widPrepare(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
1493 if (WInDev[wDevID].unixdev == 0) {
1494 fprintf(stderr,"Linux 'widPrepare' // can't prepare !\n");
1495 return MMSYSERR_NOTENABLED;
1497 if (WInDev[wDevID].lpQueueHdr != NULL) {
1498 fprintf(stderr,"Linux 'widPrepare' // already prepare !\n");
1499 return WAVERR_BADFORMAT;
1501 WInDev[wDevID].dwTotalRecorded = 0;
1502 WInDev[wDevID].lpQueueHdr = lpWaveHdr;
1503 if (lpWaveHdr->dwFlags & WHDR_INQUEUE) return WAVERR_STILLPLAYING;
1504 lpWaveHdr->dwFlags |= WHDR_PREPARED;
1505 lpWaveHdr->dwFlags |= WHDR_INQUEUE;
1506 lpWaveHdr->dwFlags &= ~WHDR_DONE;
1507 lpWaveHdr->dwBytesRecorded = 0;
1508 dprintf_mciwave(stddeb,"Linux 'widPrepare' // header prepared !\n");
1509 return MMSYSERR_NOERROR;
1510 #else
1511 return MMSYSERR_NOTENABLED;
1512 #endif
1515 /**************************************************************************
1516 * widUnprepare [internal]
1518 DWORD widUnprepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
1520 #ifdef linux
1521 dprintf_mciwave(stddeb,
1522 "widUnprepare(%u, %p, %08lX);\n", wDevID, lpWaveHdr, dwSize);
1523 if (WInDev[wDevID].unixdev == 0) {
1524 fprintf(stderr,"Linux 'widUnprepare' // can't unprepare !\n");
1525 return MMSYSERR_NOTENABLED;
1527 lpWaveHdr->dwFlags &= ~WHDR_PREPARED;
1528 lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
1529 lpWaveHdr->dwFlags |= WHDR_DONE;
1530 WInDev[wDevID].lpQueueHdr = NULL;
1531 dprintf_mciwave(stddeb,
1532 "Linux 'widUnprepare' // all headers unprepared !\n");
1533 return MMSYSERR_NOERROR;
1534 #else
1535 return MMSYSERR_NOTENABLED;
1536 #endif
1539 /**************************************************************************
1540 * widStart [internal]
1542 DWORD widStart(WORD wDevID)
1544 #ifdef linux
1545 int count = 1;
1546 LPWAVEHDR lpWIHdr;
1547 dprintf_mciwave(stddeb,"widStart(%u);\n", wDevID);
1548 if (WInDev[wDevID].unixdev == 0) {
1549 fprintf(stderr,
1550 "Linux 'widStart' // can't start recording !\n");
1551 return MMSYSERR_NOTENABLED;
1553 if (WInDev[wDevID].lpQueueHdr == NULL ||
1554 WInDev[wDevID].lpQueueHdr->lpData == NULL) {
1555 fprintf(stderr,"Linux 'widStart' // never been prepared !\n");
1556 return WAVERR_UNPREPARED;
1558 lpWIHdr = WInDev[wDevID].lpQueueHdr;
1559 while(lpWIHdr != NULL) {
1560 lpWIHdr->dwBufferLength &= 0xFFFF;
1561 dprintf_mciwave(stddeb,
1562 "widStart // recording buf#%u=%p size=%lu \n",
1563 count, lpWIHdr->lpData, lpWIHdr->dwBufferLength);
1564 fflush(stddeb);
1565 read (WInDev[wDevID].unixdev, lpWIHdr->lpData,
1566 lpWIHdr->dwBufferLength);
1567 lpWIHdr->dwBytesRecorded = lpWIHdr->dwBufferLength;
1568 WInDev[wDevID].dwTotalRecorded += lpWIHdr->dwBytesRecorded;
1569 lpWIHdr->dwFlags &= ~WHDR_INQUEUE;
1570 lpWIHdr->dwFlags |= WHDR_DONE;
1571 if (WAVE_NotifyClient(wDevID, WIM_DATA, (DWORD)lpWIHdr, 0L) !=
1572 MMSYSERR_NOERROR) {
1573 fprintf(stderr,
1574 "Linux 'widStart' // can't notify client !\n");
1575 return MMSYSERR_INVALPARAM;
1577 lpWIHdr = lpWIHdr->lpNext;
1578 count++;
1580 dprintf_mciwave(stddeb,"widStart // end of recording !\n");
1581 fflush(stdout);
1582 return MMSYSERR_NOERROR;
1583 #else
1584 return MMSYSERR_NOTENABLED;
1585 #endif
1588 /**************************************************************************
1589 * widStop [internal]
1591 DWORD widStop(WORD wDevID)
1593 #ifdef linux
1594 dprintf_mciwave(stddeb,"widStop(%u);\n", wDevID);
1595 if (WInDev[wDevID].unixdev == 0) {
1596 fprintf(stderr,"Linux 'widStop' // can't stop !\n");
1597 return MMSYSERR_NOTENABLED;
1599 return MMSYSERR_NOERROR;
1600 #else
1601 return MMSYSERR_NOTENABLED;
1602 #endif
1605 /**************************************************************************
1606 * widReset [internal]
1608 DWORD widReset(WORD wDevID)
1610 #ifdef linux
1611 dprintf_mciwave(stddeb,"widReset(%u);\n", wDevID);
1612 if (WInDev[wDevID].unixdev == 0) {
1613 fprintf(stderr,"Linux 'widReset' // can't reset !\n");
1614 return MMSYSERR_NOTENABLED;
1616 return MMSYSERR_NOERROR;
1617 #else
1618 return MMSYSERR_NOTENABLED;
1619 #endif
1622 /**************************************************************************
1623 * widGetPosition [internal]
1625 DWORD widGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize)
1627 #ifdef linux
1628 int time;
1629 dprintf_mciwave(stddeb,
1630 "widGetPosition(%u, %p, %lu);\n", wDevID, lpTime, uSize);
1631 if (WInDev[wDevID].unixdev == 0) {
1632 fprintf(stderr,"Linux 'widGetPosition' // can't get pos !\n");
1633 return MMSYSERR_NOTENABLED;
1635 if (lpTime == NULL) return MMSYSERR_INVALPARAM;
1636 TryAGAIN:
1637 dprintf_mciwave(stddeb,"widGetPosition // wType=%04X !\n",
1638 lpTime->wType);
1639 dprintf_mciwave(stddeb,"widGetPosition // wBitsPerSample=%u\n",
1640 WInDev[wDevID].Format.wBitsPerSample);
1641 dprintf_mciwave(stddeb,"widGetPosition // nSamplesPerSec=%lu\n",
1642 WInDev[wDevID].Format.wf.nSamplesPerSec);
1643 dprintf_mciwave(stddeb,"widGetPosition // nChannels=%u\n",
1644 WInDev[wDevID].Format.wf.nChannels);
1645 dprintf_mciwave(stddeb,"widGetPosition // nAvgBytesPerSec=%lu\n",
1646 WInDev[wDevID].Format.wf.nAvgBytesPerSec);
1647 fflush(stddeb);
1648 switch(lpTime->wType) {
1649 case TIME_BYTES:
1650 lpTime->u.cb = WInDev[wDevID].dwTotalRecorded;
1651 dprintf_mciwave(stddeb,
1652 "widGetPosition // TIME_BYTES=%lu\n", lpTime->u.cb);
1653 break;
1654 case TIME_SAMPLES:
1655 lpTime->u.sample = WInDev[wDevID].dwTotalRecorded * 8 /
1656 WInDev[wDevID].Format.wBitsPerSample;
1657 dprintf_mciwave(stddeb,
1658 "widGetPosition // TIME_SAMPLES=%lu\n",
1659 lpTime->u.sample);
1660 break;
1661 case TIME_MS:
1662 lpTime->u.ms = WInDev[wDevID].dwTotalRecorded /
1663 (WInDev[wDevID].Format.wf.nAvgBytesPerSec / 1000);
1664 dprintf_mciwave(stddeb,
1665 "widGetPosition // TIME_MS=%lu\n", lpTime->u.ms);
1666 break;
1667 case TIME_SMPTE:
1668 time = WInDev[wDevID].dwTotalRecorded /
1669 (WInDev[wDevID].Format.wf.nAvgBytesPerSec / 1000);
1670 lpTime->u.smpte.hour = time / 108000;
1671 time -= lpTime->u.smpte.hour * 108000;
1672 lpTime->u.smpte.min = time / 1800;
1673 time -= lpTime->u.smpte.min * 1800;
1674 lpTime->u.smpte.sec = time / 30;
1675 time -= lpTime->u.smpte.sec * 30;
1676 lpTime->u.smpte.frame = time;
1677 lpTime->u.smpte.fps = 30;
1678 dprintf_mciwave(stddeb,"widGetPosition // TIME_SMPTE=%02u:%02u:%02u:%02u\n",
1679 lpTime->u.smpte.hour, lpTime->u.smpte.min,
1680 lpTime->u.smpte.sec, lpTime->u.smpte.frame);
1681 break;
1682 default:
1683 fprintf(stderr,"widGetPosition() format not supported ! use TIME_MS !\n");
1684 lpTime->wType = TIME_MS;
1685 goto TryAGAIN;
1687 return MMSYSERR_NOERROR;
1688 #else
1689 return MMSYSERR_NOTENABLED;
1690 #endif
1693 /**************************************************************************
1694 * widMessage [sample driver]
1696 DWORD widMessage(WORD wDevID, WORD wMsg, DWORD dwUser,
1697 DWORD dwParam1, DWORD dwParam2)
1699 dprintf_mciwave(stddeb,"widMessage(%u, %04X, %08lX, %08lX, %08lX);\n",
1700 wDevID, wMsg, dwUser, dwParam1, dwParam2);
1701 switch(wMsg) {
1702 case WIDM_OPEN:
1703 return widOpen(wDevID, (LPWAVEOPENDESC)dwParam1, dwParam2);
1704 case WIDM_CLOSE:
1705 return widClose(wDevID);
1706 case WIDM_ADDBUFFER:
1707 return widAddBuffer(wDevID, (LPWAVEHDR)dwParam1, dwParam2);
1708 case WIDM_PREPARE:
1709 return widPrepare(wDevID, (LPWAVEHDR)dwParam1, dwParam2);
1710 case WIDM_UNPREPARE:
1711 return widUnprepare(wDevID, (LPWAVEHDR)dwParam1, dwParam2);
1712 case WIDM_GETDEVCAPS:
1713 return widGetDevCaps(wDevID, (LPWAVEINCAPS)dwParam1, dwParam2);
1714 case WIDM_GETNUMDEVS:
1715 return 1L;
1716 case WIDM_GETPOS:
1717 return widGetPosition(wDevID, (LPMMTIME)dwParam1, dwParam2);
1718 case WIDM_RESET:
1719 return widReset(wDevID);
1720 case WIDM_START:
1721 return widStart(wDevID);
1722 case WIDM_STOP:
1723 return widStop(wDevID);
1725 return MMSYSERR_NOTSUPPORTED;
1729 #endif /* #ifdef BUILTIN_MMSYSTEM */