/* ------------------------------------------------------------------------ */
/*  @@ Source Documentation                         *** C Version ***       */
/*                                                                          */
/*  TITLE : DEMOMIDI.C                                                      */
/*                                                                          */
/*  DESCRIPTION :                                                           */
/*      This program demostrates how to use the CTMIDI.DRV driver           */
/*      to play a midi file.                                                */
/*                                                                          */
/*      Note that the BLASTER environment has to be set before executing    */
/*      this program. Set MIDI=SYNTH:1|2 MAP:G|E|B. If MIDI is not set,     */
/*      th default SYNTH:1 and MAP:E will be used.                          */
/*                                                                          */
/*  Copyright (c) Creative Technology Ltd, 1993. All rights reserved.       */
/*                                                                          */
/* ------------------------------------------------------------------------ */

#include  <io.h>
#include  <dos.h>
#include  <bios.h>
#include  <fcntl.h>
#include  <stdlib.h>
#include  <io.h>
#include  <conio.h>
#include  <dos.h>
#include  <string.h>
#include  <ctype.h>

#include  "sbkmidi.h"
#include  "sbkmacro.h"
#include  "sbkx.h"
#include  "Loaddrv.c"


/* Local functions */
int PrepareCTMIDIDrv(char * BlasterEnv) ;
int SetMidiOutParameters(void) ;
int PlayMidi (char far * lpMusicBuf) ;
char far * LoadFile (char * szFilename) ;
int WaitMusicEnd (void) ;
void DisplayMenu (void) ;
int SearchFile (char * szCmdArg) ;


#define MAX_FILES       100             /* Maximum files searched */
#define PATH_LEN        128             /* Maximun path length with file name */
#define NAME_LEN        13              /* Length of file name */

/* Global variable */
volatile WORD wMidiStatus ;             /* Midi music output status */
char far * lpOrigin ;                   /* Midi music output status */

char FileList [MAX_FILES][NAME_LEN] ;   /* Midi file list */
char FilePath [PATH_LEN] ;              /* File path */
char * szCurrentPlay = 0;               /* File current being played */
int FilePos = 0 ;                       /* current being played file index */
int TotalFile = 0 ;                     /* Total files in the list */

char CopyRight[] = "\nCreative MIDI Player Version 4FUN\n" \
                   "Copyright (c) Creative Technology Ltd 1993. " \
                   "All rights reserved.\n" ;
char ClearLine[] = "                               \r" ;


void main (int argc, char *argv[])
{
    char * BlasterEnv ;
    char far * lpMidiBuffer ;
    int ret ;
    char Filename [PATH_LEN+NAME_LEN] ;


    printf("%s",CopyRight) ;

    if (argc == 1)
    {
        printf("Usage : DEMOMIDI mid_filename OR *.mid\n") ;
        exit(0);
    }

    /* find file */
    if ((TotalFile = SearchFile(argv[1])) == 0)
        exit(1) ;

    if ((BlasterEnv = getenv("BLASTER")) == NULL)
    {
        printf("\nBLASTER environment not set.");
        exit(2);
    }

    /* Load CTMIDI.DRV into memory */
    if (!PrepareCTMIDIDrv(BlasterEnv))
    {
        /* Initialize CTMIDI.DRV driver */
        if (!ctmdInit())
        {
            /* Set MIDI output parameters */
            if (!SetMidiOutParameters())
            {
                DisplayMenu() ;

                while (TotalFile)
                {
                    szCurrentPlay =  FileList[FilePos] ;

                    strcpy(Filename,FilePath) ;
                    strcat(Filename,FileList[FilePos]) ;

                    /* Load midi file into memory buffer */
                    if ((lpMidiBuffer = LoadFile(Filename)) != NULL)
                    {
                        ret = PlayMidi(lpMidiBuffer) ;

                        /* free music buffer */
                        sbkFreeMem(lpMidiBuffer) ;

                        if (ret)
                            break ;
                    }
                    else
                        break ;
                }
            }
            /* Terminate CTMIDI.DRV driver */
            ctmdTerminate() ;
        }
        else
            printf("\nError initialising CTMIDI.DRV driver.") ;
    }
}


/* ------------------------------------------------------------------------ */
/*  @@ Usage                                                                */
/*                                                                          */
/*  PrepareCTMIDIDrv(char * BlasterEnv)                                     */
/*                                                                          */
/*  Description :                                                           */
/*      Load and endorses CTMIDI.DRV.                                       */
/*                                                                          */
/*  Entry :                                                                 */
/*      BlasterEnv - pointer to the BLASTER enviroment setting.             */
/*                                                                          */
/*  Exit :                                                                  */
/*      zero if sucessful, non-zero otherwise.                              */
/*                                                                          */
/* ------------------------------------------------------------------------ */

int PrepareCTMIDIDrv(char * BlasterEnv)
{
    char * szMidiEnv ;


    /* load CTMIDI.DRV driver into memory. */
    if ((CTmidiDrv = (char far *)sbkLoadDriver("CTMIDI.DRV",UNUSED,(char far **)&lpOrigin)) != NULL)
    {
        if (ctmdGetDrvVer() >= 0x0100)
        {
            if (!ctmdGetEnvSettings((char far *)BlasterEnv))
            {
                /* get MIDI environment environment setting */
                if ((szMidiEnv = getenv("MIDI")) != NULL)
                    /* set synthesizer type and mapper channel */
                    ctmdGetMidiEnvSettings((const char far *)szMidiEnv) ;
                return(0) ;
            }
            else
                printf("\nBLASTER environment is not valid") ;
        }
        else
        {
            printf("\nInvalid CTMIDI.DRV - ") ;
            printf("I need CTMIDI.DRV version 1.00 or higher.\n") ;
        }
    }
    return(1) ;
}


/* ------------------------------------------------------------------------ */
/*  @@ Usage                                                                */
/*                                                                          */
/*   int SetMidiOutParameters (void)                                        */
/*                                                                          */
/*   DESCRIPTION:                                                           */
/*       Set necessaey Midi output parameters.                              */
/*                                                                          */
/*   ENTRY:                                                                 */
/*      none.                                                               */
/*                                                                          */
/*   EXIT:                                                                  */
/*       zero if successful else return 1.                                  */
/*                                                                          */
/* ------------------------------------------------------------------------ */

int SetMidiOutParameters (void)
{
    /* Reset MIDI device parameter */
    if (!ctmdResetMidiDriver())
    {
        /* Set MIDI output status address */
        if (!ctmdSetOutputStatusAddx((WORD far *)&wMidiStatus))
            return (0) ;
        else
            printf("\nError setting MIDI status address.") ;
    }
    else
        printf("\nError resetting MIDI device.") ;

    return (1) ;
}


/* ------------------------------------------------------------------------ */
/*  @@ Usage                                                                */
/*                                                                          */
/*  int PlayMidi(char far * lpMidiBuffer)                                   */
/*                                                                          */
/*  Description :                                                           */
/*      Start sending out MIDI code.                                        */
/*                                                                          */
/*  Entry :                                                                 */
/*      lpMidiBuffer :- Music buffer.                                       */
/*                                                                          */
/*  Exit :                                                                  */
/*      0 if successful else non-zero                                       */
/*                                                                          */
/* ------------------------------------------------------------------------ */

int PlayMidi (char far * lpMidiBuffer)
{

    if (!ctmdResetMidiDriver())
    {
        if (!ctmdPrepareMidiStart((const BYTE far *)lpMidiBuffer))
        {
            if (!ctmdPlayMidiMusic())
                return (WaitMusicEnd()) ;
            else
                printf("\nError outputing music.") ;
        }
        else
            printf("\nError preparing MIDI output.") ;
    }
    else
        printf("\nError resetting MIDI driver.") ;

    return (1) ;
}


/* ------------------------------------------------------------------------ */
/*  @@ Usage                                                                */
/*                                                                          */
/*   char far * LoadFile (char *szFilename)                                 */
/*                                                                          */
/*   DESCRIPTION:                                                           */
/*       Load file into memory. The Global variable lpMusicBuf is used to   */
/*       point to the loaded buffer.                                        */
/*                                                                          */
/*   ENTRY:                                                                 */
/*       szFileName :- File to be loaded.                                   */
/*                                                                          */
/*   EXIT:                                                                  */
/*       far pointer of the loader music buffer else return 0.              */
/*                                                                          */
/* ------------------------------------------------------------------------ */

char far * LoadFile (char *szFilename)
{
    char    far *lpTmpPtr = 0 ;
    char    far *lpMusicBuf = 0 ;
    int         Handle ;
    WORD    wByteRead ;
    long    lFileSize ;


    /* open file */
    if ((Handle = sbkDosOpen(szFilename)) != -1)
    {
        /* file size */
        lFileSize = filelength(Handle) ;

        /* allocate music buffer */
        if ((lpMusicBuf = sbkAllocMem(lFileSize + 15l)) != NULL)
        {
            lpTmpPtr = lpMusicBuf ;

            do
            {
                FPSEG(lpTmpPtr) += (FPOFF(lpTmpPtr) >> 4) ;
                FPOFF(lpTmpPtr) &= 0x000f ;

                if (sbkDosRead(Handle,(char far *)lpTmpPtr,0x8000,
                                (WORD far *)&wByteRead))
                {
                    printf("\nDOS : Read file error.");
                    sbkFreeMem(lpMusicBuf) ;
                    lpMusicBuf = 0 ;
                    wByteRead = 0 ;
                }
                else
                    FPOFF(lpTmpPtr) += wByteRead ;

            } while (wByteRead == 0x8000);
        }
        else
            printf("\nMemory allocation error.");

        sbkDosClose(Handle) ;
    }
    else
        printf("\nOpen %s failed.",szFilename) ;

    return(lpMusicBuf) ;
}


/* ------------------------------------------------------------------------ */
/*  @@ Usage                                                                */
/*                                                                          */
/*   WaitMusicEnd (void)                                                    */
/*                                                                          */
/*   DESCRIPTION:                                                           */
/*      Control MIDI music output.                                          */
/*                                                                          */
/*   ENTRY:                                                                 */
/*       none                                                               */
/*                                                                          */
/*   EXIT:                                                                  */
/*       0 if sucessful else return non-zero.                               */
/*                                                                          */
/* ------------------------------------------------------------------------ */

int WaitMusicEnd (void)
{
    int pause = 0, inkey ;
    int transpose = 0 , tempo = 0 , mapper_type = 0 ;
    char * CommandEnv ;
    char *mapper[] ={"General Midi", "Extended Midi", "Basic Midi"} ;


    printf("%s",ClearLine);
    printf("Title : %s\r", szCurrentPlay) ;

    /* End of music ? */
    while (wMidiStatus)
    {
        if (kbhit())
        {
            inkey = getch() ;

            switch (toupper(inkey & 0xff))
            {
                case 0x1b :
                    ctmdStopMidiMusic() ;
                    return (1) ;

                case 'N' :
                    ctmdStopMidiMusic() ;
                    break ;

                case 'L' :
                    ctmdStopMidiMusic() ;
                    FilePos -- ;
                    if (FilePos < 0 )
                        FilePos = 0 ;
                    return (0) ;

                case 'P' :
                    if (!pause)
                    {
                        printf("%s",ClearLine);
                        printf("Music pause...\r") ;
                        ctmdPauseMidiMusic() ;
                        pause = 1 ;
                    }
                    break ;

                case 'R' :
                    if (pause)
                    {
                        printf("%s",ClearLine);
                        printf("Music continue...\r") ;
                        ctmdResumeMidiMusic() ;
                        pause = 0 ;
                    }
                    break ;

                case 'M' :
                    if ((++mapper_type) > 2)
                        mapper_type = 0 ;
                    ctmdSetMapperType((WORD)mapper_type) ;
                    printf("%s",ClearLine);
                    printf("%s\r",mapper[mapper_type]) ;
                    break ;

                case 'S' :
                    printf("Type EXIT to return.\r") ;
                    if ((CommandEnv = getenv("COMSPEC")) != NULL)
                        inkey = system(CommandEnv) ;
                    else
                        inkey = system("command.com") ;
                    if (inkey != -1)
                    {
                        printf("%s",CopyRight) ;
                        DisplayMenu() ;
                        printf("Title : %s\r", szCurrentPlay) ;
                    }
                    break ;

                case 'T' :
                    printf("%s",ClearLine);
                    printf("Title : %s\r", szCurrentPlay) ;
                    break ;

                case 0x00 :
                    inkey = getch() ;
                    switch (inkey & 0xff)
                    {
                        case 72 :
                            if (tempo < 20)
                                tempo ++ ;
                            if (!ctmdSetMusicTempo(tempo))
                            {
                                printf("%s",ClearLine);
                                printf("Tempo : %d\r",tempo) ;
                            }
                            break ;

                        case 80 :
                            if (tempo > -20)
                                tempo -- ;
                            if (!ctmdSetMusicTempo(tempo))
                            {
                                printf("%s",ClearLine);
                                printf("Tempo : %d\r",tempo) ;
                            }
                            break ;

                        case 77 :
                            if (transpose < 12)
                                transpose ++ ;
                            if (!ctmdSetMusicTranspose(transpose))
                            {
                                printf("%s",ClearLine);
                                printf("Transpose : %d\r",transpose) ;
                            }
                            break ;

                        case 75 :
                            if (transpose > -12)
                                transpose -- ;
                            if (!ctmdSetMusicTranspose(transpose))
                            {
                                printf("%s",ClearLine);
                                printf("Transpose : %d\r",transpose) ;
                            }
                            break ;
                    }
                    break ;
            }
        }
    }

    if ((++FilePos) < TotalFile)
        return (0) ;

    return (1) ;
}


/* ------------------------------------------------------------------------ */
/*  SearchFile (char * szCmdArg)                                            */
/*                                                                          */
/*  Description :                                                           */
/*      Search the file specified or wild card and put into global list.    */
/*                                                                          */
/*  Entry :                                                                 */
/*      szCmdArg :- pointer to the file to be search.                       */
/*                                                                          */
/*  Exit :                                                                  */
/*      Total number of files found.                                        */
/*                                                                          */
/* ------------------------------------------------------------------------ */

int SearchFile (char * szCmdArg)
{
    int x, i, path_loc = 0 ;
    char szFilename[PATH_LEN + NAME_LEN] ;

#if defined _MSC_VER
    struct find_t   findt ;
    #define fname   name
#else
    struct ffblk    findt ;
    #define fname   ff_name
#endif

    x = strlen(szCmdArg) ;
    if (x >= (PATH_LEN + NAME_LEN - 4))
    {
        printf("\nPath name too long. Process aborted.") ;
        return (0) ;
    }

    strcpy(szFilename,szCmdArg) ;
    strupr(szFilename) ;

    for (i = 0 ; i < x; i ++)
        if ((szFilename[i] == '.') &&
            ((szFilename[i+1] == 'M') || (szFilename[i+1] == '*')))
            break ;
    if (i == x)
        strcat(szFilename,".MID");

    if (!sbkFindFirst(szFilename,&findt))
    {
        x = strlen(szFilename) ;
        for (i = 0 ; i < x; i ++)
            if (szFilename[i] == '\\' || szFilename[i] == ':')
                path_loc = i + 1;
        szFilename[path_loc] = '\0' ;

        strcpy (FilePath,szFilename) ;

        i = 0 ;

        do
        {
            if (i >= MAX_FILES)
                break ;
            strcpy(FileList[i++],findt.fname) ;

        } while (!sbkFindNext(&findt)) ;

        return (i) ;
    }
    else
        printf("< %s > - no file found.\n",szFilename) ;

    return (0) ;
}

/* ------------------------------------------------------------------------ */
/*  Display Menu                                                            */
/* ------------------------------------------------------------------------ */

 void DisplayMenu(void)
{
    printf("Press\n") ;
    printf("    Esc      - to exit          T        - to display title\n") ;
    printf("    N        - next song        M        - to change mapper\n") ;
    printf("    L        - previous song    <- or -> - to transpose\n") ;
    printf("    P        - to pause           or   - to change tempo\n") ;
    printf("    R        - to resume        S        - DOS Shell\n\n") ;
}



/* End of file */
