ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

midi.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.