Source file: /~heha/argon/multimed.zip/SNDBLST/WAVEIN.C

/****************************************************************************
 *
 *   wavein.c
 *
 *   Copyright (c) 1991-1992 Microsoft Corporation.  All Rights Reserved.
 *
 ***************************************************************************/

#include <windows.h>
#include <mmsystem.h>
#include <mmddk.h>
#include "sndblst.h"

/*****************************************************************************

    internal function prototypes

 ****************************************************************************/ 

static void NEAR PASCAL widFreeQ(void);
static void NEAR PASCAL widGetDevCaps(LPBYTE lpCaps, WORD wSize);

/****************************************************************************
 * @doc INTERNAL
 *
 * @api void | widFreeQ | Free all buffers.
 *
 * @rdesc There is no return value.
 ***************************************************************************/ 
static void NEAR PASCAL widFreeQ(void)
{
LPWAVEHDR lpH, lpN;

    lpH = glpWIQueue;              /* point to top of the queue */
    glpWIQueue = NULL;             /* mark the queue as empty */

    while (lpH) {
        lpN = lpH->lpNext;
        widBlockFinished(lpH);
        lpH = lpN;
    }
}

/****************************************************************************
 * @doc INTERNAL
 *
 * @api void | widAddBuffer | Adds a buffer to our input queue.
 *
 * @rdesc The return value is an MMSYS error code (0L if success).
 ***************************************************************************/ 
static DWORD NEAR PASCAL widAddBuffer( LPWAVEHDR lpwh )
{
LPWAVEHDR   lpN;

    /* check if it's been prepared */
    if (!(lpwh->dwFlags & WHDR_PREPARED))
        return WAVERR_UNPREPARED;

    /* check if it's in our queue already */
    if (lpwh->dwFlags & WHDR_INQUEUE)
        return WAVERR_STILLPLAYING;

    /* add the buffer to our queue */
    lpwh->dwFlags |= WHDR_INQUEUE;
    lpwh->dwFlags &= ~WHDR_DONE;

    /* sanity */
    lpwh->dwBytesRecorded = 0;
    lpwh->lpNext = NULL;

    CritEnter();
    {
        if ( lpN = glpWIQueue ) {
            while ( lpN->lpNext && (lpN = lpN->lpNext) )
                ;

            lpN->lpNext = lpwh;
        }

        else 
            glpWIQueue = lpwh;
    }
    CritLeave();

    /* return success */
    return ( 0L );
}

/****************************************************************************
 * @doc INTERNAL
 * 
 * @api WORD | widSendPartBuffer | This function is called from widStop().
 *     It looks at the buffer at the head of the queue and, if it contains
 *     any data, marks it as done as sends it back to the client.
 * 
 * @rdesc The return value is the number of bytes transfered. A value of zero
 *     indicates that there was no more data in the input queue.
 ***************************************************************************/ 
void NEAR PASCAL widSendPartBuffer(void)
{
LPWAVEHDR lpH;

    /* Note that unlike midi input, we don't have to check if the
     * current buffer has data - it is only called if wave input is
     * started, which means it has data (whereas midi input being
     * started doesn't necessarily mean data has been received).
     */
    if (glpWIQueue) {
        lpH = glpWIQueue;
        glpWIQueue = glpWIQueue->lpNext;
        lpH->dwFlags |= WHDR_DONE;
        lpH->dwFlags &= ~WHDR_INQUEUE;
        dwCurInCount = 0L;
        hpCurInData = NULL;
        widBlockFinished(lpH);
    }
}

/****************************************************************************
 * @doc INTERNAL
 *
 * @api void | widGetDevCaps | Get the device capabilities.
 *
 * @parm LPBYTE | lpCaps | Far pointer to a WAVEINCAPS structure to
 *     receive the information.
 *
 * @parm WORD | wSize | Size of the WAVEINCAPS structure.
 *
 * @rdesc There is no return value.
 ***************************************************************************/
static void NEAR PASCAL widGetDevCaps(LPBYTE lpCaps, WORD wSize)
{
WAVEINCAPS wc;

    wc.wMid = MM_MICROSOFT;
    wc.wPid = MM_SNDBLST_WAVEIN;
    wc.vDriverVersion = DRIVER_VERSION;
    wc.dwFormats = WAVE_FORMAT_1M08;
    wc.wChannels = 1;
    LoadString(ghModule, IDS_SNDBLSTWAVEIN, wc.szPname, MAXPNAMELEN);

    MemCopy(lpCaps, &wc, min(wSize, sizeof(wc)));
}

/****************************************************************************

    This function conforms to the standard wave input driver message proc

****************************************************************************/
DWORD FAR PASCAL _loadds widMessage(WORD id, UINT msg, DWORD dwUser, DWORD dwParam1, DWORD dwParam2)
{
const WAVEFORMAT FAR *lpFmt;      /* pointer to passed format */
NPWAVEALLOC           pInClient;  /* pointer to client information structure */

    if (!gfEnabled) {
        if ( msg == WIDM_INIT ) {
            D1("WIDM_INIT");
            InitDisplayConfigErrors();
            return 0L;
        }

        D1("widMessage called while disabled");
        return ((msg == WIDM_GETNUMDEVS) ? 0L : MMSYSERR_NOTENABLED);
    }

    /* this driver only supports one device */
    if (id != 0) {               
        D1("invalid wave device id");
        return MMSYSERR_BADDEVICEID;
    }

    switch (msg) {
        case WIDM_GETNUMDEVS:
            D1("WIDM_GETNUMDEVS");
            return 1L;

        case WIDM_GETDEVCAPS:
            D1("WIDM_GETDEVCAPS");
            widGetDevCaps((LPBYTE)dwParam1, (WORD)dwParam2);
            return 0L;

        case WIDM_OPEN:
            D1("WIDM_OPEN");

            /* dwParam1 contains a pointer to a WAVEOPENDESC
             * dwParam2 contains wave driver specific flags in the LOWORD
             * and generic driver flags in the HIWORD
             */

            /* make sure we can handle the format */
            lpFmt = ((LPWAVEOPENDESC)dwParam1)->lpFormat;
            if ((lpFmt->wFormatTag != WAVE_FORMAT_PCM) ||
                (lpFmt->nChannels != 1) ||
                (lpFmt->nSamplesPerSec < 4000) ||
                (lpFmt->nSamplesPerSec > 12000) ||
                (lpFmt->nAvgBytesPerSec != lpFmt->nSamplesPerSec) ||
                (lpFmt->nBlockAlign != 1) ||
                (((LPPCMWAVEFORMAT)lpFmt)->wBitsPerSample != 8))
            {
                return WAVERR_BADFORMAT;
            }

            /* did they just want format information? */
            if (dwParam2 & WAVE_FORMAT_QUERY)
                return 0L;

            /* attempt to 'acquire' the Wave input hardware */
            if ( widAcquireHardware() ) {
                D1("Wave input hardware is not available!");
                return MMSYSERR_ALLOCATED;
            }

            /* allocate my per-client structure */
            pInClient = (NPWAVEALLOC)LocalAlloc(LPTR, sizeof(WAVEALLOC));
            if (pInClient == NULL) {
                widReleaseHardware();
                return MMSYSERR_NOMEM;
            }

            /* and fill it with info */
            pInClient->dwCallback  = ((LPWAVEOPENDESC)dwParam1)->dwCallback;
            pInClient->dwInstance  = ((LPWAVEOPENDESC)dwParam1)->dwInstance;
            pInClient->hWave       = ((LPWAVEOPENDESC)dwParam1)->hWave;
            pInClient->dwFlags     = dwParam2;
            pInClient->dwByteCount = 0L;
            pInClient->pcmwf       = *((LPPCMWAVEFORMAT)lpFmt);

            /* set the sample rate */
            dspSetSampleRate((WORD)lpFmt->nSamplesPerSec);

            /* give the client my driver dw */
            *((LPDWORD)dwUser) = MAKELONG(pInClient, 0);

            /* call client's callback */
            waveCallback(pInClient, WIM_OPEN, 0L);

            return 0L;

        case WIDM_CLOSE:
            D1("WIDM_CLOSE");

            if (glpWIQueue)
                return WAVERR_STILLPLAYING;

            /* just in case they started input without adding buffers... */
            widStop();

            /* call client's callback */
            pInClient = (NPWAVEALLOC)LOWORD(dwUser);
            waveCallback(pInClient, WIM_CLOSE, 0L);

            /* free the allocated memory */
            LocalFree((LOCALHANDLE)pInClient);

            /* now 'release' the Wave input hardware */
            if ( widReleaseHardware() ) {
                D1("Wave input hardware could NOT be released!");
            }

            return 0L;

        case WIDM_ADDBUFFER:
            D1("WIDM_ADDBUFFER");
            AssertF(dwParam1 != NULL);
            AssertF(!(((LPWAVEHDR)dwParam1)->dwFlags & ~(WHDR_INQUEUE|WHDR_DONE|WHDR_PREPARED)));
            ((LPWAVEHDR)dwParam1)->dwFlags &= (WHDR_INQUEUE|WHDR_DONE|WHDR_PREPARED);

            /* store the pointer to my WAVEALLOC structure in the wavehdr */
            pInClient = (NPWAVEALLOC)LOWORD(dwUser);
            ((LPWAVEHDR)dwParam1)->reserved = (DWORD)(LPSTR)pInClient;

            /* add the buffer to our queue */
            return widAddBuffer((LPWAVEHDR)dwParam1);

        case WIDM_START:
            D1("WIDM_START");
            widStart();
            return 0L;

        case WIDM_STOP:
            D1("WIDM_STOP");
            widStop();
            return 0L;

        case WIDM_RESET:
            D1("WIDM_RESET");

            /* stop if it is started and release all buffers */
            widStop(); 
            widFreeQ(); 

            /* reset byte count */
            pInClient = (NPWAVEALLOC)LOWORD(dwUser);
            pInClient->dwByteCount = 0L;

            return 0L;

        case WIDM_GETPOS:
            D1("WIDM_GETPOS");
            return waveGetPos(dwUser, (LPMMTIME)dwParam1, (WORD)dwParam2);

        default:
            return MMSYSERR_NOTSUPPORTED;
    }

    /* should never get here... */
    AssertF(0);
    return MMSYSERR_NOTSUPPORTED;
}
Detected encoding: ASCII (7 bit)2