Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenmidi.c
Go to the documentation of this file.
00001 /* 00002 * 00003 * COPYRIGHT: See COPYING in the top level directory 00004 * PROJECT: ReactOS Multimedia 00005 * FILE: lib/mmdrv/midi.c 00006 * PURPOSE: Multimedia User Mode Driver 00007 * PROGRAMMER: Andrew Greenwood 00008 * UPDATE HISTORY: 00009 * Jan 30, 2004: Imported into ReactOS tree 00010 */ 00011 00012 #include "mmdrv.h" 00013 #include "wave.h" 00014 00015 #define NDEBUG 00016 #include <debug.h> 00017 00018 // MIDI device instance information 00019 // 00020 #define LOCAL_DATA_SIZE 20 00021 typedef struct _LOCALMIDIHDR { 00022 OVERLAPPED Ovl; 00023 DWORD BytesReturned; 00024 struct _LOCALMIDIHDR *lpNext; 00025 BOOL Done; 00026 PVOID pClient; 00027 // MIDI_DD_INPUT_DATA MidiData; 00028 BYTE ExtraData[LOCAL_DATA_SIZE - sizeof(ULONG)]; 00029 00030 } LOCALMIDIHDR, *PLOCALMIDIHDR; 00031 00032 #define LOCAL_MIDI_BUFFERS 8 00033 00034 typedef struct { 00035 00036 BOOL fMidiInStarted; 00037 DWORD dwMsg; 00038 DWORD dwCurData; 00039 BYTE status; 00040 BOOLEAN fSysex; 00041 BOOLEAN Bad; 00042 BYTE bBytesLeft; 00043 BYTE bBytePos; 00044 DWORD dwCurTime; 00045 DWORD dwMsgTime; 00046 00047 00048 PLOCALMIDIHDR DeviceQueue; 00049 00050 LOCALMIDIHDR 00051 Bufs[LOCAL_MIDI_BUFFERS]; 00052 00053 00054 } LOCALMIDIDATA, *PLOCALMIDIDATA; 00055 00056 00057 typedef struct tag_MIDIALLOC { 00058 struct tag_MIDIALLOC *Next; // Chain of devices 00059 UINT DeviceNumber; // Number of device 00060 UINT DeviceType; // MidiInput or MidiOutput 00061 DWORD dwCallback; // client's callback 00062 DWORD dwInstance; // client's instance data 00063 HMIDI hMidi; // handle for stream 00064 HANDLE DeviceHandle; // Midi device handle 00065 LPMIDIHDR lpMIQueue; // Buffers sent to device 00066 // This is only required so that 00067 // CLOSE knows when things have 00068 // really finished. 00069 // notify. This is only accessed 00070 // on the device thread and its 00071 // apcs so does not need any 00072 // synchronized access. 00073 HANDLE Event; // Event for driver syncrhonization 00074 // and notification of auxiliary 00075 // task operation completion. 00076 // MIDITHREADFUNCTION AuxFunction; // Function for thread to perform 00077 union { 00078 LPMIDIHDR pHdr; // Buffer to pass in aux task 00079 ULONG State; // State to set 00080 struct { 00081 ULONG Function; // IOCTL to use 00082 PBYTE pData; // Data to set or get 00083 ULONG DataLen; // Length of data 00084 } GetSetData; 00085 00086 } AuxParam; 00087 // 0 means terminate task. 00088 HANDLE ThreadHandle; // Handle for termination ONLY 00089 HANDLE AuxEvent1; // Aux thread waits on this 00090 HANDLE AuxEvent2; // Aux thread caller waits on this 00091 DWORD AuxReturnCode; // Return code from Aux task 00092 DWORD dwFlags; // Open flags 00093 PLOCALMIDIDATA Mid; // Extra midi input structures 00094 int l; // Helper global for modMidiLength 00095 00096 } MIDIALLOC, *PMIDIALLOC; 00097 00098 PMIDIALLOC MidiHandleList; // Our chain of wave handles 00099 00100 00101 00102 static DWORD OpenMidiDevice(UINT DeviceType, DWORD ID, DWORD User, DWORD Param1, DWORD Param2) 00103 { 00104 PMIDIALLOC pClient = NULL; 00105 MMRESULT Result = MMSYSERR_NOERROR; 00106 00107 // Check ID? 00108 DPRINT("OpenMidiDevice()\n"); 00109 00110 switch(DeviceType) 00111 { 00112 case MidiOutDevice : 00113 pClient = (PMIDIALLOC) HeapAlloc(Heap, 0, sizeof(MIDIALLOC)); 00114 if ( pClient ) memset(pClient, 0, sizeof(MIDIALLOC)); 00115 break; 00116 00117 case MidiInDevice : 00118 pClient = (PMIDIALLOC) HeapAlloc(Heap, 0, sizeof(MIDIALLOC) + sizeof(LOCALMIDIDATA)); 00119 if ( pClient ) memset(pClient, 0, sizeof(MIDIALLOC) + sizeof(LOCALMIDIDATA)); 00120 break; 00121 }; 00122 00123 if ( !pClient ) 00124 return MMSYSERR_NOMEM; 00125 00126 if (DeviceType == MidiInDevice) 00127 { 00128 int i; 00129 pClient->Mid = (PLOCALMIDIDATA)(pClient + 1); 00130 for (i = 0 ;i < LOCAL_MIDI_BUFFERS ; i++) 00131 { 00132 pClient->Mid->Bufs[i].pClient = pClient; 00133 } 00134 } 00135 00136 pClient->DeviceType = DeviceType; 00137 pClient->dwCallback = ((LPMIDIOPENDESC)Param1)->dwCallback; 00138 pClient->dwInstance = ((LPMIDIOPENDESC)Param1)->dwInstance; 00139 pClient->hMidi = ((LPMIDIOPENDESC)Param1)->hMidi; 00140 pClient->dwFlags = Param2; 00141 00142 Result = OpenDevice(DeviceType, ID, &pClient->DeviceHandle, (GENERIC_READ | GENERIC_WRITE)); 00143 00144 if ( Result != MMSYSERR_NOERROR ) 00145 { 00146 // cleanup 00147 return Result; 00148 } 00149 00150 pClient->Event = CreateEvent(NULL, FALSE, FALSE, NULL); 00151 00152 if ( !pClient->Event ) 00153 { 00154 // cleanup 00155 return MMSYSERR_NOMEM; 00156 } 00157 00158 if (DeviceType == MidiInDevice) 00159 { 00160 00161 pClient->AuxEvent1 = CreateEvent(NULL, FALSE, FALSE, NULL); 00162 if (pClient->AuxEvent1 == NULL) 00163 { 00164 // cleanup 00165 return MMSYSERR_NOMEM; 00166 } 00167 00168 pClient->AuxEvent2 = CreateEvent(NULL, FALSE, FALSE, NULL); 00169 if (pClient->AuxEvent2 == NULL) 00170 { 00171 // cleanup 00172 return MMSYSERR_NOMEM; 00173 } 00174 00175 00176 // TaskCreate 00177 00178 00179 WaitForSingleObject(pClient->AuxEvent2, INFINITE); 00180 } 00181 00182 PMIDIALLOC *pUserHandle; 00183 pUserHandle = (PMIDIALLOC*) User; 00184 *pUserHandle = pClient; 00185 00186 // callback 00187 00188 return MMSYSERR_NOERROR; 00189 } 00190 00191 00192 00193 static DWORD WriteMidi(PBYTE pData, ULONG Length, PMIDIALLOC pClient) 00194 { 00195 DWORD BytesReturned; 00196 00197 DPRINT("IOCTL_MIDI_PLAY == %d [%x]\n", IOCTL_MIDI_PLAY, IOCTL_MIDI_PLAY); 00198 00199 if ( !DeviceIoControl(pClient->DeviceHandle, IOCTL_MIDI_PLAY, (PVOID)pData, 00200 Length, NULL, 0, &BytesReturned, NULL)) 00201 return TranslateStatus(); 00202 00203 return MMSYSERR_NOERROR; 00204 } 00205 00206 00207 static int GetMidiLength(PMIDIALLOC pClient, BYTE b) 00208 { 00209 if (b >= 0xF8) 00210 { 00211 // Realtime message - leave running status 00212 return 1; // Write one byte 00213 } 00214 00215 switch (b) 00216 { 00217 case 0xF0: case 0xF4: case 0xF5: case 0xF6: case 0xF7: 00218 pClient->l = 1; 00219 return pClient->l; 00220 00221 case 0xF1: case 0xF3: 00222 pClient->l = 2; 00223 return pClient->l; 00224 00225 case 0xF2: 00226 pClient->l = 3; 00227 return pClient->l; 00228 } 00229 00230 switch (b & 0xF0) 00231 { 00232 case 0x80: case 0x90: case 0xA0: case 0xB0: case 0xE0: 00233 pClient->l = 3; 00234 return pClient->l; 00235 00236 case 0xC0: case 0xD0: 00237 pClient->l = 2; 00238 return pClient->l; 00239 } 00240 00241 return (pClient->l - 1); // uses previous value if data byte (running status) 00242 } 00243 00244 00245 00246 /* ---------------------------------------------------------------------------- 00247 Exported functions 00248 ----------------------------------------------------------------------------- */ 00249 00250 APIENTRY DWORD midMessage(DWORD dwId, DWORD dwMessage, DWORD dwUser, DWORD dwParam1, DWORD dwParam2) 00251 { 00252 DPRINT("midMessage\n"); 00253 return MMSYSERR_NOERROR; 00254 00255 switch (dwMessage) { 00256 case MIDM_GETNUMDEVS: 00257 DPRINT("MIDM_GETNUMDEVS"); 00258 return GetDeviceCount(MidiInDevice); 00259 00260 case MIDM_GETDEVCAPS: 00261 DPRINT("MIDM_GETDEVCAPS"); 00262 return GetDeviceCapabilities(dwId, MidiInDevice, (LPBYTE)dwParam1, (DWORD)dwParam2); 00263 00264 case MIDM_OPEN: 00265 DPRINT("MIDM_OPEN"); 00266 return MMSYSERR_NOERROR; 00267 00268 case MIDM_CLOSE: 00269 DPRINT("MIDM_CLOSE"); 00270 return MMSYSERR_NOERROR; 00271 00272 case MIDM_ADDBUFFER: 00273 DPRINT("MIDM_ADDBUFFER"); 00274 return MMSYSERR_NOERROR; 00275 00276 case MIDM_STOP: 00277 DPRINT("MIDM_PAUSE"); 00278 return MMSYSERR_NOERROR; 00279 00280 case MIDM_START: 00281 DPRINT("MIDM_RESTART"); 00282 return MMSYSERR_NOERROR; 00283 00284 case MIDM_RESET: 00285 DPRINT("MIDM_RESET"); 00286 return MMSYSERR_NOERROR; 00287 00288 default: 00289 return MMSYSERR_NOTSUPPORTED; 00290 } 00291 00292 // the function should never get to this point 00293 //FIXME: Would it be wise to assert here? 00294 return MMSYSERR_NOTSUPPORTED; 00295 } 00296 00297 APIENTRY DWORD modMessage(DWORD ID, DWORD Message, DWORD User, DWORD Param1, DWORD Param2) 00298 { 00299 DPRINT("modMessage\n"); 00300 00301 switch(Message) 00302 { 00303 case MODM_GETNUMDEVS: 00304 DPRINT("MODM_GETNUMDEVS == %d\n", (int)GetDeviceCount(MidiOutDevice)); 00305 return GetDeviceCount(MidiOutDevice); 00306 00307 case MODM_GETDEVCAPS: 00308 DPRINT("MODM_GETDEVCAPS"); 00309 return GetDeviceCapabilities(ID, MidiOutDevice, (LPBYTE)Param1, (DWORD)Param2); 00310 00311 case MODM_OPEN : 00312 return OpenMidiDevice(MidiOutDevice, ID, User, Param1, Param2); 00313 00314 case MODM_CLOSE: 00315 DPRINT("MODM_CLOSE"); 00316 return MMSYSERR_NOTSUPPORTED; 00317 00318 case MODM_DATA: 00319 DPRINT("MODM_DATA"); 00320 00321 int i; 00322 BYTE b[4]; 00323 for (i = 0; i < 4; i ++) { 00324 b[i] = (BYTE)(Param1 % 256); 00325 Param1 /= 256; 00326 } 00327 return WriteMidi(b, GetMidiLength((PMIDIALLOC)User, b[0]), 00328 (PMIDIALLOC)User); 00329 00330 case MODM_LONGDATA: 00331 DPRINT("MODM_LONGDATA"); 00332 return MMSYSERR_NOTSUPPORTED; 00333 00334 case MODM_RESET: 00335 DPRINT("MODM_RESET"); 00336 return MMSYSERR_NOTSUPPORTED; 00337 00338 case MODM_SETVOLUME: 00339 DPRINT("MODM_SETVOLUME"); 00340 return MMSYSERR_NOTSUPPORTED; 00341 00342 case MODM_GETVOLUME: 00343 DPRINT("MODM_GETVOLUME"); 00344 return MMSYSERR_NOTSUPPORTED; 00345 00346 case MODM_CACHEPATCHES: 00347 DPRINT("MODM_CACHEPATCHES"); 00348 return MMSYSERR_NOTSUPPORTED; 00349 00350 case MODM_CACHEDRUMPATCHES: 00351 DPRINT("MODM_CACHEDRUMPATCHES"); 00352 return MMSYSERR_NOTSUPPORTED; 00353 00354 }; 00355 00356 return MMSYSERR_NOTSUPPORTED; 00357 } Generated on Sun May 27 2012 04:24:41 for ReactOS by
1.7.6.1
|