windows-nt/Source/XPSP1/NT/multimedia/directx/dmusic/dmusic16/dmusic16.h
2020-09-26 16:20:57 +08:00

436 lines
17 KiB
C

// 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