home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
magazine
/
pcmagazi
/
1992
/
14
/
midbuf.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-04-15
|
26KB
|
812 lines
/*-------------------------------------------------------------------
MIDBUF.C -- Dynamic Link Library for Buffered MIDI Short Messages
(c) Charles Petzold
-------------------------------------------------------------------*/
#include <windows.h>
#include <mmsystem.h>
// Definitions of handle and structure for buffered MIDI input
// -----------------------------------------------------------
typedef UINT HMIDIBUFIN ;
typedef HMIDIBUFIN FAR * LPHMIDIBUFIN ;
typedef struct
{
HMIDIBUFIN hMidiBufIn ; // Used to verify validity of handle
HMIDIIN hMidiIn ; // Real MIDI input handle
DWORD dwCallBack ; // Callback passed in open function
DWORD dwUser ; // Application data passed in open function
DWORD dwFlags ; // Flags passed in open function
LPMIDIHDR lpmh ; // Pointer to first MIDIHDR structure
DWORD dwLastTime ; // Used to calculate delta-times
DWORD dwStartTime ; // Used to time-stamp whole buffers
}
MIDIBUFIN ;
typedef MIDIBUFIN * PMIDIBUFIN ;
// Definitions of handle and structure for buffered MIDI output
// ------------------------------------------------------------
typedef UINT HMIDIBUFOUT ;
typedef HMIDIBUFOUT FAR * LPHMIDIBUFOUT ;
typedef struct
{
HMIDIBUFOUT hMidiBufOut ; // Used to verify validity of handle
HMIDIOUT hMidiOut ; // Real MIDI output handle
DWORD dwCallBack ; // Callback passed in open function
DWORD dwUser ; // Application data passed in open function
DWORD dwFlags ; // Flags passed in open function
LPMIDIHDR lpmh ; // Pointer to first MIDIHDR structure
DWORD dwDataPtr ; // Pointer to current data in buffer
DWORD dwTime ; // Time before next output event
UINT iTimerID ; // ID of multimedia timer
BOOL bPaused ; // Flag if paused playing
}
MIDIBUFOUT ;
typedef MIDIBUFOUT * PMIDIBUFOUT ;
// Other miscellaneous definitions
// -------------------------------
typedef void (FAR PASCAL * MMCALLBACK) (UINT, UINT, DWORD, DWORD, DWORD) ;
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
#define MINMAX(a,x,b) (MIN (MAX (x, a), b))
// Prevent name-mangling for exported functions
// --------------------------------------------
extern "C"
{
UINT FAR PASCAL xMidiInAddBuffer (HMIDIBUFIN, LPMIDIHDR, UINT) ;
UINT FAR PASCAL xMidiInClose (HMIDIBUFIN) ;
UINT FAR PASCAL xMidiInGetID (HMIDIBUFIN, UINT FAR *) ;
DWORD FAR PASCAL xMidiInMessage (HMIDIBUFIN, UINT, DWORD, DWORD) ;
UINT FAR PASCAL xMidiInOpen (LPHMIDIBUFIN, UINT, DWORD, DWORD, DWORD) ;
UINT FAR PASCAL xMidiInPrepareHeader (HMIDIBUFIN, LPMIDIHDR, UINT) ;
UINT FAR PASCAL xMidiInReset (HMIDIBUFIN) ;
UINT FAR PASCAL xMidiInShortBuffer (HMIDIBUFIN, LPMIDIHDR, UINT) ;
UINT FAR PASCAL xMidiInStart (HMIDIBUFIN) ;
UINT FAR PASCAL xMidiInStop (HMIDIBUFIN) ;
UINT FAR PASCAL xMidiInUnprepareHeader (HMIDIBUFIN, LPMIDIHDR, UINT) ;
UINT FAR PASCAL xMidiOutCacheDrumPatches (HMIDIBUFOUT, UINT, LPKEYARRAY, UINT);
UINT FAR PASCAL xMidiOutCachePatches (HMIDIBUFOUT, UINT, LPPATCHARRAY, UINT) ;
UINT FAR PASCAL xMidiOutClose (HMIDIBUFOUT) ;
UINT FAR PASCAL xMidiOutGetID (HMIDIBUFOUT, UINT FAR *) ;
UINT FAR PASCAL xMidiOutLongMsg (HMIDIBUFOUT, LPMIDIHDR, UINT) ;
DWORD FAR PASCAL xMidiOutMessage (HMIDIBUFOUT, UINT, DWORD, DWORD) ;
UINT FAR PASCAL xMidiOutOpen (LPHMIDIBUFOUT, UINT, DWORD, DWORD, DWORD) ;
UINT FAR PASCAL xMidiOutPause (HMIDIBUFOUT) ;
UINT FAR PASCAL xMidiOutPrepareHeader (HMIDIBUFOUT, LPMIDIHDR, UINT) ;
UINT FAR PASCAL xMidiOutReset (HMIDIBUFOUT) ;
UINT FAR PASCAL xMidiOutRestart (HMIDIBUFOUT) ;
UINT FAR PASCAL xMidiOutShortBuffer (HMIDIBUFOUT, LPMIDIHDR, UINT) ;
UINT FAR PASCAL xMidiOutShortMsg (HMIDIBUFOUT, DWORD) ;
UINT FAR PASCAL xMidiOutUnprepareHeader (HMIDIBUFOUT, LPMIDIHDR, UINT) ;
}
// The only global variable (set during LibMain)
// ---------------------------------------------
TIMECAPS tc ;
// Initialization routine: Do not unlock data segment!
// ---------------------------------------------------
int FAR PASCAL LibMain (HANDLE hInstance, UINT wDataSeg, UINT wHeapSize,
LPSTR lpszCmdLine)
{
timeGetDevCaps (&tc, sizeof (TIMECAPS)) ;
return 1 ;
}
// MidiInCallBack: Call-back function for MIDI input
// --------------------------------------------------
void FAR PASCAL _export MidiInCallBack (HMIDIIN hMidiIn, UINT wMsg,
DWORD dwUser, DWORD dw1, DWORD dw2)
{
DWORD huge * lpData ;
HMIDIBUFIN hMidiBufIn ;
PMIDIBUFIN pmb ;
LPMIDIHDR lpmh ;
// Get some useful information
pmb = (PMIDIBUFIN) dwUser ;
hMidiBufIn = pmb->hMidiBufIn ;
// Post message to window or call callback function
if ((pmb->dwFlags & CALLBACK_TYPEMASK) == CALLBACK_WINDOW)
PostMessage ((HWND) pmb->dwCallBack, wMsg, hMidiBufIn, dw1) ;
if ((pmb->dwFlags & CALLBACK_TYPEMASK) == CALLBACK_FUNCTION)
((MMCALLBACK) pmb->dwCallBack) (hMidiBufIn, wMsg, pmb->dwUser,
dw1, dw2) ;
// For DATA messages, try to store them in a buffer
if (wMsg == MIM_DATA)
{
// If no MIDIHDR present, can't store data
if (NULL == (lpmh = pmb->lpmh))
return ;
// Do not store Active Sensing messages
if (dw1 == 0x000000FE)
return ;
// Store the data -- delta time first then MIDI message
lpData = (DWORD huge *) lpmh->lpData ;
lpData [lpmh->dwBytesRecorded / 4] = dw2 - pmb->dwLastTime ;
lpmh->dwBytesRecorded += 4 ;
lpData [lpmh->dwBytesRecorded / 4] = dw1 ;
lpmh->dwBytesRecorded += 4 ;
// Save the latest time stamp
pmb->dwLastTime = dw2 ;
// If at the end of a buffer, get the next one,
// and post a LONGDATA message
if (lpmh->dwBytesRecorded + 8 > lpmh->dwBufferLength)
{
pmb->lpmh = lpmh->lpNext ;
lpmh->dwFlags |= MHDR_DONE ;
if ((pmb->dwFlags & CALLBACK_TYPEMASK) == CALLBACK_WINDOW)
PostMessage ((HWND) pmb->dwCallBack, MM_MIM_LONGDATA,
hMidiBufIn, (DWORD) lpmh) ;
if ((pmb->dwFlags & CALLBACK_TYPEMASK) == CALLBACK_FUNCTION)
((MMCALLBACK) pmb->dwCallBack) (hMidiBufIn, MIM_LONGDATA,
pmb->dwUser, (DWORD) lpmh, dw2) ;
}
}
}
// MidiInValidateHandle: Convert handle to pointer and validate it
// ----------------------------------------------------------------
PMIDIBUFIN MidiInValidateHandle (HMIDIBUFIN hMidiBufIn)
{
PMIDIBUFIN pmb ;
pmb = (PMIDIBUFIN) hMidiBufIn ;
if (pmb == NULL || pmb->hMidiBufIn != hMidiBufIn)
return NULL ;
return pmb ;
}
// MidiInAddBuffer: Pass through
// ------------------------------
UINT FAR PASCAL xMidiInAddBuffer (HMIDIBUFIN hMidiBufIn,
LPMIDIHDR lpmh, UINT wSize)
{
PMIDIBUFIN pmb ;
if (NULL == (pmb = MidiInValidateHandle (hMidiBufIn)))
return MMSYSERR_INVALHANDLE ;
return midiInAddBuffer (pmb->hMidiIn, lpmh, wSize) ;
}
// MidiInClose: Free the handle
// -----------------------------
UINT FAR PASCAL xMidiInClose (HMIDIBUFIN hMidiBufIn)
{
PMIDIBUFIN pmb ;
UINT wError ;
if (NULL == (pmb = MidiInValidateHandle (hMidiBufIn)))
return MMSYSERR_INVALHANDLE ;
if (0L == (wError = midiInClose (pmb->hMidiIn)))
{
if (pmb->lpmh != NULL)
return MIDIERR_STILLPLAYING ;
LocalFree (hMidiBufIn) ;
}
return wError ;
}
// MidiInGetID: Pass through
// --------------------------
UINT FAR PASCAL xMidiInGetID (HMIDIBUFIN hMidiBufIn, UINT FAR * lpiDeviceID)
{
PMIDIBUFIN pmb ;
if (NULL == (pmb = MidiInValidateHandle (hMidiBufIn)))
return MMSYSERR_INVALHANDLE ;
return midiInGetID (pmb->hMidiIn, lpiDeviceID) ;
}
// MidiInMessage: Pass through
// ----------------------------
DWORD FAR PASCAL xMidiInMessage (HMIDIBUFIN hMidiBufIn, UINT msg,
DWORD dw1, DWORD dw2)
{
PMIDIBUFIN pmb ;
if (NULL == (pmb = MidiInValidateHandle (hMidiBufIn)))
return MMSYSERR_INVALHANDLE ;
return midiInMessage (pmb->hMidiIn, msg, dw1, dw2) ;
}
// MidiInOpen: Allocate handle and initialize stuff
// -------------------------------------------------
UINT FAR PASCAL xMidiInOpen (LPHMIDIBUFIN lphMidiBufIn,
UINT wID, DWORD dwCallBack,
DWORD dwUser, DWORD dwFlags)
{
HMIDIBUFIN hMidiBufIn ;
PMIDIBUFIN pmb ;
UINT wError ;
if (NULL == (hMidiBufIn = LocalAlloc (LPTR, sizeof (MIDIBUFIN))))
MMSYSERR_NOMEM ;
pmb = (PMIDIBUFIN) hMidiBufIn ;
pmb->hMidiBufIn = hMidiBufIn ;
pmb->dwCallBack = dwCallBack ;
pmb->dwUser = dwUser ;
pmb->dwFlags = dwFlags ;
wError = midiInOpen (&pmb->hMidiIn, wID, (DWORD) MidiInCallBack,
(DWORD) (LPVOID) pmb, CALLBACK_FUNCTION) ;
if (wError == 0)
*lphMidiBufIn = hMidiBufIn ;
else
LocalFree (hMidiBufIn) ;
return wError ;
}
// MidiInPrepareHeader: Pass through
// ----------------------------------
UINT FAR PASCAL xMidiInPrepareHeader (HMIDIBUFIN hMidiBufIn,
LPMIDIHDR lpmh, UINT wSize)
{
PMIDIBUFIN pmb ;
if (NULL == (pmb = MidiInValidateHandle (hMidiBufIn)))
return MMSYSERR_INVALHANDLE ;
return midiInPrepareHeader (pmb->hMidiIn, lpmh, wSize) ;
}
// MidiInReset: Return pending buffers to application
// ---------------------------------------------------
UINT FAR PASCAL xMidiInReset (HMIDIBUFIN hMidiBufIn)
{
PMIDIBUFIN pmb ;
LPMIDIHDR lpmh ;
UINT wError ;
if (NULL == (pmb = MidiInValidateHandle (hMidiBufIn)))
return MMSYSERR_INVALHANDLE ;
if (0L == (wError = midiInReset (pmb->hMidiIn)))
{
while (pmb->lpmh != NULL)
{
lpmh = pmb->lpmh ;
pmb->lpmh = lpmh->lpNext ;
lpmh->dwFlags |= MHDR_DONE ;
if ((pmb->dwFlags & CALLBACK_TYPEMASK) == CALLBACK_WINDOW)
PostMessage ((HWND) pmb->dwCallBack, MM_MIM_LONGDATA,
hMidiBufIn, (DWORD) lpmh) ;
if ((pmb->dwFlags & CALLBACK_TYPEMASK) == CALLBACK_FUNCTION)
((MMCALLBACK) pmb->dwCallBack) (hMidiBufIn, MIM_LONGDATA,
pmb->dwUser, (DWORD) lpmh,
timeGetTime () - pmb->dwStartTime) ;
}
}
return wError ;
}
// MidiInShortBuffer: Add buffer to chain
// ---------------------------------------
UINT FAR PASCAL xMidiInShortBuffer (HMIDIBUFIN hMidiBufIn,
LPMIDIHDR lpmh, UINT wSize)
{
PMIDIBUFIN pmb ;
LPMIDIHDR lpmhSearch ;
if (NULL == (pmb = MidiInValidateHandle (hMidiBufIn)))
return MMSYSERR_INVALHANDLE ;
if (!(lpmh->dwFlags & MHDR_PREPARED))
return MIDIERR_UNPREPARED ;
lpmh->dwBytesRecorded = 0 ;
lpmh->lpNext = NULL ;
if (pmb->lpmh == NULL)
pmb->lpmh = lpmh ;
else
{
lpmhSearch = pmb->lpmh ;
while (lpmhSearch->lpNext != NULL)
lpmhSearch = lpmhSearch->lpNext ;
lpmhSearch->lpNext = lpmh ;
}
return 0 ;
}
// MidiInStart: Set time stamp to zero
// ------------------------------------
UINT FAR PASCAL xMidiInStart (HMIDIBUFIN hMidiBufIn)
{
PMIDIBUFIN pmb ;
UINT wError ;
if (NULL == (pmb = MidiInValidateHandle (hMidiBufIn)))
return MMSYSERR_INVALHANDLE ;
if (0 == (wError = midiInStart (pmb->hMidiIn)))
pmb->dwStartTime = timeGetTime () ;
return wError ;
}
// MidiInStop: Pass through
// -------------------------
UINT FAR PASCAL xMidiInStop (HMIDIBUFIN hMidiBufIn)
{
PMIDIBUFIN pmb ;
if (NULL == (pmb = MidiInValidateHandle (hMidiBufIn)))
return MMSYSERR_INVALHANDLE ;
return midiInStop (pmb->hMidiIn) ;
}
// MidiInUnprepareHeader: Pass through
// ------------------------------------
UINT FAR PASCAL xMidiInUnprepareHeader (HMIDIBUFIN hMidiBufIn,
LPMIDIHDR lpmh, UINT wSize)
{
PMIDIBUFIN pmb ;
if (NULL == (pmb = MidiInValidateHandle (hMidiBufIn)))
return MMSYSERR_INVALHANDLE ;
return midiInUnprepareHeader (pmb->hMidiIn, lpmh, wSize) ;
}
// MidiOutTimerFunc: Send MIDI short messages from buffer
// -------------------------------------------------------
UINT MidiOutSetEvent (PMIDIBUFOUT) ;
void FAR PASCAL _export MidiOutTimerFunc (UINT wID, UINT wMsg,
DWORD dwUser, DWORD dw1, DWORD dw2)
{
DWORD dwMsg ;
DWORD huge * lpData ;
PMIDIBUFOUT pmb ;
LPMIDIHDR lpmh ;
// Get pointers to the MIDIBUF and current MIDIHDR structures
pmb = (PMIDIBUFOUT) dwUser ;
lpmh = pmb->lpmh ;
// Flag the timer event as finished
pmb->iTimerID = 0 ;
// For periods longer than maximum period, set new timer
if (pmb->dwTime > 0)
{
pmb->iTimerID = MidiOutSetEvent (pmb) ;
return ;
}
// If playback is paused, don't do anything
if (pmb->bPaused)
return ;
// Send MIDI messages out until next delta time is not zero
// Use next buffer if at end of buffer
do
{
lpData = (DWORD huge *) lpmh->lpData ;
dwMsg = lpData [pmb->dwDataPtr / 4] ;
pmb->dwDataPtr += 4 ;
midiOutShortMsg (pmb->hMidiOut, dwMsg) ;
if (pmb->dwDataPtr + 8 > lpmh->dwBufferLength)
{
pmb->lpmh = lpmh->lpNext ;
lpmh->dwFlags |= MHDR_DONE ;
if ((pmb->dwFlags & CALLBACK_TYPEMASK) == CALLBACK_WINDOW)
PostMessage ((HWND) pmb->dwCallBack, MM_MOM_DONE,
pmb->hMidiBufOut, (DWORD) lpmh) ;
if ((pmb->dwFlags & CALLBACK_TYPEMASK) == CALLBACK_FUNCTION)
((MMCALLBACK) pmb->dwCallBack) (pmb->hMidiBufOut,
MM_MOM_DONE, pmb->dwUser, (DWORD) lpmh, 0L) ;
lpmh = pmb->lpmh ;
pmb->dwDataPtr = 0 ;
}
if (lpmh == NULL)
return ;
lpData = (DWORD huge *) lpmh->lpData ;
pmb->dwTime = lpData [pmb->dwDataPtr / 4] ;
pmb->dwDataPtr += 4 ;
}
while (pmb->dwTime < tc.wPeriodMin) ;
// Set a new timer event
pmb->iTimerID = MidiOutSetEvent (pmb) ;
return ;
}
// MidiOutSetEvent: Simplified timeSetEvent Caller
// ------------------------------------------------
UINT MidiOutSetEvent (PMIDIBUFOUT pmb)
{
UINT iPeriod ;
iPeriod = (UINT) MINMAX (tc.wPeriodMin, pmb->dwTime, tc.wPeriodMax) ;
pmb->dwTime -= iPeriod ;
return timeSetEvent (iPeriod, tc.wPeriodMin, MidiOutTimerFunc,
(DWORD) (LPVOID) pmb, TIME_ONESHOT) ;
}
// MidiOutValidateHandle: Convert handle to pointer and validate it
// -----------------------------------------------------------------
PMIDIBUFOUT MidiOutValidateHandle (HMIDIBUFOUT hMidiBufOut)
{
PMIDIBUFOUT pmb ;
pmb = (PMIDIBUFOUT) hMidiBufOut ;
if (pmb == NULL || pmb->hMidiBufOut != hMidiBufOut)
return NULL ;
return pmb ;
}
// MidiOutCacheDrumPatches: Pass through
// --------------------------------------
UINT FAR PASCAL xMidiOutCacheDrumPatches (HMIDIBUFIN hMidiBufIn, UINT wPatch,
LPKEYARRAY lpka, UINT wFlags)
{
PMIDIBUFIN pmb ;
if (NULL == (pmb = MidiInValidateHandle (hMidiBufIn)))
return MMSYSERR_INVALHANDLE ;
return midiOutCacheDrumPatches (pmb->hMidiIn, wPatch, lpka, wFlags) ;
}
// MidiOutCachePatches: Pass through
// ----------------------------------
UINT FAR PASCAL xMidiOutCachePatches (HMIDIBUFIN hMidiBufIn, UINT wBank,
LPPATCHARRAY lppa, UINT wFlags)
{
PMIDIBUFIN pmb ;
if (NULL == (pmb = MidiInValidateHandle (hMidiBufIn)))
return MMSYSERR_INVALHANDLE ;
return midiOutCachePatches (pmb->hMidiIn, wBank, lppa, wFlags) ;
}
// MidiOutClose: Free handle and call timeKillEvent
// -------------------------------------------------
UINT FAR PASCAL xMidiOutClose (HMIDIBUFOUT hMidiBufOut)
{
PMIDIBUFOUT pmb ;
UINT wError ;
if (NULL == (pmb = MidiOutValidateHandle (hMidiBufOut)))
return MMSYSERR_INVALHANDLE ;
if (0L == (wError = midiOutClose (pmb->hMidiOut)))
{
if (pmb->lpmh != NULL)
return MIDIERR_STILLPLAYING ;
if (pmb->iTimerID != 0)
timeKillEvent (pmb->iTimerID) ;
timeEndPeriod (tc.wPeriodMin) ;
LocalFree (hMidiBufOut) ;
}
return wError ;
}
// MidiOutGetID: Pass through
// ---------------------------
UINT FAR PASCAL xMidiOutGetID (HMIDIBUFOUT hMidiBufOut, UINT FAR * lpiDeviceID)
{
PMIDIBUFOUT pmb ;
if (NULL == (pmb = MidiOutValidateHandle (hMidiBufOut)))
return MMSYSERR_INVALHANDLE ;
return midiOutGetID (pmb->hMidiOut, lpiDeviceID) ;
}
// MidiOutLongMsg: Pass through
// -----------------------------
UINT FAR PASCAL xMidiOutLongMsg (HMIDIBUFOUT hMidiBufOut,
LPMIDIHDR lpmh, UINT wSize)
{
PMIDIBUFOUT pmb ;
if (NULL == (pmb = MidiOutValidateHandle (hMidiBufOut)))
return MMSYSERR_INVALHANDLE ;
return midiOutLongMsg (pmb->hMidiOut, lpmh, wSize) ;
}
// MidiOutMessage: Pass through
// -----------------------------
DWORD FAR PASCAL xMidiOutMessage (HMIDIBUFIN hMidiBufIn, UINT msg,
DWORD dw1, DWORD dw2)
{
PMIDIBUFIN pmb ;
if (NULL == (pmb = MidiInValidateHandle (hMidiBufIn)))
return MMSYSERR_INVALHANDLE ;
return midiOutMessage (pmb->hMidiIn, msg, dw1, dw2) ;
}
// MidiOutOpen: Allocate handle and call timeBeginPeriod
// ------------------------------------------------------
UINT FAR PASCAL xMidiOutOpen (LPHMIDIBUFOUT lphMidiBufOut,
UINT wID, DWORD dwCallBack,
DWORD dwUser, DWORD dwFlags)
{
HMIDIBUFOUT hMidiBufOut ;
PMIDIBUFOUT pmb ;
UINT wError ;
if (NULL == (hMidiBufOut = LocalAlloc (LPTR, sizeof (MIDIBUFOUT))))
MMSYSERR_NOMEM ;
pmb = (PMIDIBUFOUT) hMidiBufOut ;
pmb->hMidiBufOut = hMidiBufOut ;
pmb->dwCallBack = dwCallBack ;
pmb->dwUser = dwUser ;
pmb->dwFlags = dwFlags ;
wError = midiOutOpen (&pmb->hMidiOut, wID, dwCallBack, dwUser, dwFlags) ;
if (wError == 0)
{
* lphMidiBufOut = hMidiBufOut ;
timeBeginPeriod (tc.wPeriodMin) ;
}
else
LocalFree (hMidiBufOut) ;
return wError ;
}
// MidiOutPause: Set pause flag
// -----------------------------
UINT FAR PASCAL xMidiOutPause (HMIDIBUFOUT hMidiBufOut)
{
PMIDIBUFOUT pmb ;
if (NULL == (pmb = MidiOutValidateHandle (hMidiBufOut)))
return MMSYSERR_INVALHANDLE ;
pmb->bPaused = TRUE ;
return 0 ;
}
// MidiOutPrepareHeader: Pass through
// -----------------------------------
UINT FAR PASCAL xMidiOutPrepareHeader (HMIDIBUFOUT hMidiBufOut,
LPMIDIHDR lpmh, UINT wSize)
{
PMIDIBUFOUT pmb ;
if (NULL == (pmb = MidiOutValidateHandle (hMidiBufOut)))
return MMSYSERR_INVALHANDLE ;
return midiOutPrepareHeader (pmb->hMidiOut, lpmh, wSize) ;
}
// MidiOutReset: Return pending buffers to application
// ----------------------------------------------------
UINT FAR PASCAL xMidiOutReset (HMIDIBUFOUT hMidiBufOut)
{
PMIDIBUFOUT pmb ;
LPMIDIHDR lpmh ;
UINT wError ;
if (NULL == (pmb = MidiOutValidateHandle (hMidiBufOut)))
return MMSYSERR_INVALHANDLE ;
if (0 == (wError = midiOutReset (pmb->hMidiOut)))
{
if (pmb->iTimerID != 0)
timeKillEvent (pmb->iTimerID) ;
while (pmb->lpmh != NULL)
{
lpmh = pmb->lpmh ;
pmb->lpmh = lpmh->lpNext ;
lpmh->dwFlags |= MHDR_DONE ;
if ((pmb->dwFlags & CALLBACK_TYPEMASK) == CALLBACK_WINDOW)
PostMessage ((HWND) pmb->dwCallBack, MM_MOM_DONE,
hMidiBufOut, (DWORD) lpmh) ;
if ((pmb->dwFlags & CALLBACK_TYPEMASK) == CALLBACK_FUNCTION)
((MMCALLBACK) pmb->dwCallBack) (hMidiBufOut, MOM_DONE,
pmb->dwUser, (DWORD) lpmh, 0) ;
}
}
return wError ;
}
// MidiOutRestart: Reset paused flag and set timer if not set
// -----------------------------------------------------------
UINT FAR PASCAL xMidiOutRestart (HMIDIBUFOUT hMidiBufOut)
{
PMIDIBUFOUT pmb ;
if (NULL == (pmb = MidiOutValidateHandle (hMidiBufOut)))
return MMSYSERR_INVALHANDLE ;
pmb->bPaused = FALSE ;
if (pmb->iTimerID == 0)
{
pmb->dwTime = tc.wPeriodMin ;
pmb->iTimerID = MidiOutSetEvent (pmb) ;
}
return 0 ;
}
// MidiOutShortBuffer: Add buffer to chain and set timer if not set
// -----------------------------------------------------------------
UINT FAR PASCAL xMidiOutShortBuffer (HMIDIBUFOUT hMidiBufOut,
LPMIDIHDR lpmh, UINT wSize)
{
DWORD huge * lpData ;
LPMIDIHDR lpmhSearch ;
PMIDIBUFOUT pmb ;
// Validate handle and check if header is prepared
if (NULL == (pmb = MidiOutValidateHandle (hMidiBufOut)))
return MMSYSERR_INVALHANDLE ;
if (!(lpmh->dwFlags & MHDR_PREPARED))
return MIDIERR_UNPREPARED ;
// Add buffer to chain
lpmh->lpNext = NULL ;
if (pmb->lpmh == NULL)
pmb->lpmh = lpmh ;
else
{
lpmhSearch = pmb->lpmh ;
while (lpmhSearch->lpNext != NULL)
lpmhSearch = lpmhSearch->lpNext ;
lpmhSearch->lpNext = lpmh ;
}
// Begin sequence by setting a timer event
if (pmb->iTimerID == 0)
{
lpData = (DWORD huge *) lpmh->lpData ;
pmb->dwTime = lpData [0] ;
pmb->dwDataPtr += 4 ;
pmb->iTimerID = MidiOutSetEvent (pmb) ;
}
return 0 ;
}
// MidiOutShortMsg: Pass through
// ------------------------------
UINT FAR PASCAL xMidiOutShortMsg (HMIDIBUFOUT hMidiBufOut, DWORD dwMsg)
{
PMIDIBUFOUT pmb ;
if (NULL == (pmb = MidiOutValidateHandle (hMidiBufOut)))
return MMSYSERR_INVALHANDLE ;
return midiOutShortMsg (pmb->hMidiOut, dwMsg) ;
}
// MidiOutUnprepareHeader: Pass through
// -------------------------------------
UINT FAR PASCAL xMidiOutUnprepareHeader (HMIDIBUFOUT hMidiBufOut,
LPMIDIHDR lpmh, UINT wSize)
{
PMIDIBUFOUT pmb ;
if (NULL == (pmb = MidiOutValidateHandle (hMidiBufOut)))
return MMSYSERR_INVALHANDLE ;
return midiOutUnprepareHeader (pmb->hMidiOut, lpmh, wSize) ;
}