Release 950727
[wine] / multimedia / midi.c
1 /*
2  * Sample MIDI Wine Driver for Linux
3  *
4  * Copyright 1994 Martin Ayotte
5  */
6
7 #ifndef WINELIB
8 #define BUILTIN_MMSYSTEM
9 #endif 
10
11 #ifdef BUILTIN_MMSYSTEM
12
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <unistd.h>
16 #include <fcntl.h>
17 #include <sys/ioctl.h>
18 #include "windows.h"
19 #include "ldt.h"
20 #include "driver.h"
21 #include "mmsystem.h"
22
23 #include "stddebug.h"
24 #include "debug.h"
25
26 #ifdef linux
27 #include <linux/soundcard.h>
28 #endif
29
30 #ifdef linux
31 #define MIDI_DEV "/dev/sequencer"
32
33 #ifdef SOUND_VERSION
34 #define IOCTL(a,b,c)            ioctl(a,b,&c)
35 #else
36 #define IOCTL(a,b,c)            (c = ioctl(a,b,c) )
37 #endif
38
39 #define MAX_MIDIINDRV   2
40 #define MAX_MIDIOUTDRV  2
41 #define MAX_MCIMIDIDRV  2
42
43 typedef struct {
44         int                             unixdev;
45         int                             state;
46         DWORD                   bufsize;
47         MIDIOPENDESC    midiDesc;
48         WORD                    wFlags;
49         LPMIDIHDR               lpQueueHdr;
50         DWORD                   dwTotalPlayed;
51         } LINUX_MIDIIN;
52
53 typedef struct {
54         int                             unixdev;
55         int                             state;
56         DWORD                   bufsize;
57         MIDIOPENDESC    midiDesc;
58         WORD                    wFlags;
59         LPMIDIHDR               lpQueueHdr;
60         DWORD                   dwTotalPlayed;
61         } LINUX_MIDIOUT;
62
63 typedef struct {
64         int     nUseCount;          /* Incremented for each shared open */
65         BOOL    fShareable;         /* TRUE if first open was shareable */
66         WORD    wNotifyDeviceID;    /* MCI device ID with a pending notification */
67         HANDLE  hCallback;          /* Callback handle for pending notification */
68         HMMIO   hFile;                          /* mmio file handle open as Element             */
69         DWORD   dwBeginData;
70         DWORD   dwTotalLen;
71         WORD    wFormat;
72         WORD    nTracks;
73         WORD    nTempo;
74         MCI_OPEN_PARMS openParms;
75         MIDIHDR         MidiHdr;
76         WORD            dwStatus;
77         } LINUX_MCIMIDI;
78
79 static LINUX_MIDIIN             MidiInDev[MAX_MIDIINDRV];
80 static LINUX_MIDIOUT    MidiOutDev[MAX_MIDIOUTDRV];
81 static LINUX_MCIMIDI    MCIMidiDev[MAX_MCIMIDIDRV];
82 #endif
83
84
85 /**************************************************************************
86 *                               MIDI_NotifyClient                       [internal]
87 */
88 static DWORD MIDI_NotifyClient(UINT wDevID, WORD wMsg, 
89                                 DWORD dwParam1, DWORD dwParam2)
90 {
91 #ifdef linux
92         if (MidiInDev[wDevID].wFlags != DCB_NULL && !DriverCallback(
93                 MidiInDev[wDevID].midiDesc.dwCallback, MidiInDev[wDevID].wFlags, 
94                 MidiInDev[wDevID].midiDesc.hMidi, wMsg, 
95                 MidiInDev[wDevID].midiDesc.dwInstance, dwParam1, dwParam2)) {
96                 dprintf_midi(stddeb, "MIDI_NotifyClient // can't notify client !\n");
97                 return MMSYSERR_NOERROR;
98                 }
99         return 0;
100 #else
101         return MMSYSERR_NOTENABLED;
102 #endif
103 }
104
105
106 /**************************************************************************
107 *                               MIDI_ReadByte                   [internal]      
108 */
109 static DWORD MIDI_ReadByte(UINT wDevID, BYTE FAR *lpbyt)
110 {
111 #ifdef linux
112         if (lpbyt != NULL) {
113                 if (mmioRead(MCIMidiDev[wDevID].hFile, (HPSTR)lpbyt,
114                         (long) sizeof(BYTE)) == (long) sizeof(BYTE)) {
115                         return 0;
116                         }
117                 }
118         dprintf_midi(stddeb, "MIDI_ReadByte // error reading wDevID=%d \n", wDevID);
119         return MCIERR_INTERNAL;
120
121 #else
122         return MMSYSERR_NOTENABLED;
123 #endif
124 }
125
126
127 /**************************************************************************
128 *                               MIDI_ReadWord                   [internal]      
129 */
130 static DWORD MIDI_ReadWord(UINT wDevID, LPWORD lpw)
131 {
132         BYTE    hibyte, lobyte;
133         if (lpw != NULL) {
134                 if (MIDI_ReadByte(wDevID, &hibyte) == 0) {
135                         if (MIDI_ReadByte(wDevID, &lobyte) == 0) {
136                                 *lpw = ((WORD)hibyte << 8) + lobyte;
137                                 return 0;
138                                 }
139                         }
140                 }
141         dprintf_midi(stddeb, "MIDI_ReadWord // error reading wDevID=%d \n", wDevID);
142         return MCIERR_INTERNAL;
143 }
144
145
146 /**************************************************************************
147 *                               MIDI_ReadLong                   [internal]      
148 */
149 static DWORD MIDI_ReadLong(UINT wDevID, LPDWORD lpdw)
150 {
151         WORD    hiword, loword;
152         if (lpdw != NULL) {
153                 if (MIDI_ReadWord(wDevID, &hiword) == 0) {
154                         if (MIDI_ReadWord(wDevID, &loword) == 0) {
155                                 *lpdw = MAKELONG(loword, hiword);
156                                 return 0;
157                                 }
158                         }
159                 }
160         dprintf_midi(stddeb, "MIDI_ReadLong // error reading wDevID=%d \n", wDevID);
161         return MCIERR_INTERNAL;
162 }
163
164
165 /**************************************************************************
166 *                               MIDI_ReadVaryLen                [internal]      
167 */
168 static DWORD MIDI_ReadVaryLen(UINT wDevID, LPDWORD lpdw)
169 {
170         BYTE    byte;
171         DWORD   value;
172         if (lpdw == NULL) return MCIERR_INTERNAL;
173         if (MIDI_ReadByte(wDevID, &byte) != 0) {
174                 dprintf_midi(stddeb, "MIDI_ReadVaryLen // error reading wDevID=%d \n", wDevID);
175                 return MCIERR_INTERNAL;
176                 }
177         value = (DWORD)(byte & 0x7F);
178         while (byte & 0x80) {
179                 if (MIDI_ReadByte(wDevID, &byte) != 0) {
180                         dprintf_midi(stddeb, "MIDI_ReadVaryLen // error reading wDevID=%d \n", wDevID);
181                         return MCIERR_INTERNAL;
182                         }
183                 value = (value << 7) + (byte & 0x7F);
184                 }
185         *lpdw = value;
186 /*
187         dprintf_midi(stddeb, "MIDI_ReadVaryLen // val=%08lX \n", value);
188 */
189         return 0;
190 }
191
192
193 /**************************************************************************
194 *                               MIDI_ReadMThd                   [internal]      
195 */
196 static DWORD MIDI_ReadMThd(UINT wDevID, DWORD dwOffset)
197 {
198 #ifdef linux
199         DWORD   toberead;
200         FOURCC  fourcc;
201         dprintf_midi(stddeb, "MIDI_ReadMThd(%04X, %08lX);\n", wDevID, dwOffset);
202         if (mmioSeek(MCIMidiDev[wDevID].hFile, dwOffset, SEEK_SET) != dwOffset) {
203                 dprintf_midi(stddeb, "MIDI_ReadMThd // can't seek at %08lX begin of 'MThd' \n", dwOffset);
204                 return MCIERR_INTERNAL;
205                 }
206         if (mmioRead(MCIMidiDev[wDevID].hFile, (HPSTR)&fourcc,
207                 (long) sizeof(FOURCC)) != (long) sizeof(FOURCC)) {
208                 return MCIERR_INTERNAL;
209                 }
210         if (MIDI_ReadLong(wDevID, &toberead) != 0) {
211                 return MCIERR_INTERNAL;
212                 }
213         if (MIDI_ReadWord(wDevID, &MCIMidiDev[wDevID].wFormat) != 0) {
214                 return MCIERR_INTERNAL;
215                 }
216         if (MIDI_ReadWord(wDevID, &MCIMidiDev[wDevID].nTracks) != 0) {
217                 return MCIERR_INTERNAL;
218                 }
219         if (MIDI_ReadWord(wDevID, &MCIMidiDev[wDevID].nTempo) != 0) {
220                 return MCIERR_INTERNAL;
221                 }
222         dprintf_midi(stddeb, "MIDI_ReadMThd // toberead=%08lX, wFormat=%04X nTracks=%04X nTempo=%04X\n",
223                 toberead, MCIMidiDev[wDevID].wFormat,
224                 MCIMidiDev[wDevID].nTracks,
225                 MCIMidiDev[wDevID].nTempo);
226         toberead -= 3 * sizeof(WORD);
227 /*
228                 ntrks = read16bit ();
229                 Mf_division = division = read16bit ();
230 */
231         return 0;
232
233 #else
234          return MMSYSERR_NOTENABLED;
235 #endif
236 }
237
238
239 static DWORD MIDI_ReadMTrk(UINT wDevID, DWORD dwOffset)
240 {
241 #ifdef linux
242         DWORD   toberead;
243         FOURCC  fourcc;
244         if (mmioSeek(MCIMidiDev[wDevID].hFile, dwOffset, SEEK_SET) != dwOffset) {
245                 dprintf_midi(stddeb, "MIDI_ReadMTrk // can't seek at %08lX begin of 'MThd' \n", dwOffset);
246                 }
247         if (mmioRead(MCIMidiDev[wDevID].hFile, (HPSTR)&fourcc,
248                 (long) sizeof(FOURCC)) != (long) sizeof(FOURCC)) {
249                 return MCIERR_INTERNAL;
250                 }
251         if (MIDI_ReadLong(wDevID, &toberead) != 0) {
252                 return MCIERR_INTERNAL;
253                 }
254         dprintf_midi(stddeb, "MIDI_ReadMTrk // toberead=%08lX\n", toberead);
255         toberead -= 3 * sizeof(WORD);
256         MCIMidiDev[wDevID].dwTotalLen = toberead;
257         return 0;
258 #else
259          return MMSYSERR_NOTENABLED;
260 #endif
261 }
262
263
264 /**************************************************************************
265 *                               MIDI_mciOpen                    [internal]      
266 */
267 static DWORD MIDI_mciOpen(UINT wDevID, DWORD dwFlags, LPMCI_OPEN_PARMS lpParms)
268 {
269 #ifdef linux
270         MIDIOPENDESC    MidiDesc;
271         DWORD           dwRet;
272         DWORD           dwOffset;
273         LPSTR           lpstrElementName;
274         char            str[128];
275
276         dprintf_midi(stddeb, "MIDI_mciOpen(%08lX, %p)\n", dwFlags, lpParms);
277         if (lpParms == NULL) return MCIERR_INTERNAL;
278         if (MCIMidiDev[wDevID].nUseCount > 0) {
279                 /* The driver already open on this channel */
280                 /* If the driver was opened shareable before and this open specifies */
281                 /* shareable then increment the use count */
282                 if (MCIMidiDev[wDevID].fShareable && (dwFlags & MCI_OPEN_SHAREABLE))
283                         ++MCIMidiDev[wDevID].nUseCount;
284                 else
285                         return MCIERR_MUST_USE_SHAREABLE;
286                 }
287         else {
288                 MCIMidiDev[wDevID].nUseCount = 1;
289                 MCIMidiDev[wDevID].fShareable = dwFlags & MCI_OPEN_SHAREABLE;
290                 }
291         dprintf_midi(stddeb, "MIDI_mciOpen // wDevID=%04X\n", wDevID);
292         lpParms->wDeviceID = wDevID;
293         dprintf_midi(stddeb, "MIDI_mciOpen // lpParms->wDevID=%04X\n", lpParms->wDeviceID);
294         dprintf_midi(stddeb, "MIDI_mciOpen // before OPEN_ELEMENT\n");
295     if (dwFlags & MCI_OPEN_ELEMENT) {
296                 lpstrElementName = (LPSTR)PTR_SEG_TO_LIN(lpParms->lpstrElementName);
297                 dprintf_midi(stddeb, "MIDI_mciOpen // MCI_OPEN_ELEMENT '%s' !\n", lpstrElementName);
298 /*              dprintf_midi(stddeb, "MIDI_mciOpen // cdw='%s'\n", DOS_GetCurrentDir(DOS_GetDefaultDrive())); */
299                 if (strlen(lpstrElementName) > 0) {
300                         strcpy(str, lpstrElementName);
301                         AnsiUpper(str);
302                         MCIMidiDev[wDevID].hFile = mmioOpen(str, NULL, 
303                                 MMIO_ALLOCBUF | MMIO_READWRITE | MMIO_EXCLUSIVE);
304                         if (MCIMidiDev[wDevID].hFile == 0) {
305                                 dprintf_midi(stddeb, "MIDI_mciOpen // can't find file='%s' !\n", str);
306                                 return MCIERR_FILE_NOT_FOUND;
307                                 }
308                         }
309                 else 
310                         MCIMidiDev[wDevID].hFile = 0;
311                 }
312         dprintf_midi(stddeb, "MIDI_mciOpen // hFile=%u\n", MCIMidiDev[wDevID].hFile);
313         memcpy(&MCIMidiDev[wDevID].openParms, lpParms, sizeof(MCI_OPEN_PARMS));
314         MCIMidiDev[wDevID].wNotifyDeviceID = lpParms->wDeviceID;
315         MCIMidiDev[wDevID].dwStatus = MCI_MODE_STOP;
316         MCIMidiDev[wDevID].dwBeginData = 0;
317         MCIMidiDev[wDevID].dwTotalLen = 0;
318         MidiDesc.hMidi = 0;
319         if (MCIMidiDev[wDevID].hFile != 0) {
320                 MMCKINFO        ckMainRIFF;
321                 if (mmioDescend(MCIMidiDev[wDevID].hFile, &ckMainRIFF, NULL, 0) != 0) {
322                         return MCIERR_INTERNAL;
323                         }
324                 dprintf_midi(stddeb,"MIDI_mciOpen // ParentChunk ckid=%.4s fccType=%.4s cksize=%08lX \n",
325                                 (LPSTR)&ckMainRIFF.ckid, (LPSTR)&ckMainRIFF.fccType,
326                                 ckMainRIFF.cksize);
327                 dwOffset = 0;
328                 if (ckMainRIFF.ckid == mmioFOURCC('R', 'M', 'I', 'D')) {
329                         dprintf_midi(stddeb, "MIDI_mciOpen // is a 'RMID' file \n");
330                         dwOffset = ckMainRIFF.dwDataOffset;
331                         }
332                 if (ckMainRIFF.ckid != mmioFOURCC('M', 'T', 'h', 'd')) {
333                         dprintf_midi(stddeb, "MIDI_mciOpen // unknown format !\n");
334                         return MCIERR_INTERNAL;
335                         }
336                 if (MIDI_ReadMThd(wDevID, dwOffset) != 0) {
337                         dprintf_midi(stddeb, "MIDI_mciOpen // can't read 'MThd' header \n");
338                         return MCIERR_INTERNAL;
339                         }
340                 dwOffset = mmioSeek(MCIMidiDev[wDevID].hFile, 0, SEEK_CUR);
341                 if (MIDI_ReadMTrk(wDevID, dwOffset) != 0) {
342                         dprintf_midi(stddeb, "MIDI_mciOpen // can't read 'MTrk' header \n");
343                         return MCIERR_INTERNAL;
344                         }
345                 dwOffset = mmioSeek(MCIMidiDev[wDevID].hFile, 0, SEEK_CUR);
346                 MCIMidiDev[wDevID].dwBeginData = dwOffset;
347                 dprintf_midi(stddeb, "MIDI_mciOpen // Chunk Found ckid=%.4s fccType=%.4s cksize=%08lX \n",
348                                 (LPSTR)&ckMainRIFF.ckid, (LPSTR)&ckMainRIFF.fccType,
349                                 ckMainRIFF.cksize);
350                 }
351         dwRet = modMessage(0, MODM_OPEN, 0, (DWORD)&MidiDesc, CALLBACK_NULL);
352         dwRet = midMessage(0, MIDM_OPEN, 0, (DWORD)&MidiDesc, CALLBACK_NULL);
353         return 0;
354 #else
355         return MMSYSERR_NOTENABLED;
356 #endif
357 }
358
359
360 /**************************************************************************
361 *                               MIDI_mciStop                    [internal]
362 */
363 static DWORD MIDI_mciStop(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
364 {
365 #ifdef linux
366         dprintf_midi(stddeb, "MIDI_mciStop(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
367         if (lpParms == NULL) return MCIERR_INTERNAL;
368         MCIMidiDev[wDevID].dwStatus = MCI_MODE_STOP;
369         dprintf_midi(stddeb, "MIDI_mciStop // MCIMidiDev[wDevID].dwStatus=%p %d\n",
370                         &MCIMidiDev[wDevID].dwStatus, MCIMidiDev[wDevID].dwStatus);
371         return 0;
372 #else
373         return MCIERR_INTERNAL;
374 #endif
375 }
376
377
378 /**************************************************************************
379 *                               MIDI_mciClose           [internal]
380 */
381 static DWORD MIDI_mciClose(UINT wDevID, DWORD dwParam, LPMCI_GENERIC_PARMS lpParms)
382 {
383 #ifdef linux
384         DWORD           dwRet;
385         dprintf_midi(stddeb, "MIDI_mciClose(%u, %08lX, %p);\n", wDevID, dwParam, lpParms);
386         if (MCIMidiDev[wDevID].dwStatus != MCI_MODE_STOP) {
387                 MIDI_mciStop(wDevID, MCI_WAIT, lpParms);
388                 }
389         MCIMidiDev[wDevID].dwStatus = MCI_MODE_STOP;
390         MCIMidiDev[wDevID].nUseCount--;
391         if (MCIMidiDev[wDevID].nUseCount == 0) {
392                 if (MCIMidiDev[wDevID].hFile != 0) {
393                         mmioClose(MCIMidiDev[wDevID].hFile, 0);
394                         MCIMidiDev[wDevID].hFile = 0;
395                         dprintf_midi(stddeb, "MIDI_mciClose // hFile closed !\n");
396                         }
397                 dwRet = modMessage(0, MODM_CLOSE, 0, 0L, 0L);
398                 if (dwRet != MMSYSERR_NOERROR) return MCIERR_INTERNAL;
399                 dwRet = midMessage(0, MIDM_CLOSE, 0, 0L, 0L);
400                 if (dwRet != MMSYSERR_NOERROR) return MCIERR_INTERNAL;
401                 }
402         return 0;
403 #else
404         return 0;
405 #endif
406 }
407
408
409 /**************************************************************************
410 *                               MIDI_mciPlay            [internal]
411 */
412 static DWORD MIDI_mciPlay(UINT wDevID, DWORD dwFlags, LPMCI_PLAY_PARMS lpParms)
413 {
414 #ifdef linux
415         int                     count;
416         int                     start, end;
417         LPMIDIHDR       lpMidiHdr;
418         DWORD           dwData;
419         LPWORD          ptr;
420         DWORD           dwRet;
421         dprintf_midi(stddeb, "MIDI_mciPlay(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
422         if (MCIMidiDev[wDevID].hFile == 0) {
423                 dprintf_midi(stddeb, "MIDI_mciPlay // can't find file='%s' !\n", 
424                                 MCIMidiDev[wDevID].openParms.lpstrElementName);
425                 return MCIERR_FILE_NOT_FOUND;
426                 }
427         start = 1;              end = 99999;
428         if (dwFlags & MCI_FROM) {
429                 start = lpParms->dwFrom; 
430                 dprintf_midi(stddeb, "MIDI_mciPlay // MCI_FROM=%d \n", start);
431                 }
432         if (dwFlags & MCI_TO) {
433                 end = lpParms->dwTo;
434                 dprintf_midi(stddeb, "MIDI_mciPlay // MCI_TO=%d \n", end);
435                 }
436 #if 0
437         if (dwFlags & MCI_NOTIFY) {
438                 dprintf_midi(stddeb, "MIDI_mciPlay // MCI_NOTIFY %08lX !\n", lpParms->dwCallback);
439                 switch(fork()) {
440                         case -1:
441                                 dprintf_midi(stddeb, "MIDI_mciPlay // Can't 'fork' process !\n");
442                                 break;
443                         case 0:
444                                 dprintf_midi(stddeb, "MIDI_mciPlay // process started ! play in background ...\n");
445                                 break;
446                         default:
447                                 dprintf_midi(stddeb, "MIDI_mciPlay // process started ! return to caller...\n");
448                                 return 0;
449                         }
450                 }
451 #endif
452         lpMidiHdr = &MCIMidiDev[wDevID].MidiHdr;
453         lpMidiHdr->lpData = (LPSTR) malloc(1200);
454         if (lpMidiHdr->lpData == NULL) return MCIERR_INTERNAL;
455         lpMidiHdr->dwBufferLength = 1024;
456         lpMidiHdr->dwUser = 0L;
457         lpMidiHdr->dwFlags = 0L;
458         dwRet = modMessage(0, MODM_PREPARE, 0, (DWORD)lpMidiHdr, sizeof(MIDIHDR));
459 /*      dprintf_midi(stddeb, "MIDI_mciPlay // after MODM_PREPARE \n"); */
460         MCIMidiDev[wDevID].dwStatus = MCI_MODE_PLAY;
461         while(MCIMidiDev[wDevID].dwStatus != MCI_MODE_STOP) {
462                 dprintf_midi(stddeb, "MIDI_mciPlay // MCIMidiDev[wDevID].dwStatus=%p %d\n",
463                         &MCIMidiDev[wDevID].dwStatus, MCIMidiDev[wDevID].dwStatus);
464                 ptr = (LPWORD)lpMidiHdr->lpData;
465                 for (count = 0; count < lpMidiHdr->dwBufferLength; count++) {
466                         if (MIDI_ReadVaryLen(wDevID, &dwData) != 0) break;
467                         *ptr = LOWORD(dwData);
468                         }
469 /*
470                 count = mmioRead(MCIMidiDev[wDevID].hFile, lpMidiHdr->lpData, lpMidiHdr->dwBufferLength);
471 */
472                 if (count < 1) break;
473                 lpMidiHdr->dwBytesRecorded = count;
474                 dprintf_midi(stddeb, "MIDI_mciPlay // before MODM_LONGDATA lpMidiHdr=%p dwBytesRecorded=%lu\n",
475                                         lpMidiHdr, lpMidiHdr->dwBytesRecorded);
476                 dwRet = modMessage(0, MODM_LONGDATA, 0, (DWORD)lpMidiHdr, sizeof(MIDIHDR));
477                 }
478         dwRet = modMessage(0, MODM_UNPREPARE, 0, (DWORD)lpMidiHdr, sizeof(MIDIHDR));
479         if (lpMidiHdr->lpData != NULL) {
480                 free(lpMidiHdr->lpData);
481                 lpMidiHdr->lpData = NULL;
482                 }
483         MCIMidiDev[wDevID].dwStatus = MCI_MODE_STOP;
484         if (dwFlags & MCI_NOTIFY) {
485                 dprintf_midi(stddeb, "MIDI_mciPlay // MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
486                 mciDriverNotify((HWND)LOWORD(lpParms->dwCallback), 
487                         MCIMidiDev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
488                 exit(1);
489                 }
490         return 0;
491 #else
492         return MMSYSERR_NOTENABLED;
493 #endif
494 }
495
496
497 /**************************************************************************
498 *                               MIDI_mciRecord                  [internal]
499 */
500 static DWORD MIDI_mciRecord(UINT wDevID, DWORD dwFlags, LPMCI_RECORD_PARMS lpParms)
501 {
502 #ifdef linux
503         int                     start, end;
504         LPMIDIHDR       lpMidiHdr;
505         DWORD           dwRet;
506
507         dprintf_midi(stddeb, "MIDI_mciRecord(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
508         if (MCIMidiDev[wDevID].hFile == 0) {
509                 dprintf_midi(stddeb, "MIDI_mciRecord // can't find file='%s' !\n", 
510                                 MCIMidiDev[wDevID].openParms.lpstrElementName);
511                 return MCIERR_FILE_NOT_FOUND;
512                 }
513         start = 1;              end = 99999;
514         if (dwFlags & MCI_FROM) {
515                 start = lpParms->dwFrom; 
516                 dprintf_midi(stddeb, "MIDI_mciRecord // MCI_FROM=%d \n", start);
517                 }
518         if (dwFlags & MCI_TO) {
519                 end = lpParms->dwTo;
520                 dprintf_midi(stddeb, "MIDI_mciRecord // MCI_TO=%d \n", end);
521                 }
522         lpMidiHdr = &MCIMidiDev[wDevID].MidiHdr;
523         lpMidiHdr->lpData = (LPSTR) malloc(1200);
524         lpMidiHdr->dwBufferLength = 1024;
525         lpMidiHdr->dwUser = 0L;
526         lpMidiHdr->dwFlags = 0L;
527         dwRet = midMessage(0, MIDM_PREPARE, 0, (DWORD)lpMidiHdr, sizeof(MIDIHDR));
528         dprintf_midi(stddeb, "MIDI_mciRecord // after MIDM_PREPARE \n");
529         MCIMidiDev[wDevID].dwStatus = MCI_MODE_RECORD;
530         while(MCIMidiDev[wDevID].dwStatus != MCI_MODE_STOP) {
531                 dprintf_midi(stddeb, "MIDI_mciRecord // MCIMidiDev[wDevID].dwStatus=%p %d\n",
532                         &MCIMidiDev[wDevID].dwStatus, MCIMidiDev[wDevID].dwStatus);
533                 lpMidiHdr->dwBytesRecorded = 0;
534                 dwRet = midMessage(0, MIDM_START, 0, 0L, 0L);
535                 dprintf_midi(stddeb, "MIDI_mciRecord // after MIDM_START lpMidiHdr=%p dwBytesRecorded=%lu\n",
536                                         lpMidiHdr, lpMidiHdr->dwBytesRecorded);
537                 if (lpMidiHdr->dwBytesRecorded == 0) break;
538                 }
539         dprintf_midi(stddeb, "MIDI_mciRecord // before MIDM_UNPREPARE \n");
540         dwRet = midMessage(0, MIDM_UNPREPARE, 0, (DWORD)lpMidiHdr, sizeof(MIDIHDR));
541         dprintf_midi(stddeb, "MIDI_mciRecord // after MIDM_UNPREPARE \n");
542         if (lpMidiHdr->lpData != NULL) {
543                 free(lpMidiHdr->lpData);
544                 lpMidiHdr->lpData = NULL;
545                 }
546         MCIMidiDev[wDevID].dwStatus = MCI_MODE_STOP;
547         if (dwFlags & MCI_NOTIFY) {
548                 dprintf_midi(stddeb, "MIDI_mciRecord // MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
549                 mciDriverNotify((HWND)LOWORD(lpParms->dwCallback), 
550                         MCIMidiDev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
551                 }
552         return 0;
553 #else
554         return MMSYSERR_NOTENABLED;
555 #endif
556 }
557
558
559 /**************************************************************************
560 *                               MIDI_mciPause                   [internal]
561 */
562 static DWORD MIDI_mciPause(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
563 {
564 #ifdef linux
565         dprintf_midi(stddeb, "MIDI_mciPause(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
566         if (lpParms == NULL) return MCIERR_INTERNAL;
567         return 0;
568 #else
569         return MCIERR_INTERNAL;
570 #endif
571 }
572
573
574 /**************************************************************************
575 *                               MIDI_mciResume                  [internal]
576 */
577 static DWORD MIDI_mciResume(UINT wDevID, DWORD dwFlags, LPMCI_GENERIC_PARMS lpParms)
578 {
579 #ifdef linux
580         dprintf_midi(stddeb, "MIDI_mciResume(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
581         if (lpParms == NULL) return MCIERR_INTERNAL;
582         return 0;
583 #else
584         return MCIERR_INTERNAL;
585 #endif
586 }
587
588
589 /**************************************************************************
590 *                               MIDI_mciSet                     [internal]
591 */
592 static DWORD MIDI_mciSet(UINT wDevID, DWORD dwFlags, LPMCI_SET_PARMS lpParms)
593 {
594 #ifdef linux
595         dprintf_midi(stddeb, "MIDI_mciSet(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
596         if (lpParms == NULL) return MCIERR_INTERNAL;
597         dprintf_midi(stddeb, "MIDI_mciSet // dwTimeFormat=%08lX\n", lpParms->dwTimeFormat);
598         dprintf_midi(stddeb, "MIDI_mciSet // dwAudio=%08lX\n", lpParms->dwAudio);
599         if (dwFlags & MCI_SET_TIME_FORMAT) {
600                 switch (lpParms->dwTimeFormat) {
601                         case MCI_FORMAT_MILLISECONDS:
602                                 dprintf_midi(stddeb, "MIDI_mciSet // MCI_FORMAT_MILLISECONDS !\n");
603                                 break;
604                         case MCI_FORMAT_BYTES:
605                                 dprintf_midi(stddeb, "MIDI_mciSet // MCI_FORMAT_BYTES !\n");
606                                 break;
607                         case MCI_FORMAT_SAMPLES:
608                                 dprintf_midi(stddeb, "MIDI_mciSet // MCI_FORMAT_SAMPLES !\n");
609                                 break;
610                         default:
611                                 dprintf_midi(stddeb, "MIDI_mciSet // bad time format !\n");
612                                 return MCIERR_BAD_TIME_FORMAT;
613                         }
614                 }
615         if (dwFlags & MCI_SET_VIDEO) return MCIERR_UNSUPPORTED_FUNCTION;
616         if (dwFlags & MCI_SET_DOOR_OPEN) return MCIERR_UNSUPPORTED_FUNCTION;
617         if (dwFlags & MCI_SET_DOOR_CLOSED) return MCIERR_UNSUPPORTED_FUNCTION;
618         if (dwFlags & MCI_SET_AUDIO) {
619                 dprintf_midi(stddeb, "MIDI_mciSet // MCI_SET_AUDIO !\n");
620                 }
621         if (dwFlags && MCI_SET_ON) {
622                 dprintf_midi(stddeb, "MIDI_mciSet // MCI_SET_ON !\n");
623                 if (dwFlags && MCI_SET_AUDIO_LEFT) {
624                         dprintf_midi(stddeb, "MIDI_mciSet // MCI_SET_AUDIO_LEFT !\n");
625                         }
626                 if (dwFlags && MCI_SET_AUDIO_RIGHT) {
627                         dprintf_midi(stddeb, "MIDI_mciSet // MCI_SET_AUDIO_RIGHT !\n");
628                         }
629                 }
630         if (dwFlags & MCI_SET_OFF) {
631                 dprintf_midi(stddeb, "MIDI_mciSet // MCI_SET_OFF !\n");
632                 }
633         if (dwFlags & MCI_SEQ_SET_MASTER) {
634                 dprintf_midi(stddeb, "MIDI_mciSet // MCI_SEQ_SET_MASTER !\n");
635                 }
636         if (dwFlags & MCI_SEQ_SET_SLAVE) {
637                 dprintf_midi(stddeb, "MIDI_mciSet // MCI_SEQ_SET_SLAVE !\n");
638                 }
639         if (dwFlags & MCI_SEQ_SET_OFFSET) {
640                 dprintf_midi(stddeb, "MIDI_mciSet // MCI_SEQ_SET_OFFSET !\n");
641                 }
642         if (dwFlags & MCI_SEQ_SET_PORT) {
643                 dprintf_midi(stddeb, "MIDI_mciSet // MCI_SEQ_SET_PORT !\n");
644                 }
645         if (dwFlags & MCI_SEQ_SET_TEMPO) {
646                 dprintf_midi(stddeb, "MIDI_mciSet // MCI_SEQ_SET_TEMPO !\n");
647                 }
648         return 0;
649 #else
650         return MCIERR_INTERNAL;
651 #endif
652 }
653
654
655 /**************************************************************************
656 *                               MIDI_mciStatus          [internal]
657 */
658 static DWORD MIDI_mciStatus(UINT wDevID, DWORD dwFlags, LPMCI_STATUS_PARMS lpParms)
659 {
660 #ifdef linux
661         dprintf_midi(stddeb, "MIDI_mciStatus(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
662         if (lpParms == NULL) return MCIERR_INTERNAL;
663         if (dwFlags & MCI_STATUS_ITEM) {
664                 switch(lpParms->dwItem) {
665                         case MCI_STATUS_CURRENT_TRACK:
666                                 lpParms->dwReturn = 1;
667                                 break;
668                         case MCI_STATUS_LENGTH:
669                                 lpParms->dwReturn = 5555;
670                                 if (dwFlags & MCI_TRACK) {
671                                         lpParms->dwTrack = 1;
672                                         lpParms->dwReturn = 2222;
673                                         }
674                                 break;
675                         case MCI_STATUS_MODE:
676                                 lpParms->dwReturn = MCI_MODE_STOP;
677                                 break;
678                         case MCI_STATUS_MEDIA_PRESENT:
679                                 dprintf_midi(stddeb, "MIDI_mciStatus // MCI_STATUS_MEDIA_PRESENT !\n");
680                                 lpParms->dwReturn = TRUE;
681                                 break;
682                         case MCI_STATUS_NUMBER_OF_TRACKS:
683                                 lpParms->dwReturn = 1;
684                                 break;
685                         case MCI_STATUS_POSITION:
686                                 lpParms->dwReturn = 3333;
687                                 if (dwFlags & MCI_STATUS_START) {
688                                         lpParms->dwItem = 1;
689                                         }
690                                 if (dwFlags & MCI_TRACK) {
691                                         lpParms->dwTrack = 1;
692                                         lpParms->dwReturn = 777;
693                                         }
694                                 break;
695                         case MCI_STATUS_READY:
696                                 dprintf_midi(stddeb, "MIDI_mciStatus // MCI_STATUS_READY !\n");
697                                 lpParms->dwReturn = TRUE;
698                                 break;
699                         case MCI_STATUS_TIME_FORMAT:
700                                 dprintf_midi(stddeb, "MIDI_mciStatus // MCI_STATUS_TIME_FORMAT !\n");
701                                 lpParms->dwReturn = MCI_FORMAT_MILLISECONDS;
702                                 break;
703                         case MCI_SEQ_STATUS_DIVTYPE:
704                                 dprintf_midi(stddeb, "MIDI_mciStatus // MCI_SEQ_STATUS_DIVTYPE !\n");
705                                 lpParms->dwReturn = 0;
706                                 break;
707                         case MCI_SEQ_STATUS_MASTER:
708                                 dprintf_midi(stddeb, "MIDI_mciStatus // MCI_SEQ_STATUS_MASTER !\n");
709                                 lpParms->dwReturn = 0;
710                                 break;
711                         case MCI_SEQ_STATUS_SLAVE:
712                                 dprintf_midi(stddeb, "MIDI_mciStatus // MCI_SEQ_STATUS_SLAVE !\n");
713                                 lpParms->dwReturn = 0;
714                                 break;
715                         case MCI_SEQ_STATUS_OFFSET:
716                                 dprintf_midi(stddeb, "MIDI_mciStatus // MCI_SEQ_STATUS_OFFSET !\n");
717                                 lpParms->dwReturn = 0;
718                                 break;
719                         case MCI_SEQ_STATUS_PORT:
720                                 dprintf_midi(stddeb, "MIDI_mciStatus // MCI_SEQ_STATUS_PORT !\n");
721                                 lpParms->dwReturn = 0;
722                                 break;
723                         case MCI_SEQ_STATUS_TEMPO:
724                                 dprintf_midi(stddeb, "MIDI_mciStatus // MCI_SEQ_STATUS_TEMPO !\n");
725                                 lpParms->dwReturn = 0;
726                                 break;
727                         default:
728                                 dprintf_midi(stddeb, "MIDI_mciStatus // unknowm command %08lX !\n", lpParms->dwItem);
729                                 return MCIERR_UNRECOGNIZED_COMMAND;
730                         }
731                 }
732         if (dwFlags & MCI_NOTIFY) {
733                 dprintf_midi(stddeb, "MIDI_mciStatus // MCI_NOTIFY_SUCCESSFUL %08lX !\n", lpParms->dwCallback);
734                 mciDriverNotify((HWND)LOWORD(lpParms->dwCallback), 
735                         MCIMidiDev[wDevID].wNotifyDeviceID, MCI_NOTIFY_SUCCESSFUL);
736                 }
737         return 0;
738 #else
739         return MCIERR_INTERNAL;
740 #endif
741 }
742
743 /**************************************************************************
744 *                               MIDI_mciGetDevCaps              [internal]
745 */
746 static DWORD MIDI_mciGetDevCaps(UINT wDevID, DWORD dwFlags, 
747                                         LPMCI_GETDEVCAPS_PARMS lpParms)
748 {
749 #ifdef linux
750         dprintf_midi(stddeb, "MIDI_mciGetDevCaps(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
751         if (lpParms == NULL) return MCIERR_INTERNAL;
752         if (dwFlags & MCI_GETDEVCAPS_ITEM) {
753                 switch(lpParms->dwItem) {
754                         case MCI_GETDEVCAPS_CAN_RECORD:
755                                 lpParms->dwReturn = TRUE;
756                                 break;
757                         case MCI_GETDEVCAPS_HAS_AUDIO:
758                                 lpParms->dwReturn = TRUE;
759                                 break;
760                         case MCI_GETDEVCAPS_HAS_VIDEO:
761                                 lpParms->dwReturn = FALSE;
762                                 break;
763                         case MCI_GETDEVCAPS_DEVICE_TYPE:
764                                 lpParms->dwReturn = MCI_DEVTYPE_SEQUENCER;
765                                 break;
766                         case MCI_GETDEVCAPS_USES_FILES:
767                                 lpParms->dwReturn = TRUE;
768                                 break;
769                         case MCI_GETDEVCAPS_COMPOUND_DEVICE:
770                                 lpParms->dwReturn = TRUE;
771                                 break;
772                         case MCI_GETDEVCAPS_CAN_EJECT:
773                                 lpParms->dwReturn = FALSE;
774                                 break;
775                         case MCI_GETDEVCAPS_CAN_PLAY:
776                                 lpParms->dwReturn = TRUE;
777                                 break;
778                         case MCI_GETDEVCAPS_CAN_SAVE:
779                                 lpParms->dwReturn = FALSE;
780                                 break;
781                         default:
782                                 return MCIERR_UNRECOGNIZED_COMMAND;
783                         }
784                 }
785         return 0;
786 #else
787         return MCIERR_INTERNAL;
788 #endif
789 }
790
791 /**************************************************************************
792 *                               MIDI_mciInfo                    [internal]
793 */
794 static DWORD MIDI_mciInfo(UINT wDevID, DWORD dwFlags, LPMCI_INFO_PARMS lpParms)
795 {
796 #ifdef linux
797         dprintf_midi(stddeb, "MIDI_mciInfo(%u, %08lX, %p);\n", wDevID, dwFlags, lpParms);
798         if (lpParms == NULL) return MCIERR_INTERNAL;
799         lpParms->lpstrReturn = NULL;
800         switch(dwFlags) {
801                 case MCI_INFO_PRODUCT:
802                         lpParms->lpstrReturn = "Linux Sound System 0.5";
803                         break;
804                 case MCI_INFO_FILE:
805                         lpParms->lpstrReturn = "FileName";
806                         break;
807                 default:
808                         return MCIERR_UNRECOGNIZED_COMMAND;
809                 }
810         if (lpParms->lpstrReturn != NULL)
811                 lpParms->dwRetSize = strlen(lpParms->lpstrReturn);
812         else
813                 lpParms->dwRetSize = 0;
814         return 0;
815 #else
816         return MCIERR_INTERNAL;
817 #endif
818 }
819
820
821 /*-----------------------------------------------------------------------*/
822
823
824 /**************************************************************************
825 *                               midGetDevCaps                   [internal]
826 */
827 static DWORD midGetDevCaps(WORD wDevID, LPMIDIINCAPS lpCaps, DWORD dwSize)
828 {
829         dprintf_midi(stddeb, "midGetDevCaps(%u, %p, %08lX);\n", wDevID, lpCaps, dwSize);
830         return MMSYSERR_NOTENABLED;
831 }
832
833 /**************************************************************************
834 *                               midOpen                                 [internal]
835 */
836 static DWORD midOpen(WORD wDevID, LPMIDIOPENDESC lpDesc, DWORD dwFlags)
837 {
838 #ifdef linux
839         int             midi;
840         dprintf_midi(stddeb,
841                 "midOpen(%u, %p, %08lX);\n", wDevID, lpDesc, dwFlags);
842         if (lpDesc == NULL) {
843                 dprintf_midi(stddeb,"Linux 'midOpen' // Invalid Parameter !\n");
844                 return MMSYSERR_INVALPARAM;
845                 }
846         if (wDevID >= MAX_MIDIINDRV) {
847                 dprintf_midi(stddeb,"Linux 'midOpen' // MAX_MIDIINDRV reached !\n");
848                 return MMSYSERR_ALLOCATED;
849                 }
850         MidiInDev[wDevID].unixdev = 0;
851         midi = open (MIDI_DEV, O_RDONLY, 0);
852         if (midi == -1) {
853                 dprintf_midi(stddeb,"Linux 'midOpen' // can't open !\n");
854                 return MMSYSERR_NOTENABLED;
855                 }
856         MidiInDev[wDevID].wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
857         switch(MidiInDev[wDevID].wFlags) {
858                 case DCB_NULL:
859                         dprintf_midi(stddeb,"Linux 'midOpen' // CALLBACK_NULL !\n");
860                         break;
861                 case DCB_WINDOW:
862                         dprintf_midi(stddeb,
863                                 "Linux 'midOpen' // CALLBACK_WINDOW !\n");
864                         break;
865                 case DCB_TASK:
866                         dprintf_midi(stddeb,
867                                    "Linux 'midOpen' // CALLBACK_TASK !\n");
868                         break;
869                 case DCB_FUNCTION:
870                         dprintf_midi(stddeb,
871                                    "Linux 'midOpen' // CALLBACK_FUNCTION !\n");
872                         break;
873                 }
874         MidiInDev[wDevID].lpQueueHdr = NULL;
875         MidiInDev[wDevID].unixdev = midi;
876         MidiInDev[wDevID].dwTotalPlayed = 0;
877         MidiInDev[wDevID].bufsize = 0x3FFF;
878         if (MIDI_NotifyClient(wDevID, MIM_OPEN, 0L, 0L) != MMSYSERR_NOERROR) {
879                 dprintf_midi(stddeb,"Linux 'midOpen' // can't notify client !\n");
880                 return MMSYSERR_INVALPARAM;
881                 }
882         return MMSYSERR_NOERROR;
883 #else
884         return MMSYSERR_NOTENABLED;
885 #endif
886 }
887
888 /**************************************************************************
889 *                               midClose                                [internal]
890 */
891 static DWORD midClose(WORD wDevID)
892 {
893 #ifdef linux
894         dprintf_midi(stddeb, "midClose(%u);\n", wDevID);
895         if (MidiInDev[wDevID].unixdev == 0) {
896                 dprintf_midi(stddeb,"Linux 'midClose' // can't close !\n");
897                 return MMSYSERR_NOTENABLED;
898                 }
899         close(MidiInDev[wDevID].unixdev);
900         MidiInDev[wDevID].unixdev = 0;
901         MidiInDev[wDevID].bufsize = 0;
902         if (MIDI_NotifyClient(wDevID, MIM_CLOSE, 0L, 0L) != MMSYSERR_NOERROR) {
903                 dprintf_midi(stddeb,"Linux 'midClose' // can't notify client !\n");
904                 return MMSYSERR_INVALPARAM;
905                 }
906         return MMSYSERR_NOERROR;
907 #else
908         return MMSYSERR_NOTENABLED;
909 #endif
910 }
911
912 /**************************************************************************
913 *                               midAddBuffer            [internal]
914 */
915 static DWORD midAddBuffer(WORD wDevID, LPMIDIHDR lpMidiHdr, DWORD dwSize)
916 {
917         dprintf_midi(stddeb, "midAddBuffer(%u, %p, %08lX);\n", wDevID, lpMidiHdr, dwSize);
918         return MMSYSERR_NOTENABLED;
919 }
920
921 /**************************************************************************
922 *                               midPrepare                      [internal]
923 */
924 static DWORD midPrepare(WORD wDevID, LPMIDIHDR lpMidiHdr, DWORD dwSize)
925 {
926         dprintf_midi(stddeb, "midPrepare(%u, %p, %08lX);\n", wDevID, lpMidiHdr, dwSize);
927         return MMSYSERR_NOTENABLED;
928 }
929
930 /**************************************************************************
931 *                               midUnprepare                    [internal]
932 */
933 static DWORD midUnprepare(WORD wDevID, LPMIDIHDR lpMidiHdr, DWORD dwSize)
934 {
935         dprintf_midi(stddeb, "midUnprepare(%u, %p, %08lX);\n", wDevID, lpMidiHdr, dwSize);
936         return MMSYSERR_NOTENABLED;
937 }
938
939 /**************************************************************************
940 *                               midReset                                [internal]
941 */
942 static DWORD midReset(WORD wDevID)
943 {
944         dprintf_midi(stddeb, "midReset(%u);\n", wDevID);
945         return MMSYSERR_NOTENABLED;
946 }
947
948
949 /**************************************************************************
950 *                               midStart                                [internal]
951 */
952 static DWORD midStart(WORD wDevID)
953 {
954         dprintf_midi(stddeb, "midStart(%u);\n", wDevID);
955         return MMSYSERR_NOTENABLED;
956 }
957
958
959 /**************************************************************************
960 *                               midStop                                 [internal]
961 */
962 static DWORD midStop(WORD wDevID)
963 {
964         dprintf_midi(stddeb, "midStop(%u);\n", wDevID);
965         return MMSYSERR_NOTENABLED;
966 }
967
968
969 /**************************************************************************
970 *                               midMessage                              [sample driver]
971 */
972 DWORD midMessage(WORD wDevID, WORD wMsg, DWORD dwUser, 
973                                         DWORD dwParam1, DWORD dwParam2)
974 {
975         dprintf_midi(stddeb, "midMessage(%u, %04X, %08lX, %08lX, %08lX);\n", 
976                         wDevID, wMsg, dwUser, dwParam1, dwParam2);
977         switch(wMsg) {
978                 case MIDM_OPEN:
979                         return midOpen(wDevID, (LPMIDIOPENDESC)PTR_SEG_TO_LIN(dwParam1), dwParam2);
980                 case MIDM_CLOSE:
981                         return midClose(wDevID);
982                 case MIDM_ADDBUFFER:
983                         return midAddBuffer(wDevID, (LPMIDIHDR)PTR_SEG_TO_LIN(dwParam1), dwParam2);
984                 case MIDM_PREPARE:
985                         return midPrepare(wDevID, (LPMIDIHDR)PTR_SEG_TO_LIN(dwParam1), dwParam2);
986                 case MIDM_UNPREPARE:
987                         return midUnprepare(wDevID, (LPMIDIHDR)PTR_SEG_TO_LIN(dwParam1), dwParam2);
988                 case MIDM_GETDEVCAPS:
989                         return midGetDevCaps(wDevID, (LPMIDIINCAPS)PTR_SEG_TO_LIN(dwParam1), dwParam2);
990                 case MIDM_GETNUMDEVS:
991                         return 0;
992                 case MIDM_RESET:
993                         return midReset(wDevID);
994                 case MIDM_START:
995                         return midStart(wDevID);
996                 case MIDM_STOP:
997                         return midStop(wDevID);
998                 }
999         return MMSYSERR_NOTSUPPORTED;
1000 }
1001
1002
1003
1004 /*-----------------------------------------------------------------------*/
1005
1006
1007 /**************************************************************************
1008 *                               modGetDevCaps                   [internal]
1009 */
1010 static DWORD modGetDevCaps(WORD wDevID, LPMIDIOUTCAPS lpCaps, DWORD dwSize)
1011 {
1012         dprintf_midi(stddeb, "modGetDevCaps(%u, %p, %08lX);\n", wDevID, lpCaps, dwSize);
1013         return MMSYSERR_NOTENABLED;
1014 }
1015
1016
1017 /**************************************************************************
1018 *                               modOpen                                 [internal]
1019 */
1020 static DWORD modOpen(WORD wDevID, LPMIDIOPENDESC lpDesc, DWORD dwFlags)
1021 {                                                                
1022 #ifdef linux
1023         int             midi;
1024         dprintf_midi(stddeb,
1025                 "modOpen(%u, %p, %08lX);\n", wDevID, lpDesc, dwFlags);
1026         if (lpDesc == NULL) {
1027                 dprintf_midi(stddeb,"Linux 'modOpen' // Invalid Parameter !\n");
1028                 return MMSYSERR_INVALPARAM;
1029                 }
1030         if (wDevID >= MAX_MIDIOUTDRV) {
1031                 dprintf_midi(stddeb,"Linux 'modOpen' // MAX_MIDIOUTDRV reached !\n");
1032                 return MMSYSERR_ALLOCATED;
1033                 }
1034         MidiOutDev[wDevID].unixdev = 0;
1035         midi = open (MIDI_DEV, O_WRONLY, 0);
1036         if (midi == -1) {
1037                 dprintf_midi(stddeb,"Linux 'modOpen' // can't open !\n");
1038                 return MMSYSERR_NOTENABLED;
1039                 }
1040         MidiOutDev[wDevID].wFlags = HIWORD(dwFlags & CALLBACK_TYPEMASK);
1041         switch(MidiOutDev[wDevID].wFlags) {
1042                 case DCB_NULL:
1043                         dprintf_midi(stddeb,"Linux 'modOpen' // CALLBACK_NULL !\n");
1044                         break;
1045                 case DCB_WINDOW:
1046                         dprintf_midi(stddeb,
1047                                 "Linux 'modOpen' // CALLBACK_WINDOW !\n");
1048                         break;
1049                 case DCB_TASK:
1050                         dprintf_midi(stddeb,
1051                                 "Linux 'modOpen' // CALLBACK_TASK !\n");
1052                         break;
1053                 case DCB_FUNCTION:
1054                         dprintf_midi(stddeb,
1055                                 "Linux 'modOpen' // CALLBACK_FUNCTION !\n");
1056                         break;
1057                 }
1058         MidiOutDev[wDevID].lpQueueHdr = NULL;
1059         MidiOutDev[wDevID].unixdev = midi;
1060         MidiOutDev[wDevID].dwTotalPlayed = 0;
1061         MidiOutDev[wDevID].bufsize = 0x3FFF;
1062         if (MIDI_NotifyClient(wDevID, MOM_OPEN, 0L, 0L) != MMSYSERR_NOERROR) {
1063                 dprintf_midi(stddeb,"Linux 'modOpen' // can't notify client !\n");
1064                 return MMSYSERR_INVALPARAM;
1065                 }
1066         dprintf_midi(stddeb,
1067                 "Linux 'modOpen' // Succesful unixdev=%d !\n", midi);
1068         return MMSYSERR_NOERROR;
1069 #else
1070         return MMSYSERR_NOTENABLED;
1071 #endif
1072 }
1073
1074
1075 /**************************************************************************
1076 *                               modClose                                [internal]
1077 */
1078 static DWORD modClose(WORD wDevID)
1079 {
1080 #ifdef linux
1081         dprintf_midi(stddeb, "modClose(%u);\n", wDevID);
1082         if (MidiOutDev[wDevID].unixdev == 0) {
1083                 dprintf_midi(stddeb,"Linux 'modClose' // can't close !\n");
1084                 return MMSYSERR_NOTENABLED;
1085                 }
1086         close(MidiOutDev[wDevID].unixdev);
1087         MidiOutDev[wDevID].unixdev = 0;
1088         MidiOutDev[wDevID].bufsize = 0;
1089         if (MIDI_NotifyClient(wDevID, MOM_CLOSE, 0L, 0L) != MMSYSERR_NOERROR) {
1090                 dprintf_midi(stddeb,"Linux 'modClose' // can't notify client !\n");
1091                 return MMSYSERR_INVALPARAM;
1092                 }
1093         return MMSYSERR_NOERROR;
1094 #else
1095         return MMSYSERR_NOTENABLED;
1096 #endif
1097 }
1098
1099 /**************************************************************************
1100 *                               modData                                 [internal]
1101 */
1102 static DWORD modData(WORD wDevID, DWORD dwParam)
1103 {
1104 #ifdef linux
1105         WORD    event;
1106         dprintf_midi(stddeb,    
1107                 "modData(%u, %08lX);\n", wDevID, dwParam);
1108         if (MidiOutDev[wDevID].unixdev == 0) {
1109         dprintf_midi(stddeb,"Linux 'modData' // can't play !\n");
1110                 return MIDIERR_NODEVICE;
1111                 }
1112         event = LOWORD(dwParam);
1113         if (write (MidiOutDev[wDevID].unixdev, 
1114                 &event, sizeof(WORD)) != sizeof(WORD)) {
1115                 dprintf_midi(stddeb,
1116                         "modData() // error writting unixdev !\n");
1117                 }
1118         return MMSYSERR_NOTENABLED;
1119 #else
1120         return MMSYSERR_NOTENABLED;
1121 #endif
1122 }
1123
1124 /**************************************************************************
1125 *                               modLongData                                     [internal]
1126 */
1127 static DWORD modLongData(WORD wDevID, LPMIDIHDR lpMidiHdr, DWORD dwSize)
1128 {
1129 #ifdef linux
1130         int             count;
1131         LPWORD  ptr;
1132         dprintf_midi(stddeb,    
1133                 "modLongData(%u, %p, %08lX);\n", wDevID, lpMidiHdr, dwSize);
1134         dprintf_midi(stddeb, "modLongData(%u, %p, %08lX);\n", wDevID, lpMidiHdr, dwSize);
1135         if (MidiOutDev[wDevID].unixdev == 0) {
1136         dprintf_midi(stddeb,"Linux 'modLongData' // can't play !\n");
1137                 return MIDIERR_NODEVICE;
1138                 }
1139         if (lpMidiHdr->lpData == NULL) return MIDIERR_UNPREPARED;
1140         if (!(lpMidiHdr->dwFlags & MHDR_PREPARED)) return MIDIERR_UNPREPARED;
1141         if (lpMidiHdr->dwFlags & MHDR_INQUEUE) return MIDIERR_STILLPLAYING;
1142         lpMidiHdr->dwFlags &= ~MHDR_DONE;
1143         lpMidiHdr->dwFlags |= MHDR_INQUEUE;
1144         dprintf_midi(stddeb,
1145                 "modLongData() // dwBytesRecorded %lu !\n", lpMidiHdr->dwBytesRecorded);
1146 /*
1147         count = write (MidiOutDev[wDevID].unixdev, 
1148                 lpMidiHdr->lpData, lpMidiHdr->dwBytesRecorded);
1149 */
1150         ptr = (LPWORD)lpMidiHdr->lpData;
1151         for (count = 0; count < lpMidiHdr->dwBytesRecorded; count++) {
1152                 if (write (MidiOutDev[wDevID].unixdev, ptr, 
1153                         sizeof(WORD)) != sizeof(WORD)) break;
1154                 ptr++;
1155                 }
1156         if (count != lpMidiHdr->dwBytesRecorded) {
1157                 dprintf_midi(stddeb,
1158                         "modLongData() // error writting unixdev #%d ! (%d != %ld)\n",
1159                         MidiOutDev[wDevID].unixdev, count, lpMidiHdr->dwBytesRecorded);
1160                 return MMSYSERR_NOTENABLED;
1161                 }
1162         lpMidiHdr->dwFlags &= ~MHDR_INQUEUE;
1163         lpMidiHdr->dwFlags |= MHDR_DONE;
1164         if (MIDI_NotifyClient(wDevID, MOM_DONE, 0L, 0L) != MMSYSERR_NOERROR) {
1165                 dprintf_midi(stddeb,"Linux 'modLongData' // can't notify client !\n");
1166                 return MMSYSERR_INVALPARAM;
1167                 }
1168         return MMSYSERR_NOERROR;
1169 #else
1170         return MMSYSERR_NOTENABLED;
1171 #endif
1172 }
1173
1174 /**************************************************************************
1175 *                               modPrepare                              [internal]
1176 */
1177 static DWORD modPrepare(WORD wDevID, LPMIDIHDR lpMidiHdr, DWORD dwSize)
1178 {
1179 #ifdef linux
1180         dprintf_midi(stddeb,
1181                   "modPrepare(%u, %p, %08lX);\n", wDevID, lpMidiHdr, dwSize);
1182         if (MidiOutDev[wDevID].unixdev == 0) {
1183                 dprintf_midi(stddeb,"Linux 'modPrepare' // can't prepare !\n");
1184                 return MMSYSERR_NOTENABLED;
1185                 }
1186         if (MidiOutDev[wDevID].lpQueueHdr != NULL) {
1187                 dprintf_midi(stddeb,"Linux 'modPrepare' // already prepare !\n");
1188                 return MMSYSERR_NOTENABLED;
1189                 }
1190         MidiOutDev[wDevID].dwTotalPlayed = 0;
1191         MidiOutDev[wDevID].lpQueueHdr = lpMidiHdr;
1192         if (lpMidiHdr->dwFlags & MHDR_INQUEUE) return MIDIERR_STILLPLAYING;
1193         lpMidiHdr->dwFlags |= MHDR_PREPARED;
1194         lpMidiHdr->dwFlags &= ~MHDR_DONE;
1195         return MMSYSERR_NOERROR;
1196 #else
1197         return MMSYSERR_NOTENABLED;
1198 #endif
1199 }
1200
1201 /**************************************************************************
1202 *                               modUnprepare                    [internal]
1203 */
1204 static DWORD modUnprepare(WORD wDevID, LPMIDIHDR lpMidiHdr, DWORD dwSize)
1205 {
1206 #ifdef linux
1207         dprintf_midi(stddeb,
1208                 "modUnprepare(%u, %p, %08lX);\n", wDevID, lpMidiHdr, dwSize);
1209         if (MidiOutDev[wDevID].unixdev == 0) {
1210                 dprintf_midi(stddeb,"Linux 'modUnprepare' // can't unprepare !\n");
1211                 return MMSYSERR_NOTENABLED;
1212                 }
1213         return MMSYSERR_NOERROR;
1214 #else
1215         return MMSYSERR_NOTENABLED;
1216 #endif
1217 }
1218
1219 /**************************************************************************
1220 *                               modReset                                [internal]
1221 */
1222 static DWORD modReset(WORD wDevID)
1223 {
1224         dprintf_midi(stddeb, "modReset(%u);\n", wDevID);
1225         return MMSYSERR_NOTENABLED;
1226 }
1227
1228
1229 /**************************************************************************
1230 *                               modMessage                      [sample driver]
1231 */
1232 DWORD modMessage(WORD wDevID, WORD wMsg, DWORD dwUser, 
1233                                         DWORD dwParam1, DWORD dwParam2)
1234 {
1235         dprintf_midi(stddeb, "modMessage(%u, %04X, %08lX, %08lX, %08lX);\n", 
1236                         wDevID, wMsg, dwUser, dwParam1, dwParam2);
1237         switch(wMsg) {
1238                 case MODM_OPEN:
1239                         return modOpen(wDevID, (LPMIDIOPENDESC)PTR_SEG_TO_LIN(dwParam1), dwParam2);
1240                 case MODM_CLOSE:
1241                         return modClose(wDevID);
1242                 case MODM_DATA:
1243                         return modData(wDevID, dwParam1);
1244                 case MODM_LONGDATA:
1245                         return modLongData(wDevID, (LPMIDIHDR)PTR_SEG_TO_LIN(dwParam1), dwParam2);
1246                 case MODM_PREPARE:
1247                         return modPrepare(wDevID, (LPMIDIHDR)PTR_SEG_TO_LIN(dwParam1), dwParam2);
1248                 case MODM_UNPREPARE:
1249                         return modUnprepare(wDevID, (LPMIDIHDR)PTR_SEG_TO_LIN(dwParam1), dwParam2);
1250                 case MODM_GETDEVCAPS:
1251                         return modGetDevCaps(wDevID, (LPMIDIOUTCAPS)PTR_SEG_TO_LIN(dwParam1), dwParam2);
1252                 case MODM_GETNUMDEVS:
1253                         return 1;
1254                 case MODM_GETVOLUME:
1255                         return 0;
1256                 case MODM_SETVOLUME:
1257                         return 0;
1258                 case MODM_RESET:
1259                         return modReset(wDevID);
1260                 }
1261         return MMSYSERR_NOTSUPPORTED;
1262 }
1263
1264
1265 /**************************************************************************
1266 *                               MIDI_DriverProc         [sample driver]
1267 */
1268 LONG MIDI_DriverProc(DWORD dwDevID, HDRVR hDriv, WORD wMsg, 
1269                                                 DWORD dwParam1, DWORD dwParam2)
1270 {
1271 #ifdef linux
1272         switch(wMsg) {
1273                 case DRV_LOAD:
1274                         return 1;
1275                 case DRV_FREE:
1276                         return 1;
1277                 case DRV_OPEN:
1278                         return 1;
1279                 case DRV_CLOSE:
1280                         return 1;
1281                 case DRV_ENABLE:
1282                         return 1;
1283                 case DRV_DISABLE:
1284                         return 1;
1285                 case DRV_QUERYCONFIGURE:
1286                         return 1;
1287                 case DRV_CONFIGURE:
1288                         MessageBox(0, "Sample Midi Linux Driver !", 
1289                                                                 "MMLinux Driver", MB_OK);
1290                         return 1;
1291                 case DRV_INSTALL:
1292                         return DRVCNF_RESTART;
1293                 case DRV_REMOVE:
1294                         return DRVCNF_RESTART;
1295                 case MCI_OPEN_DRIVER:
1296                 case MCI_OPEN:
1297                         return MIDI_mciOpen(dwDevID, dwParam1, (LPMCI_OPEN_PARMS)PTR_SEG_TO_LIN(dwParam2));
1298                 case MCI_CLOSE_DRIVER:
1299                 case MCI_CLOSE:
1300                         return MIDI_mciClose(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)PTR_SEG_TO_LIN(dwParam2));
1301                 case MCI_PLAY:
1302                         return MIDI_mciPlay(dwDevID, dwParam1, (LPMCI_PLAY_PARMS)PTR_SEG_TO_LIN(dwParam2));
1303                 case MCI_RECORD:
1304                         return MIDI_mciRecord(dwDevID, dwParam1, (LPMCI_RECORD_PARMS)PTR_SEG_TO_LIN(dwParam2));
1305                 case MCI_STOP:
1306                         return MIDI_mciStop(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)PTR_SEG_TO_LIN(dwParam2));
1307                 case MCI_SET:
1308                         return MIDI_mciSet(dwDevID, dwParam1, (LPMCI_SET_PARMS)PTR_SEG_TO_LIN(dwParam2));
1309                 case MCI_PAUSE:
1310                         return MIDI_mciPause(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)PTR_SEG_TO_LIN(dwParam2));
1311                 case MCI_RESUME:
1312                         return MIDI_mciResume(dwDevID, dwParam1, (LPMCI_GENERIC_PARMS)PTR_SEG_TO_LIN(dwParam2));
1313                 case MCI_STATUS:
1314                         return MIDI_mciStatus(dwDevID, dwParam1, (LPMCI_STATUS_PARMS)PTR_SEG_TO_LIN(dwParam2));
1315                 case MCI_GETDEVCAPS:
1316                         return MIDI_mciGetDevCaps(dwDevID, dwParam1, (LPMCI_GETDEVCAPS_PARMS)PTR_SEG_TO_LIN(dwParam2));
1317                 case MCI_INFO:
1318                         return MIDI_mciInfo(dwDevID, dwParam1, (LPMCI_INFO_PARMS)PTR_SEG_TO_LIN(dwParam2));
1319                 default:
1320                         return DefDriverProc(dwDevID, hDriv, wMsg, dwParam1, dwParam2);
1321                 }
1322 #else
1323         return MMSYSERR_NOTENABLED;
1324 #endif
1325 }
1326
1327
1328 /*-----------------------------------------------------------------------*/
1329
1330 #endif /* #ifdef BUILTIN_MMSYSTEM */