3383 lines
106 KiB
C
3383 lines
106 KiB
C
/***********************************************************************\
|
|
|
|
*
|
|
* WOW v1.0
|
|
*
|
|
* Copyright (c) 1991, Microsoft Corporation
|
|
*
|
|
* WMMEDIA2.C
|
|
* WOW32 16-bit MultiMedia API support
|
|
*
|
|
* Contains:
|
|
* Midi IN apis
|
|
* Midi OUT apis
|
|
* Wave IN apis
|
|
* Wave OUT apis
|
|
*
|
|
*
|
|
* History:
|
|
* Created 21-Jan-1992 by Mike Tricker (MikeTri), after jeffpar
|
|
* Changed 15-Jul-1992 by Mike Tricker (MikeTri), fixing GetDevCaps calls
|
|
* 26-Jul-1992 by Stephen Estrop (StephenE) thunks for mciSendCommand
|
|
* 30-Jul-1992 by Mike Tricker (MikeTri), fixing Wave/Midi/MMIO
|
|
* 03-Aug-1992 by Mike Tricker (MikeTri), added proper error handling
|
|
* 08-Oct-1992 by StephenE spawned from the original wmmedia.c
|
|
*
|
|
\***********************************************************************/
|
|
|
|
|
|
//
|
|
// We define NO_STRICT so that the compiler doesn't moan and groan when
|
|
// I use the FARPROC type for the Multi-Media api loading.
|
|
//
|
|
#define NO_STRICT
|
|
#define OEMRESOURCE
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
#if 0
|
|
|
|
|
|
MODNAME(wmmedia2.c);
|
|
|
|
// A 32 bit ptr to the 16 bit callback data
|
|
extern PCALLBACK_DATA pCallBackData;
|
|
extern CRITICAL_SECTION mmCriticalSection;
|
|
|
|
#if DBG
|
|
/*
|
|
** AllocCount maintains a count of the number XXM_DONE messages that
|
|
** we expect to receive before the device is closed. When the device is
|
|
** closed this count should be zero.
|
|
**
|
|
*/
|
|
int AllocWaveCount = 0;
|
|
int AllocMidiCount = 0;
|
|
int mmTraceWave = 0;
|
|
int mmTraceMidi = 0;
|
|
#endif
|
|
|
|
|
|
/* ---------------------------------------------------------------------
|
|
** MIDI Output API's
|
|
** ---------------------------------------------------------------------
|
|
*/
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* WMM32midiOutGetNumDevs
|
|
*
|
|
* This function retrieves the number of MIDI output devices present
|
|
* in the system.
|
|
*
|
|
\**********************************************************************/
|
|
ULONG FASTCALL WMM32midiOutGetNumDevs(PVDMFRAME pFrame)
|
|
{
|
|
static FARPROC mmAPI = NULL;
|
|
ULONG ul;
|
|
|
|
UNREFERENCED_PARAMETER(pFrame);
|
|
|
|
GET_MULTIMEDIA_API( "midiOutGetNumDevs", mmAPI, MMSYSERR_NODRIVER );
|
|
|
|
trace_midi(( "midiOutGetNumDevs()" ));
|
|
ul = GETWORD16((*mmAPI)() );
|
|
trace_midi(( "-> %ld\n", ul ));
|
|
|
|
RETURN(ul);
|
|
}
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* WMM32midiOutGetDevCaps
|
|
*
|
|
* This function queries a specified MIDI output device to determine its
|
|
* capabilities.
|
|
*
|
|
*
|
|
*
|
|
* We will now change things...
|
|
*
|
|
* Step 1: get the ENTIRE Caps structure, irrespective of the number of bytes
|
|
* requested
|
|
* (previously I was getting the requested number of bytes via
|
|
* parg16->f3 (plus 2 'cos of the WORD -> UINT change for version -
|
|
* which was wrong anyway...) )
|
|
*
|
|
* Step 2: thunk the ENTIRE structure in to a 16 bit local variable
|
|
*
|
|
* Step 3: RtlCopyMemory the REQUESTED number of bytes from the local copy
|
|
* to the "real" structure within the app
|
|
*
|
|
* Thanks to RCBS for sorting me out once again !
|
|
*
|
|
*
|
|
*
|
|
\**********************************************************************/
|
|
ULONG FASTCALL WMM32midiOutGetDevCaps(PVDMFRAME pFrame)
|
|
|
|
{
|
|
register PMIDIOUTGETDEVCAPS16 parg16;
|
|
static FARPROC mmAPI = NULL;
|
|
ULONG ul;
|
|
MIDIOUTCAPS midioutcaps;
|
|
|
|
GET_MULTIMEDIA_API( "midiOutGetDevCapsA", mmAPI, MMSYSERR_NODRIVER );
|
|
|
|
GETARGPTR(pFrame, sizeof(MIDIOUTGETDEVCAPS16), parg16);
|
|
|
|
trace_midi(( "midiOutGetDevCaps( %x, %x, %x )", INT32( parg16->f1 ),
|
|
DWORD32( parg16->f2 ), UINT32( parg16->f3 ) ));
|
|
|
|
|
|
/*
|
|
** If the size parameter was zero return straight away. Note that this
|
|
** is not an error.
|
|
*/
|
|
if ( UINT32( parg16->f3 ) == 0 ) {
|
|
ul = MMSYSERR_NOERROR;
|
|
}
|
|
else {
|
|
|
|
ul = GETWORD16((*mmAPI)( INT32(parg16->f1), &midioutcaps,
|
|
sizeof(MIDIOUTCAPS) ));
|
|
/*
|
|
** This must now thunk the ENTIRE structure, then copy parg16->f3
|
|
** bytes onto the "real" structure in the app, but only if the call
|
|
** returned success.
|
|
*/
|
|
if ( ul == MMSYSERR_NOERROR ) {
|
|
ul = PUTMIDIOUTCAPS16(parg16->f2, &midioutcaps, UINT32(parg16->f3));
|
|
}
|
|
}
|
|
trace_midi(( "-> %ld\n", ul ));
|
|
|
|
|
|
FREEARGPTR(parg16);
|
|
RETURN(ul);
|
|
}
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* WMM32midiOutGetErrorText
|
|
*
|
|
* This function retrieves a textual description of the error
|
|
* identified by the specified error number.
|
|
*
|
|
\**********************************************************************/
|
|
ULONG FASTCALL WMM32midiOutGetErrorText(PVDMFRAME pFrame)
|
|
{
|
|
register PMIDIOUTGETERRORTEXT16 parg16;
|
|
static FARPROC mmAPI = NULL;
|
|
ULONG ul = MMSYSERR_NOERROR;
|
|
PSZ pszText;
|
|
|
|
GET_MULTIMEDIA_API( "midiOutGetErrorTextA", mmAPI, MMSYSERR_NODRIVER );
|
|
|
|
GETARGPTR(pFrame, sizeof(MIDIOUTGETERRORTEXT16), parg16);
|
|
|
|
trace_midi(( "midiOutGetErrorText( %x, %x, %x )", UINT32( parg16->f1 ),
|
|
DWORD32( parg16->f2 ), UINT32( parg16->f3 ) ));
|
|
|
|
/*
|
|
** Test against a zero length string and a NULL pointer. If 0 is passed
|
|
** as the buffer length then the manual says we should return
|
|
** MMSYSERR_NOERR. MMGETOPTPTR only returns a pointer if parg16->f2 is
|
|
** not NULL.
|
|
*/
|
|
MMGETOPTPTR( parg16->f2, UINT32(parg16->f3), pszText );
|
|
if ( pszText != NULL ) {
|
|
|
|
ul = GETWORD16((*mmAPI)( UINT32(parg16->f1), pszText,
|
|
UINT32(parg16->f3) ));
|
|
|
|
FLUSHVDMPTR(DWORD32(parg16->f2), UINT32(parg16->f3), pszText);
|
|
FREEVDMPTR(pszText);
|
|
}
|
|
trace_midi(( "-> %ld\n", ul ));
|
|
|
|
FREEARGPTR(parg16);
|
|
RETURN(ul);
|
|
}
|
|
|
|
/***********************************************************************\
|
|
*
|
|
* WMM32midiOutOpen
|
|
*
|
|
* This function opens a specified MIDI output device for playback.
|
|
*
|
|
\***********************************************************************/
|
|
ULONG FASTCALL WMM32midiOutOpen(PVDMFRAME pFrame)
|
|
{
|
|
register PMIDIOUTOPEN16 parg16;
|
|
static FARPROC mmAPI = NULL;
|
|
|
|
ULONG ul = MMSYSERR_NOERROR;
|
|
UINT uDevID;
|
|
PINSTANCEDATA pInstanceData;
|
|
LPHMIDIOUT lpHMidiOut; // pointer to handle in 16 bit app space
|
|
HMIDIOUT Hand32; // 32bit handle
|
|
|
|
GET_MULTIMEDIA_API( "midiOutOpen", mmAPI, MMSYSERR_NODRIVER );
|
|
|
|
GETARGPTR(pFrame, sizeof(MIDIOUTOPEN16), parg16);
|
|
|
|
trace_midi(( "midiOutOpen( %x, %x, %x, %x, %x )",
|
|
DWORD32( parg16->f1 ), INT32 ( parg16->f2 ),
|
|
DWORD32( parg16->f3 ), DWORD32( parg16->f4 ),
|
|
DWORD32( parg16->f5 ) ));
|
|
|
|
/*
|
|
** Get the device ID. We use INT32 here not UINT32 to make sure that
|
|
** negative values (such as MIDI_MAPPER (-1)) get thunked correctly.
|
|
*/
|
|
uDevID = (UINT)INT32(parg16->f2);
|
|
|
|
/*
|
|
** Map the 16 bit pointer is one was specified.
|
|
*/
|
|
MMGETOPTPTR( parg16->f1, sizeof(HMIDIOUT16), lpHMidiOut );
|
|
if ( lpHMidiOut ) {
|
|
|
|
/*
|
|
** Create InstanceData block to be used by our callback routine.
|
|
**
|
|
** NOTE: Although we malloc it here we don't free it.
|
|
** This is not a mistake - it must not be freed before the
|
|
** callback routine has used it - so it does the freeing.
|
|
**
|
|
** If the malloc fails we bomb down to the bottom,
|
|
** set ul to MMSYSERR_NOMEM and exit gracefully.
|
|
**
|
|
** We always have a callback functions. This is to ensure that
|
|
** the MIDIHDR structure keeps getting copied back from
|
|
** 32 bit space to 16 bit, as it contains flags which
|
|
** applications are liable to keep checking.
|
|
*/
|
|
if ( pInstanceData = malloc_w(sizeof(INSTANCEDATA)) ) {
|
|
|
|
dprintf2(( "WM32midiOutOpen: Allocated instance buffer at %8X",
|
|
pInstanceData ));
|
|
pInstanceData->dwCallback = DWORD32(parg16->f3);
|
|
pInstanceData->dwCallbackInstance = DWORD32(parg16->f4);
|
|
pInstanceData->dwFlags = DWORD32(parg16->f5);
|
|
|
|
ul = GETWORD16((*mmAPI)( &Hand32, uDevID,
|
|
(DWORD)W32CommonDeviceOpen,
|
|
(DWORD)pInstanceData,
|
|
CALLBACK_FUNCTION ));
|
|
|
|
}
|
|
else {
|
|
ul = MMSYSERR_NOMEM;
|
|
}
|
|
|
|
/*
|
|
** If the call returns success update the 16 bit handle,
|
|
** otherwise don't, and free the memory we malloc'd earlier, as
|
|
** the callback that would have freed it will never get callled.
|
|
*/
|
|
if ( ul == MMSYSERR_NOERROR ) {
|
|
|
|
HMIDIOUT16 Hand16 = GETHMIDIOUT16(Hand32);
|
|
|
|
trace_midi(( "Handle -> %x", Hand16 ));
|
|
|
|
STOREWORD ( *lpHMidiOut, Hand16 );
|
|
FLUSHVDMPTR( DWORD32(parg16->f1), sizeof(HMIDIOUT16),
|
|
lpHMidiOut );
|
|
}
|
|
|
|
/*
|
|
** We only free the memory if we actually allocated any
|
|
*/
|
|
else if ( pInstanceData ) {
|
|
|
|
free_w(pInstanceData);
|
|
}
|
|
|
|
/*
|
|
** Regardless of sucess or failure we need to free the pointer
|
|
** to the 16 bit MidiIn handle.
|
|
*/
|
|
FREEVDMPTR ( lpHMidiOut );
|
|
|
|
}
|
|
else {
|
|
|
|
ul = MMSYSERR_INVALPARAM;
|
|
}
|
|
trace_midi(( "-> %ld\n", ul ));
|
|
|
|
FREEARGPTR(parg16);
|
|
RETURN(ul);
|
|
}
|
|
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* WMM32midiOutClose
|
|
*
|
|
* This function closes the specified MIDI output device.
|
|
*
|
|
\**********************************************************************/
|
|
ULONG FASTCALL WMM32midiOutClose(PVDMFRAME pFrame)
|
|
{
|
|
register PMIDIOUTCLOSE16 parg16;
|
|
static FARPROC mmAPI = NULL;
|
|
ULONG ul;
|
|
|
|
GET_MULTIMEDIA_API( "midiOutClose", mmAPI, MMSYSERR_NODRIVER );
|
|
|
|
GETARGPTR(pFrame, sizeof(MIDIOUTCLOSE16), parg16);
|
|
|
|
trace_midi(( "midiOutClose( %x )", WORD32( parg16->f1 ) ));
|
|
ul = GETWORD16( (*mmAPI)(HMIDIOUT32(parg16->f1) ));
|
|
trace_midi(( "-> %ld\n", ul ));
|
|
|
|
FREEARGPTR(parg16);
|
|
RETURN(ul);
|
|
}
|
|
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* WMM32midiOutPrepareHeader
|
|
*
|
|
* This function prepares the specified midiform header.
|
|
*
|
|
\**********************************************************************/
|
|
ULONG FASTCALL WMM32midiOutPrepareHeader(PVDMFRAME pFrame)
|
|
{
|
|
register PMIDIOUTPREPAREHEADER3216 parg16;
|
|
static FARPROC mmAPI = NULL;
|
|
ULONG ul;
|
|
MIDIHDR midihdr;
|
|
|
|
|
|
GET_MULTIMEDIA_API( "midiOutPrepareHeader", mmAPI, MMSYSERR_NODRIVER );
|
|
GETARGPTR(pFrame, sizeof(MIDIOUTPREPAREHEADER3216), parg16);
|
|
trace_midi(( "midiOutPrepareHeader( %x %x %x)", WORD32( parg16->f1 ),
|
|
DWORD32( parg16->f2 ), WORD32( parg16->f3 ) ));
|
|
|
|
GETMIDIHDR16(parg16->f2, &midihdr);
|
|
|
|
ul = GETWORD16((*mmAPI)( HMIDIOUT32(parg16->f1),
|
|
&midihdr, WORD32(parg16->f3) ) );
|
|
/*
|
|
** Only update the 16 bit structure if the call returns success
|
|
**
|
|
*/
|
|
if ( !ul ) {
|
|
PUTMIDIHDR16(parg16->f2, &midihdr);
|
|
}
|
|
|
|
trace_midi(( "-> %ld\n", ul ));
|
|
FREEARGPTR(parg16);
|
|
RETURN(ul);
|
|
}
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* WMM32midiOutUnprepareHeader
|
|
*
|
|
* This function prepares the specified midiform header.
|
|
* This function cleans up the preparation performed by midiOutPrepareHeader.
|
|
* The function must be called after the device driver has finished with a
|
|
* data block. You must call this function before freeing the data buffer.
|
|
*
|
|
\**********************************************************************/
|
|
ULONG FASTCALL WMM32midiOutUnprepareHeader(PVDMFRAME pFrame)
|
|
{
|
|
register PMIDIOUTUNPREPAREHEADER3216 parg16;
|
|
static FARPROC mmAPI = NULL;
|
|
ULONG ul;
|
|
MIDIHDR midihdr;
|
|
|
|
GET_MULTIMEDIA_API( "midiOutUnprepareHeader", mmAPI, MMSYSERR_NODRIVER );
|
|
GETARGPTR(pFrame, sizeof(MIDIOUTUNPREPAREHEADER3216), parg16);
|
|
trace_midi(( "midiOutUnprepareHeader( %x %x %x)", WORD32( parg16->f1 ),
|
|
DWORD32( parg16->f2 ), WORD32( parg16->f3 ) ));
|
|
|
|
GETMIDIHDR16(parg16->f2, &midihdr);
|
|
|
|
ul = GETWORD16((*mmAPI)( HMIDIOUT32(parg16->f1),
|
|
&midihdr, WORD32(parg16->f3) ) );
|
|
/*
|
|
** Only update the 16 bit structure if the call returns success
|
|
*/
|
|
if (!ul) {
|
|
PUTMIDIHDR16(parg16->f2, &midihdr);
|
|
}
|
|
|
|
trace_midi(( "-> %ld\n", ul ));
|
|
FREEARGPTR(parg16);
|
|
RETURN(ul);
|
|
}
|
|
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* WMM32midiOutShortMsg
|
|
*
|
|
* This function sends a short MIDI message to the specified MIDI output device.
|
|
* Use this function to send any MIDI message except for system exclusive
|
|
* messages.
|
|
*
|
|
\**********************************************************************/
|
|
ULONG FASTCALL WMM32midiOutShortMsg(PVDMFRAME pFrame)
|
|
{
|
|
register PMIDIOUTSHORTMSG16 parg16;
|
|
static FARPROC mmAPI = NULL;
|
|
ULONG ul;
|
|
|
|
GET_MULTIMEDIA_API( "midiOutShortMsg", mmAPI, MMSYSERR_NODRIVER );
|
|
|
|
GETARGPTR(pFrame, sizeof(MIDIOUTSHORTMSG16), parg16);
|
|
|
|
trace_midi(( "midiOutShortMsg( %x, %x )", WORD32( parg16->f1 ),
|
|
DWORD32( parg16->f2 ) ));
|
|
|
|
ul = GETWORD16((*mmAPI)( HMIDIOUT32(parg16->f1), DWORD32(parg16->f2) ));
|
|
trace_midi(( "-> %ld\n", ul ));
|
|
|
|
FREEARGPTR(parg16);
|
|
RETURN(ul);
|
|
}
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* WMM32midiOutLongMsg
|
|
*
|
|
* This function sends a long MIDI message to the specified MIDI output
|
|
* device. Use this function to send system exclusive messages or to
|
|
* send a buffer filled with short messages.
|
|
*
|
|
\**********************************************************************/
|
|
ULONG FASTCALL WMM32midiOutLongMsg(PVDMFRAME pFrame)
|
|
{
|
|
register PMIDIOUTLONGMSG16 parg16;
|
|
static FARPROC mmAPI = NULL;
|
|
ULONG ul;
|
|
PMIDIHDR32 pMidihdr32;
|
|
|
|
GET_MULTIMEDIA_API( "midiOutLongMsg", mmAPI, MMSYSERR_NODRIVER );
|
|
|
|
GETARGPTR(pFrame, sizeof(MIDIOUTLONGMSG16), parg16);
|
|
|
|
trace_midi(( "midiOutLongMsg( %x, %x, %x )", WORD32( parg16->f1 ),
|
|
DWORD32( parg16->f2 ), UINT32( parg16->f3 ) ));
|
|
|
|
/*
|
|
** If the given size of the MIDIHDR structure is too small
|
|
** or the lphdr is invalid return an error
|
|
**
|
|
*/
|
|
if ( UINT32(parg16->f3) < sizeof(MIDIHDR16)
|
|
|| HIWORD( DWORD32(parg16->f2) ) == 0 ) {
|
|
|
|
ul = MMSYSERR_INVALPARAM;
|
|
}
|
|
else {
|
|
if ( pMidihdr32 = malloc_w(sizeof(MIDIHDR32)) ) {
|
|
|
|
PMIDIHDR lpwhdr;
|
|
#if DBG
|
|
AllocMidiCount++;
|
|
dprintf2(( "M>> %8X (%d)", pMidihdr32, AllocMidiCount ));
|
|
#endif
|
|
/* Copy across the midi header stuff. Note that lpwhdr (a
|
|
** 32 bit ptr to a 32 bit midi header) is used to make the
|
|
** pointer stuff a bit less hairy.
|
|
**
|
|
** pMidihdr32->pMidihdr32 is a 32 bit ptr to a 16 bit midi header
|
|
** pMidihdr32->pMidihdr16 is a 16 bit ptr to a 16 bit midi header
|
|
** pMidihdr32->Midihdr is a 32 bit midi header
|
|
*/
|
|
lpwhdr = &(pMidihdr32->Midihdr);
|
|
pMidihdr32->pMidihdr16 = (PMIDIHDR16)DWORD32(parg16->f2);
|
|
pMidihdr32->pMidihdr32 = GETMIDIHDR16(DWORD32(parg16->f2), lpwhdr);
|
|
|
|
/*
|
|
** GETMIDIHDR16 can return NULL, in which case we should set
|
|
** lpwhdr to NULL too and call midiOutLongMessage only to get the
|
|
** correct error code.
|
|
*/
|
|
if ( pMidihdr32->pMidihdr32 == NULL ) {
|
|
lpwhdr = NULL;
|
|
}
|
|
|
|
ul = GETWORD16( (*mmAPI)( HMIDIOUT32(parg16->f1), lpwhdr,
|
|
UINT32(parg16->f3) ) );
|
|
/*
|
|
** If the call fails we need to free the memory we malloc'd
|
|
** above, as the callback that would have freed it will never
|
|
** get called.
|
|
**
|
|
*/
|
|
if ( ul == MMSYSERR_NOERROR ) {
|
|
|
|
/*
|
|
** Make sure we reflect any changes that midiOutLongMessage did
|
|
** to the MIDIHDR back to 16 bit land.
|
|
**
|
|
** This is important because some apps poll the
|
|
** MHDR_DONE bit !!
|
|
*/
|
|
COPY_MIDIOUTHDR16_FLAGS( pMidihdr32->pMidihdr32,
|
|
pMidihdr32->Midihdr );
|
|
}
|
|
else {
|
|
#if DBG
|
|
AllocMidiCount--;
|
|
dprintf2(( "M<< \t%8X (%d)", pMidihdr32,
|
|
AllocMidiCount ));
|
|
#endif
|
|
free_w( pMidihdr32 );
|
|
}
|
|
}
|
|
else {
|
|
ul = MMSYSERR_NOMEM;
|
|
}
|
|
}
|
|
trace_midi(( "-> %ld\n", ul ));
|
|
|
|
FREEARGPTR(parg16);
|
|
RETURN(ul);
|
|
}
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* WMM32midiOutReset
|
|
*
|
|
* This function turns off all notes on al MIDI channels for the specified
|
|
* MIDI output deice.
|
|
*
|
|
\**********************************************************************/
|
|
ULONG FASTCALL WMM32midiOutReset(PVDMFRAME pFrame)
|
|
{
|
|
register PMIDIOUTRESET16 parg16;
|
|
static FARPROC mmAPI = NULL;
|
|
ULONG ul;
|
|
|
|
GET_MULTIMEDIA_API( "midiOutReset", mmAPI, MMSYSERR_NODRIVER );
|
|
|
|
GETARGPTR(pFrame, sizeof(MIDIOUTRESET16), parg16);
|
|
|
|
trace_midi(( "midiOutReset( %x )", WORD32( parg16->f1 ) ));
|
|
ul = GETWORD16((*mmAPI)( HMIDIOUT32(parg16->f1) ));
|
|
trace_midi(( "-> %ld\n", ul ));
|
|
|
|
FREEARGPTR(parg16);
|
|
RETURN(ul);
|
|
}
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* WMM32midiOutGetVolume
|
|
*
|
|
* This function returns the current volume setting of a MIDI output device.
|
|
*
|
|
\**********************************************************************/
|
|
ULONG FASTCALL WMM32midiOutGetVolume(PVDMFRAME pFrame)
|
|
{
|
|
register PMIDIOUTGETVOLUME16 parg16;
|
|
static FARPROC mmAPI = NULL;
|
|
ULONG ul;
|
|
LPDWORD lpdwVolume;
|
|
DWORD dwVolume;
|
|
|
|
GET_MULTIMEDIA_API( "midiOutGetVolume", mmAPI, MMSYSERR_NODRIVER );
|
|
|
|
GETARGPTR(pFrame, sizeof(MIDIOUTGETVOLUME16), parg16);
|
|
|
|
trace_midi(( "midiOutGetVolume( %x, %x )", INT32( parg16->f1 ),
|
|
DWORD32( parg16->f2 ) ));
|
|
|
|
ul = GETWORD16((*mmAPI)( INT32(parg16->f1), &dwVolume ));
|
|
if ( ul == MMSYSERR_NOERROR ) {
|
|
|
|
MMGETOPTPTR( parg16->f2, sizeof(DWORD), lpdwVolume);
|
|
|
|
if ( lpdwVolume ) {
|
|
STOREDWORD ( *lpdwVolume, dwVolume );
|
|
FLUSHVDMPTR( DWORD32(parg16->f2), sizeof(DWORD), lpdwVolume );
|
|
FREEVDMPTR ( lpdwVolume );
|
|
}
|
|
else {
|
|
ul = MMSYSERR_INVALPARAM;
|
|
}
|
|
}
|
|
trace_midi(( "-> %ld\n", ul ));
|
|
|
|
FREEARGPTR(parg16);
|
|
RETURN(ul);
|
|
}
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* WMM32midiOutSetVolume
|
|
*
|
|
* This function sets the volume of a MIDI output device.
|
|
*
|
|
\**********************************************************************/
|
|
ULONG FASTCALL WMM32midiOutSetVolume(PVDMFRAME pFrame)
|
|
{
|
|
register PMIDIOUTSETVOLUME16 parg16;
|
|
static FARPROC mmAPI = NULL;
|
|
ULONG ul;
|
|
|
|
GET_MULTIMEDIA_API( "midiOutSetVolume", mmAPI, MMSYSERR_NODRIVER );
|
|
|
|
GETARGPTR(pFrame, sizeof(MIDIOUTSETVOLUME16), parg16);
|
|
|
|
trace_midi(( "midiOutSetVolume( %x, %x )", WORD32( parg16->f1 ),
|
|
DWORD32( parg16->f2 ) ));
|
|
ul = GETWORD16((*mmAPI)( INT32(parg16->f1), DWORD32(parg16->f2) ));
|
|
trace_midi(( "-> %ld\n", ul ));
|
|
|
|
FREEARGPTR(parg16);
|
|
RETURN(ul);
|
|
}
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* WMM32midiOutCachePatches
|
|
*
|
|
* This function requests that an internal MIDI synthesizer device preload a
|
|
* specified set of patches. Some synthesizers are not capable of keeping all
|
|
* patches loaded simultaneously and must load data from disk when they receive
|
|
* MIDI program change messages. Caching patches ensures specified patches are
|
|
* immediately available.
|
|
*
|
|
\**********************************************************************/
|
|
ULONG FASTCALL WMM32midiOutCachePatches(PVDMFRAME pFrame)
|
|
{
|
|
register PMIDIOUTCACHEPATCHES16 parg16;
|
|
static FARPROC mmAPI = NULL;
|
|
ULONG ul = MMSYSERR_INVALPARAM;
|
|
LPPATCHARRAY lppa1;
|
|
|
|
GET_MULTIMEDIA_API( "midiOutCachePatches", mmAPI, MMSYSERR_NODRIVER );
|
|
|
|
GETARGPTR(pFrame, sizeof(MIDIOUTCACHEPATCHES16), parg16);
|
|
|
|
trace_midi(( "midiOutCachePatches( %x, %x, %x, %x )", WORD32( parg16->f1 ),
|
|
UINT32( parg16->f2 ), DWORD32( parg16->f3 ),
|
|
UINT32( parg16->f4 ) ));
|
|
|
|
/*
|
|
** GETMISCPTR checks that parg16->f3 is not zero so we need not bother.
|
|
*/
|
|
GETMISCPTR( DWORD32( parg16->f3 ), lppa1 );
|
|
|
|
if ( lppa1 ) {
|
|
|
|
ul = GETWORD16((*mmAPI)( HMIDIOUT32(parg16->f1), UINT32(parg16->f2),
|
|
lppa1, UINT32(parg16->f4) ));
|
|
FREEMISCPTR( lppa1 );
|
|
|
|
}
|
|
else {
|
|
dprintf1(( "WMM32midiOutCachePatches passed a NULL pointer" ));
|
|
}
|
|
trace_midi(( "-> %ld\n", ul ));
|
|
|
|
FREEARGPTR(parg16);
|
|
RETURN(ul);
|
|
}
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* WMM32midiOutCacheDrumPatches
|
|
*
|
|
* This function requests that an internal MIDI synthesizer device preload a
|
|
* specified set of key-based percussion patches. Some synthesizers are not
|
|
* capable of keeping all percussion patches loaded simultaneously. Caching
|
|
* patches ensures specified patches are immediately available.
|
|
*
|
|
\**********************************************************************/
|
|
ULONG FASTCALL WMM32midiOutCacheDrumPatches(PVDMFRAME pFrame)
|
|
{
|
|
register PMIDIOUTCACHEDRUMPATCHES16 parg16;
|
|
static FARPROC mmAPI = NULL;
|
|
ULONG ul = MMSYSERR_INVALPARAM;
|
|
LPKEYARRAY lpka1;
|
|
|
|
GET_MULTIMEDIA_API( "midiOutCacheDrumPatches", mmAPI, MMSYSERR_NODRIVER );
|
|
|
|
GETARGPTR(pFrame, sizeof(MIDIOUTCACHEDRUMPATCHES16), parg16);
|
|
trace_midi(( "midiOutCacheDrumPatches( %x, %x, %x, %x )",
|
|
WORD32( parg16->f1 ), UINT32( parg16->f2 ),
|
|
DWORD32( parg16->f3 ), UINT32( parg16->f4 ) ));
|
|
|
|
GETMISCPTR( DWORD32( parg16->f3 ), lpka1 );
|
|
if ( lpka1 ) {
|
|
|
|
ul = GETWORD16((*mmAPI)( HMIDIOUT32(parg16->f1), UINT32(parg16->f2),
|
|
lpka1, UINT32(parg16->f4) ) );
|
|
FREEMISCPTR(lpka1);
|
|
}
|
|
else {
|
|
dprintf1(( "WMM32midiOutCacheDrumPatches passed a NULL pointer" ));
|
|
}
|
|
trace_midi(( "-> %ld\n", ul ));
|
|
|
|
FREEARGPTR(parg16);
|
|
RETURN(ul);
|
|
}
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* WMM32midiOutGetID
|
|
*
|
|
* This function gets the device ID for a MIDI output device.
|
|
*
|
|
\**********************************************************************/
|
|
ULONG FASTCALL WMM32midiOutGetID(PVDMFRAME pFrame)
|
|
{
|
|
register PMIDIOUTGETID16 parg16;
|
|
static FARPROC mmAPI = NULL;
|
|
ULONG ul;
|
|
UINT dwDeviceID32;
|
|
LPWORD lpwDeviceID16;
|
|
|
|
GET_MULTIMEDIA_API( "midiOutGetID", mmAPI, MMSYSERR_NODRIVER );
|
|
|
|
GETARGPTR(pFrame, sizeof(MIDIOUTGETID16), parg16);
|
|
|
|
trace_midi(( "midiOutGetID( %x, %x )", WORD32( parg16->f1 ),
|
|
DWORD32( parg16->f2 ) ));
|
|
|
|
ul = GETWORD16((*mmAPI)( (HMIDIOUT)HMIDIOUT32(parg16->f1), &dwDeviceID32 ));
|
|
|
|
/*
|
|
** Only copy the ID back to 16 bit space if the call was sucessful
|
|
**
|
|
*/
|
|
if ( ul == MMSYSERR_NOERROR ) {
|
|
|
|
MMGETOPTPTR( parg16->f2, sizeof(WORD), lpwDeviceID16 );
|
|
|
|
if ( lpwDeviceID16 ) {
|
|
STOREWORD ( *lpwDeviceID16, dwDeviceID32 );
|
|
FLUSHVDMPTR( DWORD32(parg16->f2), sizeof(WORD), lpwDeviceID16 );
|
|
FREEVDMPTR ( lpwDeviceID16 );
|
|
}
|
|
else {
|
|
ul = MMSYSERR_INVALPARAM;
|
|
}
|
|
}
|
|
trace_midi(( "-> %ld\n", ul ));
|
|
|
|
FREEARGPTR(parg16);
|
|
RETURN(ul);
|
|
}
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* WMM32midiOutMessage
|
|
*
|
|
* This function sends a message to the specified MIDI output device.
|
|
*
|
|
\**********************************************************************/
|
|
ULONG FASTCALL WMM32midiOutMessage(PVDMFRAME pFrame)
|
|
{
|
|
register PMIDIOUTMESSAGE3216 parg16;
|
|
static FARPROC mmAPI = NULL;
|
|
ULONG ul;
|
|
|
|
GET_MULTIMEDIA_API( "midiOutMessage", mmAPI, MMSYSERR_NODRIVER );
|
|
|
|
GETARGPTR(pFrame, sizeof(MIDIOUTMESSAGE16), parg16);
|
|
|
|
trace_midi(( "midiOutMessage( %x, %x, %x, %x )",
|
|
WORD32( parg16->f1 ), UINT32( parg16->f2 ),
|
|
DWORD32( parg16->f3 ), DWORD32( parg16->f4 ) ));
|
|
|
|
if ( (UINT32(parg16->f2) >= DRV_BUFFER_LOW)
|
|
&& (UINT32(parg16->f2) <= DRV_BUFFER_HIGH) ) {
|
|
|
|
LPDWORD lpdwParam1;
|
|
GETMISCPTR(parg16->f3, lpdwParam1);
|
|
|
|
ul = GETDWORD16((*mmAPI)( HMIDIOUT32(parg16->f1), UINT32(parg16->f2),
|
|
(DWORD)lpdwParam1, DWORD32(parg16->f4)));
|
|
FREEMISCPTR(lpdwParam1);
|
|
|
|
} else {
|
|
ul = GETDWORD16((*mmAPI)( HMIDIOUT32(parg16->f1),
|
|
MAKELONG( WORD32(parg16->f2), 0xFFFF ),
|
|
DWORD32(parg16->f3), DWORD32(parg16->f4) ));
|
|
}
|
|
|
|
trace_midi(( "-> %ld\n", ul ));
|
|
|
|
FREEARGPTR(parg16);
|
|
RETURN(ul);
|
|
}
|
|
|
|
|
|
/* ---------------------------------------------------------------------
|
|
** MIDI Input API's
|
|
** ---------------------------------------------------------------------
|
|
*/
|
|
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* WMM32midiInGetNumDevs
|
|
*
|
|
* This function retrieves the number of MIDI input devices in the system.
|
|
*
|
|
\**********************************************************************/
|
|
ULONG FASTCALL WMM32midiInGetNumDevs(PVDMFRAME pFrame)
|
|
{
|
|
static FARPROC mmAPI = NULL;
|
|
ULONG ul;
|
|
|
|
GET_MULTIMEDIA_API( "midiInGetNumDevs", mmAPI, MMSYSERR_NODRIVER );
|
|
|
|
UNREFERENCED_PARAMETER(pFrame);
|
|
|
|
trace_midi(( "midiInGetNumDevs()" ));
|
|
ul = GETWORD16((*mmAPI)() );
|
|
trace_midi(( "-> %ld\n", ul ));
|
|
|
|
RETURN(ul);
|
|
}
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* WMM32midiInGetDevCaps
|
|
*
|
|
* This function queries a specified MIDI input device to determine its
|
|
* capabilities.
|
|
*
|
|
\**********************************************************************/
|
|
ULONG FASTCALL WMM32midiInGetDevCaps(PVDMFRAME pFrame)
|
|
{
|
|
ULONG ul;
|
|
MIDIINCAPS midiincaps1;
|
|
register PMIDIINGETDEVCAPS16 parg16;
|
|
static FARPROC mmAPI = NULL;
|
|
|
|
GET_MULTIMEDIA_API( "midiInGetDevCapsA", mmAPI, MMSYSERR_NODRIVER );
|
|
|
|
GETARGPTR(pFrame, sizeof(MIDIINGETDEVCAPS16), parg16);
|
|
|
|
trace_midi(( "midiInGetDevCaps( %x, %x, %x )", INT32( parg16->f1 ),
|
|
DWORD32( parg16->f2 ), UINT32( parg16->f3 ) ));
|
|
if ( UINT32( parg16->f3 ) == 0 ) {
|
|
ul = MMSYSERR_NOERROR;
|
|
}
|
|
else {
|
|
|
|
ul = GETWORD16((*mmAPI)(INT32(parg16->f1), &midiincaps1,
|
|
sizeof(MIDIINCAPS) ) );
|
|
/*
|
|
** This must now thunk the ENTIRE structure, then copy parg16->f3
|
|
** bytes onto the "real" structure in the app, but only if the
|
|
** call returned success.
|
|
*/
|
|
if ( ul == MMSYSERR_NOERROR ) {
|
|
ul = PUTMIDIINCAPS16( parg16->f2, &midiincaps1, UINT32(parg16->f3) );
|
|
}
|
|
}
|
|
trace_midi(( "-> %ld\n", ul ));
|
|
|
|
|
|
FREEARGPTR(parg16);
|
|
RETURN(ul);
|
|
}
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* WMM32midiInGetErrorText
|
|
*
|
|
* This function retrieves a textual description of the error identified by the
|
|
* specified error number.
|
|
*
|
|
\**********************************************************************/
|
|
ULONG FASTCALL WMM32midiInGetErrorText(PVDMFRAME pFrame)
|
|
{
|
|
register PMIDIINGETERRORTEXT16 parg16;
|
|
ULONG ul = MMSYSERR_NOERROR;
|
|
PSZ pszText;
|
|
static FARPROC mmAPI = NULL;
|
|
|
|
GET_MULTIMEDIA_API( "midiInGetErrorTextA", mmAPI, MMSYSERR_NODRIVER );
|
|
|
|
GETARGPTR( pFrame, sizeof(MIDIINGETERRORTEXT16), parg16 );
|
|
|
|
trace_midi(( "midiInGetErrorText( %x, %x, %x )", UINT32( parg16->f1 ),
|
|
DWORD32( parg16->f2 ), UINT32( parg16->f3 ) ));
|
|
/*
|
|
** Test against a zero length string and a NULL pointer. If 0 is passed
|
|
** as the buffer length then the manual says we should return
|
|
** MMSYSERR_NOERR.
|
|
*/
|
|
MMGETOPTPTR( parg16->f2, UINT32(parg16->f3), pszText );
|
|
if ( pszText != NULL ) {
|
|
|
|
ul = GETWORD16( (*mmAPI)( UINT32(parg16->f1), pszText,
|
|
UINT32(parg16->f3) ) );
|
|
|
|
FLUSHVDMPTR( DWORD32(parg16->f2), UINT32(parg16->f3), pszText);
|
|
FREEVDMPTR( pszText );
|
|
}
|
|
trace_midi(( "-> %ld\n", ul ));
|
|
|
|
FREEARGPTR(parg16);
|
|
RETURN(ul);
|
|
}
|
|
|
|
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* WMM32midiInOpen
|
|
*
|
|
* This function opens a specified MIDI input device.
|
|
*
|
|
\***********************************************************************/
|
|
ULONG FASTCALL WMM32midiInOpen(PVDMFRAME pFrame)
|
|
{
|
|
ULONG ul=0;
|
|
UINT uDevID;
|
|
PINSTANCEDATA pInstanceData;
|
|
LPHMIDIIN lpHMidiIn; // pointer to handle in 16 bit app space
|
|
HMIDIIN Hand32; // 32bit handle
|
|
register PMIDIINOPEN16 parg16;
|
|
static FARPROC mmAPI = NULL;
|
|
|
|
GET_MULTIMEDIA_API( "midiInOpen", mmAPI, MMSYSERR_NODRIVER );
|
|
|
|
GETARGPTR(pFrame, sizeof(MIDIINOPEN16), parg16);
|
|
|
|
trace_midi(( "midiInOpen( %x, %x, %x, %x, %x )",
|
|
DWORD32( parg16->f1 ), INT32 ( parg16->f2 ),
|
|
DWORD32( parg16->f3 ), DWORD32( parg16->f4 ),
|
|
DWORD32( parg16->f5 ) ));
|
|
|
|
/*
|
|
** Get the device ID. We use INT32 here not UINT32 to make sure that
|
|
** negative values (such as MIDI_MAPPER (-1)) get thunked correctly.
|
|
*/
|
|
uDevID = (UINT)INT32(parg16->f2);
|
|
|
|
/*
|
|
** Map the 16 bit pointer is one was specified.
|
|
*/
|
|
MMGETOPTPTR( parg16->f1, sizeof(HMIDIIN), lpHMidiIn );
|
|
if ( lpHMidiIn ) {
|
|
|
|
/*
|
|
** Create InstanceData block to be used by our callback routine.
|
|
**
|
|
** NOTE: Although we malloc it here we don't free it.
|
|
** This is not a mistake - it must not be freed before the
|
|
** callback routine has used it - so it does the freeing.
|
|
**
|
|
** If the malloc fails we bomb down to the bottom,
|
|
** set ul to MMSYSERR_NOMEM and exit gracefully.
|
|
**
|
|
** We always have a callback functions. This is to ensure that
|
|
** the MIDIHDR structure keeps getting copied back from
|
|
** 32 bit space to 16 bit, as it contains flags which
|
|
** applications are liable to keep checking.
|
|
*/
|
|
if ( pInstanceData = malloc_w(sizeof(INSTANCEDATA) ) ) {
|
|
|
|
dprintf2(( "WM32midiInOpen: Allocated instance buffer at %8X",
|
|
pInstanceData ));
|
|
pInstanceData->dwCallback = DWORD32(parg16->f3);
|
|
pInstanceData->dwCallbackInstance = DWORD32(parg16->f4);
|
|
pInstanceData->dwFlags = DWORD32(parg16->f5);
|
|
|
|
ul = GETWORD16((*mmAPI)( &Hand32, uDevID,
|
|
(DWORD)W32CommonDeviceOpen,
|
|
(DWORD)pInstanceData,
|
|
CALLBACK_FUNCTION ));
|
|
|
|
}
|
|
else {
|
|
|
|
ul = (ULONG)MMSYSERR_NOMEM;
|
|
}
|
|
|
|
/*
|
|
** If the call returns success update the 16 bit handle,
|
|
** otherwise don't, and free the memory we malloc'd earlier, as
|
|
** the callback that would have freed it will never get callled.
|
|
*/
|
|
if ( ul == MMSYSERR_NOERROR ) {
|
|
|
|
HMIDIIN16 Hand16 = GETHMIDIIN16(Hand32);
|
|
|
|
trace_midi(( "Handle -> %x", Hand16 ));
|
|
STOREWORD ( *lpHMidiIn, Hand16 );
|
|
FLUSHVDMPTR( DWORD32(parg16->f1), sizeof(HMIDIIN), lpHMidiIn );
|
|
}
|
|
|
|
/*
|
|
** We only free the memory if we actually allocated any and the
|
|
** 32 bit call failed.
|
|
*/
|
|
else if ( pInstanceData ) {
|
|
|
|
free_w(pInstanceData);
|
|
}
|
|
|
|
/*
|
|
** Regardless of sucess or failure we need to free the pointer
|
|
** to the 16 bit MidiIn handle.
|
|
*/
|
|
FREEVDMPTR ( lpHMidiIn );
|
|
|
|
}
|
|
else {
|
|
ul = MMSYSERR_INVALPARAM;
|
|
}
|
|
|
|
trace_midi(( "-> %ld\n", ul ));
|
|
|
|
FREEARGPTR(parg16);
|
|
RETURN(ul);
|
|
}
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* WMM32midiInClose
|
|
*
|
|
* This function closes the specified MIDI input device.
|
|
*
|
|
\**********************************************************************/
|
|
ULONG FASTCALL WMM32midiInClose(PVDMFRAME pFrame)
|
|
{
|
|
ULONG ul;
|
|
register PMIDIINCLOSE16 parg16;
|
|
static FARPROC mmAPI = NULL;
|
|
|
|
GET_MULTIMEDIA_API( "midiInClose", mmAPI, MMSYSERR_NODRIVER );
|
|
|
|
GETARGPTR(pFrame, sizeof(MIDIINCLOSE16), parg16);
|
|
|
|
trace_midi(( "midiInClose( %x )", WORD32( parg16->f1 ) ));
|
|
ul = GETWORD16((*mmAPI)(HMIDIIN32(parg16->f1) ) );
|
|
trace_midi(( "-> %ld\n", ul ));
|
|
|
|
FREEARGPTR(parg16);
|
|
RETURN(ul);
|
|
}
|
|
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* WMM32midiInPrepareHeader
|
|
*
|
|
* This function prepares the specified midiform header.
|
|
*
|
|
\**********************************************************************/
|
|
ULONG FASTCALL WMM32midiInPrepareHeader(PVDMFRAME pFrame)
|
|
{
|
|
register PMIDIOUTPREPAREHEADER3216 parg16;
|
|
static FARPROC mmAPI = NULL;
|
|
ULONG ul;
|
|
MIDIHDR midihdr;
|
|
|
|
|
|
GET_MULTIMEDIA_API( "midiInPrepareHeader", mmAPI, MMSYSERR_NODRIVER );
|
|
GETARGPTR(pFrame, sizeof(MIDIOUTPREPAREHEADER3216), parg16);
|
|
trace_midi(( "midiInPrepareHeader( %x %x %x)", WORD32( parg16->f1 ),
|
|
DWORD32( parg16->f2 ), WORD32( parg16->f3 ) ));
|
|
|
|
GETMIDIHDR16(parg16->f2, &midihdr);
|
|
|
|
ul = GETWORD16((*mmAPI)( HMIDIOUT32(parg16->f1),
|
|
&midihdr, WORD32(parg16->f3) ) );
|
|
/*
|
|
** Only update the 16 bit structure if the call returns success
|
|
**
|
|
*/
|
|
if ( !ul ) {
|
|
PUTMIDIHDR16(parg16->f2, &midihdr);
|
|
}
|
|
|
|
trace_midi(( "-> %ld\n", ul ));
|
|
FREEARGPTR(parg16);
|
|
RETURN(ul);
|
|
}
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* WMM32midiInUnprepareHeader
|
|
*
|
|
* This function prepares the specified midiform header.
|
|
* This function cleans up the preparation performed by midiInPrepareHeader.
|
|
* The function must be called after the device driver has finished with a
|
|
* data block. You must call this function before freeing the data buffer.
|
|
*
|
|
\**********************************************************************/
|
|
ULONG FASTCALL WMM32midiInUnprepareHeader(PVDMFRAME pFrame)
|
|
{
|
|
register PMIDIOUTUNPREPAREHEADER3216 parg16;
|
|
static FARPROC mmAPI = NULL;
|
|
ULONG ul;
|
|
MIDIHDR midihdr;
|
|
|
|
GET_MULTIMEDIA_API( "midiInUnprepareHeader", mmAPI, MMSYSERR_NODRIVER );
|
|
GETARGPTR(pFrame, sizeof(MIDIOUTUNPREPAREHEADER3216), parg16);
|
|
trace_midi(( "midiInUnprepareHeader( %x %x %x)", WORD32( parg16->f1 ),
|
|
DWORD32( parg16->f2 ), WORD32( parg16->f3 ) ));
|
|
|
|
GETMIDIHDR16(parg16->f2, &midihdr);
|
|
|
|
ul = GETWORD16((*mmAPI)( HMIDIOUT32(parg16->f1),
|
|
&midihdr, WORD32(parg16->f3) ) );
|
|
/*
|
|
** Only update the 16 bit structure if the call returns success
|
|
*/
|
|
if (!ul) {
|
|
PUTMIDIHDR16(parg16->f2, &midihdr);
|
|
}
|
|
|
|
trace_midi(( "-> %ld\n", ul ));
|
|
FREEARGPTR(parg16);
|
|
RETURN(ul);
|
|
}
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* WMM32midiInAddBuffer
|
|
*
|
|
* This function sends an input buffer to a specified opened MIDI input device.
|
|
* When the buffer is filled, it is sent back to the application. Input buffers
|
|
* are used only for system exclusive messages.
|
|
*
|
|
\**********************************************************************/
|
|
ULONG FASTCALL WMM32midiInAddBuffer(PVDMFRAME pFrame)
|
|
{
|
|
ULONG ul;
|
|
PMIDIHDR32 pMidihdr32;
|
|
register PMIDIINADDBUFFER16 parg16;
|
|
static FARPROC mmAPI = NULL;
|
|
|
|
GET_MULTIMEDIA_API( "midiInAddBuffer", mmAPI, MMSYSERR_NODRIVER );
|
|
|
|
GETARGPTR(pFrame, sizeof(MIDIINADDBUFFER16), parg16);
|
|
|
|
trace_midi(( "midiInAddBuffer( %x, %x, %x )", WORD32( parg16->f1 ),
|
|
DWORD32( parg16->f2 ), UINT32( parg16->f3 ) ));
|
|
|
|
/*
|
|
** If the given size of the MIDIHDR structure is too small
|
|
** or the lphdr is invalid return an error
|
|
**
|
|
*/
|
|
if ( UINT32(parg16->f3) < sizeof(MIDIHDR16)
|
|
|| HIWORD( DWORD32(parg16->f2) ) == 0 ) {
|
|
|
|
ul = (ULONG)MMSYSERR_INVALPARAM;
|
|
}
|
|
else {
|
|
if (pMidihdr32 = malloc_w(sizeof(MIDIHDR32) ) ) {
|
|
|
|
PMIDIHDR lpwhdr;
|
|
#if DBG
|
|
AllocMidiCount++;
|
|
dprintf2(( "M>> %8X (%d)", pMidihdr32, AllocMidiCount ));
|
|
#endif
|
|
/* Copy across the midi header stuff. Note that lpwhdr (a
|
|
** 32 bit ptr to a 32 bit midi header) is used to make the
|
|
** pointer stuff a bit less hairy.
|
|
**
|
|
** pMidihdr32->Midihdr is a 32 bit midi header
|
|
** pMidihdr32->pMidihdr16 is a 16 bit ptr to a 16 bit midi header
|
|
** pMidihdr32->pMidihdr32 is a 32 bit ptr to a 16 bit midi header
|
|
*/
|
|
lpwhdr = &(pMidihdr32->Midihdr);
|
|
pMidihdr32->pMidihdr16 = (PMIDIHDR16)DWORD32(parg16->f2);
|
|
pMidihdr32->pMidihdr32 = GETMIDIHDR16(DWORD32(parg16->f2), lpwhdr);
|
|
|
|
/*
|
|
** GETMIDIHDR16 can return NULL, in which case we should set
|
|
** lpwhdr to NULL too and call midiInAddBuffer only to get the
|
|
** correct error code.
|
|
*/
|
|
if ( pMidihdr32->pMidihdr32 == NULL ) {
|
|
lpwhdr = NULL;
|
|
}
|
|
|
|
ul = GETWORD16((*mmAPI)( HMIDIIN32(parg16->f1), lpwhdr,
|
|
UINT32(parg16->f3) ));
|
|
/*
|
|
** If the call fails we need to free the memory we malloc'd
|
|
** above, as the callback that would have freed it will never
|
|
** get called.
|
|
**
|
|
*/
|
|
if ( ul == MMSYSERR_NOERROR ) {
|
|
|
|
/*
|
|
** Make sure we reflect any changes that midiInAddBuffer did
|
|
** to the MIDIHDR back to 16 bit land.
|
|
**
|
|
** This is important because some apps poll the
|
|
** MHDR_DONE bit !!
|
|
*/
|
|
COPY_MIDIINHDR16_FLAGS( pMidihdr32->pMidihdr32,
|
|
pMidihdr32->Midihdr );
|
|
}
|
|
else {
|
|
#if DBG
|
|
AllocMidiCount--;
|
|
dprintf2(( "M<< \t%8X (%d)", pMidihdr32,
|
|
AllocMidiCount ));
|
|
#endif
|
|
free_w( pMidihdr32 );
|
|
}
|
|
}
|
|
else {
|
|
ul = (ULONG)MMSYSERR_NOMEM;
|
|
}
|
|
}
|
|
trace_midi(( "-> %ld\n", ul ));
|
|
|
|
FREEARGPTR(parg16);
|
|
RETURN(ul);
|
|
}
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* WMM32midiInStart
|
|
*
|
|
* This function starts MIDI input on the specified MIDI input device.
|
|
*
|
|
\**********************************************************************/
|
|
ULONG FASTCALL WMM32midiInStart(PVDMFRAME pFrame)
|
|
{
|
|
ULONG ul;
|
|
register PMIDIINSTART16 parg16;
|
|
static FARPROC mmAPI = NULL;
|
|
|
|
GET_MULTIMEDIA_API( "midiInStart", mmAPI, MMSYSERR_NODRIVER );
|
|
|
|
GETARGPTR(pFrame, sizeof(MIDIINSTART16), parg16);
|
|
|
|
trace_midi(( "midiInStart( %x )", WORD32( parg16->f1 ) ));
|
|
ul = GETWORD16((*mmAPI)(HMIDIIN32(parg16->f1) ) );
|
|
trace_midi(( "-> %ld\n", ul ));
|
|
|
|
FREEARGPTR(parg16);
|
|
RETURN(ul);
|
|
}
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* WMM32midiInStop
|
|
*
|
|
* This function terminates MIDI input on the specified MIDI input device.
|
|
*
|
|
\**********************************************************************/
|
|
ULONG FASTCALL WMM32midiInStop(PVDMFRAME pFrame)
|
|
{
|
|
ULONG ul;
|
|
register PMIDIINSTOP16 parg16;
|
|
static FARPROC mmAPI = NULL;
|
|
|
|
GET_MULTIMEDIA_API( "midiInStop", mmAPI, MMSYSERR_NODRIVER );
|
|
|
|
GETARGPTR(pFrame, sizeof(MIDIINSTOP16), parg16);
|
|
|
|
trace_midi(( "midiInStop( %x )", WORD32( parg16->f1 ) ));
|
|
ul = GETWORD16((*mmAPI)(HMIDIIN32(parg16->f1) ) );
|
|
trace_midi(( "-> %ld\n", ul ));
|
|
|
|
FREEARGPTR(parg16);
|
|
RETURN(ul);
|
|
}
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* WMM32midiInReset
|
|
*
|
|
* This function stops input on a given MIDI input device and marks all pending
|
|
* input buffers as done.
|
|
*
|
|
\**********************************************************************/
|
|
ULONG FASTCALL WMM32midiInReset(PVDMFRAME pFrame)
|
|
{
|
|
ULONG ul;
|
|
register PMIDIINRESET16 parg16;
|
|
static FARPROC mmAPI = NULL;
|
|
|
|
GET_MULTIMEDIA_API( "midiInReset", mmAPI, MMSYSERR_NODRIVER );
|
|
|
|
GETARGPTR(pFrame, sizeof(MIDIINRESET16), parg16);
|
|
|
|
trace_midi(( "midiInReset( %x )", WORD32( parg16->f1 ) ));
|
|
ul = GETWORD16((*mmAPI)(HMIDIIN32(parg16->f1) ) );
|
|
trace_midi(( "-> %ld\n", ul ));
|
|
|
|
FREEARGPTR(parg16);
|
|
RETURN(ul);
|
|
}
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* WMM32midiInGetID
|
|
*
|
|
* This function gets the device ID for a MIDI input device.
|
|
*
|
|
\**********************************************************************/
|
|
ULONG FASTCALL WMM32midiInGetID(PVDMFRAME pFrame)
|
|
{
|
|
register PMIDIINGETID16 parg16;
|
|
static FARPROC mmAPI = NULL;
|
|
ULONG ul;
|
|
UINT dwDeviceID32;
|
|
LPWORD lpwDeviceID16;
|
|
|
|
GET_MULTIMEDIA_API( "midiInGetID", mmAPI, MMSYSERR_NODRIVER );
|
|
|
|
GETARGPTR(pFrame, sizeof(MIDIINGETID16), parg16);
|
|
|
|
trace_midi(( "midiInGetID( %x, %x )", WORD32( parg16->f1 ),
|
|
DWORD32( parg16->f2 ) ));
|
|
|
|
ul = GETWORD16((*mmAPI)( HMIDIIN32(parg16->f1), &dwDeviceID32 ));
|
|
|
|
/*
|
|
** Only copy the ID back to 16 bit space if the call was sucessful
|
|
**
|
|
*/
|
|
if ( ul == MMSYSERR_NOERROR ) {
|
|
|
|
MMGETOPTPTR( parg16->f2, sizeof(WORD), lpwDeviceID16 );
|
|
|
|
if ( lpwDeviceID16 ) {
|
|
STOREWORD ( *lpwDeviceID16, dwDeviceID32 );
|
|
FLUSHVDMPTR( DWORD32(parg16->f2), sizeof(WORD), lpwDeviceID16 );
|
|
FREEVDMPTR ( lpwDeviceID16 );
|
|
}
|
|
else {
|
|
ul = MMSYSERR_INVALPARAM;
|
|
}
|
|
}
|
|
trace_midi(( "-> %ld\n", ul ));
|
|
|
|
FREEARGPTR(parg16);
|
|
RETURN(ul);
|
|
}
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* WMM32midiInMessage
|
|
*
|
|
* This function sends a message to the specified MIDI input device.
|
|
*
|
|
\**********************************************************************/
|
|
ULONG FASTCALL WMM32midiInMessage(PVDMFRAME pFrame)
|
|
{
|
|
ULONG ul;
|
|
register PMIDIINMESSAGE3216 parg16;
|
|
static FARPROC mmAPI = NULL;
|
|
|
|
GET_MULTIMEDIA_API( "midiInMessage", mmAPI, MMSYSERR_NODRIVER );
|
|
|
|
GETARGPTR(pFrame, sizeof(MIDIINMESSAGE16), parg16);
|
|
|
|
trace_midi(( "midiInMessage( %x, %x, %x, %x )",
|
|
WORD32( parg16->f1 ), UINT32( parg16->f2 ),
|
|
DWORD32( parg16->f3 ), DWORD32( parg16->f4 ) ));
|
|
|
|
if ( (UINT32(parg16->f2) >= DRV_BUFFER_LOW)
|
|
&& (UINT32(parg16->f2) <= DRV_BUFFER_HIGH) ) {
|
|
|
|
LPDWORD lpdwParam1;
|
|
GETMISCPTR(parg16->f3, lpdwParam1);
|
|
|
|
ul = GETDWORD16((*mmAPI)( HMIDIIN32(parg16->f1), UINT32(parg16->f2),
|
|
(DWORD)lpdwParam1, DWORD32(parg16->f4)));
|
|
FREEMISCPTR(lpdwParam1);
|
|
|
|
} else {
|
|
ul = GETDWORD16((*mmAPI)( HMIDIIN32(parg16->f1),
|
|
MAKELONG( WORD32(parg16->f2), 0xFFFF ),
|
|
DWORD32(parg16->f3), DWORD32(parg16->f4) ));
|
|
}
|
|
|
|
trace_midi(( "-> %ld\n", ul ));
|
|
FREEARGPTR(parg16);
|
|
RETURN(ul);
|
|
}
|
|
|
|
|
|
/* ---------------------------------------------------------------------
|
|
** WAVE Output API's
|
|
** ---------------------------------------------------------------------
|
|
*/
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* WMM32waveOutGetNumDevs
|
|
*
|
|
* This function retrieves the number of waveform output devices present in the
|
|
* system.
|
|
*
|
|
\**********************************************************************/
|
|
ULONG FASTCALL WMM32waveOutGetNumDevs(PVDMFRAME pFrame)
|
|
{
|
|
static FARPROC mmAPI = NULL;
|
|
ULONG ul;
|
|
|
|
GET_MULTIMEDIA_API( "waveOutGetNumDevs", mmAPI, MMSYSERR_NODRIVER );
|
|
|
|
trace_wave(( "waveOutGetNumDevs()" ));
|
|
ul = GETWORD16((*mmAPI)() );
|
|
trace_wave(( "-> %ld\n", ul ));
|
|
|
|
RETURN(ul);
|
|
|
|
UNREFERENCED_PARAMETER(pFrame);
|
|
}
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* WMM32waveOutGetDevCaps
|
|
*
|
|
* This function queries a specified waveform device to determine its
|
|
* capabilities.
|
|
*
|
|
\**********************************************************************/
|
|
ULONG FASTCALL WMM32waveOutGetDevCaps(PVDMFRAME pFrame)
|
|
{
|
|
register PWAVEOUTGETDEVCAPS16 parg16;
|
|
static FARPROC mmAPI = NULL;
|
|
ULONG ul;
|
|
WAVEOUTCAPS waveoutcaps;
|
|
|
|
GET_MULTIMEDIA_API( "waveOutGetDevCapsA", mmAPI, MMSYSERR_NODRIVER );
|
|
|
|
GETARGPTR(pFrame, sizeof(WAVEOUTGETDEVCAPS16), parg16);
|
|
|
|
trace_wave(( "waveOutGetDevCaps( %x, %x, %x )", INT32( parg16->f1 ),
|
|
DWORD32( parg16->f2 ), UINT32( parg16->f3 ) ));
|
|
|
|
/*
|
|
** If the size parameter was zero return straight away. Note that this
|
|
** is not an error.
|
|
*/
|
|
if ( UINT32( parg16->f3 ) == 0 ) {
|
|
ul = MMSYSERR_NOERROR;
|
|
}
|
|
else {
|
|
|
|
ul = GETWORD16((*mmAPI)( INT32(parg16->f1), &waveoutcaps,
|
|
sizeof(WAVEOUTCAPS) ));
|
|
/*
|
|
** Don't update the 16 bit structure if the call failed
|
|
**
|
|
*/
|
|
if ( ul == MMSYSERR_NOERROR ) {
|
|
ul = PUTWAVEOUTCAPS16(parg16->f2, &waveoutcaps, UINT32(parg16->f3));
|
|
}
|
|
}
|
|
|
|
trace_wave(( "-> %ld\n", ul ));
|
|
|
|
FREEARGPTR(parg16);
|
|
|
|
RETURN(ul);
|
|
}
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* WMM32waveOutGetErrorText
|
|
*
|
|
* This function retrieves a textual description of the error identified by the
|
|
* specified error number.
|
|
*
|
|
\**********************************************************************/
|
|
ULONG FASTCALL WMM32waveOutGetErrorText(PVDMFRAME pFrame)
|
|
{
|
|
register PWAVEOUTGETERRORTEXT16 parg16;
|
|
static FARPROC mmAPI = NULL;
|
|
ULONG ul = MMSYSERR_NOERROR;
|
|
PSZ pszText;
|
|
|
|
GET_MULTIMEDIA_API( "waveOutGetErrorTextA", mmAPI, MMSYSERR_NODRIVER );
|
|
|
|
GETARGPTR(pFrame, sizeof(WAVEOUTGETERRORTEXT16), parg16);
|
|
|
|
trace_wave(( "waveOutGetErrorText( %x, %x, %x )", UINT32( parg16->f1 ),
|
|
DWORD32( parg16->f2 ), UINT32( parg16->f3 ) ));
|
|
|
|
/*
|
|
** Test against a zero length string and a NULL pointer. If 0 is passed
|
|
** as the buffer length then the manual says we should return
|
|
** MMSYSERR_NOERR. MMGETOPTPTR only returns a pointer if parg16->f2 is
|
|
** not NULL.
|
|
*/
|
|
MMGETOPTPTR( parg16->f2, UINT32(parg16->f3), pszText );
|
|
if ( pszText != NULL ) {
|
|
|
|
ul = GETWORD16( (*mmAPI)( UINT32(parg16->f1), pszText,
|
|
UINT32(parg16->f3) ) );
|
|
|
|
FLUSHVDMPTR( DWORD32(parg16->f2), UINT32(parg16->f3), pszText);
|
|
FREEVDMPTR(pszText);
|
|
}
|
|
trace_wave(( "-> %ld\n", ul ));
|
|
|
|
FREEARGPTR(parg16);
|
|
RETURN(ul);
|
|
}
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* WMM32waveOutOpen
|
|
*
|
|
* This function opens a specified waveform output device for playback.
|
|
*
|
|
* As of November 1992 we map the 16 bit Wave Format data directly to the
|
|
* the 32 bit side, no thunking of the parameters is performed.
|
|
*
|
|
\**********************************************************************/
|
|
ULONG FASTCALL WMM32waveOutOpen(PVDMFRAME pFrame)
|
|
{
|
|
ULONG ul = MMSYSERR_NOERROR;
|
|
UINT uDevID;
|
|
PINSTANCEDATA pInstanceData = NULL;
|
|
DWORD dwFlags;
|
|
PWAVEFORMAT16 lpWaveformData;
|
|
LPHWAVEOUT lphWaveOut = NULL; // pointer to handle in 16 bit app space
|
|
HWAVEOUT Hand32; // 32bit handle
|
|
register PWAVEOUTOPEN16 parg16;
|
|
static FARPROC mmAPI = NULL;
|
|
|
|
GET_MULTIMEDIA_API( "waveOutOpen", mmAPI, MMSYSERR_NODRIVER );
|
|
|
|
|
|
GETARGPTR(pFrame, sizeof(WAVEOUTOPEN16), parg16);
|
|
|
|
trace_wave(( "waveOutOpen( %x, %x, %x, %x, %x, %x )",
|
|
DWORD32( parg16->f1 ), INT32 ( parg16->f2 ),
|
|
DWORD32( parg16->f3 ), DWORD32( parg16->f4 ),
|
|
DWORD32( parg16->f5 ), DWORD32( parg16->f6 ) ));
|
|
|
|
/*
|
|
** Get the device ID. We use INT32 here not UINT32 to make sure that
|
|
** negative values (such as WAVE_MAPPER (-1)) get thunked correctly.
|
|
** Also, get the flags to be used.
|
|
*/
|
|
uDevID = (UINT)INT32(parg16->f2);
|
|
dwFlags = DWORD32(parg16->f6);
|
|
|
|
|
|
/*
|
|
** Get a pointer to the WAVEFORMAT structure. Because the format of this
|
|
** structure is exactly the same in 32 and 16 bit land I will use
|
|
** GETMISCPTR to get a generic pointer to the data. The stuff being
|
|
** pointed to could be full of unaligned WORDs, but the 32 bit code
|
|
** would have to cope with this anyway.
|
|
*/
|
|
GETMISCPTR( parg16->f3, lpWaveformData );
|
|
if ( lpWaveformData == (PWAVEFORMAT16)NULL ) {
|
|
ul = (ULONG)MMSYSERR_INVALPARAM;
|
|
goto exit_function;
|
|
}
|
|
|
|
|
|
/*
|
|
** We don't need a callback routine when the WAVE_FORMAT_QUERY flag
|
|
** is specified.
|
|
*/
|
|
if ( !(dwFlags & WAVE_FORMAT_QUERY) ) {
|
|
|
|
/*
|
|
** Map the 16 bit pointer is one was specified.
|
|
*/
|
|
MMGETOPTPTR( parg16->f1, sizeof(HWAVEOUT), lphWaveOut );
|
|
if ( lphWaveOut == NULL ) {
|
|
|
|
ul = MMSYSERR_INVALPARAM;
|
|
}
|
|
|
|
/*
|
|
** Create InstanceData block to be used by our callback routine.
|
|
**
|
|
** NOTE: Although we malloc it here we don't free it.
|
|
** This is not a mistake - it must not be freed before the
|
|
** callback routine has used it - so it does the freeing.
|
|
**
|
|
** If the malloc fails we bomb down to the bottom,
|
|
** set ul to MMSYSERR_NOMEM and exit gracefully.
|
|
**
|
|
** We always have a callback functions. This is to ensure that
|
|
** the WAVEHDR structure keeps getting copied back from
|
|
** 32 bit space to 16 bit, as it contains flags which
|
|
** applications are liable to keep checking.
|
|
*/
|
|
else if ( pInstanceData = malloc_w(sizeof(INSTANCEDATA) ) ) {
|
|
|
|
DWORD dwNewFlags = CALLBACK_FUNCTION;
|
|
|
|
dprintf2(( "WM32waveOutOpen: Allocated instance buffer at %8X",
|
|
pInstanceData ));
|
|
pInstanceData->dwCallback = DWORD32(parg16->f4);;
|
|
pInstanceData->dwCallbackInstance = DWORD32(parg16->f5);
|
|
pInstanceData->dwFlags = dwFlags;
|
|
|
|
dwNewFlags |= (dwFlags & WAVE_ALLOWSYNC);
|
|
|
|
ul = GETWORD16((*mmAPI)( &Hand32, uDevID,
|
|
(LPWAVEFORMAT)lpWaveformData,
|
|
(DWORD)W32CommonDeviceOpen,
|
|
(DWORD)pInstanceData, dwNewFlags ));
|
|
/*
|
|
** If the call returns success update the 16 bit handle,
|
|
** otherwise don't, and free the memory we malloc'd earlier, as
|
|
** the callback that would have freed it will never get callled.
|
|
*/
|
|
if ( ul == MMSYSERR_NOERROR ) {
|
|
|
|
HWAVEOUT16 Hand16 = GETHWAVEOUT16(Hand32);
|
|
|
|
trace_wave(( "Handle -> %x", Hand16 ));
|
|
|
|
STOREWORD ( *lphWaveOut, Hand16);
|
|
FLUSHVDMPTR( DWORD32(parg16->f1), sizeof(HWAVEOUT),
|
|
lphWaveOut );
|
|
}
|
|
else {
|
|
|
|
dprintf2(( "WM32waveOutOpen: Freeing instance buffer at %8X",
|
|
pInstanceData ));
|
|
free_w(pInstanceData);
|
|
}
|
|
|
|
/*
|
|
** Regardless of sucess or failure we need to free the pointer
|
|
** to the 16 bit WaveOut handle.
|
|
*/
|
|
FREEVDMPTR ( lphWaveOut );
|
|
}
|
|
else {
|
|
ul = (ULONG)MMSYSERR_NOMEM;
|
|
}
|
|
}
|
|
else {
|
|
ul = GETWORD16((*mmAPI)( NULL, uDevID, (LPWAVEFORMAT)lpWaveformData,
|
|
DWORD32(parg16->f4), DWORD32(parg16->f5),
|
|
dwFlags ));
|
|
}
|
|
|
|
/*
|
|
** Regardless of sucess or failure we need to free the pointer to the
|
|
** 16 bit WaveFormatData.
|
|
*/
|
|
FREEMISCPTR( lpWaveformData );
|
|
|
|
|
|
exit_function:
|
|
trace_wave(( "-> %ld\n", ul ));
|
|
FREEARGPTR(parg16);
|
|
RETURN(ul);
|
|
}
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* WMM32waveOutClose
|
|
*
|
|
* This function closes the specified waveform output device.
|
|
*
|
|
\**********************************************************************/
|
|
ULONG FASTCALL WMM32waveOutClose(PVDMFRAME pFrame)
|
|
{
|
|
register PWAVEOUTCLOSE16 parg16;
|
|
static FARPROC mmAPI = NULL;
|
|
ULONG ul;
|
|
|
|
GET_MULTIMEDIA_API( "waveOutClose", mmAPI, MMSYSERR_NODRIVER );
|
|
|
|
GETARGPTR(pFrame, sizeof(WAVEOUTCLOSE16), parg16);
|
|
|
|
trace_wave(( "waveOutClose( %x )", WORD32( parg16->f1 ) ));
|
|
ul = GETWORD16((*mmAPI)( HWAVEOUT32(parg16->f1) ));
|
|
trace_wave(( "-> %ld\n", ul ));
|
|
|
|
FREEARGPTR(parg16);
|
|
RETURN(ul);
|
|
}
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* WMM32waveOutPrepareHeader
|
|
*
|
|
* This function prepares the specified waveform header.
|
|
*
|
|
\**********************************************************************/
|
|
ULONG FASTCALL WMM32waveOutPrepareHeader(PVDMFRAME pFrame)
|
|
{
|
|
register PWAVEOUTPREPAREHEADER3216 parg16;
|
|
static FARPROC mmAPI = NULL;
|
|
ULONG ul;
|
|
WAVEHDR wavehdr;
|
|
|
|
|
|
GET_MULTIMEDIA_API( "waveOutPrepareHeader", mmAPI, MMSYSERR_NODRIVER );
|
|
GETARGPTR(pFrame, sizeof(WAVEOUTPREPAREHEADER3216), parg16);
|
|
trace_wave(( "waveOutPrepareHeader( %x %x %x)", WORD32( parg16->f1 ),
|
|
DWORD32( parg16->f2 ), WORD32( parg16->f3 ) ));
|
|
|
|
GETWAVEHDR16(parg16->f2, &wavehdr);
|
|
|
|
ul = GETWORD16((*mmAPI)( HWAVEOUT32(parg16->f1),
|
|
&wavehdr, WORD32(parg16->f3) ) );
|
|
/*
|
|
** Only update the 16 bit structure if the call returns success
|
|
**
|
|
*/
|
|
if ( !ul ) {
|
|
PUTWAVEHDR16(parg16->f2, &wavehdr);
|
|
}
|
|
|
|
trace_wave(( "-> %ld\n", ul ));
|
|
FREEARGPTR(parg16);
|
|
RETURN(ul);
|
|
}
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* WMM32waveOutUnprepareHeader
|
|
*
|
|
* This function prepares the specified waveform header.
|
|
* This function cleans up the preparation performed by waveOutPrepareHeader.
|
|
* The function must be called after the device driver has finished with a
|
|
* data block. You must call this function before freeing the data buffer.
|
|
*
|
|
\**********************************************************************/
|
|
ULONG FASTCALL WMM32waveOutUnprepareHeader(PVDMFRAME pFrame)
|
|
{
|
|
register PWAVEOUTUNPREPAREHEADER3216 parg16;
|
|
static FARPROC mmAPI = NULL;
|
|
ULONG ul;
|
|
WAVEHDR wavehdr;
|
|
|
|
GET_MULTIMEDIA_API( "waveOutUnprepareHeader", mmAPI, MMSYSERR_NODRIVER );
|
|
GETARGPTR(pFrame, sizeof(WAVEOUTUNPREPAREHEADER3216), parg16);
|
|
trace_wave(( "waveOutUnprepareHeader( %x %x %x)", WORD32( parg16->f1 ),
|
|
DWORD32( parg16->f2 ), WORD32( parg16->f3 ) ));
|
|
|
|
GETWAVEHDR16(parg16->f2, &wavehdr);
|
|
|
|
ul = GETWORD16((*mmAPI)( HWAVEOUT32(parg16->f1),
|
|
&wavehdr, WORD32(parg16->f3) ) );
|
|
/*
|
|
** Only update the 16 bit structure if the call returns success
|
|
*/
|
|
if (!ul) {
|
|
PUTWAVEHDR16(parg16->f2, &wavehdr);
|
|
}
|
|
|
|
trace_wave(( "-> %ld\n", ul ));
|
|
FREEARGPTR(parg16);
|
|
RETURN(ul);
|
|
}
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* WMM32waveOutWrite
|
|
*
|
|
* This function sends a data block to the specified waveform output device.
|
|
*
|
|
\**********************************************************************/
|
|
ULONG FASTCALL WMM32waveOutWrite(PVDMFRAME pFrame)
|
|
{
|
|
register PWAVEOUTWRITE16 parg16;
|
|
static FARPROC mmAPI = NULL;
|
|
ULONG ul;
|
|
PWAVEHDR32 pWavehdr32;
|
|
|
|
GET_MULTIMEDIA_API( "waveOutWrite", mmAPI, MMSYSERR_NODRIVER );
|
|
|
|
GETARGPTR(pFrame, sizeof(WAVEOUTWRITE16), parg16);
|
|
|
|
trace_wave(( "waveOutWrite( %x, %x, %x)", WORD32( parg16->f1 ),
|
|
DWORD32( parg16->f2 ), UINT32( parg16->f3 ) ));
|
|
|
|
/*
|
|
** If the given size of the WAVEHDR structure is too small
|
|
** or the lphdr is invalid return an error
|
|
**
|
|
*/
|
|
if ( UINT32(parg16->f3) < sizeof(WAVEHDR16)
|
|
|| HIWORD( DWORD32(parg16->f2) ) == 0 ) {
|
|
|
|
ul = (ULONG)MMSYSERR_INVALPARAM;
|
|
}
|
|
else {
|
|
|
|
if ( pWavehdr32 = malloc_w( sizeof(WAVEHDR32) ) ) {
|
|
|
|
PWAVEHDR lpwhdr; /* used to simplify ptr stuff later on */
|
|
#if DBG
|
|
AllocWaveCount++;
|
|
dprintf2(( "W>> %8X (%d)", pWavehdr32, AllocWaveCount ));
|
|
#endif
|
|
|
|
/* Copy across the wave header stuff. Note that lpwhdr (a
|
|
** 32 bit ptr to a 32 bit wave header) is used to make the
|
|
** pointer stuff a bit less hairy.
|
|
**
|
|
** pWavehdr32->Wavehdr is a 32 bit wave header
|
|
** pWavehdr32->pWavehdr16 is a 16 bit ptr to a 16 bit wave header
|
|
** pWavehdr32->pWavehdr32 is a 32 bit ptr to a 16 bit wave header
|
|
*/
|
|
lpwhdr = &(pWavehdr32->Wavehdr);
|
|
pWavehdr32->pWavehdr16 = (PWAVEHDR16)DWORD32(parg16->f2);
|
|
pWavehdr32->pWavehdr32 = GETWAVEHDR16(DWORD32(parg16->f2), lpwhdr);
|
|
|
|
/*
|
|
** GETWAVEHDR16 can return NULL, in which case we should set
|
|
** lpwhdr to NULL too and call waveOutWrite only to get the
|
|
** correct error code.
|
|
*/
|
|
if ( pWavehdr32->pWavehdr32 == NULL ) {
|
|
lpwhdr = NULL;
|
|
}
|
|
|
|
ul = GETWORD16( (*mmAPI)( HWAVEOUT32(parg16->f1),
|
|
lpwhdr, UINT32(parg16->f3) ) );
|
|
|
|
/* If the call fails we need to free the memory we malloc'd
|
|
** above, as the callback that would have freed it will never
|
|
** get called.
|
|
*/
|
|
if ( ul == MMSYSERR_NOERROR ) {
|
|
|
|
/* Make sure we reflect any changes that waveOutWrite did
|
|
** to the WAVEHDR back to 16 bit land.
|
|
**
|
|
** This is important because some apps (waveedit) poll the
|
|
** WHDR_DONE bit !!
|
|
*/
|
|
COPY_WAVEOUTHDR16_FLAGS( pWavehdr32->pWavehdr32,
|
|
pWavehdr32->Wavehdr );
|
|
}
|
|
else {
|
|
#if DBG
|
|
AllocWaveCount--;
|
|
dprintf2(( "W<< \t%8X (%d)", pWavehdr32,
|
|
AllocWaveCount ));
|
|
#endif
|
|
free_w( pWavehdr32 );
|
|
}
|
|
}
|
|
else {
|
|
ul = (ULONG)MMSYSERR_NOMEM;
|
|
}
|
|
}
|
|
|
|
trace_wave(( "-> %ld\n", ul ));
|
|
FREEARGPTR(parg16);
|
|
RETURN(ul);
|
|
}
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* WMM32waveOutPause
|
|
*
|
|
* This function pauses playback on a specified waveform output device. The
|
|
* current playback position is saved. Use wavOutRestart to resume playback from
|
|
* the current playback position.
|
|
*
|
|
\**********************************************************************/
|
|
ULONG FASTCALL WMM32waveOutPause(PVDMFRAME pFrame)
|
|
{
|
|
ULONG ul;
|
|
register PWAVEOUTPAUSE16 parg16;
|
|
static FARPROC mmAPI = NULL;
|
|
|
|
GET_MULTIMEDIA_API( "waveOutPause", mmAPI, MMSYSERR_NODRIVER );
|
|
|
|
GETARGPTR(pFrame, sizeof(WAVEOUTPAUSE16), parg16);
|
|
|
|
trace_wave(( "waveOutGetPause( %x )", WORD32( parg16->f1 ) ));
|
|
ul = GETWORD16((*mmAPI)( HWAVEOUT32(parg16->f1) ));
|
|
trace_wave(( "-> %ld\n", ul ));
|
|
|
|
FREEARGPTR(parg16);
|
|
RETURN(ul);
|
|
}
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* WMM32waveOutRestart
|
|
*
|
|
* This function restarts a paused waveform output device.
|
|
*
|
|
\**********************************************************************/
|
|
ULONG FASTCALL WMM32waveOutRestart(PVDMFRAME pFrame)
|
|
{
|
|
ULONG ul;
|
|
register PWAVEOUTRESTART16 parg16;
|
|
static FARPROC mmAPI = NULL;
|
|
|
|
GET_MULTIMEDIA_API( "waveOutRestart", mmAPI, MMSYSERR_NODRIVER );
|
|
|
|
GETARGPTR(pFrame, sizeof(WAVEOUTRESTART16), parg16);
|
|
|
|
trace_wave(( "waveOutRestart( %x )", WORD32( parg16->f1 ) ));
|
|
ul = GETWORD16((*mmAPI)( HWAVEOUT32(parg16->f1) ));
|
|
trace_wave(( "-> %ld\n", ul ));
|
|
|
|
FREEARGPTR(parg16);
|
|
RETURN(ul);
|
|
}
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* WMM32waveOutReset
|
|
*
|
|
* This function stops playback on a given waveform output device and resets the
|
|
* current position to 0. All pending playback buffers are marked as done and
|
|
* returned to the application.
|
|
*
|
|
\**********************************************************************/
|
|
ULONG FASTCALL WMM32waveOutReset(PVDMFRAME pFrame)
|
|
{
|
|
ULONG ul;
|
|
register PWAVEOUTRESET16 parg16;
|
|
static FARPROC mmAPI = NULL;
|
|
|
|
GET_MULTIMEDIA_API( "waveOutReset", mmAPI, MMSYSERR_NODRIVER );
|
|
|
|
GETARGPTR(pFrame, sizeof(WAVEOUTRESET16), parg16);
|
|
|
|
trace_wave(( "waveOutReset( %x )", WORD32( parg16->f1 ) ));
|
|
ul = GETWORD16( (*mmAPI)( HWAVEOUT32(parg16->f1) ));
|
|
trace_wave(( "-> %ld\n", ul ));
|
|
|
|
FREEARGPTR(parg16);
|
|
RETURN(ul);
|
|
}
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* WMM32waveOutGetPosition
|
|
*
|
|
* This function retrieves the current palyback position of the specified
|
|
* waveform output device.
|
|
*
|
|
\**********************************************************************/
|
|
ULONG FASTCALL WMM32waveOutGetPosition(PVDMFRAME pFrame)
|
|
{
|
|
register PWAVEOUTGETPOSITION16 parg16;
|
|
static FARPROC mmAPI = NULL;
|
|
MMTIME mmtime;
|
|
ULONG ul = MMSYSERR_INVALPARAM;
|
|
|
|
GET_MULTIMEDIA_API( "waveOutGetPosition", mmAPI, MMSYSERR_NODRIVER );
|
|
|
|
GETARGPTR(pFrame, sizeof(WAVEOUTGETPOSITION16), parg16);
|
|
|
|
trace_wave(( "waveOutGetPosition( %x, %x, %x )", WORD32( parg16->f1 ),
|
|
DWORD32( parg16->f2 ), UINT32( parg16->f3 ) ));
|
|
|
|
/*
|
|
** If the given size of the MMTIME structure is too small return an error
|
|
**
|
|
** There is a problem here on MIPS. For some reason the MIPS
|
|
** compiler thinks a MMTIME16 structure is 10 bytes big. We
|
|
** have a pragma in wowmmed.h to align this structure on byte
|
|
** boundaries therefore I guess this is a compiler bug!
|
|
**
|
|
** If the input structure is not large enough we return immediately
|
|
*/
|
|
|
|
#ifdef MIPS_COMPILER_PACKING_BUG
|
|
if ( UINT32(parg16->f3) >= 8 ) {
|
|
#else
|
|
if ( UINT32(parg16->f3) >= sizeof(MMTIME16) ) {
|
|
#endif
|
|
|
|
ul = GETMMTIME16( parg16->f2, &mmtime);
|
|
if ( ul == MMSYSERR_NOERROR ) {
|
|
|
|
ul = GETWORD16((*mmAPI)( HWAVEOUT32(parg16->f1),
|
|
&mmtime, sizeof(MMTIME) ));
|
|
/*
|
|
** Only update the 16 bit structure if the call returns success
|
|
**
|
|
*/
|
|
if ( ul == MMSYSERR_NOERROR ) {
|
|
ul = PUTMMTIME16( parg16->f2, &mmtime);
|
|
}
|
|
}
|
|
}
|
|
|
|
trace_wave(( "-> %ld\n", ul ));
|
|
FREEARGPTR(parg16);
|
|
RETURN(ul);
|
|
}
|
|
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* WMM32waveOutGetPitch
|
|
*
|
|
* This function queries the current pitch setting of a waveform output device.
|
|
*
|
|
\**********************************************************************/
|
|
ULONG FASTCALL WMM32waveOutGetPitch(PVDMFRAME pFrame)
|
|
{
|
|
register PWAVEOUTGETPITCH16 parg16;
|
|
static FARPROC mmAPI = NULL;
|
|
ULONG ul = MMSYSERR_INVALPARAM;
|
|
LPDWORD lpdwPitch;
|
|
DWORD dwPitch;
|
|
|
|
GET_MULTIMEDIA_API( "waveOutGetPitch", mmAPI, MMSYSERR_NODRIVER );
|
|
|
|
GETARGPTR(pFrame, sizeof(WAVEOUTGETPITCH16), parg16);
|
|
trace_wave(( "waveOutGetPitch( %x, %x )", WORD32( parg16->f1 ),
|
|
DWORD32( parg16->f2 ) ));
|
|
|
|
ul = GETWORD16((*mmAPI)( HWAVEOUT32(parg16->f1), &dwPitch ));
|
|
|
|
if ( ul == MMSYSERR_NOERROR ) {
|
|
|
|
MMGETOPTPTR( parg16->f2, sizeof(DWORD), lpdwPitch);
|
|
|
|
if ( lpdwPitch ) {
|
|
STOREDWORD ( *lpdwPitch, dwPitch );
|
|
FLUSHVDMPTR( DWORD32(parg16->f2), sizeof(DWORD), lpdwPitch );
|
|
FREEVDMPTR ( lpdwPitch );
|
|
}
|
|
else {
|
|
ul = MMSYSERR_INVALPARAM;
|
|
}
|
|
}
|
|
|
|
trace_wave(( "-> %ld\n", ul ));
|
|
FREEARGPTR(parg16);
|
|
RETURN(ul);
|
|
}
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* WMM32waveOutSetPitch
|
|
*
|
|
* This function sets the pitch of a waveform output device.
|
|
*
|
|
\**********************************************************************/
|
|
ULONG FASTCALL WMM32waveOutSetPitch(PVDMFRAME pFrame)
|
|
{
|
|
register PWAVEOUTSETPITCH16 parg16;
|
|
static FARPROC mmAPI = NULL;
|
|
ULONG ul;
|
|
|
|
GET_MULTIMEDIA_API( "waveOutSetPitch", mmAPI, MMSYSERR_NODRIVER );
|
|
|
|
GETARGPTR(pFrame, sizeof(WAVEOUTSETPITCH16), parg16);
|
|
trace_wave(( "waveOutSetPitch( %x, %x )", WORD32( parg16->f1 ),
|
|
DWORD32( parg16->f2 ) ));
|
|
|
|
ul = GETWORD16((*mmAPI)( HWAVEOUT32(parg16->f1), DWORD32(parg16->f2) ));
|
|
|
|
trace_wave(( "-> %ld\n", ul ));
|
|
FREEARGPTR(parg16);
|
|
RETURN(ul);
|
|
}
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* WMM32waveOutGetVolume
|
|
*
|
|
* This function queries the current volume setting of a waveform output device.
|
|
*
|
|
\**********************************************************************/
|
|
ULONG FASTCALL WMM32waveOutGetVolume(PVDMFRAME pFrame)
|
|
{
|
|
register PWAVEOUTGETVOLUME16 parg16;
|
|
static FARPROC mmAPI = NULL;
|
|
ULONG ul;
|
|
LPDWORD lpdwVolume;
|
|
DWORD dwVolume;
|
|
|
|
GET_MULTIMEDIA_API( "waveOutGetVolume", mmAPI, MMSYSERR_NODRIVER );
|
|
|
|
GETARGPTR(pFrame, sizeof(WAVEOUTGETVOLUME16), parg16);
|
|
|
|
trace_wave(( "waveOutGetVolume( %x, %x )", INT32( parg16->f1 ),
|
|
DWORD32( parg16->f2 ) ));
|
|
|
|
ul = GETWORD16((*mmAPI)( INT32(parg16->f1), &dwVolume ));
|
|
if ( ul == MMSYSERR_NOERROR ) {
|
|
|
|
MMGETOPTPTR( parg16->f2, sizeof(DWORD), lpdwVolume);
|
|
|
|
if ( lpdwVolume ) {
|
|
STOREDWORD ( *lpdwVolume, dwVolume );
|
|
FLUSHVDMPTR( DWORD32(parg16->f2), sizeof(DWORD), lpdwVolume );
|
|
FREEVDMPTR ( lpdwVolume );
|
|
}
|
|
else {
|
|
ul = MMSYSERR_INVALPARAM;
|
|
}
|
|
}
|
|
trace_wave(( "-> %ld\n", ul ));
|
|
|
|
FREEARGPTR(parg16);
|
|
RETURN(ul);
|
|
}
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* WMM32waveOutSetVolume
|
|
*
|
|
* This function sets the volume of a waveform output device.
|
|
*
|
|
\**********************************************************************/
|
|
ULONG FASTCALL WMM32waveOutSetVolume(PVDMFRAME pFrame)
|
|
{
|
|
ULONG ul;
|
|
register PWAVEOUTSETVOLUME16 parg16;
|
|
static FARPROC mmAPI = NULL;
|
|
|
|
GET_MULTIMEDIA_API( "waveOutSetVolume", mmAPI, MMSYSERR_NODRIVER );
|
|
|
|
GETARGPTR(pFrame, sizeof(WAVEOUTSETVOLUME16), parg16);
|
|
|
|
trace_wave(( "waveOutSetVolume( %x, %x )", INT32( parg16->f1 ),
|
|
DWORD32( parg16->f2 ) ));
|
|
ul = GETWORD16((*mmAPI)( INT32(parg16->f1), DWORD32(parg16->f2) ));
|
|
trace_wave(( "-> %ld\n", ul ));
|
|
|
|
FREEARGPTR(parg16);
|
|
RETURN(ul);
|
|
}
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* WMM32waveOutGetPlaybackRate
|
|
*
|
|
* This function queries the current playback rate setting of a waveform output
|
|
* device.
|
|
*
|
|
\**********************************************************************/
|
|
ULONG FASTCALL WMM32waveOutGetPlaybackRate(PVDMFRAME pFrame)
|
|
{
|
|
register PWAVEOUTGETPLAYBACKRATE16 parg16;
|
|
static FARPROC mmAPI = NULL;
|
|
ULONG ul;
|
|
LPDWORD lpdwRate;
|
|
DWORD dwRate;
|
|
|
|
GET_MULTIMEDIA_API( "waveOutGetPlaybackRate", mmAPI, MMSYSERR_NODRIVER );
|
|
|
|
GETARGPTR(pFrame, sizeof(WAVEOUTGETPLAYBACKRATE16), parg16);
|
|
trace_wave(( "waveOutGetPlaybackRate( %x, %x )", WORD32( parg16->f1 ),
|
|
DWORD32( parg16->f2 ) ));
|
|
|
|
ul = GETWORD16((*mmAPI)( HWAVEOUT32(parg16->f1), &dwRate ));
|
|
if ( ul == MMSYSERR_NOERROR ) {
|
|
|
|
MMGETOPTPTR( parg16->f2, sizeof(DWORD), lpdwRate );
|
|
|
|
if ( lpdwRate ) {
|
|
|
|
STOREDWORD ( *lpdwRate, dwRate );
|
|
FLUSHVDMPTR( DWORD32(parg16->f2), sizeof(DWORD), lpdwRate );
|
|
FREEVDMPTR ( lpdwRate );
|
|
}
|
|
}
|
|
trace_wave(( "-> %ld\n", ul ));
|
|
|
|
FREEARGPTR(parg16);
|
|
RETURN(ul);
|
|
}
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* WMM32waveOutSetPlaybackRate
|
|
*
|
|
* This function sets the playback rate of a waveform output device.
|
|
*
|
|
\**********************************************************************/
|
|
ULONG FASTCALL WMM32waveOutSetPlaybackRate(PVDMFRAME pFrame)
|
|
{
|
|
ULONG ul;
|
|
register PWAVEOUTSETPLAYBACKRATE16 parg16;
|
|
static FARPROC mmAPI = NULL;
|
|
|
|
GET_MULTIMEDIA_API( "waveOutSetPlaybackRate", mmAPI, MMSYSERR_NODRIVER );
|
|
|
|
GETARGPTR(pFrame, sizeof(WAVEOUTSETPLAYBACKRATE16), parg16);
|
|
|
|
trace_wave(( "waveOutSetPlaybackRate( %x, %x )", WORD32( parg16->f1 ),
|
|
DWORD32( parg16->f2 ) ));
|
|
ul = GETWORD16((*mmAPI)( HWAVEOUT32(parg16->f1), DWORD32(parg16->f2) ));
|
|
trace_wave(( "-> %ld\n", ul ));
|
|
|
|
FREEARGPTR(parg16);
|
|
RETURN(ul);
|
|
}
|
|
|
|
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* WMM32waveOutBreakLoop
|
|
*
|
|
* This function breaks a loop on a given waveform output device and allows
|
|
* playback to continue with the next block in the driver list.
|
|
*
|
|
\**********************************************************************/
|
|
ULONG FASTCALL WMM32waveOutBreakLoop(PVDMFRAME pFrame)
|
|
{
|
|
ULONG ul;
|
|
register PWAVEOUTBREAKLOOP16 parg16;
|
|
static FARPROC mmAPI = NULL;
|
|
|
|
GET_MULTIMEDIA_API( "waveOutBreakLoop", mmAPI, MMSYSERR_NODRIVER );
|
|
|
|
GETARGPTR(pFrame, sizeof(WAVEOUTBREAKLOOP16), parg16);
|
|
|
|
trace_wave(( "waveOutBreakLoop( %x )", WORD32( parg16->f1 ) ));
|
|
ul = GETWORD16((*mmAPI)( HWAVEOUT32(parg16->f1) ));
|
|
trace_wave(( "-> %ld\n", ul ));
|
|
|
|
FREEARGPTR(parg16);
|
|
RETURN(ul);
|
|
}
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* WMM32waveOutGetID
|
|
*
|
|
* This function gets the device ID for a waveform output device.
|
|
*
|
|
\**********************************************************************/
|
|
ULONG FASTCALL WMM32waveOutGetID(PVDMFRAME pFrame)
|
|
{
|
|
register PWAVEOUTGETID16 parg16;
|
|
static FARPROC mmAPI = NULL;
|
|
ULONG ul;
|
|
UINT dwDeviceID32;
|
|
LPWORD lpwDeviceID16;
|
|
|
|
GET_MULTIMEDIA_API( "waveOutGetID", mmAPI, MMSYSERR_NODRIVER );
|
|
|
|
GETARGPTR(pFrame, sizeof(WAVEOUTGETID16), parg16);
|
|
|
|
trace_wave(( "waveOutGetID( %x, %x )", WORD32( parg16->f1 ),
|
|
DWORD32( parg16->f2 ) ));
|
|
|
|
ul = GETWORD16((*mmAPI)( HWAVEOUT32(parg16->f1), &dwDeviceID32 ));
|
|
|
|
/*
|
|
** Only copy the ID back to 16 bit space if the call was sucessful
|
|
**
|
|
*/
|
|
if ( ul == MMSYSERR_NOERROR ) {
|
|
|
|
MMGETOPTPTR( parg16->f2, sizeof(WORD), lpwDeviceID16 );
|
|
|
|
if ( lpwDeviceID16 ) {
|
|
STOREWORD ( *lpwDeviceID16, dwDeviceID32 );
|
|
FLUSHVDMPTR( DWORD32(parg16->f2), sizeof(WORD), lpwDeviceID16 );
|
|
FREEVDMPTR ( lpwDeviceID16 );
|
|
}
|
|
else {
|
|
ul = MMSYSERR_INVALPARAM;
|
|
}
|
|
}
|
|
|
|
trace_wave(( "-> %ld\n", ul ));
|
|
FREEARGPTR(parg16);
|
|
RETURN(ul);
|
|
}
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* WMM32waveOutMessage
|
|
*
|
|
* This function send a message to a waveform output device.
|
|
*
|
|
\**********************************************************************/
|
|
ULONG FASTCALL WMM32waveOutMessage(PVDMFRAME pFrame)
|
|
{
|
|
ULONG ul;
|
|
register PWAVEOUTMESSAGE3216 parg16;
|
|
static FARPROC mmAPI = NULL;
|
|
|
|
GET_MULTIMEDIA_API( "waveOutMessage", mmAPI, MMSYSERR_NODRIVER );
|
|
|
|
GETARGPTR(pFrame, sizeof(WAVEOUTMESSAGE16), parg16);
|
|
|
|
trace_wave(( "waveOutMessage( %x, %x, %x, %x )",
|
|
WORD32( parg16->f1 ), UINT32( parg16->f2 ),
|
|
DWORD32( parg16->f3 ), DWORD32( parg16->f4 ) ));
|
|
|
|
if ( (UINT32(parg16->f2) >= DRV_BUFFER_LOW)
|
|
&& (UINT32(parg16->f2) <= DRV_BUFFER_HIGH) ) {
|
|
|
|
LPDWORD lpdwParam1;
|
|
GETMISCPTR(parg16->f3, lpdwParam1);
|
|
|
|
ul = GETDWORD16((*mmAPI)( HWAVEOUT32(parg16->f1), UINT32(parg16->f2),
|
|
(DWORD)lpdwParam1, DWORD32(parg16->f4) ));
|
|
FREEMISCPTR(lpdwParam1);
|
|
|
|
} else {
|
|
ul = GETDWORD16((*mmAPI)( HWAVEOUT32(parg16->f1),
|
|
MAKELONG( WORD32(parg16->f2), 0xFFFF ),
|
|
DWORD32(parg16->f3), DWORD32(parg16->f4) ));
|
|
}
|
|
|
|
trace_wave(( "-> %ld\n", ul ));
|
|
|
|
FREEARGPTR(parg16);
|
|
RETURN(ul);
|
|
}
|
|
|
|
|
|
/* ---------------------------------------------------------------------
|
|
** WAVE Input API's
|
|
** ---------------------------------------------------------------------
|
|
*/
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* WMM32waveInGetNumDevs
|
|
*
|
|
* This function returns the number of waveform input devices.
|
|
*
|
|
\**********************************************************************/
|
|
ULONG FASTCALL WMM32waveInGetNumDevs(PVDMFRAME pFrame)
|
|
{
|
|
ULONG ul;
|
|
static FARPROC mmAPI = NULL;
|
|
|
|
GET_MULTIMEDIA_API( "waveInGetNumDevs", mmAPI, MMSYSERR_NODRIVER );
|
|
|
|
UNREFERENCED_PARAMETER(pFrame);
|
|
|
|
trace_wave(( "waveInGetNumDevs()" ));
|
|
ul = GETWORD16((*mmAPI)() );
|
|
trace_wave(( "-> %ld\n", ul ));
|
|
|
|
RETURN(ul);
|
|
}
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* WMM32waveInGetDevCaps
|
|
*
|
|
* This function queries a specified waveform input device to determine its
|
|
* capabilities.
|
|
*
|
|
\**********************************************************************/
|
|
ULONG FASTCALL WMM32waveInGetDevCaps(PVDMFRAME pFrame)
|
|
{
|
|
ULONG ul;
|
|
WAVEINCAPS waveincaps1;
|
|
register PWAVEINGETDEVCAPS16 parg16;
|
|
static FARPROC mmAPI = NULL;
|
|
|
|
GET_MULTIMEDIA_API( "waveInGetDevCapsA", mmAPI, MMSYSERR_NODRIVER );
|
|
|
|
GETARGPTR(pFrame, sizeof(WAVEINGETDEVCAPS16), parg16);
|
|
|
|
trace_wave(( "waveInGetDevCaps( %x, %x, %x )", WORD32( parg16->f1 ),
|
|
DWORD32( parg16->f2 ), UINT32( parg16->f3 ) ));
|
|
|
|
/*
|
|
** If the size parameter was zero return straight away. Note that this
|
|
** is not an error.
|
|
*/
|
|
if ( UINT32( parg16->f3 ) == 0 ) {
|
|
ul = MMSYSERR_NOERROR;
|
|
}
|
|
else {
|
|
|
|
ul = GETWORD16((*mmAPI)(INT32(parg16->f1), &waveincaps1,
|
|
sizeof(WAVEINCAPS) ) );
|
|
/*
|
|
** Don't update the 16 bit structure if the call failed
|
|
**
|
|
*/
|
|
if ( ul == MMSYSERR_NOERROR ) {
|
|
ul = PUTWAVEINCAPS16(parg16->f2, &waveincaps1, UINT32(parg16->f3));
|
|
}
|
|
}
|
|
trace_wave(( "-> %ld\n", ul ));
|
|
|
|
FREEARGPTR(parg16);
|
|
|
|
RETURN(ul);
|
|
}
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* WMM32waveInGetErrorText
|
|
*
|
|
* This function retrieves a textual description of the error identified by the
|
|
* specified error number.
|
|
*
|
|
\**********************************************************************/
|
|
ULONG FASTCALL WMM32waveInGetErrorText(PVDMFRAME pFrame)
|
|
{
|
|
ULONG ul = MMSYSERR_NOERROR;
|
|
PSZ pszText;
|
|
register PWAVEINGETERRORTEXT16 parg16;
|
|
static FARPROC mmAPI = NULL;
|
|
|
|
GET_MULTIMEDIA_API( "waveInGetErrorTextA", mmAPI, MMSYSERR_NODRIVER );
|
|
|
|
GETARGPTR(pFrame, sizeof(WAVEINGETERRORTEXT16), parg16);
|
|
|
|
trace_wave(( "waveInGetErrorText( %x, %x, %x )", UINT32( parg16->f1 ),
|
|
DWORD32( parg16->f2 ), UINT32( parg16->f3 ) ));
|
|
|
|
/*
|
|
** Test against a zero length string and a NULL pointer. If 0 is passed
|
|
** as the buffer length then the manual says we should return
|
|
** MMSYSERR_NOERR. MMGETOPTPTR only returns a pointer if parg16->f2 is
|
|
** not NULL.
|
|
*/
|
|
MMGETOPTPTR( parg16->f2, UINT32(parg16->f3), pszText );
|
|
if ( pszText != NULL ) {
|
|
|
|
ul = GETWORD16((*mmAPI)( UINT32(parg16->f1), pszText,
|
|
UINT32(parg16->f3) ));
|
|
|
|
FLUSHVDMPTR( DWORD32(parg16->f2), UINT32(parg16->f3), pszText);
|
|
FREEVDMPTR(pszText);
|
|
}
|
|
|
|
trace_wave(( "-> %ld\n", ul ));
|
|
|
|
FREEARGPTR(parg16);
|
|
RETURN(ul);
|
|
}
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* WMM32waveInOpen
|
|
*
|
|
* This function opens a specified waveform input device for recording.
|
|
*
|
|
* As of November 1992 we map the 16 bit Wave Format data directly to the
|
|
* the 32 bit side, no thunking of the parameters is performed.
|
|
*
|
|
*
|
|
\**********************************************************************/
|
|
ULONG FASTCALL WMM32waveInOpen(PVDMFRAME pFrame)
|
|
{
|
|
ULONG ul=0;
|
|
UINT uDevID;
|
|
PINSTANCEDATA pInstanceData = NULL;
|
|
DWORD dwFlags;
|
|
PWAVEFORMAT16 lpWaveformData;
|
|
LPHWAVEIN lphWaveIn; // pointer to handle in 16 bit app space
|
|
HWAVEIN Hand32; // 32bit handle
|
|
register PWAVEINOPEN16 parg16;
|
|
static FARPROC mmAPI = NULL;
|
|
|
|
GET_MULTIMEDIA_API( "waveInOpen", mmAPI, MMSYSERR_NODRIVER );
|
|
|
|
GETARGPTR(pFrame, sizeof(WAVEINOPEN16), parg16);
|
|
|
|
trace_wave(( "waveInOpen( %x, %x, %x, %x, %x, %x )",
|
|
DWORD32( parg16->f1 ), INT32 ( parg16->f2 ),
|
|
DWORD32( parg16->f3 ), DWORD32( parg16->f4 ),
|
|
DWORD32( parg16->f5 ), DWORD32( parg16->f6 ) ));
|
|
|
|
/*
|
|
** Get the device ID. We use INT32 here not UINT32 to make sure that
|
|
** negative values (such as WAVE_MAPPER (-1)) get thunked correctly.
|
|
*/
|
|
uDevID = (UINT)INT32(parg16->f2);
|
|
|
|
/*
|
|
** Get the flags to be used.
|
|
*/
|
|
dwFlags = DWORD32(parg16->f6);
|
|
|
|
/*
|
|
** Get a pointer to the WAVEFORMAT structure. Because the format of this
|
|
** structure is exactly the same in 32 and 16 bit land I will use
|
|
** GETMISCPTR to get a generic pointer to the data. The stuff being
|
|
** pointed to could be full of unaligned WORDs, but the 32 bit code
|
|
** would have to cope with this anyway.
|
|
*/
|
|
GETMISCPTR( DWORD32(parg16->f3), lpWaveformData );
|
|
if ( lpWaveformData == (PWAVEFORMAT16)NULL ) {
|
|
ul = (ULONG)MMSYSERR_INVALPARAM;
|
|
goto exit_function;
|
|
}
|
|
|
|
/*
|
|
** We don't need a callback routine when the WAVE_FORMAT_QUERY flag
|
|
** is specified.
|
|
*/
|
|
if ( !( dwFlags & WAVE_FORMAT_QUERY ) ) {
|
|
|
|
/*
|
|
** Map the 16 bit pointer is one was specified.
|
|
*/
|
|
MMGETOPTPTR( parg16->f1, sizeof(HWAVEIN), lphWaveIn );
|
|
if ( lphWaveIn == NULL ) {
|
|
|
|
ul = MMSYSERR_INVALPARAM;
|
|
}
|
|
|
|
/*
|
|
** Create InstanceData block to be used by our callback routine.
|
|
**
|
|
** NOTE: Although we malloc it here we don't free it.
|
|
** This is not a mistake - it must not be freed before the
|
|
** callback routine has used it - so it does the freeing.
|
|
**
|
|
** If the malloc fails we bomb down to the bottom,
|
|
** set ul to MMSYSERR_NOMEM and exit gracefully.
|
|
**
|
|
** We always have a callback functions. This is to ensure that
|
|
** the WAVEHDR structure keeps getting copied back from
|
|
** 32 bit space to 16 bit, as it contains flags which
|
|
** applications are liable to keep checking.
|
|
*/
|
|
else if ( pInstanceData = malloc_w(sizeof(INSTANCEDATA) ) ) {
|
|
|
|
DWORD dwNewFlags = CALLBACK_FUNCTION;
|
|
|
|
dprintf2(( "WM32waveInOpen: Allocated instance buffer at %8X",
|
|
pInstanceData ));
|
|
pInstanceData->dwCallback = DWORD32(parg16->f4);;
|
|
pInstanceData->dwCallbackInstance = DWORD32(parg16->f5);
|
|
pInstanceData->dwFlags = dwFlags;
|
|
|
|
dwNewFlags |= (dwFlags & WAVE_ALLOWSYNC);
|
|
|
|
ul = GETWORD16( (*mmAPI)( &Hand32, uDevID,
|
|
(LPWAVEFORMAT)lpWaveformData,
|
|
(DWORD)W32CommonDeviceOpen,
|
|
(DWORD)pInstanceData, dwNewFlags ) );
|
|
/*
|
|
** If the call returns success update the 16 bit handle,
|
|
** otherwise don't, and free the memory we malloc'd earlier, as
|
|
** the callback that would have freed it will never get callled.
|
|
*/
|
|
if ( ul == MMSYSERR_NOERROR ) {
|
|
|
|
HWAVEIN16 Hand16 = GETHWAVEIN16(Hand32);
|
|
|
|
trace_wave(( "Handle -> %x", Hand16 ));
|
|
STOREWORD ( *lphWaveIn, Hand16 );
|
|
FLUSHVDMPTR( DWORD32(parg16->f1), sizeof(HWAVEIN), lphWaveIn );
|
|
}
|
|
else {
|
|
|
|
free_w(pInstanceData);
|
|
}
|
|
|
|
/*
|
|
** Regardless of sucess or failure we need to free the pointer
|
|
** to the 16 bit WaveIn handle.
|
|
*/
|
|
FREEVDMPTR ( lphWaveIn );
|
|
}
|
|
else {
|
|
ul = (ULONG)MMSYSERR_NOMEM;
|
|
}
|
|
}
|
|
else {
|
|
|
|
ul = GETWORD16( (*mmAPI)( NULL, uDevID, (LPWAVEFORMAT)lpWaveformData,
|
|
DWORD32(parg16->f4),
|
|
DWORD32(parg16->f5), dwFlags) );
|
|
}
|
|
|
|
/*
|
|
** Regardless of sucess or failure we need to free the pointer to the
|
|
** 16 bit WaveFormatData.
|
|
*/
|
|
FREEMISCPTR( lpWaveformData );
|
|
|
|
|
|
exit_function:
|
|
trace_wave(( "-> %ld\n", ul ));
|
|
FREEARGPTR(parg16);
|
|
RETURN(ul);
|
|
}
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* WMM32waveInClose
|
|
*
|
|
* This function closes the specified waveform input device.
|
|
*
|
|
\**********************************************************************/
|
|
ULONG FASTCALL WMM32waveInClose(PVDMFRAME pFrame)
|
|
{
|
|
ULONG ul;
|
|
register PWAVEINCLOSE16 parg16;
|
|
static FARPROC mmAPI = NULL;
|
|
|
|
GET_MULTIMEDIA_API( "waveInClose", mmAPI, MMSYSERR_NODRIVER );
|
|
|
|
GETARGPTR(pFrame, sizeof(WAVEINCLOSE16), parg16);
|
|
|
|
trace_wave(( "waveInClose( %x )", WORD32( parg16->f1 ) ));
|
|
ul = GETWORD16((*mmAPI)( HWAVEIN32(parg16->f1) ));
|
|
trace_wave(( "-> %ld\n", ul ));
|
|
|
|
FREEARGPTR(parg16);
|
|
RETURN(ul);
|
|
}
|
|
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* WMM32waveInPrepareHeader
|
|
*
|
|
* This function prepares the specified waveform header.
|
|
*
|
|
\**********************************************************************/
|
|
ULONG FASTCALL WMM32waveInPrepareHeader(PVDMFRAME pFrame)
|
|
{
|
|
register PWAVEINPREPAREHEADER3216 parg16;
|
|
static FARPROC mmAPI = NULL;
|
|
ULONG ul;
|
|
WAVEHDR wavehdr;
|
|
|
|
|
|
GET_MULTIMEDIA_API( "waveInPrepareHeader", mmAPI, MMSYSERR_NODRIVER );
|
|
GETARGPTR(pFrame, sizeof(WAVEINPREPAREHEADER3216), parg16);
|
|
trace_wave(( "waveInPrepareHeader( %x %x %x)", WORD32( parg16->f1 ),
|
|
DWORD32( parg16->f2 ), WORD32( parg16->f3 ) ));
|
|
|
|
GETWAVEHDR16(parg16->f2, &wavehdr);
|
|
|
|
ul = GETWORD16((*mmAPI)( HWAVEIN32(parg16->f1),
|
|
&wavehdr, WORD32(parg16->f3) ) );
|
|
/*
|
|
** Only update the 16 bit structure if the call returns success
|
|
**
|
|
*/
|
|
if ( !ul ) {
|
|
PUTWAVEHDR16(parg16->f2, &wavehdr);
|
|
}
|
|
|
|
trace_wave(( "-> %ld\n", ul ));
|
|
FREEARGPTR(parg16);
|
|
RETURN(ul);
|
|
}
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* WMM32waveInUnprepareHeader
|
|
*
|
|
* This function prepares the specified waveform header.
|
|
* This function cleans up the preparation performed by waveInPrepareHeader.
|
|
* The function must be called after the device driver has finished with a
|
|
* data block. You must call this function before freeing the data buffer.
|
|
*
|
|
\**********************************************************************/
|
|
ULONG FASTCALL WMM32waveInUnprepareHeader(PVDMFRAME pFrame)
|
|
{
|
|
register PWAVEINUNPREPAREHEADER3216 parg16;
|
|
static FARPROC mmAPI = NULL;
|
|
ULONG ul;
|
|
WAVEHDR wavehdr;
|
|
|
|
GET_MULTIMEDIA_API( "waveInUnprepareHeader", mmAPI, MMSYSERR_NODRIVER );
|
|
GETARGPTR(pFrame, sizeof(WAVEINUNPREPAREHEADER3216), parg16);
|
|
trace_wave(( "waveInUnprepareHeader( %x %x %x)", WORD32( parg16->f1 ),
|
|
DWORD32( parg16->f2 ), WORD32( parg16->f3 ) ));
|
|
|
|
GETWAVEHDR16(parg16->f2, &wavehdr);
|
|
|
|
ul = GETWORD16((*mmAPI)( HWAVEIN32(parg16->f1),
|
|
&wavehdr, WORD32(parg16->f3) ) );
|
|
/*
|
|
** Only update the 16 bit structure if the call returns success
|
|
*/
|
|
if (!ul) {
|
|
PUTWAVEHDR16(parg16->f2, &wavehdr);
|
|
}
|
|
|
|
trace_wave(( "-> %ld\n", ul ));
|
|
FREEARGPTR(parg16);
|
|
RETURN(ul);
|
|
}
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* WMM32waveInAddBuffer
|
|
*
|
|
* This function sends an input buffer to a waveform input device.
|
|
* When the buffer is filled it is sent back to the application.
|
|
*
|
|
\**********************************************************************/
|
|
ULONG FASTCALL WMM32waveInAddBuffer(PVDMFRAME pFrame)
|
|
{
|
|
ULONG ul;
|
|
PWAVEHDR32 pWavehdr32;
|
|
register PWAVEINADDBUFFER16 parg16;
|
|
static FARPROC mmAPI = NULL;
|
|
|
|
GET_MULTIMEDIA_API( "waveInAddBuffer", mmAPI, MMSYSERR_NODRIVER );
|
|
|
|
GETARGPTR(pFrame, sizeof(WAVEINADDBUFFER16), parg16);
|
|
|
|
trace_wave(( "waveInAddBuffer( %x, %x, %x)", WORD32( parg16->f1 ),
|
|
DWORD32( parg16->f2 ), UINT32( parg16->f3 ) ));
|
|
|
|
/*
|
|
** If the given size of the WAVEHDR structure is too small
|
|
** or the lphdr is invalid return an error
|
|
**
|
|
*/
|
|
if ( UINT32(parg16->f3) < sizeof(WAVEHDR16)
|
|
|| HIWORD( DWORD32(parg16->f2) ) == 0 ) {
|
|
|
|
ul = (ULONG)MMSYSERR_INVALPARAM;
|
|
}
|
|
else {
|
|
if (pWavehdr32 = malloc_w(sizeof(WAVEHDR32) ) ) {
|
|
|
|
PWAVEHDR lpwhdr; /* used to simplify ptr stuff later on */
|
|
#if DBG
|
|
AllocWaveCount++;
|
|
dprintf2(( "W>> %8X (%d)", pWavehdr32, AllocWaveCount ));
|
|
#endif
|
|
|
|
/* Copy across the wave header stuff. Note that lpwhdr (a
|
|
** 32 bit ptr to a 32 bit wave header) is used to make the
|
|
** pointer stuff a bit less hairy.
|
|
**
|
|
** pWavehdr32->Wavehdr is a 32 bit wave header
|
|
** pWavehdr32->pWavehdr16 is a 16 bit ptr to a 16 bit wave header
|
|
** pWavehdr32->pWavehdr32 is a 32 bit ptr to a 16 bit wave header
|
|
*/
|
|
lpwhdr = &(pWavehdr32->Wavehdr);
|
|
pWavehdr32->pWavehdr16 = (PWAVEHDR16)DWORD32(parg16->f2);
|
|
pWavehdr32->pWavehdr32 = GETWAVEHDR16(DWORD32(parg16->f2), lpwhdr);
|
|
|
|
/*
|
|
** GETWAVEHDR16 can return NULL, in which case we should set
|
|
** lpwhdr to NULL too and call waveInAddBuffer only to get the
|
|
** correct error code.
|
|
*/
|
|
if ( pWavehdr32->pWavehdr32 == NULL ) {
|
|
lpwhdr = NULL;
|
|
}
|
|
|
|
ul = GETWORD16( (*mmAPI)( HWAVEIN32(parg16->f1),
|
|
lpwhdr, UINT32(parg16->f3) ) );
|
|
/*
|
|
** If the call fails we need to free the memory we malloc'd
|
|
** above, as the callback that would have freed it will never
|
|
** get called.
|
|
**
|
|
*/
|
|
if ( ul == MMSYSERR_NOERROR ) {
|
|
|
|
/*
|
|
** Make sure we reflect any changes that waveInAddBuffer did
|
|
** to the WAVEHDR back to 16 bit land.
|
|
**
|
|
** This is important because some apps (waveedit) poll the
|
|
** WHDR_DONE bit !!
|
|
*/
|
|
COPY_WAVEINHDR16_FLAGS( pWavehdr32->pWavehdr32,
|
|
pWavehdr32->Wavehdr );
|
|
}
|
|
else {
|
|
#if DBG
|
|
AllocWaveCount--;
|
|
dprintf2(( "W<< \t%8X (%d)", pWavehdr32,
|
|
AllocWaveCount ));
|
|
#endif
|
|
free_w( pWavehdr32 );
|
|
}
|
|
}
|
|
else {
|
|
ul = (ULONG)MMSYSERR_NOMEM;
|
|
}
|
|
}
|
|
trace_wave(( "-> %ld\n", ul ));
|
|
|
|
FREEARGPTR(parg16);
|
|
RETURN(ul);
|
|
}
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* WMM32waveInStart
|
|
*
|
|
* This function starts input on the specified waveform input device.
|
|
*
|
|
\**********************************************************************/
|
|
ULONG FASTCALL WMM32waveInStart(PVDMFRAME pFrame)
|
|
{
|
|
ULONG ul;
|
|
register PWAVEINSTART16 parg16;
|
|
static FARPROC mmAPI = NULL;
|
|
|
|
GET_MULTIMEDIA_API( "waveInStart", mmAPI, MMSYSERR_NODRIVER );
|
|
|
|
GETARGPTR(pFrame, sizeof(WAVEINSTART16), parg16);
|
|
|
|
trace_wave(( "waveInStart( %x )", WORD32( parg16->f1 ) ));
|
|
ul = GETWORD16((*mmAPI)( HWAVEIN32(parg16->f1) ));
|
|
trace_wave(( "-> %ld\n", ul ));
|
|
|
|
FREEARGPTR(parg16);
|
|
RETURN(ul);
|
|
}
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* WMM32waveInStop
|
|
*
|
|
* This function stops waveform input.
|
|
*
|
|
\**********************************************************************/
|
|
ULONG FASTCALL WMM32waveInStop(PVDMFRAME pFrame)
|
|
{
|
|
ULONG ul;
|
|
register PWAVEINSTOP16 parg16;
|
|
static FARPROC mmAPI = NULL;
|
|
|
|
GET_MULTIMEDIA_API( "waveInStop", mmAPI, MMSYSERR_NODRIVER );
|
|
|
|
GETARGPTR(pFrame, sizeof(WAVEINSTOP16), parg16);
|
|
|
|
trace_wave(( "waveInStop( %x )", WORD32( parg16->f1 ) ));
|
|
ul = GETWORD16((*mmAPI)( HWAVEIN32(parg16->f1) ));
|
|
trace_wave(( "-> %ld\n", ul ));
|
|
|
|
FREEARGPTR(parg16);
|
|
RETURN(ul);
|
|
}
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* WMM32waveInReset
|
|
*
|
|
* This function stops input on a given waveform input device and resets the
|
|
* current position to 0. All pending buffers are marked as done and returned
|
|
* to the application.
|
|
*
|
|
\**********************************************************************/
|
|
ULONG FASTCALL WMM32waveInReset(PVDMFRAME pFrame)
|
|
{
|
|
ULONG ul;
|
|
register PWAVEINRESET16 parg16;
|
|
static FARPROC mmAPI = NULL;
|
|
|
|
GET_MULTIMEDIA_API( "waveInReset", mmAPI, MMSYSERR_NODRIVER );
|
|
|
|
GETARGPTR(pFrame, sizeof(WAVEINRESET16), parg16);
|
|
|
|
trace_wave(( "waveInReset( %x )", WORD32( parg16->f1 ) ));
|
|
ul = GETWORD16((*mmAPI)( HWAVEIN32(parg16->f1) ));
|
|
trace_wave(( "-> %ld\n", ul ));
|
|
|
|
FREEARGPTR(parg16);
|
|
RETURN(ul);
|
|
}
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* WMM32waveInGetPosition
|
|
*
|
|
* This function retrieves the current input position of the specified waveform
|
|
* input device.
|
|
*
|
|
\**********************************************************************/
|
|
ULONG FASTCALL WMM32waveInGetPosition(PVDMFRAME pFrame)
|
|
{
|
|
register PWAVEINGETPOSITION16 parg16;
|
|
MMTIME mmtime;
|
|
ULONG ul = MMSYSERR_INVALPARAM;
|
|
static FARPROC mmAPI = NULL;
|
|
|
|
GET_MULTIMEDIA_API( "waveInGetPosition", mmAPI, MMSYSERR_NODRIVER );
|
|
|
|
GETARGPTR(pFrame, sizeof(WAVEINGETPOSITION16), parg16);
|
|
|
|
trace_wave(( "waveInGetPosition( %x, %x, %x )", WORD32( parg16->f1 ),
|
|
DWORD32( parg16->f2 ), UINT32( parg16->f3 ) ));
|
|
|
|
/*
|
|
** If the given size of the MMTIME structure is too small return an error
|
|
**
|
|
** There is a problem here on MIPS. For some reason the MIPS
|
|
** compiler thinks a MMTIME16 structure is 10 bytes big. We
|
|
** have a pragma in wowmmed.h to align this structure on byte
|
|
** boundaries therefore I guess this is a compiler bug!
|
|
**
|
|
** If the input structure is not large enough we return immediately
|
|
*/
|
|
#ifdef MIPS_COMPILER_PACKING_BUG
|
|
if ( UINT32(parg16->f3) >= 8 ) {
|
|
#else
|
|
if ( UINT32(parg16->f3) >= sizeof(MMTIME16) ) {
|
|
#endif
|
|
|
|
ul = GETMMTIME16( parg16->f2, &mmtime );
|
|
if ( ul == MMSYSERR_NOERROR ) {
|
|
|
|
ul = GETWORD16((*mmAPI)( HWAVEIN32(parg16->f1),
|
|
&mmtime, sizeof(MMTIME) ));
|
|
/*
|
|
** Only update the 16 bit structure if the call returns success
|
|
**
|
|
*/
|
|
if ( ul == MMSYSERR_NOERROR ) {
|
|
ul = PUTMMTIME16( parg16->f2, &mmtime );
|
|
}
|
|
}
|
|
}
|
|
trace_wave(( "-> %ld\n", ul ));
|
|
|
|
FREEARGPTR(parg16);
|
|
RETURN(ul);
|
|
}
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* WMM32waveInGetID
|
|
*
|
|
* This function gets the device ID for a waveform input device.
|
|
*
|
|
\**********************************************************************/
|
|
ULONG FASTCALL WMM32waveInGetID(PVDMFRAME pFrame)
|
|
{
|
|
register PWAVEINGETID16 parg16;
|
|
ULONG ul;
|
|
UINT dwDeviceID32;
|
|
LPWORD lpwDeviceID16;
|
|
static FARPROC mmAPI = NULL;
|
|
|
|
GET_MULTIMEDIA_API( "waveInGetID", mmAPI, MMSYSERR_NODRIVER );
|
|
|
|
GETARGPTR(pFrame, sizeof(WAVEINGETID16), parg16);
|
|
trace_wave(( "waveInGetID( %x, %x )", WORD32( parg16->f1 ),
|
|
DWORD32( parg16->f2 ) ));
|
|
|
|
ul = GETWORD16((*mmAPI)( HWAVEIN32(parg16->f1), &dwDeviceID32 ));
|
|
|
|
/*
|
|
** Only copy the ID back to 16 bit space if the call was sucessful
|
|
**
|
|
*/
|
|
if ( ul == MMSYSERR_NOERROR ) {
|
|
|
|
MMGETOPTPTR( parg16->f2, sizeof(WORD), lpwDeviceID16 );
|
|
|
|
if ( lpwDeviceID16 ) {
|
|
STOREWORD ( *lpwDeviceID16, dwDeviceID32 );
|
|
FLUSHVDMPTR( DWORD32(parg16->f2), sizeof(WORD), lpwDeviceID16 );
|
|
FREEVDMPTR ( lpwDeviceID16 );
|
|
}
|
|
else {
|
|
ul = MMSYSERR_INVALPARAM;
|
|
}
|
|
}
|
|
trace_wave(( "-> %ld\n", ul ));
|
|
|
|
FREEARGPTR(parg16);
|
|
RETURN(ul);
|
|
}
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* WMM32waveInMessage
|
|
*
|
|
* This function sends a message to a waveform input device.
|
|
*
|
|
\**********************************************************************/
|
|
ULONG FASTCALL WMM32waveInMessage(PVDMFRAME pFrame)
|
|
{
|
|
ULONG ul;
|
|
register PWAVEINMESSAGE3216 parg16;
|
|
static FARPROC mmAPI = NULL;
|
|
|
|
GET_MULTIMEDIA_API( "waveInMessage", mmAPI, MMSYSERR_NODRIVER );
|
|
|
|
GETARGPTR(pFrame, sizeof(WAVEINMESSAGE16), parg16);
|
|
|
|
|
|
trace_wave(( "waveInMessage( %x, %x, %x, %x )", WORD32( parg16->f1 ),
|
|
UINT32( parg16->f2 ), DWORD32( parg16->f3 ),
|
|
DWORD32( parg16->f4 ) ));
|
|
|
|
if ( (UINT32(parg16->f2) >= DRV_BUFFER_LOW)
|
|
&& (UINT32(parg16->f2) <= DRV_BUFFER_HIGH) ) {
|
|
|
|
LPDWORD lpdwParam1;
|
|
GETMISCPTR(parg16->f3, lpdwParam1);
|
|
|
|
ul = GETDWORD16((*mmAPI)( HWAVEIN32(parg16->f1), UINT32(parg16->f2),
|
|
(DWORD)lpdwParam1, DWORD32(parg16->f4) ));
|
|
FREEMISCPTR(lpdwParam1);
|
|
|
|
} else {
|
|
ul = GETDWORD16((*mmAPI)( HWAVEIN32(parg16->f1),
|
|
MAKELONG( WORD32(parg16->f2), 0xFFFF ),
|
|
DWORD32(parg16->f3), DWORD32(parg16->f4) ));
|
|
}
|
|
trace_wave(( "-> %ld\n", ul ));
|
|
|
|
FREEARGPTR(parg16);
|
|
RETURN(ul);
|
|
}
|
|
|
|
/**********************************************************************\
|
|
*
|
|
* W32CommonDeviceOpen
|
|
*
|
|
* This routine is the callback which is ALWAYS called by wave and midi
|
|
* functions. This is done to ensure that the XXXXHDR structure keeps
|
|
* getting copied back from 32 bit space to 16 bit, as it contains flags
|
|
* which the application is liable to keep checking.
|
|
*
|
|
* The way this whole business works is that the wave/midi data stays in 16
|
|
* bit space, but the XXXXHDR is copied to the 32 bit side, with the
|
|
* address of the data thunked accordingly so that Robin's device driver
|
|
* can still get at the data but we don't have the performance penalty of
|
|
* copying it back and forth all the time, not least because it is liable
|
|
* to be rather large...
|
|
*
|
|
* It also handles the tidying up of memory which is reserved to store
|
|
* the XXXXHDR, and the instance data (HWND/Callback address; instance
|
|
* data; flags) which the xxxxOpen calls pass to this routine, enabling
|
|
* it to forward messages or call callback as required.
|
|
*
|
|
* This routine handles all the messages that get sent from Robin's
|
|
* driver, and in fact thunks them back to the correct 16 bit form. In
|
|
* theory there should be no MM_ format messages from the 16 bit side, so
|
|
* I can zap 'em out of WMSG16. However the 32 bit side should thunk the
|
|
* mesages correctly and forward them to the 16 bit side and thence to
|
|
* the app.
|
|
*
|
|
* However... I discover that somewhere in the system the wParam Msg
|
|
* parameter (which is 32 bits in Win32 and 16 bits in Win16) is having
|
|
* the top 16 bits trashed (zeroed actually). As I pass a 32 bit handle
|
|
* in it, to be thunked in WMDISP32 back to a 16 bit handle, the loss of
|
|
* the top 16 bits is not conducive to correct thunking. Soooo, no more
|
|
* thunking in WMDISP32 - I do it all here and Post the correct 16 bit
|
|
* message.
|
|
*
|
|
* Hence WMTBL32 (the 32 bit message switch table) contains the
|
|
* NoThunking entry for all the MM_ messages - I'll do 'em myself thank
|
|
* you.
|
|
*
|
|
*
|
|
* For the MM_WIM_DATA and MM_WOM_DONE message dwParam1 points to the
|
|
* following data struture.
|
|
*
|
|
* P32HDR is a 32 bit pointer to the original 16 bit header
|
|
* P16HDR is a 16 bit far pointer to the original 16 bit header
|
|
*
|
|
* If we need to refernece the original header we must do via the
|
|
* P32HDR pointer.
|
|
*
|
|
* +---------+
|
|
* | P32HDR +----->+---------+
|
|
* +---------+ | 16 bit |
|
|
* | P16HDR +----->| | This is the original
|
|
* dwParam1 ----->+---------+ | Wave | wave header passed to
|
|
* | 32 bit | | Header | us by the Win 16 app.
|
|
* This is the 32 | | | |
|
|
* bit wave | Wave | +---------+
|
|
* header that we | Header |
|
|
* thunked at | |
|
|
* earlier. +---------+
|
|
*
|
|
*
|
|
* We must ensure that the 32 bit structure is completely hidden from the
|
|
* 16 bit application, ie. the 16 bit app only see's the wave header that it
|
|
* passed to us earlier.
|
|
*
|
|
*
|
|
* NOTE: dwParam2 is junk
|
|
*
|
|
*
|
|
\**********************************************************************/
|
|
VOID W32CommonDeviceOpen( HANDLE handle, UINT uMsg, DWORD dwInstance,
|
|
DWORD dwParam1, DWORD dwParam2 )
|
|
{
|
|
PWAVEHDR32 pWavehdr32;
|
|
PMIDIHDR32 pMidihdr32;
|
|
PINSTANCEDATA pInstanceData;
|
|
WORD Handle;
|
|
|
|
|
|
switch (uMsg) {
|
|
|
|
/* ------------------------------------------------------------
|
|
** MIDI INPUT MESSAGES
|
|
** ------------------------------------------------------------
|
|
*/
|
|
|
|
case MM_MIM_LONGDATA:
|
|
/*
|
|
** This message is sent to a window when an input buffer has been
|
|
** filled with MIDI system-exclusive data and is being returned to
|
|
** the application.
|
|
*/
|
|
|
|
case MM_MIM_LONGERROR:
|
|
/*
|
|
** This message is sent to a window when an invalid MIDI
|
|
** system-exclusive message is received.
|
|
*/
|
|
pMidihdr32 = (PMIDIHDR32)( (PBYTE)dwParam1 - (sizeof(PMIDIHDR16) * 2) );
|
|
WOW32ASSERT( pMidihdr32 );
|
|
COPY_MIDIINHDR16_FLAGS( pMidihdr32->pMidihdr32, pMidihdr32->Midihdr );
|
|
dwParam1 = (DWORD)pMidihdr32->pMidihdr16;
|
|
|
|
|
|
case MM_MIM_DATA:
|
|
/*
|
|
** This message is sent to a window when a MIDI message is
|
|
** received by a MIDI input device.
|
|
*/
|
|
|
|
case MM_MIM_ERROR:
|
|
/*
|
|
** This message is sent to a window when an invalid MIDI message
|
|
** is received.
|
|
*/
|
|
|
|
case MM_MIM_OPEN:
|
|
/*
|
|
** This message is sent to a window when a MIDI input device is opened.
|
|
** We process this message the same way as MM_MIM_CLOSE (see below)
|
|
*/
|
|
|
|
case MM_MIM_CLOSE:
|
|
/*
|
|
** This message is sent to a window when a MIDI input device is
|
|
** closed. The device handle is no longer valid once this message
|
|
** has been sent.
|
|
*/
|
|
Handle = GETHMIDIIN16(handle);
|
|
break;
|
|
|
|
|
|
|
|
/* ------------------------------------------------------------
|
|
** MIDI OUTPUT MESSAGES
|
|
** ------------------------------------------------------------
|
|
*/
|
|
|
|
case MM_MOM_DONE:
|
|
/*
|
|
** This message is sent to a window when the specified
|
|
** system-exclusive buffer has been played and is being returned to
|
|
** the application.
|
|
*/
|
|
pMidihdr32 = (PMIDIHDR32)( (PBYTE)dwParam1 - (sizeof(PMIDIHDR16) * 2) );
|
|
WOW32ASSERT( pMidihdr32 );
|
|
COPY_MIDIOUTHDR16_FLAGS( pMidihdr32->pMidihdr32, pMidihdr32->Midihdr );
|
|
dwParam1 = (DWORD)pMidihdr32->pMidihdr16;
|
|
|
|
|
|
case MM_MOM_OPEN:
|
|
/*
|
|
** This message is sent to a window when a MIDI output device is opened.
|
|
** We process this message the same way as MM_MOM_CLOSE (see below)
|
|
*/
|
|
|
|
case MM_MOM_CLOSE:
|
|
/*
|
|
** This message is sent to a window when a MIDI output device is
|
|
** closed. The device handle is no longer valid once this message
|
|
** has been sent.
|
|
*/
|
|
Handle = GETHMIDIOUT16(handle);
|
|
break;
|
|
|
|
|
|
|
|
/* ------------------------------------------------------------
|
|
** WAVE INPUT MESSAGES
|
|
** ------------------------------------------------------------
|
|
*/
|
|
|
|
case MM_WIM_DATA:
|
|
/*
|
|
** This message is sent to a window when waveform data is present
|
|
** in the input buffer and the buffer is being returned to the
|
|
** application. The message can be sent either when the buffer
|
|
** is full, or after the waveInReset function is called.
|
|
*/
|
|
pWavehdr32 = (PWAVEHDR32)( (PBYTE)dwParam1 - (sizeof(PWAVEHDR16) * 2));
|
|
WOW32ASSERT( pWavehdr32 );
|
|
COPY_WAVEINHDR16_FLAGS( pWavehdr32->pWavehdr32, pWavehdr32->Wavehdr );
|
|
dwParam1 = (DWORD)pWavehdr32->pWavehdr16;
|
|
|
|
case MM_WIM_OPEN:
|
|
/*
|
|
** This message is sent to a window when a waveform input
|
|
** device is opened.
|
|
**
|
|
** We process this message the same way as MM_WIM_CLOSE (see below)
|
|
*/
|
|
|
|
case MM_WIM_CLOSE:
|
|
/*
|
|
** This message is sent to a window when a waveform input device is
|
|
** closed. The device handle is no longer valid once the message has
|
|
** been sent.
|
|
*/
|
|
Handle = GETHWAVEIN16(handle);
|
|
break;
|
|
|
|
|
|
|
|
/* ------------------------------------------------------------
|
|
** WAVE OUTPUT MESSAGES
|
|
** ------------------------------------------------------------
|
|
*/
|
|
|
|
case MM_WOM_DONE:
|
|
/*
|
|
** This message is sent to a window when the specified output
|
|
** buffer is being returned to the application. Buffers are returned
|
|
** to the application when they have been played, or as the result of
|
|
** a call to waveOutReset.
|
|
*/
|
|
pWavehdr32 = (PWAVEHDR32)( (PBYTE)dwParam1 - (sizeof(PWAVEHDR16) * 2));
|
|
WOW32ASSERT( pWavehdr32 );
|
|
COPY_WAVEOUTHDR16_FLAGS( pWavehdr32->pWavehdr32, pWavehdr32->Wavehdr );
|
|
dwParam1 = (DWORD)pWavehdr32->pWavehdr16;
|
|
|
|
case MM_WOM_OPEN:
|
|
/*
|
|
** This message is sent to a window when a waveform output device
|
|
** is opened.
|
|
**
|
|
** We process this message the same way as MM_WOM_CLOSE (see below)
|
|
*/
|
|
|
|
case MM_WOM_CLOSE:
|
|
/*
|
|
** This message is sent to a window when a waveform output device
|
|
** is closed. The device handle is no longer valid once the
|
|
** message has been sent.
|
|
*/
|
|
Handle = GETHWAVEOUT16(handle);
|
|
break;
|
|
|
|
#if DBG
|
|
default:
|
|
dprintf(( "Unknown message received in CallBack function " ));
|
|
dprintf(( "best call StephenE or MikeTri" ));
|
|
return;
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
** Now make the CallBack, or PostMessage call depending
|
|
** on the flags passed to original (wave|midi)(In|Out)Open call.
|
|
*/
|
|
pInstanceData = (PINSTANCEDATA)dwInstance;
|
|
WOW32ASSERT( pInstanceData );
|
|
|
|
switch (pInstanceData->dwFlags & CALLBACK_TYPEMASK) {
|
|
|
|
case CALLBACK_WINDOW:
|
|
dprintf2(( "WINDOW callback identified" ));
|
|
PostMessage( HWND32( LOWORD(pInstanceData->dwCallback) ),
|
|
uMsg, Handle, dwParam1 );
|
|
break;
|
|
|
|
|
|
case CALLBACK_TASK:
|
|
case CALLBACK_FUNCTION: {
|
|
|
|
DWORD dwFlags;
|
|
|
|
if ( (pInstanceData->dwFlags & CALLBACK_TYPEMASK) == CALLBACK_TASK ) {
|
|
dprintf2(( "TASK callback identified" ));
|
|
dwFlags = DCB_TASK;
|
|
}
|
|
else {
|
|
dprintf2(( "FUNCTION callback identified" ));
|
|
dwFlags = DCB_FUNCTION;
|
|
}
|
|
|
|
WOW32DriverCallback( pInstanceData->dwCallback,
|
|
dwFlags,
|
|
Handle,
|
|
LOWORD( uMsg ),
|
|
pInstanceData->dwCallbackInstance,
|
|
dwParam1,
|
|
dwParam2 );
|
|
|
|
}
|
|
break;
|
|
}
|
|
|
|
/*
|
|
** Now, free up any storage that was allocated during the waveOutOpen
|
|
** and waveInOpen. This should only be freed during the MM_WOM_CLOSE or
|
|
** MM_WIM_CLOSE message.
|
|
**
|
|
** Also, free up any storage that was allocated during the waveOutWrite
|
|
** and waveInAddBuffer call. This should only be freed during the
|
|
** MM_WOM_DONE or MM_WIM_DATA message.
|
|
*/
|
|
switch (uMsg) {
|
|
|
|
case MM_MIM_CLOSE:
|
|
case MM_MOM_CLOSE:
|
|
case MM_WIM_CLOSE:
|
|
case MM_WOM_CLOSE:
|
|
dprintf2(( "W32CommonDeviceOpen: Freeing device open buffer at %X",
|
|
pInstanceData ));
|
|
dprintf2(( "Alloc Midi count = %d", AllocMidiCount ));
|
|
dprintf2(( "Alloc Wave count = %d", AllocWaveCount ));
|
|
free_w( pInstanceData );
|
|
FREEHWAVEIN16( Handle );
|
|
break;
|
|
|
|
case MM_WIM_DATA:
|
|
case MM_WOM_DONE:
|
|
# if DBG
|
|
AllocWaveCount--;
|
|
dprintf2(( "W<< \t%8X (%d)", pWavehdr32, AllocWaveCount ));
|
|
# endif
|
|
free_w( pWavehdr32 );
|
|
break;
|
|
|
|
case MM_MIM_LONGDATA:
|
|
case MM_MIM_LONGERROR:
|
|
case MM_MOM_DONE:
|
|
# if DBG
|
|
AllocMidiCount--;
|
|
dprintf2(( "M<< \t%8X (%d)", pMidihdr32, AllocMidiCount ));
|
|
# endif
|
|
free_w( pMidihdr32 );
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|