1 /*
2 gkrellflynn.c
3
4 author: Henryk Richter
5
6 last update: Tue May 7 2002
7
8 purpose: just an addon toy for gkrellm
9
10 changelog:
11 0.5 - port to GKrellm 2.0 (thanks to Bill Nalen)
12 - port to Win32 (thanks to Bill Nalen)
13 - kept the code downwards compatible
14
15 0.4 - port to GKrellm 1.2.x
16
17 0.3 - stops /proc/stat parsing after the first found cpu line,
18 shows better results on SMP machines
19
20 0.2 - minor cleanups, about box
21
22 0.1 - initial version
23
24 */
25 #ifndef WIN32
26
27 /* see makefile */
28 #ifdef GKRELLM2
29 #include <gkrellm2/gkrellm.h>
30 #else /* GKRELLM2 */
31 #include <gkrellm/gkrellm.h>
32 #endif /* GKRELLM2 */
33
34 #include <sys/time.h>
35 #include <sys/wait.h>
36
37 #else /* WIN32 */
38
39 #include <src/gkrellm.h>
40 #include <src/win32-plugin.h>
41
42 #endif /* WIN32 */
43
44
45 #include <stdlib.h>
46
47 #define FLYNN_MAJOR_VERSION 0
48 #define FLYNN_MINOR_VERSION 5
49
50 #include "flynn.picture_alpha_big.xpm"
51 #define STYLE_NAME "flynn"
52
53 #define HEIGHT 74
54 #define IMAGE_WIDTH 48
55 #define IMAGE_HEIGHT 64
56 #define IMAGE_COUNT 27
57
58 /* 3 different directions to look */
59 #define F_LOOKSTATES 3
60 /* 2 extra states (strength, grin) */
61 #define F_EXTRASTATE1 3
62 #define F_EXTRASTATE2 4
63 /* 5 torture variants per state */
64 #define F_TORTURES 5
65
66 #define GRIN_TIME 3
67
68 #if GKRELLM_VERSION_MAJOR < 2
69 static Panel *panel;
70 static Decal *flynn = NULL;
71 #else
72 static GkrellmPanel *panel;
73 static GkrellmDecal *flynn = NULL;
74 static GkrellmMonitor *monitor;
75 #endif
76
77 static gint style_id;
78 static GdkPixmap *flynn_image = NULL;
79 static GdkBitmap *flynn_mask = NULL;
80 static int dogrin = 0;
81
82 /* config stuff */
83 #define PLUGIN_CONFIG_KEYWORD "FlynnA"
84 static GtkWidget *nice_checkbutton;
85 static int nice_checkdisable = 0;
86 static GtkWidget *term_checkbutton;
87 static int term_checkdisable = 0;
88
89 static GtkWidget *commandline_entry;
90 static gchar command_line[256];
91 static GtkWidget *terminal_entry;
92 static gchar terminal_command_line[256];
93 static int child_started = 0;
94
flynn_apply_config(void)95 void flynn_apply_config(void)
96 {
97 nice_checkdisable = GTK_TOGGLE_BUTTON(nice_checkbutton)->active;
98 term_checkdisable = GTK_TOGGLE_BUTTON(term_checkbutton)->active;
99 strncpy(command_line, gtk_entry_get_text(GTK_ENTRY(commandline_entry)), 255);
100 strncpy(terminal_command_line, gtk_entry_get_text(GTK_ENTRY(terminal_entry)), 255);
101 }
102
flynn_save_config(FILE * f)103 static void flynn_save_config(FILE *f)
104 {
105 fprintf(f, "%s exclude_nice %d\n", PLUGIN_CONFIG_KEYWORD,nice_checkdisable);
106 fprintf(f, "%s command_line %s\n", PLUGIN_CONFIG_KEYWORD,command_line);
107 fprintf(f, "%s run_in_term %d\n", PLUGIN_CONFIG_KEYWORD,term_checkdisable);
108 fprintf(f, "%s terminal_command %s\n", PLUGIN_CONFIG_KEYWORD,terminal_command_line);
109 }
110
flynn_load_config(gchar * arg)111 static void flynn_load_config (gchar *arg)
112 {
113 gchar config[64], item[256];
114 gint n;
115
116 n = sscanf(arg, "%s %[^\n]", config, item);
117 if (n != 2)
118 return;
119
120 if (strcmp(config, "exclude_nice") == 0 )
121 sscanf(item, "%d\n", &nice_checkdisable);
122 if (strcmp(config, "command_line") == 0 )
123 strncpy(command_line,item,255);
124 if (strcmp(config, "run_in_term") == 0 )
125 sscanf(item, "%d\n", &term_checkdisable);
126 if (strcmp(config, "terminal_command") == 0 )
127 strncpy(terminal_command_line,item,255);
128 }
129
130 /* get current cpu usage */
getcpu(void)131 int getcpu( void )
132 {
133 float scale_factor = 1;
134 #if 0
135 FILE * fin;
136 char buffer[256];
137 char tokens[4] = " \t\n";
138 #endif
139
140 static long last_user = 0;
141 static long last_nice = 0;
142 static long last_sys = 0;
143 static long last_idle = 0;
144
145 long user=0, nice=0, sys=0, idle=0, total=0;
146 long d_user, d_nice, d_sys, d_idle;
147 float cpu_use;
148 float percent;
149
150 gkrellm_cpu_stats(0, &user, &nice, &sys, &idle);
151
152 #if 0
153 if ( (fin = fopen("/proc/stat", "r")) == NULL ) {
154 return(0);
155 }
156
157 while ( fgets(buffer, 256, fin) ) {
158 if ( strstr(buffer,"cpu") != NULL ) {
159 strtok(buffer,tokens);
160 user = atol(strtok(NULL,tokens));
161 nice = atol(strtok(NULL,tokens));
162 sys = atol(strtok(NULL,tokens));
163 idle = atol(strtok(NULL,tokens));
164
165 break;
166 }
167 }
168
169 fclose (fin);
170 #endif
171
172 d_user = user - last_user;
173 d_nice = nice - last_nice;
174 d_sys = sys - last_sys;
175 d_idle = idle - last_idle;
176
177 last_user = user;
178 last_nice = nice;
179 last_sys = sys;
180 last_idle = idle;
181
182 total = d_user + d_sys + d_nice + d_idle;
183 if( nice_checkdisable == 1 )
184 d_idle += d_nice;
185
186 if ( total < 1 )
187 total = 1.0;
188
189 cpu_use = 1.0 - ( (float) d_idle / (float) total );
190 #if 0
191 printf(" CPU (/proc/stat): %5.2f ", cpu_use);
192 printf(" (jiffies: user:%ld nice:%ld system:%ld idle:%ld total:%ld)\n",
193 d_user, d_nice, d_sys, d_idle, total );
194 #endif
195 percent = cpu_use / scale_factor;
196 if ( percent > .999999 )
197 percent = .999999;
198
199 return ( (int)(percent*100) );
200 }
201
202
update_plugin()203 static void update_plugin()
204 {
205 static int image_number = 0;
206 static int flynn_look = 0;
207 int dir;
208 int percent;
209
210 /* first check looking direction */
211 #if GKRELLM_VERSION_MAJOR < 2
212 if( GK.second_tick )
213 #else
214 if( gkrellm_ticks()->second_tick )
215 #endif
216 {
217 /* catch exiting childs if any (no semaphore used, gkrellm is synchronous) */
218 #ifndef WIN32
219 if( child_started > 0 )
220 {
221 if( waitpid( -1, NULL, WNOHANG ) > 0 )
222 child_started--;
223 }
224 #endif
225 if( dogrin > 0 )
226 {
227 dogrin--;
228 flynn_look = F_EXTRASTATE2;
229 }
230 else
231 {
232 dir = (int)( (float)F_LOOKSTATES * (float)rand() / (RAND_MAX+1.0));
233 switch( dir )
234 {
235 case 0:
236 break;
237 case 1:
238 flynn_look++;
239 break;
240 case 2:
241 flynn_look--;
242 break;
243 default:
244 break;
245 }
246 if( flynn_look < 0 ) flynn_look = 0;
247 if( flynn_look >= F_LOOKSTATES ) flynn_look = F_LOOKSTATES-1;
248 }
249 percent = getcpu();
250
251 image_number = flynn_look * F_TORTURES + (F_TORTURES * percent / 100);
252
253 /*printf("%d\n",image_number);*/
254 }
255
256
257 /* draw determined frame */
258 gkrellm_draw_decal_pixmap(panel, flynn, image_number);
259 #if GKRELLM_VERSION_MAJOR < 2
260 gkrellm_draw_layers(panel);
261 #else
262 gkrellm_draw_panel_layers(panel);
263 #endif
264 }
265
panel_expose_event(GtkWidget * widget,GdkEventExpose * ev)266 static gint panel_expose_event(GtkWidget *widget, GdkEventExpose *ev)
267 {
268 gdk_draw_pixmap(widget->window,
269 widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
270 panel->pixmap, ev->area.x, ev->area.y, ev->area.x, ev->area.y,
271 ev->area.width, ev->area.height);
272 return FALSE;
273 }
274
panel_click_event(GtkWidget * widget,GdkEventExpose * ev)275 static gint panel_click_event(GtkWidget *widget, GdkEventExpose *ev)
276 {
277 gchar* argv[32];
278 gchar localcmd[256];
279 int i;
280 pid_t pid;
281
282 dogrin = GRIN_TIME;
283
284 /* check for command line */
285 if (strlen(command_line) == 0) return FALSE;
286
287 child_started++;
288
289 /* forkint status */
290 pid = fork();
291 if (pid == 0)
292 {
293 /* this is the child process - setup */
294 i=0;
295 memset(localcmd,0,256);
296 /* check for "run in terminal" option */
297 if (term_checkdisable)
298 {
299 strcpy(localcmd,terminal_command_line);
300 }
301 /* create command line */
302 strncat(localcmd,command_line,255);
303 /* separate command line into argument array */
304 argv[i] = strtok(localcmd," ");
305 while (argv[i++] != NULL)
306 {
307 argv[i] = strtok(NULL," ");
308 }
309 /* exec child process */
310 /* execv(argv[0],argv); */
311 execvp(argv[0],argv);
312 _exit(EXIT_FAILURE);
313 }
314
315 return FALSE;
316 }
317
load_images()318 static void load_images()
319 {
320 #if GKRELLM_VERSION_MAJOR < 2
321 static GdkImlibImage *image = NULL;
322
323 gkrellm_load_image(NULL, flynn_xpm, &image, NULL);
324 gkrellm_render_to_pixmap(image, &flynn_image, &flynn_mask, 0, 0);
325 #else
326 static GkrellmPiximage *image = NULL;
327 gkrellm_load_piximage(NULL, flynn_xpm, &image, NULL);
328 gkrellm_scale_piximage_to_pixmap(image, &flynn_image, &flynn_mask, 0, 0);
329 #endif
330 }
331
create_plugin(GtkWidget * vbox,gint first_create)332 static void create_plugin(GtkWidget *vbox, gint first_create)
333 {
334 #if GKRELLM_VERSION_MAJOR < 2
335 Style *style = NULL;
336 #else
337 GkrellmStyle *style = NULL;
338 #endif
339
340 int image_x_offset;
341 int image_y_offset;
342
343 load_images();
344
345 if (first_create)
346 {
347 panel = gkrellm_panel_new0();
348 }
349 else
350 gkrellm_destroy_decal_list(panel);
351
352 style = gkrellm_meter_style(style_id);
353
354 image_x_offset = (gkrellm_chart_width() - IMAGE_WIDTH) / 2;
355 image_y_offset = (HEIGHT - IMAGE_HEIGHT) / 2;
356
357 flynn = gkrellm_create_decal_pixmap(panel, flynn_image, flynn_mask,
358 IMAGE_COUNT,
359 style, image_x_offset, image_y_offset);
360
361 panel->textstyle = gkrellm_meter_textstyle(style_id);
362 panel->label->h_panel = HEIGHT;
363
364 #if GKRELLM_VERSION_MAJOR < 2
365 gkrellm_create_panel(vbox, panel, gkrellm_bg_meter_image(style_id));
366 gkrellm_monitor_height_adjust(panel->h);
367 #else
368 gkrellm_panel_configure(panel, "", style);
369 gkrellm_panel_create(vbox, monitor, panel);
370 #endif
371
372 if (first_create)
373 {
374 gtk_signal_connect(GTK_OBJECT(panel->drawing_area),
375 "expose_event", (GtkSignalFunc) panel_expose_event,
376 NULL);
377 gtk_signal_connect(GTK_OBJECT(panel->drawing_area),
378 "button_press_event", (GtkSignalFunc) panel_click_event,
379 NULL);
380 }
381
382 gkrellm_draw_decal_pixmap(panel, flynn, 1 );
383
384 #if GKRELLM_VERSION_MAJOR < 2
385 gkrellm_draw_layers(panel);
386 #else
387 gkrellm_draw_panel_layers(panel);
388 #endif
389
390
391
392 }
393
flynn_create_plugin_tab(GtkWidget * tab_vbox)394 static void flynn_create_plugin_tab(GtkWidget *tab_vbox)
395 {
396 GtkWidget *tabs;
397 GtkWidget *vbox,*vbox1,*vbox2;
398 GtkWidget *frame, *commandframe;
399
400 tabs = gtk_notebook_new();
401 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(tabs), GTK_POS_TOP);
402 gtk_box_pack_start(GTK_BOX(tab_vbox), tabs, TRUE, TRUE, 0);
403
404 /* Config TAB */
405 {
406 {
407 #if GKRELLM_VERSION_MAJOR < 2
408 vbox = gkrellm_create_tab(tabs, _("Config"));
409 #else
410 vbox = gkrellm_gtk_framed_notebook_page(tabs, _("Config"));
411 #endif
412
413 frame = gtk_frame_new(_("CPU time Calculations"));
414 gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 5);
415 vbox1 = gtk_vbox_new (FALSE, 2);
416 gtk_container_add(GTK_CONTAINER(frame), vbox1);
417
418 commandframe = gtk_frame_new(_("Command Line (program executed on click)"));
419 gtk_box_pack_start(GTK_BOX(vbox), commandframe, TRUE, TRUE, 5);
420 vbox2 = gtk_vbox_new (FALSE, 2);
421 gtk_container_add(GTK_CONTAINER(commandframe), vbox2);
422
423 #if GKRELLM_VERSION_MAJOR < 2
424 gkrellm_check_button(vbox1, &nice_checkbutton, nice_checkdisable, FALSE, 0,
425 "Exclude Nice time from calculations");
426 #else
427 {
428 gchar *label = _("Exclude Nice time from calculations");
429 gkrellm_gtk_check_button_connected(vbox1, &nice_checkbutton, nice_checkdisable, FALSE, 0,0,
430 flynn_apply_config,
431 NULL,
432 label);
433 }
434 #endif
435 }
436
437 /* Set up command line text box */
438 commandline_entry = gtk_entry_new();
439 gtk_entry_set_text(GTK_ENTRY(commandline_entry),command_line);
440 gtk_box_pack_start (GTK_BOX(vbox2), commandline_entry, FALSE, TRUE, 0);
441 g_signal_connect(G_OBJECT(commandline_entry),"changed",
442 G_CALLBACK(flynn_apply_config),NULL);
443
444 /* Set up run in terminal checkbox */
445 #if GKRELLM_VERSION_MAJOR < 2
446 gkrellm_check_button(vbox2, &term_checkbutton, term_checkdisable, FALSE, 0,
447 "Run in Terminal");
448 #else
449 {
450 gchar *label = _("Run in Terminal");
451 gkrellm_gtk_check_button_connected(vbox2, &term_checkbutton, term_checkdisable, FALSE, 0,0,
452 flynn_apply_config,
453 NULL,
454 label);
455 }
456 #endif
457 terminal_entry = gtk_entry_new();
458 gtk_entry_set_text(GTK_ENTRY(terminal_entry),terminal_command_line);
459 gtk_box_pack_start (GTK_BOX(vbox2), terminal_entry, FALSE, TRUE, 0);
460 g_signal_connect(G_OBJECT(terminal_entry),"changed",
461 G_CALLBACK(flynn_apply_config),NULL);
462
463
464
465 }
466
467 /* ABOUT TAB */
468 {
469 gchar *plugin_about_text;
470 GtkWidget *label, *text;
471
472 plugin_about_text = g_strdup_printf(
473 "GKrellFlynn %d.%d\n"
474 "GKrellM Load Meter Plugin\n\n"
475 "(C) 2001 Henryk Richter\n"
476 "<buggs@comlabien.net>\n"
477 "http://horus.comlabien.net/flynn\n\n"
478 "Released under the GNU General Public License",
479 FLYNN_MAJOR_VERSION, FLYNN_MINOR_VERSION);
480
481 text = gtk_label_new(plugin_about_text);
482 label = gtk_label_new("About");
483 gtk_notebook_append_page(GTK_NOTEBOOK(tabs),text,label);
484 g_free(plugin_about_text);
485 }
486
487 }
488
489 #if GKRELLM_VERSION_MAJOR < 2
490 static Monitor plugin_mon =
491 #else
492 static GkrellmMonitor plugin_mon =
493 #endif
494 {
495 "Flynn", /* Name, for config tab. */
496 0, /* Id, 0 if a plugin */
497 create_plugin, /* The create_plugin() function */
498 update_plugin, /* The update_plugin() function */
499 flynn_create_plugin_tab, /* The create_plugin_tab() config function */
500 flynn_apply_config, /* The apply_plugin_config() function */
501
502 flynn_save_config, /* The save_plugin_config() function */
503 flynn_load_config, /* The load_plugin_config() function */
504 PLUGIN_CONFIG_KEYWORD, /* config keyword */
505
506 NULL, /* Undefined 2 */
507 NULL, /* Undefined 1 */
508 NULL, /* Undefined 0 */
509
510 MON_INSERT_AFTER|MON_CLOCK, /* Insert plugin before this monitor. */
511 NULL, /* Handle if a plugin, filled in by GKrellM */
512 NULL /* path if a plugin, filled in by GKrellM */
513 };
514
515 #if GKRELLM_VERSION_MAJOR < 2
init_plugin(void)516 Monitor * init_plugin(void)
517 #else
518 #ifdef WIN32
519 __declspec(dllexport) GkrellmMonitor *
520 gkrellm_init_plugin(win32_plugin_callbacks* calls)
521 #else
522 GkrellmMonitor *
523 gkrellm_init_plugin()
524 #endif
525 #endif
526 {
527 #if GKRELLM_VERSION_MAJOR < 2
528 style_id = gkrellm_add_meter_style(&plugin_mon, STYLE_NAME);
529 #else
530 #if defined(WIN32)
531 callbacks = calls;
532 pwin32GK = calls->GK;
533 #endif
534 style_id = gkrellm_add_meter_style(&plugin_mon, STYLE_NAME);
535 monitor = &plugin_mon;
536 #endif
537
538 /* set defaults */
539 strcpy( terminal_command_line, "/usr/bin/gnome-terminal -x " );
540
541 return &plugin_mon;
542 }
543
544