/* ------------------------------------------------------------------------ */
/*  @@ Source Documentation                         *** C Version ***       */
/*                                                                          */
/*  TITLE : DEMOWDP.C                                                       */
/*                                                                          */
/*  DESCRIPTION :                                                           */
/*      This program demostrates how to playback wave using the             */
/*      CTWDSK.DRV driver. The wave output is using the Disk                */
/*      Double Buffering method.                                            */
/*                                                                          */
/*      The program retrieves BLASTER environment for the Card settings     */
/*      and passes it to the driver.                                        */
/*                                                                          */
/*      Note that the program included the module LOADDRV.C to load         */
/*      the loadable CTWDSK.DRV into memory.                                */
/*                                                                          */
/*  Copyright (c) Creative Technology Ltd, 1993. All rights reserved.       */
/*                                                                          */
/* ------------------------------------------------------------------------ */

#include <dos.h>
#include <bios.h>
#include <stdio.h>
#include <fcntl.h>
#include <conio.h>
#include <dos.h>

#include "sbkwave.h"
#include "sbkmacro.h"
#include "sbkx.h"
#include "loaddrv.c"

#define TWO_KBYTES  2048l
#define PARA_ADJ    15l     /* 15 bytes for paragraph adjustment */

/*
## DMA_UNIT is unit of half embedded DMA in size of 2 kbytes .
## Change this value (from 1 - 16) if allocating own DMA buffer.
## This value effect the smoothy of sound output proportionally.
## Increase this value will be more efficient compare to DD_UNIT.
*/
#define DMA_UNIT    4
#define DMA_SIZE    ((DMA_UNIT * TWO_KBYTES * 2l) + PARA_ADJ)

/*
## DD_UNIT is unit of half double disk buffer in size of 2 kbytes.
## Change this value (from 2 - 32) when allocating dd buffer.
## It is recommended that this unit is at least double the DMA_UNIT.
## This value effect the smoothy of sound output proportionally.
*/
#define DD_UNIT     16
#define DD_SIZE     ((DD_UNIT * TWO_KBYTES * 2l) + PARA_ADJ)

/* Local function prototype */
int PrepareCTWDSKDrv(char * BlasterEnv) ;
int SetOutputParam(void) ;
void PlayUntilStopped (WORD wIOHandle,char * szFilename) ;
void ShowError(void) ;

/* Global variable */
volatile WORD ct_wave_status ;      /* wave i/o status */
char far * lpOrigin ;               /* original pointer of driver buffer */

main (int argc, char * argv[])
{
    char * BlasterEnv ;
    int  wIOHandle ;


    if (argc < 2)
    {
        printf("\nUsage : DEMOWDP wav_filename") ;
        exit (0) ;
    }

    printf ("\nPlayback %s through double disk buffer.",argv[1]) ;

    /* Retrieve the BLASTER environment settings */
    if ((BlasterEnv = getenv("BLASTER")) != NULL)
    {
        if (!PrepareCTWDSKDrv(BlasterEnv))
        {
            if (!ctwdInit())
            {
                if ((wIOHandle = SetOutputParam()) >= 0)
                    PlayUntilStopped((WORD)wIOHandle,argv[1]) ;

                ctwdTerminate() ;
            }
            else
                ShowError() ;
        }
    }
    else
        printf("BLASTER environment not set or incomplete or invalid.\n");

    return 0 ;
}


/* ------------------------------------------------------------------------ */
/*  @@ Usage                                                                */
/*                                                                          */
/*  PrepareCTWDSKDrv(char * BlasterEnv)                                     */
/*                                                                          */
/*  Description :                                                           */
/*      Load and endorse CTWDSK.DRV.                                        */
/*                                                                          */
/*  Entry :                                                                 */
/*      BlasterEnv - pointer to the BLASTER environment.                    */
/*                                                                          */
/*  Exit :                                                                  */
/*      zero if sucessful, non-zero otherwise.                              */
/*                                                                          */
/* ------------------------------------------------------------------------ */

int PrepareCTWDSKDrv(char * BlasterEnv)
{
    DWORD   dwVersion = 0 ;


    if ((CTwdskDrv = sbkLoadDriver("CTWDSK.DRV",UNUSED,
                        (char far **)&lpOrigin)) != NULL)
    {
        /* Retrieves CTWDSK.DRV version */
        if (!ctwdGetParam(CTWAV_DRIVERVERSION,
                          (DWORD far *)&dwVersion))
        {
            if ((dwVersion & 0xffff) >= 0x0305)
            {
                /* Passes BLASTER environment settings to driver */
                if (!ctwdGetEnvSettings((const char far *)BlasterEnv))
                    return(0) ;
                else
                    printf("\nDriver : BLASTER environment is not valid");
            }
            else
            {
                printf("\nInvalid CTWDSK.DRV - ") ;
                printf("I need CTWDSK.DRV version 3.05 or higher.\n") ;
            }
        }
        else
            printf("\nDriver : Unrecognized CTWDSK.DRV\n");
    }
    return(1) ;
}


/* ------------------------------------------------------------------------ */
/*  @@ Usage                                                                */
/*                                                                          */
/*   SetOutputParam (void)                                                  */
/*                                                                          */
/*   DESCRIPTION:                                                           */
/*       Set the necessary output parameters.                               */
/*                                                                          */
/*   ENTRY:                                                                 */
/*       none.                                                              */
/*                                                                          */
/*   EXIT:                                                                  */
/*       i/o wave handle if successful otherwise return -1.                 */
/*                                                                          */
/* ------------------------------------------------------------------------ */

int SetOutputParam(void)
{
    WORD   wIOHandle ;
    DWORD  dwValue ;
    BYTE   far * lpDiskBuf, far * lpDmaBuf ;


    /* Allocate double disk buffer */
    if ((lpDiskBuf = (BYTE far *)sbkAllocMem((DWORD)DD_SIZE)) == NULL)
    {
        printf("\nDOS : Error allocating Double Disk buffer.") ;
        return (-1) ;
    }

    /* Allocate two DMA buffer. The 2nd buffer is used when
      the 1st buffer crosses the 64k boundary */
    if ((lpDmaBuf = (BYTE far *)sbkAllocMem((DWORD)(DMA_SIZE * 2))) == NULL)
    {
        printf("\nDOS : Error allocating DMA buffer.") ;
        return (-1) ;
    }

    if (!ctwdGetParam(CTWAV_IOHANDLES,(DWORD far *)&dwValue))
    {
        if (dwValue)
        {   /* wave io handle */
            wIOHandle = (WORD)(dwValue - 1) ;

            /* Set double disk buffer */
            if (!ctwdSetDiskBuffer(wIOHandle,lpDiskBuf,(WORD)DD_UNIT))
            {
                if (!ctwdSetIOParam(wIOHandle,CTWAV_IO_LPSTATUSWORD,
                                    (DWORD)(WORD far *)&ct_wave_status))
                {
                    /* convert to 32-bit linear address */
                    dwValue = (DWORD)((DWORD)FPSEG(lpDmaBuf) << 4) +
                                             FPOFF(lpDmaBuf) ;

                    /* Set up DMA buffer. If failed, the DMA buffer
                       may have crossed the 64 k boundary, thus use
                       the 2nd Dma buffer */
                    if (!ctwdSetDMABuffer(wIOHandle,dwValue,(WORD)DMA_UNIT))
                        return ((int)wIOHandle) ;

                    dwValue += (DWORD)DMA_SIZE ;
                    if (!ctwdSetDMABuffer(wIOHandle,dwValue,(WORD)DMA_UNIT))
                        return ((int)wIOHandle) ;

                    printf ("\nDriver : Error setting DMA buffer.");

                }
                else
                    printf ("\nError setting ct_wave_status.") ;
            }
            else
                printf ("\nDriver : Error setting Double Disk buffer.") ;
        }
        else
            printf ("\nI/O wave handle unavailable.") ;
    }
    else
        printf ("\nError retrieving I/O wave handles.") ;

    return (-1) ;

}


/* ------------------------------------------------------------------------ */
/*  @@ Usage                                                                */
/*                                                                          */
/*   PlayUntilStopped (WORD wIOHandle, char * szFilename)                   */
/*                                                                          */
/*   DESCRIPTION:                                                           */
/*       Open wave file and start playing back.                             */
/*                                                                          */
/*   ENTRY:                                                                 */
/*       wIOHandle  - i/o wave handle.                                      */
/*       szFilename - file name to be played back.                          */
/*                                                                          */
/*   EXIT:                                                                  */
/*       None.                                                              */
/*                                                                          */
/* ------------------------------------------------------------------------ */

void PlayUntilStopped (WORD wIOHandle,char * szFilename)
{
    WORD    wKey, Pause = 0 ;
    int     iFileHandle ;


    /* Open the wave file */
    if ((iFileHandle = sbkDosOpen(szFilename)) != -1)
    {
        ctwdSetSpeaker(1) ;

        if (!ctwdOutput(wIOHandle,(WORD)iFileHandle))
        {
            printf ("\nStart playing back...") ;
            printf("\n\t[Esc] - to stop\n");
            printf("\t[P  ] - to pause\n");
            printf("\t[C  ] - to continue\n");

            /* polls for the wave stop */
            while (ct_wave_status)
            {
                /* if (sbkBiosKeybrd(KEYBRD_READY)) */
                if (kbhit())
                {
                    /* wKey = (WORD)(sbkBiosKeybrd((WORD)KEYBRD_READ) & 0xff) ; */
                    wKey = getch() & 0xff ;

                    switch (wKey)
                    {
                        case 0x1b :

                            ctwdStop(wIOHandle) ;
                            break ;

                        case 'P' :
                        case 'p' :
                            if (!Pause)
                            {
                                printf("\nWave pauses...") ;
                                ctwdPause(wIOHandle) ;
                                Pause = 1 ;
                            }
                            break ;

                        case 'C' :
                        case 'c' :
                            if (Pause)
                            {
                                printf("\nWave continues...") ;
                                ctwdContinue(wIOHandle) ;
                                Pause = 0 ;
                            }
                            break ;
                    }
                }
            }
            printf ("\nWave stop.") ;
        }
        else
            ShowError() ;

        sbkDosClose(iFileHandle) ;
    }
    else
        printf("\nDos : Error open %s",szFilename) ;

}



/* ------------------------------------------------------------------------ */
/*  @@ Usage                                                                */
/*                                                                          */
/*   ShowError (void)                                                       */
/*                                                                          */
/*   DESCRIPTION:                                                           */
/*       Display error occurred during the process of wave i/o.             */
/*                                                                          */
/*   ENTRY:                                                                 */
/*       None.                                                              */
/*                                                                          */
/*   EXIT:                                                                  */
/*       None.                                                              */
/*                                                                          */
/* ------------------------------------------------------------------------ */

void ShowError (void)
{
    int     Err ;


    /* Show the driver error and the DOS extended error code */
    Err = ctwdGetDrvError() ;

    printf("\nDriver error = %2d", Err) ;

    Err = ctwdGetExtError();
    if ( Err != 0 )
        printf ("\nDOS error = %2d\n", Err) ;
}
/* End of file */
