#include <exec/types.h>
#include <exec/memory.h>
#include <libraries/dos.h>
#include <devices/audio.h>

struct Voice8Header
{
    ULONG   oneShotHiSamples, repeatHiSamples, samplesPerHiCycle;
    UWORD   samplesPerSec;
    UBYTE   ctOctave, sCompression;
    LONG    volume;
};

// This stuff is declared somewhere else
extern struct IOAudio *PlaySound();
extern __far BYTE Cuckoo[];
extern void ToggleLED(void);
extern BOOL GetLEDStatus(void);

BOOL Find8SVXInformation(BYTE *buffer, BYTE **sample, ULONG *len, UWORD *rate);

char txt[] = "$VER: Cuckoo 1.2 (6.10.93) by Anders Melchiorsen\n"
	     "Cuckoo will, when started at ??:00 or ??:30, play a cuckoo sample.\n";

main()
{
    UWORD cuck_rate;
    ULONG cuck_len,repeat;
    BYTE *cuck_start;
    struct IOAudio *id;
    struct DateStamp now;
    WORD hour, minute;
    BOOL ledon;

    // Just to make me famous:
    Write( Output(), &txt[6], strlen(&txt[6]) );

    // Get current time
    DateStamp(&now);
    hour   = now.ds_Minute/60;
    minute = now.ds_Minute%60;

    // Dicede how many times to call
    repeat = 0;
    if (minute == 0)  repeat = ((hour % 12) ? (hour % 12) : 12);
    if (minute == 30) repeat = 1;

    // No call -> exit
    if (repeat == 0)
	return(0);

    // Find out where sample starts, how long it is, and how fast it should be
    // played
    if (!Find8SVXInformation(Cuckoo, &cuck_start, &cuck_len, &cuck_rate))
	return(20);

    // Turn the low-pass filter off
    ledon = GetLEDStatus();
    if (ledon)
	ToggleLED();

    // Play sample the right number of times, delay for half a sec between
    // each cuckoo.
    while (repeat--)
    {
	ULONG signals = NULL;

	if (id = PlaySound(cuck_start, cuck_len, 1, 3579545/cuck_rate, 64))
	{
	    signals = Wait((1 << id->ioa_Request.io_Message.mn_ReplyPort->mp_SigBit) | SIGBREAKF_CTRL_C);
	    StopSound(id);
	}

	// Don't repeat anymore if ^C was pressed
	if (signals & SIGBREAKF_CTRL_C)
	    repeat = 0;

	if (repeat)
	    Delay(25);
    }

    // Turn filter back on (if it was shut off)
    if (ledon)
	ToggleLED();
    return(0);
}

// Finds out of certain 8SVX stuff from a buffer in memory
// Returns TRUE on success
//
// Must be initialized
//  buffer = Pointer to complete 8SVX 'file'
//
// The following are filled in by this routine:
//  sample = Where actual sample starts
//  len    = Length of sample
//  rate   = The samples rate
//
// Don't get confused; it IS a weird pointer example :-)

BOOL Find8SVXInformation(BYTE *buffer, BYTE **sample, ULONG *len, UWORD *rate)
{
    LONG jump;
    BOOL foundVHDR = FALSE, foundBODY = FALSE;
    struct Voice8Header *Header;

    // Pass 'FORM....'
    buffer += 8;

    // Is this a 8SVX file?
    if ( strncmp(buffer, "8SVX", 4) != 0)
	return(FALSE);

    // Pass '....' (size of 8SVX; should perhaps use this. Oh well...)
    buffer += 4;

    // Find VHDR and BODY chunks and get the info needed from them
    // If one of them is missing I keep on searching forever ... not good :-(
    do
    {
	if (strncmp(buffer, "VHDR", 4) == 0)
	{
	    Header = buffer + 8;
	    *len = Header->oneShotHiSamples + Header->repeatHiSamples;
	    *rate = Header->samplesPerSec;
	    foundVHDR = TRUE;
	}

	if (strncmp(buffer, "BODY", 4) == 0)
	{
	    *sample = buffer + 8;
	    foundBODY = TRUE;
	}

	buffer += 4;	 // Pass chunk ID

	// Read chuck size
	jump = (*(buffer)   << 24)
	     + (*(buffer+1) << 16)
	     + (*(buffer+2) << 8)
	     + *(buffer+3);

	buffer += 4;	 // Pass chunk size information
	buffer += jump;  // Pass rest of chunk (actual data)
    } while ( (foundVHDR==FALSE) || (foundBODY==FALSE) );

    return(TRUE);
}

