Release 980329
[wine/multimedia.git] / multimedia / midi.c
blob0a2f89724e3974ac866a768eac7df087fb06f8f0
1 /*
2 * Sample MIDI Wine Driver for Linux
4 * Copyright 1994 Martin Ayotte
5 */
7 #include <stdio.h>
8 #include <errno.h>
9 #include <string.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <unistd.h>
13 #include <fcntl.h>
14 #include <sys/ioctl.h>
15 #include "windows.h"
16 #include "ldt.h"
17 #include "multimedia.h"
18 #include "user.h"
19 #include "driver.h"
20 #include "mmsystem.h"
21 #include "xmalloc.h"
22 #include "debug.h"
24 #if defined (__HAS_SOUNDCARD_H__)
26 static LINUX_MIDIIN MidiInDev[MAX_MIDIINDRV];
27 static LINUX_MIDIOUT MidiOutDev[MAX_MIDIOUTDRV];
28 static LINUX_MCIMIDI MCIMidiDev[MAX_MCIMIDIDRV];
30 #endif
32 /* this is the total number of MIDI devices found */
33 int MODM_NUMDEVS = 0;
35 /* this structure holds pointers with information for each MIDI
36 * device found.
38 LPMIDIOUTCAPS16 midiDevices[MAX_MIDIOUTDRV];
40 /**************************************************************************
41 * MIDI_NotifyClient [internal]
43 static DWORD MIDI_NotifyClient(UINT16 wDevID, WORD wMsg,
44 DWORD dwParam1, DWORD dwParam2)
46 TRACE(midi,"wDevID = %04X wMsg = %d dwParm1 = %04lX dwParam2 = %04lX\n",wDevID, wMsg, dwParam1, dwParam2);
48 #if defined(linux) || defined(__FreeBSD__)
50 switch (wMsg) {
51 case MOM_OPEN:
52 case MOM_CLOSE:
53 case MOM_DONE:
54 if (wDevID > MAX_MIDIOUTDRV) return MCIERR_INTERNAL;
56 if (MidiOutDev[wDevID].wFlags != DCB_NULL && !DriverCallback(
57 MidiOutDev[wDevID].midiDesc.dwCallback,
58 MidiOutDev[wDevID].wFlags,
59 MidiOutDev[wDevID].midiDesc.hMidi,
60 wMsg,
61 MidiOutDev[wDevID].midiDesc.dwInstance,
62 dwParam1,
63 dwParam2)) {
64 WARN(midi,"can't notify client !\n");
65 return MMSYSERR_NOERROR;
67 break;
69 case MIM_OPEN:
70 case MIM_CLOSE:
71 if (wDevID > MAX_MIDIINDRV) return MCIERR_INTERNAL;
73 if (MidiInDev[wDevID].wFlags != DCB_NULL && !DriverCallback(
74 MidiInDev[wDevID].midiDesc.dwCallback, MidiInDev[wDevID].wFlags,
75 MidiInDev[wDevID].midiDesc.hMidi, wMsg,
76 MidiInDev[wDevID].midiDesc.dwInstance, dwParam1, dwParam2)) {
77 WARN(mciwave,"can't notify client !\n");
78 return MMSYSERR_NOERROR;
80 break;
82 return 0;
83 #else
84 return MMSYSERR_NOTENABLED;
85 #endif
89 /**************************************************************************
90 * MIDI_ReadByte [internal]
92 static DWORD MIDI_ReadByte(UINT16 wDevID, BYTE *lpbyt)
94 #if defined(linux) || defined(__FreeBSD__)
95 if (lpbyt != NULL) {
96 if (mmioRead(MCIMidiDev[wDevID].hFile, (HPSTR)lpbyt,
97 (long) sizeof(BYTE)) == (long) sizeof(BYTE)) {
98 return 0;
101 WARN(midi, "error reading wDevID=%04X\n", wDevID);
102 return MCIERR_INTERNAL;
104 #else
105 return MMSYSERR_NOTENABLED;
106 #endif
110 /**************************************************************************
111 * MIDI_ReadWord [internal]
113 static DWORD MIDI_ReadWord(UINT16 wDevID, LPWORD lpw)
115 BYTE hibyte, lobyte;
116 if (lpw != NULL) {
117 if (MIDI_ReadByte(wDevID, &hibyte) == 0) {
118 if (MIDI_ReadByte(wDevID, &lobyte) == 0) {
119 *lpw = ((WORD)hibyte << 8) + lobyte;
120 return 0;
124 WARN(midi, "error reading wDevID=%04X\n", wDevID);
125 return MCIERR_INTERNAL;
129 /**************************************************************************
130 * MIDI_ReadLong [internal]
132 static DWORD MIDI_ReadLong(UINT16 wDevID, LPDWORD lpdw)
134 WORD hiword, loword;
135 if (lpdw != NULL) {
136 if (MIDI_ReadWord(wDevID, &hiword) == 0) {
137 if (MIDI_ReadWord(wDevID, &loword) == 0) {
138 *lpdw = MAKELONG(loword, hiword);
139 return 0;
143 WARN(midi, "error reading wDevID=%04X\n", wDevID);
144 return MCIERR_INTERNAL;
148 /**************************************************************************
149 * MIDI_ReadVaryLen [internal]
151 static DWORD MIDI_ReadVaryLen(UINT16 wDevID, LPDWORD lpdw)
153 BYTE byte;
154 DWORD value;
155 if (lpdw == NULL) return MCIERR_INTERNAL;
156 if (MIDI_ReadByte(wDevID, &byte) != 0) {
157 WARN(midi, "error reading wDevID=%04X\n", wDevID);
158 return MCIERR_INTERNAL;
160 value = (DWORD)(byte & 0x7F);
161 while (byte & 0x80) {
162 if (MIDI_ReadByte(wDevID, &byte) != 0) {
163 WARN(midi, "error reading wDevID=%04X\n", wDevID);
164 return MCIERR_INTERNAL;
166 value = (value << 7) + (byte & 0x7F);
168 *lpdw = value;
170 TRACE(midi, "val=%08lX \n", value);
172 return 0;
176 /**************************************************************************
177 * MIDI_ReadMThd [internal]
179 static DWORD MIDI_ReadMThd(UINT16 wDevID, DWORD dwOffset)
181 #if defined(linux) || defined(__FreeBSD__)
182 DWORD toberead;
183 FOURCC fourcc;
184 TRACE(midi, "(%04X, %08lX);\n", wDevID, dwOffset);
185 if (mmioSeek(MCIMidiDev[wDevID].hFile, dwOffset, SEEK_SET) != dwOffset) {
186 WARN(midi, "can't seek at %08lX begin of 'MThd' \n", dwOffset);
187 return MCIERR_INTERNAL;
189 if (mmioRead(MCIMidiDev[wDevID].hFile, (HPSTR)&fourcc,
190 (long) sizeof(FOURCC)) != (long) sizeof(FOURCC))
191 return MCIERR_INTERNAL;
192 if (MIDI_ReadLong(wDevID, &toberead) != 0)
193 return MCIERR_INTERNAL;
194 if (MIDI_ReadWord(wDevID, &MCIMidiDev[wDevID].wFormat) != 0)
195 return MCIERR_INTERNAL;
196 if (MIDI_ReadWord(wDevID, &MCIMidiDev[wDevID].nTracks) != 0)
197 return MCIERR_INTERNAL;
198 if (MIDI_ReadWord(wDevID, &MCIMidiDev[wDevID].nTempo) != 0)
199 return MCIERR_INTERNAL;
200 TRACE(midi, "toberead=%08lX, wFormat=%04X nTracks=%04X nTempo=%04X\n",
201 toberead, MCIMidiDev[wDevID].wFormat,
202 MCIMidiDev[wDevID].nTracks,
203 MCIMidiDev[wDevID].nTempo);
204 toberead -= 3 * sizeof(WORD);
206 ntrks = read16bit ();
207 Mf_division = division = read16bit ();
209 return 0;
210 #else
211 return MMSYSERR_NOTENABLED;
212 #endif
216 static DWORD MIDI_ReadMTrk(UINT16 wDevID, DWORD dwOffset)
218 #if defined(linux) || defined(__FreeBSD__)
219 DWORD toberead;
220 FOURCC fourcc;
221 if (mmioSeek(MCIMidiDev[wDevID].hFile, dwOffset, SEEK_SET) != dwOffset) {
222 WARN(midi, "can't seek at %08lX begin of 'MThd' \n", dwOffset);
224 if (mmioRead(MCIMidiDev[wDevID].hFile, (HPSTR)&fourcc,
225 (long) sizeof(FOURCC)) != (long) sizeof(FOURCC)) {
226 return MCIERR_INTERNAL;
228 if (MIDI_ReadLong(wDevID, &toberead) != 0) {
229 return MCIERR_INTERNAL;
231 TRACE(midi, "toberead=%08lX\n", toberead);
232 toberead -= 3 * sizeof(WORD);
233 MCIMidiDev[wDevID].dwTotalLen = toberead;
234 return 0;
235 #else
236 return MMSYSERR_NOTENABLED;
237 #endif
241 /**************************************************************************
242 * MIDI_mciOpen [internal]
244 static DWORD MIDI_mciOpen(UINT16 wDevID, DWORD dwFlags, LPMCI_OPEN_PARMS16 lpParms)
246 #if defined(linux) || defined(__FreeBSD__)
247 MIDIOPENDESC MidiDesc;
248 DWORD dwRet;
249 DWORD dwOffset;
250 LPSTR lpstrElementName;
251 char str[128];
253 TRACE(midi, "(%08lX, %p)\n", dwFlags, lpParms);
254 if (lpParms == NULL) return MCIERR_INTERNAL;
256 if (MCIMidiDev[wDevID].nUseCount > 0) {
257 /* The driver already open on this channel */
258 /* If the driver was opened shareable before and this open specifies */
259 /* shareable then increment the use count */
260 if (MCIMidiDev[wDevID].fShareable && (dwFlags & MCI_OPEN_SHAREABLE))
261 ++MCIMidiDev[wDevID].nUseCount;
262 else
263 return MCIERR_MUST_USE_SHAREABLE;
264 } else {
265 MCIMidiDev[wDevID].nUseCount = 1;
266 MCIMidiDev[wDevID].fShareable = dwFlags & MCI_OPEN_SHAREABLE;
267 MCIMidiDev[wDevID].hMidiHdr = USER_HEAP_ALLOC(sizeof(MIDIHDR));
270 TRACE(midi, "wDevID=%04X\n", wDevID);
271 /* lpParms->wDeviceID = wDevID;*/
272 TRACE(midi, "lpParms->wDevID=%04X\n", lpParms->wDeviceID);
273 TRACE(midi, "before OPEN_ELEMENT\n");
274 if (dwFlags & MCI_OPEN_ELEMENT) {
275 lpstrElementName = (LPSTR)PTR_SEG_TO_LIN(lpParms->lpstrElementName);
276 TRACE(midi, "MCI_OPEN_ELEMENT '%s' !\n", lpstrElementName);
277 if (strlen(lpstrElementName) > 0) {
278 strcpy(str, lpstrElementName);
279 CharUpper32A(str);
280 MCIMidiDev[wDevID].hFile = mmioOpen16(str, NULL,
281 MMIO_ALLOCBUF | MMIO_READWRITE | MMIO_EXCLUSIVE);
282 if (MCIMidiDev[wDevID].hFile == 0) {
283 WARN(midi, "can't find file='%s' !\n", str);
284 return MCIERR_FILE_NOT_FOUND;
286 } else
287 MCIMidiDev[wDevID].hFile = 0;
289 TRACE(midi, "hFile=%u\n", MCIMidiDev[wDevID].hFile);
290 memcpy(&MCIMidiDev[wDevID].openParms, lpParms, sizeof(MCI_OPEN_PARMS16));
291 MCIMidiDev[wDevID].wNotifyDeviceID = lpParms->wDeviceID;
292 MCIMidiDev[wDevID].dwStatus = MCI_MODE_STOP;
293 MCIMidiDev[wDevID].dwBeginData = 0;
294 MCIMidiDev[wDevID].dwTotalLen = 0;
295 MidiDesc.hMidi = 0;
296 if (MCIMidiDev[wDevID].hFile != 0) {
297 MMCKINFO ckMainRIFF;
298 if (mmioDescend(MCIMidiDev[wDevID].hFile, &ckMainRIFF, NULL, 0) != 0) {
299 return MCIERR_INTERNAL;
301 TRACE(midi,"ParentChunk ckid=%.4s fccType=%.4s cksize=%08lX \n",
302 (LPSTR)&ckMainRIFF.ckid, (LPSTR)&ckMainRIFF.fccType,
303 ckMainRIFF.cksize);
304 dwOffset = 0;
305 if (ckMainRIFF.ckid == mmioFOURCC('R', 'M', 'I', 'D')) {
306 TRACE(midi, "is a 'RMID' file \n");
307 dwOffset = ckMainRIFF.dwDataOffset;
309 if (ckMainRIFF.ckid != mmioFOURCC('M', 'T', 'h', 'd')) {
310 WARN(midi, "unknown format !\n");
311 return MCIERR_INTERNAL;
313 if (MIDI_ReadMThd(wDevID, dwOffset) != 0) {
314 WARN(midi, "can't read 'MThd' header \n");
315 return MCIERR_INTERNAL;
317 dwOffset = mmioSeek(MCIMidiDev[wDevID].hFile, 0, SEEK_CUR);
318 if (MIDI_ReadMTrk(wDevID, dwOffset) != 0) {
319 WARN(midi, "can't read 'MTrk' header \n");
320 return MCIERR_INTERNAL;
322 dwOffset = mmioSeek(MCIMidiDev[wDevID].hFile, 0, SEEK_CUR);
323 MCIMidiDev[wDevID].dwBeginData = dwOffset;
324 TRACE(midi, "Chunk Found ckid=%.4s fccType=%.4s cksize=%08lX \n",
325 (LPSTR)&ckMainRIFF.ckid, (LPSTR)&ckMainRIFF.fccType,
326 ckMainRIFF.cksize);
329 dwRet = modMessage(wDevID, MODM_OPEN, 0, (DWORD)&MidiDesc, CALLBACK_NULL);
330 /* dwRet = midMessage(wDevID, MIDM_OPEN, 0, (DWORD)&MidiDesc, CALLBACK_NULL);*/
332 return 0;
333 #else
334 return MMSYSERR_NOTENABLED;
335 #endif
338 /**************************************************************************
339 * MIDI_mciStop [internal]
341 static DWORD MIDI_mciStop(UINT16 wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
343 #if defined(linux) || defined(__FreeBSD__)
344 TRACE(midi, "(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);
345 if (lpParms == NULL) return MCIERR_INTERNAL;
346 MCIMidiDev[wDevID].dwStatus = MCI_MODE_STOP;
347 TRACE(midi, "MCIMidiDev[wDevID].dwStatus=%p %d\n",
348 &MCIMidiDev[wDevID].dwStatus, MCIMidiDev[wDevID].dwStatus);
349 return 0;
350 #else
351 return MCIERR_INTERNAL;
352 #endif
356 /**************************************************************************
357 * MIDI_mciClose [internal]
359 static DWORD MIDI_mciClose(UINT16 wDevID, DWORD dwParam, LPMCI_GENERIC_PARMS lpParms)
361 #if defined(linux) || defined(__FreeBSD__)
362 DWORD dwRet;
364 TRACE(midi, "(%04X, %08lX, %p);\n", wDevID, dwParam, lpParms);
365 if (MCIMidiDev[wDevID].dwStatus != MCI_MODE_STOP) {
366 MIDI_mciStop(wDevID, MCI_WAIT, lpParms);
368 MCIMidiDev[wDevID].dwStatus = MCI_MODE_STOP;
369 MCIMidiDev[wDevID].nUseCount--;
370 if (MCIMidiDev[wDevID].nUseCount == 0) {
371 if (MCIMidiDev[wDevID].hFile != 0) {
372 mmioClose(MCIMidiDev[wDevID].hFile, 0);
373 MCIMidiDev[wDevID].hFile = 0;
374 TRACE(midi, "hFile closed !\n");
376 USER_HEAP_FREE(MCIMidiDev[wDevID].hMidiHdr);
377 dwRet = modMessage(wDevID, MODM_CLOSE, 0, 0L, 0L);
378 if (dwRet != MMSYSERR_NOERROR) return MCIERR_INTERNAL;
380 dwRet = midMessage(wDevID, MIDM_CLOSE, 0, 0L, 0L);
381 if (dwRet != MMSYSERR_NOERROR) return MCIERR_INTERNAL;
384 return 0;
385 #else
386 return 0;
387 #endif
391 /**************************************************************************
392 * MIDI_mciPlay [internal]
394 static DWORD MIDI_mciPlay(UINT16 wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms)
396 #if defined(linux) || defined(__FreeBSD__)
397 int count,start,end;
398 LPMIDIHDR lpMidiHdr;
399 DWORD dwData,dwRet;
400 LPWORD ptr;
402 TRACE(midi, "(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);
403 if (MCIMidiDev[wDevID].hFile == 0) {
404 WARN(midi, "can't find file='%08lx' !\n",
405 (DWORD)MCIMidiDev[wDevID].openParms.lpstrElementName);
406 return MCIERR_FILE_NOT_FOUND;
408 start = 1; end = 99999;
409 if (dwFlags & MCI_FROM) {
410 start = lpParms->dwFrom;
411 TRACE(midi, "MCI_FROM=%d \n", start);
413 if (dwFlags & MCI_TO) {
414 end = lpParms->dwTo;
415 TRACE(midi, "MCI_TO=%d \n", end);
417 #if 0
418 if (dwFlags & MCI_NOTIFY) {
419 TRACE(midi, "MCI_NOTIFY %08lX !\n", lpParms->dwCallback);
420 switch(fork()) {
421 case -1:
422 WARN(midi, "Can't 'fork' process !\n");
423 break;
424 case 0:
425 TRACE(midi, "process started ! play in background ...\n");
426 break;
427 default:
428 TRACE(midi, "process started ! return to caller...\n");
429 return 0;
432 #endif
434 lpMidiHdr = USER_HEAP_LIN_ADDR(MCIMidiDev[wDevID].hMidiHdr);
436 lpMidiHdr->lpData = (LPSTR)xmalloc(1200);
437 if (lpMidiHdr->lpData == NULL) return MCIERR_INTERNAL;
438 lpMidiHdr->dwBufferLength = 1024;
439 lpMidiHdr->dwUser = 0L;
440 lpMidiHdr->dwFlags = 0L;
441 dwRet = modMessage(wDevID, MODM_PREPARE, 0, (DWORD)lpMidiHdr, sizeof(MIDIHDR));
443 /* TRACE(midi, "after MODM_PREPARE \n"); */
445 MCIMidiDev[wDevID].dwStatus = MCI_MODE_PLAY;
446 while(MCIMidiDev[wDevID].dwStatus != MCI_MODE_STOP) {
447 TRACE(midi, "MCIMidiDev[wDevID].dwStatus=%p %d\n",
448 &MCIMidiDev[wDevID].dwStatus, MCIMidiDev[wDevID].dwStatus);
450 ptr = (LPWORD)lpMidiHdr->lpData;
451 for (count = 0; count < lpMidiHdr->dwBufferLength; count++) {
452 if (MIDI_ReadVaryLen(wDevID, &dwData) != 0) break;
453 *ptr = LOWORD(dwData);
456 count = mmioRead(MCIMidiDev[wDevID].hFile, lpMidiHdr->lpData, lpMidiHdr->dwBufferLength);
458 TRACE(midi, "after read count = %d\n",count);
460 if (count < 1) break;
461 lpMidiHdr->dwBytesRecorded = count;
462 TRACE(midi, "before MODM_LONGDATA lpMidiHdr=%p dwBytesRecorded=%lu\n",
463 lpMidiHdr, lpMidiHdr->dwBytesRecorded);
464 dwRet = modMessage(wDevID, MODM_LONGDATA, 0, (DWORD)lpMidiHdr, sizeof(MIDIHDR));
465 if (dwRet != MMSYSERR_NOERROR) {
466 switch (dwRet) {
467 case MMSYSERR_NOTENABLED:
468 return MCIERR_DEVICE_NOT_READY;
470 case MIDIERR_NODEVICE:
471 return MCIERR_INVALID_DEVICE_ID;
473 case MIDIERR_UNPREPARED:
474 return MCIERR_DRIVER_INTERNAL;
476 case MIDIERR_STILLPLAYING:
477 return MCIERR_SEQ_PORT_INUSE;
479 case MMSYSERR_INVALPARAM:
480 return MCIERR_CANNOT_LOAD_DRIVER;
482 default:
483 return MCIERR_DRIVER;
487 dwRet = modMessage(wDevID, MODM_UNPREPARE, 0, (DWORD)lpMidiHdr, sizeof(MIDIHDR));
488 if (lpMidiHdr->lpData != NULL) {
489 free(lpMidiHdr->lpData);
490 lpMidiHdr->lpData = NULL;
492 MCIMidiDev[wDevID].dwStatus = MCI_MODE_STOP;
493 if (dwFlags & MCI_NOTIFY) {
494 TRACE(midi, "MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
495 mciDriverNotify((HWND16)LOWORD(lpParms->dwCallback),
496 MCIMidiDev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
497 #if 0
498 exit(1);
499 #endif
501 return 0;
502 #else
503 return MMSYSERR_NOTENABLED;
504 #endif
508 /**************************************************************************
509 * MIDI_mciRecord [internal]
511 static DWORD MIDI_mciRecord(UINT16 wDevID, DWORD dwFlags, LPMCI_RECORD_PARMS lpParms)
513 #if defined(linux) || defined(__FreeBSD__)
514 int start, end;
515 LPMIDIHDR lpMidiHdr;
516 DWORD dwRet;
518 TRACE(midi, "(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);
519 if (MCIMidiDev[wDevID].hFile == 0) {
520 WARN(midi, "can't find file='%08lx' !\n",
521 (DWORD)MCIMidiDev[wDevID].openParms.lpstrElementName);
522 return MCIERR_FILE_NOT_FOUND;
524 start = 1; end = 99999;
525 if (dwFlags & MCI_FROM) {
526 start = lpParms->dwFrom;
527 TRACE(midi, "MCI_FROM=%d \n", start);
529 if (dwFlags & MCI_TO) {
530 end = lpParms->dwTo;
531 TRACE(midi, "MCI_TO=%d \n", end);
533 lpMidiHdr = USER_HEAP_LIN_ADDR(MCIMidiDev[wDevID].hMidiHdr);
534 lpMidiHdr->lpData = (LPSTR) xmalloc(1200);
535 lpMidiHdr->dwBufferLength = 1024;
536 lpMidiHdr->dwUser = 0L;
537 lpMidiHdr->dwFlags = 0L;
538 dwRet = midMessage(wDevID, MIDM_PREPARE, 0, (DWORD)lpMidiHdr, sizeof(MIDIHDR));
539 TRACE(midi, "after MIDM_PREPARE \n");
540 MCIMidiDev[wDevID].dwStatus = MCI_MODE_RECORD;
541 while(MCIMidiDev[wDevID].dwStatus != MCI_MODE_STOP) {
542 TRACE(midi, "MCIMidiDev[wDevID].dwStatus=%p %d\n",
543 &MCIMidiDev[wDevID].dwStatus, MCIMidiDev[wDevID].dwStatus);
544 lpMidiHdr->dwBytesRecorded = 0;
545 dwRet = midMessage(wDevID, MIDM_START, 0, 0L, 0L);
546 TRACE(midi, "after MIDM_START lpMidiHdr=%p dwBytesRecorded=%lu\n",
547 lpMidiHdr, lpMidiHdr->dwBytesRecorded);
548 if (lpMidiHdr->dwBytesRecorded == 0) break;
550 TRACE(midi, "before MIDM_UNPREPARE \n");
551 dwRet = midMessage(wDevID, MIDM_UNPREPARE, 0, (DWORD)lpMidiHdr, sizeof(MIDIHDR));
552 TRACE(midi, "after MIDM_UNPREPARE \n");
553 if (lpMidiHdr->lpData != NULL) {
554 free(lpMidiHdr->lpData);
555 lpMidiHdr->lpData = NULL;
557 MCIMidiDev[wDevID].dwStatus = MCI_MODE_STOP;
558 if (dwFlags & MCI_NOTIFY) {
559 TRACE(midi, "MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
560 mciDriverNotify((HWND16)LOWORD(lpParms->dwCallback),
561 MCIMidiDev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
563 return 0;
564 #else
565 return MMSYSERR_NOTENABLED;
566 #endif
570 /**************************************************************************
571 * MIDI_mciPause [internal]
573 static DWORD MIDI_mciPause(UINT16 wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
575 #if defined(linux) || defined(__FreeBSD__)
576 TRACE(midi, "(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);
577 if (lpParms == NULL) return MCIERR_INTERNAL;
578 return 0;
579 #else
580 return MCIERR_INTERNAL;
581 #endif
585 /**************************************************************************
586 * MIDI_mciResume [internal]
588 static DWORD MIDI_mciResume(UINT16 wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
590 #if defined(linux) || defined(__FreeBSD__)
591 TRACE(midi, "(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);
592 if (lpParms == NULL) return MCIERR_INTERNAL;
593 return 0;
594 #else
595 return MCIERR_INTERNAL;
596 #endif
600 /**************************************************************************
601 * MIDI_mciSet [internal]
603 static DWORD MIDI_mciSet(UINT16 wDevID, DWORD dwFlags, LPMCI_SET_PARMS lpParms)
605 #if defined(linux) || defined(__FreeBSD__)
606 TRACE(midi, "(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);
607 if (lpParms == NULL) return MCIERR_INTERNAL;
608 TRACE(midi, "dwTimeFormat=%08lX\n", lpParms->dwTimeFormat);
609 TRACE(midi, "dwAudio=%08lX\n", lpParms->dwAudio);
610 if (dwFlags & MCI_SET_TIME_FORMAT) {
611 switch (lpParms->dwTimeFormat) {
612 case MCI_FORMAT_MILLISECONDS:
613 TRACE(midi, "MCI_FORMAT_MILLISECONDS !\n");
614 break;
615 case MCI_FORMAT_BYTES:
616 TRACE(midi, "MCI_FORMAT_BYTES !\n");
617 break;
618 case MCI_FORMAT_SAMPLES:
619 TRACE(midi, "MCI_FORMAT_SAMPLES !\n");
620 break;
621 default:
622 WARN(midi, "bad time format !\n");
623 return MCIERR_BAD_TIME_FORMAT;
626 if (dwFlags & MCI_SET_VIDEO) return MCIERR_UNSUPPORTED_FUNCTION;
627 if (dwFlags & MCI_SET_DOOR_OPEN) return MCIERR_UNSUPPORTED_FUNCTION;
628 if (dwFlags & MCI_SET_DOOR_CLOSED) return MCIERR_UNSUPPORTED_FUNCTION;
629 if (dwFlags & MCI_SET_AUDIO)
630 TRACE(midi, "MCI_SET_AUDIO !\n");
631 if (dwFlags && MCI_SET_ON) {
632 TRACE(midi, "MCI_SET_ON !\n");
633 if (dwFlags && MCI_SET_AUDIO_LEFT)
634 TRACE(midi, "MCI_SET_AUDIO_LEFT !\n");
635 if (dwFlags && MCI_SET_AUDIO_RIGHT)
636 TRACE(midi, "MCI_SET_AUDIO_RIGHT !\n");
638 if (dwFlags & MCI_SET_OFF)
639 TRACE(midi, "MCI_SET_OFF !\n");
640 if (dwFlags & MCI_SEQ_SET_MASTER)
641 TRACE(midi, "MCI_SEQ_SET_MASTER !\n");
642 if (dwFlags & MCI_SEQ_SET_SLAVE)
643 TRACE(midi, "MCI_SEQ_SET_SLAVE !\n");
644 if (dwFlags & MCI_SEQ_SET_OFFSET)
645 TRACE(midi, "MCI_SEQ_SET_OFFSET !\n");
646 if (dwFlags & MCI_SEQ_SET_PORT)
647 TRACE(midi, "MCI_SEQ_SET_PORT !\n");
648 if (dwFlags & MCI_SEQ_SET_TEMPO)
649 TRACE(midi, "MCI_SEQ_SET_TEMPO !\n");
650 return 0;
651 #else
652 return MCIERR_INTERNAL;
653 #endif
657 /**************************************************************************
658 * MIDI_mciStatus [internal]
660 static DWORD MIDI_mciStatus(UINT16 wDevID, DWORD dwFlags, LPMCI_STATUS_PARMS lpParms)
662 #if defined(linux) || defined(__FreeBSD__)
663 TRACE(midi, "(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);
664 if (lpParms == NULL) return MCIERR_INTERNAL;
665 if (dwFlags & MCI_STATUS_ITEM) {
666 switch(lpParms->dwItem) {
667 case MCI_STATUS_CURRENT_TRACK:
668 lpParms->dwReturn = 1;
669 break;
670 case MCI_STATUS_LENGTH:
671 lpParms->dwReturn = 5555;
672 if (dwFlags & MCI_TRACK) {
673 lpParms->dwTrack = 1;
674 lpParms->dwReturn = 2222;
676 break;
677 case MCI_STATUS_MODE:
678 lpParms->dwReturn = MCI_MODE_STOP;
679 break;
680 case MCI_STATUS_MEDIA_PRESENT:
681 TRACE(midi, "MCI_STATUS_MEDIA_PRESENT !\n");
682 lpParms->dwReturn = TRUE;
683 break;
684 case MCI_STATUS_NUMBER_OF_TRACKS:
685 lpParms->dwReturn = 1;
686 break;
687 case MCI_STATUS_POSITION:
688 lpParms->dwReturn = 3333;
689 if (dwFlags & MCI_STATUS_START)
690 lpParms->dwItem = 1;
691 if (dwFlags & MCI_TRACK) {
692 lpParms->dwTrack = 1;
693 lpParms->dwReturn = 777;
695 break;
696 case MCI_STATUS_READY:
697 TRACE(midi, "MCI_STATUS_READY !\n");
698 lpParms->dwReturn = TRUE;
699 break;
700 case MCI_STATUS_TIME_FORMAT:
701 TRACE(midi, "MCI_STATUS_TIME_FORMAT !\n");
702 lpParms->dwReturn = MCI_FORMAT_MILLISECONDS;
703 break;
704 case MCI_SEQ_STATUS_DIVTYPE:
705 TRACE(midi, "MCI_SEQ_STATUS_DIVTYPE !\n");
706 lpParms->dwReturn = 0;
707 break;
708 case MCI_SEQ_STATUS_MASTER:
709 TRACE(midi, "MCI_SEQ_STATUS_MASTER !\n");
710 lpParms->dwReturn = 0;
711 break;
712 case MCI_SEQ_STATUS_SLAVE:
713 TRACE(midi, "MCI_SEQ_STATUS_SLAVE !\n");
714 lpParms->dwReturn = 0;
715 break;
716 case MCI_SEQ_STATUS_OFFSET:
717 TRACE(midi, "MCI_SEQ_STATUS_OFFSET !\n");
718 lpParms->dwReturn = 0;
719 break;
720 case MCI_SEQ_STATUS_PORT:
721 TRACE(midi, "MCI_SEQ_STATUS_PORT !\n");
722 lpParms->dwReturn = 0;
723 break;
724 case MCI_SEQ_STATUS_TEMPO:
725 TRACE(midi, "MCI_SEQ_STATUS_TEMPO !\n");
726 lpParms->dwReturn = 0;
727 break;
728 default:
729 WARN(midi, "unknowm command %08lX !\n", lpParms->dwItem);
730 return MCIERR_UNRECOGNIZED_COMMAND;
733 if (dwFlags & MCI_NOTIFY) {
734 TRACE(midi, "MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
735 mciDriverNotify((HWND16)LOWORD(lpParms->dwCallback),
736 MCIMidiDev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
738 return 0;
739 #else
740 return MCIERR_INTERNAL;
741 #endif
744 /**************************************************************************
745 * MIDI_mciGetDevCaps [internal]
747 static DWORD MIDI_mciGetDevCaps(UINT16 wDevID, DWORD dwFlags,
748 LPMCI_GETDEVCAPS_PARMS lpParms)
750 #if defined(linux) || defined(__FreeBSD__)
751 TRACE(midi, "(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);
752 if (lpParms == NULL) return MCIERR_INTERNAL;
753 if (dwFlags & MCI_GETDEVCAPS_ITEM) {
754 switch(lpParms->dwItem) {
755 case MCI_GETDEVCAPS_CAN_RECORD:
756 lpParms->dwReturn = TRUE;
757 break;
758 case MCI_GETDEVCAPS_HAS_AUDIO:
759 lpParms->dwReturn = TRUE;
760 break;
761 case MCI_GETDEVCAPS_HAS_VIDEO:
762 lpParms->dwReturn = FALSE;
763 break;
764 case MCI_GETDEVCAPS_DEVICE_TYPE:
765 lpParms->dwReturn = MCI_DEVTYPE_SEQUENCER;
766 break;
767 case MCI_GETDEVCAPS_USES_FILES:
768 lpParms->dwReturn = TRUE;
769 break;
770 case MCI_GETDEVCAPS_COMPOUND_DEVICE:
771 lpParms->dwReturn = TRUE;
772 break;
773 case MCI_GETDEVCAPS_CAN_EJECT:
774 lpParms->dwReturn = FALSE;
775 break;
776 case MCI_GETDEVCAPS_CAN_PLAY:
777 lpParms->dwReturn = TRUE;
778 break;
779 case MCI_GETDEVCAPS_CAN_SAVE:
780 lpParms->dwReturn = FALSE;
781 break;
782 default:
783 return MCIERR_UNRECOGNIZED_COMMAND;
786 return 0;
787 #else
788 return MCIERR_INTERNAL;
789 #endif
793 /**************************************************************************
794 * MIDI_mciInfo [internal]
796 static DWORD MIDI_mciInfo(UINT16 wDevID, DWORD dwFlags, LPMCI_INFO_PARMS16 lpParms)
798 # if defined(__FreeBSD__) || defined (linux)
799 TRACE(midi, "(%04X, %08lX, %p);\n", wDevID, dwFlags, lpParms);
800 if (lpParms == NULL) return MCIERR_INTERNAL;
801 lpParms->lpstrReturn = NULL;
802 switch(dwFlags) {
803 case MCI_INFO_PRODUCT:
804 lpParms->lpstrReturn = "Linux Sound System 0.5";
805 break;
806 case MCI_INFO_FILE:
807 lpParms->lpstrReturn = "FileName";
808 break;
809 default:
810 return MCIERR_UNRECOGNIZED_COMMAND;
812 if (lpParms->lpstrReturn != NULL)
813 lpParms->dwRetSize = strlen(lpParms->lpstrReturn);
814 else
815 lpParms->dwRetSize = 0;
816 return 0;
817 #else
818 return MCIERR_INTERNAL;
819 #endif
823 /*-----------------------------------------------------------------------*/
826 /**************************************************************************
827 * midGetDevCaps [internal]
829 static DWORD midGetDevCaps(WORD wDevID, LPMIDIINCAPS16 lpCaps, DWORD dwSize)
831 TRACE(midi, "(%04X, %p, %08lX);\n", wDevID, lpCaps, dwSize);
832 lpCaps->wMid = 0x00FF; /* Manufac ID */
833 lpCaps->wPid = 0x0001; /* Product ID */
834 lpCaps->vDriverVersion = 0x001; /* Product Version */
835 strcpy(lpCaps->szPname, "Linux MIDIIN Driver");
837 return MMSYSERR_NOERROR;
840 /**************************************************************************
841 * midOpen [internal]
843 static DWORD midOpen(WORD wDevID, LPMIDIOPENDESC lpDesc, DWORD dwFlags)
845 #if defined(linux) || defined(__FreeBSD__)
846 int midi;
847 TRACE(midi, "(%04X, %p, %08lX);\n", wDevID, lpDesc, dwFlags);
848 if (lpDesc == NULL) {
849 WARN(midi, "Invalid Parameter !\n");
850 return MMSYSERR_INVALPARAM;
852 if (wDevID >= MAX_MIDIINDRV) {
853 TRACE(midi,"MAX_MIDIINDRV reached !\n");
854 return MMSYSERR_ALLOCATED;
856 MidiInDev[wDevID].unixdev = 0;
857 midi = open (MIDI_DEV, O_RDONLY, 0);
858 if (midi == -1) {
859 WARN(midi,"can't open !\n");
860 return MMSYSERR_NOTENABLED;
862 MidiInDev[wDevID].wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
863 switch(MidiInDev[wDevID].wFlags) {
864 case DCB_NULL:
865 TRACE(midi,"CALLBACK_NULL !\n");
866 break;
867 case DCB_WINDOW:
868 TRACE(midi, "CALLBACK_WINDOW !\n");
869 break;
870 case DCB_TASK:
871 TRACE(midi, "CALLBACK_TASK !\n");
872 break;
873 case DCB_FUNCTION:
874 TRACE(midi, "CALLBACK_FUNCTION !\n");
875 break;
877 MidiInDev[wDevID].lpQueueHdr = NULL;
878 MidiInDev[wDevID].unixdev = midi;
879 MidiInDev[wDevID].dwTotalPlayed = 0;
880 MidiInDev[wDevID].bufsize = 0x3FFF;
881 if (MIDI_NotifyClient(wDevID, MIM_OPEN, 0L, 0L) != MMSYSERR_NOERROR) {
882 WARN(midi,"can't notify client !\n");
883 return MMSYSERR_INVALPARAM;
885 return MMSYSERR_NOERROR;
886 #else
887 return MMSYSERR_NOTENABLED;
888 #endif
891 /**************************************************************************
892 * midClose [internal]
894 static DWORD midClose(WORD wDevID)
896 #if defined(linux) || defined(__FreeBSD__)
897 TRACE(midi, "(%04X);\n", wDevID);
898 if (MidiInDev[wDevID].unixdev == 0) {
899 WARN(midi,"can't close !\n");
900 return MMSYSERR_NOTENABLED;
902 close(MidiInDev[wDevID].unixdev);
903 MidiInDev[wDevID].unixdev = 0;
904 MidiInDev[wDevID].bufsize = 0;
905 if (MIDI_NotifyClient(wDevID, MIM_CLOSE, 0L, 0L) != MMSYSERR_NOERROR) {
906 WARN(midi,"can't notify client !\n");
907 return MMSYSERR_INVALPARAM;
909 return MMSYSERR_NOERROR;
910 #else
911 return MMSYSERR_NOTENABLED;
912 #endif
915 /**************************************************************************
916 * midAddBuffer [internal]
918 static DWORD midAddBuffer(WORD wDevID, LPMIDIHDR lpMidiHdr, DWORD dwSize)
920 TRACE(midi, "(%04X, %p, %08lX);\n", wDevID, lpMidiHdr, dwSize);
921 return MMSYSERR_NOTENABLED;
924 /**************************************************************************
925 * midPrepare [internal]
927 static DWORD midPrepare(WORD wDevID, LPMIDIHDR lpMidiHdr, DWORD dwSize)
929 TRACE(midi, "(%04X, %p, %08lX);\n", wDevID, lpMidiHdr, dwSize);
930 return MMSYSERR_NOTENABLED;
933 /**************************************************************************
934 * midUnprepare [internal]
936 static DWORD midUnprepare(WORD wDevID, LPMIDIHDR lpMidiHdr, DWORD dwSize)
938 TRACE(midi, "(%04X, %p, %08lX);\n", wDevID, lpMidiHdr, dwSize);
939 return MMSYSERR_NOTENABLED;
942 /**************************************************************************
943 * midReset [internal]
945 static DWORD midReset(WORD wDevID)
947 TRACE(midi, "(%04X);\n", wDevID);
948 return MMSYSERR_NOTENABLED;
952 /**************************************************************************
953 * midStart [internal]
955 static DWORD midStart(WORD wDevID)
957 TRACE(midi, "(%04X);\n", wDevID);
958 return MMSYSERR_NOTENABLED;
962 /**************************************************************************
963 * midStop [internal]
965 static DWORD midStop(WORD wDevID)
967 TRACE(midi, "(%04X);\n", wDevID);
968 return MMSYSERR_NOTENABLED;
972 /**************************************************************************
973 * midMessage [sample driver]
975 DWORD midMessage(WORD wDevID, WORD wMsg, DWORD dwUser,
976 DWORD dwParam1, DWORD dwParam2)
978 TRACE(midi, "(%04X, %04X, %08lX, %08lX, %08lX);\n",
979 wDevID, wMsg, dwUser, dwParam1, dwParam2);
980 switch(wMsg) {
981 case MIDM_OPEN:
982 return midOpen(wDevID,(LPMIDIOPENDESC)dwParam1, dwParam2);
983 case MIDM_CLOSE:
984 return midClose(wDevID);
985 case MIDM_ADDBUFFER:
986 return midAddBuffer(wDevID,(LPMIDIHDR)dwParam1, dwParam2);
987 case MIDM_PREPARE:
988 return midPrepare(wDevID,(LPMIDIHDR)dwParam1, dwParam2);
989 case MIDM_UNPREPARE:
990 return midUnprepare(wDevID,(LPMIDIHDR)dwParam1, dwParam2);
991 case MIDM_GETDEVCAPS:
992 return midGetDevCaps(wDevID,(LPMIDIINCAPS16)dwParam1,dwParam2);
993 case MIDM_GETNUMDEVS:
994 return 0;
995 case MIDM_RESET:
996 return midReset(wDevID);
997 case MIDM_START:
998 return midStart(wDevID);
999 case MIDM_STOP:
1000 return midStop(wDevID);
1002 return MMSYSERR_NOTSUPPORTED;
1005 /*-----------------------------------------------------------------------*/
1007 /**************************************************************************
1008 * modGetDevCaps [internal]
1010 static DWORD modGetDevCaps(WORD wDevID, LPMIDIOUTCAPS16 lpCaps, DWORD dwSize)
1012 LPMIDIOUTCAPS16 tmplpCaps;
1014 TRACE(midi, "(%04X, %p, %08lX);\n", wDevID, lpCaps, dwSize);
1015 if (wDevID == (WORD) MIDI_MAPPER) {
1016 lpCaps->wMid = 0x00FF; /* Manufac ID */
1017 lpCaps->wPid = 0x0001; /* Product ID */
1018 lpCaps->vDriverVersion = 0x001; /* Product Version */
1019 strcpy(lpCaps->szPname, "MIDI Maper (not functional yet)");
1020 lpCaps->wTechnology = MOD_FMSYNTH; /* FIXME Does it make any difference ? */
1021 lpCaps->wVoices = 14; /* FIXME */
1022 lpCaps->wNotes = 14; /* FIXME */
1023 lpCaps->dwSupport = MIDICAPS_VOLUME|MIDICAPS_LRVOLUME; /* FIXME Does it make any difference ? */
1024 } else {
1025 /* FIXME There is a way to do it so easily, but I'm too
1026 * sleepy to think and I want to test
1028 tmplpCaps = midiDevices [wDevID];
1029 lpCaps->wMid = tmplpCaps->wMid;
1030 lpCaps->wPid = tmplpCaps->wPid;
1031 lpCaps->vDriverVersion = tmplpCaps->vDriverVersion;
1032 strcpy(lpCaps->szPname, tmplpCaps->szPname);
1033 lpCaps->wTechnology = tmplpCaps->wTechnology;
1034 lpCaps->wVoices = tmplpCaps->wVoices;
1035 lpCaps->wNotes = tmplpCaps->wNotes;
1036 lpCaps->dwSupport = tmplpCaps->dwSupport;
1038 return MMSYSERR_NOERROR;
1041 /**************************************************************************
1042 * modOpen [internal]
1044 static DWORD modOpen(WORD wDevID, LPMIDIOPENDESC lpDesc, DWORD dwFlags)
1046 #if defined(linux) || defined(__FreeBSD__)
1047 int midi;
1049 TRACE(midi, "(%04X, %p, %08lX);\n", wDevID, lpDesc, dwFlags);
1050 if (lpDesc == NULL) {
1051 WARN(midi, "Invalid Parameter !\n");
1052 return MMSYSERR_INVALPARAM;
1054 if (wDevID>= MAX_MIDIOUTDRV) {
1055 TRACE(midi,"MAX_MIDIOUTDRV reached !\n");
1056 return MMSYSERR_ALLOCATED; /* FIXME isn't MMSYSERR_BADDEVICEID the right answer ? */
1058 MidiOutDev[wDevID].unixdev = 0;
1059 midi = open (MIDI_DEV, O_WRONLY, 0);
1060 if (midi == -1) {
1061 WARN(midi, "can't open !\n");
1062 return MMSYSERR_NOTENABLED;
1064 MidiOutDev[wDevID].wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
1065 switch(MidiOutDev[wDevID].wFlags) {
1066 case DCB_NULL:
1067 TRACE(midi,"CALLBACK_NULL !\n");
1068 break;
1069 case DCB_WINDOW:
1070 TRACE(midi, "CALLBACK_WINDOW !\n");
1071 break;
1072 case DCB_TASK:
1073 TRACE(midi, "CALLBACK_TASK !\n");
1074 break;
1075 case DCB_FUNCTION:
1076 TRACE(midi, "CALLBACK_FUNCTION !\n");
1077 break;
1079 MidiOutDev[wDevID].lpQueueHdr = NULL;
1080 MidiOutDev[wDevID].unixdev = midi;
1081 MidiOutDev[wDevID].dwTotalPlayed = 0;
1082 MidiOutDev[wDevID].bufsize = 0x3FFF;
1083 if (MIDI_NotifyClient(wDevID, MOM_OPEN, 0L, 0L) != MMSYSERR_NOERROR) {
1084 WARN(midi,"can't notify client !\n");
1085 return MMSYSERR_INVALPARAM;
1087 TRACE(midi, "Succesful unixdev=%d !\n", midi);
1088 return MMSYSERR_NOERROR;
1089 #else
1090 return MMSYSERR_NOTENABLED;
1091 #endif
1095 /**************************************************************************
1096 * modClose [internal]
1098 static DWORD modClose(WORD wDevID)
1100 #if defined(linux) || defined(__FreeBSD__)
1101 TRACE(midi, "(%04X);\n", wDevID);
1102 if (MidiOutDev[wDevID].unixdev == 0) {
1103 WARN(midi,"can't close !\n");
1104 return MMSYSERR_NOTENABLED;
1106 close(MidiOutDev[wDevID].unixdev);
1107 MidiOutDev[wDevID].unixdev = 0;
1108 MidiOutDev[wDevID].bufsize = 0;
1109 if (MIDI_NotifyClient(wDevID, MOM_CLOSE, 0L, 0L) != MMSYSERR_NOERROR) {
1110 WARN(midi,"can't notify client !\n");
1111 return MMSYSERR_INVALPARAM;
1113 return MMSYSERR_NOERROR;
1114 #else
1115 return MMSYSERR_NOTENABLED;
1116 #endif
1119 /**************************************************************************
1120 * modData [internal]
1122 static DWORD modData(WORD wDevID, DWORD dwParam)
1124 #if defined(linux) || defined(__FreeBSD__)
1125 WORD event;
1127 TRACE(midi, "(%04X, %08lX);\n", wDevID, dwParam);
1128 if (MidiOutDev[wDevID].unixdev == 0) {
1129 WARN(midi,"can't play !\n");
1130 return MIDIERR_NODEVICE;
1132 event = LOWORD(dwParam);
1133 if (write (MidiOutDev[wDevID].unixdev,
1134 &event, sizeof(WORD)) != sizeof(WORD)) {
1135 WARN(midi, "error writting unixdev !\n");
1137 return MMSYSERR_NOTENABLED;
1138 #else
1139 return MMSYSERR_NOTENABLED;
1140 #endif
1143 /**************************************************************************
1144 * modLongData [internal]
1146 static DWORD modLongData(WORD wDevID, LPMIDIHDR lpMidiHdr, DWORD dwSize)
1148 #if defined(linux) || defined(__FreeBSD__)
1149 int count;
1150 LPWORD ptr;
1151 int en;
1153 TRACE(midi, "(%04X, %p, %08lX);\n", wDevID, lpMidiHdr, dwSize);
1154 if (MidiOutDev[wDevID].unixdev == 0) {
1155 WARN(midi,"can't play !\n");
1156 return MIDIERR_NODEVICE;
1158 if (lpMidiHdr->lpData == NULL) return MIDIERR_UNPREPARED;
1159 if (!(lpMidiHdr->dwFlags & MHDR_PREPARED)) return MIDIERR_UNPREPARED;
1160 if (lpMidiHdr->dwFlags & MHDR_INQUEUE) return MIDIERR_STILLPLAYING;
1161 lpMidiHdr->dwFlags &= ~MHDR_DONE;
1162 lpMidiHdr->dwFlags |= MHDR_INQUEUE;
1163 TRACE(midi, "dwBytesRecorded %lu !\n", lpMidiHdr->dwBytesRecorded);
1164 TRACE(midi, " %02X %02X %02X %02X\n",
1165 lpMidiHdr->lpData[0], lpMidiHdr->lpData[1],
1166 lpMidiHdr->lpData[2], lpMidiHdr->lpData[3]);
1168 count = write (MidiOutDev[wDevID].unixdev,
1169 lpMidiHdr->lpData, lpMidiHdr->dwBytesRecorded);
1171 ptr = (LPWORD)lpMidiHdr->lpData;
1172 for (count = 0; count < lpMidiHdr->dwBytesRecorded; count++) {
1173 if (write (MidiOutDev[wDevID].unixdev, ptr,
1174 sizeof(WORD)) != sizeof(WORD)) break;
1175 ptr++;
1178 en = errno;
1179 TRACE(midi, "after write count = %d\n",count);
1180 if (count != lpMidiHdr->dwBytesRecorded) {
1181 WARN(midi, "error writting unixdev #%d ! (%d != %ld)\n",
1182 MidiOutDev[wDevID].unixdev, count,
1183 lpMidiHdr->dwBytesRecorded);
1184 TRACE(midi, "\terrno = %d error = %s\n",en,strerror(en));
1185 return MMSYSERR_NOTENABLED;
1187 lpMidiHdr->dwFlags &= ~MHDR_INQUEUE;
1188 lpMidiHdr->dwFlags |= MHDR_DONE;
1189 if (MIDI_NotifyClient(wDevID, MOM_DONE, 0L, 0L) != MMSYSERR_NOERROR) {
1190 WARN(midi,"can't notify client !\n");
1191 return MMSYSERR_INVALPARAM;
1193 return MMSYSERR_NOERROR;
1194 #else
1195 return MMSYSERR_NOTENABLED;
1196 #endif
1199 /**************************************************************************
1200 * modPrepare [internal]
1202 static DWORD modPrepare(WORD wDevID, LPMIDIHDR lpMidiHdr, DWORD dwSize)
1204 #if defined(linux) || defined(__FreeBSD__)
1205 TRACE(midi, "(%04X, %p, %08lX);\n", wDevID, lpMidiHdr, dwSize);
1206 if (MidiOutDev[wDevID].unixdev == 0) {
1207 WARN(midi,"can't prepare !\n");
1208 return MMSYSERR_NOTENABLED;
1210 if (MidiOutDev[wDevID].lpQueueHdr != NULL) {
1211 TRACE(midi,"already prepare !\n");
1212 return MMSYSERR_NOTENABLED;
1214 MidiOutDev[wDevID].dwTotalPlayed = 0;
1215 MidiOutDev[wDevID].lpQueueHdr = PTR_SEG_TO_LIN(lpMidiHdr);
1216 if (lpMidiHdr->dwFlags & MHDR_INQUEUE) return MIDIERR_STILLPLAYING;
1217 lpMidiHdr->dwFlags |= MHDR_PREPARED;
1218 lpMidiHdr->dwFlags &= ~MHDR_DONE;
1219 return MMSYSERR_NOERROR;
1220 #else
1221 return MMSYSERR_NOTENABLED;
1222 #endif
1225 /**************************************************************************
1226 * modUnprepare [internal]
1228 static DWORD modUnprepare(WORD wDevID, LPMIDIHDR lpMidiHdr, DWORD dwSize)
1230 #if defined(linux) || defined(__FreeBSD__)
1231 TRACE(midi, "(%04X, %p, %08lX);\n", wDevID, lpMidiHdr, dwSize);
1232 if (MidiOutDev[wDevID].unixdev == 0) {
1233 WARN(midi,"can't unprepare !\n");
1234 return MMSYSERR_NOTENABLED;
1236 return MMSYSERR_NOERROR;
1237 #else
1238 return MMSYSERR_NOTENABLED;
1239 #endif
1242 /**************************************************************************
1243 * modReset [internal]
1245 static DWORD modReset(WORD wDevID)
1247 TRACE(midi, "(%04X);\n", wDevID);
1248 return MMSYSERR_NOTENABLED;
1252 /**************************************************************************
1253 * modMessage [sample driver]
1255 DWORD modMessage(WORD wDevID, WORD wMsg, DWORD dwUser,
1256 DWORD dwParam1, DWORD dwParam2)
1258 TRACE(midi, "(%04X, %04X, %08lX, %08lX, %08lX);\n",
1259 wDevID, wMsg, dwUser, dwParam1, dwParam2);
1260 switch(wMsg) {
1261 case MODM_OPEN:
1262 return modOpen(wDevID, (LPMIDIOPENDESC)dwParam1, dwParam2);
1263 case MODM_CLOSE:
1264 return modClose(wDevID);
1265 case MODM_DATA:
1266 return modData(wDevID, dwParam1);
1267 case MODM_LONGDATA:
1268 return modLongData(wDevID, (LPMIDIHDR)dwParam1, dwParam2);
1269 case MODM_PREPARE:
1270 return modPrepare(wDevID, (LPMIDIHDR)dwParam1, dwParam2);
1271 case MODM_UNPREPARE:
1272 return modUnprepare(wDevID, (LPMIDIHDR)dwParam1, dwParam2);
1273 case MODM_GETDEVCAPS:
1274 return modGetDevCaps(wDevID,(LPMIDIOUTCAPS16)dwParam1,dwParam2);
1275 case MODM_GETNUMDEVS:
1276 return MODM_NUMDEVS;
1277 case MODM_GETVOLUME:
1278 return 0;
1279 case MODM_SETVOLUME:
1280 return 0;
1281 case MODM_RESET:
1282 return modReset(wDevID);
1284 return MMSYSERR_NOTSUPPORTED;
1288 /**************************************************************************
1289 * MIDI_DriverProc [sample driver]
1291 LONG MIDI_DriverProc(DWORD dwDevID, HDRVR16 hDriv, WORD wMsg,
1292 DWORD dwParam1, DWORD dwParam2)
1294 #if defined(linux) || defined(__FreeBSD__)
1295 switch(wMsg) {
1296 case DRV_LOAD:
1297 return 1;
1298 case DRV_FREE:
1299 return 1;
1300 case DRV_OPEN:
1301 return 1;
1302 case DRV_CLOSE:
1303 return 1;
1304 case DRV_ENABLE:
1305 return 1;
1306 case DRV_DISABLE:
1307 return 1;
1308 case DRV_QUERYCONFIGURE:
1309 return 1;
1310 case DRV_CONFIGURE:
1311 MessageBox16(0, "Sample Midi Linux Driver !",
1312 "MMLinux Driver", MB_OK);
1313 return 1;
1314 case DRV_INSTALL:
1315 return DRVCNF_RESTART;
1316 case DRV_REMOVE:
1317 return DRVCNF_RESTART;
1318 case MCI_OPEN_DRIVER:
1319 case MCI_OPEN:
1320 return MIDI_mciOpen(dwDevID, dwParam1, (LPMCI_OPEN_PARMS16)PTR_SEG_TO_LIN(dwParam2));
1321 case MCI_CLOSE_DRIVER:
1322 case MCI_CLOSE:
1323 return MIDI_mciClose(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)PTR_SEG_TO_LIN(dwParam2));
1324 case MCI_PLAY:
1325 return MIDI_mciPlay(dwDevID, dwParam1, (LPMCI_PLAY_PARMS)PTR_SEG_TO_LIN(dwParam2));
1326 case MCI_RECORD:
1327 return MIDI_mciRecord(dwDevID, dwParam1, (LPMCI_RECORD_PARMS)PTR_SEG_TO_LIN(dwParam2));
1328 case MCI_STOP:
1329 return MIDI_mciStop(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)PTR_SEG_TO_LIN(dwParam2));
1330 case MCI_SET:
1331 return MIDI_mciSet(dwDevID, dwParam1, (LPMCI_SET_PARMS)PTR_SEG_TO_LIN(dwParam2));
1332 case MCI_PAUSE:
1333 return MIDI_mciPause(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)PTR_SEG_TO_LIN(dwParam2));
1334 case MCI_RESUME:
1335 return MIDI_mciResume(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)PTR_SEG_TO_LIN(dwParam2));
1336 case MCI_STATUS:
1337 return MIDI_mciStatus(dwDevID, dwParam1, (LPMCI_STATUS_PARMS)PTR_SEG_TO_LIN(dwParam2));
1338 case MCI_GETDEVCAPS:
1339 return MIDI_mciGetDevCaps(dwDevID, dwParam1, (LPMCI_GETDEVCAPS_PARMS)PTR_SEG_TO_LIN(dwParam2));
1340 case MCI_INFO:
1341 return MIDI_mciInfo(dwDevID, dwParam1, (LPMCI_INFO_PARMS16)PTR_SEG_TO_LIN(dwParam2));
1342 default:
1343 return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);
1345 #else
1346 return MMSYSERR_NOTENABLED;
1347 #endif
1351 /*-----------------------------------------------------------------------*/