/*
  MidiPlay - MIDI file player driver module

  main.h - Common declarations and definitions

  created  19/01/10
  1.0      14/06/14
*/

#ifndef main_h
#define main_h

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include "midi_spec.h"

#ifndef FALSE
#define FALSE 0
#define TRUE !FALSE
#endif

#ifndef NULL
#define NULL 0
#endif

// Saturates 'x' to 'lo' or 'hi'
#define LIMIT(lo,x,hi) \
  if((x) < (lo)) (x) = (lo); \
  else if((x) > (hi)) (x) = (hi)

typedef unsigned long long int Uint64;
typedef signed long long int Int64;

// error return values, negative where used, eg. return -PARAMETER_ERROR
enum err_msg_e
{
  NO_ERROR_, // must be first
  UNKNOWN_ERROR,
  PARAMETER_ERROR,
  OUT_OF_RANGE,
  NO_SSOUND,
  NO_AUDIO,
  NO_HEADER,
  INVALID_HEADER_LENGTH,
  UNSUPPORTED_FORMAT,
  INVALID_NUMBER_OF_TRACKS,
  FILE_TOO_LARGE,
  PROBLEM_READING_FILE,
  INCOMPLETE,
  PROBLEM_OPENING_FILE,
  NO_FILE_LOADED,
  CANNOT_ALLOCATE_MEMORY,
  NUM_ERRORS // must be last
};

#ifdef DEFINE_ERROR_STRINGS
const char * const errstr[] =
{
  "Unknown error",
  "Parameter error",
  "Out of range",
  "SharedSound module not found",
  "Cannot register audio driver",
  "No file header",
  "Invalid header length",
  "Unsupported format",
  "Too many tracks",
  "File is too large",
  "Problem reading file",
  "Track incomplete",
  "Cannot open file",
  "No file loaded",
  "Cannot allocate memory"
};
#else
extern const char * const errstr[];
#endif

// midi i/o interface
typedef struct midi_io_if_s
{
  void(* reset)(void);
  void(* tx_byte)(int data);
  void(* tx_word)(int status, unsigned char *buff, int n);
  void(* all_notes_off)(void);
  void(* volume)(int volume);
} midi_io_if_t;

// general module data
typedef struct module_s
{
  int tx_chan;        // channel to use for Tx channel commands
  FILE *log;          // debugging log file handle
  unsigned int debug; // bitfield, see below
  int ticker_callbacks; // ticker callbacks pending
  int master_clock;   // ticker clock rate. i.e. tickerv = 100 (Hz), timer mod = 1kHz
  const midi_io_if_t *midi;
  unsigned int ticks; // current timestamp

} module_t;

#define DBG_MSG       0 // log midi messages
#define DBG_SWI       1 // log swi calls
#define DBG_LYRICS    2 // log lyric text
#define DBG_FN_CALLS  3 // log main function calls
#define DBG_CLK       4 // log timing

extern module_t mod;

//player.c
enum{CTRL_LOAD, CTRL_PLAY, CTRL_PAUSE, CTRL_UNPAUSE,
     CTRL_TEMPO, CTRL_INFO, CTRL_CLOSE, CTRL_CONTROLS}; // midiPlayer_control, cmd values
int midiPlayer_control(int cmd, int data, int *ret);
void midiPlayer_info(int additional);
void midiPlayer_new(void);
void midiPlayer_term(void);
void midi_file_player(void);
int player_tempo(int data);
int player_pitch(int data);
int player_load(char *name, int options);
int get_text(void);

// midi module interface
void midi_reset(void);
void midi_tx_byte(int data);
void midi_tx_word(int status, unsigned char *buff, int n);
void midi_all_notes_off(void);
void midi_volume(int volume);

#endif
