Release 980628
[wine/multimedia.git] / multimedia / midi.c
blobabcccb5a14b06b3ef80b11cc9e429c134b83f293
1 /*
2 * Sample MIDI Wine Driver for Linux
4 * Copyright 1994 Martin Ayotte
5 */
7 #include <errno.h>
8 #include <string.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <unistd.h>
12 #include <fcntl.h>
13 #include "windows.h"
14 #include "ldt.h"
15 #include "multimedia.h"
16 #include "user.h"
17 #include "driver.h"
18 #include "mmsystem.h"
19 #include "xmalloc.h"
20 #include "debug.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 */
27 int MODM_NUMDEVS = 0;
29 /* this structure holds pointers with information for each MIDI
30 * device found.
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);
42 switch (wMsg) {
43 case MOM_OPEN:
44 case MOM_CLOSE:
45 case MOM_DONE:
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,
52 wMsg,
53 MidiOutDev[wDevID].midiDesc.dwInstance,
54 dwParam1,
55 dwParam2)) {
56 WARN(midi,"can't notify client !\n");
57 return MMSYSERR_NOERROR;
59 break;
61 case MIM_OPEN:
62 case MIM_CLOSE:
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;
72 break;
74 return 0;
78 /**************************************************************************
79 * MIDI_ReadByte [internal]
81 static DWORD MIDI_ReadByte(UINT16 wDevID, BYTE *lpbyt)
83 if (lpbyt != NULL) {
84 if (mmioRead32(MCIMidiDev[wDevID].hFile, (HPSTR)lpbyt,
85 (long) sizeof(BYTE)) == (long) sizeof(BYTE)) {
86 return 0;
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)
100 BYTE hibyte, lobyte;
101 if (lpw != NULL) {
102 if (MIDI_ReadByte(wDevID, &hibyte) == 0) {
103 if (MIDI_ReadByte(wDevID, &lobyte) == 0) {
104 *lpw = ((WORD)hibyte << 8) + lobyte;
105 return 0;
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)
119 WORD hiword, loword;
120 if (lpdw != NULL) {
121 if (MIDI_ReadWord(wDevID, &hiword) == 0) {
122 if (MIDI_ReadWord(wDevID, &loword) == 0) {
123 *lpdw = MAKELONG(loword, hiword);
124 return 0;
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)
138 BYTE byte;
139 DWORD value;
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);
153 *lpdw = value;
155 TRACE(midi, "val=%08lX \n", value);
157 return 0;
161 /**************************************************************************
162 * MIDI_ReadMThd [internal]
164 static DWORD MIDI_ReadMThd(UINT16 wDevID, DWORD dwOffset)
166 DWORD toberead;
167 FOURCC fourcc;
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 ();
193 return 0;
197 static DWORD MIDI_ReadMTrk(UINT16 wDevID, DWORD dwOffset)
199 DWORD toberead;
200 FOURCC fourcc;
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;
214 return 0;
218 /**************************************************************************
219 * MIDI_mciOpen [internal]
221 static DWORD MIDI_mciOpen(UINT16 wDevID, DWORD dwFlags, LPMCI_OPEN_PARMS16 lpParms)
223 MIDIOPENDESC MidiDesc;
224 DWORD dwRet;
225 DWORD dwOffset;
226 LPSTR lpstrElementName;
227 char str[128];
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;
238 else
239 return MCIERR_MUST_USE_SHAREABLE;
240 } else {
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);
255 CharUpper32A(str);
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;
262 } else
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;
271 MidiDesc.hMidi = 0;
272 if (MCIMidiDev[wDevID].hFile != 0) {
273 MMCKINFO ckMainRIFF;
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,
279 ckMainRIFF.cksize);
280 dwOffset = 0;
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,
302 ckMainRIFF.cksize);
305 dwRet = modMessage(wDevID, MODM_OPEN, 0, (DWORD)&MidiDesc, CALLBACK_NULL);
306 /* dwRet = midMessage(wDevID, MIDM_OPEN, 0, (DWORD)&MidiDesc, CALLBACK_NULL);*/
308 return 0;
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);
321 return 0;
325 /**************************************************************************
326 * MIDI_mciClose [internal]
328 static DWORD MIDI_mciClose(UINT16 wDevID, DWORD dwParam, LPMCI_GENERIC_PARMS lpParms)
330 DWORD dwRet;
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;
352 return 0;
356 /**************************************************************************
357 * MIDI_mciPlay [internal]
359 static DWORD MIDI_mciPlay(UINT16 wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms)
361 int count,start,end;
362 LPMIDIHDR lpMidiHdr;
363 DWORD dwData,dwRet;
364 LPWORD ptr;
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) {
378 end = lpParms->dwTo;
379 TRACE(midi, "MCI_TO=%d \n", end);
381 #if 0
382 if (dwFlags & MCI_NOTIFY) {
383 TRACE(midi, "MCI_NOTIFY %08lX !\n", lpParms->dwCallback);
384 switch(fork()) {
385 case -1:
386 WARN(midi, "Can't 'fork' process !\n");
387 break;
388 case 0:
389 TRACE(midi, "process started ! play in background ...\n");
390 break;
391 default:
392 TRACE(midi, "process started ! return to caller...\n");
393 return 0;
396 #endif
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) {
430 switch (dwRet) {
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;
446 default:
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);
462 return 0;
466 /**************************************************************************
467 * MIDI_mciRecord [internal]
469 static DWORD MIDI_mciRecord(UINT16 wDevID, DWORD dwFlags, LPMCI_RECORD_PARMS lpParms)
471 int start, end;
472 LPMIDIHDR lpMidiHdr;
473 DWORD dwRet;
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) {
487 end = lpParms->dwTo;
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);
520 return 0;
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;
531 return 0;
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;
542 return 0;
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");
559 break;
560 case MCI_FORMAT_BYTES:
561 TRACE(midi, "MCI_FORMAT_BYTES !\n");
562 break;
563 case MCI_FORMAT_SAMPLES:
564 TRACE(midi, "MCI_FORMAT_SAMPLES !\n");
565 break;
566 default:
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");
595 return 0;
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;
610 break;
611 case MCI_STATUS_LENGTH:
612 lpParms->dwReturn = 5555;
613 if (dwFlags & MCI_TRACK) {
614 lpParms->dwTrack = 1;
615 lpParms->dwReturn = 2222;
617 break;
618 case MCI_STATUS_MODE:
619 lpParms->dwReturn = MCI_MODE_STOP;
620 break;
621 case MCI_STATUS_MEDIA_PRESENT:
622 TRACE(midi, "MCI_STATUS_MEDIA_PRESENT !\n");
623 lpParms->dwReturn = TRUE;
624 break;
625 case MCI_STATUS_NUMBER_OF_TRACKS:
626 lpParms->dwReturn = 1;
627 break;
628 case MCI_STATUS_POSITION:
629 lpParms->dwReturn = 3333;
630 if (dwFlags & MCI_STATUS_START)
631 lpParms->dwItem = 1;
632 if (dwFlags & MCI_TRACK) {
633 lpParms->dwTrack = 1;
634 lpParms->dwReturn = 777;
636 break;
637 case MCI_STATUS_READY:
638 TRACE(midi, "MCI_STATUS_READY !\n");
639 lpParms->dwReturn = TRUE;
640 break;
641 case MCI_STATUS_TIME_FORMAT:
642 TRACE(midi, "MCI_STATUS_TIME_FORMAT !\n");
643 lpParms->dwReturn = MCI_FORMAT_MILLISECONDS;
644 break;
645 case MCI_SEQ_STATUS_DIVTYPE:
646 TRACE(midi, "MCI_SEQ_STATUS_DIVTYPE !\n");
647 lpParms->dwReturn = 0;
648 break;
649 case MCI_SEQ_STATUS_MASTER:
650 TRACE(midi, "MCI_SEQ_STATUS_MASTER !\n");
651 lpParms->dwReturn = 0;
652 break;
653 case MCI_SEQ_STATUS_SLAVE:
654 TRACE(midi, "MCI_SEQ_STATUS_SLAVE !\n");
655 lpParms->dwReturn = 0;
656 break;
657 case MCI_SEQ_STATUS_OFFSET:
658 TRACE(midi, "MCI_SEQ_STATUS_OFFSET !\n");
659 lpParms->dwReturn = 0;
660 break;
661 case MCI_SEQ_STATUS_PORT:
662 TRACE(midi, "MCI_SEQ_STATUS_PORT !\n");
663 lpParms->dwReturn = 0;
664 break;
665 case MCI_SEQ_STATUS_TEMPO:
666 TRACE(midi, "MCI_SEQ_STATUS_TEMPO !\n");
667 lpParms->dwReturn = 0;
668 break;
669 default:
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);
679 return 0;
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;
694 break;
695 case MCI_GETDEVCAPS_HAS_AUDIO:
696 lpParms->dwReturn = TRUE;
697 break;
698 case MCI_GETDEVCAPS_HAS_VIDEO:
699 lpParms->dwReturn = FALSE;
700 break;
701 case MCI_GETDEVCAPS_DEVICE_TYPE:
702 lpParms->dwReturn = MCI_DEVTYPE_SEQUENCER;
703 break;
704 case MCI_GETDEVCAPS_USES_FILES:
705 lpParms->dwReturn = TRUE;
706 break;
707 case MCI_GETDEVCAPS_COMPOUND_DEVICE:
708 lpParms->dwReturn = TRUE;
709 break;
710 case MCI_GETDEVCAPS_CAN_EJECT:
711 lpParms->dwReturn = FALSE;
712 break;
713 case MCI_GETDEVCAPS_CAN_PLAY:
714 lpParms->dwReturn = TRUE;
715 break;
716 case MCI_GETDEVCAPS_CAN_SAVE:
717 lpParms->dwReturn = FALSE;
718 break;
719 default:
720 return MCIERR_UNRECOGNIZED_COMMAND;
723 return 0;
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;
735 switch(dwFlags) {
736 case MCI_INFO_PRODUCT:
737 lpParms->lpstrReturn = "Linux Sound System 0.5";
738 break;
739 case MCI_INFO_FILE:
740 lpParms->lpstrReturn = "FileName";
741 break;
742 default:
743 return MCIERR_UNRECOGNIZED_COMMAND;
745 if (lpParms->lpstrReturn != NULL)
746 lpParms->dwRetSize = strlen(lpParms->lpstrReturn);
747 else
748 lpParms->dwRetSize = 0;
749 return 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 /**************************************************************************
771 * midOpen [internal]
773 static DWORD midOpen(WORD wDevID, LPMIDIOPENDESC lpDesc, DWORD dwFlags)
775 int midi;
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);
787 if (midi == -1) {
788 WARN(midi,"can't open !\n");
789 return MMSYSERR_NOTENABLED;
791 MidiInDev[wDevID].wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
792 switch(MidiInDev[wDevID].wFlags) {
793 case DCB_NULL:
794 TRACE(midi,"CALLBACK_NULL !\n");
795 break;
796 case DCB_WINDOW:
797 TRACE(midi, "CALLBACK_WINDOW !\n");
798 break;
799 case DCB_TASK:
800 TRACE(midi, "CALLBACK_TASK !\n");
801 break;
802 case DCB_FUNCTION:
803 TRACE(midi, "CALLBACK_FUNCTION !\n");
804 break;
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 /**************************************************************************
885 * midStop [internal]
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);
902 switch(wMsg) {
903 case MIDM_OPEN:
904 return midOpen(wDevID,(LPMIDIOPENDESC)dwParam1, dwParam2);
905 case MIDM_CLOSE:
906 return midClose(wDevID);
907 case MIDM_ADDBUFFER:
908 return midAddBuffer(wDevID,(LPMIDIHDR)dwParam1, dwParam2);
909 case MIDM_PREPARE:
910 return midPrepare(wDevID,(LPMIDIHDR)dwParam1, dwParam2);
911 case MIDM_UNPREPARE:
912 return midUnprepare(wDevID,(LPMIDIHDR)dwParam1, dwParam2);
913 case MIDM_GETDEVCAPS:
914 return midGetDevCaps(wDevID,(LPMIDIINCAPS16)dwParam1,dwParam2);
915 case MIDM_GETNUMDEVS:
916 return 0;
917 case MIDM_RESET:
918 return midReset(wDevID);
919 case MIDM_START:
920 return midStart(wDevID);
921 case MIDM_STOP:
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 ? */
946 } else {
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 /**************************************************************************
964 * modOpen [internal]
966 static DWORD modOpen(WORD wDevID, LPMIDIOPENDESC lpDesc, DWORD dwFlags)
968 int midi;
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);
981 if (midi == -1) {
982 WARN(midi, "can't open !\n");
983 return MMSYSERR_NOTENABLED;
985 MidiOutDev[wDevID].wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
986 switch(MidiOutDev[wDevID].wFlags) {
987 case DCB_NULL:
988 TRACE(midi,"CALLBACK_NULL !\n");
989 break;
990 case DCB_WINDOW:
991 TRACE(midi, "CALLBACK_WINDOW !\n");
992 break;
993 case DCB_TASK:
994 TRACE(midi, "CALLBACK_TASK !\n");
995 break;
996 case DCB_FUNCTION:
997 TRACE(midi, "CALLBACK_FUNCTION !\n");
998 break;
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)
1038 WORD event;
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)
1058 int count;
1059 LPWORD ptr;
1060 int en;
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;
1084 ptr++;
1087 en = errno;
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);
1158 switch(wMsg) {
1159 case MODM_OPEN:
1160 return modOpen(wDevID, (LPMIDIOPENDESC)dwParam1, dwParam2);
1161 case MODM_CLOSE:
1162 return modClose(wDevID);
1163 case MODM_DATA:
1164 return modData(wDevID, dwParam1);
1165 case MODM_LONGDATA:
1166 return modLongData(wDevID, (LPMIDIHDR)dwParam1, dwParam2);
1167 case MODM_PREPARE:
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:
1176 return 0;
1177 case MODM_SETVOLUME:
1178 return 0;
1179 case MODM_RESET:
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)
1192 switch(wMsg) {
1193 case DRV_LOAD:
1194 return 1;
1195 case DRV_FREE:
1196 return 1;
1197 case DRV_OPEN:
1198 return 1;
1199 case DRV_CLOSE:
1200 return 1;
1201 case DRV_ENABLE:
1202 return 1;
1203 case DRV_DISABLE:
1204 return 1;
1205 case DRV_QUERYCONFIGURE:
1206 return 1;
1207 case DRV_CONFIGURE:
1208 MessageBox16(0, "Sample Midi Linux Driver !",
1209 "MMLinux Driver", MB_OK);
1210 return 1;
1211 case DRV_INSTALL:
1212 return DRVCNF_RESTART;
1213 case DRV_REMOVE:
1214 return DRVCNF_RESTART;
1215 case MCI_OPEN_DRIVER:
1216 case MCI_OPEN:
1217 return MIDI_mciOpen(dwDevID, dwParam1, (LPMCI_OPEN_PARMS16)PTR_SEG_TO_LIN(dwParam2));
1218 case MCI_CLOSE_DRIVER:
1219 case MCI_CLOSE:
1220 return MIDI_mciClose(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)PTR_SEG_TO_LIN(dwParam2));
1221 case MCI_PLAY:
1222 return MIDI_mciPlay(dwDevID, dwParam1, (LPMCI_PLAY_PARMS)PTR_SEG_TO_LIN(dwParam2));
1223 case MCI_RECORD:
1224 return MIDI_mciRecord(dwDevID, dwParam1, (LPMCI_RECORD_PARMS)PTR_SEG_TO_LIN(dwParam2));
1225 case MCI_STOP:
1226 return MIDI_mciStop(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)PTR_SEG_TO_LIN(dwParam2));
1227 case MCI_SET:
1228 return MIDI_mciSet(dwDevID, dwParam1, (LPMCI_SET_PARMS)PTR_SEG_TO_LIN(dwParam2));
1229 case MCI_PAUSE:
1230 return MIDI_mciPause(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)PTR_SEG_TO_LIN(dwParam2));
1231 case MCI_RESUME:
1232 return MIDI_mciResume(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)PTR_SEG_TO_LIN(dwParam2));
1233 case MCI_STATUS:
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));
1237 case MCI_INFO:
1238 return MIDI_mciInfo(dwDevID, dwParam1, (LPMCI_INFO_PARMS16)PTR_SEG_TO_LIN(dwParam2));
1239 default:
1240 return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);
1243 /*-----------------------------------------------------------------------*/