2 * Sample MIDI Wine Driver for Linux
4 * Copyright 1994 Martin Ayotte
14 #include <sys/ioctl.h>
17 #include "multimedia.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
];
32 /* this is the total number of MIDI devices found */
35 /* this structure holds pointers with information for each MIDI
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__)
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
,
61 MidiOutDev
[wDevID
].midiDesc
.dwInstance
,
64 WARN(midi
,"can't notify client !\n");
65 return MMSYSERR_NOERROR
;
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
;
84 return MMSYSERR_NOTENABLED
;
89 /**************************************************************************
90 * MIDI_ReadByte [internal]
92 static DWORD
MIDI_ReadByte(UINT16 wDevID
, BYTE
*lpbyt
)
94 #if defined(linux) || defined(__FreeBSD__)
96 if (mmioRead(MCIMidiDev
[wDevID
].hFile
, (HPSTR
)lpbyt
,
97 (long) sizeof(BYTE
)) == (long) sizeof(BYTE
)) {
101 WARN(midi
, "error reading wDevID=%04X\n", wDevID
);
102 return MCIERR_INTERNAL
;
105 return MMSYSERR_NOTENABLED
;
110 /**************************************************************************
111 * MIDI_ReadWord [internal]
113 static DWORD
MIDI_ReadWord(UINT16 wDevID
, LPWORD lpw
)
117 if (MIDI_ReadByte(wDevID
, &hibyte
) == 0) {
118 if (MIDI_ReadByte(wDevID
, &lobyte
) == 0) {
119 *lpw
= ((WORD
)hibyte
<< 8) + lobyte
;
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
)
136 if (MIDI_ReadWord(wDevID
, &hiword
) == 0) {
137 if (MIDI_ReadWord(wDevID
, &loword
) == 0) {
138 *lpdw
= MAKELONG(loword
, hiword
);
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
)
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);
170 TRACE(midi, "val=%08lX \n", value);
176 /**************************************************************************
177 * MIDI_ReadMThd [internal]
179 static DWORD
MIDI_ReadMThd(UINT16 wDevID
, DWORD dwOffset
)
181 #if defined(linux) || defined(__FreeBSD__)
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 ();
211 return MMSYSERR_NOTENABLED
;
216 static DWORD
MIDI_ReadMTrk(UINT16 wDevID
, DWORD dwOffset
)
218 #if defined(linux) || defined(__FreeBSD__)
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
;
236 return MMSYSERR_NOTENABLED
;
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
;
250 LPSTR lpstrElementName
;
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
;
263 return MCIERR_MUST_USE_SHAREABLE
;
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
);
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
;
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;
296 if (MCIMidiDev
[wDevID
].hFile
!= 0) {
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
,
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
,
329 dwRet
= modMessage(wDevID
, MODM_OPEN
, 0, (DWORD
)&MidiDesc
, CALLBACK_NULL
);
330 /* dwRet = midMessage(wDevID, MIDM_OPEN, 0, (DWORD)&MidiDesc, CALLBACK_NULL);*/
334 return MMSYSERR_NOTENABLED
;
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
);
351 return MCIERR_INTERNAL
;
356 /**************************************************************************
357 * MIDI_mciClose [internal]
359 static DWORD
MIDI_mciClose(UINT16 wDevID
, DWORD dwParam
, LPMCI_GENERIC_PARMS lpParms
)
361 #if defined(linux) || defined(__FreeBSD__)
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;
391 /**************************************************************************
392 * MIDI_mciPlay [internal]
394 static DWORD
MIDI_mciPlay(UINT16 wDevID
, DWORD dwFlags
, LPMCI_PLAY_PARMS lpParms
)
396 #if defined(linux) || defined(__FreeBSD__)
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
) {
415 TRACE(midi
, "MCI_TO=%d \n", end
);
418 if (dwFlags
& MCI_NOTIFY
) {
419 TRACE(midi
, "MCI_NOTIFY %08lX !\n", lpParms
->dwCallback
);
422 WARN(midi
, "Can't 'fork' process !\n");
425 TRACE(midi
, "process started ! play in background ...\n");
428 TRACE(midi
, "process started ! return to caller...\n");
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
) {
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
;
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
);
503 return MMSYSERR_NOTENABLED
;
508 /**************************************************************************
509 * MIDI_mciRecord [internal]
511 static DWORD
MIDI_mciRecord(UINT16 wDevID
, DWORD dwFlags
, LPMCI_RECORD_PARMS lpParms
)
513 #if defined(linux) || defined(__FreeBSD__)
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
) {
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
);
565 return MMSYSERR_NOTENABLED
;
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
;
580 return MCIERR_INTERNAL
;
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
;
595 return MCIERR_INTERNAL
;
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");
615 case MCI_FORMAT_BYTES
:
616 TRACE(midi
, "MCI_FORMAT_BYTES !\n");
618 case MCI_FORMAT_SAMPLES
:
619 TRACE(midi
, "MCI_FORMAT_SAMPLES !\n");
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");
652 return MCIERR_INTERNAL
;
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;
670 case MCI_STATUS_LENGTH
:
671 lpParms
->dwReturn
= 5555;
672 if (dwFlags
& MCI_TRACK
) {
673 lpParms
->dwTrack
= 1;
674 lpParms
->dwReturn
= 2222;
677 case MCI_STATUS_MODE
:
678 lpParms
->dwReturn
= MCI_MODE_STOP
;
680 case MCI_STATUS_MEDIA_PRESENT
:
681 TRACE(midi
, "MCI_STATUS_MEDIA_PRESENT !\n");
682 lpParms
->dwReturn
= TRUE
;
684 case MCI_STATUS_NUMBER_OF_TRACKS
:
685 lpParms
->dwReturn
= 1;
687 case MCI_STATUS_POSITION
:
688 lpParms
->dwReturn
= 3333;
689 if (dwFlags
& MCI_STATUS_START
)
691 if (dwFlags
& MCI_TRACK
) {
692 lpParms
->dwTrack
= 1;
693 lpParms
->dwReturn
= 777;
696 case MCI_STATUS_READY
:
697 TRACE(midi
, "MCI_STATUS_READY !\n");
698 lpParms
->dwReturn
= TRUE
;
700 case MCI_STATUS_TIME_FORMAT
:
701 TRACE(midi
, "MCI_STATUS_TIME_FORMAT !\n");
702 lpParms
->dwReturn
= MCI_FORMAT_MILLISECONDS
;
704 case MCI_SEQ_STATUS_DIVTYPE
:
705 TRACE(midi
, "MCI_SEQ_STATUS_DIVTYPE !\n");
706 lpParms
->dwReturn
= 0;
708 case MCI_SEQ_STATUS_MASTER
:
709 TRACE(midi
, "MCI_SEQ_STATUS_MASTER !\n");
710 lpParms
->dwReturn
= 0;
712 case MCI_SEQ_STATUS_SLAVE
:
713 TRACE(midi
, "MCI_SEQ_STATUS_SLAVE !\n");
714 lpParms
->dwReturn
= 0;
716 case MCI_SEQ_STATUS_OFFSET
:
717 TRACE(midi
, "MCI_SEQ_STATUS_OFFSET !\n");
718 lpParms
->dwReturn
= 0;
720 case MCI_SEQ_STATUS_PORT
:
721 TRACE(midi
, "MCI_SEQ_STATUS_PORT !\n");
722 lpParms
->dwReturn
= 0;
724 case MCI_SEQ_STATUS_TEMPO
:
725 TRACE(midi
, "MCI_SEQ_STATUS_TEMPO !\n");
726 lpParms
->dwReturn
= 0;
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
);
740 return MCIERR_INTERNAL
;
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
;
758 case MCI_GETDEVCAPS_HAS_AUDIO
:
759 lpParms
->dwReturn
= TRUE
;
761 case MCI_GETDEVCAPS_HAS_VIDEO
:
762 lpParms
->dwReturn
= FALSE
;
764 case MCI_GETDEVCAPS_DEVICE_TYPE
:
765 lpParms
->dwReturn
= MCI_DEVTYPE_SEQUENCER
;
767 case MCI_GETDEVCAPS_USES_FILES
:
768 lpParms
->dwReturn
= TRUE
;
770 case MCI_GETDEVCAPS_COMPOUND_DEVICE
:
771 lpParms
->dwReturn
= TRUE
;
773 case MCI_GETDEVCAPS_CAN_EJECT
:
774 lpParms
->dwReturn
= FALSE
;
776 case MCI_GETDEVCAPS_CAN_PLAY
:
777 lpParms
->dwReturn
= TRUE
;
779 case MCI_GETDEVCAPS_CAN_SAVE
:
780 lpParms
->dwReturn
= FALSE
;
783 return MCIERR_UNRECOGNIZED_COMMAND
;
788 return MCIERR_INTERNAL
;
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
;
803 case MCI_INFO_PRODUCT
:
804 lpParms
->lpstrReturn
= "Linux Sound System 0.5";
807 lpParms
->lpstrReturn
= "FileName";
810 return MCIERR_UNRECOGNIZED_COMMAND
;
812 if (lpParms
->lpstrReturn
!= NULL
)
813 lpParms
->dwRetSize
= strlen(lpParms
->lpstrReturn
);
815 lpParms
->dwRetSize
= 0;
818 return MCIERR_INTERNAL
;
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 /**************************************************************************
843 static DWORD
midOpen(WORD wDevID
, LPMIDIOPENDESC lpDesc
, DWORD dwFlags
)
845 #if defined(linux) || defined(__FreeBSD__)
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);
859 WARN(midi
,"can't open !\n");
860 return MMSYSERR_NOTENABLED
;
862 MidiInDev
[wDevID
].wFlags
= HIWORD(dwFlags
& CALLBACK_TYPEMASK
);
863 switch(MidiInDev
[wDevID
].wFlags
) {
865 TRACE(midi
,"CALLBACK_NULL !\n");
868 TRACE(midi
, "CALLBACK_WINDOW !\n");
871 TRACE(midi
, "CALLBACK_TASK !\n");
874 TRACE(midi
, "CALLBACK_FUNCTION !\n");
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
;
887 return MMSYSERR_NOTENABLED
;
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
;
911 return MMSYSERR_NOTENABLED
;
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 /**************************************************************************
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
);
982 return midOpen(wDevID
,(LPMIDIOPENDESC
)dwParam1
, dwParam2
);
984 return midClose(wDevID
);
986 return midAddBuffer(wDevID
,(LPMIDIHDR
)dwParam1
, dwParam2
);
988 return midPrepare(wDevID
,(LPMIDIHDR
)dwParam1
, dwParam2
);
990 return midUnprepare(wDevID
,(LPMIDIHDR
)dwParam1
, dwParam2
);
991 case MIDM_GETDEVCAPS
:
992 return midGetDevCaps(wDevID
,(LPMIDIINCAPS16
)dwParam1
,dwParam2
);
993 case MIDM_GETNUMDEVS
:
996 return midReset(wDevID
);
998 return midStart(wDevID
);
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 ? */
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__)
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);
1061 WARN(midi
, "can't open !\n");
1062 return MMSYSERR_NOTENABLED
;
1064 MidiOutDev
[wDevID
].wFlags
= HIWORD(dwFlags
& CALLBACK_TYPEMASK
);
1065 switch(MidiOutDev
[wDevID
].wFlags
) {
1067 TRACE(midi
,"CALLBACK_NULL !\n");
1070 TRACE(midi
, "CALLBACK_WINDOW !\n");
1073 TRACE(midi
, "CALLBACK_TASK !\n");
1076 TRACE(midi
, "CALLBACK_FUNCTION !\n");
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
;
1090 return MMSYSERR_NOTENABLED
;
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
;
1115 return MMSYSERR_NOTENABLED
;
1119 /**************************************************************************
1120 * modData [internal]
1122 static DWORD
modData(WORD wDevID
, DWORD dwParam
)
1124 #if defined(linux) || defined(__FreeBSD__)
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
;
1139 return MMSYSERR_NOTENABLED
;
1143 /**************************************************************************
1144 * modLongData [internal]
1146 static DWORD
modLongData(WORD wDevID
, LPMIDIHDR lpMidiHdr
, DWORD dwSize
)
1148 #if defined(linux) || defined(__FreeBSD__)
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;
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
;
1195 return MMSYSERR_NOTENABLED
;
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
;
1221 return MMSYSERR_NOTENABLED
;
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
;
1238 return MMSYSERR_NOTENABLED
;
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
);
1262 return modOpen(wDevID
, (LPMIDIOPENDESC
)dwParam1
, dwParam2
);
1264 return modClose(wDevID
);
1266 return modData(wDevID
, dwParam1
);
1268 return modLongData(wDevID
, (LPMIDIHDR
)dwParam1
, dwParam2
);
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
:
1279 case MODM_SETVOLUME
:
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__)
1308 case DRV_QUERYCONFIGURE
:
1311 MessageBox16(0, "Sample Midi Linux Driver !",
1312 "MMLinux Driver", MB_OK
);
1315 return DRVCNF_RESTART
;
1317 return DRVCNF_RESTART
;
1318 case MCI_OPEN_DRIVER
:
1320 return MIDI_mciOpen(dwDevID
, dwParam1
, (LPMCI_OPEN_PARMS16
)PTR_SEG_TO_LIN(dwParam2
));
1321 case MCI_CLOSE_DRIVER
:
1323 return MIDI_mciClose(dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1325 return MIDI_mciPlay(dwDevID
, dwParam1
, (LPMCI_PLAY_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1327 return MIDI_mciRecord(dwDevID
, dwParam1
, (LPMCI_RECORD_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1329 return MIDI_mciStop(dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1331 return MIDI_mciSet(dwDevID
, dwParam1
, (LPMCI_SET_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1333 return MIDI_mciPause(dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1335 return MIDI_mciResume(dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
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
));
1341 return MIDI_mciInfo(dwDevID
, dwParam1
, (LPMCI_INFO_PARMS16
)PTR_SEG_TO_LIN(dwParam2
));
1343 return DefDriverProc(dwDevID
, hDriv
, wMsg
, dwParam1
, dwParam2
);
1346 return MMSYSERR_NOTENABLED
;
1351 /*-----------------------------------------------------------------------*/