/**************************************************************************
* iofunctions.c:
*		Functions for input/output in a variety of formats.	
*		Part of MP, the MIDI Playground.
*
* Author:	Daniel Barrett
* Version:	See the file "version.h".
* Copyright:	None!  This program is in the Public Domain.
*		Please share it with others.
***************************************************************************/

	
#include "mp.h"
#include "midi.h"


/* Read data from MIDI.  Return the value of the next MIDI byte.  Because
 * reading byte-by-byte from the MIDI port is inefficient, we read as
 * much as we can and keep it in a static buffer. */
	
MIDI_RESULT FromMidi(FILE *in, MIDI_VALUE *value)
{
	static long bytesWaiting = 0L;	/* # bytes waiting at serial port. */
	static UBYTE buf[BUFSIZ];	/* Static buffer. */
	static long currentByte = 0L;	/* Index of next byte to return. */

	if (currentByte >= bytesWaiting)
	{
		bytesWaiting = FastSerialRead(buf);
		currentByte = 0L;
	}

	if (bytesWaiting == CTRL_C_NO_BYTES)
	{
		bytesWaiting = currentByte = 0L;
		return(RESULT_STOP);
	}
	else if (bytesWaiting <= 0)
	{
		bytesWaiting = currentByte = 0L;
		return(RESULT_ERROR);
	}
	else
	{
		*value = buf[currentByte++];
		return(RESULT_OK);
	}
}


/* Write a byte to MIDI.  It is inefficient to write 1 byte at a time, but
 * we want instant transmission.  I will rewrite this eventually. */
	
BOOL ToMidi(FILE *dummy, MIDI_VALUE value)
{
	PrepareToWriteMidi(&value, 1);
	return(DoTheIO() == 1L);
}

/* Read 1 byte from text.  We use a finite state automaton.
 * If an error occurs, assign the value of the last character read
 * to *answer. */
	
MIDI_RESULT FromText(FILE *in, MIDI_VALUE *value)
{
	STATE_T state = STATE_NORMAL;
	int c;
	
	*value = 0L;

	while ((state != STATE_SUCCESS) && (state != STATE_ERROR)
	&&     (state != STATE_OVERFLOW)
	&&     ((c = getc(in)) != EOF))

		state = NewState(c, state, value);

	if (state == STATE_SUCCESS)
		return(RESULT_OK);
	else if (c == EOF && state == STATE_NORMAL)
		return(RESULT_STOP);
	else if (c == EOF)
		return(RESULT_ERROR);
	else if (state == STATE_OVERFLOW)
		return(RESULT_OVERFLOW);
	else
	{
		*value = c;
		return(RESULT_ERROR);
	}
}


/* Write 1 MIDI value as text. */
	
BOOL ToText(FILE *out, MIDI_VALUE value)
{
	static long byt = 0L;

	fprintf(out, "<%6ld>   ", ++byt);
	PrintNumber(value, out);
}


/* Read 1 MIDI value from a binary file.  Inefficient. */
	
MIDI_RESULT FromBinary(FILE *in, MIDI_VALUE *value)
{
	int c;
	if ((c = getc(in)) != EOF)
	{
	    	*value = (MIDI_VALUE)c;
		return(RESULT_OK);
	}

	return(RESULT_STOP);
}


/* Write 1 MIDI value to a binary file.  Inefficient. */
	
BOOL ToBinary(FILE *out, MIDI_VALUE value)
{
	return(putc(value, out) != EOF);
}

	
/****************************************************************************
* Skipping input.
****************************************************************************/

	
/* Skip to the next valid text input. */

void SkipText(FILE *in, MIDI_VALUE value)
{
	register int c;

	if (isspace(value))
		return;

	while ((c = getc(in)) != EOF && !isspace(c))
		;
	if (c != EOF)
		ungetc(c, in);
}


/* Skip to the next valid MIDI input by clearing the serial port buffer. */
	
void SkipMidi(FILE *dummy, MIDI_VALUE junk)
{
	ResetSerialPort();
}


/* Skip to the next valid binary value.  This is currently just a stub. */
	
void SkipBinary(FILE *in, MIDI_VALUE junk)
{
	return;
}
