#include <stdio.h>
#include <exec/types.h>
#include <exec/memory.h>
#include <hardware/custom.h>
#include <hardware/dmabits.h>
#include <intuition/intuition.h>
#include <devices/audio.h>
#include <proto/intuition.h>
#include <proto/exec.h>

#define SOUNDPREC       -40
#define MAXVOLUME       64

struct IntuitionBase *IntuitionBase;

struct NewWindow newwindow = {
        20, 20, 130, 20,
        0, 1,
        CLOSEWINDOW,
        WINDOWDEPTH | WINDOWCLOSE | SMART_REFRESH | ACTIVATE |
                WINDOWDRAG | NOCAREREFRESH,
        NULL, NULL,
        "Play",
        NULL, NULL,
        0, 0, 0, 0,
        WBENCHSCREEN
};

int StartSample( UBYTE *, int, int, int );
void StopSample();

void main(argc, argv)
int argc;
char *argv[];
{
        struct Window *window;
        FILE *fp;
        int size, tsize, period, cycles;
        char *buffer;

        if( argc != 5 ) {
                fprintf( stderr, "Usage: %s file len period cycles\n", argv[0] );
                exit(0);
        }

        if( (size = atoi( argv[2] ) ) <= 0 ) {
                fprintf( stderr, "Illegal size %d\n", size );
                exit(0);
        }

        if( (period = atoi( argv[3] ) ) <= 0 ) {
                fprintf( stderr, "Illegal period\n", period );
                exit(0);
        }

        if( (cycles = atoi( argv[4] ) ) <= 0 ) {
                fprintf( stderr, "Illegal number of cycles\n", period );
                exit(0);
        }

        if( (fp = fopen( argv[1], "r" ) ) == NULL ) {
                fprintf( stderr, "Can't open %s\n", argv[1] );
                exit(0);
        }

        if( (buffer = AllocMem( size, MEMF_CHIP | MEMF_PUBLIC ) ) == NULL ) {
                fprintf( stderr, "No mem for buffer\n" );
                fclose( fp );
                exit(0);
        }

        tsize = fread( buffer, 1, size, fp );
        fclose(fp);

        if( tsize <= 0 ) {
                fprintf( stderr, "Read failed\n" );
                FreeMem( buffer, size );
                exit(0);
        }

        if( StartSample( buffer, tsize, period, cycles ) == 0 ) {

            IntuitionBase = (struct IntuitionBase *)
                    OpenLibrary( "intuition.library", 0 );

            if(( window = (struct Window *)OpenWindow( &newwindow ) ) != NULL ) {

                Wait( 1 << ( window->UserPort->mp_SigBit ) );

                CloseWindow( window );
            } else
                fprintf( stderr, "Window wont open\n" );

            CloseLibrary( (struct Library *)IntuitionBase );
            StopSample();
        }

        FreeMem( buffer, size );
}

static struct IOAudio allocIOB;
static UBYTE allocationmap[] = { 3, 5, 10, 12 };
static struct MsgPort *MusicPort;

int StartSample( UBYTE *buffer, int len, int period, int cycles )
{

        if( (MusicPort = CreatePort( "MusicPort", 0 ) ) == 0 ) {
            return 1;
        }

        allocIOB.ioa_Data = allocationmap;
        allocIOB.ioa_Length = sizeof( allocationmap );
        allocIOB.ioa_Request.io_Message.mn_Node.ln_Pri = SOUNDPREC;
        allocIOB.ioa_Request.io_Message.mn_ReplyPort = MusicPort;

        if( OpenDevice( AUDIONAME, 0, (struct IORequest*)&allocIOB, 0 ) != 0 ) {
            DeletePort( MusicPort );
            return 1;
        }

        allocIOB.ioa_Data = buffer;
        allocIOB.ioa_Length = len;
        allocIOB.ioa_Period = period;
        allocIOB.ioa_Volume = MAXVOLUME;
        allocIOB.ioa_Cycles = cycles;

        allocIOB.ioa_Request.io_Command = CMD_WRITE;
        allocIOB.ioa_Request.io_Flags = ADIOF_PERVOL;

        BeginIO( (struct IORequest*)&allocIOB );

/*        WaitIO( (struct IORequest*)&allocIOB ); */

        return 0;
}

void StopSample()
{
        CloseDevice( (struct IORequest*)&allocIOB );
        DeletePort( MusicPort );
}