/* 

    TiMidity -- Experimental MIDI to WAVE converter
    Copyright (C) 1995 Tuukka Toivonen <toivonen@clinet.fi>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

    dumb_c.c
    Minimal control mode -- no interaction, just prints out messages.
    */

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>

#include "gtim.h"
#include "common.h"
#include "output.h"
#include "controls.h"
#include "instrum.h"
#include "playmidi.h"

static void ctl_refresh (void);
static void ctl_total_time (uint32 tt);
static void ctl_master_volume (int mv);
static void ctl_file_name (char *name);
static void ctl_current_time (uint32 ct);
static void ctl_note (int v);
static void ctl_program (int ch, int val, const char *name);
static void ctl_bank (int ch, int val, int var, const char *name);
static void ctl_volume (int ch, int val);
static void ctl_expression (int ch, int val);
static void ctl_panning (int ch, int val);
static void ctl_sustain (int ch, int val, int letter);
static void ctl_pitch_bend (int ch, int val, uint32 mod);
static void ctl_reset (void);
static void ctl_redo (void);
static int ctl_open (int using_stdin, int using_stdout);
static void ctl_close (void);
static int ctl_read (int32 *valp);
static int cmsg (int type, int verbosity_level, const char *fmt, ...);
static void ctl_tempo(int t, int tr);
static void ctl_keysig(int k, int ko);
static void ctl_timesig(int n, int d, int c, int b);
static void ctl_misc_controller(int ch, int val, int col, int letter, int use_color);
static void ctl_song_title (char *name);
static void ctl_author (char *name);


/**********************************/
/* export the interface functions */

#define ctl dumb_control_mode

ControlMode ctl = {
    "dumb interface", 'd',
    0, 0, 0,
    ctl_open, dumb_pass_playing_list, ctl_close, ctl_read, cmsg,
    ctl_refresh, ctl_reset, ctl_redo, ctl_file_name, ctl_total_time, ctl_current_time,
    ctl_note, ctl_master_volume, ctl_program, ctl_bank, ctl_volume,
    ctl_expression, ctl_panning, ctl_sustain, ctl_pitch_bend,
    ctl_tempo, ctl_keysig, ctl_timesig, ctl_misc_controller, ctl_song_title, ctl_author
};

static FILE *infp;		/* infp isn't actually used yet */
static FILE *outfp;

static int
ctl_open (int using_stdin, int using_stdout)
{
    infp = stdin;
    outfp = stdout;
    if (using_stdin && using_stdout)
	infp = outfp = stderr;
    else if (using_stdout)
	outfp = stderr;
    else if (using_stdin)
	infp = stdout;

    ctl.opened = 1;
    return 0;
}

static void
ctl_close (void)
{
    fflush (outfp);
    ctl.opened = 0;
}

static int
ctl_read (int32 *valp)
{
    if (valp)
	return (RC_NONE);
    return RC_NONE;
}

static int
cmsg (int type, int verbosity_level, const char *fmt, ...)
{
    va_list ap;
    int     flag_newline = 1;
    if ((type == CMSG_TEXT || type == CMSG_INFO || type == CMSG_LOAD ||
			    type == CMSG_WARNING || type == CMSG_TRACE) &&
	ctl.verbosity < verbosity_level)
	return 0;
    if (*fmt == '~') {
	flag_newline = 0;
	fmt++;
    }
    va_start (ap, fmt);
    if (!ctl.opened) {
	vfprintf (stderr, fmt, ap);
	if (flag_newline)
	    fprintf (stderr, "\n");
    }
    else {
	vfprintf (outfp, fmt, ap);
	if (flag_newline)
	    fprintf (outfp, "\n");
    }
    va_end (ap);
    if (!flag_newline)
	fflush (outfp);
    return 0;
}

static void
ctl_refresh (void)
{
}

static void
ctl_total_time (uint32 tt)
{
    uint32  mins, secs;
    if (ctl.trace_playing) {
	secs = tt / play_mode->rate;
	mins = secs / 60;
	secs -= mins * 60;
	fprintf (outfp, "Total playing time: %3d min %02d s\n", mins, secs);
    }
}

static void
ctl_master_volume (int mv)
{
    mv = 0;
}

static void
ctl_file_name (char *name)
{
    if (ctl.verbosity >= 0 || ctl.trace_playing) {
	if (play_mode->id_character == 'w' || play_mode->id_character == 'd')
	    fprintf (outfp, "Rendering %s\n", name);
	else fprintf (outfp, "Playing %s\n", name);
    }
}

static void
ctl_song_title (char *name) {
    if (/*ctl.verbosity >= 0 ||*/ ctl.trace_playing)
	fprintf (outfp, "Title: %s\n", name);
}

static void
ctl_author (char *name) {
    if (/*ctl.verbosity >= 0 ||*/ ctl.trace_playing)
	fprintf (outfp, "%s\n", name);
}

static void
ctl_current_time (uint32 ct)
{
    uint32  mins, secs;
    if (ctl.trace_playing) {
	secs = ct / play_mode->rate;
	mins = secs / 60;
	secs -= mins * 60;
	fprintf (outfp, "\r%3d:%02d", mins, secs);
	fflush (outfp);
    }
}

static void
ctl_note (int v)
{
    v = 0;
}

static void
ctl_program (int ch, int val, const char *name)
{
    ch = val = 0;
    name = 0;
}

static void
ctl_bank (int ch, int val, int var, const char *name)
{
    ch = val = var = 0;
    name = 0;
}

static void
ctl_volume (int ch, int val)
{
    ch = val = 0;
}

static void
ctl_expression (int ch, int val)
{
    ch = val = 0;
}

static void
ctl_panning (int ch, int val)
{
    ch = val = 0;
}

static void
ctl_sustain (int ch, int val, int letter)
{
    ch = val = letter = 0;
}

static void
ctl_pitch_bend (int ch, int val, uint32 mod)
{
    mod = ch = val = 0;
}

static void
ctl_reset (void)
{
}

static void
ctl_redo (void)
{
}

static void
ctl_keysig(int k, int ko)
{
#ifdef tplus
	static int8 lastkeysig = CTL_STATUS_UPDATE;
	static int lastoffset = CTL_STATUS_UPDATE;
	static const char *keysig_name[] = {
		"Cb", "Gb", "Db", "Ab", "Eb", "Bb", "F ", "C ",
		"G ", "D ", "A ", "E ", "B ", "F#", "C#", "G#",
		"D#", "A#"
	};
	int i, j;
	
	if (k == CTL_STATUS_UPDATE)
		k = lastkeysig;
	else
		lastkeysig = k;
	if (ko == CTL_STATUS_UPDATE)
		ko = lastoffset;
	else
		lastoffset = ko;
	i = k + ((k < 8) ? 7 : -6);
	if (ko > 0)
		for (j = 0; j < ko; j++)
			i += (i > 10) ? -5 : 7;
	else
		for (j = 0; j < abs(ko); j++)
			i += (i < 7) ? 5 : -7;
	cmsg (CMSG_INFO, VERB_VERBOSE, "Key signature %s %s (%+03d) ",
			keysig_name[i], (k < 8) ? "Maj" : "Min", ko);
#endif
}

static void
ctl_tempo(int t, int tr)
{
#ifdef tplus
	static int lasttempo = CTL_STATUS_UPDATE;
	static int lastratio = CTL_STATUS_UPDATE;
	
	if (t == CTL_STATUS_UPDATE)
		t = lasttempo;
	else
		lasttempo = t;
	if (tr == CTL_STATUS_UPDATE)
		tr = lastratio;
	else
		lastratio = tr;
	t = (int) (500000 / (double) t * 120 * (double) tr / 100 + 0.5);
	cmsg (CMSG_INFO, VERB_VERBOSE, "Tempo %3d (%03d %%) ", t, tr);
#endif
}

static void
ctl_timesig(int n, int d, int c, int b)
{
    cmsg(CMSG_INFO, VERB_VERBOSE,
	      "Time signature: %d/%d %d clock %d q.n.", n, 1<<d, c, b);
}

static void
ctl_misc_controller(int ch, int val, int col, int letter, int use_color)
{
    ch = val = col = letter = use_color = 0;
}
