// Copyright (c) 1998-1999 Microsoft Corporation /* @Doc DMusic16 * * @Module DMusic16.h - Internal definitions for DMusic16.DLL | */ #ifndef __DMUSIC16__ #define __DMUSIC16__ #undef WINAPI #define WINAPI _loadds FAR PASCAL #ifdef WIN32 #define BCODE #define BSTACK #else #define BCODE __based(__segname("_CODE")) #define BSTACK __based(__segname("_STACK")) #endif /* Make symbols show up in debug builds */ #ifdef DEBUG #define STATIC #else #define STATIC static #endif /* MIDI defines */ #define MIDI_CHANNELS 16 #define SZCODE const char BCODE /* Quadword alignment for event lengths in DMEVENT's */ #define QWORD_ALIGN(x) (((x) + 7) & ~7) /* Next highest */ #define QWORD_TRUNC(x) ((x) & ~7) /* Next lowest */ /* Multiplier to convert between reftime and milliseconds */ #define REFTIME_TO_MS (10L*1000L) /* Number of events we want in the capture pool. Based on about a second's worth of high * concentration data */ #define CAP_HIGHWATERMARK 1024 /* How often user-mode timer ticks happen (milliseconds) */ #define MS_USERMODE 1000 /* Typedefs for everyone. Woohoo! */ typedef struct QUADWORD QUADWORD; typedef struct QUADWORD NEAR *NPQUADWORD; typedef struct QUADWORD FAR *LPQUADWORD; typedef struct LINKNODE LINKNODE; typedef struct LINKNODE NEAR *NPLINKNODE; typedef struct LINKNODE FAR *LPLINKNODE; typedef struct DMEVENT DMEVENT; typedef struct DMEVENT NEAR *NPDMEVENT; typedef struct DMEVENT FAR *LPDMEVENT; typedef struct EVENT EVENT; typedef struct EVENT NEAR *NPEVENT; typedef struct EVENT FAR *LPEVENT; typedef struct EVENTQUEUE EVENTQUEUE; typedef struct EVENTQUEUE NEAR *NPEVENTQUEUE; typedef struct EVENTQUEUE FAR *LPEVENTQUEUE; typedef struct OPENHANDLEINSTANCE OPENHANDLEINSTANCE; typedef struct OPENHANDLEINSTANCE NEAR *NPOPENHANDLEINSTANCE; typedef struct OPENHANDLEINSTANCE FAR *LPOPENHANDLEINSTANCE; typedef struct OPENHANDLE OPENHANDLE; typedef struct OPENHANDLE NEAR *NPOPENHANDLE; typedef struct OPENHANDLE FAR *LPOPENHANDLE; typedef struct THRUCHANNEL THRUCHANNEL; typedef struct THRUCHANNEL NEAR *NPTHRUCHANNEL; typedef struct THRUCHANNEL FAR *LPTHRUCHANNEL; /* 64-bit integer used w/ assembly helpers */ struct QUADWORD { DWORD dwLow; DWORD dwHigh; }; /* @struct Holds things in doubly linked lists */ struct LINKNODE { NPLINKNODE pPrev; /* @field NPLINKNODE | pPrev | Pointer to the previous node in the list */ NPLINKNODE pNext; /* @field NPLINKNODE | pNext | Pointer to the next node in the list */ }; /* @struct DirectMusic event as packed by IDirectMusic */ struct DMEVENT { DWORD cbEvent; /* @field DWORD | cbEvent | Unrounded number of event bytes */ DWORD dwChannelGroup; /* @field DWORD | dwChannelGroup | This field determines which channel group (set of 16 MIDI channels) receives the event. */ QUADWORD rtDelta; /* @field QUADWORD | rtDelta | Offset from buffer header in 100 ns units */ DWORD dwFlags; /* @field DWORD | dwFlags | DMEVENT_xxx */ BYTE abEvent[0]; /* @field BYTE | abEvent[] | Actual event data, rounded up to be an even number of QWORD's (8 bytes) */ }; /* Total size of an event needed to hold cb bytes of data */ #define DMEVENT_SIZE(cb) QWORD_ALIGN(sizeof(DMEVENT) + (cb)) /* If we have cb for event + data, how much data can we fit? */ #define DMEVENT_DATASIZE(cb) (QWORD_TRUNC(cb) - sizeof(DMEVENT)) #define DMEVENT_STRUCTURED 0x00000001 #define EVENT_F_MIDIHDR 0x0001 /* @struct Event as stored in an . */ struct EVENT { LPEVENT lpNext; /* @field LPEVENT | lpNext | Next event in queue */ DWORD msTime; /* @field DWORD | msTime | Absolute ms time in stream time (i.e. timeSetEvent) */ QUADWORD rtTime; /* @field QUADWORD | rtTime | Absolute time in 100ns units relative to reference clock. Use for sorting event queue. */ WORD wFlags; /* @field WORD | wFlags | A bitwise combination of the following flags: @flag EVENT_F_MIDIHDR | The event data starts with a MIDIHDR */ WORD cbEvent; /* @field WORD | cbEvent | The unrounded number of bytes in the event data */ BYTE abEvent[0]; /* @field BYTE | abEvent[] | The actual event data, rounded up to be an even number of DWORD's */ }; /* @struct A queue of structs. * * @comm * This is not the same as the generic list in list.c because we don't need * the overhead of a prev pointer here and we don't need the overhead of a far * pointer there. */ struct EVENTQUEUE { LPEVENT pHead; /* @field LPEVENT | pHead | Pointer to the first event */ LPEVENT pTail; /* @field LPEVENT | pTail | Pointer to the last event */ UINT cEle; /* @field UINT | cEle | The number of events currently in queue */ }; /* @struct An instance of an open device * * @comm * * Since multiple Win32 processes can hold a single MMSYSTEM handle open, * we need to track them. There is one of these structs per Win32 client * per open handle. It simply refers to the OPENHANDLE which contains * all the actual handle data. * */ struct OPENHANDLEINSTANCE { LINKNODE link; /* @field LINKNODE | link | Holds this handle in gOpenHandleInstanceList */ LINKNODE linkHandleList; /* @field LINKNODE | linkHandleList | Holds this handle in the list maintained in the struct for this device. */ NPOPENHANDLE pHandle; /* @field NPOPENHANDLE | pHandle | Pointer to the struct for this device. */ DWORD dwVxDEventHandle; /* @field DWORD | dwVxDEventHandle | VxD Event handle for signalling input on this device for this client. */ BOOL fActive; /* @field BOOL | fActive | Indicates if the port is active or not. This is used for per-instance focus management. If the port is flagged as inactive, then the underlying device is not opened. */ WORD wTask; /* @field WORD | wTask | Task which opened the handle. This is used to clean up if the task terminates abnormally. */ NPTHRUCHANNEL pThru; /* @field NPTHRUCHANNEL | pThru If an input device, an array of 16 thru entries, one per input channel. */ }; /* OPENHANDLE.wFlags */ #define OH_F_MIDIIN 0x0001 /* This is a MIDI input device */ #define OH_F_CLOSING 0x0002 /* This device is being closed */ #define OH_F_SHARED 0x0004 /* This device is shareable */ /* @struct An open device * * @comm * * There is a one-to-one relationship between open handles and structs. * * All of the following event queues are either * Protected - means it is accessible at callback time and user time, and is * protected by wCritSect * Callback - Means it is unprotected by a critical section and is only accessible * at callback time. Callbacks, per handle, are not reentered. * * In the MIDI in callback, we *cannot* just go away if we don't get wCritSect, * as we can on output. Hence the multiple input queues below. * * When the user mode refill algorithm runs, it puts events in qFree, protected * by the critical section. (The one exception to this is preloading qFreeCB before * midiInStart is called on the handle). When the callback runs, it tried to get the * critical section. If it can, it moves the free events from qFree to qFreeCB. * * In any case, the callback can now use qFreeCB even if it didn't get the critical * section. It pulls a free event from the queue, fills it, and puts it back onto * the tail of qDoneCB. If the critical section is held, it then transfers the * entire contents of qDoneCB to qDone. * * These transfers are not time consuming; they are merely the manipulation of * a couple of pointers. */ struct OPENHANDLE { LINKNODE link; /* @field LINKNODE | link | Holds this handle in gOpenHandles */ NPLINKNODE pInstanceList; /* @field NPLINKLINK | pInstanceList | Points to the first element in the list of open handle instances using this device. */ UINT uReferenceCount; /* @field UINT | uReferenceCount | The number of clients using this device; i.e., the number of elements in the pInstanceList. */ UINT uActiveCount; /* @field UINT | uActiveCount | The number of clients that have activated this device */ UINT id; /* @field UINT | id | The MMSYSTEM device ID of this device */ WORD wFlags; /* @field WORD | wFlags | Some combination of the following flags: @flag OH_F_MIDIIN | This device is a MIDI input device @flag OH_F_CLOSING | This device is being closed. @flag OH_F_SHARE | This device is opened in shared mode */ HMIDIOUT hmo; /* @field HMIDIOUT | hmo | MIDI output handle if an output device */ HMIDIIN hmi; /* @field HMIDIIN | hmi | MIDI input handle if an input device */ WORD wCritSect; /* @field WORD | wCritSect | Critical section protecting protected queues */ DWORD msStartTime; /* @field DWORD | msStartTime | Time we started input */ EVENTQUEUE qPlay; /* @field EVENTQUEUE | qPlay | Output: Queue of events to play (protected) */ EVENTQUEUE qDone; /* @field EVENTQUEUE | qDone | Input/Output: Events already done (played or received) (protected) */ EVENTQUEUE qFree; /* @field EVENTQUEUE | qFree | Input: Queue of free events (protected) */ EVENTQUEUE qFreeCB; /* @field EVENTQUEUE | qFreeCB | Input: Queue of free events used by callback */ EVENTQUEUE qDoneCB; /* @field EVENTQUEUE | qDoneCB | Input: Queue of received events used by callback */ WORD wPostedSysExBuffers; /* @field WORD | cPostedSysExBuffers | Input: Buffers posted in MMSYSTEM for recording SysEx */ }; #define CLASS_MIDI 0 /* dwEventClass */ /* Close to our page size */ #define SEG_SIZE 4096 #define C_PER_SEG ((SEG_SIZE - sizeof(SEGHDR)) / (sizeof(EVENT) + sizeof(DWORD))) #define SEG_F_4BYTE_EVENTS 0x0001 typedef struct SEGHDR SEGHDR; typedef struct SEGHDR FAR * LPSEGHDR; /* @struct The header for one segment of allocated memory */ struct SEGHDR { WORD selNext; /* @field WORD | selNext | The selector of the next block of memory in the allocated list */ WORD hSeg; /* @field WORD | hSeg | The global handle of the memory block */ WORD wFlags; /* @field WORD | wFlags | A bitwise combination of the following flags: @flag SEG_F_4BYTE_EVENTS | This segment contains multiple channel messages */ WORD cbSeg; /* @field WORD | cbSeg | The size of the segment, less the */ }; /* @struct Thru information for one channel * * @comm * * Each input device handle instance contains an array of 16 of these structures containing * the thru destination for data that arrives on that channel. * */ struct THRUCHANNEL { WORD wChannel; /* @field WORD | wChannel | The destination channel */ NPOPENHANDLEINSTANCE pohi; /* @field NPOPENHANDLEINSTANCE | pohi | The output handle instance to receive the thru'ed data. */ }; /* globals */ extern HINSTANCE ghInst; extern NPLINKNODE gOpenHandleInstanceList; extern NPLINKNODE gOpenHandleList; extern UINT gcOpenInputDevices; extern UINT gcOpenOutputDevices; /* device.c */ #define VA_F_INPUT 0x0001 #define VA_F_OUTPUT 0x0002 #define VA_F_EITHER (VA_F_INPUT | VA_F_OUTPUT) extern VOID PASCAL DeviceOnLoad(VOID); extern MMRESULT PASCAL CloseLegacyDeviceI(NPOPENHANDLEINSTANCE pohi); extern MMRESULT PASCAL ActivateLegacyDeviceI(NPOPENHANDLEINSTANCE pohi, BOOL fActivate); extern BOOL PASCAL IsValidHandle(HANDLE h, WORD wType, NPOPENHANDLEINSTANCE FAR *lppohi); extern VOID PASCAL CloseDevicesForTask(WORD wTask); /* list.c */ extern VOID PASCAL ListInsert(NPLINKNODE *pHead, NPLINKNODE pNode); extern VOID PASCAL ListRemove(NPLINKNODE *pHead, NPLINKNODE pNode); /* eventq.c */ extern VOID PASCAL QueueInit(NPEVENTQUEUE pQueue); extern VOID PASCAL QueueAppend(NPEVENTQUEUE pQueue, LPEVENT pEvent); extern VOID PASCAL QueueCat(NPEVENTQUEUE pDest, NPEVENTQUEUE pSource); extern LPEVENT PASCAL QueueRemoveFromFront(NPEVENTQUEUE pQueue); #define QUEUE_FILTER_KEEP (0) #define QUEUE_FILTER_REMOVE (1) typedef int (PASCAL *PFNQUEUEFILTER)(LPEVENT pEvent, DWORD dwInstance); extern VOID PASCAL QueueFilter(NPEVENTQUEUE pQueue, DWORD dwInstance, PFNQUEUEFILTER pfnFilter); extern LPEVENT PASCAL QueuePeek(NPEVENTQUEUE pQueue); #ifdef DEBUG #define AssertQueueValid(pQueue) _AssertQueueValid((pQueue), __FILE__, __LINE__) extern VOID PASCAL _AssertQueueValid(NPEVENTQUEUE pQueue, LPSTR pstrFile, UINT uLine); #else #define AssertQueueValid #endif /* locks.c */ #define LOCK_F_INPUT 0x0001 #define LOCK_F_OUTPUT 0x0002 #define LOCK_F_COMMON 0x0004 extern VOID PASCAL LockCode(WORD wFlags); extern VOID PASCAL UnlockCode(WORD wFlags); /* dmhelp.asm */ extern VOID PASCAL InitializeCriticalSection(LPWORD lpwCritSect); #define CS_NONBLOCKING (0) #define CS_BLOCKING (1) extern WORD PASCAL EnterCriticalSection(LPWORD lpwCritSect, WORD fBlocking); extern VOID PASCAL LeaveCriticalSection(LPWORD lpwCritSect); extern WORD PASCAL DisableInterrupts(VOID); extern VOID PASCAL RestoreInterrupts(WORD wIntStat); extern WORD PASCAL InterlockedIncrement(LPWORD pw); extern WORD PASCAL InterlockedDecrement(LPWORD pw); extern DWORD PASCAL QuadwordDiv(QUADWORD qwDividend, DWORD dwDivisor); extern VOID PASCAL QuadwordMul(DWORD m1, DWORD m2, LPQUADWORD qwResult); extern BOOL PASCAL QuadwordLT(QUADWORD qwLValue, QUADWORD qwRValue); extern VOID PASCAL QuadwordAdd(QUADWORD qwOp1, QUADWORD qwOp2, LPQUADWORD lpqwResult); /* alloc.c */ extern VOID PASCAL AllocOnLoad(VOID); extern VOID PASCAL AllocOnExit(VOID); extern LPEVENT PASCAL AllocEvent(DWORD msTime, QUADWORD rtTime, WORD cbEvent); extern VOID PASCAL FreeEvent(LPEVENT lpEvent); /* midiout.c */ extern VOID PASCAL MidiOutOnLoad(VOID); extern VOID PASCAL MidiOutOnExit(VOID); extern MMRESULT PASCAL MidiOutOnOpen(NPOPENHANDLEINSTANCE pohi); extern VOID PASCAL MidiOutOnClose(NPOPENHANDLEINSTANCE pohi); extern MMRESULT PASCAL MidiOutOnActivate(NPOPENHANDLEINSTANCE pohi); extern MMRESULT PASCAL MidiOutOnDeactivate(NPOPENHANDLEINSTANCE pohi); extern VOID PASCAL SetOutputTimerRes(BOOL fOnOpen); extern VOID PASCAL FreeDoneHandleEvents(NPOPENHANDLE poh, BOOL fClosing); extern VOID PASCAL MidiOutThru(NPOPENHANDLEINSTANCE pohi, DWORD dwMessage); /* midiin.c */ extern VOID PASCAL MidiInOnLoad(VOID); extern VOID PASCAL MidiInOnExit(VOID); extern MMRESULT PASCAL MidiInOnOpen(NPOPENHANDLEINSTANCE pohi); extern VOID PASCAL MidiInOnClose(NPOPENHANDLEINSTANCE pohi); extern MMRESULT PASCAL MidiInOnActivate(NPOPENHANDLEINSTANCE pohi); extern MMRESULT PASCAL MidiInOnDeactivate(NPOPENHANDLEINSTANCE pohi); extern VOID PASCAL MidiInRefillFreeLists(VOID); extern VOID PASCAL MidiInUnthruToInstance(NPOPENHANDLEINSTANCE pohi); extern VOID PASCAL FreeAllQueueEvents(NPEVENTQUEUE peq); /* mmdevldr.asm */ extern MMRESULT CDECL SetWin32Event(DWORD dwVxDEvent); /* Must be CDECL! */ /* timerwnd.c */ extern BOOL PASCAL CreateTimerTask(VOID); extern VOID PASCAL DestroyTimerTask(VOID); #endif