ReactOS  0.4.14-dev-98-gb0d4763
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
22 typedef struct _LOCALMIDIHDR {
28  // MIDI_DD_INPUT_DATA MidiData;
30 
32 
33 #define LOCAL_MIDI_BUFFERS 8
34 
35 typedef struct {
36 
47 
48 
50 
53 
54 
56 
57 
58 typedef 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
85  } GetSetData;
86 
87  } AuxParam;
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 
99 PMIDIALLOC MidiHandleList; // Our chain of wave handles
100 
101 
102 
103 static DWORD OpenMidiDevice(UINT DeviceType, DWORD ID, DWORD User, DWORD Param1, DWORD Param2)
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 
127  if (DeviceType == MidiInDevice)
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 
159  if (DeviceType == MidiInDevice)
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 
201  Length, NULL, 0, &BytesReturned, NULL))
202  return TranslateStatus();
203 
204  return MMSYSERR_NOERROR;
205 }
206 
207 
208 static 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 
251 APIENTRY 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:
290  return MMSYSERR_NOTSUPPORTED;
291  }
292 
293  // the function should never get to this point
294  //FIXME: Would it be wise to assert here?
295  return MMSYSERR_NOTSUPPORTED;
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");
317  return MMSYSERR_NOTSUPPORTED;
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");
333  return MMSYSERR_NOTSUPPORTED;
334 
335  case MODM_RESET:
336  DPRINT("MODM_RESET");
337  return MMSYSERR_NOTSUPPORTED;
338 
339  case MODM_SETVOLUME:
340  DPRINT("MODM_SETVOLUME");
341  return MMSYSERR_NOTSUPPORTED;
342 
343  case MODM_GETVOLUME:
344  DPRINT("MODM_GETVOLUME");
345  return MMSYSERR_NOTSUPPORTED;
346 
347  case MODM_CACHEPATCHES:
348  DPRINT("MODM_CACHEPATCHES");
349  return MMSYSERR_NOTSUPPORTED;
350 
352  DPRINT("MODM_CACHEDRUMPATCHES");
353  return MMSYSERR_NOTSUPPORTED;
354 
355  };
356 
357  return MMSYSERR_NOTSUPPORTED;
358 }
#define CreateEvent
Definition: winbase.h:3572
UINT DeviceNumber
Definition: midi.c:60
HANDLE Event
Definition: midi.c:74
int l
Definition: midi.c:95
#define MIDM_CLOSE
Definition: mmddk.h:172
struct _LOCALMIDIHDR * PLOCALMIDIHDR
PLOCALMIDIHDR DeviceQueue
Definition: midi.c:49
union tag_MIDIALLOC::@449 AuxParam
PVOID pClient
Definition: midi.c:27
#define LOCAL_DATA_SIZE
Definition: midi.c:21
DeviceType
Definition: mmdrv.h:41
UINT DeviceType
Definition: midi.c:61
#define MODM_LONGDATA
Definition: mmddk.h:161
LPMIDIHDR lpMIQueue
Definition: midi.c:66
struct tag_MIDIALLOC * Next
Definition: midi.c:59
DWORD BytesReturned
Definition: midi.c:24
UINT MMRESULT
Definition: mmsystem.h:962
BOOLEAN fSysex
Definition: midi.c:41
LPMIDIHDR pHdr
Definition: midi.c:79
#define MIDM_START
Definition: mmddk.h:176
#define MIDM_RESET
Definition: mmddk.h:178
APIENTRY DWORD modMessage(DWORD ID, DWORD Message, DWORD User, DWORD Param1, DWORD Param2)
Definition: midi.c:298
static DWORD WriteMidi(PBYTE pData, ULONG Length, PMIDIALLOC pClient)
Definition: midi.c:194
#define IOCTL_MIDI_PLAY
Definition: mmdef.h:74
static int GetMidiLength(PMIDIALLOC pClient, BYTE b)
Definition: midi.c:208
#define MIDM_GETNUMDEVS
Definition: mmddk.h:169
BYTE bBytePos
Definition: midi.c:44
struct _LOCALMIDIHDR LOCALMIDIHDR
#define MODM_GETDEVCAPS
Definition: mmddk.h:155
PBYTE pData
Definition: midi.c:83
DWORD dwCurData
Definition: midi.c:39
#define LOCAL_MIDI_BUFFERS
Definition: midi.c:33
#define MIDM_GETDEVCAPS
Definition: mmddk.h:170
struct tag_MIDIALLOC * PMIDIALLOC
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
#define MMSYSERR_NOMEM
Definition: mmsystem.h:103
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
DWORD AuxReturnCode
Definition: midi.c:92
MMRESULT OpenDevice(DeviceInfo **private_data, MIDIOPENDESC *open_desc, DWORD flags)
Definition: beepmidi.c:264
unsigned char * LPBYTE
Definition: typedefs.h:52
LOCALMIDIHDR Bufs[LOCAL_MIDI_BUFFERS]
Definition: midi.c:52
unsigned int BOOL
Definition: ntddk_ex.h:94
BOOLEAN Bad
Definition: midi.c:42
BYTE ExtraData[LOCAL_DATA_SIZE - sizeof(ULONG)]
Definition: midi.c:29
#define GENERIC_WRITE
Definition: nt_native.h:90
DWORD dwMsgTime
Definition: midi.c:46
OVERLAPPED Ovl
Definition: midi.c:23
ULONG Function
Definition: midi.c:82
struct tag_MIDIALLOC::@449::@450 GetSetData
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
_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:426
void DPRINT(...)
Definition: polytest.cpp:61
HANDLE AuxEvent2
Definition: midi.c:91
#define MODM_GETNUMDEVS
Definition: mmddk.h:154
#define MODM_CLOSE
Definition: mmddk.h:157
DWORD TranslateStatus(void)
Definition: utils.c:30
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
#define MMSYSERR_NOERROR
Definition: mmsystem.h:96
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
#define MODM_CACHEDRUMPATCHES
Definition: mmddk.h:166
ULONG State
Definition: midi.c:80
unsigned long DWORD
Definition: ntddk_ex.h:95
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
HANDLE ThreadHandle
Definition: midi.c:89
#define MMSYSERR_NOTSUPPORTED
Definition: mmsystem.h:104
#define MODM_OPEN
Definition: mmddk.h:156
struct _LOCALMIDIHDR * lpNext
Definition: midi.c:25
CHAR Message[80]
Definition: alive.c:5
HANDLE AuxEvent1
Definition: midi.c:90
ULONG DataLen
Definition: midi.c:84
DWORD dwFlags
Definition: midi.c:93
PLOCALMIDIDATA Mid
Definition: midi.c:94
HANDLE DeviceHandle
Definition: midi.c:65
unsigned char BYTE
Definition: mem.h:68
#define MODM_RESET
Definition: mmddk.h:162
struct MIDIOPENDESC * LPMIDIOPENDESC
#define GENERIC_READ
Definition: compat.h:124
BYTE status
Definition: midi.c:40
#define ID
Definition: ruserpass.c:36
BOOL Done
Definition: midi.c:26
#define MODM_CACHEPATCHES
Definition: mmddk.h:165
HMIDI hMidi
Definition: midi.c:64
DWORD dwCallback
Definition: midi.c:62
#define MIDM_OPEN
Definition: mmddk.h:171
#define MODM_DATA
Definition: mmddk.h:160
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 MIDM_ADDBUFFER
Definition: mmddk.h:175
_In_ FILTER_INFORMATION_CLASS _In_ ULONG _Out_ PULONG BytesReturned
Definition: fltkernel.h:1716
DWORD dwInstance
Definition: midi.c:63
unsigned int UINT
Definition: ndis.h:50
BOOL fMidiInStarted
Definition: midi.c:37
struct LOCALMIDIDATA * PLOCALMIDIDATA
DWORD dwCurTime
Definition: midi.c:45
DWORD GetDeviceCount(DeviceType device_type)
Definition: common.c:58
struct tag_MIDIALLOC MIDIALLOC
static DWORD OpenMidiDevice(UINT DeviceType, DWORD ID, DWORD User, DWORD Param1, DWORD Param2)
Definition: midi.c:103
BYTE bBytesLeft
Definition: midi.c:43
#define MIDM_STOP
Definition: mmddk.h:177
unsigned int ULONG
Definition: retypes.h:1
APIENTRY DWORD midMessage(DWORD dwId, DWORD dwMessage, DWORD dwUser, DWORD dwParam1, DWORD dwParam2)
Definition: midi.c:251
PMIDIALLOC MidiHandleList
Definition: midi.c:99
#define MODM_GETVOLUME
Definition: mmddk.h:163
TW_UINT32 TW_UINT16 TW_UINT16 TW_MEMREF pData
Definition: twain.h:1827
#define INFINITE
Definition: serial.h:102
#define MODM_SETVOLUME
Definition: mmddk.h:164
DWORD dwMsg
Definition: midi.c:38
#define memset(x, y, z)
Definition: compat.h:39
MMRESULT GetDeviceCapabilities(MIDIOUTCAPS *caps)
Definition: beepmidi.c:210
BYTE * PBYTE
Definition: pedump.c:66
#define APIENTRY
Definition: api.h:79