/* dump.c */

/* try out for the ``play routines''
 */


/* $Author: Espie $
 * $Date: 91/05/16 15:04:51 $
 * $Revision: 1.48 $
 * $Log:	dump.c,v $
 * Revision 1.48  91/05/16  15:04:51  Espie
 * *** empty log message ***
 * 
 * Revision 1.47  91/05/12  19:57:22  Espie
 * Corrected the loader's logic.
 * Change of behavior: release the audio.device briefly when
 * changing songs. That looks better after all (mixing albums, for
 * instance).
 * 
 * Revision 1.46  91/05/12  15:56:25  Espie
 * Tried to correct some snapshot problem, plus some more cleanup.
 * 
 * Revision 1.45  91/05/11  14:57:44  Espie
 * *** empty log message ***
 * 
 * Revision 1.44  91/05/10  00:02:56  Espie
 * Added albums, moved all iterator stuff to files.c
 * 
 * Revision 1.43  91/05/09  17:34:37  Espie
 * Support for wb icons added, more coherent song loading.
 * Default and specialized options added.
 * 
 * Revision 1.42  91/05/08  18:34:52  Espie
 * 
 * Details changed.
 * 
 * Revision 1.41  91/05/08  15:50:12  Espie
 * Moved wb stuff to files.c (new iterator project...).
 * 
 * Revision 1.40  91/05/07  02:53:02  Espie
 * Reads the cli defaults in player.config now.
 * 
 * Revision 1.39  91/05/06  23:33:08  Espie
 * Added more workbench support,
 * now supports tooltypes.
 * The new requester call gives back a WBArg-like
 * answer, everything gets simpler and simpler...
 * 
 * Revision 1.38  91/05/05  19:05:57  Espie
 * *** empty log message ***
 * 
 * Revision 1.37  91/05/05  15:37:45  Espie
 * Separated the play structure into a private/public parts...
 * More to come !
 * 
 * Revision 1.36  91/05/05  04:00:21  Espie
 * Added some support for workbench arguments.
 * 
 * Revision 1.35  91/05/03  02:48:39  Espie
 * *** empty log message ***
 * 
 * Revision 1.34  91/05/02  23:32:02  Espie
 * Simpler, more functional.
 * 
 * Revision 1.33  91/05/02  11:17:56  Espie
 * Simplified again !
 * Added test for loaded song, so that we don't request the audio hw for nothing.
 * Added lockout to prevent loading two songs at once.
 * Should ideally put a queue there, and handle wbargs for multiselects...
 * 
 * Revision 1.32  91/05/02  01:28:40  Espie
 * Dump is simpler than ever !
 * Does not try to handle the number of replays correctly...
 * 
 * Revision 1.31  91/05/01  00:50:06  Espie
 * Small bug fix: display->new_title.
 * 
 * Revision 1.30  91/04/30  16:51:35  Espie
 * New interface for changing titles (new titles erases the old one).
 * Suppressed every IO.
 * 
 * Revision 1.29  91/04/30  01:48:35  Espie
 * Cleaned up a bit what is still alive :-).
 * 
 * Revision 1.28  91/04/30  00:36:22  Espie
 * Stable version III.
 * 
 * Revision 1.27  91/04/30  00:23:11  Espie
 * Added more control for the file requester (now works from workbench).
 * 
 * Revision 1.26  91/04/29  23:53:28  Espie
 * New loader ``on the fly''.
 * Now, load.c needs some modifications.
 * 
 * Revision 1.25  91/04/29  15:05:58  Espie
 * ...still vanishing !
 * 
 * Revision 1.24  91/04/29  13:03:43  Espie
 * Interfaced to new audio_soft.
 * 
 * Revision 1.23  91/04/29  03:53:13  Espie
 * Vanishing program.
 * 
 * Revision 1.22  91/04/29  02:21:53  Espie
 * First attempt at an interface.
 * 
 * Revision 1.21  91/04/28  22:53:05  Espie
 * transpose added.
 * 
 * Revision 1.20  91/04/28  20:35:26  Espie
 * Small bug corrected (reset tempo at start of piece).
 * Looks more and more like a kludge, real player coming soon.
 * 
 * Revision 1.19  91/04/27  20:48:53  Espie
 * *** empty log message ***
 * 
 * Revision 1.18  91/04/27  16:45:38  Espie
 * Added crude priority control for tests.
 * 
 * Revision 1.17  91/04/27  04:02:16  Espie
 * Added auto-timing code, suppressed fastest speed
 * --> need to get more control on the speed
 * (one timing for the new_notes, another for the effects).
 * 
 * Revision 1.16  91/04/27  00:25:47  Espie
 * *** empty log message ***
 * 
 * Revision 1.15  91/04/26  16:29:54  Espie
 * See interrupt.c for changes indication.
 * 
 * Revision 1.14  91/04/24  16:10:19  Espie
 * Small changes, (missed a goto loop...)
 * 
 * Revision 1.13  91/04/24  15:24:58  Espie
 * Now dump works with lots of signal: from audio_soft, the player and the user.
 * Will write a real interface soon.
 * 
 * Revision 1.12  91/04/24  13:58:01  Espie
 * Added automatic version check.
 * 
 * Revision 1.11  91/04/23  21:27:58  Espie
 * Almost completely new logic. Demonstrates most commands of play.c,
 * uses new interrupts.
 * 
 * Revision 1.10  91/04/21  20:05:09  Espie
 * *** empty log message ***
 * 
 * Revision 1.9  91/04/21  12:11:35  Espie
 * Stable version, known as bunch II.
 * Also features ``right'' log description.
 * 
 * Revision 1.8  91/04/21  11:15:30  Espie
 * Added more comprehensive command line options 1/2:-)
 *
 * Revision 1.7  91/04/20  18:14:19  Espie
 *
 * Revision 1.6  91/04/19  13:21:56  Espie
 * Prototype for a real player, which waits for events,
 * and processes them.
 *
 * Revision 1.5  91/04/19  02:19:44  Espie
 * Simplified dump. Plays, and wait for ^C/^D.
 *
 * Revision 1.4  91/04/18  20:22:44  Espie
 * no big change in this file.
 *
 * Revision 1.3  91/04/18  02:25:51  Espie
 * bunch I.
 *
 * Revision 1.2  91/04/18  02:17:54  Espie
 * this version plays a module.
 * No commands implemented, just notes.
 * No interrupts, just sequence.
 *
 * Revision 1.1  91/04/17  18:51:13  Espie
 * Initial revision
 *
 */
 
#include <exec/types.h>
#include <dos/dos.h>
#include <workbench/startup.h>
#include <workbench/workbench.h>
#include <string.h>
#include <stddef.h>
#include <custom/cleanup.h>
#include <proto/exec.h>
#include <proto/icon.h>
#include <stdio.h>

#include "song.h"
#include "public_play.h"
#include "proto.h"

LONG _Stack = 4000;
char *_procname = "Experiment IV player";
LONG _priority = 0;
LONG _BackGroundIO = 0;


struct pub_play *play;

#define tstclr(mask, val) ( (mask) & (val) ? ( (mask) &= ~(val), TRUE) : FALSE)

/* quick and dirty... */

struct song *the_song;

int counter;


struct iterator *it;

/* to wade through several identifiers at once */

char *get_song_args(BOOL req)
	{
	char *result;
		while ((result = next_song(&it, req)) && is_info(result));
		return result;
	}
	
int def_volume, def_transpose, def_speed, def_mode, def_repeat;

char *mode_names[] = { "STD", "OLD", "NEW", NULL};
char *speed_names[] = {"PAL", "NTSC", "FAST", "SCAN", "SLOW", "NULL"};
char *file_names[] = {"UNKNOWN", "ALBUM"};

LOCAL void setup_the_song(struct song *new)
	{
		song_available(FALSE);
		unload_song(the_song);
		the_song = new;
		if (new)
			{
				new_title(0, the_song->info->length, the_song->title);
				setup_song(new);
				song_available(TRUE);
			}
		else
			no_title();
	}

LOCAL void change_song(char *arg, struct song *new)
	{
	char **tools;
	int speed, mode, transpose /*, volume, repeat */;
		tools = grab_tooltypes(it, arg);
/*		volume = get_arg(tools, "VOLUME", def_volume);
 */
		speed = map_arg(tools, "SPEED", speed_names, def_speed);
		mode = map_arg(tools, "MODE", mode_names, def_mode);
		transpose = get_arg(tools, "TRANSPOSE", def_transpose);
/*		repeat = get_arg(tools, "REPEAT", def_repeat);
 */
			/* modified repeat to def_repeat there */
		play->oneshot = def_repeat == 1;
		counter = def_repeat;
		play->signaled &= ~ON_END;
/*		pref_volume(volume);
 */
		pref_speed(speed);
		pref_mode(mode);
		play->transpose = transpose;
		(void)safe_unload_song();
		setup_the_song(new);
		launch_play(0);
	}

	
BOOL safe_unload_song(void)
	{
		if (the_song)
			{
				setup_the_song(NULL);
				return TRUE;
			}
		else
			return FALSE;
	}
	
BOOL safe_load_song(char *arg)
	{
	struct song *new;	
		new = load_song(arg);
		if (new)
			change_song(arg, new);
		else
			{
				if (load_error() < 0 && the_song)
					{
						safe_unload_song();
						new = load_song(arg);
						if (new)
							change_song(arg, new);
						else		
							return FALSE;
					}
				else
					return FALSE;
			}
		return TRUE;
	}
	
main(int argc, char *argv[])
	{
	int pri, xoffset, yoffset;
	char *arg;
		SetUpCleanUp(NIL);
		open_libraries();
		onbreak(nobreak);
		it = setup_arguments(argc, argv);
		
		pri = do_get_arg("PRIORITY", 0);
		def_repeat = do_get_arg("REPEAT", 0);
		xoffset = do_get_arg("X", 0);
		yoffset = do_get_arg("Y", 1);
		def_volume = do_get_arg("VOLUME", 100);
		def_transpose = do_get_arg("TRANSPOSE", 0);
		def_speed = do_map_arg("SPEED", speed_names, 0);
		def_mode = do_map_arg("MODE", mode_names, 0);		
		play = init_events(pri, xoffset, yoffset);
		pref_volume(def_volume);
		pref_speed(def_speed);
		pref_mode(def_mode);
		play->transpose = def_transpose;
		while (arg = get_song_args(FALSE))
			if (safe_load_song(arg))
				break;
		play->on_signal = ON_END|ON_COMMAND|ON_PATTERN|ON_PROBLEM|ON_BLIP;
		
		forever
			wait_abort();
	}

/* due to the file requester and check_abort, 
 * we might just invoke try_change_song() recursively.
 * lock_out insures that one invocation only can succeed.
 */

	 		
void try_change_song(void)
	{
	static BOOL lock_out = FALSE;
	char *arg;
		if (lock_out)
			return;
		lock_out = TRUE;
		do {
			if (!(arg = get_song_args(TRUE)))
				break;
			} while (!safe_load_song(arg));	
		lock_out = FALSE;
	}	


void add_some_songs(struct AppMessage *msg)
	{
		insert_args(&it, msg);
		try_change_song();
	}
	
void handle_player()
	{
		if (counter == 1)
			play->oneshot = TRUE;
		if tstclr(play->signaled, ON_PATTERN)
			update_title(play->pattern, the_song->info->length, the_song->title);
		if (tstclr(play->signaled, ON_END))
			{
				counter--;
				if (counter == 0)
					try_change_song();
			}
	}
