2 * WinMM (midiout.c) : MIDI output related functions
4 * [8-18-2003] AG: Started adding stubs and implemented a few functions
16 #define IsValidMidiOutHandle(hmo) \
17 (((LPMidiOutHandleInfo*)hmo < mo_HandleInfo) || \
18 ((LPMidiOutHandleInfo*)hmo >= mo_HandleInfo + (mo_HandleCount * sizeof(MidiOutHandleInfo))))
21 LPMidiOutDeviceInfo *mo_DeviceInfo = NULL;
22 UINT mo_DeviceCount = 0;
23 LPMidiOutHandleInfo *mo_HandleInfo = NULL;
24 UINT mo_HandleCount = 0;
27 /* ------------------------------------------------------------------------- */
29 MMRESULT WINAPI midiOutOpen(
33 DWORD dwCallbackInstance,
36 // TODO: Add device open checking and return MMSYSERR_ALLOCATED, but what
37 // happens for multi-client drivers?
38 // Also, MIDI_MAPPER needs to be implemented somehow...
40 MidiOutHandleInfo *Info = NULL;
44 return MMSYSERR_INVALPARAM;
46 if ((uDeviceID >= mo_DeviceCount) && (uDeviceID != MIDI_MAPPER))
47 return MMSYSERR_BADDEVICEID;
49 // Make sure we have a callback address if a callback is desired
50 if ((! dwCallback) && (dwFlags != CALLBACK_NULL))
51 return MMSYSERR_INVALPARAM;
54 // Check existing handles to see if one is free
55 for (i = 0; i < mo_HandleCount; i ++)
56 if (! mo_HandleInfo[i]->IsOpen)
58 Info = mo_HandleInfo[i];
62 // Allocate a new handle info structure
67 LPMidiOutHandleInfo *Old = mo_HandleInfo;
69 // This was before I added file mapping stuff
70 // if (! mo_HandleInfo)
71 // mo_HandleInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(MidiOutHandleInfo) * mo_HandleCount);
73 // mo_HandleInfo = HeapReAlloc(GetProcessHeap(), 0, mo_HandleInfo, sizeof(MidiOutHandleInfo) * mo_HandleCount);
79 return MMSYSERR_NOMEM; // Correct?
82 Info = mo_HandleInfo[mo_HandleCount - 1];
85 Info->DeviceID = uDeviceID;
87 // Pretend we opened OK (really need to query device driver)
92 LPMIDICALLBACK mo_Proc = (LPMIDICALLBACK) dwCallback;
96 case CALLBACK_FUNCTION :
97 mo_Proc((HMIDIOUT) Info, MM_MOM_OPEN, dwCallbackInstance, 0, 0);
100 case CALLBACK_EVENT :
104 case CALLBACK_THREAD :
108 case CALLBACK_WINDOW :
115 return MMSYSERR_ERROR; // Correct if can't be opened?
117 // Copy the handle (really a pointer to Info):
118 *lphmo = (HMIDIOUT) Info;
120 return MMSYSERR_NOERROR;
124 MMRESULT WINAPI midiOutClose(HMIDIOUT hmo)
126 LPMidiOutHandleInfo Info = NULL;
128 if (IsValidMidiOutHandle(hmo))
129 return MMSYSERR_INVALHANDLE;
131 // Check if buffers still queued and return MIDIERR_STILLPLAYING if so...
134 Info = (LPMidiOutHandleInfo) hmo;
135 Info->IsOpen = FALSE;
137 return MMSYSERR_NOERROR;
141 MMRESULT WINAPI midiOutGetDevCaps(
143 LPMIDIOUTCAPS lpMidiOutCaps,
147 return MMSYSERR_NOERROR;
151 MMRESULT WINAPI midiOutGetErrorText(
157 return MMSYSERR_NOERROR;
160 return MMSYSERR_INVALPARAM;
162 if (((mmrError >= MMSYSERR_BASE) && (mmrError <= MMSYSERR_LASTERROR)) ||
163 ((mmrError >= MIDIERR_BASE) && (mmrError <= MIDIERR_LASTERROR)))
165 // LoadString(GetModuleHandle(NULL), mmrError, lpText, cchText); // bytes/chars?
166 return MMSYSERR_NOERROR;
169 return MMSYSERR_BADERRNUM;
173 MMRESULT WINAPI midiOutGetID(
177 // What triggers MMSYSERR_NODRIVER and MMSYSERR_NOMEM error codes?
179 LPMidiOutHandleInfo Info = NULL;
182 return MMSYSERR_INVALPARAM;
184 if (IsValidMidiOutHandle(hmo))
185 return MMSYSERR_INVALHANDLE;
187 Info = (LPMidiOutHandleInfo) hmo;
188 *puDeviceID = Info->DeviceID;
190 return MMSYSERR_NOERROR;
194 UINT WINAPI midiOutGetNumDevs(VOID)
196 // +1 for MIDI_MAPPER :
197 return mo_DeviceCount ? mo_DeviceCount + 1 : 0;
201 MMRESULT WINAPI midiOutSetVolume(
205 if (IsValidMidiOutHandle(hmo))
206 return MMSYSERR_INVALHANDLE;
209 return MMSYSERR_NOERROR;
213 MMRESULT WINAPI midiOutGetVolume(
217 if (IsValidMidiOutHandle(hmo))
218 return MMSYSERR_INVALHANDLE;
221 return MMSYSERR_NOERROR;
225 MMRESULT WINAPI midiOutLongMsg(
227 LPMIDIHDR lpMidiOutHdr,
230 if (IsValidMidiOutHandle(hmo))
231 return MMSYSERR_INVALHANDLE;
234 return MMSYSERR_NOERROR;
238 // This is *supposed* to return a DWORD:
239 MMRESULT WINAPI midiOutMessage(
245 if (IsValidMidiOutHandle(hmo))
246 return MMSYSERR_INVALHANDLE;
253 MMRESULT WINAPI midiOutPrepareHeader(
255 LPMIDIHDR lpMidiOutHdr,
258 if (IsValidMidiOutHandle(hmo))
259 return MMSYSERR_INVALHANDLE;
262 return MMSYSERR_INVALPARAM;
264 if (! lpMidiOutHdr->lpData)
265 return MMSYSERR_INVALPARAM;
267 // Yup, we're prepared! dwFlags must be 0 to begin with, so no | needed:
268 lpMidiOutHdr->dwFlags = MHDR_PREPARED;
270 return MMSYSERR_NOERROR;
274 MMRESULT WINAPI midiOutUnprepareHeader(
276 LPMIDIHDR lpMidiOutHdr,
279 if (IsValidMidiOutHandle(hmo))
280 return MMSYSERR_INVALHANDLE;
283 return MMSYSERR_INVALPARAM;
285 if (! lpMidiOutHdr->lpData)
286 return MMSYSERR_INVALPARAM;
288 // We're unprepared! Clear the MHDR_PREPARED flag:
289 lpMidiOutHdr->dwFlags &= ! MHDR_PREPARED;
291 return MMSYSERR_NOERROR;
295 MMRESULT WINAPI midiOutReset(HMIDIOUT hmo)
297 if (IsValidMidiOutHandle(hmo))
298 return MMSYSERR_INVALHANDLE;
301 return MMSYSERR_NOERROR;
305 MMRESULT WINAPI midiOutShortMsg(
309 if (IsValidMidiOutHandle(hmo))
310 return MMSYSERR_INVALHANDLE;
313 return MMSYSERR_NOERROR;
317 MMRESULT WINAPI midiOutCacheDrumPatches(
324 return MMSYSERR_NOERROR;
328 MMRESULT WINAPI midiOutCachePatches(
335 return MMSYSERR_NOERROR;
339 /* ------------------------------------------------------------------------- */
343 // Internal routine for initializing MIDI-Out related stuff
346 HANDLE modi_fm, mohi_fm;
348 // modi_fm = CreateFileMapping((HANDLE)0xFFFFFFFF, (LPSECURITY_ATTRIBUTES)NULL,
349 // PAGE_READWRITE, 0, 64 * 1024, FM_MIDI_OUT_DEV_INFO);
351 First = ! GetLastError();
353 // mo_DeviceInfo = MapViewOfFile(modi_fm, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(SomeStruct)
357 mo_DeviceInfo = MapViewOfFile(modi_fm, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(MidiOutDeviceInfo));
359 // Just set up a fake device for now
360 mo_DeviceCount ++; // need mapping for this
361 // mo_DeviceInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(MidiOutDeviceInfo) * mo_DeviceCount);
364 UnmapViewOfFile(mo_DeviceInfo);
367 // mohi_fm = CreateFileMapping((HANDLE)0xFFFFFFFF, (LPSECURITY_ATTRIBUTES)NULL,
368 // PAGE_READWRITE, 0, 64 * 1024, FM_MIDI_OUT_HANDLE_INFO);