ReactOS 0.4.15-dev-7934-g1dc8d80
midi.c
Go to the documentation of this file.
1/*
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS Multimedia
5 * FILE: lib/mmdrv/midi.c
6 * PURPOSE: Multimedia User Mode Driver
7 * PROGRAMMER: Andrew Greenwood
8 * UPDATE HISTORY:
9 * Jan 30, 2004: Imported into ReactOS tree
10 */
11
12#include "mmdrv.h"
13
14#define NDEBUG
15#include <debug.h>
16
17#include "wave.h"
18
19// MIDI device instance information
20//
21#define LOCAL_DATA_SIZE 20
22typedef struct _LOCALMIDIHDR {
28 // MIDI_DD_INPUT_DATA MidiData;
30
32
33#define LOCAL_MIDI_BUFFERS 8
34
35typedef struct {
36
47
48
50
53
54
56
57
58typedef struct tag_MIDIALLOC {
59 struct tag_MIDIALLOC *Next; // Chain of devices
60 UINT DeviceNumber; // Number of device
61 UINT DeviceType; // MidiInput or MidiOutput
62 DWORD dwCallback; // client's callback
63 DWORD dwInstance; // client's instance data
64 HMIDI hMidi; // handle for stream
65 HANDLE DeviceHandle; // Midi device handle
66 LPMIDIHDR lpMIQueue; // Buffers sent to device
67 // This is only required so that
68 // CLOSE knows when things have
69 // really finished.
70 // notify. This is only accessed
71 // on the device thread and its
72 // apcs so does not need any
73 // synchronized access.
74 HANDLE Event; // Event for driver synchronization
75 // and notification of auxiliary
76 // task operation completion.
77// MIDITHREADFUNCTION AuxFunction; // Function for thread to perform
78 union {
79 LPMIDIHDR pHdr; // Buffer to pass in aux task
80 ULONG State; // State to set
81 struct {
82 ULONG Function; // IOCTL to use
83 PBYTE pData; // Data to set or get
84 ULONG DataLen; // Length of data
86
88 // 0 means terminate task.
89 HANDLE ThreadHandle; // Handle for termination ONLY
90 HANDLE AuxEvent1; // Aux thread waits on this
91 HANDLE AuxEvent2; // Aux thread caller waits on this
92 DWORD AuxReturnCode; // Return code from Aux task
93 DWORD dwFlags; // Open flags
94 PLOCALMIDIDATA Mid; // Extra midi input structures
95 int l; // Helper global for modMidiLength
96
98
99PMIDIALLOC MidiHandleList; // Our chain of wave handles
100
101
102
104{
105 PMIDIALLOC pClient = NULL;
107
108 // Check ID?
109 DPRINT("OpenMidiDevice()\n");
110
111 switch(DeviceType)
112 {
113 case MidiOutDevice :
114 pClient = (PMIDIALLOC) HeapAlloc(Heap, 0, sizeof(MIDIALLOC));
115 if ( pClient ) memset(pClient, 0, sizeof(MIDIALLOC));
116 break;
117
118 case MidiInDevice :
119 pClient = (PMIDIALLOC) HeapAlloc(Heap, 0, sizeof(MIDIALLOC) + sizeof(LOCALMIDIDATA));
120 if ( pClient ) memset(pClient, 0, sizeof(MIDIALLOC) + sizeof(LOCALMIDIDATA));
121 break;
122 };
123
124 if ( !pClient )
125 return MMSYSERR_NOMEM;
126
128 {
129 int i;
130 pClient->Mid = (PLOCALMIDIDATA)(pClient + 1);
131 for (i = 0 ;i < LOCAL_MIDI_BUFFERS ; i++)
132 {
133 pClient->Mid->Bufs[i].pClient = pClient;
134 }
135 }
136
137 pClient->DeviceType = DeviceType;
138 pClient->dwCallback = ((LPMIDIOPENDESC)Param1)->dwCallback;
139 pClient->dwInstance = ((LPMIDIOPENDESC)Param1)->dwInstance;
140 pClient->hMidi = ((LPMIDIOPENDESC)Param1)->hMidi;
141 pClient->dwFlags = Param2;
142
144
145 if ( Result != MMSYSERR_NOERROR )
146 {
147 // cleanup
148 return Result;
149 }
150
151 pClient->Event = CreateEvent(NULL, FALSE, FALSE, NULL);
152
153 if ( !pClient->Event )
154 {
155 // cleanup
156 return MMSYSERR_NOMEM;
157 }
158
160 {
161
162 pClient->AuxEvent1 = CreateEvent(NULL, FALSE, FALSE, NULL);
163 if (pClient->AuxEvent1 == NULL)
164 {
165 // cleanup
166 return MMSYSERR_NOMEM;
167 }
168
169 pClient->AuxEvent2 = CreateEvent(NULL, FALSE, FALSE, NULL);
170 if (pClient->AuxEvent2 == NULL)
171 {
172 // cleanup
173 return MMSYSERR_NOMEM;
174 }
175
176
177 // TaskCreate
178
179
181 }
182
183 PMIDIALLOC *pUserHandle;
184 pUserHandle = (PMIDIALLOC*) User;
185 *pUserHandle = pClient;
186
187 // callback
188
189 return MMSYSERR_NOERROR;
190}
191
192
193
195{
197
198 DPRINT("IOCTL_MIDI_PLAY == %d [%x]\n", IOCTL_MIDI_PLAY, IOCTL_MIDI_PLAY);
199
202 return TranslateStatus();
203
204 return MMSYSERR_NOERROR;
205}
206
207
208static int GetMidiLength(PMIDIALLOC pClient, BYTE b)
209{
210 if (b >= 0xF8)
211 {
212 // Realtime message - leave running status
213 return 1; // Write one byte
214 }
215
216 switch (b)
217 {
218 case 0xF0: case 0xF4: case 0xF5: case 0xF6: case 0xF7:
219 pClient->l = 1;
220 return pClient->l;
221
222 case 0xF1: case 0xF3:
223 pClient->l = 2;
224 return pClient->l;
225
226 case 0xF2:
227 pClient->l = 3;
228 return pClient->l;
229 }
230
231 switch (b & 0xF0)
232 {
233 case 0x80: case 0x90: case 0xA0: case 0xB0: case 0xE0:
234 pClient->l = 3;
235 return pClient->l;
236
237 case 0xC0: case 0xD0:
238 pClient->l = 2;
239 return pClient->l;
240 }
241
242 return (pClient->l - 1); // uses previous value if data byte (running status)
243}
244
245
246
247/* ----------------------------------------------------------------------------
248 Exported functions
249----------------------------------------------------------------------------- */
250
251APIENTRY DWORD midMessage(DWORD dwId, DWORD dwMessage, DWORD dwUser, DWORD dwParam1, DWORD dwParam2)
252{
253 DPRINT("midMessage\n");
254 return MMSYSERR_NOERROR;
255
256 switch (dwMessage) {
257 case MIDM_GETNUMDEVS:
258 DPRINT("MIDM_GETNUMDEVS");
260
261 case MIDM_GETDEVCAPS:
262 DPRINT("MIDM_GETDEVCAPS");
263 return GetDeviceCapabilities(dwId, MidiInDevice, (LPBYTE)dwParam1, (DWORD)dwParam2);
264
265 case MIDM_OPEN:
266 DPRINT("MIDM_OPEN");
267 return MMSYSERR_NOERROR;
268
269 case MIDM_CLOSE:
270 DPRINT("MIDM_CLOSE");
271 return MMSYSERR_NOERROR;
272
273 case MIDM_ADDBUFFER:
274 DPRINT("MIDM_ADDBUFFER");
275 return MMSYSERR_NOERROR;
276
277 case MIDM_STOP:
278 DPRINT("MIDM_PAUSE");
279 return MMSYSERR_NOERROR;
280
281 case MIDM_START:
282 DPRINT("MIDM_RESTART");
283 return MMSYSERR_NOERROR;
284
285 case MIDM_RESET:
286 DPRINT("MIDM_RESET");
287 return MMSYSERR_NOERROR;
288
289 default:
291 }
292
293 // the function should never get to this point
294 //FIXME: Would it be wise to assert here?
296}
297
299{
300 DPRINT("modMessage\n");
301
302 switch(Message)
303 {
304 case MODM_GETNUMDEVS:
305 DPRINT("MODM_GETNUMDEVS == %d\n", (int)GetDeviceCount(MidiOutDevice));
307
308 case MODM_GETDEVCAPS:
309 DPRINT("MODM_GETDEVCAPS");
310 return GetDeviceCapabilities(ID, MidiOutDevice, (LPBYTE)Param1, (DWORD)Param2);
311
312 case MODM_OPEN :
313 return OpenMidiDevice(MidiOutDevice, ID, User, Param1, Param2);
314
315 case MODM_CLOSE:
316 DPRINT("MODM_CLOSE");
318
319 case MODM_DATA:
320 DPRINT("MODM_DATA");
321
322 int i;
323 BYTE b[4];
324 for (i = 0; i < 4; i ++) {
325 b[i] = (BYTE)(Param1 % 256);
326 Param1 /= 256;
327 }
328 return WriteMidi(b, GetMidiLength((PMIDIALLOC)User, b[0]),
329 (PMIDIALLOC)User);
330
331 case MODM_LONGDATA:
332 DPRINT("MODM_LONGDATA");
334
335 case MODM_RESET:
336 DPRINT("MODM_RESET");
338
339 case MODM_SETVOLUME:
340 DPRINT("MODM_SETVOLUME");
342
343 case MODM_GETVOLUME:
344 DPRINT("MODM_GETVOLUME");
346
348 DPRINT("MODM_CACHEPATCHES");
350
352 DPRINT("MODM_CACHEDRUMPATCHES");
354
355 };
356
358}
unsigned char BOOLEAN
MMRESULT GetDeviceCapabilities(MIDIOUTCAPS *caps)
Definition: beepmidi.c:210
MMRESULT OpenDevice(DeviceInfo **private_data, MIDIOPENDESC *open_desc, DWORD flags)
Definition: beepmidi.c:264
BOOL WINAPI DeviceIoControl(IN HANDLE hDevice, IN DWORD dwIoControlCode, IN LPVOID lpInBuffer OPTIONAL, IN DWORD nInBufferSize OPTIONAL, OUT LPVOID lpOutBuffer OPTIONAL, IN DWORD nOutBufferSize OPTIONAL, OUT LPDWORD lpBytesReturned OPTIONAL, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: deviceio.c:136
#define NULL
Definition: types.h:112
#define FALSE
Definition: types.h:117
#define APIENTRY
Definition: api.h:79
#define HeapAlloc
Definition: compat.h:733
#define GENERIC_READ
Definition: compat.h:135
DWORD GetDeviceCount(DeviceType device_type)
Definition: common.c:58
struct _LOCALMIDIHDR * PLOCALMIDIHDR
struct tag_MIDIALLOC * PMIDIALLOC
struct LOCALMIDIDATA * PLOCALMIDIDATA
struct tag_MIDIALLOC MIDIALLOC
static DWORD WriteMidi(PBYTE pData, ULONG Length, PMIDIALLOC pClient)
Definition: midi.c:194
PMIDIALLOC MidiHandleList
Definition: midi.c:99
APIENTRY DWORD midMessage(DWORD dwId, DWORD dwMessage, DWORD dwUser, DWORD dwParam1, DWORD dwParam2)
Definition: midi.c:251
struct _LOCALMIDIHDR LOCALMIDIHDR
APIENTRY DWORD modMessage(DWORD ID, DWORD Message, DWORD User, DWORD Param1, DWORD Param2)
Definition: midi.c:298
#define LOCAL_MIDI_BUFFERS
Definition: midi.c:33
static DWORD OpenMidiDevice(UINT DeviceType, DWORD ID, DWORD User, DWORD Param1, DWORD Param2)
Definition: midi.c:103
static int GetMidiLength(PMIDIALLOC pClient, BYTE b)
Definition: midi.c:208
#define LOCAL_DATA_SIZE
Definition: midi.c:21
#define MODM_GETDEVCAPS
Definition: mmddk.h:155
#define MIDM_OPEN
Definition: mmddk.h:171
#define MIDM_START
Definition: mmddk.h:176
#define MIDM_ADDBUFFER
Definition: mmddk.h:175
#define MIDM_RESET
Definition: mmddk.h:178
#define MIDM_STOP
Definition: mmddk.h:177
struct MIDIOPENDESC * LPMIDIOPENDESC
#define MODM_CACHEDRUMPATCHES
Definition: mmddk.h:166
#define MODM_RESET
Definition: mmddk.h:162
#define MODM_GETNUMDEVS
Definition: mmddk.h:154
#define MODM_DATA
Definition: mmddk.h:160
#define MODM_GETVOLUME
Definition: mmddk.h:163
#define MODM_OPEN
Definition: mmddk.h:156
#define MODM_SETVOLUME
Definition: mmddk.h:164
#define MIDM_CLOSE
Definition: mmddk.h:172
#define MIDM_GETDEVCAPS
Definition: mmddk.h:170
#define MIDM_GETNUMDEVS
Definition: mmddk.h:169
#define MODM_LONGDATA
Definition: mmddk.h:161
#define MODM_CLOSE
Definition: mmddk.h:157
#define MODM_CACHEPATCHES
Definition: mmddk.h:165
DWORD TranslateStatus(void)
Definition: utils.c:30
static const WCHAR Message[]
Definition: register.c:74
#define INFINITE
Definition: serial.h:102
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define IOCTL_MIDI_PLAY
Definition: mmdef.h:74
DeviceType
Definition: mmdrv.h:42
@ MidiOutDevice
Definition: mmdrv.h:45
@ MidiInDevice
Definition: mmdrv.h:46
#define MMSYSERR_NOMEM
Definition: mmsystem.h:103
UINT MMRESULT
Definition: mmsystem.h:962
#define MMSYSERR_NOTSUPPORTED
Definition: mmsystem.h:104
#define MMSYSERR_NOERROR
Definition: mmsystem.h:96
unsigned int UINT
Definition: ndis.h:50
#define GENERIC_WRITE
Definition: nt_native.h:90
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
BYTE * PBYTE
Definition: pedump.c:66
#define ID
Definition: ruserpass.c:36
#define memset(x, y, z)
Definition: compat.h:39
#define DPRINT
Definition: sndvol32.h:71
BYTE status
Definition: midi.c:40
BOOL fMidiInStarted
Definition: midi.c:37
DWORD dwMsg
Definition: midi.c:38
PLOCALMIDIHDR DeviceQueue
Definition: midi.c:49
BOOLEAN fSysex
Definition: midi.c:41
BYTE bBytesLeft
Definition: midi.c:43
BYTE bBytePos
Definition: midi.c:44
DWORD dwCurData
Definition: midi.c:39
BOOLEAN Bad
Definition: midi.c:42
DWORD dwMsgTime
Definition: midi.c:46
DWORD dwCurTime
Definition: midi.c:45
LOCALMIDIHDR Bufs[LOCAL_MIDI_BUFFERS]
Definition: midi.c:52
BYTE ExtraData[LOCAL_DATA_SIZE - sizeof(ULONG)]
Definition: midi.c:29
DWORD BytesReturned
Definition: midi.c:24
PVOID pClient
Definition: midi.c:27
OVERLAPPED Ovl
Definition: midi.c:23
BOOL Done
Definition: midi.c:26
struct _LOCALMIDIHDR * lpNext
Definition: midi.c:25
struct tag_MIDIALLOC * Next
Definition: midi.c:59
HANDLE ThreadHandle
Definition: midi.c:89
PLOCALMIDIDATA Mid
Definition: midi.c:94
HANDLE DeviceHandle
Definition: midi.c:65
struct tag_MIDIALLOC::@468::@469 GetSetData
LPMIDIHDR lpMIQueue
Definition: midi.c:66
HANDLE AuxEvent2
Definition: midi.c:91
DWORD AuxReturnCode
Definition: midi.c:92
HMIDI hMidi
Definition: midi.c:64
ULONG DataLen
Definition: midi.c:84
int l
Definition: midi.c:95
LPMIDIHDR pHdr
Definition: midi.c:79
DWORD dwInstance
Definition: midi.c:63
UINT DeviceType
Definition: midi.c:61
UINT DeviceNumber
Definition: midi.c:60
PBYTE pData
Definition: midi.c:83
HANDLE Event
Definition: midi.c:74
ULONG Function
Definition: midi.c:82
HANDLE AuxEvent1
Definition: midi.c:90
DWORD dwCallback
Definition: midi.c:62
union tag_MIDIALLOC::@468 AuxParam
DWORD dwFlags
Definition: midi.c:93
ULONG State
Definition: midi.c:80
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
TW_UINT32 TW_UINT16 TW_UINT16 TW_MEMREF pData
Definition: twain.h:1830
unsigned char * LPBYTE
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_ ULONG _In_opt_ PWDF_MEMORY_DESCRIPTOR _In_opt_ PWDF_MEMORY_DESCRIPTOR _In_opt_ PWDF_REQUEST_SEND_OPTIONS _Out_opt_ PULONG_PTR BytesReturned
Definition: wdfiotarget.h:1052
#define CreateEvent
Definition: winbase.h:3748
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:409
unsigned char BYTE
Definition: xxhash.c:193