|
|
// 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 <c EVENTQUEUE>.
*/ 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 <c EVENT> 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 <c OPENHANDLE> struct for this device. */ NPOPENHANDLE pHandle; /* @field NPOPENHANDLE | pHandle |
Pointer to the <c OPENHANDLE> 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 <c OPENHANDLE> 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 | <f timeGetTime()> 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 <c SEGHDR> */ };
/* @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
|