1270 lines
42 KiB
C
1270 lines
42 KiB
C
|
/***************************************************************************
|
||
|
* winmmi.h
|
||
|
*
|
||
|
* Copyright (c) Microsoft Corporation 1990. All rights reserved
|
||
|
*
|
||
|
* private include file
|
||
|
*
|
||
|
* History
|
||
|
*
|
||
|
* 15 Jan 92 - Robin Speed (RobinSp) and Steve Davies (SteveDav) -
|
||
|
* major NT update
|
||
|
* 6 Feb 92 - LaurieGr replaced HLOCAL by HANDLE
|
||
|
*
|
||
|
***************************************************************************/
|
||
|
|
||
|
/***************************************************************************
|
||
|
|
||
|
|
||
|
Useful include files for winmm component
|
||
|
|
||
|
|
||
|
***************************************************************************/
|
||
|
#define DEBUG_RETAIL /* Parameter checking is IN */
|
||
|
#if DBG
|
||
|
#ifndef DEBUG
|
||
|
#define DEBUG
|
||
|
#endif
|
||
|
#endif
|
||
|
|
||
|
#ifndef WINMMI_H
|
||
|
#define WINMMI_H /* Protect against double inclusion */
|
||
|
|
||
|
#ifndef RC_INVOKED
|
||
|
|
||
|
#include <string.h>
|
||
|
#include <stdio.h>
|
||
|
|
||
|
#endif /* RC_INVOKED */
|
||
|
|
||
|
#include <windows.h>
|
||
|
#include "mmsystem.h" /* Pick up the public header */
|
||
|
#include "mmsysp.h" /* pick up the internal definitions */
|
||
|
#include "mmcommon.h" /* pick up the definitions common to the NT project */
|
||
|
|
||
|
#ifndef NODDK
|
||
|
#include "mmddk.h"
|
||
|
#endif
|
||
|
|
||
|
|
||
|
extern BOOL WinmmRunningInWOW; // Are we running in WOW
|
||
|
|
||
|
|
||
|
/*--------------------------------------------------------------------*\
|
||
|
* Unicode helper macros
|
||
|
\*--------------------------------------------------------------------*/
|
||
|
#define SZCODE CHAR
|
||
|
#define WSZCODE WCHAR
|
||
|
|
||
|
#define BYTE_GIVEN_CHAR(x) ( (x) * sizeof( WCHAR ) )
|
||
|
#define CHAR_GIVEN_BYTE(x) ( (x) / sizeof( WCHAR ) )
|
||
|
|
||
|
int Iwcstombs(LPSTR lpstr, LPCWSTR lpwstr, int len);
|
||
|
int Imbstowcs(LPWSTR lpwstr, LPCSTR lpstr, int len);
|
||
|
|
||
|
/***************************************************************************
|
||
|
|
||
|
|
||
|
Definitions to help with common windows code
|
||
|
|
||
|
|
||
|
***************************************************************************/
|
||
|
|
||
|
#define HPSTR LPSTR
|
||
|
|
||
|
#ifndef RC_INVOKED /* These are defined to RC */
|
||
|
#define STATICDT
|
||
|
#define STATICFN
|
||
|
#define STATIC
|
||
|
|
||
|
#if DBG
|
||
|
extern void InitDebugLevel(void);
|
||
|
void mciCheckLocks(void);
|
||
|
|
||
|
#undef STATICDT
|
||
|
#undef STATICFN
|
||
|
#undef STATIC
|
||
|
#define STATICDT
|
||
|
#define STATICFN
|
||
|
#define STATIC
|
||
|
#else
|
||
|
#define InitDebugLevel()
|
||
|
#endif /* DBG */
|
||
|
|
||
|
#endif /* RC_INVOKED */
|
||
|
|
||
|
|
||
|
/**************************************************************************
|
||
|
|
||
|
|
||
|
Strings related to INI files
|
||
|
|
||
|
|
||
|
**************************************************************************/
|
||
|
|
||
|
/*
|
||
|
// File and section names for sound aliases
|
||
|
*/
|
||
|
|
||
|
#define SOUND_INI_FILE L"win.ini"
|
||
|
#define SOUND_SECTION L"Sounds"
|
||
|
#define SOUND_DEFAULT L".Default"
|
||
|
#define SOUND_RESOURCE_TYPE L"WAVE" // in .rc file
|
||
|
extern WSZCODE szSystemDefaultSound[]; // Name of the default sound
|
||
|
extern WSZCODE szSoundSection[]; // WIN.INI section for sounds
|
||
|
extern WSZCODE wszSystemIni[]; // defined in Winmm.c
|
||
|
extern WSZCODE wszDrivers[]; // defined in Winmm.c
|
||
|
extern WSZCODE wszNull[]; // defined in Winmm.c
|
||
|
|
||
|
#define STR_ALIAS_SYSTEMASTERISK 3000
|
||
|
#define STR_ALIAS_SYSTEMQUESTION 3001
|
||
|
#define STR_ALIAS_SYSTEMHAND 3002
|
||
|
#define STR_ALIAS_SYSTEMEXIT 3003
|
||
|
#define STR_ALIAS_SYSTEMSTART 3004
|
||
|
#define STR_ALIAS_SYSTEMWELCOME 3005
|
||
|
#define STR_ALIAS_SYSTEMEXCLAMATION 3006
|
||
|
#define STR_ALIAS_SYSTEMDEFAULT 3007
|
||
|
|
||
|
#define STR_LABEL_APPGPFAULT 3008
|
||
|
#define STR_LABEL_CLOSE 3009
|
||
|
#define STR_LABEL_EMPTYRECYCLEBIN 3010
|
||
|
#define STR_LABEL_MAXIMIZE 3011
|
||
|
#define STR_LABEL_MENUCOMMAND 3012
|
||
|
#define STR_LABEL_MENUPOPUP 3013
|
||
|
#define STR_LABEL_MINIMIZE 3014
|
||
|
#define STR_LABEL_OPEN 3015
|
||
|
#define STR_LABEL_RESTOREDOWN 3016
|
||
|
#define STR_LABEL_RESTOREUP 3017
|
||
|
#define STR_LABEL_RINGIN 3018
|
||
|
#define STR_LABEL_RINGOUT 3019
|
||
|
#define STR_LABEL_SYSTEMASTERISK 3020
|
||
|
#define STR_LABEL_SYSTEMDEFAULT 3021
|
||
|
#define STR_LABEL_SYSTEMEXCLAMATION 3022
|
||
|
#define STR_LABEL_SYSTEMEXIT 3023
|
||
|
#define STR_LABEL_SYSTEMHAND 3024
|
||
|
#define STR_LABEL_SYSTEMQUESTION 3025
|
||
|
#define STR_LABEL_SYSTEMSTART 3026
|
||
|
|
||
|
#define STR_WINDOWS_APP_NAME 3027
|
||
|
#define STR_EXPLORER_APP_NAME 3028
|
||
|
|
||
|
/*
|
||
|
// File and section names for the mci functions
|
||
|
*/
|
||
|
|
||
|
#define MCIDRIVERS_INI_FILE L"system.ini"
|
||
|
#define MCI_HANDLERS MCI_SECTION
|
||
|
|
||
|
/***********************************************************************
|
||
|
*
|
||
|
* Speed up profile stuff by going straight to the registry
|
||
|
*
|
||
|
***********************************************************************/
|
||
|
|
||
|
VOID mmRegFree(VOID);
|
||
|
BOOL
|
||
|
mmRegCreateUserKey (
|
||
|
LPCWSTR lpszPathName,
|
||
|
LPCWSTR lpszKeyName
|
||
|
);
|
||
|
|
||
|
BOOL
|
||
|
mmRegQueryUserKey (
|
||
|
LPCWSTR lpszKeyName
|
||
|
);
|
||
|
|
||
|
BOOL
|
||
|
mmRegDeleteUserKey (
|
||
|
LPCWSTR lpszKeyName
|
||
|
);
|
||
|
|
||
|
BOOL
|
||
|
mmRegSetUserValue (
|
||
|
LPCWSTR lpszSectionName,
|
||
|
LPCWSTR lpszValueName,
|
||
|
LPCWSTR lpszValue
|
||
|
);
|
||
|
|
||
|
BOOL
|
||
|
mmRegQueryUserValue (
|
||
|
LPCWSTR lpszSectionName,
|
||
|
LPCWSTR lpszValueName,
|
||
|
ULONG dwLen,
|
||
|
LPWSTR lpszValue
|
||
|
);
|
||
|
|
||
|
BOOL
|
||
|
mmRegCreateMachineKey (
|
||
|
LPCWSTR lpszPath,
|
||
|
LPCWSTR lpszNewKey
|
||
|
);
|
||
|
|
||
|
BOOL
|
||
|
mmRegSetMachineValue (
|
||
|
LPCWSTR lpszSectionName,
|
||
|
LPCWSTR lpszValueName,
|
||
|
LPCWSTR lpszValue
|
||
|
);
|
||
|
|
||
|
BOOL
|
||
|
mmRegQueryMachineValue (
|
||
|
LPCWSTR lpszSectionName,
|
||
|
LPCWSTR lpszValueName,
|
||
|
ULONG dwLen,
|
||
|
LPWSTR lpszValue
|
||
|
);
|
||
|
|
||
|
DWORD
|
||
|
winmmGetProfileString(
|
||
|
LPCWSTR lpAppName,
|
||
|
LPCWSTR lpKeyName,
|
||
|
LPCWSTR lpDefault,
|
||
|
LPWSTR lpReturnedString,
|
||
|
DWORD nSize
|
||
|
);
|
||
|
|
||
|
DWORD
|
||
|
winmmGetPrivateProfileString(
|
||
|
LPCWSTR lpSection,
|
||
|
LPCWSTR lpKeyName,
|
||
|
LPCWSTR lpDefault,
|
||
|
LPWSTR lpReturnedString,
|
||
|
DWORD nSize,
|
||
|
LPCWSTR lpFileName
|
||
|
);
|
||
|
|
||
|
/***********************************************************************
|
||
|
*
|
||
|
* Used by hwndNotify code
|
||
|
*
|
||
|
***********************************************************************/
|
||
|
|
||
|
extern BOOL sndMessage( LPWSTR lszSoundName, UINT wFlags );
|
||
|
extern BOOL InitAsyncSound(VOID);
|
||
|
extern CRITICAL_SECTION WavHdrCritSec;
|
||
|
extern CRITICAL_SECTION SoundCritSec;
|
||
|
extern CRITICAL_SECTION mciGlobalCritSec;
|
||
|
extern CRITICAL_SECTION midiStrmHdrCritSec;
|
||
|
|
||
|
/***********************************************************************
|
||
|
*
|
||
|
* Flag deduced by initialization to special case running in the server
|
||
|
*
|
||
|
***********************************************************************/
|
||
|
|
||
|
extern BOOL WinmmRunningInServer; // Are we running in the user/base server?
|
||
|
|
||
|
/***********************************************************************
|
||
|
*
|
||
|
* prototypes from "winmm.c"
|
||
|
*
|
||
|
***********************************************************************/
|
||
|
|
||
|
void WaveMapperInit(void);
|
||
|
void MidiMapperInit(void);
|
||
|
void midiEmulatorInit(void);
|
||
|
|
||
|
|
||
|
/***********************************************************************
|
||
|
*
|
||
|
* prototypes from "mmiomisc.c"
|
||
|
*
|
||
|
***********************************************************************/
|
||
|
|
||
|
|
||
|
PBYTE AsciiStrToUnicodeStr( PBYTE pdst, PBYTE pmax, LPCSTR psrc );
|
||
|
PBYTE UnicodeStrToAsciiStr( PBYTE pdst, PBYTE pmax, LPCWSTR psrc);
|
||
|
LPWSTR AllocUnicodeStr( LPCSTR lpSourceStr );
|
||
|
BOOL FreeUnicodeStr( LPWSTR lpStr );
|
||
|
LPSTR AllocAsciiStr( LPCWSTR lpSourceStr );
|
||
|
BOOL FreeAsciiStr( LPSTR lpStr );
|
||
|
|
||
|
/***********************************************************************
|
||
|
*
|
||
|
* prototypes from "mmio.c"
|
||
|
*
|
||
|
***********************************************************************/
|
||
|
|
||
|
void mmioCleanupIOProcs(HANDLE hTask);
|
||
|
|
||
|
/***********************************************************************
|
||
|
*
|
||
|
* Timer functions
|
||
|
*
|
||
|
***********************************************************************/
|
||
|
|
||
|
#ifndef MMNOTIMER
|
||
|
BOOL TimeInit(void);
|
||
|
void TimeCleanup(DWORD ThreadId);
|
||
|
UINT timeSetEventInternal(UINT wDelay, UINT wResolution,
|
||
|
LPTIMECALLBACK lpFunction, DWORD dwUser, UINT wFlags, BOOL IsWOW);
|
||
|
#endif // !MMNOTIMER
|
||
|
|
||
|
|
||
|
/***********************************************************************
|
||
|
*
|
||
|
* Information structure used to play sounds
|
||
|
*
|
||
|
***********************************************************************/
|
||
|
|
||
|
#define PLAY_NAME_SIZE 256
|
||
|
|
||
|
typedef struct _PLAY_INFO {
|
||
|
HANDLE hModule;
|
||
|
HANDLE hRequestingTask; // Handle of thread that requested sound
|
||
|
DWORD dwFlags;
|
||
|
WCHAR szName[1]; // the structure will be allocated large enough for the name
|
||
|
} PLAY_INFO, *PPLAY_INFO;
|
||
|
|
||
|
|
||
|
#define WAIT_FOREVER ((DWORD)(-1))
|
||
|
|
||
|
/***************************************************************************
|
||
|
|
||
|
global data
|
||
|
|
||
|
***************************************************************************/
|
||
|
|
||
|
extern HANDLE ghInst;
|
||
|
HANDLE hHeap;
|
||
|
|
||
|
|
||
|
/***************************************************************************
|
||
|
*
|
||
|
* Define the product version to be returned from
|
||
|
* mmsystemgetversion and any other messagebox or
|
||
|
* API that needs the public product version.
|
||
|
*
|
||
|
***************************************************************************/
|
||
|
|
||
|
#define MMSYSTEM_VERSION 0X030A
|
||
|
|
||
|
|
||
|
|
||
|
typedef UINT MMMESSAGE; // Multi media message type (internal)
|
||
|
|
||
|
#ifndef WM_MM_RESERVED_FIRST // Copy constants from winuserp.h
|
||
|
#define WM_MM_RESERVED_FIRST 0x03A0
|
||
|
#define WM_MM_RESERVED_LAST 0x03DF
|
||
|
#endif
|
||
|
#define MM_POLYMSGBUFRDONE (WM_MM_RESERVED_FIRST+0x2B)
|
||
|
#define MM_SND_PLAY (WM_MM_RESERVED_FIRST+0x2C)
|
||
|
#define MM_SND_ABORT (WM_MM_RESERVED_FIRST+0x2D)
|
||
|
#define MM_SND_SEND (WM_MM_RESERVED_FIRST+0x2E)
|
||
|
#define MM_SND_WAIT (WM_MM_RESERVED_FIRST+0x2F)
|
||
|
#define MCIWAITMSG (MM_SND_WAIT)
|
||
|
|
||
|
#if MM_SND_WAIT > WM_MM_RESERVED_LAST
|
||
|
#error "MM_SND_WAIT is defined beyond the reserved WM_MM range"
|
||
|
#endif
|
||
|
|
||
|
/***************************************************************************
|
||
|
|
||
|
DEBUGGING SUPPORT
|
||
|
|
||
|
***************************************************************************/
|
||
|
|
||
|
|
||
|
#if DBG
|
||
|
|
||
|
#ifdef DEBUGLEVELVAR
|
||
|
// So that other WINMM related modules can use their own debug level
|
||
|
// variable
|
||
|
#define winmmDebugLevel DEBUGLEVELVAR
|
||
|
#endif
|
||
|
|
||
|
extern int winmmDebugLevel;
|
||
|
extern void winmmDbgOut(LPSTR lpszFormat, ...);
|
||
|
extern void dDbgAssert(LPSTR exp, LPSTR file, int line);
|
||
|
|
||
|
DWORD __dwEval;
|
||
|
|
||
|
extern void winmmDbgOut(LPSTR lpszFormat, ...);
|
||
|
|
||
|
#define dprintf( _x_ ) winmmDbgOut _x_
|
||
|
#define dprintf1( _x_ ) if (winmmDebugLevel >= 1) winmmDbgOut _x_
|
||
|
#define dprintf2( _x_ ) if (winmmDebugLevel >= 2) winmmDbgOut _x_
|
||
|
#define dprintf3( _x_ ) if (winmmDebugLevel >= 3) winmmDbgOut _x_
|
||
|
#define dprintf4( _x_ ) if (winmmDebugLevel >= 4) winmmDbgOut _x_
|
||
|
#define dprintf5( _x_ ) if (winmmDebugLevel >= 5) winmmDbgOut _x_
|
||
|
#define dprintf6( _x_ ) if (winmmDebugLevel >= 6) winmmDbgOut _x_
|
||
|
|
||
|
#define WinAssert(exp) \
|
||
|
((exp) ? (void)0 : dDbgAssert(#exp, __FILE__, __LINE__))
|
||
|
|
||
|
#define WinEval(exp) \
|
||
|
((__dwEval=(DWORD)(exp)), \
|
||
|
__dwEval ? (void)0 : dDbgAssert(#exp, __FILE__, __LINE__), __dwEval)
|
||
|
|
||
|
#define DOUT(x) (OutputDebugStringA x, 0)
|
||
|
// #define DOUTX(x) (OutputDebugStringA x, 0)
|
||
|
// #define ROUTS(x) (OutputDebugStringA(x), OutputDebugStringA("\r\n"), 0)
|
||
|
#define ROUTSW(x) (OutputDebugStringW x, OutputDebugStringW(L"\r\n"), 0)
|
||
|
#define ROUT(x) (OutputDebugStringA x, OutputDebugStringA("\r\n"), 0)
|
||
|
// #define ROUTX(x) (OutputDebugStringA(x), 0)
|
||
|
|
||
|
#else
|
||
|
|
||
|
#define dprintf(x)
|
||
|
#define dprintf1(x)
|
||
|
#define dprintf2(x)
|
||
|
#define dprintf3(x)
|
||
|
#define dprintf4(x)
|
||
|
#define dprintf5(x)
|
||
|
#define dprintf6(x)
|
||
|
|
||
|
#define WinAssert(exp) 0
|
||
|
#define WinEval(exp) (exp)
|
||
|
|
||
|
#define DOUT(x) 0
|
||
|
// #define DOUTX(x) 0
|
||
|
// #define ROUTS(x) 0
|
||
|
#define ROUT(x) 0
|
||
|
// #define ROUTX(x) 0
|
||
|
|
||
|
#endif
|
||
|
|
||
|
|
||
|
|
||
|
/***************************************************************************
|
||
|
|
||
|
Resource IDs
|
||
|
|
||
|
***************************************************************************/
|
||
|
|
||
|
#define IDS_TASKSTUB 2000
|
||
|
#define STR_MCIUNKNOWN 2001 /* "Unknown error returned from MCI command" */
|
||
|
// #define STR_WAVEINPUT 2004
|
||
|
// #define STR_WAVEOUTPUT 2005
|
||
|
// #define STR_MIDIINPUT 2006
|
||
|
// #define STR_MIDIOUTPUT 2007
|
||
|
#define STR_MCISSERRTXT 2009
|
||
|
#define STR_MCISCERRTXT 2010
|
||
|
#define STR_MIDIMAPPER 2011
|
||
|
#define STR_DRIVERS 2012
|
||
|
#define STR_SYSTEMINI 2013
|
||
|
#define STR_BOOT 2014
|
||
|
|
||
|
/***************************************************************************
|
||
|
|
||
|
Memory allocation using our local heap
|
||
|
|
||
|
***************************************************************************/
|
||
|
HANDLE hHeap;
|
||
|
PVOID winmmAlloc(DWORD cb);
|
||
|
PVOID winmmReAlloc(PVOID ptr, DWORD cb);
|
||
|
#define winmmFree(ptr) HeapFree(hHeap, 0, (ptr))
|
||
|
|
||
|
/***************************************************************************
|
||
|
|
||
|
LOCKING AND UNLOCKING MEMORY
|
||
|
|
||
|
***************************************************************************/
|
||
|
|
||
|
#if 0
|
||
|
BOOL HugePageLock(LPVOID lpArea, DWORD dwLength);
|
||
|
void HugePageUnlock(LPVOID lpArea, DWORD dwLength);
|
||
|
#else
|
||
|
#define HugePageLock(lpArea, dwLength) (TRUE)
|
||
|
#define HugePageUnlock(lpArea, dwLength)
|
||
|
#endif
|
||
|
|
||
|
/****************************************************************************
|
||
|
|
||
|
API to install/remove/query a MMSYS driver
|
||
|
|
||
|
****************************************************************************/
|
||
|
|
||
|
/* generic prototype for audio device driver entry-point functions
|
||
|
// midMessage(), modMessage(), widMessage(), wodMessage(), auxMessage()
|
||
|
*/
|
||
|
typedef DWORD (APIENTRY *DRIVERMSGPROC)(DWORD, DWORD, DWORD, DWORD, DWORD);
|
||
|
|
||
|
UINT APIENTRY mmDrvInstall(HANDLE hDriver, WCHAR * wszDrvEntry, DRIVERMSGPROC drvMessage, UINT wFlags);
|
||
|
|
||
|
/*
|
||
|
@doc INTERNAL MMSYSTEM
|
||
|
@type UINT | HMD |
|
||
|
This type definition specifies a handle to media resource entry. This
|
||
|
can be used as a unique identifier when specifying a media resource.
|
||
|
*/
|
||
|
|
||
|
DECLARE_HANDLE(HMD);
|
||
|
|
||
|
BOOL FAR PASCAL mregHandleInternalMessages (LPVOID pmd, DWORD dwType, DWORD dwMap, UINT msg, DWORD dw1, DWORD dw2, MMRESULT * pmmr);
|
||
|
DWORD FAR PASCAL mregDriverInformation(UINT uDeviceID, WORD fwClass, UINT uMessage, DWORD dwParam1, DWORD dwParam2);
|
||
|
UINT FAR PASCAL mregIncUsage(HMD hmd);
|
||
|
UINT FAR PASCAL mregDecUsage(HMD hmd);
|
||
|
MMRESULT FAR PASCAL mregFindDevice(UINT uDeviceID, WORD fwFindDevice, HMD FAR* phmd, UINT FAR* puDevicePort);
|
||
|
|
||
|
|
||
|
/*****************************************************************************
|
||
|
|
||
|
Driver stuff - BUGBUG this will change when we work out the real
|
||
|
installable driver story on NT
|
||
|
|
||
|
****************************************************************************/
|
||
|
LONG DrvClose(HANDLE hDriver, LONG lParam1, LONG lParam2);
|
||
|
HANDLE DrvOpen(LPCWSTR szDriverName, LPCWSTR szSectionName, LONG lParam2);
|
||
|
LONG DrvSendMessage(HANDLE hDriver, UINT message, LONG lParam1, LONG lParam2);
|
||
|
//HMODULE APIENTRY DrvGetModuleHandle(HDRVR hDriver);
|
||
|
|
||
|
typedef DWORD (DRVPROC)(HANDLE hDriver, UINT msg, LONG lp1, LONG lp2);
|
||
|
typedef DRVPROC *LPDRVPROC;
|
||
|
|
||
|
//
|
||
|
// Initialize Joystick code
|
||
|
//
|
||
|
|
||
|
BOOL JoyInit(void);
|
||
|
|
||
|
/*
|
||
|
** Special function for creating threads inside the server process (we only
|
||
|
** use this to create the thread for playing sounds)
|
||
|
*/
|
||
|
|
||
|
BOOLEAN CreateServerPlayingThread(PVOID ThreadStartRoutine);
|
||
|
|
||
|
/*
|
||
|
// exclude some stuff if MMDDK.H is not included
|
||
|
*/
|
||
|
#ifdef MMDDKINC /* use this to test for MMDDK.H */
|
||
|
|
||
|
//
|
||
|
// note this must be the same as MIDIDRV/WAVEDRV/AUXDRV
|
||
|
//
|
||
|
typedef struct {
|
||
|
HANDLE hDriver; /* handle to the module */
|
||
|
DRIVERMSGPROC drvMessage; /* pointer to entry point */
|
||
|
BYTE bNumDevs; /* number of devices supported */
|
||
|
BYTE bUsage; /* usage count (number of handle's open) */
|
||
|
WCHAR wszDrvEntry[64]; /* driver filename */
|
||
|
} MMDRV, *PMMDRV;
|
||
|
|
||
|
#ifndef MMNOMIDI
|
||
|
|
||
|
|
||
|
/****************************************************************************
|
||
|
|
||
|
Clock routines used by MIDI. These routines provide clocks which run
|
||
|
at the current tempo or SMPTE rate based on timeGetTime().
|
||
|
|
||
|
****************************************************************************/
|
||
|
|
||
|
typedef DWORD MILLISECS;
|
||
|
typedef long TICKS;
|
||
|
|
||
|
#define CLK_CS_PAUSED 0x00000001L
|
||
|
#define CLK_CS_RUNNING 0x00000002L
|
||
|
|
||
|
#define CLK_TK_NOW ((TICKS)-1L)
|
||
|
|
||
|
//
|
||
|
// This structure is allocated by the client (probably in a handle structure)
|
||
|
// in MMSYSTEM's DS and passed as a near pointer.
|
||
|
//
|
||
|
|
||
|
typedef struct tag_clock *PCLOCK;
|
||
|
|
||
|
typedef DWORD (FAR PASCAL *CLK_TIMEBASE)(PCLOCK);
|
||
|
typedef struct tag_clock
|
||
|
{
|
||
|
MILLISECS msPrev;
|
||
|
TICKS tkPrev;
|
||
|
MILLISECS msT0;
|
||
|
DWORD dwNum;
|
||
|
DWORD dwDenom;
|
||
|
DWORD dwState;
|
||
|
CLK_TIMEBASE fnTimebase;
|
||
|
} CLOCK;
|
||
|
|
||
|
void FAR PASCAL clockInit(PCLOCK pclock, MILLISECS msPrev, TICKS tkPrev, CLK_TIMEBASE fnTimebase);
|
||
|
void FAR PASCAL clockSetRate(PCLOCK pclock, TICKS tkWhen, DWORD dwNum, DWORD dwDenom);
|
||
|
void FAR PASCAL clockPause(PCLOCK pclock, TICKS tkWhen);
|
||
|
void FAR PASCAL clockRestart(PCLOCK pclock, TICKS tkWhen, MILLISECS msWhen);
|
||
|
TICKS FAR PASCAL clockTime(PCLOCK pclock);
|
||
|
MILLISECS FAR PASCAL clockMsTime(PCLOCK pclock);
|
||
|
MILLISECS FAR PASCAL clockOffsetTo(PCLOCK pclock, TICKS tkWhen);
|
||
|
|
||
|
/****************************************************************************
|
||
|
|
||
|
Macros and prototypes shared by the MIDI subsystem.
|
||
|
|
||
|
****************************************************************************/
|
||
|
|
||
|
// #pragma message() with file/line numbers!
|
||
|
//
|
||
|
#define __PRAGMSG(l,x,c) message(__FILE__"("#l") : "c": "x)
|
||
|
#define _WARN(l,x) __PRAGMSG(l,x, "warning")
|
||
|
#define WARNMSG(x) _WARN(__LINE__,x)
|
||
|
|
||
|
#define _FIX(l,x) __PRAGMSG(l,x, "fix")
|
||
|
#define FIXMSG(x) _FIX(__LINE__,x)
|
||
|
|
||
|
#define DEFAULT_TEMPO 500000L // 500,000 uSec/qn == 120 BPM
|
||
|
#define DEFAULT_TIMEDIV 24 // 24 ticks per quarter note
|
||
|
#define DEFAULT_CBTIMEOUT 100 // 100 milliseconds
|
||
|
|
||
|
#define PM_STATE_READY 0 // polymsg ready to play
|
||
|
#define PM_STATE_BLOCKED 1 // Blocked on outgoing SysEx
|
||
|
#define PM_STATE_EMPTY 2 // No polymsg queued
|
||
|
#define PM_STATE_STOPPED 3 // Just opened/reset/stopped
|
||
|
// No polymsg sent yet.
|
||
|
#define PM_STATE_PAUSED 4 // Paused at some position
|
||
|
|
||
|
#define MIN_PERIOD 1 // millisecs of timer resolution
|
||
|
|
||
|
//
|
||
|
// Macros for dealing with time division dword
|
||
|
//
|
||
|
#define IS_SMPTE 0x00008000L
|
||
|
#define METER_NUM(dw) (UINT)((HIWORD(dw)>>8)&0x00FF)
|
||
|
#define METER_DENOM(dw) (UINT)(HIWORD(dw)&0x00FF)
|
||
|
#define TICKS_PER_QN(dw) (UINT)((dw)&0x7FFF)
|
||
|
#define SMPTE_FORMAT(dw) (((int)((dw)&0xFF00))>>8)
|
||
|
#define TICKS_PER_FRAME(dw) (UINT)((dw)&0x00FF)
|
||
|
|
||
|
//
|
||
|
// Constants for 30-Drop format conversion
|
||
|
//
|
||
|
#define S30D_FRAMES_PER_10MIN 17982
|
||
|
#define S30D_FRAMES_PER_MIN 1798
|
||
|
|
||
|
//
|
||
|
// SMPTE formats from MIDI file time division
|
||
|
//
|
||
|
#define SMPTE_24 24
|
||
|
#define SMPTE_25 25
|
||
|
#define SMPTE_30DROP 29
|
||
|
#define SMPTE_30 30
|
||
|
|
||
|
//
|
||
|
// Stuff that's part of MIDI spec
|
||
|
//
|
||
|
#define MIDI_NOTEOFF (BYTE)(0x80)
|
||
|
#define MIDI_NOTEON (BYTE)(0x90)
|
||
|
#define MIDI_CONTROLCHANGE (BYTE)(0xB0)
|
||
|
#define MIDI_SYSEX (BYTE)(0xF0)
|
||
|
#define MIDI_TIMING_CLK (BYTE)(0xF8)
|
||
|
|
||
|
#define MIDI_SUSTAIN (BYTE)(0x40) // w/ MIDI_CONTROLCHANGE
|
||
|
|
||
|
//
|
||
|
// Indices into dwReserved[] fields of struct
|
||
|
//
|
||
|
// 0,1,2 -- MMSYSTEM (core, emulator)
|
||
|
// 3,4,5 -- MIDI mapper
|
||
|
// 6,7 -- DDK (3rd party drivers)
|
||
|
#define MH_REFCNT 0 // MMSYSTEM core (stream header only)
|
||
|
#define MH_PARENT 0 // MMSYSTEM core (shadow header only)
|
||
|
#define MH_STREAM 0 // Emulator (long msg header only)
|
||
|
#define MH_SHADOW 1 // MMSYSTEM core (stream header only)
|
||
|
#define MH_BUFIDX 1 // Emulator (shadow header only)
|
||
|
#define MH_STRMPME 2 // Emulator (shadow header, long msg header)
|
||
|
|
||
|
/*****************************************************************************
|
||
|
*
|
||
|
* @doc INTERNAL MIDI
|
||
|
*
|
||
|
* @types MIDIDRV | This structure contains all of the information about an
|
||
|
* open <t HMIDIIN> or <t HMIDIOUT> handle.
|
||
|
*
|
||
|
* @field HMD | hmd |
|
||
|
* Handle to media device for this driver.
|
||
|
*
|
||
|
* @field UINT | uDevice |
|
||
|
* Index of this device off of HMD (subunit number relative to this driver).
|
||
|
*
|
||
|
* @field DRIVERMSGPROC | drvMessage |
|
||
|
* Pointer to the associated driver entry point.
|
||
|
*
|
||
|
* @field DWORD | dwDrvUser |
|
||
|
* Driver user DWORD; used by driver to differentiate open instance. Set
|
||
|
* by driver on OPEN message; passed back to driver on every call.
|
||
|
*
|
||
|
* @field PMIDIDRV | pdevNext |
|
||
|
* Specifies the next handle in the linked list of open handles.
|
||
|
* (Only kept for <t HMIDIOUT> handles.
|
||
|
*
|
||
|
* @field UINT | uLockCount |
|
||
|
* Semaphore to serialize access to the handle structure between API calls
|
||
|
* and interrupt callbacks.
|
||
|
*
|
||
|
* @field DWORD | dwTimeDiv |
|
||
|
* The time division setting that is active right now during polymsg playback
|
||
|
* on this handle. The format is the same as described for
|
||
|
* <f midiOutSetTimeDivision>.
|
||
|
*
|
||
|
* @field DWORD | dwTempo |
|
||
|
* Current tempo for polymsg out in microseconds per quarter note (as in the
|
||
|
* Standard MIDI File specification).
|
||
|
*
|
||
|
* @field DWORD | dwPolyMsgState |
|
||
|
* The current state of polymsg playback for emulation.
|
||
|
* @flag PM_STATE_READY | Events may be played and are waiting.
|
||
|
* @flag PM_STATE_BLOCKED | Driver is busy sending SysEx; don't play anything
|
||
|
* else.
|
||
|
* @flag PM_STATE_EMPTY | Not busy but nothing else in the queue to play.
|
||
|
* @flag PM_STATE_PAUSED | Device has been paused with <f midiOutPause>.
|
||
|
*
|
||
|
* @field DWORD | dwSavedState |
|
||
|
* If the device is paused, this field will contain the state to be
|
||
|
* restored when restart occurs.
|
||
|
*
|
||
|
* @field LPMIDIHDR | lpmhFront |
|
||
|
* Front of queue of MIDIHDR's waiting to be played via polymsg in/out. The
|
||
|
* header pointed to by this field is the header currently being played/
|
||
|
* recorded.
|
||
|
*
|
||
|
* @field LPMIDIHDR | lpmhRear |
|
||
|
* End of MIDIHDR queue. Buffers are inserted from the app here.
|
||
|
*
|
||
|
* @field DWORD | dwCallback |
|
||
|
* Address of user callback.
|
||
|
*
|
||
|
* @field DWORD | dwFlags |
|
||
|
* User-supplied callback flags.
|
||
|
*
|
||
|
* @field BOOL | fEmulate |
|
||
|
* TRUE if we are emulating polymsg in/out.
|
||
|
*
|
||
|
* @field BOOL | fReset |
|
||
|
* TRUE if we're in the middle of a MIDM_RESET. Checked to see if we should
|
||
|
* give our shadow buffers back to the driver or retain them for cleanup.
|
||
|
*
|
||
|
* @field BOOL | fStarted |
|
||
|
* TRUE if MIDI input has been started.
|
||
|
*
|
||
|
* @field UINT | uCBTimeout |
|
||
|
* Time in milliseconds that a buffer can be help in MIDI input w/o being
|
||
|
* called back.
|
||
|
*
|
||
|
* @field UINT | uCBTimer |
|
||
|
* Timer ID of the timer which is being used to determine if a MIDI
|
||
|
* input buffer has been queued for too long.
|
||
|
*
|
||
|
* @field DWORD | dwInputBuffers |
|
||
|
* The maximum number of input buffers that have been prepared on this handle.
|
||
|
* Used for calculating shadow buffer pool.
|
||
|
*
|
||
|
* @field DWORD | cbInputBuffers |
|
||
|
* The maximum size of input buffer which has been prepared on this handle.
|
||
|
* Used for calculating shadow buffer pool.
|
||
|
*
|
||
|
* @field DWORD | dwShadowBuffers |
|
||
|
* The current number of shadow buffers allocated on this handle.
|
||
|
*
|
||
|
* @field CLOCK | clock |
|
||
|
* Clock maintained by the clock API's for timebase of both output and
|
||
|
* input emulation.
|
||
|
*
|
||
|
* @field DWORD | tkNextEventDue | Tick time of the next event due
|
||
|
* on polymsg emulation.
|
||
|
*
|
||
|
* @field TICKS | tkTimeOfLastEvent | Tick time that emulator sent the
|
||
|
* last event.
|
||
|
*
|
||
|
* @field DWORD | tkPlayed | Total ticks played on stream.
|
||
|
*
|
||
|
* @field DWORD | tkTime | Tick position in stream now.
|
||
|
*
|
||
|
* @field DWORD | dwTimebase | Flag indicating where timebase is coming
|
||
|
* from. May be one of:
|
||
|
* @flag MIDI_TBF_INTERNAL | Timebase is <f timeGetTime>
|
||
|
* @flag MIDI_TBF_MIDICLK | Timebase is MIDI input clocks.
|
||
|
*
|
||
|
* @field BYTE | rbNoteOn[] | Array of note-on counts per-channel per-note.
|
||
|
* Only allocated for output handles which are doing COOKED mode emulation.
|
||
|
*
|
||
|
*****************************************************************************/
|
||
|
|
||
|
#define ELESIZE(t,e) (sizeof(((t*)NULL)->e))
|
||
|
|
||
|
//#define MDV_F_EXPANDSTATUS 0x00000001L
|
||
|
#define MDV_F_EMULATE 0x00000002L
|
||
|
#define MDV_F_RESET 0x00000004L
|
||
|
#define MDV_F_STARTED 0x00000008L
|
||
|
#define MDV_F_ZOMBIE 0x00000010L
|
||
|
#define MDV_F_SENDING 0x00000020L
|
||
|
#define MDV_F_OWNED 0x00000040L
|
||
|
#define MDV_F_LOCKED 0x00000080L
|
||
|
|
||
|
#define MEM_MAX_LATENESS 64
|
||
|
|
||
|
|
||
|
typedef MMDRV MIDIDRV, *PMIDIDRV;
|
||
|
|
||
|
typedef struct midistrm_tag *PMIDISTRM;
|
||
|
typedef struct mididev_tag *PMIDIDEV;
|
||
|
typedef struct midiemu_tag *PMIDIEMU;
|
||
|
|
||
|
typedef struct mididev_tag {
|
||
|
PMIDIDRV mididrv;
|
||
|
UINT wDevice;
|
||
|
DWORD dwDrvUser;
|
||
|
UINT uDeviceID;
|
||
|
PMIDIDEV pmThru; /* pointer to midi thru device */
|
||
|
PMIDIEMU pme; /* Iff owned by emulator */
|
||
|
} MIDIDEV;
|
||
|
typedef MIDIDEV *PMIDIDEV;
|
||
|
|
||
|
extern MIDIDRV midioutdrv[MAXMIDIDRIVERS+1]; /* output device driver list */
|
||
|
extern MIDIDRV midiindrv[MAXMIDIDRIVERS+1]; /* input device driver list */
|
||
|
extern UINT wTotalMidiOutDevs; /* total midi output devices */
|
||
|
extern UINT wTotalMidiInDevs; /* total midi input devices */
|
||
|
|
||
|
typedef struct midiemusid_tag {
|
||
|
DWORD dwStreamID;
|
||
|
HMIDI hMidi;
|
||
|
} MIDIEMUSID, *PMIDIEMUSID;
|
||
|
|
||
|
typedef struct midiemu_tag {
|
||
|
PMIDIEMU pNext;
|
||
|
HMIDISTRM hStream;
|
||
|
DWORD fdwDev;
|
||
|
LONG lLockCount; // Must be 32-bit aligned
|
||
|
CRITICAL_SECTION CritSec; // Serialize access
|
||
|
DWORD dwSignature; // Cookie to keep track of validity
|
||
|
DWORD dwTimeDiv; // Time division in use right now
|
||
|
DWORD dwTempo; // Current tempo
|
||
|
DWORD dwPolyMsgState; // Ready or blocked on SysEx
|
||
|
DWORD dwSavedState; // State saved when paused
|
||
|
LPMIDIHDR lpmhFront ; // Front of PolyMsg queue
|
||
|
LPMIDIHDR lpmhRear ; // Rear of PolyMsg queue
|
||
|
DWORD dwCallback; // User callback
|
||
|
DWORD dwFlags; // User callback flags
|
||
|
DWORD dwInstance;
|
||
|
DWORD dwSupport; // From MODM_GETDEVCAPS
|
||
|
BYTE bRunningStatus; // Track running status
|
||
|
|
||
|
//
|
||
|
// Rewrite midiOutPolyMsg timekeeping - new stuff!!!
|
||
|
//
|
||
|
CLOCK clock;
|
||
|
|
||
|
TICKS tkNextEventDue; // Tick time of next event
|
||
|
TICKS tkTimeOfLastEvent; // Tick time of last received event
|
||
|
TICKS tkPlayed; // Cumulative ticks played so far
|
||
|
TICKS tkTime; // Tick position in stream *NOW*
|
||
|
|
||
|
LPBYTE rbNoteOn; // Count of notes on per channel per note
|
||
|
|
||
|
UINT cSentLongMsgs; // Oustanding long messages
|
||
|
|
||
|
UINT chMidi; // # Stream ID's
|
||
|
|
||
|
UINT cPostedBuffers; // Posted to mmtask for cleanup
|
||
|
|
||
|
#ifdef DEBUG
|
||
|
DWORD cEvents;
|
||
|
UINT auLateness[MEM_MAX_LATENESS];
|
||
|
// 0..64 milliseconds late
|
||
|
#endif
|
||
|
|
||
|
MIDIEMUSID rIds[]; // HMIDI's indexed by stream ID
|
||
|
} MIDIEMU;
|
||
|
|
||
|
#define MSI_F_EMULATOR 0x00000001L
|
||
|
#define MSI_F_FIRST 0x00000002L
|
||
|
#define MSI_F_OPENED 0x00000004L
|
||
|
|
||
|
#define MSE_SIGNATURE 0x12341234L
|
||
|
|
||
|
typedef struct midistrmid_tag {
|
||
|
HMD hmd;
|
||
|
UINT uDevice;
|
||
|
DRIVERMSGPROC drvMessage;
|
||
|
DWORD dwDrvUser;
|
||
|
DWORD fdwId;
|
||
|
CRITICAL_SECTION CritSec;
|
||
|
} MIDISTRMID, *PMIDISTRMID;
|
||
|
|
||
|
#define MDS_F_STOPPING 0x00000001L
|
||
|
|
||
|
typedef struct midistrm_tag {
|
||
|
DWORD fdwOpen;
|
||
|
DWORD fdwStrm;
|
||
|
DWORD dwCallback;
|
||
|
DWORD dwInstance;
|
||
|
LPMIDIHDR lpmhFront;
|
||
|
LPMIDIHDR lpmhRear;
|
||
|
DWORD cDrvrs; // # unique drivers in rgIds[]
|
||
|
DWORD cIds;
|
||
|
MIDISTRMID rgIds[];
|
||
|
} MIDISTRM;
|
||
|
|
||
|
|
||
|
/*****************************************************************************
|
||
|
*
|
||
|
* @doc INTERNAL MIDI
|
||
|
*
|
||
|
* @types MIDIHDREXT |
|
||
|
* This structure is allocated by <f midiOutPolyMsg> and is pointed to by the
|
||
|
* <t reserved> field of the associated <t MIDIHDR>. It contains information
|
||
|
* about what embedded long messages are in the polymsg buffer described
|
||
|
* by the MIDIHDR.
|
||
|
*
|
||
|
* The <t MIDIHDREXT> is followed by multiple <t MIDIDHR> structures, also
|
||
|
* allocated by <f midiOutPolyMsg>, which describe each of the embedded
|
||
|
* long messages which need to be played.
|
||
|
*
|
||
|
* @field DWORD | dwTimeDivision |
|
||
|
* The time division specified with <f midiOutPolyMsg> to play this buffer
|
||
|
* with.
|
||
|
*
|
||
|
* @field UINT | nHeaders |
|
||
|
* The number of <t MIDIHDR> structures which follow the end of this
|
||
|
* <MIDIHDREXT>.
|
||
|
*
|
||
|
* @field LPMIDIHDR | lpmidihdr |
|
||
|
* Pointer to the next <t MIDIHDR> structure due to be played.
|
||
|
*
|
||
|
*
|
||
|
*****************************************************************************/
|
||
|
typedef struct midihdrext_tag {
|
||
|
UINT nHeaders ;
|
||
|
LPMIDIHDR lpmidihdr ;
|
||
|
} MIDIHDREXT, FAR *LPMIDIHDREXT ;
|
||
|
|
||
|
extern HANDLE g_hClosepme;
|
||
|
|
||
|
/*
|
||
|
* Internal prototypes for MIDI
|
||
|
*/
|
||
|
extern STATIC DWORD MapMidiId(PMIDIDRV mididrv, UINT wTotalNumDevs, UINT id);
|
||
|
|
||
|
|
||
|
extern BOOL FAR PASCAL midiLockPageable(void);
|
||
|
extern void NEAR PASCAL midiUnlockPageable(void);
|
||
|
extern MMRESULT NEAR PASCAL midiPrepareHeader(LPMIDIHDR lpMidiHdr, UINT wSize);
|
||
|
extern MMRESULT NEAR PASCAL midiUnprepareHeader(LPMIDIHDR lpMidiHdr, UINT wSize);
|
||
|
extern STATIC MMRESULT midiMessage(HMIDI hMidi, UINT msg, DWORD dwP1, DWORD dwP2);
|
||
|
extern DWORD FAR PASCAL midiStreamMessage(PMIDISTRMID pmsi, UINT msg, DWORD dwP1, DWORD dwP2);
|
||
|
extern DWORD FAR PASCAL midiStreamBroadcast(PMIDISTRM pms, UINT msg, DWORD dwP1, DWORD dwP2);
|
||
|
extern STATIC MMRESULT midiIDMessage(PMIDIDRV mididrv, UINT wTotalNumDevs, UINT uDeviceID, UINT wMessage, DWORD dwParam1, DWORD dwParam2);
|
||
|
extern MMRESULT NEAR PASCAL midiGetPosition(PMIDISTRM pms, LPMMTIME pmmt, UINT cbmmt);
|
||
|
extern MMRESULT NEAR PASCAL midiGetErrorText(MMRESULT wError, LPSTR lpText, UINT wSize);
|
||
|
|
||
|
|
||
|
extern MMRESULT WINAPI midiOutGetID(HMIDIOUT hMidiOut, UINT FAR* lpuDeviceID);
|
||
|
extern MMRESULT FAR PASCAL mseOutSend(PMIDIEMU pme, LPMIDIHDR lpMidiHdr, UINT cbMidiHdr);
|
||
|
extern void FAR PASCAL midiOutSetClockRate(PMIDIEMU pme, TICKS tkWhen);
|
||
|
extern BOOL NEAR PASCAL midiOutScheduleNextEvent(PMIDIEMU pme);
|
||
|
#ifdef DEBUG
|
||
|
extern void NEAR PASCAL midiOutPlayNextPolyEvent(PMIDIEMU pme, DWORD dwStartTime);
|
||
|
#else
|
||
|
extern void NEAR PASCAL midiOutPlayNextPolyEvent(PMIDIEMU pme);
|
||
|
#endif
|
||
|
|
||
|
extern void NEAR PASCAL midiOutDequeueAndCallback(PMIDIEMU pme);
|
||
|
extern void FAR PASCAL midiOutNukePMBuffer(PMIDIEMU pme, LPMIDIHDR lpmh);
|
||
|
extern void CALLBACK midiOutTimerTick(UINT uTimerID, UINT wMsg, DWORD dwUser, DWORD dw1, DWORD dw2);
|
||
|
extern void CALLBACK midiOutCallback(HMIDIOUT hMidiOut, WORD wMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2);
|
||
|
extern void NEAR PASCAL midiOutAllNotesOff(PMIDIEMU pme);
|
||
|
|
||
|
extern void CALLBACK midiOutStreamCallback(HMIDISTRM hMidiOut, WORD wMsg, DWORD dwInstance, DWORD dwParam1, DWORD dwParam2);
|
||
|
|
||
|
extern MMRESULT midiInSetThru (HMIDI hmi, HMIDIOUT hmo, BOOL bAdd);
|
||
|
|
||
|
// mseXXX - MIDI Stream Emulator
|
||
|
//
|
||
|
extern DWORD FAR PASCAL mseMessage(UINT msg, DWORD dwUser, DWORD dwParam1, DWORD dwParam2);
|
||
|
|
||
|
|
||
|
#endif /* ifndef MMNOMIDI */
|
||
|
|
||
|
#ifndef MMNOWAVE
|
||
|
|
||
|
typedef MMDRV WAVEDRV, *PWAVEDRV;
|
||
|
|
||
|
extern WAVEDRV waveoutdrv[MAXWAVEDRIVERS+1]; /* output device driver list */
|
||
|
extern WAVEDRV waveindrv[MAXWAVEDRIVERS+1]; /* input device driver list */
|
||
|
extern UINT wTotalWaveOutDevs; /* total wave output devices */
|
||
|
extern UINT wTotalWaveInDevs; /* total wave input devices */
|
||
|
|
||
|
extern STATIC DWORD MapWaveId(PWAVEDRV wavedrv, UINT wTotalNumDevs, UINT id);
|
||
|
|
||
|
#endif /*ifndef MMNOWAVE */
|
||
|
|
||
|
#ifndef MMNOAUX
|
||
|
|
||
|
typedef MMDRV AUXDRV, *PAUXDRV;
|
||
|
|
||
|
extern AUXDRV auxdrv[MAXAUXDRIVERS+1]; /* auxiliary device driver list */
|
||
|
extern UINT wTotalAuxDevs; /* total auxiliary output devices */
|
||
|
|
||
|
extern STATIC DWORD MapAuxId(UINT id);
|
||
|
|
||
|
#endif /* ifndef MMNOAUX */
|
||
|
|
||
|
#ifdef DEBUG_RETAIL
|
||
|
extern BYTE fIdReverse;
|
||
|
#endif /* ifdef DEBUG_RETAIL */
|
||
|
|
||
|
#endif //ifdef MMDDKINC
|
||
|
|
||
|
/****************************************************************************
|
||
|
|
||
|
handle apis's
|
||
|
|
||
|
****************************************************************************/
|
||
|
|
||
|
/*
|
||
|
// all MMSYSTEM handles are tagged with the following structure.
|
||
|
//
|
||
|
// a MMSYSTEM handle is really a fixed local memory object.
|
||
|
//
|
||
|
// the functions NewHandle() and FreeHandle() create and release a MMSYSTEM
|
||
|
// handle.
|
||
|
//
|
||
|
*/
|
||
|
typedef struct tagHNDL {
|
||
|
struct tagHNDL *pNext; // link to next handle
|
||
|
UINT uType; // type of handle wave, midi, mmio, ...
|
||
|
HANDLE hThread; // task that owns it
|
||
|
UINT h16; // Corresponding WOW handle
|
||
|
CRITICAL_SECTION CritSec; // Serialize access
|
||
|
} HNDL, *PHNDL;
|
||
|
/*************************************************************************/
|
||
|
|
||
|
#define HtoPH(h) ((PHNDL)(h)-1)
|
||
|
#define PHtoH(ph) ((ph) ? (HANDLE)((PHNDL)(ph)+1) : 0)
|
||
|
#define HtoPT(t,h) ((t)(h))
|
||
|
#define PTtoH(t,pt) ((t)(pt))
|
||
|
|
||
|
|
||
|
//
|
||
|
// Handles can be tested for ownership and reserved at the same time
|
||
|
//
|
||
|
|
||
|
#define ENTER_MM_HANDLE(h) (EnterCriticalSection(&HtoPH(h)->CritSec))
|
||
|
#define LEAVE_MM_HANDLE(h) ((void)LeaveCriticalSection(&HtoPH(h)->CritSec))
|
||
|
|
||
|
/*
|
||
|
// all wave and midi handles will be linked into
|
||
|
// a global list, so we can enumerate them latter if needed.
|
||
|
//
|
||
|
// all handle structures start with a HNDL structure, that contain common fields
|
||
|
//
|
||
|
// pHandleList points to the first handle in the list
|
||
|
//
|
||
|
// HandleListCritSec protects the handle list
|
||
|
//
|
||
|
// the NewHandle() and FreeHandle() functions are used to add/remove
|
||
|
// a handle to/from the list
|
||
|
*/
|
||
|
|
||
|
PHNDL pHandleList;
|
||
|
CRITICAL_SECTION HandleListCritSec;
|
||
|
|
||
|
extern HANDLE NewHandle(UINT uType, UINT size);
|
||
|
extern void FreeHandle(HANDLE h);
|
||
|
|
||
|
#define GetHandleType(h) (HtoPH(h)->uType)
|
||
|
#define GetHandleOwner(h) (HtoPH(h)->hThread)
|
||
|
#define GetHandleFirst() (PHtoH(pHandleList))
|
||
|
#define GetHandleNext(h) (PHtoH(HtoPH(h)->pNext))
|
||
|
#define SetHandleOwner(h,hOwn) (HtoPH(h)->hThread = (hOwn))
|
||
|
|
||
|
#define GetWOWHandle(h) (HtoPH(h)->h16)
|
||
|
#define SetWOWHandle(h, myh16) (HtoPH(h)->h16 = (myh16))
|
||
|
|
||
|
/**************************************************************************
|
||
|
|
||
|
Test whether the current process is the WOW process. This
|
||
|
is not a very nice test to have to make but it's the best we
|
||
|
can think of until the WOW people come up with a proper call
|
||
|
|
||
|
**************************************************************************/
|
||
|
|
||
|
#define IS_WOW_PROCESS (NULL != GetModuleHandleW(L"WOW32.DLL"))
|
||
|
|
||
|
|
||
|
/****************************************************************************
|
||
|
|
||
|
user debug support
|
||
|
|
||
|
****************************************************************************/
|
||
|
|
||
|
#define DebugErr(x,y) /* BUGBUG - put in error logging later */
|
||
|
#define DebugErr1(flags, sz, a)
|
||
|
|
||
|
#ifdef DEBUG_RETAIL
|
||
|
|
||
|
#define MM_GET_DEBUG DRV_USER
|
||
|
#define MM_GET_DEBUGOUT DRV_USER+1
|
||
|
#define MM_SET_DEBUGOUT DRV_USER+2
|
||
|
#define MM_GET_MCI_DEBUG DRV_USER+3
|
||
|
#define MM_SET_MCI_DEBUG DRV_USER+4
|
||
|
#define MM_GET_MM_DEBUG DRV_USER+5
|
||
|
#define MM_SET_MM_DEBUG DRV_USER+6
|
||
|
|
||
|
#define MM_HINFO_NEXT DRV_USER+10
|
||
|
#define MM_HINFO_TASK DRV_USER+11
|
||
|
#define MM_HINFO_TYPE DRV_USER+12
|
||
|
#define MM_HINFO_MCI DRV_USER+20
|
||
|
|
||
|
#define MM_DRV_RESTART DRV_USER+30
|
||
|
|
||
|
/*
|
||
|
// these validation routines can be found in DEBUG.C
|
||
|
*/
|
||
|
// The kernel validation is turned OFF because it appeared to test every page
|
||
|
// before use and this took over a minute for soundrec with a 10MB buffer
|
||
|
//
|
||
|
//#define USE_KERNEL_VALIDATION
|
||
|
#ifdef USE_KERNEL_VALIDATION
|
||
|
|
||
|
#define ValidateReadPointer(p, len) (!IsBadReadPtr(p, len))
|
||
|
#define ValidateWritePointer(p, len) (!IsBadWritePtr(p, len))
|
||
|
#define ValidateString(lsz, max_len) (!IsBadStringPtrA(lsz, max_len))
|
||
|
#define ValidateStringW(lsz, max_len) (!IsBadStringPtrW(lsz, max_len))
|
||
|
|
||
|
#else
|
||
|
|
||
|
BOOL ValidateReadPointer(LPVOID p, DWORD len);
|
||
|
BOOL ValidateWritePointer(LPVOID p, DWORD len);
|
||
|
BOOL ValidateString(LPCSTR lsz, DWORD max_len);
|
||
|
BOOL ValidateStringW(LPCWSTR lsz, DWORD max_len);
|
||
|
|
||
|
#endif // USE_KERNEL_VALIDATION
|
||
|
|
||
|
BOOL ValidateHandle(HANDLE h, UINT uType);
|
||
|
BOOL ValidateHeader(LPVOID p, UINT uSize, UINT uType);
|
||
|
BOOL ValidateCallbackType(DWORD dwCallback, UINT uType);
|
||
|
|
||
|
/********************************************************************
|
||
|
* When time permits we should change to using the Kernel supplied and
|
||
|
* supported validation routines:
|
||
|
*
|
||
|
* BOOL WINAPI IsBadReadPtr(CONST VOID *lp, UINT ucb );
|
||
|
* BOOL WINAPI IsBadWritePtr(LPVOID lp, UINT ucb );
|
||
|
* BOOL WINAPI IsBadHugeReadPtr(CONST VOID *lp, UINT ucb);
|
||
|
* BOOL WINAPI IsBadHugeWritePtr(LPVOID lp, UINT ucb);
|
||
|
* BOOL WINAPI IsBadCodePtr(FARPROC lpfn);
|
||
|
* BOOL WINAPI IsBadStringPtrA(LPCSTR lpsz, UINT ucchMax);
|
||
|
* BOOL WINAPI IsBadStringPtrW(LPCWSTR lpsz, UINT ucchMax);
|
||
|
*
|
||
|
* These routines can be found in * \nt\private\WINDOWS\BASE\CLIENT\PROCESS.C
|
||
|
*
|
||
|
********************************************************************/
|
||
|
|
||
|
#define V_HANDLE(h, t, r) { if (!ValidateHandle(h, t)) return (r); }
|
||
|
#define BAD_HANDLE(h, t) ( !(ValidateHandle((h), (t))) )
|
||
|
#define V_HEADER(p, w, t, r) { if (!ValidateHeader((p), (w), (t))) return (r); }
|
||
|
#define V_RPOINTER(p, l, r) { if (!ValidateReadPointer((PVOID)(p), (l))) return (r); }
|
||
|
#define V_RPOINTER0(p, l, r) { if ((p) && !ValidateReadPointer((PVOID)(p), (l))) return (r); }
|
||
|
#define V_WPOINTER(p, l, r) { if (!ValidateWritePointer((PVOID)(p), (l))) return (r); }
|
||
|
#define V_WPOINTER0(p, l, r) { if ((p) && !ValidateWritePointer((PVOID)(p), (l))) return (r); }
|
||
|
#define V_DCALLBACK(d, w, r) { if ((d) && !ValidateCallbackType((d), (w))) return(r); }
|
||
|
//#define V_DCALLBACK(d, w, r) 0
|
||
|
#define V_TCALLBACK(d, r) 0
|
||
|
#define V_CALLBACK(f, r) { if (IsBadCodePtr((f))) return (r); }
|
||
|
#define V_CALLBACK0(f, r) { if ((f) && IsBadCodePtr((f))) return (r); }
|
||
|
#define V_STRING(s, l, r) { if (!ValidateString(s,l)) return (r); }
|
||
|
#define V_STRING_W(s, l, r) { if (!ValidateStringW(s,l)) return (r); }
|
||
|
#define V_FLAGS(t, b, f, r) { if ((t) & ~(b)) { return (r); }}
|
||
|
#define V_DFLAGS(t, b, f, r) { if ((t) & ~(b)) {/* LogParamError(ERR_BAD_DFLAGS, (FARPROC)(f), (LPVOID)(DWORD)(t));*/ return (r); }}
|
||
|
#define V_MMSYSERR(e, f, t, r) { /* LogParamError(e, (FARPROC)(f), (LPVOID)(DWORD)(t));*/ return (r); }
|
||
|
|
||
|
#else /*ifdef DEBUG_RETAIL */
|
||
|
|
||
|
#define V_HANDLE(h, t, r) { if (!(h)) return (r); }
|
||
|
#define BAD_HANDLE(h, t) ( !(ValidateHandle((h), (t))) )
|
||
|
#define V_HEADER(p, w, t, r) { if (!(p)) return (r); }
|
||
|
#define V_RPOINTER(p, l, r) { if (!(p)) return (r); }
|
||
|
#define V_RPOINTER0(p, l, r) 0
|
||
|
#define V_WPOINTER(p, l, r) { if (!(p)) return (r); }
|
||
|
#define V_WPOINTER0(p, l, r) 0
|
||
|
#define V_DCALLBACK(d, w, r) { if ((d) && !ValidateCallbackType((d), (w))) return(r); }
|
||
|
//#define V_DCALLBACK(d, w, r) 0
|
||
|
#define V_TCALLBACK(d, r) 0
|
||
|
#define V_CALLBACK(f, r) { if (IsBadCodePtr((f))) return (r); }
|
||
|
#define V_CALLBACK0(f, r) { if ((f) && IsBadCodePtr((f))) return (r); }
|
||
|
//#define V_CALLBACK(f, r) { if (!(f)) return (r); }
|
||
|
#define V_CALLBACK0(f, r) 0
|
||
|
#define V_STRING(s, l, r) { if (!(s)) return (r); }
|
||
|
#define V_STRING_W(s, l, r) { if (!(s)) return (r); }
|
||
|
#define V_FLAGS(t, b, f, r) 0
|
||
|
#define V_DFLAGS(t, b, f, r) { if ((t) & ~(b)) return (r); }
|
||
|
#define V_MMSYSERR(e, f, t, r) { return (r); }
|
||
|
|
||
|
#endif /* ifdef DEBUG_RETAIL */
|
||
|
|
||
|
/**************************************************************************
|
||
|
//
|
||
|
//**************************************************************************/
|
||
|
#define TYPE_UNKNOWN 0
|
||
|
#define TYPE_WAVEOUT 1
|
||
|
#define TYPE_WAVEIN 2
|
||
|
#define TYPE_MIDIOUT 3
|
||
|
#define TYPE_MIDIIN 4
|
||
|
#define TYPE_MMIO 5
|
||
|
#define TYPE_MCI 6
|
||
|
#define TYPE_DRVR 7
|
||
|
#define TYPE_MIXER 8
|
||
|
#define TYPE_MIDISTRM 9
|
||
|
#define TYPE_AUX 10
|
||
|
|
||
|
|
||
|
|
||
|
/**************************************************************************/
|
||
|
|
||
|
|
||
|
/****************************************************************************
|
||
|
|
||
|
RIFF constants used to access wave files
|
||
|
|
||
|
****************************************************************************/
|
||
|
|
||
|
#define FOURCC_FMT mmioFOURCC('f', 'm', 't', ' ')
|
||
|
#define FOURCC_DATA mmioFOURCC('d', 'a', 't', 'a')
|
||
|
#define FOURCC_WAVE mmioFOURCC('W', 'A', 'V', 'E')
|
||
|
|
||
|
|
||
|
extern HWND hwndNotify;
|
||
|
|
||
|
void FAR PASCAL WaveOutNotify(DWORD wParam, LONG lParam); // in PLAYWAV.C
|
||
|
|
||
|
/*
|
||
|
// Things not in Win32
|
||
|
*/
|
||
|
|
||
|
#define GetCurrentTask() ((HANDLE)GetCurrentThreadId())
|
||
|
|
||
|
/*
|
||
|
// other stuff
|
||
|
*/
|
||
|
|
||
|
// Maximum length, including the terminating NULL, of an Scheme entry.
|
||
|
//
|
||
|
#define SCH_TYPE_MAX_LENGTH 64
|
||
|
|
||
|
// Maximum length, including the terminating NULL, of an Event entry.
|
||
|
//
|
||
|
#define EVT_TYPE_MAX_LENGTH 32
|
||
|
|
||
|
// Maximum length, including the terminating NULL, of an App entry.
|
||
|
//
|
||
|
#define APP_TYPE_MAX_LENGTH 64
|
||
|
|
||
|
// Sound event names can be a fully qualified filepath with a NULL
|
||
|
// terminator.
|
||
|
//
|
||
|
#define MAX_SOUND_NAME_CHARS 144
|
||
|
|
||
|
// sound atom names are composed of:
|
||
|
// <1 char id>
|
||
|
// <reg key name>
|
||
|
// <1 char sep>
|
||
|
// <filepath>
|
||
|
//
|
||
|
#define MAX_SOUND_ATOM_CHARS (1 + 40 + 1 + MAX_SOUND_NAME_CHARS)
|
||
|
|
||
|
#if 0
|
||
|
#undef hmemcpy
|
||
|
#define hmemcpy CopyMemory
|
||
|
#endif
|
||
|
|
||
|
#endif /* WINMMI_H */
|