/* GKrellM
|  Copyright (C) 1999-2000 Bill Wilson
|
|  Author:  Bill Wilson    bill@gkrellm.net
|  Latest versions might be found at:  http://gkrellm.net
|
|  This program is free software which I release under the GNU General Public
|  License. You may redistribute and/or modify this program under the terms
|  of that 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.
|
|  To get a copy of the GNU General Puplic License,  write to the
|  Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

/* Seti@home plugin for GKrellM
|
|  Copyright (C) 2000  Henry Palonen
|
|  Author:  Henry Palonen		h yty dot net
*/

/* Simple seti@home client monitor. See www.setiathome.com for details about
|  seti@home effort. Basicaly we are trying to find extraterrestial
|  intelligence ;)
|  
|  Plugin is based to Bill Wilson's great work, GKrellM & meminfo.c & template.c files.
|
|  Latest versions might be found from http://www.yty.net/h/gkrellm
*/

/* If this file is compiled as a shared object file and installed in
|  in your ~/.gkrellm/plugins directory, then it will be loaded when
|  gkrellm starts up.
|
|     gcc -fPIC `gtk-config --cflags` `imlib-config --cflags-gdk` -c seti.c
|     gcc -shared -Wl -o seti.so seti.o
|     cp seti.so ~/.gkrellm/plugins
*/ 

/*
|  Starting code, finally ;)
*/

#include "../gkrellm.h"
#include <utime.h>
#include <dirent.h>


#define PIPE_SIZE	4

static Panel	*seti;	
static gchar 	*seti_file_path;
static gint	seti_pipe[PIPE_SIZE];

typedef struct
        {
        gchar   *command;
        FILE    *pipe;
        gint    timeout;
        gint    messages;
        gint    new;
        gint    seen;
        }
        Setiproc;

static Decal    *seti_label_decal;
static Decal    *seti_icon_decal;
static Setiproc         seti_user_agent;
static gint             seti_prog_state;

/*
 *	Updating krell
 */

void
update_seti(void)
	{
	FILE	*f;
	gchar	buf[160];
	gdouble lprogress;

	gchar 	hjuu[10];
	gfloat 	daa;

	Krell	*krell;

	krell = seti->krell;

/* It's enough to update once every ten seconds. It's actually too
|  often. Should be minute or so. But then there should be a call which 
|  updates krell with "force" at startup so seti@home status is readable
|  right away. I worst case there would be one minute delay. Now delay is 10 secs max.
*/
	
	if (GK.ten_second_tick)
		{

		/* File format is something with
		|
	  	|  prog=0.2355233
		|
		|  line on it.
	 	*/

		if ((f = fopen(seti_file_path, "r")) != NULL)
			{
			while ((fgets(buf, sizeof(buf), f)) != NULL)
				{
				if (strncmp(buf, "prog", 4) == 0)
					{
					sscanf(buf,"prog=%lg",
						 &lprogress);
					if (GK.debug) 
						printf("setiprogress %g \n", lprogress);
	
					lprogress = lprogress * 100;
					krell->full_scale = 100;
					krell->previous = 0;
					gkrellm_update_krell(seti, seti->krell, lprogress);
					gkrellm_draw_layers(seti);
					}
				}
			fclose(f);
			}
		}


	}	


static void
pipe_command(Setiproc *mp)
        {
        gchar   buf[128];

        if (mp->command == NULL || *(mp->command) == '\0')
                return;
        snprintf(buf, sizeof(buf), "%s 1>ls.txt", mp->command);
        if (GK.debug)
                printf("pipe_command: %s\n", buf);
        if ((mp->pipe = popen(buf, "r")) == NULL)
                return;
        fcntl(fileno(mp->pipe), F_SETFL, O_NONBLOCK);
        }


/* User has clicked panel. We should try to start/stop seti@home software */

static gint
seti_panel_click(GtkWidget *widget, GdkEventButton *ev)
        {

        if (ev->button == 1)
                {
                if (GK.debug)
			printf("Right click on seti@home. Will try to start/stop software\n");
		
		if (seti_prog_state)
			{
			seti_user_agent.command = g_strdup("killall -STOP setiathome");
			seti_prog_state=0;
			}
		else
			{
			seti_user_agent.command = g_strdup("killall -CONT setiathome");
			seti_prog_state=1;
			}

		pipe_command(&seti_user_agent);
		}
	}

static gint
seti_expose_event (GtkWidget *widget, GdkEventExpose *event)
	{
	if (widget == seti->drawing_area)
		{
		gdk_draw_pixmap(widget->window,
				widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
				seti->pixmap,
				event->area.x, event->area.y,
				event->area.x, event->area.y,
				event->area.width, event->area.height);
		}
	return FALSE;
	}


/*
 *	Creating seti-monitor
 */

void
create_seti(GtkWidget *vbox)
	{
	Style		*style;
	GdkImlibImage   *bg_image;

#ifdef USE_FS_STYLE_WHICH_MAY_SHOW_A_DIFF_ONLY_IN_THE_DEFAULT_THEME
#define MY_STYLE        FS_STYLE
#else
#define MY_STYLE        DEFAULT_STYLE
#endif

        /* Allocate a panel structure.  plug->label and plug->textstyle
        |  structures will also be allocated...
        */

	seti = gkrellm_panel_new0();

	style = GK.meter_style[MY_STYLE];
	gkrellm_create_krell(GK.krell_meter_image[MY_STYLE], &seti->krell, style);
	
    	gkrellm_default_textstyle(seti->textstyle, TEXTSTYLE_METER, style);
	
	gkrellm_configure_panel(seti, "Seti", style);

	bg_image = gkrellm_bg_meter_image(MY_STYLE);
	gkrellm_create_panel(vbox, seti, bg_image);

    	gkrellm_monitor_height_adjust(seti->h);

	/* Signals used to handle backing pixmap
	*/
	gtk_signal_connect(GTK_OBJECT (seti->drawing_area), "expose_event",
			(GtkSignalFunc) seti_expose_event, NULL);
	
	gtk_signal_connect(GTK_OBJECT(seti->drawing_area),"button_release_event",
                        (GtkSignalFunc) seti_panel_click, NULL);

	}

/*
 *	Configuration page
 *	Configuration contains path to 'state.txt'
 */

static GtkWidget                *seti_path_entry;
static gchar			*seti_info_text =
"Seti@home progress meter shows current progress in \n"
"seti-workunit.\n\n"
"Progress value is read every ten seconds from \n"
"'state.txt' file. User can change the filename\n"
"using 'File location' tab.\n\n"
"File is parsed for line 'prog=0.nnnnnnn' and\n"
"that value is simply converted to krell movement.\n\n"
"Copyright 2000, Henry Palonen <h yty dot net>\n"
"http://www.yty.net/h/gkrellm";

static void
create_seti_tab(GtkWidget *tab_vbox)
        {
        GtkWidget               *hbox;
        GtkWidget               *label;
	GtkWidget		*vbox;
	GtkWidget		*tabs;
        GtkWidget               *text;
        GtkWidget               *scrolled;

        tabs = gtk_notebook_new();
        gtk_notebook_set_tab_pos(GTK_NOTEBOOK(tabs), GTK_POS_TOP);
        gtk_box_pack_start(GTK_BOX(tab_vbox), tabs, TRUE, TRUE, 0);

/* File location tab */

        vbox = create_tab(tabs, "File location");
        seti_path_entry = gtk_entry_new_with_max_length(255);
        gtk_box_pack_start(GTK_BOX(vbox), seti_path_entry, FALSE, FALSE, 2);
        gtk_entry_set_text(GTK_ENTRY(seti_path_entry), seti_file_path);

/* Info tab */

        vbox = create_tab(tabs, "Info");
        scrolled = gtk_scrolled_window_new(NULL, NULL);
        gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
                        GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
        gtk_box_pack_start(GTK_BOX(vbox), scrolled, TRUE, TRUE, 0);
        text = gtk_text_new(NULL, NULL);
        gtk_text_insert(GTK_TEXT(text), NULL, NULL, NULL, seti_info_text, -1);
        gtk_text_set_editable(GTK_TEXT(text), FALSE);
        gtk_container_add(GTK_CONTAINER(scrolled), text);

        }

/*
 *	Saving config
 */

static void
save_seti_config(FILE *f)
        {
        fprintf(f, "seti filename %s\n", seti_file_path);
        }

/*
 *  Loading config
 */

static void
load_seti_config(gchar *arg)
        {
        gchar   seti_config[64], item[256];
        gint    n;

        n = sscanf(arg, "%s %[^\n]", seti_config, item);

        if (n == 2)
                {
                if (GK.debug)
                        printf("seti_config=%s item=<%s>\n", seti_config, item);
                if (strcmp(seti_config, "filename") == 0)
                        seti_file_path = g_strdup(item);
                }
        }

/*
 *	Applying config.
 *	This includes only updating seti_file_path variable.
 */

static void
apply_seti_config()
	{
        gchar                  *s;

       	s = gtk_entry_get_text(GTK_ENTRY(seti_path_entry));

        if (strcmp(s, seti_file_path))
                {
//                g_free(seti_file_path);
                seti_file_path = g_strdup(s);
                }
	}


static Monitor  plugin_mon      =
        {
        "Seti",               		/* Name, for config tab.    */
        0,                              /* Id,  0 if a plugin       */
        create_seti,          		/* The create function      */
        update_seti,          		/* The update function      */
        create_seti_tab,                /* The config tab create function   */
        apply_seti_config,              /* Apply the config function        */
        save_seti_config,               /* Save user config */
        load_seti_config,               /* Load user config */
        "seti",                         /* config keyword */
        NULL,                           /* Undefined 2  */
        NULL,                           /* Undefined 1  */
        NULL,                           /* Undefined 0  */
        0, 0,                           /* pre-spacer, post_spacer  */
        MON_APM,                        /* Insert plugin before this monitor */
        NULL,                           /* Handle if a plugin, filled in by GKrellM     */
        NULL                            /* path if a plugin, filled in by GKrellM       */
        };


Monitor *
init_plugin()
        {
	seti_file_path = "/home/luser/setiathome/state.txt";
        return &plugin_mon;
        }
