/* 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 #include #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 \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; }