2 * Sample MIDI Wine Driver for Linux
4 * Copyright 1994 Martin Ayotte
15 #include "multimedia.h"
22 static LINUX_MIDIIN MidiInDev
[MAX_MIDIINDRV
];
23 static LINUX_MIDIOUT MidiOutDev
[MAX_MIDIOUTDRV
];
24 static LINUX_MCIMIDI MCIMidiDev
[MAX_MCIMIDIDRV
];
26 /* this is the total number of MIDI devices found */
29 /* this structure holds pointers with information for each MIDI
32 LPMIDIOUTCAPS16 midiDevices
[MAX_MIDIOUTDRV
];
34 /**************************************************************************
35 * MIDI_NotifyClient [internal]
37 static DWORD
MIDI_NotifyClient(UINT16 wDevID
, WORD wMsg
,
38 DWORD dwParam1
, DWORD dwParam2
)
40 TRACE(midi
,"wDevID = %04X wMsg = %d dwParm1 = %04lX dwParam2 = %04lX\n",wDevID
, wMsg
, dwParam1
, dwParam2
);
46 if (wDevID
> MAX_MIDIOUTDRV
) return MCIERR_INTERNAL
;
48 if (MidiOutDev
[wDevID
].wFlags
!= DCB_NULL
&& !DriverCallback(
49 MidiOutDev
[wDevID
].midiDesc
.dwCallback
,
50 MidiOutDev
[wDevID
].wFlags
,
51 MidiOutDev
[wDevID
].midiDesc
.hMidi
,
53 MidiOutDev
[wDevID
].midiDesc
.dwInstance
,
56 WARN(midi
,"can't notify client !\n");
57 return MMSYSERR_NOERROR
;
63 if (wDevID
> MAX_MIDIINDRV
) return MCIERR_INTERNAL
;
65 if (MidiInDev
[wDevID
].wFlags
!= DCB_NULL
&& !DriverCallback(
66 MidiInDev
[wDevID
].midiDesc
.dwCallback
, MidiInDev
[wDevID
].wFlags
,
67 MidiInDev
[wDevID
].midiDesc
.hMidi
, wMsg
,
68 MidiInDev
[wDevID
].midiDesc
.dwInstance
, dwParam1
, dwParam2
)) {
69 WARN(mciwave
,"can't notify client !\n");
70 return MMSYSERR_NOERROR
;
78 /**************************************************************************
79 * MIDI_ReadByte [internal]
81 static DWORD
MIDI_ReadByte(UINT16 wDevID
, BYTE
*lpbyt
)
84 if (mmioRead32(MCIMidiDev
[wDevID
].hFile
, (HPSTR
)lpbyt
,
85 (long) sizeof(BYTE
)) == (long) sizeof(BYTE
)) {
89 WARN(midi
, "error reading wDevID=%04X\n", wDevID
);
90 return MCIERR_INTERNAL
;
95 /**************************************************************************
96 * MIDI_ReadWord [internal]
98 static DWORD
MIDI_ReadWord(UINT16 wDevID
, LPWORD lpw
)
102 if (MIDI_ReadByte(wDevID
, &hibyte
) == 0) {
103 if (MIDI_ReadByte(wDevID
, &lobyte
) == 0) {
104 *lpw
= ((WORD
)hibyte
<< 8) + lobyte
;
109 WARN(midi
, "error reading wDevID=%04X\n", wDevID
);
110 return MCIERR_INTERNAL
;
114 /**************************************************************************
115 * MIDI_ReadLong [internal]
117 static DWORD
MIDI_ReadLong(UINT16 wDevID
, LPDWORD lpdw
)
121 if (MIDI_ReadWord(wDevID
, &hiword
) == 0) {
122 if (MIDI_ReadWord(wDevID
, &loword
) == 0) {
123 *lpdw
= MAKELONG(loword
, hiword
);
128 WARN(midi
, "error reading wDevID=%04X\n", wDevID
);
129 return MCIERR_INTERNAL
;
133 /**************************************************************************
134 * MIDI_ReadVaryLen [internal]
136 static DWORD
MIDI_ReadVaryLen(UINT16 wDevID
, LPDWORD lpdw
)
140 if (lpdw
== NULL
) return MCIERR_INTERNAL
;
141 if (MIDI_ReadByte(wDevID
, &byte
) != 0) {
142 WARN(midi
, "error reading wDevID=%04X\n", wDevID
);
143 return MCIERR_INTERNAL
;
145 value
= (DWORD
)(byte
& 0x7F);
146 while (byte
& 0x80) {
147 if (MIDI_ReadByte(wDevID
, &byte
) != 0) {
148 WARN(midi
, "error reading wDevID=%04X\n", wDevID
);
149 return MCIERR_INTERNAL
;
151 value
= (value
<< 7) + (byte
& 0x7F);
155 TRACE(midi, "val=%08lX \n", value);
161 /**************************************************************************
162 * MIDI_ReadMThd [internal]
164 static DWORD
MIDI_ReadMThd(UINT16 wDevID
, DWORD dwOffset
)
168 TRACE(midi
, "(%04X, %08lX);\n", wDevID
, dwOffset
);
169 if (mmioSeek32(MCIMidiDev
[wDevID
].hFile
, dwOffset
, SEEK_SET
) != dwOffset
) {
170 WARN(midi
, "can't seek at %08lX begin of 'MThd' \n", dwOffset
);
171 return MCIERR_INTERNAL
;
173 if (mmioRead32(MCIMidiDev
[wDevID
].hFile
, (HPSTR
)&fourcc
,
174 (long) sizeof(FOURCC
)) != (long) sizeof(FOURCC
))
175 return MCIERR_INTERNAL
;
176 if (MIDI_ReadLong(wDevID
, &toberead
) != 0)
177 return MCIERR_INTERNAL
;
178 if (MIDI_ReadWord(wDevID
, &MCIMidiDev
[wDevID
].wFormat
) != 0)
179 return MCIERR_INTERNAL
;
180 if (MIDI_ReadWord(wDevID
, &MCIMidiDev
[wDevID
].nTracks
) != 0)
181 return MCIERR_INTERNAL
;
182 if (MIDI_ReadWord(wDevID
, &MCIMidiDev
[wDevID
].nTempo
) != 0)
183 return MCIERR_INTERNAL
;
184 TRACE(midi
, "toberead=%08lX, wFormat=%04X nTracks=%04X nTempo=%04X\n",
185 toberead
, MCIMidiDev
[wDevID
].wFormat
,
186 MCIMidiDev
[wDevID
].nTracks
,
187 MCIMidiDev
[wDevID
].nTempo
);
188 toberead
-= 3 * sizeof(WORD
);
190 ntrks = read16bit ();
191 Mf_division = division = read16bit ();
197 static DWORD
MIDI_ReadMTrk(UINT16 wDevID
, DWORD dwOffset
)
201 if (mmioSeek32(MCIMidiDev
[wDevID
].hFile
, dwOffset
, SEEK_SET
) != dwOffset
) {
202 WARN(midi
, "can't seek at %08lX begin of 'MThd' \n", dwOffset
);
204 if (mmioRead32(MCIMidiDev
[wDevID
].hFile
, (HPSTR
)&fourcc
,
205 (long) sizeof(FOURCC
)) != (long) sizeof(FOURCC
)) {
206 return MCIERR_INTERNAL
;
208 if (MIDI_ReadLong(wDevID
, &toberead
) != 0) {
209 return MCIERR_INTERNAL
;
211 TRACE(midi
, "toberead=%08lX\n", toberead
);
212 toberead
-= 3 * sizeof(WORD
);
213 MCIMidiDev
[wDevID
].dwTotalLen
= toberead
;
218 /**************************************************************************
219 * MIDI_mciOpen [internal]
221 static DWORD
MIDI_mciOpen(UINT16 wDevID
, DWORD dwFlags
, LPMCI_OPEN_PARMS16 lpParms
)
223 MIDIOPENDESC MidiDesc
;
226 LPSTR lpstrElementName
;
229 TRACE(midi
, "(%08lX, %p)\n", dwFlags
, lpParms
);
230 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
232 if (MCIMidiDev
[wDevID
].nUseCount
> 0) {
233 /* The driver already open on this channel */
234 /* If the driver was opened shareable before and this open specifies */
235 /* shareable then increment the use count */
236 if (MCIMidiDev
[wDevID
].fShareable
&& (dwFlags
& MCI_OPEN_SHAREABLE
))
237 ++MCIMidiDev
[wDevID
].nUseCount
;
239 return MCIERR_MUST_USE_SHAREABLE
;
241 MCIMidiDev
[wDevID
].nUseCount
= 1;
242 MCIMidiDev
[wDevID
].fShareable
= dwFlags
& MCI_OPEN_SHAREABLE
;
243 MCIMidiDev
[wDevID
].hMidiHdr
= USER_HEAP_ALLOC(sizeof(MIDIHDR
));
246 TRACE(midi
, "wDevID=%04X\n", wDevID
);
247 /* lpParms->wDeviceID = wDevID;*/
248 TRACE(midi
, "lpParms->wDevID=%04X\n", lpParms
->wDeviceID
);
249 TRACE(midi
, "before OPEN_ELEMENT\n");
250 if (dwFlags
& MCI_OPEN_ELEMENT
) {
251 lpstrElementName
= (LPSTR
)PTR_SEG_TO_LIN(lpParms
->lpstrElementName
);
252 TRACE(midi
, "MCI_OPEN_ELEMENT '%s' !\n", lpstrElementName
);
253 if (strlen(lpstrElementName
) > 0) {
254 strcpy(str
, lpstrElementName
);
256 MCIMidiDev
[wDevID
].hFile
= mmioOpen16(str
, NULL
,
257 MMIO_ALLOCBUF
| MMIO_READWRITE
| MMIO_EXCLUSIVE
);
258 if (MCIMidiDev
[wDevID
].hFile
== 0) {
259 WARN(midi
, "can't find file='%s' !\n", str
);
260 return MCIERR_FILE_NOT_FOUND
;
263 MCIMidiDev
[wDevID
].hFile
= 0;
265 TRACE(midi
, "hFile=%u\n", MCIMidiDev
[wDevID
].hFile
);
266 memcpy(&MCIMidiDev
[wDevID
].openParms
, lpParms
, sizeof(MCI_OPEN_PARMS16
));
267 MCIMidiDev
[wDevID
].wNotifyDeviceID
= lpParms
->wDeviceID
;
268 MCIMidiDev
[wDevID
].dwStatus
= MCI_MODE_STOP
;
269 MCIMidiDev
[wDevID
].dwBeginData
= 0;
270 MCIMidiDev
[wDevID
].dwTotalLen
= 0;
272 if (MCIMidiDev
[wDevID
].hFile
!= 0) {
274 if (mmioDescend(MCIMidiDev
[wDevID
].hFile
, &ckMainRIFF
, NULL
, 0) != 0) {
275 return MCIERR_INTERNAL
;
277 TRACE(midi
,"ParentChunk ckid=%.4s fccType=%.4s cksize=%08lX \n",
278 (LPSTR
)&ckMainRIFF
.ckid
, (LPSTR
)&ckMainRIFF
.fccType
,
281 if (ckMainRIFF
.ckid
== mmioFOURCC('R', 'M', 'I', 'D')) {
282 TRACE(midi
, "is a 'RMID' file \n");
283 dwOffset
= ckMainRIFF
.dwDataOffset
;
285 if (ckMainRIFF
.ckid
!= mmioFOURCC('M', 'T', 'h', 'd')) {
286 WARN(midi
, "unknown format !\n");
287 return MCIERR_INTERNAL
;
289 if (MIDI_ReadMThd(wDevID
, dwOffset
) != 0) {
290 WARN(midi
, "can't read 'MThd' header \n");
291 return MCIERR_INTERNAL
;
293 dwOffset
= mmioSeek32(MCIMidiDev
[wDevID
].hFile
, 0, SEEK_CUR
);
294 if (MIDI_ReadMTrk(wDevID
, dwOffset
) != 0) {
295 WARN(midi
, "can't read 'MTrk' header \n");
296 return MCIERR_INTERNAL
;
298 dwOffset
= mmioSeek32(MCIMidiDev
[wDevID
].hFile
, 0, SEEK_CUR
);
299 MCIMidiDev
[wDevID
].dwBeginData
= dwOffset
;
300 TRACE(midi
, "Chunk Found ckid=%.4s fccType=%.4s cksize=%08lX \n",
301 (LPSTR
)&ckMainRIFF
.ckid
, (LPSTR
)&ckMainRIFF
.fccType
,
305 dwRet
= modMessage(wDevID
, MODM_OPEN
, 0, (DWORD
)&MidiDesc
, CALLBACK_NULL
);
306 /* dwRet = midMessage(wDevID, MIDM_OPEN, 0, (DWORD)&MidiDesc, CALLBACK_NULL);*/
311 /**************************************************************************
312 * MIDI_mciStop [internal]
314 static DWORD
MIDI_mciStop(UINT16 wDevID
, DWORD dwFlags
, LPMCI_GENERIC_PARMS lpParms
)
316 TRACE(midi
, "(%04X, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
317 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
318 MCIMidiDev
[wDevID
].dwStatus
= MCI_MODE_STOP
;
319 TRACE(midi
, "MCIMidiDev[wDevID].dwStatus=%p %d\n",
320 &MCIMidiDev
[wDevID
].dwStatus
, MCIMidiDev
[wDevID
].dwStatus
);
325 /**************************************************************************
326 * MIDI_mciClose [internal]
328 static DWORD
MIDI_mciClose(UINT16 wDevID
, DWORD dwParam
, LPMCI_GENERIC_PARMS lpParms
)
332 TRACE(midi
, "(%04X, %08lX, %p);\n", wDevID
, dwParam
, lpParms
);
333 if (MCIMidiDev
[wDevID
].dwStatus
!= MCI_MODE_STOP
) {
334 MIDI_mciStop(wDevID
, MCI_WAIT
, lpParms
);
336 MCIMidiDev
[wDevID
].dwStatus
= MCI_MODE_STOP
;
337 MCIMidiDev
[wDevID
].nUseCount
--;
338 if (MCIMidiDev
[wDevID
].nUseCount
== 0) {
339 if (MCIMidiDev
[wDevID
].hFile
!= 0) {
340 mmioClose32(MCIMidiDev
[wDevID
].hFile
, 0);
341 MCIMidiDev
[wDevID
].hFile
= 0;
342 TRACE(midi
, "hFile closed !\n");
344 USER_HEAP_FREE(MCIMidiDev
[wDevID
].hMidiHdr
);
345 dwRet
= modMessage(wDevID
, MODM_CLOSE
, 0, 0L, 0L);
346 if (dwRet
!= MMSYSERR_NOERROR
) return MCIERR_INTERNAL
;
348 dwRet = midMessage(wDevID, MIDM_CLOSE, 0, 0L, 0L);
349 if (dwRet != MMSYSERR_NOERROR) return MCIERR_INTERNAL;
356 /**************************************************************************
357 * MIDI_mciPlay [internal]
359 static DWORD
MIDI_mciPlay(UINT16 wDevID
, DWORD dwFlags
, LPMCI_PLAY_PARMS lpParms
)
366 TRACE(midi
, "(%04X, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
367 if (MCIMidiDev
[wDevID
].hFile
== 0) {
368 WARN(midi
, "can't find file='%08lx' !\n",
369 (DWORD
)MCIMidiDev
[wDevID
].openParms
.lpstrElementName
);
370 return MCIERR_FILE_NOT_FOUND
;
372 start
= 1; end
= 99999;
373 if (dwFlags
& MCI_FROM
) {
374 start
= lpParms
->dwFrom
;
375 TRACE(midi
, "MCI_FROM=%d \n", start
);
377 if (dwFlags
& MCI_TO
) {
379 TRACE(midi
, "MCI_TO=%d \n", end
);
382 if (dwFlags
& MCI_NOTIFY
) {
383 TRACE(midi
, "MCI_NOTIFY %08lX !\n", lpParms
->dwCallback
);
386 WARN(midi
, "Can't 'fork' process !\n");
389 TRACE(midi
, "process started ! play in background ...\n");
392 TRACE(midi
, "process started ! return to caller...\n");
398 lpMidiHdr
= USER_HEAP_LIN_ADDR(MCIMidiDev
[wDevID
].hMidiHdr
);
400 lpMidiHdr
->lpData
= (LPSTR
)xmalloc(1200);
401 if (lpMidiHdr
->lpData
== NULL
) return MCIERR_INTERNAL
;
402 lpMidiHdr
->dwBufferLength
= 1024;
403 lpMidiHdr
->dwUser
= 0L;
404 lpMidiHdr
->dwFlags
= 0L;
405 dwRet
= modMessage(wDevID
, MODM_PREPARE
, 0, (DWORD
)lpMidiHdr
, sizeof(MIDIHDR
));
407 /* TRACE(midi, "after MODM_PREPARE \n"); */
409 MCIMidiDev
[wDevID
].dwStatus
= MCI_MODE_PLAY
;
410 while(MCIMidiDev
[wDevID
].dwStatus
!= MCI_MODE_STOP
) {
411 TRACE(midi
, "MCIMidiDev[wDevID].dwStatus=%p %d\n",
412 &MCIMidiDev
[wDevID
].dwStatus
, MCIMidiDev
[wDevID
].dwStatus
);
414 ptr
= (LPWORD
)lpMidiHdr
->lpData
;
415 for (count
= 0; count
< lpMidiHdr
->dwBufferLength
; count
++) {
416 if (MIDI_ReadVaryLen(wDevID
, &dwData
) != 0) break;
417 *ptr
= LOWORD(dwData
);
420 count = mmioRead32(MCIMidiDev[wDevID].hFile, lpMidiHdr->lpData, lpMidiHdr->dwBufferLength);
422 TRACE(midi
, "after read count = %d\n",count
);
424 if (count
< 1) break;
425 lpMidiHdr
->dwBytesRecorded
= count
;
426 TRACE(midi
, "before MODM_LONGDATA lpMidiHdr=%p dwBytesRecorded=%lu\n",
427 lpMidiHdr
, lpMidiHdr
->dwBytesRecorded
);
428 dwRet
= modMessage(wDevID
, MODM_LONGDATA
, 0, (DWORD
)lpMidiHdr
, sizeof(MIDIHDR
));
429 if (dwRet
!= MMSYSERR_NOERROR
) {
431 case MMSYSERR_NOTENABLED
:
432 return MCIERR_DEVICE_NOT_READY
;
434 case MIDIERR_NODEVICE
:
435 return MCIERR_INVALID_DEVICE_ID
;
437 case MIDIERR_UNPREPARED
:
438 return MCIERR_DRIVER_INTERNAL
;
440 case MIDIERR_STILLPLAYING
:
441 return MCIERR_SEQ_PORT_INUSE
;
443 case MMSYSERR_INVALPARAM
:
444 return MCIERR_CANNOT_LOAD_DRIVER
;
447 return MCIERR_DRIVER
;
451 dwRet
= modMessage(wDevID
, MODM_UNPREPARE
, 0, (DWORD
)lpMidiHdr
, sizeof(MIDIHDR
));
452 if (lpMidiHdr
->lpData
!= NULL
) {
453 free(lpMidiHdr
->lpData
);
454 lpMidiHdr
->lpData
= NULL
;
456 MCIMidiDev
[wDevID
].dwStatus
= MCI_MODE_STOP
;
457 if (dwFlags
& MCI_NOTIFY
) {
458 TRACE(midi
, "MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms
->dwCallback
);
459 mciDriverNotify((HWND16
)LOWORD(lpParms
->dwCallback
),
460 MCIMidiDev
[wDevID
].wNotifyDeviceID
, MCI_NOTIFY_SUCCESSFUL
);
466 /**************************************************************************
467 * MIDI_mciRecord [internal]
469 static DWORD
MIDI_mciRecord(UINT16 wDevID
, DWORD dwFlags
, LPMCI_RECORD_PARMS lpParms
)
475 TRACE(midi
, "(%04X, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
476 if (MCIMidiDev
[wDevID
].hFile
== 0) {
477 WARN(midi
, "can't find file='%08lx' !\n",
478 (DWORD
)MCIMidiDev
[wDevID
].openParms
.lpstrElementName
);
479 return MCIERR_FILE_NOT_FOUND
;
481 start
= 1; end
= 99999;
482 if (dwFlags
& MCI_FROM
) {
483 start
= lpParms
->dwFrom
;
484 TRACE(midi
, "MCI_FROM=%d \n", start
);
486 if (dwFlags
& MCI_TO
) {
488 TRACE(midi
, "MCI_TO=%d \n", end
);
490 lpMidiHdr
= USER_HEAP_LIN_ADDR(MCIMidiDev
[wDevID
].hMidiHdr
);
491 lpMidiHdr
->lpData
= (LPSTR
) xmalloc(1200);
492 lpMidiHdr
->dwBufferLength
= 1024;
493 lpMidiHdr
->dwUser
= 0L;
494 lpMidiHdr
->dwFlags
= 0L;
495 dwRet
= midMessage(wDevID
, MIDM_PREPARE
, 0, (DWORD
)lpMidiHdr
, sizeof(MIDIHDR
));
496 TRACE(midi
, "after MIDM_PREPARE \n");
497 MCIMidiDev
[wDevID
].dwStatus
= MCI_MODE_RECORD
;
498 while(MCIMidiDev
[wDevID
].dwStatus
!= MCI_MODE_STOP
) {
499 TRACE(midi
, "MCIMidiDev[wDevID].dwStatus=%p %d\n",
500 &MCIMidiDev
[wDevID
].dwStatus
, MCIMidiDev
[wDevID
].dwStatus
);
501 lpMidiHdr
->dwBytesRecorded
= 0;
502 dwRet
= midMessage(wDevID
, MIDM_START
, 0, 0L, 0L);
503 TRACE(midi
, "after MIDM_START lpMidiHdr=%p dwBytesRecorded=%lu\n",
504 lpMidiHdr
, lpMidiHdr
->dwBytesRecorded
);
505 if (lpMidiHdr
->dwBytesRecorded
== 0) break;
507 TRACE(midi
, "before MIDM_UNPREPARE \n");
508 dwRet
= midMessage(wDevID
, MIDM_UNPREPARE
, 0, (DWORD
)lpMidiHdr
, sizeof(MIDIHDR
));
509 TRACE(midi
, "after MIDM_UNPREPARE \n");
510 if (lpMidiHdr
->lpData
!= NULL
) {
511 free(lpMidiHdr
->lpData
);
512 lpMidiHdr
->lpData
= NULL
;
514 MCIMidiDev
[wDevID
].dwStatus
= MCI_MODE_STOP
;
515 if (dwFlags
& MCI_NOTIFY
) {
516 TRACE(midi
, "MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms
->dwCallback
);
517 mciDriverNotify((HWND16
)LOWORD(lpParms
->dwCallback
),
518 MCIMidiDev
[wDevID
].wNotifyDeviceID
, MCI_NOTIFY_SUCCESSFUL
);
524 /**************************************************************************
525 * MIDI_mciPause [internal]
527 static DWORD
MIDI_mciPause(UINT16 wDevID
, DWORD dwFlags
, LPMCI_GENERIC_PARMS lpParms
)
529 TRACE(midi
, "(%04X, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
530 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
535 /**************************************************************************
536 * MIDI_mciResume [internal]
538 static DWORD
MIDI_mciResume(UINT16 wDevID
, DWORD dwFlags
, LPMCI_GENERIC_PARMS lpParms
)
540 TRACE(midi
, "(%04X, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
541 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
546 /**************************************************************************
547 * MIDI_mciSet [internal]
549 static DWORD
MIDI_mciSet(UINT16 wDevID
, DWORD dwFlags
, LPMCI_SET_PARMS lpParms
)
551 TRACE(midi
, "(%04X, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
552 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
553 TRACE(midi
, "dwTimeFormat=%08lX\n", lpParms
->dwTimeFormat
);
554 TRACE(midi
, "dwAudio=%08lX\n", lpParms
->dwAudio
);
555 if (dwFlags
& MCI_SET_TIME_FORMAT
) {
556 switch (lpParms
->dwTimeFormat
) {
557 case MCI_FORMAT_MILLISECONDS
:
558 TRACE(midi
, "MCI_FORMAT_MILLISECONDS !\n");
560 case MCI_FORMAT_BYTES
:
561 TRACE(midi
, "MCI_FORMAT_BYTES !\n");
563 case MCI_FORMAT_SAMPLES
:
564 TRACE(midi
, "MCI_FORMAT_SAMPLES !\n");
567 WARN(midi
, "bad time format !\n");
568 return MCIERR_BAD_TIME_FORMAT
;
571 if (dwFlags
& MCI_SET_VIDEO
) return MCIERR_UNSUPPORTED_FUNCTION
;
572 if (dwFlags
& MCI_SET_DOOR_OPEN
) return MCIERR_UNSUPPORTED_FUNCTION
;
573 if (dwFlags
& MCI_SET_DOOR_CLOSED
) return MCIERR_UNSUPPORTED_FUNCTION
;
574 if (dwFlags
& MCI_SET_AUDIO
)
575 TRACE(midi
, "MCI_SET_AUDIO !\n");
576 if (dwFlags
&& MCI_SET_ON
) {
577 TRACE(midi
, "MCI_SET_ON !\n");
578 if (dwFlags
&& MCI_SET_AUDIO_LEFT
)
579 TRACE(midi
, "MCI_SET_AUDIO_LEFT !\n");
580 if (dwFlags
&& MCI_SET_AUDIO_RIGHT
)
581 TRACE(midi
, "MCI_SET_AUDIO_RIGHT !\n");
583 if (dwFlags
& MCI_SET_OFF
)
584 TRACE(midi
, "MCI_SET_OFF !\n");
585 if (dwFlags
& MCI_SEQ_SET_MASTER
)
586 TRACE(midi
, "MCI_SEQ_SET_MASTER !\n");
587 if (dwFlags
& MCI_SEQ_SET_SLAVE
)
588 TRACE(midi
, "MCI_SEQ_SET_SLAVE !\n");
589 if (dwFlags
& MCI_SEQ_SET_OFFSET
)
590 TRACE(midi
, "MCI_SEQ_SET_OFFSET !\n");
591 if (dwFlags
& MCI_SEQ_SET_PORT
)
592 TRACE(midi
, "MCI_SEQ_SET_PORT !\n");
593 if (dwFlags
& MCI_SEQ_SET_TEMPO
)
594 TRACE(midi
, "MCI_SEQ_SET_TEMPO !\n");
599 /**************************************************************************
600 * MIDI_mciStatus [internal]
602 static DWORD
MIDI_mciStatus(UINT16 wDevID
, DWORD dwFlags
, LPMCI_STATUS_PARMS lpParms
)
604 TRACE(midi
, "(%04X, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
605 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
606 if (dwFlags
& MCI_STATUS_ITEM
) {
607 switch(lpParms
->dwItem
) {
608 case MCI_STATUS_CURRENT_TRACK
:
609 lpParms
->dwReturn
= 1;
611 case MCI_STATUS_LENGTH
:
612 lpParms
->dwReturn
= 5555;
613 if (dwFlags
& MCI_TRACK
) {
614 lpParms
->dwTrack
= 1;
615 lpParms
->dwReturn
= 2222;
618 case MCI_STATUS_MODE
:
619 lpParms
->dwReturn
= MCI_MODE_STOP
;
621 case MCI_STATUS_MEDIA_PRESENT
:
622 TRACE(midi
, "MCI_STATUS_MEDIA_PRESENT !\n");
623 lpParms
->dwReturn
= TRUE
;
625 case MCI_STATUS_NUMBER_OF_TRACKS
:
626 lpParms
->dwReturn
= 1;
628 case MCI_STATUS_POSITION
:
629 lpParms
->dwReturn
= 3333;
630 if (dwFlags
& MCI_STATUS_START
)
632 if (dwFlags
& MCI_TRACK
) {
633 lpParms
->dwTrack
= 1;
634 lpParms
->dwReturn
= 777;
637 case MCI_STATUS_READY
:
638 TRACE(midi
, "MCI_STATUS_READY !\n");
639 lpParms
->dwReturn
= TRUE
;
641 case MCI_STATUS_TIME_FORMAT
:
642 TRACE(midi
, "MCI_STATUS_TIME_FORMAT !\n");
643 lpParms
->dwReturn
= MCI_FORMAT_MILLISECONDS
;
645 case MCI_SEQ_STATUS_DIVTYPE
:
646 TRACE(midi
, "MCI_SEQ_STATUS_DIVTYPE !\n");
647 lpParms
->dwReturn
= 0;
649 case MCI_SEQ_STATUS_MASTER
:
650 TRACE(midi
, "MCI_SEQ_STATUS_MASTER !\n");
651 lpParms
->dwReturn
= 0;
653 case MCI_SEQ_STATUS_SLAVE
:
654 TRACE(midi
, "MCI_SEQ_STATUS_SLAVE !\n");
655 lpParms
->dwReturn
= 0;
657 case MCI_SEQ_STATUS_OFFSET
:
658 TRACE(midi
, "MCI_SEQ_STATUS_OFFSET !\n");
659 lpParms
->dwReturn
= 0;
661 case MCI_SEQ_STATUS_PORT
:
662 TRACE(midi
, "MCI_SEQ_STATUS_PORT !\n");
663 lpParms
->dwReturn
= 0;
665 case MCI_SEQ_STATUS_TEMPO
:
666 TRACE(midi
, "MCI_SEQ_STATUS_TEMPO !\n");
667 lpParms
->dwReturn
= 0;
670 WARN(midi
, "unknowm command %08lX !\n", lpParms
->dwItem
);
671 return MCIERR_UNRECOGNIZED_COMMAND
;
674 if (dwFlags
& MCI_NOTIFY
) {
675 TRACE(midi
, "MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms
->dwCallback
);
676 mciDriverNotify((HWND16
)LOWORD(lpParms
->dwCallback
),
677 MCIMidiDev
[wDevID
].wNotifyDeviceID
, MCI_NOTIFY_SUCCESSFUL
);
682 /**************************************************************************
683 * MIDI_mciGetDevCaps [internal]
685 static DWORD
MIDI_mciGetDevCaps(UINT16 wDevID
, DWORD dwFlags
,
686 LPMCI_GETDEVCAPS_PARMS lpParms
)
688 TRACE(midi
, "(%04X, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
689 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
690 if (dwFlags
& MCI_GETDEVCAPS_ITEM
) {
691 switch(lpParms
->dwItem
) {
692 case MCI_GETDEVCAPS_CAN_RECORD
:
693 lpParms
->dwReturn
= TRUE
;
695 case MCI_GETDEVCAPS_HAS_AUDIO
:
696 lpParms
->dwReturn
= TRUE
;
698 case MCI_GETDEVCAPS_HAS_VIDEO
:
699 lpParms
->dwReturn
= FALSE
;
701 case MCI_GETDEVCAPS_DEVICE_TYPE
:
702 lpParms
->dwReturn
= MCI_DEVTYPE_SEQUENCER
;
704 case MCI_GETDEVCAPS_USES_FILES
:
705 lpParms
->dwReturn
= TRUE
;
707 case MCI_GETDEVCAPS_COMPOUND_DEVICE
:
708 lpParms
->dwReturn
= TRUE
;
710 case MCI_GETDEVCAPS_CAN_EJECT
:
711 lpParms
->dwReturn
= FALSE
;
713 case MCI_GETDEVCAPS_CAN_PLAY
:
714 lpParms
->dwReturn
= TRUE
;
716 case MCI_GETDEVCAPS_CAN_SAVE
:
717 lpParms
->dwReturn
= FALSE
;
720 return MCIERR_UNRECOGNIZED_COMMAND
;
727 /**************************************************************************
728 * MIDI_mciInfo [internal]
730 static DWORD
MIDI_mciInfo(UINT16 wDevID
, DWORD dwFlags
, LPMCI_INFO_PARMS16 lpParms
)
732 TRACE(midi
, "(%04X, %08lX, %p);\n", wDevID
, dwFlags
, lpParms
);
733 if (lpParms
== NULL
) return MCIERR_INTERNAL
;
734 lpParms
->lpstrReturn
= NULL
;
736 case MCI_INFO_PRODUCT
:
737 lpParms
->lpstrReturn
= "Linux Sound System 0.5";
740 lpParms
->lpstrReturn
= "FileName";
743 return MCIERR_UNRECOGNIZED_COMMAND
;
745 if (lpParms
->lpstrReturn
!= NULL
)
746 lpParms
->dwRetSize
= strlen(lpParms
->lpstrReturn
);
748 lpParms
->dwRetSize
= 0;
753 /*-----------------------------------------------------------------------*/
756 /**************************************************************************
757 * midGetDevCaps [internal]
759 static DWORD
midGetDevCaps(WORD wDevID
, LPMIDIINCAPS16 lpCaps
, DWORD dwSize
)
761 TRACE(midi
, "(%04X, %p, %08lX);\n", wDevID
, lpCaps
, dwSize
);
762 lpCaps
->wMid
= 0x00FF; /* Manufac ID */
763 lpCaps
->wPid
= 0x0001; /* Product ID */
764 lpCaps
->vDriverVersion
= 0x001; /* Product Version */
765 strcpy(lpCaps
->szPname
, "Linux MIDIIN Driver");
767 return MMSYSERR_NOERROR
;
770 /**************************************************************************
773 static DWORD
midOpen(WORD wDevID
, LPMIDIOPENDESC lpDesc
, DWORD dwFlags
)
776 TRACE(midi
, "(%04X, %p, %08lX);\n", wDevID
, lpDesc
, dwFlags
);
777 if (lpDesc
== NULL
) {
778 WARN(midi
, "Invalid Parameter !\n");
779 return MMSYSERR_INVALPARAM
;
781 if (wDevID
>= MAX_MIDIINDRV
) {
782 TRACE(midi
,"MAX_MIDIINDRV reached !\n");
783 return MMSYSERR_ALLOCATED
;
785 MidiInDev
[wDevID
].unixdev
= 0;
786 midi
= open (MIDI_DEV
, O_RDONLY
, 0);
788 WARN(midi
,"can't open !\n");
789 return MMSYSERR_NOTENABLED
;
791 MidiInDev
[wDevID
].wFlags
= HIWORD(dwFlags
& CALLBACK_TYPEMASK
);
792 switch(MidiInDev
[wDevID
].wFlags
) {
794 TRACE(midi
,"CALLBACK_NULL !\n");
797 TRACE(midi
, "CALLBACK_WINDOW !\n");
800 TRACE(midi
, "CALLBACK_TASK !\n");
803 TRACE(midi
, "CALLBACK_FUNCTION !\n");
806 MidiInDev
[wDevID
].lpQueueHdr
= NULL
;
807 MidiInDev
[wDevID
].unixdev
= midi
;
808 MidiInDev
[wDevID
].dwTotalPlayed
= 0;
809 MidiInDev
[wDevID
].bufsize
= 0x3FFF;
810 if (MIDI_NotifyClient(wDevID
, MIM_OPEN
, 0L, 0L) != MMSYSERR_NOERROR
) {
811 WARN(midi
,"can't notify client !\n");
812 return MMSYSERR_INVALPARAM
;
814 return MMSYSERR_NOERROR
;
817 /**************************************************************************
818 * midClose [internal]
820 static DWORD
midClose(WORD wDevID
)
822 TRACE(midi
, "(%04X);\n", wDevID
);
823 if (MidiInDev
[wDevID
].unixdev
== 0) {
824 WARN(midi
,"can't close !\n");
825 return MMSYSERR_NOTENABLED
;
827 close(MidiInDev
[wDevID
].unixdev
);
828 MidiInDev
[wDevID
].unixdev
= 0;
829 MidiInDev
[wDevID
].bufsize
= 0;
830 if (MIDI_NotifyClient(wDevID
, MIM_CLOSE
, 0L, 0L) != MMSYSERR_NOERROR
) {
831 WARN(midi
,"can't notify client !\n");
832 return MMSYSERR_INVALPARAM
;
834 return MMSYSERR_NOERROR
;
837 /**************************************************************************
838 * midAddBuffer [internal]
840 static DWORD
midAddBuffer(WORD wDevID
, LPMIDIHDR lpMidiHdr
, DWORD dwSize
)
842 TRACE(midi
, "(%04X, %p, %08lX);\n", wDevID
, lpMidiHdr
, dwSize
);
843 return MMSYSERR_NOTENABLED
;
846 /**************************************************************************
847 * midPrepare [internal]
849 static DWORD
midPrepare(WORD wDevID
, LPMIDIHDR lpMidiHdr
, DWORD dwSize
)
851 TRACE(midi
, "(%04X, %p, %08lX);\n", wDevID
, lpMidiHdr
, dwSize
);
852 return MMSYSERR_NOTENABLED
;
855 /**************************************************************************
856 * midUnprepare [internal]
858 static DWORD
midUnprepare(WORD wDevID
, LPMIDIHDR lpMidiHdr
, DWORD dwSize
)
860 TRACE(midi
, "(%04X, %p, %08lX);\n", wDevID
, lpMidiHdr
, dwSize
);
861 return MMSYSERR_NOTENABLED
;
864 /**************************************************************************
865 * midReset [internal]
867 static DWORD
midReset(WORD wDevID
)
869 TRACE(midi
, "(%04X);\n", wDevID
);
870 return MMSYSERR_NOTENABLED
;
874 /**************************************************************************
875 * midStart [internal]
877 static DWORD
midStart(WORD wDevID
)
879 TRACE(midi
, "(%04X);\n", wDevID
);
880 return MMSYSERR_NOTENABLED
;
884 /**************************************************************************
887 static DWORD
midStop(WORD wDevID
)
889 TRACE(midi
, "(%04X);\n", wDevID
);
890 return MMSYSERR_NOTENABLED
;
894 /**************************************************************************
895 * midMessage [sample driver]
897 DWORD
midMessage(WORD wDevID
, WORD wMsg
, DWORD dwUser
,
898 DWORD dwParam1
, DWORD dwParam2
)
900 TRACE(midi
, "(%04X, %04X, %08lX, %08lX, %08lX);\n",
901 wDevID
, wMsg
, dwUser
, dwParam1
, dwParam2
);
904 return midOpen(wDevID
,(LPMIDIOPENDESC
)dwParam1
, dwParam2
);
906 return midClose(wDevID
);
908 return midAddBuffer(wDevID
,(LPMIDIHDR
)dwParam1
, dwParam2
);
910 return midPrepare(wDevID
,(LPMIDIHDR
)dwParam1
, dwParam2
);
912 return midUnprepare(wDevID
,(LPMIDIHDR
)dwParam1
, dwParam2
);
913 case MIDM_GETDEVCAPS
:
914 return midGetDevCaps(wDevID
,(LPMIDIINCAPS16
)dwParam1
,dwParam2
);
915 case MIDM_GETNUMDEVS
:
918 return midReset(wDevID
);
920 return midStart(wDevID
);
922 return midStop(wDevID
);
924 return MMSYSERR_NOTSUPPORTED
;
927 /*-----------------------------------------------------------------------*/
929 /**************************************************************************
930 * modGetDevCaps [internal]
932 static DWORD
modGetDevCaps(WORD wDevID
, LPMIDIOUTCAPS16 lpCaps
, DWORD dwSize
)
934 LPMIDIOUTCAPS16 tmplpCaps
;
936 TRACE(midi
, "(%04X, %p, %08lX);\n", wDevID
, lpCaps
, dwSize
);
937 if (wDevID
== (WORD
) MIDI_MAPPER
) {
938 lpCaps
->wMid
= 0x00FF; /* Manufac ID */
939 lpCaps
->wPid
= 0x0001; /* Product ID */
940 lpCaps
->vDriverVersion
= 0x001; /* Product Version */
941 strcpy(lpCaps
->szPname
, "MIDI Maper (not functional yet)");
942 lpCaps
->wTechnology
= MOD_FMSYNTH
; /* FIXME Does it make any difference ? */
943 lpCaps
->wVoices
= 14; /* FIXME */
944 lpCaps
->wNotes
= 14; /* FIXME */
945 lpCaps
->dwSupport
= MIDICAPS_VOLUME
|MIDICAPS_LRVOLUME
; /* FIXME Does it make any difference ? */
947 /* FIXME There is a way to do it so easily, but I'm too
948 * sleepy to think and I want to test
950 tmplpCaps
= midiDevices
[wDevID
];
951 lpCaps
->wMid
= tmplpCaps
->wMid
;
952 lpCaps
->wPid
= tmplpCaps
->wPid
;
953 lpCaps
->vDriverVersion
= tmplpCaps
->vDriverVersion
;
954 strcpy(lpCaps
->szPname
, tmplpCaps
->szPname
);
955 lpCaps
->wTechnology
= tmplpCaps
->wTechnology
;
956 lpCaps
->wVoices
= tmplpCaps
->wVoices
;
957 lpCaps
->wNotes
= tmplpCaps
->wNotes
;
958 lpCaps
->dwSupport
= tmplpCaps
->dwSupport
;
960 return MMSYSERR_NOERROR
;
963 /**************************************************************************
966 static DWORD
modOpen(WORD wDevID
, LPMIDIOPENDESC lpDesc
, DWORD dwFlags
)
970 TRACE(midi
, "(%04X, %p, %08lX);\n", wDevID
, lpDesc
, dwFlags
);
971 if (lpDesc
== NULL
) {
972 WARN(midi
, "Invalid Parameter !\n");
973 return MMSYSERR_INVALPARAM
;
975 if (wDevID
>= MAX_MIDIOUTDRV
) {
976 TRACE(midi
,"MAX_MIDIOUTDRV reached !\n");
977 return MMSYSERR_ALLOCATED
; /* FIXME isn't MMSYSERR_BADDEVICEID the right answer ? */
979 MidiOutDev
[wDevID
].unixdev
= 0;
980 midi
= open (MIDI_DEV
, O_WRONLY
, 0);
982 WARN(midi
, "can't open !\n");
983 return MMSYSERR_NOTENABLED
;
985 MidiOutDev
[wDevID
].wFlags
= HIWORD(dwFlags
& CALLBACK_TYPEMASK
);
986 switch(MidiOutDev
[wDevID
].wFlags
) {
988 TRACE(midi
,"CALLBACK_NULL !\n");
991 TRACE(midi
, "CALLBACK_WINDOW !\n");
994 TRACE(midi
, "CALLBACK_TASK !\n");
997 TRACE(midi
, "CALLBACK_FUNCTION !\n");
1000 MidiOutDev
[wDevID
].lpQueueHdr
= NULL
;
1001 MidiOutDev
[wDevID
].unixdev
= midi
;
1002 MidiOutDev
[wDevID
].dwTotalPlayed
= 0;
1003 MidiOutDev
[wDevID
].bufsize
= 0x3FFF;
1004 if (MIDI_NotifyClient(wDevID
, MOM_OPEN
, 0L, 0L) != MMSYSERR_NOERROR
) {
1005 WARN(midi
,"can't notify client !\n");
1006 return MMSYSERR_INVALPARAM
;
1008 TRACE(midi
, "Succesful unixdev=%d !\n", midi
);
1009 return MMSYSERR_NOERROR
;
1013 /**************************************************************************
1014 * modClose [internal]
1016 static DWORD
modClose(WORD wDevID
)
1018 TRACE(midi
, "(%04X);\n", wDevID
);
1019 if (MidiOutDev
[wDevID
].unixdev
== 0) {
1020 WARN(midi
,"can't close !\n");
1021 return MMSYSERR_NOTENABLED
;
1023 close(MidiOutDev
[wDevID
].unixdev
);
1024 MidiOutDev
[wDevID
].unixdev
= 0;
1025 MidiOutDev
[wDevID
].bufsize
= 0;
1026 if (MIDI_NotifyClient(wDevID
, MOM_CLOSE
, 0L, 0L) != MMSYSERR_NOERROR
) {
1027 WARN(midi
,"can't notify client !\n");
1028 return MMSYSERR_INVALPARAM
;
1030 return MMSYSERR_NOERROR
;
1033 /**************************************************************************
1034 * modData [internal]
1036 static DWORD
modData(WORD wDevID
, DWORD dwParam
)
1040 TRACE(midi
, "(%04X, %08lX);\n", wDevID
, dwParam
);
1041 if (MidiOutDev
[wDevID
].unixdev
== 0) {
1042 WARN(midi
,"can't play !\n");
1043 return MIDIERR_NODEVICE
;
1045 event
= LOWORD(dwParam
);
1046 if (write (MidiOutDev
[wDevID
].unixdev
,
1047 &event
, sizeof(WORD
)) != sizeof(WORD
)) {
1048 WARN(midi
, "error writting unixdev !\n");
1050 return MMSYSERR_NOTENABLED
;
1053 /**************************************************************************
1054 * modLongData [internal]
1056 static DWORD
modLongData(WORD wDevID
, LPMIDIHDR lpMidiHdr
, DWORD dwSize
)
1062 TRACE(midi
, "(%04X, %p, %08lX);\n", wDevID
, lpMidiHdr
, dwSize
);
1063 if (MidiOutDev
[wDevID
].unixdev
== 0) {
1064 WARN(midi
,"can't play !\n");
1065 return MIDIERR_NODEVICE
;
1067 if (lpMidiHdr
->lpData
== NULL
) return MIDIERR_UNPREPARED
;
1068 if (!(lpMidiHdr
->dwFlags
& MHDR_PREPARED
)) return MIDIERR_UNPREPARED
;
1069 if (lpMidiHdr
->dwFlags
& MHDR_INQUEUE
) return MIDIERR_STILLPLAYING
;
1070 lpMidiHdr
->dwFlags
&= ~MHDR_DONE
;
1071 lpMidiHdr
->dwFlags
|= MHDR_INQUEUE
;
1072 TRACE(midi
, "dwBytesRecorded %lu !\n", lpMidiHdr
->dwBytesRecorded
);
1073 TRACE(midi
, " %02X %02X %02X %02X\n",
1074 lpMidiHdr
->lpData
[0], lpMidiHdr
->lpData
[1],
1075 lpMidiHdr
->lpData
[2], lpMidiHdr
->lpData
[3]);
1077 count = write (MidiOutDev[wDevID].unixdev,
1078 lpMidiHdr->lpData, lpMidiHdr->dwBytesRecorded);
1080 ptr
= (LPWORD
)lpMidiHdr
->lpData
;
1081 for (count
= 0; count
< lpMidiHdr
->dwBytesRecorded
; count
++) {
1082 if (write (MidiOutDev
[wDevID
].unixdev
, ptr
,
1083 sizeof(WORD
)) != sizeof(WORD
)) break;
1088 TRACE(midi
, "after write count = %d\n",count
);
1089 if (count
!= lpMidiHdr
->dwBytesRecorded
) {
1090 WARN(midi
, "error writting unixdev #%d ! (%d != %ld)\n",
1091 MidiOutDev
[wDevID
].unixdev
, count
,
1092 lpMidiHdr
->dwBytesRecorded
);
1093 TRACE(midi
, "\terrno = %d error = %s\n",en
,strerror(en
));
1094 return MMSYSERR_NOTENABLED
;
1096 lpMidiHdr
->dwFlags
&= ~MHDR_INQUEUE
;
1097 lpMidiHdr
->dwFlags
|= MHDR_DONE
;
1098 if (MIDI_NotifyClient(wDevID
, MOM_DONE
, 0L, 0L) != MMSYSERR_NOERROR
) {
1099 WARN(midi
,"can't notify client !\n");
1100 return MMSYSERR_INVALPARAM
;
1102 return MMSYSERR_NOERROR
;
1105 /**************************************************************************
1106 * modPrepare [internal]
1108 static DWORD
modPrepare(WORD wDevID
, LPMIDIHDR lpMidiHdr
, DWORD dwSize
)
1110 TRACE(midi
, "(%04X, %p, %08lX);\n", wDevID
, lpMidiHdr
, dwSize
);
1111 if (MidiOutDev
[wDevID
].unixdev
== 0) {
1112 WARN(midi
,"can't prepare !\n");
1113 return MMSYSERR_NOTENABLED
;
1115 if (MidiOutDev
[wDevID
].lpQueueHdr
!= NULL
) {
1116 TRACE(midi
,"already prepare !\n");
1117 return MMSYSERR_NOTENABLED
;
1119 MidiOutDev
[wDevID
].dwTotalPlayed
= 0;
1120 MidiOutDev
[wDevID
].lpQueueHdr
= PTR_SEG_TO_LIN(lpMidiHdr
);
1121 if (lpMidiHdr
->dwFlags
& MHDR_INQUEUE
) return MIDIERR_STILLPLAYING
;
1122 lpMidiHdr
->dwFlags
|= MHDR_PREPARED
;
1123 lpMidiHdr
->dwFlags
&= ~MHDR_DONE
;
1124 return MMSYSERR_NOERROR
;
1127 /**************************************************************************
1128 * modUnprepare [internal]
1130 static DWORD
modUnprepare(WORD wDevID
, LPMIDIHDR lpMidiHdr
, DWORD dwSize
)
1132 TRACE(midi
, "(%04X, %p, %08lX);\n", wDevID
, lpMidiHdr
, dwSize
);
1133 if (MidiOutDev
[wDevID
].unixdev
== 0) {
1134 WARN(midi
,"can't unprepare !\n");
1135 return MMSYSERR_NOTENABLED
;
1137 return MMSYSERR_NOERROR
;
1140 /**************************************************************************
1141 * modReset [internal]
1143 static DWORD
modReset(WORD wDevID
)
1145 TRACE(midi
, "(%04X);\n", wDevID
);
1146 return MMSYSERR_NOTENABLED
;
1150 /**************************************************************************
1151 * modMessage [sample driver]
1153 DWORD
modMessage(WORD wDevID
, WORD wMsg
, DWORD dwUser
,
1154 DWORD dwParam1
, DWORD dwParam2
)
1156 TRACE(midi
, "(%04X, %04X, %08lX, %08lX, %08lX);\n",
1157 wDevID
, wMsg
, dwUser
, dwParam1
, dwParam2
);
1160 return modOpen(wDevID
, (LPMIDIOPENDESC
)dwParam1
, dwParam2
);
1162 return modClose(wDevID
);
1164 return modData(wDevID
, dwParam1
);
1166 return modLongData(wDevID
, (LPMIDIHDR
)dwParam1
, dwParam2
);
1168 return modPrepare(wDevID
, (LPMIDIHDR
)dwParam1
, dwParam2
);
1169 case MODM_UNPREPARE
:
1170 return modUnprepare(wDevID
, (LPMIDIHDR
)dwParam1
, dwParam2
);
1171 case MODM_GETDEVCAPS
:
1172 return modGetDevCaps(wDevID
,(LPMIDIOUTCAPS16
)dwParam1
,dwParam2
);
1173 case MODM_GETNUMDEVS
:
1174 return MODM_NUMDEVS
;
1175 case MODM_GETVOLUME
:
1177 case MODM_SETVOLUME
:
1180 return modReset(wDevID
);
1182 return MMSYSERR_NOTSUPPORTED
;
1186 /**************************************************************************
1187 * MIDI_DriverProc [sample driver]
1189 LONG
MIDI_DriverProc(DWORD dwDevID
, HDRVR16 hDriv
, WORD wMsg
,
1190 DWORD dwParam1
, DWORD dwParam2
)
1205 case DRV_QUERYCONFIGURE
:
1208 MessageBox16(0, "Sample Midi Linux Driver !",
1209 "MMLinux Driver", MB_OK
);
1212 return DRVCNF_RESTART
;
1214 return DRVCNF_RESTART
;
1215 case MCI_OPEN_DRIVER
:
1217 return MIDI_mciOpen(dwDevID
, dwParam1
, (LPMCI_OPEN_PARMS16
)PTR_SEG_TO_LIN(dwParam2
));
1218 case MCI_CLOSE_DRIVER
:
1220 return MIDI_mciClose(dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1222 return MIDI_mciPlay(dwDevID
, dwParam1
, (LPMCI_PLAY_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1224 return MIDI_mciRecord(dwDevID
, dwParam1
, (LPMCI_RECORD_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1226 return MIDI_mciStop(dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1228 return MIDI_mciSet(dwDevID
, dwParam1
, (LPMCI_SET_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1230 return MIDI_mciPause(dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1232 return MIDI_mciResume(dwDevID
, dwParam1
, (LPMCI_GENERIC_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1234 return MIDI_mciStatus(dwDevID
, dwParam1
, (LPMCI_STATUS_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1235 case MCI_GETDEVCAPS
:
1236 return MIDI_mciGetDevCaps(dwDevID
, dwParam1
, (LPMCI_GETDEVCAPS_PARMS
)PTR_SEG_TO_LIN(dwParam2
));
1238 return MIDI_mciInfo(dwDevID
, dwParam1
, (LPMCI_INFO_PARMS16
)PTR_SEG_TO_LIN(dwParam2
));
1240 return DefDriverProc(dwDevID
, hDriv
, wMsg
, dwParam1
, dwParam2
);
1243 /*-----------------------------------------------------------------------*/