#include "DFC5.h"
#include <devices/audio.h>
#include <devices/narrator.h>
#include <proto/translator.h>

#define PHONEMESSIZE 512

BYTE AllocTries[]={ 1,2,4,8 }; /* we try all channels */

static int SoundOpen;
static struct IOAudio IOAudio;
static BYTE sound[]={ 0,64,127,64,0,-64,-127,-64 }, *chipsound; /* a very little sound */

static int VoiceOpen;
static char *Phonemes;
static struct narrator_rb rb;
struct Library *TranslatorBase;

/*
 * This function produces an async beep if SoundOpen!=0, otherwise DisplayBeep()s.
 */

void Beep(int Period) {
	if (SoundOpen) {
		WaitPort(IOAudio.ioa_Request.io_Message.mn_ReplyPort);
		GetMsg(IOAudio.ioa_Request.io_Message.mn_ReplyPort);
		IOAudio.ioa_Volume = 32;
		IOAudio.ioa_Period = Period;
		BeginIO((struct IORequest *)&IOAudio);
	}
	else DisplayBeep(NULL);
}

/*
 * Here we open the audio.device. Nothing is returned because we don't really
 * care if we can use audio.device.
 */

void SetUpAudio(void) {

	IOAudio.ioa_Request.io_Message.mn_Node.ln_Pri = 10;
	if ((IOAudio.ioa_Request.io_Message.mn_ReplyPort = CreatePort(NULL,0)) &&
		(chipsound = AllocMem(sizeof(sound), MEMF_CHIP))) {

		memcpy(chipsound, sound, sizeof(sound));
		IOAudio.ioa_Data = AllocTries;
		IOAudio.ioa_Length = sizeof(AllocTries);

		if (!OpenDevice(AUDIONAME,0,(struct IORequest *)&IOAudio,0)) {
			SoundOpen=1;
			IOAudio.ioa_Request.io_Command = CMD_WRITE;
			IOAudio.ioa_Request.io_Flags = ADIOF_PERVOL;
			IOAudio.ioa_Data = chipsound;
			IOAudio.ioa_Length = sizeof(sound);
			IOAudio.ioa_Period = 400;
			IOAudio.ioa_Cycles = 8;
			BeginIO((struct IORequest *)&IOAudio);
			return;
		}
	}

	CloseAudio();
}

/*
 * Here we close the audio.device
 */

void CloseAudio(void) {

	if (SoundOpen) {
		WaitPort(IOAudio.ioa_Request.io_Message.mn_ReplyPort);
		GetMsg(IOAudio.ioa_Request.io_Message.mn_ReplyPort);
		CloseDevice((struct IORequest *)&IOAudio);
		SoundOpen = 0;
	}
	if (IOAudio.ioa_Request.io_Message.mn_ReplyPort) {
		DeletePort(IOAudio.ioa_Request.io_Message.mn_ReplyPort);
		IOAudio.ioa_Request.io_Message.mn_ReplyPort = NULL;
	}
	if (chipsound) {
		FreeMem(chipsound, sizeof(sound));
		chipsound = NULL;
	}
}

/*
 * Here we open the narrator.device, if someone selected Talk.
 */

int OpenVoice(void) {

	if ((rb.message.io_Message.mn_ReplyPort = CreatePort(NULL,0))
		&& (TranslatorBase = OpenLibrary("translator.library",0))
		&& (Phonemes = AllocMem(PHONEMESSIZE, MEMF_CLEAR))) {

		if (!OpenDevice("narrator.device",0,(struct IORequest *)&rb,0)) {
			VoiceOpen = 1;
			rb.message.io_Command = CMD_WRITE;
			rb.ch_masks = AllocTries;
			rb.nm_masks = 4;
			return(1);
		}
	}

	CloseVoice();
	return(0);
}

/*
 * Here we closed the narrator.device.
 */

void CloseVoice(void) {

	if (VoiceOpen) {
		if (VoiceOpen == 2) WaitIO((struct IORequest *)&rb);
		CloseDevice((struct IORequest *)&rb);
		VoiceOpen = 0;
	}

	if (rb.message.io_Message.mn_ReplyPort) {
		DeletePort(rb.message.io_Message.mn_ReplyPort);
		rb.message.io_Message.mn_ReplyPort = NULL;
	}

	if (TranslatorBase) {
		CloseLibrary(TranslatorBase);
		TranslatorBase = NULL;
	}

	if (Phonemes) {
		FreeMem(Phonemes, PHONEMESSIZE);
		Phonemes = NULL;
	}
}

/*
 * And here we talk!
 * Note that Say() is *always* called---only it won't to anything if VoiceOpen==0.
 * Note also that since we use SendIO() the spoken message and the system
 * requester run concurrently 8^).
 */

void Say(char *s) {

	if (VoiceOpen) {
		if (VoiceOpen == 1) VoiceOpen = 2;
		else WaitIO((struct IORequest *)&rb);
		Translate(s, strlen(s), Phonemes, PHONEMESSIZE);
		rb.message.io_Data = (APTR)Phonemes;
		rb.message.io_Length = strlen(Phonemes);
		SendIO((struct IORequest *)&rb);
	}
}
