Release 941030
[wine/hacks.git] / misc / audio.c
blob42e63ee5ce3a19f79d08c265dc6a029e818cc956
1 /*
2 * Sample Wine Driver for Linux
4 * Copyright 1994 Martin Ayotte
5 */
6 static char Copyright[] = "Copyright Martin Ayotte, 1994";
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 "win.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 /* #define DEBUG_MCIWAVE /* */
32 /* #undef DEBUG_MCIWAVE /* */
33 #include "debug.h"
35 #ifdef linux
36 #define SOUND_DEV "/dev/dsp"
38 #ifdef SOUND_VERSION
39 #define IOCTL(a,b,c) ioctl(a,b,&c)
40 #else
41 #define IOCTL(a,b,c) (c = ioctl(a,b,c) )
42 #endif
44 #define MAX_WAVOUTDRV 2
45 #define MAX_WAVINDRV 2
46 #define MAX_MCIWAVDRV 2
48 typedef struct {
49 int unixdev;
50 int state;
51 DWORD bufsize;
52 WAVEOPENDESC waveDesc;
53 WORD wFlags;
54 PCMWAVEFORMAT Format;
55 LPWAVEHDR lpQueueHdr;
56 DWORD dwTotalPlayed;
57 } LINUX_WAVEOUT;
59 typedef struct {
60 int unixdev;
61 int state;
62 DWORD bufsize; /* Linux '/dev/dsp' give us that size */
63 WAVEOPENDESC waveDesc;
64 WORD wFlags;
65 PCMWAVEFORMAT Format;
66 LPWAVEHDR lpQueueHdr;
67 DWORD dwTotalRecorded;
68 } LINUX_WAVEIN;
70 typedef struct {
71 int nUseCount; /* Incremented for each shared open */
72 BOOL fShareable; /* TRUE if first open was shareable */
73 WORD wNotifyDeviceID; /* MCI device ID with a pending notification */
74 HANDLE hCallback; /* Callback handle for pending notification */
75 HMMIO hFile; /* mmio file handle open as Element */
76 MCI_WAVE_OPEN_PARMS openParms;
77 PCMWAVEFORMAT WaveFormat;
78 WAVEHDR WaveHdr;
79 } LINUX_MCIWAVE;
81 static LINUX_WAVEOUT WOutDev[MAX_WAVOUTDRV];
82 static LINUX_WAVEIN WInDev[MAX_WAVOUTDRV];
83 static LINUX_MCIWAVE MCIWavDev[MAX_MCIWAVDRV];
84 #endif
86 DWORD WAVE_mciOpen(DWORD dwFlags, LPMCI_WAVE_OPEN_PARMS lpParms);
87 DWORD WAVE_mciClose(UINT wDevID, DWORD dwParam, LPMCI_GENERIC_PARMS lpParms);
88 DWORD WAVE_mciPlay(UINT wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms);
89 DWORD WAVE_mciRecord(UINT wDevID, DWORD dwFlags, LPMCI_RECORD_PARMS lpParms);
90 DWORD WAVE_mciStop(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms);
91 DWORD WAVE_mciPause(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms);
92 DWORD WAVE_mciResume(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms);
93 DWORD WAVE_mciSet(UINT wDevID, DWORD dwFlags, LPMCI_SET_PARMS lpParms);
94 DWORD WAVE_mciStatus(UINT wDevID, DWORD dwFlags, LPMCI_STATUS_PARMS lpParms);
95 DWORD WAVE_mciGetDevCaps(UINT wDevID, DWORD dwFlags, LPMCI_GETDEVCAPS_PARMS lpParms);
96 DWORD WAVE_mciInfo(UINT wDevID, DWORD dwFlags, LPMCI_INFO_PARMS lpParms);
98 DWORD wodGetDevCaps(WORD wDevID, LPWAVEOUTCAPS lpCaps, DWORD dwSize);
99 DWORD wodOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags);
100 DWORD wodClose(WORD wDevID);
101 DWORD wodWrite(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize);
102 DWORD wodPrepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize);
103 DWORD wodUnprepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize);
106 /**************************************************************************
107 * WAVE_NotifyClient [internal]
109 DWORD WAVE_NotifyClient(UINT wDevID, WORD wMsg,
110 DWORD dwParam1, DWORD dwParam2)
112 #ifdef linux
113 if (WInDev[wDevID].wFlags != DCB_NULL && !DriverCallback(
114 WInDev[wDevID].waveDesc.dwCallBack, WInDev[wDevID].wFlags,
115 WInDev[wDevID].waveDesc.hWave, wMsg,
116 WInDev[wDevID].waveDesc.dwInstance, dwParam1, dwParam2)) {
117 fprintf(stderr,"WAVE_NotifyClient // can't notify client !\n");
118 return MMSYSERR_NOERROR;
120 #else
121 return MMSYSERR_NOTENABLED;
122 #endif
126 /**************************************************************************
127 * AUDIO_DriverProc [sample driver]
129 LRESULT WAVE_DriverProc(DWORD dwDevID, HDRVR hDriv, WORD wMsg,
130 DWORD dwParam1, DWORD dwParam2)
132 #ifdef linux
133 switch(wMsg) {
134 case DRV_LOAD:
135 return (LRESULT)1L;
136 case DRV_FREE:
137 return (LRESULT)1L;
138 case DRV_OPEN:
139 return (LRESULT)1L;
140 case DRV_CLOSE:
141 return (LRESULT)1L;
142 case DRV_ENABLE:
143 return (LRESULT)1L;
144 case DRV_DISABLE:
145 return (LRESULT)1L;
146 case DRV_QUERYCONFIGURE:
147 return (LRESULT)1L;
148 case DRV_CONFIGURE:
149 MessageBox((HWND)NULL, "Sample MultiMedia Linux Driver !",
150 "MMLinux Driver", MB_OK);
151 return (LRESULT)1L;
152 case DRV_INSTALL:
153 return (LRESULT)DRVCNF_RESTART;
154 case DRV_REMOVE:
155 return (LRESULT)DRVCNF_RESTART;
156 case MCI_OPEN_DRIVER:
157 case MCI_OPEN:
158 return WAVE_mciOpen(dwParam1, (LPMCI_WAVE_OPEN_PARMS)dwParam2);
159 case MCI_CLOSE_DRIVER:
160 case MCI_CLOSE:
161 return WAVE_mciClose(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)dwParam2);
162 case MCI_PLAY:
163 return WAVE_mciPlay(dwDevID, dwParam1, (LPMCI_PLAY_PARMS)dwParam2);
164 case MCI_RECORD:
165 return WAVE_mciRecord(dwDevID, dwParam1, (LPMCI_RECORD_PARMS)dwParam2);
166 case MCI_STOP:
167 return WAVE_mciStop(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)dwParam2);
168 case MCI_SET:
169 return WAVE_mciSet(dwDevID, dwParam1, (LPMCI_SET_PARMS)dwParam2);
170 case MCI_PAUSE:
171 return WAVE_mciPause(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)dwParam2);
172 case MCI_RESUME:
173 return WAVE_mciResume(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)dwParam2);
174 case MCI_STATUS:
175 return WAVE_mciStatus(dwDevID, dwParam1, (LPMCI_STATUS_PARMS)dwParam2);
176 case MCI_GETDEVCAPS:
177 return WAVE_mciGetDevCaps(dwDevID, dwParam1, (LPMCI_GETDEVCAPS_PARMS)dwParam2);
178 case MCI_INFO:
179 return WAVE_mciInfo(dwDevID, dwParam1, (LPMCI_INFO_PARMS)dwParam2);
180 default:
181 return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);
183 #else
184 return MMSYSERR_NOTENABLED;
185 #endif
188 /**************************************************************************
189 * WAVE_mciOpen */
190 DWORD WAVE_mciOpen(DWORD dwFlags, LPMCI_WAVE_OPEN_PARMS lpParms)
192 #ifdef linux
193 int hFile;
194 UINT wDevID;
195 OFSTRUCT OFstruct;
196 LPPCMWAVEFORMAT lpWaveFormat;
197 WAVEOPENDESC WaveDesc;
198 DWORD dwRet;
199 char str[128];
200 LPSTR ptr;
201 dprintf_mciwave(stddeb,"WAVE_mciOpen(%08X, %08X)\n", dwFlags, lpParms);
202 if (lpParms == NULL) return MCIERR_INTERNAL;
203 wDevID = lpParms->wDeviceID;
204 if (MCIWavDev[wDevID].nUseCount > 0) {
205 /* The driver already open on this channel */
206 /* If the driver was opened shareable before and this open specifies */
207 /* shareable then increment the use count */
208 if (MCIWavDev[wDevID].fShareable && (dwFlags & MCI_OPEN_SHAREABLE))
209 ++MCIWavDev[wDevID].nUseCount;
210 else
211 return MCIERR_MUST_USE_SHAREABLE;
213 else {
214 MCIWavDev[wDevID].nUseCount = 1;
215 MCIWavDev[wDevID].fShareable = dwFlags & MCI_OPEN_SHAREABLE;
217 if (dwFlags & MCI_OPEN_ELEMENT) {
218 dprintf_mciwave(stddeb,"WAVE_mciOpen // MCI_OPEN_ELEMENT '%s' !\n",
219 lpParms->lpstrElementName);
220 /* printf("WAVE_mciOpen // cdw='%s'\n", DOS_GetCurrentDir(DOS_GetDefaultDrive())); */
221 if (strlen(lpParms->lpstrElementName) > 0) {
222 strcpy(str, lpParms->lpstrElementName);
223 AnsiUpper(str);
224 MCIWavDev[wDevID].hFile = mmioOpen(str, NULL,
225 MMIO_ALLOCBUF | MMIO_READWRITE | MMIO_EXCLUSIVE);
226 if (MCIWavDev[wDevID].hFile == 0) {
227 fprintf(stderr,"WAVE_mciOpen // can't find file='%s' !\n", str);
228 return MCIERR_FILE_NOT_FOUND;
231 else
232 MCIWavDev[wDevID].hFile = 0;
234 dprintf_mciwave(stddeb,"WAVE_mciOpen // hFile=%u\n", MCIWavDev[wDevID].hFile);
235 memcpy(&MCIWavDev[wDevID].openParms, lpParms, sizeof(MCI_WAVE_OPEN_PARMS));
236 MCIWavDev[wDevID].wNotifyDeviceID = lpParms->wDeviceID;
237 lpWaveFormat = &MCIWavDev[wDevID].WaveFormat;
238 WaveDesc.hWave = 0;
239 WaveDesc.lpFormat = (LPWAVEFORMAT)lpWaveFormat;
240 lpWaveFormat->wf.wFormatTag = WAVE_FORMAT_PCM;
241 lpWaveFormat->wBitsPerSample = 8;
242 lpWaveFormat->wf.nChannels = 1;
243 lpWaveFormat->wf.nSamplesPerSec = 11025;
244 lpWaveFormat->wf.nAvgBytesPerSec = 11025;
245 lpWaveFormat->wf.nBlockAlign = 1;
246 if (MCIWavDev[wDevID].hFile != 0) {
247 MMCKINFO mmckInfo;
248 MMCKINFO ckMainRIFF;
249 if (mmioDescend(MCIWavDev[wDevID].hFile, &ckMainRIFF, NULL, 0) != 0) {
250 return MCIERR_INTERNAL;
252 dprintf_mciwave(stddeb,
253 "WAVE_mciOpen // ParentChunk ckid=%.4s fccType=%.4s cksize=%08lX \n",
254 (LPSTR)&ckMainRIFF.ckid, (LPSTR)&ckMainRIFF.fccType,
255 ckMainRIFF.cksize);
256 if ((ckMainRIFF.ckid != FOURCC_RIFF) ||
257 (ckMainRIFF.fccType != mmioFOURCC('W', 'A', 'V', 'E'))) {
258 return MCIERR_INTERNAL;
260 mmckInfo.ckid = mmioFOURCC('f', 'm', 't', ' ');
261 if (mmioDescend(MCIWavDev[wDevID].hFile, &mmckInfo, &ckMainRIFF, MMIO_FINDCHUNK) != 0) {
262 return MCIERR_INTERNAL;
264 dprintf_mciwave(stddeb,
265 "WAVE_mciOpen // Chunk Found ckid=%.4s fccType=%.4s cksize=%08lX \n",
266 (LPSTR)&mmckInfo.ckid, (LPSTR)&mmckInfo.fccType,
267 mmckInfo.cksize);
268 if (mmioRead(MCIWavDev[wDevID].hFile, (HPSTR) lpWaveFormat,
269 (long) sizeof(PCMWAVEFORMAT)) != (long) sizeof(PCMWAVEFORMAT)) {
270 return MCIERR_INTERNAL;
272 mmckInfo.ckid = mmioFOURCC('d', 'a', 't', 'a');
273 if (mmioDescend(MCIWavDev[wDevID].hFile, &mmckInfo, &ckMainRIFF, MMIO_FINDCHUNK) != 0) {
274 return MCIERR_INTERNAL;
276 dprintf_mciwave(stddeb,
277 "WAVE_mciOpen // Chunk Found ckid=%.4s fccType=%.4s cksize=%08lX \n",
278 (LPSTR)&mmckInfo.ckid, (LPSTR)&mmckInfo.fccType,
279 mmckInfo.cksize);
280 dprintf_mciwave(stddeb,
281 "WAVE_mciOpen // nChannels=%d nSamplesPerSec=%d\n",
282 lpWaveFormat->wf.nChannels, lpWaveFormat->wf.nSamplesPerSec);
283 lpWaveFormat->wBitsPerSample = 0;
285 lpWaveFormat->wf.nAvgBytesPerSec =
286 lpWaveFormat->wf.nSamplesPerSec * lpWaveFormat->wf.nBlockAlign;
287 dwRet = wodMessage(0, WODM_OPEN, 0, (DWORD)&WaveDesc, CALLBACK_NULL);
288 dwRet = widMessage(0, WIDM_OPEN, 0, (DWORD)&WaveDesc, CALLBACK_NULL);
289 return 0;
290 #else
291 return MMSYSERR_NOTENABLED;
292 #endif
295 /**************************************************************************
296 * WAVE_mciClose [internal]
298 DWORD WAVE_mciClose(UINT wDevID, DWORD dwParam, LPMCI_GENERIC_PARMS lpParms)
300 #ifdef linux
301 DWORD dwRet;
302 dprintf_mciwave(stddeb,
303 "WAVE_mciClose(%u, %08X, %08X);\n", wDevID, dwParam, lpParms);
304 MCIWavDev[wDevID].nUseCount--;
305 if (MCIWavDev[wDevID].nUseCount == 0) {
306 if (MCIWavDev[wDevID].hFile != 0) {
307 close(MCIWavDev[wDevID].hFile);
308 MCIWavDev[wDevID].hFile = 0;
310 dwRet = wodMessage(0, WODM_CLOSE, 0, 0L, 0L);
311 if (dwRet != MMSYSERR_NOERROR) return MCIERR_INTERNAL;
312 dwRet = widMessage(0, WIDM_CLOSE, 0, 0L, 0L);
313 if (dwRet != MMSYSERR_NOERROR) return MCIERR_INTERNAL;
315 return 0;
316 #else
317 return 0;
318 #endif
322 /**************************************************************************
323 * WAVE_mciPlay [internal]
325 DWORD WAVE_mciPlay(UINT wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms)
327 #ifdef linux
328 int count;
329 int start, end;
330 LPWAVEHDR lpWaveHdr;
331 DWORD dwRet;
332 dprintf_mciwave(stddeb,
333 "WAVE_mciPlay(%u, %08X, %08X);\n", wDevID, dwFlags, lpParms);
334 if (MCIWavDev[wDevID].hFile == 0) {
335 fprintf(stderr,"WAVE_mciPlay // can't find file='%s' !\n",
336 MCIWavDev[wDevID].openParms.lpstrElementName);
337 return MCIERR_FILE_NOT_FOUND;
339 start = 1; end = 99999;
340 if (dwFlags & MCI_FROM) {
341 start = lpParms->dwFrom;
342 dprintf_mciwave(stddeb,
343 "WAVE_mciPlay // MCI_FROM=%d \n", start);
345 if (dwFlags & MCI_TO) {
346 end = lpParms->dwTo;
347 dprintf_mciwave(stddeb,"WAVE_mciPlay // MCI_TO=%d \n", end);
349 /**/
350 if (dwFlags & MCI_NOTIFY) {
351 dprintf_mciwave(stddeb,
352 "WAVE_mciPlay // MCI_NOTIFY %08X !\n", lpParms->dwCallback);
353 switch(fork()) {
354 case -1:
355 fprintf(stderr,
356 "WAVE_mciPlay // Can't 'fork' process !\n");
357 break;
358 case 0:
359 break;
360 default:
361 dprintf_mciwave(stddeb,"WAVE_mciPlay // process started ! return to caller...\n");
362 return 0;
365 /**/
366 lpWaveHdr = &MCIWavDev[wDevID].WaveHdr;
367 lpWaveHdr->lpData = (LPSTR) malloc(64000);
368 lpWaveHdr->dwBufferLength = 32000;
369 lpWaveHdr->dwUser = 0L;
370 lpWaveHdr->dwFlags = 0L;
371 lpWaveHdr->dwLoops = 0L;
372 dwRet = wodMessage(0, WODM_PREPARE, 0, (DWORD)lpWaveHdr, sizeof(WAVEHDR));
373 /* printf("WAVE_mciPlay // after WODM_PREPARE \n"); */
374 while(TRUE) {
375 count = mmioRead(MCIWavDev[wDevID].hFile, lpWaveHdr->lpData, lpWaveHdr->dwBufferLength);
376 if (count < 1) break;
377 lpWaveHdr->dwBytesRecorded = count;
378 dprintf_mciwave(stddeb,"WAVE_mciPlay // before WODM_WRITE lpWaveHdr=%08X dwBytesRecorded=%u\n",
379 lpWaveHdr, lpWaveHdr->dwBytesRecorded);
380 dwRet = wodMessage(0, WODM_WRITE, 0, (DWORD)lpWaveHdr, sizeof(WAVEHDR));
382 dwRet = wodMessage(0, WODM_UNPREPARE, 0, (DWORD)lpWaveHdr, sizeof(WAVEHDR));
383 if (lpWaveHdr->lpData != NULL) {
384 free(lpWaveHdr->lpData);
385 lpWaveHdr->lpData = NULL;
387 if (dwFlags & MCI_NOTIFY) {
388 dprintf_mciwave(stddeb,"WAVE_mciPlay // MCI_NOTIFY_SUCCESSFUL %08X !\n", lpParms->dwCallback);
389 mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
390 MCIWavDev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
392 return 0;
393 #else
394 return MMSYSERR_NOTENABLED;
395 #endif
399 /**************************************************************************
400 * WAVE_mciRecord [internal]
402 DWORD WAVE_mciRecord(UINT wDevID, DWORD dwFlags, LPMCI_RECORD_PARMS lpParms)
404 #ifdef linux
405 int count;
406 int start, end;
407 LPWAVEHDR lpWaveHdr;
408 DWORD dwRet;
409 dprintf_mciwave(stddeb,
410 "WAVE_mciRecord(%u, %08X, %08X);\n", wDevID, dwFlags, lpParms);
411 if (MCIWavDev[wDevID].hFile == 0) {
412 fprintf(stderr,"WAVE_mciRecord // can't find file='%s' !\n",
413 MCIWavDev[wDevID].openParms.lpstrElementName);
414 return MCIERR_FILE_NOT_FOUND;
416 start = 1; end = 99999;
417 if (dwFlags & MCI_FROM) {
418 start = lpParms->dwFrom;
419 dprintf_mciwave(stddeb,
420 "WAVE_mciRecord // MCI_FROM=%d \n", start);
422 if (dwFlags & MCI_TO) {
423 end = lpParms->dwTo;
424 dprintf_mciwave(stddeb,"WAVE_mciRecord // MCI_TO=%d \n", end);
426 lpWaveHdr = &MCIWavDev[wDevID].WaveHdr;
427 lpWaveHdr->lpData = (LPSTR) malloc(64000);
428 lpWaveHdr->dwBufferLength = 32000;
429 lpWaveHdr->dwUser = 0L;
430 lpWaveHdr->dwFlags = 0L;
431 lpWaveHdr->dwLoops = 0L;
432 dwRet = widMessage(0, WIDM_PREPARE, 0, (DWORD)lpWaveHdr, sizeof(WAVEHDR));
433 dprintf_mciwave(stddeb,"WAVE_mciRecord // after WIDM_PREPARE \n");
434 while(TRUE) {
435 lpWaveHdr->dwBytesRecorded = 0;
436 dwRet = widMessage(0, WIDM_START, 0, 0L, 0L);
437 dprintf_mciwave(stddeb,
438 "WAVE_mciRecord // after WIDM_START lpWaveHdr=%08X dwBytesRecorded=%u\n",
439 lpWaveHdr, lpWaveHdr->dwBytesRecorded);
440 if (lpWaveHdr->dwBytesRecorded == 0) break;
442 dprintf_mciwave(stddeb,"WAVE_mciRecord // before WIDM_UNPREPARE \n");
443 dwRet = widMessage(0, WIDM_UNPREPARE, 0, (DWORD)lpWaveHdr, sizeof(WAVEHDR));
444 dprintf_mciwave(stddeb,"WAVE_mciRecord // after WIDM_UNPREPARE \n");
445 if (lpWaveHdr->lpData != NULL) {
446 free(lpWaveHdr->lpData);
447 lpWaveHdr->lpData = NULL;
449 if (dwFlags & MCI_NOTIFY) {
450 dprintf_mciwave(stddeb,"WAVE_mciRecord // MCI_NOTIFY_SUCCESSFUL %08X !\n", lpParms->dwCallback);
451 mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
452 MCIWavDev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
454 return 0;
455 #else
456 return MMSYSERR_NOTENABLED;
457 #endif
461 /**************************************************************************
462 * WAVE_mciStop [internal]
464 DWORD WAVE_mciStop(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
466 #ifdef linux
467 dprintf_mciwave(stddeb,
468 "WAVE_mciStop(%u, %08X, %08X);\n", wDevID, dwFlags, lpParms);
469 if (lpParms == NULL) return MCIERR_INTERNAL;
470 return 0;
471 #else
472 return MCIERR_INTERNAL;
473 #endif
477 /**************************************************************************
478 * WAVE_mciPause [internal]
480 DWORD WAVE_mciPause(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
482 #ifdef linux
483 dprintf_mciwave(stddeb,
484 "WAVE_mciPause(%u, %08X, %08X);\n", wDevID, dwFlags, lpParms);
485 if (lpParms == NULL) return MCIERR_INTERNAL;
486 return 0;
487 #else
488 return MCIERR_INTERNAL;
489 #endif
493 /**************************************************************************
494 * WAVE_mciResume [internal]
496 DWORD WAVE_mciResume(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
498 #ifdef linux
499 dprintf_mciwave(stddeb,
500 "WAVE_mciResume(%u, %08X, %08X);\n", wDevID, dwFlags, lpParms);
501 if (lpParms == NULL) return MCIERR_INTERNAL;
502 return 0;
503 #else
504 return MCIERR_INTERNAL;
505 #endif
509 /**************************************************************************
510 * WAVE_mciSet [internal]
512 DWORD WAVE_mciSet(UINT wDevID, DWORD dwFlags, LPMCI_SET_PARMS lpParms)
514 #ifdef linux
515 dprintf_mciwave(stddeb,
516 "WAVE_mciSet(%u, %08X, %08X);\n", wDevID, dwFlags, lpParms);
517 if (lpParms == NULL) return MCIERR_INTERNAL;
518 dprintf_mciwave(stddeb,
519 "WAVE_mciSet // dwTimeFormat=%08X\n", lpParms->dwTimeFormat);
520 dprintf_mciwave(stddeb,
521 "WAVE_mciSet // dwAudio=%08X\n", lpParms->dwAudio);
522 if (dwFlags & MCI_SET_TIME_FORMAT) {
523 switch (lpParms->dwTimeFormat) {
524 case MCI_FORMAT_MILLISECONDS:
525 dprintf_mciwave(stddeb,
526 "WAVE_mciSet // MCI_FORMAT_MILLISECONDS !\n");
527 break;
528 case MCI_FORMAT_BYTES:
529 dprintf_mciwave(stddeb,
530 "WAVE_mciSet // MCI_FORMAT_BYTES !\n");
531 break;
532 case MCI_FORMAT_SAMPLES:
533 dprintf_mciwave(stddeb,
534 "WAVE_mciSet // MCI_FORMAT_SAMPLES !\n");
535 break;
536 default:
537 fprintf(stderr,
538 "WAVE_mciSet // bad time format !\n");
539 return MCIERR_BAD_TIME_FORMAT;
542 if (dwFlags & MCI_SET_VIDEO) return MCIERR_UNSUPPORTED_FUNCTION;
543 if (dwFlags & MCI_SET_DOOR_OPEN) return MCIERR_UNSUPPORTED_FUNCTION;
544 if (dwFlags & MCI_SET_DOOR_CLOSED) return MCIERR_UNSUPPORTED_FUNCTION;
545 if (dwFlags & MCI_SET_AUDIO)
546 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_SET_AUDIO !\n");
547 if (dwFlags && MCI_SET_ON) {
548 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_SET_ON !\n");
549 if (dwFlags && MCI_SET_AUDIO_LEFT)
550 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_SET_AUDIO_LEFT !\n");
551 if (dwFlags && MCI_SET_AUDIO_RIGHT)
552 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_SET_AUDIO_RIGHT !\n");
554 if (dwFlags & MCI_SET_OFF)
555 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_SET_OFF !\n");
556 if (dwFlags & MCI_WAVE_INPUT)
557 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_WAVE_INPUT !\n");
558 if (dwFlags & MCI_WAVE_OUTPUT)
559 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_WAVE_OUTPUT !\n");
560 if (dwFlags & MCI_WAVE_SET_ANYINPUT)
561 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_WAVE_SET_ANYINPUT !\n");
562 if (dwFlags & MCI_WAVE_SET_ANYOUTPUT)
563 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_WAVE_SET_ANYOUTPUT !\n");
564 if (dwFlags & MCI_WAVE_SET_AVGBYTESPERSEC)
565 dprintf_mciwave(stddeb,
566 "WAVE_mciSet // MCI_WAVE_SET_AVGBYTESPERSEC !\n");
567 if (dwFlags & MCI_WAVE_SET_BITSPERSAMPLE)
568 dprintf_mciwave(stddeb,
569 "WAVE_mciSet // MCI_WAVE_SET_BITSPERSAMPLE !\n");
570 if (dwFlags & MCI_WAVE_SET_BLOCKALIGN)
571 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_WAVE_SET_BLOCKALIGN !\n");
572 if (dwFlags & MCI_WAVE_SET_CHANNELS)
573 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_WAVE_SET_CHANNELS !\n");
574 if (dwFlags & MCI_WAVE_SET_FORMATTAG)
575 dprintf_mciwave(stddeb,"WAVE_mciSet // MCI_WAVE_SET_FORMATTAG !\n");
576 if (dwFlags & MCI_WAVE_SET_SAMPLESPERSEC)
577 dprintf_mciwave(stddeb,
578 "WAVE_mciSet // MCI_WAVE_SET_SAMPLESPERSEC !\n");
579 return 0;
580 #else
581 return MCIERR_INTERNAL;
582 #endif
586 /**************************************************************************
587 * WAVE_mciStatus [internal]
589 DWORD WAVE_mciStatus(UINT wDevID, DWORD dwFlags, LPMCI_STATUS_PARMS lpParms)
591 #ifdef linux
592 dprintf_mciwave(stddeb,
593 "WAVE_mciStatus(%u, %08X, %08X);\n", wDevID, dwFlags, lpParms);
594 if (lpParms == NULL) return MCIERR_INTERNAL;
595 if (dwFlags & MCI_STATUS_ITEM) {
596 switch(lpParms->dwItem) {
597 case MCI_STATUS_CURRENT_TRACK:
598 lpParms->dwReturn = 1;
599 break;
600 case MCI_STATUS_LENGTH:
601 lpParms->dwReturn = 5555;
602 if (dwFlags & MCI_TRACK) {
603 lpParms->dwTrack = 1;
604 lpParms->dwReturn = 2222;
606 break;
607 case MCI_STATUS_MODE:
608 lpParms->dwReturn = MCI_MODE_STOP;
609 break;
610 case MCI_STATUS_MEDIA_PRESENT:
611 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_STATUS_MEDIA_PRESENT !\n");
612 lpParms->dwReturn = TRUE;
613 break;
614 case MCI_STATUS_NUMBER_OF_TRACKS:
615 lpParms->dwReturn = 1;
616 break;
617 case MCI_STATUS_POSITION:
618 lpParms->dwReturn = 3333;
619 if (dwFlags & MCI_STATUS_START) {
620 lpParms->dwItem = 1;
622 if (dwFlags & MCI_TRACK) {
623 lpParms->dwTrack = 1;
624 lpParms->dwReturn = 777;
626 break;
627 case MCI_STATUS_READY:
628 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_STATUS_READY !\n");
629 lpParms->dwReturn = TRUE;
630 break;
631 case MCI_STATUS_TIME_FORMAT:
632 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_STATUS_TIME_FORMAT !\n");
633 lpParms->dwReturn = MCI_FORMAT_MILLISECONDS;
634 break;
635 case MCI_WAVE_INPUT:
636 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_INPUT !\n");
637 lpParms->dwReturn = 0;
638 break;
639 case MCI_WAVE_OUTPUT:
640 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_OUTPUT !\n");
641 lpParms->dwReturn = 0;
642 break;
643 case MCI_WAVE_STATUS_AVGBYTESPERSEC:
644 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_STATUS_AVGBYTESPERSEC !\n");
645 lpParms->dwReturn = 22050;
646 break;
647 case MCI_WAVE_STATUS_BITSPERSAMPLE:
648 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_STATUS_BITSPERSAMPLE !\n");
649 lpParms->dwReturn = 8;
650 break;
651 case MCI_WAVE_STATUS_BLOCKALIGN:
652 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_STATUS_BLOCKALIGN !\n");
653 lpParms->dwReturn = 1;
654 break;
655 case MCI_WAVE_STATUS_CHANNELS:
656 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_STATUS_CHANNELS !\n");
657 lpParms->dwReturn = 1;
658 break;
659 case MCI_WAVE_STATUS_FORMATTAG:
660 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_FORMATTAG !\n");
661 lpParms->dwReturn = WAVE_FORMAT_PCM;
662 break;
663 case MCI_WAVE_STATUS_LEVEL:
664 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_STATUS_LEVEL !\n");
665 lpParms->dwReturn = 0xAAAA5555;
666 break;
667 case MCI_WAVE_STATUS_SAMPLESPERSEC:
668 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_WAVE_STATUS_SAMPLESPERSEC !\n");
669 lpParms->dwReturn = 22050;
670 break;
671 default:
672 fprintf(stderr,"WAVE_mciStatus // unknown command %04X !\n", lpParms->dwItem);
673 return MCIERR_UNRECOGNIZED_COMMAND;
676 if (dwFlags & MCI_NOTIFY) {
677 dprintf_mciwave(stddeb,"WAVE_mciStatus // MCI_NOTIFY_SUCCESSFUL %08X !\n", lpParms->dwCallback);
678 mciDriverNotify((HWND)LOWORD(lpParms->dwCallback),
679 MCIWavDev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
681 return 0;
682 #else
683 return MCIERR_INTERNAL;
684 #endif
687 /**************************************************************************
688 * WAVE_mciGetDevCaps [internal]
690 DWORD WAVE_mciGetDevCaps(UINT wDevID, DWORD dwFlags,
691 LPMCI_GETDEVCAPS_PARMS lpParms)
693 #ifdef linux
694 dprintf_mciwave(stddeb,
695 "WAVE_mciGetDevCaps(%u, %08X, %08X);\n", wDevID, dwFlags, lpParms);
696 if (lpParms == NULL) return MCIERR_INTERNAL;
697 if (dwFlags & MCI_GETDEVCAPS_ITEM) {
698 switch(lpParms->dwItem) {
699 case MCI_GETDEVCAPS_CAN_RECORD:
700 lpParms->dwReturn = TRUE;
701 break;
702 case MCI_GETDEVCAPS_HAS_AUDIO:
703 lpParms->dwReturn = TRUE;
704 break;
705 case MCI_GETDEVCAPS_HAS_VIDEO:
706 lpParms->dwReturn = FALSE;
707 break;
708 case MCI_GETDEVCAPS_DEVICE_TYPE:
709 lpParms->dwReturn = MCI_DEVTYPE_WAVEFORM_AUDIO;
710 break;
711 case MCI_GETDEVCAPS_USES_FILES:
712 lpParms->dwReturn = TRUE;
713 break;
714 case MCI_GETDEVCAPS_COMPOUND_DEVICE:
715 lpParms->dwReturn = TRUE;
716 break;
717 case MCI_GETDEVCAPS_CAN_EJECT:
718 lpParms->dwReturn = FALSE;
719 break;
720 case MCI_GETDEVCAPS_CAN_PLAY:
721 lpParms->dwReturn = TRUE;
722 break;
723 case MCI_GETDEVCAPS_CAN_SAVE:
724 lpParms->dwReturn = TRUE;
725 break;
726 case MCI_WAVE_GETDEVCAPS_INPUTS:
727 lpParms->dwReturn = 1;
728 break;
729 case MCI_WAVE_GETDEVCAPS_OUTPUTS:
730 lpParms->dwReturn = 1;
731 break;
732 default:
733 return MCIERR_UNRECOGNIZED_COMMAND;
736 return 0;
737 #else
738 return MCIERR_INTERNAL;
739 #endif
742 /**************************************************************************
743 * WAVE_mciInfo [internal]
745 DWORD WAVE_mciInfo(UINT wDevID, DWORD dwFlags, LPMCI_INFO_PARMS lpParms)
747 #ifdef linux
748 dprintf_mciwave(stddeb,
749 "WAVE_mciInfo(%u, %08X, %08X);\n", wDevID, dwFlags, lpParms);
750 if (lpParms == NULL) return MCIERR_INTERNAL;
751 lpParms->lpstrReturn = NULL;
752 switch(dwFlags) {
753 case MCI_INFO_PRODUCT:
754 lpParms->lpstrReturn = "Linux Sound System 0.5";
755 break;
756 case MCI_INFO_FILE:
757 lpParms->lpstrReturn =
758 (LPSTR)MCIWavDev[wDevID].openParms.lpstrElementName;
759 break;
760 case MCI_WAVE_INPUT:
761 lpParms->lpstrReturn = "Linux Sound System 0.5";
762 break;
763 case MCI_WAVE_OUTPUT:
764 lpParms->lpstrReturn = "Linux Sound System 0.5";
765 break;
766 default:
767 return MCIERR_UNRECOGNIZED_COMMAND;
769 if (lpParms->lpstrReturn != NULL)
770 lpParms->dwRetSize = strlen(lpParms->lpstrReturn);
771 else
772 lpParms->dwRetSize = 0;
773 return 0;
774 #else
775 return MCIERR_INTERNAL;
776 #endif
780 /*-----------------------------------------------------------------------*/
783 /**************************************************************************
784 * wodGetDevCaps [internal]
786 DWORD wodGetDevCaps(WORD wDevID, LPWAVEOUTCAPS lpCaps, DWORD dwSize)
788 #ifdef linux
789 int audio;
790 int smplrate;
791 int samplesize = 16;
792 int dsp_stereo = 1;
793 int bytespersmpl;
794 dprintf_mciwave(stddeb,
795 "wodGetDevCaps(%u, %08X, %u);\n", wDevID, lpCaps, dwSize);
796 if (lpCaps == NULL) return MMSYSERR_NOTENABLED;
797 audio = open (SOUND_DEV, O_WRONLY, 0);
798 if (audio == -1) return MMSYSERR_NOTENABLED;
799 #ifdef EMULATE_SB16
800 lpCaps->wMid = 0x0002;
801 lpCaps->wPid = 0x0104;
802 strcpy(lpCaps->szPname, "SB16 Wave Out");
803 #else
804 lpCaps->wMid = 0x00FF; /* Manufac ID */
805 lpCaps->wPid = 0x0001; /* Product ID */
806 strcpy(lpCaps->szPname, "Linux WAVOUT Driver");
807 #endif
808 lpCaps->dwFormats = 0x00000000;
809 lpCaps->dwSupport = WAVECAPS_VOLUME;
810 lpCaps->wChannels = (IOCTL(audio, SNDCTL_DSP_STEREO, dsp_stereo) != 0) ? 1 : 2;
811 if (lpCaps->wChannels > 1) lpCaps->dwSupport |= WAVECAPS_LRVOLUME;
812 bytespersmpl = (IOCTL(audio, SNDCTL_DSP_SAMPLESIZE, samplesize) != 0) ? 1 : 2;
813 smplrate = 44100;
814 if (IOCTL(audio, SNDCTL_DSP_SPEED, smplrate) == 0) {
815 lpCaps->dwFormats |= WAVE_FORMAT_4M08;
816 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_4S08;
817 if (bytespersmpl > 1) {
818 lpCaps->dwFormats |= WAVE_FORMAT_4M16;
819 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_4S16;
822 smplrate = 22050;
823 if (IOCTL(audio, SNDCTL_DSP_SPEED, smplrate) == 0) {
824 lpCaps->dwFormats |= WAVE_FORMAT_2M08;
825 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_2S08;
826 if (bytespersmpl > 1) {
827 lpCaps->dwFormats |= WAVE_FORMAT_2M16;
828 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_2S16;
831 smplrate = 11025;
832 if (IOCTL(audio, SNDCTL_DSP_SPEED, smplrate) == 0) {
833 lpCaps->dwFormats |= WAVE_FORMAT_1M08;
834 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_1S08;
835 if (bytespersmpl > 1) {
836 lpCaps->dwFormats |= WAVE_FORMAT_1M16;
837 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_1S16;
840 close(audio);
841 dprintf_mciwave(stddeb,
842 "wodGetDevCaps // dwFormats = %08X\n", lpCaps->dwFormats);
843 return MMSYSERR_NOERROR;
844 #else
845 return MMSYSERR_NOTENABLED;
846 #endif
850 /**************************************************************************
851 * wodOpen [internal]
853 DWORD wodOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
855 #ifdef linux
856 int audio;
857 int abuf_size;
858 int smplrate;
859 int samplesize;
860 int dsp_stereo;
861 dprintf_mciwave(stddeb,
862 "wodOpen(%u, %08X, %08X);\n", wDevID, lpDesc, dwFlags);
863 if (lpDesc == NULL) {
864 fprintf(stderr,"Linux 'wodOpen' // Invalid Parameter !\n");
865 return MMSYSERR_INVALPARAM;
867 if (wDevID >= MAX_WAVOUTDRV) {
868 fprintf(stderr,"Linux 'wodOpen' // MAX_WAVOUTDRV reached !\n");
869 return MMSYSERR_ALLOCATED;
871 WOutDev[wDevID].unixdev = 0;
872 audio = open (SOUND_DEV, O_WRONLY, 0);
873 if (audio == -1) {
874 fprintf(stderr,"Linux 'wodOpen' // can't open !\n");
875 return MMSYSERR_NOTENABLED;
877 IOCTL(audio, SNDCTL_DSP_GETBLKSIZE, abuf_size);
878 if (abuf_size < 4096 || abuf_size > 65536) {
879 if (abuf_size == -1)
880 fprintf(stderr,"Linux 'wodOpen' // IOCTL can't 'SNDCTL_DSP_GETBLKSIZE' !\n");
881 else
882 fprintf(stderr,"Linux 'wodOpen' // SNDCTL_DSP_GETBLKSIZE Invalid bufsize !\n");
883 return MMSYSERR_NOTENABLED;
885 WOutDev[wDevID].wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
886 switch(WOutDev[wDevID].wFlags) {
887 case DCB_NULL:
888 fprintf(stderr,"Linux 'wodOpen' // CALLBACK_NULL !\n");
889 break;
890 case DCB_WINDOW:
891 dprintf_mciwave(stddeb,
892 "Linux 'wodOpen' // CALLBACK_WINDOW !\n");
893 break;
894 case DCB_TASK:
895 dprintf_mciwave(stddeb,
896 "Linux 'wodOpen' // CALLBACK_TASK !\n");
897 break;
898 case DCB_FUNCTION:
899 dprintf_mciwave(stddeb,
900 "Linux 'wodOpen' // CALLBACK_FUNCTION !\n");
901 break;
903 WOutDev[wDevID].lpQueueHdr = NULL;
904 WOutDev[wDevID].unixdev = audio;
905 WOutDev[wDevID].dwTotalPlayed = 0;
906 WOutDev[wDevID].bufsize = abuf_size;
907 memcpy(&WOutDev[wDevID].waveDesc, lpDesc, sizeof(WAVEOPENDESC));
908 if (lpDesc->lpFormat->wFormatTag != WAVE_FORMAT_PCM) {
909 fprintf(stderr,"Linux 'wodOpen' // Bad format %04X !\n",
910 lpDesc->lpFormat->wFormatTag);
911 return WAVERR_BADFORMAT;
913 memcpy(&WOutDev[wDevID].Format, lpDesc->lpFormat, sizeof(PCMWAVEFORMAT));
914 if (WOutDev[wDevID].Format.wf.nChannels == 0) return WAVERR_BADFORMAT;
915 if (WOutDev[wDevID].Format.wf.nSamplesPerSec == 0) return WAVERR_BADFORMAT;
916 if (WOutDev[wDevID].Format.wBitsPerSample == 0) {
917 WOutDev[wDevID].Format.wBitsPerSample = 8 *
918 (WOutDev[wDevID].Format.wf.nAvgBytesPerSec /
919 WOutDev[wDevID].Format.wf.nSamplesPerSec) /
920 WOutDev[wDevID].Format.wf.nChannels;
922 samplesize = WOutDev[wDevID].Format.wBitsPerSample;
923 smplrate = WOutDev[wDevID].Format.wf.nSamplesPerSec;
924 dsp_stereo = (WOutDev[wDevID].Format.wf.nChannels > 1) ? TRUE : FALSE;
925 IOCTL(audio, SNDCTL_DSP_SPEED, smplrate);
926 IOCTL(audio, SNDCTL_DSP_SAMPLESIZE, samplesize);
927 IOCTL(audio, SNDCTL_DSP_STEREO, dsp_stereo);
928 dprintf_mciwave(stddeb,"Linux 'wodOpen' // wBitsPerSample=%u !\n",
929 WOutDev[wDevID].Format.wBitsPerSample);
930 dprintf_mciwave(stddeb,"Linux 'wodOpen' // nSamplesPerSec=%u !\n",
931 WOutDev[wDevID].Format.wf.nSamplesPerSec);
932 dprintf_mciwave(stddeb,"Linux 'wodOpen' // nChannels=%u !\n",
933 WOutDev[wDevID].Format.wf.nChannels);
934 if (WAVE_NotifyClient(wDevID, WOM_OPEN, 0L, 0L) != MMSYSERR_NOERROR) {
935 fprintf(stderr,"Linux 'wodOpen' // can't notify client !\n");
936 return MMSYSERR_INVALPARAM;
938 return MMSYSERR_NOERROR;
939 #else
940 return MMSYSERR_NOTENABLED;
941 #endif
944 /**************************************************************************
945 * wodClose [internal]
947 DWORD wodClose(WORD wDevID)
949 #ifdef linux
950 dprintf_mciwave(stddeb,"wodClose(%u);\n", wDevID);
951 if (WOutDev[wDevID].unixdev == 0) {
952 fprintf(stderr,"Linux 'wodClose' // can't close !\n");
953 return MMSYSERR_NOTENABLED;
955 close(WOutDev[wDevID].unixdev);
956 WOutDev[wDevID].unixdev = 0;
957 WOutDev[wDevID].bufsize = 0;
958 if (WAVE_NotifyClient(wDevID, WOM_CLOSE, 0L, 0L) != MMSYSERR_NOERROR) {
959 fprintf(stderr,"Linux 'wodClose' // can't notify client !\n");
960 return MMSYSERR_INVALPARAM;
962 return MMSYSERR_NOERROR;
963 #else
964 return MMSYSERR_NOTENABLED;
965 #endif
968 /**************************************************************************
969 * wodWrite [internal]
971 DWORD wodWrite(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
973 #ifdef linux
974 dprintf_mciwave(stddeb,"wodWrite(%u, %08X, %08X);\n", wDevID, lpWaveHdr, dwSize);
975 if (WOutDev[wDevID].unixdev == 0) {
976 fprintf(stderr,"Linux 'wodWrite' // can't play !\n");
977 return MMSYSERR_NOTENABLED;
979 if (lpWaveHdr->lpData == NULL) return WAVERR_UNPREPARED;
980 if (!(lpWaveHdr->dwFlags & WHDR_PREPARED)) return WAVERR_UNPREPARED;
981 if (lpWaveHdr->dwFlags & WHDR_INQUEUE) return WAVERR_STILLPLAYING;
982 lpWaveHdr->dwFlags &= ~WHDR_DONE;
983 lpWaveHdr->dwFlags |= WHDR_INQUEUE;
984 dprintf_mciwave(stddeb,
985 "wodWrite() // dwBytesRecorded %u !\n", lpWaveHdr->dwBytesRecorded);
986 if (write (WOutDev[wDevID].unixdev, lpWaveHdr->lpData,
987 lpWaveHdr->dwBytesRecorded) != lpWaveHdr->dwBytesRecorded) {
988 return MMSYSERR_NOTENABLED;
990 lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
991 lpWaveHdr->dwFlags |= WHDR_DONE;
992 if (WAVE_NotifyClient(wDevID, WOM_DONE, 0L, 0L) != MMSYSERR_NOERROR) {
993 fprintf(stderr,"Linux 'wodWrite' // can't notify client !\n");
994 return MMSYSERR_INVALPARAM;
996 return MMSYSERR_NOERROR;
997 #else
998 return MMSYSERR_NOTENABLED;
999 #endif
1002 /**************************************************************************
1003 * wodPrepare [internal]
1005 DWORD wodPrepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
1007 #ifdef linux
1008 dprintf_mciwave(stddeb,
1009 "wodPrepare(%u, %08X, %08X);\n", wDevID, lpWaveHdr, dwSize);
1010 if (WOutDev[wDevID].unixdev == 0) {
1011 fprintf(stderr,"Linux 'wodPrepare' // can't prepare !\n");
1012 return MMSYSERR_NOTENABLED;
1014 if (WOutDev[wDevID].lpQueueHdr != NULL) {
1015 fprintf(stderr,"Linux 'wodPrepare' // already prepare !\n");
1016 return MMSYSERR_NOTENABLED;
1018 WOutDev[wDevID].dwTotalPlayed = 0;
1019 WOutDev[wDevID].lpQueueHdr = lpWaveHdr;
1020 if (lpWaveHdr->dwFlags & WHDR_INQUEUE) return WAVERR_STILLPLAYING;
1021 lpWaveHdr->dwFlags |= WHDR_PREPARED;
1022 lpWaveHdr->dwFlags &= ~WHDR_DONE;
1023 return MMSYSERR_NOERROR;
1024 #else
1025 return MMSYSERR_NOTENABLED;
1026 #endif
1029 /**************************************************************************
1030 * wodUnprepare [internal]
1032 DWORD wodUnprepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
1034 #ifdef linux
1035 dprintf_mciwave(stddeb,
1036 "wodUnprepare(%u, %08X, %08X);\n", wDevID, lpWaveHdr, dwSize);
1037 if (WOutDev[wDevID].unixdev == 0) {
1038 fprintf(stderr,"Linux 'wodUnprepare' // can't unprepare !\n");
1039 return MMSYSERR_NOTENABLED;
1041 return MMSYSERR_NOERROR;
1042 #else
1043 return MMSYSERR_NOTENABLED;
1044 #endif
1047 /**************************************************************************
1048 * wodRestart [internal]
1050 DWORD wodRestart(WORD wDevID)
1052 #ifdef linux
1053 dprintf_mciwave(stddeb,"wodRestart(%u);\n", wDevID);
1054 if (WOutDev[wDevID].unixdev == 0) {
1055 fprintf(stderr,"Linux 'wodRestart' // can't restart !\n");
1056 return MMSYSERR_NOTENABLED;
1058 return MMSYSERR_NOERROR;
1059 #else
1060 return MMSYSERR_NOTENABLED;
1061 #endif
1064 /**************************************************************************
1065 * wodReset [internal]
1067 DWORD wodReset(WORD wDevID)
1069 #ifdef linux
1070 dprintf_mciwave(stddeb,"wodReset(%u);\n", wDevID);
1071 if (WOutDev[wDevID].unixdev == 0) {
1072 fprintf(stderr,"Linux 'wodReset' // can't reset !\n");
1073 return MMSYSERR_NOTENABLED;
1075 return MMSYSERR_NOERROR;
1076 #else
1077 return MMSYSERR_NOTENABLED;
1078 #endif
1082 /**************************************************************************
1083 * wodGetPosition [internal]
1085 DWORD wodGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize)
1087 #ifdef linux
1088 int time;
1089 dprintf_mciwave(stddeb,"wodGetPosition(%u, %08X, %u);\n", wDevID, lpTime, uSize);
1090 if (WOutDev[wDevID].unixdev == 0) {
1091 fprintf(stderr,"Linux 'wodGetPosition' // can't get pos !\n");
1092 return MMSYSERR_NOTENABLED;
1094 if (lpTime == NULL) return MMSYSERR_INVALPARAM;
1095 TryAGAIN:
1096 switch(lpTime->wType) {
1097 case TIME_BYTES:
1098 lpTime->u.cb = WOutDev[wDevID].dwTotalPlayed;
1099 dprintf_mciwave(stddeb,"wodGetPosition // TIME_BYTES=%u\n", lpTime->u.cb);
1100 break;
1101 case TIME_SAMPLES:
1102 lpTime->u.sample = WOutDev[wDevID].dwTotalPlayed * 8 /
1103 WOutDev[wDevID].Format.wBitsPerSample;
1104 dprintf_mciwave(stddeb,"wodGetPosition // TIME_SAMPLES=%u\n", lpTime->u.sample);
1105 break;
1106 case TIME_MS:
1107 lpTime->u.ms = WOutDev[wDevID].dwTotalPlayed /
1108 (WOutDev[wDevID].Format.wf.nAvgBytesPerSec / 1000);
1109 dprintf_mciwave(stddeb,"wodGetPosition // TIME_MS=%u\n", lpTime->u.ms);
1110 break;
1111 case TIME_SMPTE:
1112 time = WOutDev[wDevID].dwTotalPlayed /
1113 (WOutDev[wDevID].Format.wf.nAvgBytesPerSec / 1000);
1114 lpTime->u.smpte.hour = time / 108000;
1115 time -= lpTime->u.smpte.hour * 108000;
1116 lpTime->u.smpte.min = time / 1800;
1117 time -= lpTime->u.smpte.min * 1800;
1118 lpTime->u.smpte.sec = time / 30;
1119 time -= lpTime->u.smpte.sec * 30;
1120 lpTime->u.smpte.frame = time;
1121 lpTime->u.smpte.fps = 30;
1122 dprintf_mciwave(stddeb,
1123 "wodGetPosition // TIME_SMPTE=%02u:%02u:%02u:%02u\n",
1124 lpTime->u.smpte.hour, lpTime->u.smpte.min,
1125 lpTime->u.smpte.sec, lpTime->u.smpte.frame);
1126 break;
1127 default:
1128 fprintf(stderr,"wodGetPosition() format not supported ! use TIME_MS !\n");
1129 lpTime->wType = TIME_MS;
1130 goto TryAGAIN;
1132 return MMSYSERR_NOERROR;
1133 #else
1134 return MMSYSERR_NOTENABLED;
1135 #endif
1138 /**************************************************************************
1139 * wodSetVolume [internal]
1141 DWORD wodSetVolume(WORD wDevID, DWORD dwParam)
1143 #ifdef linux
1144 int mixer;
1145 int volume = 50;
1146 dprintf_mciwave(stddeb,"wodSetVolume(%u, %08X);\n", wDevID, dwParam);
1147 if (WOutDev[wDevID].unixdev == 0) {
1148 fprintf(stderr,"Linux 'wodSetVolume' // can't set volume !\n");
1149 return MMSYSERR_NOTENABLED;
1151 if ((mixer = open("/dev/mixer", O_RDWR)) < 0) {
1152 fprintf(stderr,
1153 "Linux 'wodSetVolume' // mixer device not available !\n");
1154 return MMSYSERR_NOTENABLED;
1156 if (ioctl(mixer, SOUND_MIXER_WRITE_PCM, &volume) == -1) {
1157 fprintf(stderr,"Linux 'wodSetVolume' // unable set mixer !\n");
1158 return MMSYSERR_NOTENABLED;
1160 close(mixer);
1161 return MMSYSERR_NOERROR;
1162 #else
1163 return MMSYSERR_NOTENABLED;
1164 #endif
1168 /**************************************************************************
1169 * wodMessage [sample driver]
1171 DWORD wodMessage(WORD wDevID, WORD wMsg, DWORD dwUser,
1172 DWORD dwParam1, DWORD dwParam2)
1174 dprintf_mciwave(stddeb,"wodMessage(%u, %04X, %08X, %08X, %08X);\n",
1175 wDevID, wMsg, dwUser, dwParam1, dwParam2);
1176 switch(wMsg) {
1177 case WODM_OPEN:
1178 return wodOpen(wDevID, (LPWAVEOPENDESC)dwParam1, dwParam2);
1179 case WODM_CLOSE:
1180 return wodClose(wDevID);
1181 case WODM_WRITE:
1182 return wodWrite(wDevID, (LPWAVEHDR)dwParam1, dwParam2);
1183 case WODM_PAUSE:
1184 return 0L;
1185 case WODM_GETPOS:
1186 return wodGetPosition(wDevID, (LPMMTIME)dwParam1, dwParam2);
1187 case WODM_BREAKLOOP:
1188 return 0L;
1189 case WODM_PREPARE:
1190 return wodPrepare(wDevID, (LPWAVEHDR)dwParam1, dwParam2);
1191 case WODM_UNPREPARE:
1192 return wodUnprepare(wDevID, (LPWAVEHDR)dwParam1, dwParam2);
1193 case WODM_GETDEVCAPS:
1194 return wodGetDevCaps(wDevID, (LPWAVEOUTCAPS)dwParam1, dwParam2);
1195 case WODM_GETNUMDEVS:
1196 return 1L;
1197 case WODM_GETPITCH:
1198 return 0L;
1199 case WODM_SETPITCH:
1200 return 0L;
1201 case WODM_GETPLAYBACKRATE:
1202 return 0L;
1203 case WODM_SETPLAYBACKRATE:
1204 return 0L;
1205 case WODM_GETVOLUME:
1206 return 0L;
1207 case WODM_SETVOLUME:
1208 return wodSetVolume(wDevID, dwParam1);
1209 case WODM_RESTART:
1210 return wodRestart(wDevID);
1211 case WODM_RESET:
1212 return wodReset(wDevID);
1214 return MMSYSERR_NOTSUPPORTED;
1218 /*-----------------------------------------------------------------------*/
1220 /**************************************************************************
1221 * widGetDevCaps [internal]
1223 DWORD widGetDevCaps(WORD wDevID, LPWAVEINCAPS lpCaps, DWORD dwSize)
1225 #ifdef linux
1226 int audio;
1227 int smplrate;
1228 int samplesize = 16;
1229 int dsp_stereo = 1;
1230 int bytespersmpl;
1231 dprintf_mciwave(stddeb,
1232 "widGetDevCaps(%u, %08X, %u);\n", wDevID, lpCaps, dwSize);
1233 if (lpCaps == NULL) return MMSYSERR_NOTENABLED;
1234 audio = open (SOUND_DEV, O_RDONLY, 0);
1235 if (audio == -1) return MMSYSERR_NOTENABLED;
1236 #ifdef EMULATE_SB16
1237 lpCaps->wMid = 0x0002;
1238 lpCaps->wPid = 0x0004;
1239 strcpy(lpCaps->szPname, "SB16 Wave Out");
1240 #else
1241 lpCaps->wMid = 0x00FF; /* Manufac ID */
1242 lpCaps->wPid = 0x0001; /* Product ID */
1243 strcpy(lpCaps->szPname, "Linux WAVIN Driver");
1244 #endif
1245 lpCaps->dwFormats = 0x00000000;
1246 lpCaps->wChannels = (IOCTL(audio, SNDCTL_DSP_STEREO, dsp_stereo) != 0) ? 1 : 2;
1247 bytespersmpl = (IOCTL(audio, SNDCTL_DSP_SAMPLESIZE, samplesize) != 0) ? 1 : 2;
1248 smplrate = 44100;
1249 if (IOCTL(audio, SNDCTL_DSP_SPEED, smplrate) == 0) {
1250 lpCaps->dwFormats |= WAVE_FORMAT_4M08;
1251 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_4S08;
1252 if (bytespersmpl > 1) {
1253 lpCaps->dwFormats |= WAVE_FORMAT_4M16;
1254 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_4S16;
1257 smplrate = 22050;
1258 if (IOCTL(audio, SNDCTL_DSP_SPEED, smplrate) == 0) {
1259 lpCaps->dwFormats |= WAVE_FORMAT_2M08;
1260 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_2S08;
1261 if (bytespersmpl > 1) {
1262 lpCaps->dwFormats |= WAVE_FORMAT_2M16;
1263 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_2S16;
1266 smplrate = 11025;
1267 if (IOCTL(audio, SNDCTL_DSP_SPEED, smplrate) == 0) {
1268 lpCaps->dwFormats |= WAVE_FORMAT_1M08;
1269 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_1S08;
1270 if (bytespersmpl > 1) {
1271 lpCaps->dwFormats |= WAVE_FORMAT_1M16;
1272 if (lpCaps->wChannels > 1) lpCaps->dwFormats |= WAVE_FORMAT_1S16;
1275 close(audio);
1276 dprintf_mciwave(stddeb,
1277 "widGetDevCaps // dwFormats = %08X\n", lpCaps->dwFormats);
1278 return MMSYSERR_NOERROR;
1279 #else
1280 return MMSYSERR_NOTENABLED;
1281 #endif
1285 /**************************************************************************
1286 * widOpen [internal]
1288 DWORD widOpen(WORD wDevID, LPWAVEOPENDESC lpDesc, DWORD dwFlags)
1290 #ifdef linux
1291 int audio;
1292 int abuf_size;
1293 int smplrate;
1294 int samplesize;
1295 int dsp_stereo;
1296 dprintf_mciwave(stddeb,
1297 "widOpen(%u, %08X, %08X);\n", wDevID, lpDesc, dwFlags);
1298 if (lpDesc == NULL) {
1299 fprintf(stderr,"Linux 'widOpen' // Invalid Parameter !\n");
1300 return MMSYSERR_INVALPARAM;
1302 if (wDevID >= MAX_WAVINDRV) {
1303 fprintf(stderr,"Linux 'widOpen' // MAX_WAVINDRV reached !\n");
1304 return MMSYSERR_ALLOCATED;
1306 WInDev[wDevID].unixdev = 0;
1307 audio = open (SOUND_DEV, O_RDONLY, 0);
1308 if (audio == -1) {
1309 fprintf(stderr,"Linux 'widOpen' // can't open !\n");
1310 return MMSYSERR_NOTENABLED;
1312 IOCTL(audio, SNDCTL_DSP_GETBLKSIZE, abuf_size);
1313 if (abuf_size < 4096 || abuf_size > 65536) {
1314 if (abuf_size == -1)
1315 fprintf(stderr,"Linux 'widOpen' // IOCTL can't 'SNDCTL_DSP_GETBLKSIZE' !\n");
1316 else
1317 fprintf(stderr,"Linux 'widOpen' // SNDCTL_DSP_GETBLKSIZE Invalid bufsize !\n");
1318 return MMSYSERR_NOTENABLED;
1320 WInDev[wDevID].wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
1321 switch(WInDev[wDevID].wFlags) {
1322 case DCB_NULL:
1323 dprintf_mciwave(stddeb,
1324 "Linux 'widOpen' // CALLBACK_NULL !\n");
1325 break;
1326 case DCB_WINDOW:
1327 dprintf_mciwave(stddeb,
1328 "Linux 'widOpen' // CALLBACK_WINDOW !\n");
1329 break;
1330 case DCB_TASK:
1331 dprintf_mciwave(stddeb,
1332 "Linux 'widOpen' // CALLBACK_TASK !\n");
1333 break;
1334 case DCB_FUNCTION:
1335 dprintf_mciwave(stddeb,
1336 "Linux 'widOpen' // CALLBACK_FUNCTION !\n");
1337 break;
1339 WInDev[wDevID].lpQueueHdr = NULL;
1340 WInDev[wDevID].unixdev = audio;
1341 WInDev[wDevID].bufsize = abuf_size;
1342 WInDev[wDevID].dwTotalRecorded = 0;
1343 memcpy(&WInDev[wDevID].waveDesc, lpDesc, sizeof(WAVEOPENDESC));
1344 if (lpDesc->lpFormat->wFormatTag != WAVE_FORMAT_PCM) {
1345 fprintf(stderr,"Linux 'widOpen' // Bad format %04X !\n",
1346 lpDesc->lpFormat->wFormatTag);
1347 return WAVERR_BADFORMAT;
1349 memcpy(&WInDev[wDevID].Format, lpDesc->lpFormat, sizeof(PCMWAVEFORMAT));
1350 WInDev[wDevID].Format.wBitsPerSample = 8; /* <-------------- */
1351 if (WInDev[wDevID].Format.wf.nChannels == 0) return WAVERR_BADFORMAT;
1352 if (WInDev[wDevID].Format.wf.nSamplesPerSec == 0) return WAVERR_BADFORMAT;
1353 if (WInDev[wDevID].Format.wBitsPerSample == 0) {
1354 WInDev[wDevID].Format.wBitsPerSample = 8 *
1355 (WInDev[wDevID].Format.wf.nAvgBytesPerSec /
1356 WInDev[wDevID].Format.wf.nSamplesPerSec) /
1357 WInDev[wDevID].Format.wf.nChannels;
1359 samplesize = WInDev[wDevID].Format.wBitsPerSample;
1360 smplrate = WInDev[wDevID].Format.wf.nSamplesPerSec;
1361 dsp_stereo = (WInDev[wDevID].Format.wf.nChannels > 1) ? TRUE : FALSE;
1362 IOCTL(audio, SNDCTL_DSP_SPEED, smplrate);
1363 IOCTL(audio, SNDCTL_DSP_SAMPLESIZE, samplesize);
1364 IOCTL(audio, SNDCTL_DSP_STEREO, dsp_stereo);
1365 dprintf_mciwave(stddeb,"Linux 'widOpen' // wBitsPerSample=%u !\n",
1366 WInDev[wDevID].Format.wBitsPerSample);
1367 dprintf_mciwave(stddeb,"Linux 'widOpen' // nSamplesPerSec=%u !\n",
1368 WInDev[wDevID].Format.wf.nSamplesPerSec);
1369 dprintf_mciwave(stddeb,"Linux 'widOpen' // nChannels=%u !\n",
1370 WInDev[wDevID].Format.wf.nChannels);
1371 dprintf_mciwave(stddeb,"Linux 'widOpen' // nAvgBytesPerSec=%u\n",
1372 WInDev[wDevID].Format.wf.nAvgBytesPerSec);
1373 if (WAVE_NotifyClient(wDevID, WIM_OPEN, 0L, 0L) != MMSYSERR_NOERROR) {
1374 fprintf(stderr,"Linux 'widOpen' // can't notify client !\n");
1375 return MMSYSERR_INVALPARAM;
1377 return MMSYSERR_NOERROR;
1378 #else
1379 return MMSYSERR_NOTENABLED;
1380 #endif
1383 /**************************************************************************
1384 * widClose [internal]
1386 DWORD widClose(WORD wDevID)
1388 #ifdef linux
1389 dprintf_mciwave(stddeb,"widClose(%u);\n", wDevID);
1390 if (WInDev[wDevID].unixdev == 0) {
1391 fprintf(stderr,"Linux 'widClose' // can't close !\n");
1392 return MMSYSERR_NOTENABLED;
1394 close(WInDev[wDevID].unixdev);
1395 WInDev[wDevID].unixdev = 0;
1396 WInDev[wDevID].bufsize = 0;
1397 if (WAVE_NotifyClient(wDevID, WIM_CLOSE, 0L, 0L) != MMSYSERR_NOERROR) {
1398 fprintf(stderr,"Linux 'widClose' // can't notify client !\n");
1399 return MMSYSERR_INVALPARAM;
1401 return MMSYSERR_NOERROR;
1402 #else
1403 return MMSYSERR_NOTENABLED;
1404 #endif
1407 /**************************************************************************
1408 * widAddBuffer [internal]
1410 DWORD widAddBuffer(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
1412 #ifdef linux
1413 int count = 1;
1414 LPWAVEHDR lpWIHdr;
1415 dprintf_mciwave(stddeb,
1416 "widAddBuffer(%u, %08X, %08X);\n", wDevID, lpWaveHdr, dwSize);
1417 if (WInDev[wDevID].unixdev == 0) {
1418 fprintf(stderr,"Linux 'widAddBuffer' // can't do it !\n");
1419 return MMSYSERR_NOTENABLED;
1421 if (WInDev[wDevID].lpQueueHdr == NULL ||
1422 !(lpWaveHdr->dwFlags & WHDR_PREPARED)) {
1423 fprintf(stderr,
1424 "Linux 'widAddBuffer' // never been prepared !\n");
1425 return WAVERR_UNPREPARED;
1427 if ((lpWaveHdr->dwFlags & WHDR_INQUEUE) &&
1428 (WInDev[wDevID].lpQueueHdr != lpWaveHdr)) {
1429 /* except if it's the one just prepared ... */
1430 fprintf(stderr,
1431 "Linux 'widAddBuffer' // header already in use !\n");
1432 return WAVERR_STILLPLAYING;
1434 lpWaveHdr->dwFlags |= WHDR_PREPARED;
1435 lpWaveHdr->dwFlags |= WHDR_INQUEUE;
1436 lpWaveHdr->dwFlags &= ~WHDR_DONE;
1437 lpWaveHdr->dwBytesRecorded = 0;
1438 /* added to the queue, except if it's the one just prepared ... */
1439 if (WInDev[wDevID].lpQueueHdr != lpWaveHdr) {
1440 lpWIHdr = WInDev[wDevID].lpQueueHdr;
1441 while (lpWIHdr->lpNext != NULL) {
1442 lpWIHdr = lpWIHdr->lpNext;
1443 count++;
1445 lpWIHdr->lpNext = lpWaveHdr;
1446 count++;
1448 dprintf_mciwave(stddeb,
1449 "widAddBuffer // buffer added ! (now %u in queue)\n", count);
1450 return MMSYSERR_NOERROR;
1451 #else
1452 return MMSYSERR_NOTENABLED;
1453 #endif
1456 /**************************************************************************
1457 * widPrepare [internal]
1459 DWORD widPrepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
1461 #ifdef linux
1462 dprintf_mciwave(stddeb,
1463 "widPrepare(%u, %08X, %08X);\n", wDevID, lpWaveHdr, dwSize);
1464 if (WInDev[wDevID].unixdev == 0) {
1465 fprintf(stderr,"Linux 'widPrepare' // can't prepare !\n");
1466 return MMSYSERR_NOTENABLED;
1468 if (WInDev[wDevID].lpQueueHdr != NULL) {
1469 fprintf(stderr,"Linux 'widPrepare' // already prepare !\n");
1470 return WAVERR_BADFORMAT;
1472 WInDev[wDevID].dwTotalRecorded = 0;
1473 WInDev[wDevID].lpQueueHdr = lpWaveHdr;
1474 if (lpWaveHdr->dwFlags & WHDR_INQUEUE) return WAVERR_STILLPLAYING;
1475 lpWaveHdr->dwFlags |= WHDR_PREPARED;
1476 lpWaveHdr->dwFlags |= WHDR_INQUEUE;
1477 lpWaveHdr->dwFlags &= ~WHDR_DONE;
1478 lpWaveHdr->dwBytesRecorded = 0;
1479 dprintf_mciwave(stddeb,"Linux 'widPrepare' // header prepared !\n");
1480 return MMSYSERR_NOERROR;
1481 #else
1482 return MMSYSERR_NOTENABLED;
1483 #endif
1486 /**************************************************************************
1487 * widUnprepare [internal]
1489 DWORD widUnprepare(WORD wDevID, LPWAVEHDR lpWaveHdr, DWORD dwSize)
1491 #ifdef linux
1492 dprintf_mciwave(stddeb,
1493 "widUnprepare(%u, %08X, %08X);\n", wDevID, lpWaveHdr, dwSize);
1494 if (WInDev[wDevID].unixdev == 0) {
1495 fprintf(stderr,"Linux 'widUnprepare' // can't unprepare !\n");
1496 return MMSYSERR_NOTENABLED;
1498 lpWaveHdr->dwFlags &= ~WHDR_PREPARED;
1499 lpWaveHdr->dwFlags &= ~WHDR_INQUEUE;
1500 lpWaveHdr->dwFlags |= WHDR_DONE;
1501 WInDev[wDevID].lpQueueHdr = NULL;
1502 dprintf_mciwave(stddeb,
1503 "Linux 'widUnprepare' // all headers unprepared !\n");
1504 return MMSYSERR_NOERROR;
1505 #else
1506 return MMSYSERR_NOTENABLED;
1507 #endif
1510 /**************************************************************************
1511 * widStart [internal]
1513 DWORD widStart(WORD wDevID)
1515 #ifdef linux
1516 int count = 1;
1517 LPWAVEHDR lpWIHdr;
1518 dprintf_mciwave(stddeb,"widStart(%u);\n", wDevID);
1519 if (WInDev[wDevID].unixdev == 0) {
1520 fprintf(stderr,
1521 "Linux 'widStart' // can't start recording !\n");
1522 return MMSYSERR_NOTENABLED;
1524 if (WInDev[wDevID].lpQueueHdr == NULL ||
1525 WInDev[wDevID].lpQueueHdr->lpData == NULL) {
1526 fprintf(stderr,"Linux 'widStart' // never been prepared !\n");
1527 return WAVERR_UNPREPARED;
1529 lpWIHdr = WInDev[wDevID].lpQueueHdr;
1530 while(lpWIHdr != NULL) {
1531 lpWIHdr->dwBufferLength &= 0xFFFF;
1532 dprintf_mciwave(stddeb,
1533 "widStart // recording buf#%u=%08X size=%u \n",
1534 count, lpWIHdr->lpData, lpWIHdr->dwBufferLength);
1535 fflush(stddeb);
1536 read (WInDev[wDevID].unixdev, lpWIHdr->lpData,
1537 lpWIHdr->dwBufferLength);
1538 lpWIHdr->dwBytesRecorded = lpWIHdr->dwBufferLength;
1539 WInDev[wDevID].dwTotalRecorded += lpWIHdr->dwBytesRecorded;
1540 lpWIHdr->dwFlags &= ~WHDR_INQUEUE;
1541 lpWIHdr->dwFlags |= WHDR_DONE;
1542 if (WAVE_NotifyClient(wDevID, WIM_DATA, (DWORD)lpWIHdr, 0L) !=
1543 MMSYSERR_NOERROR) {
1544 fprintf(stderr,
1545 "Linux 'widStart' // can't notify client !\n");
1546 return MMSYSERR_INVALPARAM;
1548 lpWIHdr = lpWIHdr->lpNext;
1549 count++;
1551 dprintf_mciwave(stddeb,"widStart // end of recording !\n");
1552 fflush(stdout);
1553 return MMSYSERR_NOERROR;
1554 #else
1555 return MMSYSERR_NOTENABLED;
1556 #endif
1559 /**************************************************************************
1560 * widStop [internal]
1562 DWORD widStop(WORD wDevID)
1564 #ifdef linux
1565 dprintf_mciwave(stddeb,"widStop(%u);\n", wDevID);
1566 if (WInDev[wDevID].unixdev == 0) {
1567 fprintf(stderr,"Linux 'widStop' // can't stop !\n");
1568 return MMSYSERR_NOTENABLED;
1570 return MMSYSERR_NOERROR;
1571 #else
1572 return MMSYSERR_NOTENABLED;
1573 #endif
1576 /**************************************************************************
1577 * widReset [internal]
1579 DWORD widReset(WORD wDevID)
1581 #ifdef linux
1582 dprintf_mciwave(stddeb,"widReset(%u);\n", wDevID);
1583 if (WInDev[wDevID].unixdev == 0) {
1584 fprintf(stderr,"Linux 'widReset' // can't reset !\n");
1585 return MMSYSERR_NOTENABLED;
1587 return MMSYSERR_NOERROR;
1588 #else
1589 return MMSYSERR_NOTENABLED;
1590 #endif
1593 /**************************************************************************
1594 * widGetPosition [internal]
1596 DWORD widGetPosition(WORD wDevID, LPMMTIME lpTime, DWORD uSize)
1598 #ifdef linux
1599 int time;
1600 dprintf_mciwave(stddeb,
1601 "widGetPosition(%u, %08X, %u);\n", wDevID, lpTime, uSize);
1602 if (WInDev[wDevID].unixdev == 0) {
1603 fprintf(stderr,"Linux 'widGetPosition' // can't get pos !\n");
1604 return MMSYSERR_NOTENABLED;
1606 if (lpTime == NULL) return MMSYSERR_INVALPARAM;
1607 TryAGAIN:
1608 dprintf_mciwave(stddeb,"widGetPosition // wType=%04X !\n",
1609 lpTime->wType);
1610 dprintf_mciwave(stddeb,"widGetPosition // wBitsPerSample=%u\n",
1611 WInDev[wDevID].Format.wBitsPerSample);
1612 dprintf_mciwave(stddeb,"widGetPosition // nSamplesPerSec=%u\n",
1613 WInDev[wDevID].Format.wf.nSamplesPerSec);
1614 dprintf_mciwave(stddeb,"widGetPosition // nChannels=%u\n",
1615 WInDev[wDevID].Format.wf.nChannels);
1616 dprintf_mciwave(stddeb,"widGetPosition // nAvgBytesPerSec=%u\n",
1617 WInDev[wDevID].Format.wf.nAvgBytesPerSec);
1618 fflush(stddeb);
1619 switch(lpTime->wType) {
1620 case TIME_BYTES:
1621 lpTime->u.cb = WInDev[wDevID].dwTotalRecorded;
1622 dprintf_mciwave(stddeb,
1623 "widGetPosition // TIME_BYTES=%u\n", lpTime->u.cb);
1624 break;
1625 case TIME_SAMPLES:
1626 lpTime->u.sample = WInDev[wDevID].dwTotalRecorded * 8 /
1627 WInDev[wDevID].Format.wBitsPerSample;
1628 dprintf_mciwave(stddeb,
1629 "widGetPosition // TIME_SAMPLES=%u\n",
1630 lpTime->u.sample);
1631 break;
1632 case TIME_MS:
1633 lpTime->u.ms = WInDev[wDevID].dwTotalRecorded /
1634 (WInDev[wDevID].Format.wf.nAvgBytesPerSec / 1000);
1635 dprintf_mciwave(stddeb,
1636 "widGetPosition // TIME_MS=%u\n", lpTime->u.ms);
1637 break;
1638 case TIME_SMPTE:
1639 time = WInDev[wDevID].dwTotalRecorded /
1640 (WInDev[wDevID].Format.wf.nAvgBytesPerSec / 1000);
1641 lpTime->u.smpte.hour = time / 108000;
1642 time -= lpTime->u.smpte.hour * 108000;
1643 lpTime->u.smpte.min = time / 1800;
1644 time -= lpTime->u.smpte.min * 1800;
1645 lpTime->u.smpte.sec = time / 30;
1646 time -= lpTime->u.smpte.sec * 30;
1647 lpTime->u.smpte.frame = time;
1648 lpTime->u.smpte.fps = 30;
1649 dprintf_mciwave(stddeb,"widGetPosition // TIME_SMPTE=%02u:%02u:%02u:%02u\n",
1650 lpTime->u.smpte.hour, lpTime->u.smpte.min,
1651 lpTime->u.smpte.sec, lpTime->u.smpte.frame);
1652 break;
1653 default:
1654 fprintf(stderr,"widGetPosition() format not supported ! use TIME_MS !\n");
1655 lpTime->wType = TIME_MS;
1656 goto TryAGAIN;
1658 return MMSYSERR_NOERROR;
1659 #else
1660 return MMSYSERR_NOTENABLED;
1661 #endif
1664 /**************************************************************************
1665 * widMessage [sample driver]
1667 DWORD widMessage(WORD wDevID, WORD wMsg, DWORD dwUser,
1668 DWORD dwParam1, DWORD dwParam2)
1670 dprintf_mciwave(stddeb,"widMessage(%u, %04X, %08X, %08X, %08X);\n",
1671 wDevID, wMsg, dwUser, dwParam1, dwParam2);
1672 switch(wMsg) {
1673 case WIDM_OPEN:
1674 return widOpen(wDevID, (LPWAVEOPENDESC)dwParam1, dwParam2);
1675 case WIDM_CLOSE:
1676 return widClose(wDevID);
1677 case WIDM_ADDBUFFER:
1678 return widAddBuffer(wDevID, (LPWAVEHDR)dwParam1, dwParam2);
1679 case WIDM_PREPARE:
1680 return widPrepare(wDevID, (LPWAVEHDR)dwParam1, dwParam2);
1681 case WIDM_UNPREPARE:
1682 return widUnprepare(wDevID, (LPWAVEHDR)dwParam1, dwParam2);
1683 case WIDM_GETDEVCAPS:
1684 return widGetDevCaps(wDevID, (LPWAVEINCAPS)dwParam1, dwParam2);
1685 case WIDM_GETNUMDEVS:
1686 return 1L;
1687 case WIDM_GETPOS:
1688 return widGetPosition(wDevID, (LPMMTIME)dwParam1, dwParam2);
1689 case WIDM_RESET:
1690 return widReset(wDevID);
1691 case WIDM_START:
1692 return widStart(wDevID);
1693 case WIDM_STOP:
1694 return widStop(wDevID);
1696 return MMSYSERR_NOTSUPPORTED;
1700 #endif /* #ifdef BUILTIN_MMSYSTEM */