
#include <config.h>
#include <applet-widget.h>
#include "quickrecord_applet.h"

/* Globals: */
GtkWidget *label=NULL;
GtkStyle *redstyle=NULL;
GtkStyle *graystyle=NULL;
GtkStyle *blackstyle=NULL;


static void read_options(GtkWidget *applet, Properties *props);
static gchar *get_next_file(Properties *props);


/*************** CALLBACK FUNCTIONS: *****************/

/*
 * Pops up an about-box.
 */
static void about(AppletWidget *applet, gpointer data) {
	static GtkWidget *about_box = NULL;
	static const char *authors[] =
	{ "Sampo Niskanen <sampo.niskanen@iki.fi>", NULL };
	
	if (about_box != NULL) {
		gdk_window_show(about_box->window);
		gdk_window_raise(about_box->window);
		return;
	}
	about_box = gnome_about_new(
		_("Quick Record"), VERSION,
		_("Copyright (C) 2001 Sampo Niskanen"), authors,
		_("Quick one-click recording with optional prerecording "
		  "buffer for spontaneous recording."),
		NULL);
	gtk_signal_connect(GTK_OBJECT(about_box),"destroy",
			   GTK_SIGNAL_FUNC(gtk_widget_destroyed),&about_box);
	
	gtk_widget_show(about_box);
	return;
}


/*
 * Callback to be called when the applet is clicked. Starts/stops recording
 * and sets the label style accordingly.
 */
static void applet_clicked(GtkWidget *widget, GdkEventButton *ev,
			   gpointer data) {
	static GTimer *timer = NULL;
	Properties *props = (Properties*) data;
	static gchar *file;

	/* Disable accidental double-clicks */
	if (timer==NULL) {
		timer=g_timer_new();
		g_timer_start(timer);
	} else if (g_timer_elapsed(timer,NULL)<0.2)
		return;
	g_timer_reset(timer);

	if (recording) {
		record_stop_record();
		if (buffering)
			gtk_widget_set_style(label,blackstyle);
		else
			gtk_widget_set_style(label,graystyle);
	} else {
		file=get_next_file(props);
		if (file==NULL) {
			error_no_file();
			return;
		}
		if (record_start_record(file)) {
			gtk_widget_set_style(label,redstyle);
		}
	}
	return;
}

/*
 * Callback for menu->Toggle prerecording. Start/stop prerecording and
 * set the label style accordingly (if not recording).
 */
static void applet_toggle_prerec(AppletWidget *applet, gpointer data) {
	if (buffering) {
		record_stop_prerecord();
		if (!recording)
			gtk_widget_set_style(label,graystyle);
	} else {
		if (record_start_prerecord() && !recording)
			gtk_widget_set_style(label,blackstyle);
	}
	return;
}

/*
 * Save the applet configuration (options_xxx). Made to function as a
 * callback. Use applet_widget_sync_config(AppletWidget *applet) to save
 * the configuration. Reading the config is in helper functions, below.
 */
static gint applet_save_session(GtkWidget *w, const char *privcfgpath,
				const char *globcfgpath, gpointer data) {
	Properties *props = (Properties *)data;
	gchar buf[1000];

	gnome_config_push_prefix(privcfgpath);

	gnome_config_set_int("soundcfg/rate",props->rate);
	gnome_config_set_int("soundcfg/bits",props->bits);
	gnome_config_set_bool("soundcfg/stereo",props->stereo);
	gnome_config_set_bool("soundcfg/cd_source",props->source&REC_CD);
	gnome_config_set_bool("soundcfg/mic_source",props->source&REC_MIC);
	gnome_config_set_bool("soundcfg/line_source",props->source&REC_LINE);
	gnome_config_set_float("soundcfg/prerecord_amount",
			       props->prerec_amount);
	gnome_config_set_bool("soundcfg/prerecord",props->start_prerec);

	if (props->filestart<0) {
		gnome_config_set_string("filecfg/filename",props->filename);
	} else {
		snprintf(buf,900,props->filename,props->filestart);
		gnome_config_set_string("filecfg/filename",buf);
	}

	gnome_config_pop_prefix();

	gnome_config_sync();
	/* you need to use the drop_all here since we're all writing to
	 * one file, without it, things might not work too well */
	gnome_config_drop_all();
	
	/* Return FALSE, according to tutorial. */
	return FALSE;
}



/*
 * Main. Do the stuff, captain!
 */
int main(int argc, char **argv) {
	GtkWidget *applet;
	GtkWidget *box;
	GtkWidget *frame;
	gchar *applet_name = "quickrecord_applet";
	Properties *props;

	bindtextdomain(PACKAGE, GNOMELOCALEDIR);
	textdomain(PACKAGE);
	applet_widget_init(applet_name,VERSION,argc,argv,NULL,0,NULL);


	/* Create the applet - simple job. */
	applet=applet_widget_new(applet_name);
	/* in the rare case that the communication with the panel failed */
	if (!applet)
		g_error(_("Can't create applet!\n"));

	/* Create the widget inside the applet */
	box=gtk_event_box_new();
	gtk_widget_show(box);

	frame=gtk_aspect_frame_new(NULL,0.5,0.5,1,TRUE);
	gtk_container_add(GTK_CONTAINER(box),frame);
	gtk_widget_show(frame);

	label=gtk_label_new("REC");
	gtk_container_add(GTK_CONTAINER(frame),label);
	gtk_widget_show(label);

	/* Make the text styles */
	redstyle = gtk_style_copy(gtk_widget_get_default_style());
	graystyle = gtk_style_copy(gtk_widget_get_default_style());
	blackstyle = gtk_style_copy(gtk_widget_get_default_style());
	redstyle->fg[GTK_STATE_NORMAL].red   = 0xFFFF;
	redstyle->fg[GTK_STATE_NORMAL].green = 0x0000;
	redstyle->fg[GTK_STATE_NORMAL].blue  = 0x0000;
	graystyle->fg[GTK_STATE_NORMAL].red   = 0xA000;
	graystyle->fg[GTK_STATE_NORMAL].green = 0xA000;
	graystyle->fg[GTK_STATE_NORMAL].blue  = 0xA000;

	/* Set the default text style, gray (no prerec) - may be changed
	 * further on */
	gtk_widget_set_style(label,graystyle);


	/* Handle the recording options to sane values */
	props=g_new0(Properties,1);
	read_options(applet,props);
	record_set_options(props);

	if (props->start_prerec) {
		if (record_start_prerecord())
			gtk_widget_set_style(label,blackstyle);
	}


	/* Set the event handlers */
        gtk_widget_set_events(applet, gtk_widget_get_events(applet) |
			      GDK_BUTTON_PRESS_MASK);
        gtk_signal_connect(GTK_OBJECT(applet), "button_press_event",
			   GTK_SIGNAL_FUNC(applet_clicked), props);


	applet_widget_add(APPLET_WIDGET(applet),box);
	/* Yeah, we use props in the source but we mean prefs. */
	applet_widget_register_stock_callback(APPLET_WIDGET(applet),
					      "preferences",
					      GNOME_STOCK_MENU_PREF,
					      _("Preferences..."),
					      properties,props);
	applet_widget_register_callback(APPLET_WIDGET(applet),"toggleprerec",
					_("Toggle prerecording"),
					applet_toggle_prerec,NULL);
	applet_widget_register_stock_callback(APPLET_WIDGET(applet),
					      "about", GNOME_STOCK_MENU_ABOUT,
					      _("About..."), about, NULL);
	gtk_widget_show(applet);

	/* Set options to be saved on request. */
	gtk_signal_connect(GTK_OBJECT(applet),"save_session",
			   GTK_SIGNAL_FUNC(applet_save_session),
			   (gpointer)props);
	
	applet_widget_gtk_main();
	return EXIT_SUCCESS;
}



/*************** HELPER FUNCTIONS: ******************/

/*
 * Read options_xxx options from the gnome saved options.
 * Includes the default used if none are saved from a previous session.
 * Session saving is in the callback section.
 */
static void read_options(GtkWidget *applet, Properties *props) {
	gchar *c;
	gchar *def;

	gnome_config_push_prefix(APPLET_WIDGET(applet)->privcfgpath);
	props->rate=gnome_config_get_int("soundcfg/rate=44100");
	props->bits=gnome_config_get_int("soundcfg/bits=16");
	props->stereo=gnome_config_get_bool("soundcfg/stereo=FALSE");

	props->source=0;
	if (gnome_config_get_bool("soundcfg/line_source=FALSE"))
		props->source|=REC_LINE;
	if (gnome_config_get_bool("soundcfg/mic_source=FALSE"))
		props->source|=REC_MIC;
	if (gnome_config_get_bool("soundcfg/cd_source=FALSE"))
		props->source|=REC_CD;

	props->prerec_amount=
		gnome_config_get_float("soundcfg/prerecord_amount=5.0");
	props->start_prerec=gnome_config_get_bool("soundcfg/prerecord=FALSE");

	def=g_strconcat("filecfg/filename=",g_get_home_dir(),"/rec%03d.wav",
			NULL);
	c=gnome_config_get_string(def);
	parse_to_printf_string(props,c);
	g_free(def);

	gnome_config_pop_prefix();

	return;
}

/*
 * Returns a pointer to a static copy of the next suitable file, as defined
 * in props. The file is guaranteed not to exists.
 */
static gchar *get_next_file(Properties *props) {
	static gchar file[1000];
	gint i;
	FILE *fp;

	if (props->filestart<-1) {
		/* No %d in filename. */
		fp=fopen(props->filename,"rb");
		if (fp==NULL)
			return props->filename;
		fclose(fp);
		return NULL;
	}

	for (i=MAX(props->filestart,0); i<1000000; i++) {
		snprintf(file,990,props->filename,i);
		fp=fopen(file,"rb");
		if (fp==NULL)
			break;
		fclose(fp);
	}
	if (i>=1000000)
		return NULL;
	if (props->filestart>=0)
		props->filestart=i+1;
	return file;
}


