Two more fixes on compilation warnings.
[lxde/lxpanel.git] / src / plugins / cpufreq / cpufreq.c
1 /**
2 * CPUFreq plugin to lxpanel
3 *
4 * Copyright (C) 2009 by Daniel Kesler <kesler.daniel@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22 #include <sys/types.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <glib.h>
26 #include <glib/gi18n.h>
27
28 #include <string.h>
29
30 #include "panel.h"
31 #include "misc.h"
32 #include "private.h"
33
34 #include "dbg.h"
35
36 #define PROC_ICON PACKAGE_DATA_DIR "/images/cpufreq-icon.png"
37 #define SYSFS_CPU_DIRECTORY "/sys/devices/system/cpu"
38 #define SCALING_GOV "scaling_governor"
39 #define SCALING_AGOV "scaling_available_governors"
40 #define SCALING_AFREQ "scaling_available_frequencies"
41 #define SCALING_CUR_FREQ "scaling_cur_freq"
42 #define SCALING_SETFREQ "scaling_setspeed"
43 #define SCALING_MAX "scaling_max_freq"
44 #define SCALING_MIN "scaling_min_freq"
45
46
47 typedef struct {
48 GtkWidget *main;
49 GtkWidget *namew;
50 GtkTooltips *tip;
51 GList *governors;
52 GList *cpus;
53 int has_cpufreq;
54 char* cur_governor;
55 int cur_freq;
56 unsigned int timer;
57 gboolean remember;
58 } cpufreq;
59
60 typedef struct {
61 char *data;
62 cpufreq *cf;
63 } Param;
64
65 static void
66 get_cur_governor(cpufreq *cf){
67 FILE *fp;
68 char buf[ 100 ], sstmp [ 256 ];
69
70 snprintf(sstmp, sizeof(sstmp), "%s/%s", (char*)cf->cpus->data, SCALING_GOV);
71 if ((fp = fopen( sstmp, "r")) != NULL) {
72 if(cf->cur_governor)
73 {
74 g_free(cf->cur_governor);
75 cf->cur_governor = NULL;
76 }
77 if (fgets(buf, 100, fp))
78 {
79 buf[strlen(buf)-1] = '\0';
80 cf->cur_governor = strdup(buf);
81 }
82 fclose(fp);
83 }
84 }
85
86 static void
87 get_cur_freq(cpufreq *cf){
88 FILE *fp;
89 char buf[ 100 ], sstmp [ 256 ];
90
91 snprintf(sstmp, sizeof(sstmp), "%s/%s", (char*)cf->cpus->data, SCALING_CUR_FREQ);
92 if ((fp = fopen( sstmp, "r")) != NULL) {
93 if (fgets(buf, 100, fp))
94 {
95 buf[strlen(buf)-1] = '\0';
96 cf->cur_freq = atoi(buf);
97 }
98 fclose(fp);
99 }
100 }
101
102 /*static void
103 get_governors(cpufreq *cf){
104 FILE *fp;
105 GList *l;
106 char buf[ 100 ], sstmp [ 256 ], c, bufl = 0;
107
108 g_list_free(cf->governors);
109 cf->governors = NULL;
110
111 get_cur_governor(cf);
112
113 if(cf->cpus == NULL){
114 cf->governors = NULL;
115 return;
116 }
117 sprintf(sstmp,"%s/%s",cf->cpus->data, SCALING_AGOV);
118
119 if (!(fp = fopen( sstmp, "r"))) {
120 printf("cpufreq: cannot open %s\n",sstmp);
121 return;
122 }
123
124 while((c = fgetc(fp)) != EOF){
125 if(c == ' '){
126 if(bufl > 1){
127 buf[bufl] = '\0';
128 cf->governors = g_list_append(cf->governors, strdup(buf));
129 }
130 bufl = 0;
131 buf[0] = '\0';
132 }else{
133 buf[bufl++] = c;
134 }
135 }
136
137 fclose(fp);
138 }
139
140 static void
141 cpufreq_set_freq(GtkWidget *widget, Param* p){
142 FILE *fp;
143 char buf[ 100 ], sstmp [ 256 ];
144
145 if(strcmp(p->cf->cur_governor, "userspace")) return;
146
147 sprintf(sstmp,"%s/%s",p->cf->cpus->data, SCALING_SETFREQ);
148 if ((fp = fopen( sstmp, "w")) != NULL) {
149 fprintf(fp,"%s",p->data);
150 fclose(fp);
151 }
152 }
153
154 static GtkWidget *
155 frequency_menu(cpufreq *cf){
156 FILE *fp;
157 Param* param;
158 char buf[ 100 ], sstmp [ 256 ], c, bufl = 0;
159
160 sprintf(sstmp,"%s/%s",cf->cpus->data, SCALING_AFREQ);
161
162 if (!(fp = fopen( sstmp, "r"))) {
163 printf("cpufreq: cannot open %s\n",sstmp);
164 return 0;
165 }
166
167 GtkMenu* menu = GTK_MENU(gtk_menu_new());
168 GtkWidget* menuitem;
169
170 while((c = fgetc(fp)) != EOF){
171 if(c == ' '){
172 if(bufl > 1){
173 buf[bufl] = '\0';
174 menuitem = gtk_menu_item_new_with_label(strdup(buf));
175 gtk_menu_append (GTK_MENU_SHELL (menu), menuitem);
176 gtk_widget_show (menuitem);
177 param = g_new0(Param, 1);
178 param->data = strdup(buf);
179 param->cf = cf;
180 g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(cpufreq_set_freq), param);
181 g_object_weak_ref(G_OBJECT(menuitem), (GWeakNotify)g_free, param);
182 }
183 bufl = 0;
184 buf[0] = '\0';
185 }else{
186 buf[bufl++] = c;
187 }
188 }
189
190 fclose(fp);
191 return GTK_WIDGET(menu);
192 }*/
193
194 static void
195 get_cpus(cpufreq *cf)
196 {
197
198 const char *cpu;
199 char cpu_path[100];
200
201 GDir * cpuDirectory = g_dir_open(SYSFS_CPU_DIRECTORY, 0, NULL);
202 if (cpuDirectory == NULL)
203 {
204 cf->cpus = NULL;
205 printf("cpufreq: no cpu found\n");
206 return;
207 }
208
209 while ((cpu = g_dir_read_name(cpuDirectory)))
210 {
211 /* Look for directories of the form "cpu<n>", where "<n>" is a decimal integer. */
212 if ((strncmp(cpu, "cpu", 3) == 0) && (cpu[3] >= '0') && (cpu[3] <= '9'))
213 {
214 snprintf(cpu_path, sizeof(cpu_path), "%s/%s/cpufreq", SYSFS_CPU_DIRECTORY, cpu);
215
216 GDir * cpufreqDir = g_dir_open(SYSFS_CPU_DIRECTORY, 0, NULL);
217 if (cpufreqDir == NULL)
218 {
219 cf->cpus = NULL;
220 cf->has_cpufreq = 0;
221 break;
222 }
223
224 cf->has_cpufreq = 1;
225 cf->cpus = g_list_append(cf->cpus, strdup(cpu_path));
226 }
227 }
228 g_dir_close(cpuDirectory);
229 }
230
231 /*static void
232 cpufreq_set_governor(GtkWidget *widget, Param* p){
233 FILE *fp;
234 char buf[ 100 ], sstmp [ 256 ];
235
236 sprintf(sstmp, "%s/%s", p->cf->cpus->data, SCALING_GOV);
237 if ((fp = fopen( sstmp, "w")) != NULL) {
238 fprintf(fp,"%s",p->data);
239 fclose(fp);
240 }
241 }
242
243 static GtkWidget *
244 cpufreq_menu(cpufreq *cf){
245 GList *l;
246 GSList *group;
247 char buff[100];
248 GtkMenuItem* menuitem;
249 Param* param;
250
251 GtkMenu* menu = GTK_MENU(gtk_menu_new());
252 g_signal_connect(menu, "selection-done", G_CALLBACK(gtk_widget_destroy), NULL);
253
254 get_governors(cf);
255 group = NULL;
256
257 if((cf->governors == NULL) || (!cf->has_cpufreq) || (cf->cur_governor == NULL)){
258 menuitem = GTK_MENU_ITEM(gtk_menu_item_new_with_label("CPUFreq not supported"));
259 gtk_menu_append (GTK_MENU_SHELL (menu), GTK_WIDGET (menuitem));
260 gtk_widget_show (GTK_WIDGET (menuitem));
261 return GTK_WIDGET(menu);
262 }
263
264 if(strcmp(cf->cur_governor, "userspace") == 0){
265 menuitem = GTK_MENU_ITEM(gtk_menu_item_new_with_label(" Frequency"));
266 gtk_menu_append (GTK_MENU_SHELL (menu), GTK_WIDGET (menuitem));
267 gtk_widget_show (GTK_WIDGET (menuitem));
268 gtk_menu_item_set_submenu(menuitem, frequency_menu(cf));
269 menuitem = GTK_MENU_ITEM(gtk_separator_menu_item_new());
270 gtk_menu_append (GTK_MENU_SHELL (menu), GTK_WIDGET (menuitem));
271 gtk_widget_show (GTK_WIDGET(menuitem));
272 }
273
274 for( l = cf->governors; l; l = l->next )
275 {
276 if(strcmp((char*)l->data, cf->cur_governor) == 0){
277 sprintf(buff,"> %s", l->data);
278 menuitem = GTK_MENU_ITEM(gtk_menu_item_new_with_label(strdup(buff)));
279 }else{
280 sprintf(buff," %s", l->data);
281 menuitem = GTK_MENU_ITEM(gtk_menu_item_new_with_label(strdup(buff)));
282 }
283
284 gtk_menu_shell_append (GTK_MENU_SHELL (menu), GTK_WIDGET (menuitem));
285 gtk_widget_show (GTK_WIDGET (menuitem));
286 param = g_new0(Param, 1);
287 param->data = l->data;
288 param->cf = cf;
289 g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(cpufreq_set_governor), param);
290 g_object_weak_ref(G_OBJECT(menuitem), (GWeakNotify) g_free, param);
291 }
292
293 return GTK_WIDGET (menu);
294 }*/
295
296
297
298 static gboolean
299 clicked( GtkWidget *widget, GdkEventButton* evt, Plugin* plugin)
300 {
301 ENTER2;
302 if( evt->button == 1 )
303 {
304 // Setting governor can't work without root privilege
305 // gtk_menu_popup( cpufreq_menu((cpufreq*)plugin->priv), NULL, NULL, NULL, NULL,
306 // evt->button, evt->time );
307 return TRUE;
308 }else if ( evt->button == 3 )
309 {
310 GtkMenu* popup = lxpanel_get_panel_menu( plugin->panel, plugin, FALSE );
311 gtk_menu_popup( popup, NULL, NULL, NULL, NULL, evt->button, evt->time );
312 return TRUE;
313 return TRUE;
314 }
315
316 RET2(TRUE);
317 }
318
319 static gboolean
320 _update_tooltip(cpufreq *cf)
321 {
322 char *tooltip;
323
324 get_cur_freq(cf);
325 get_cur_governor(cf);
326
327 ENTER;
328
329 tooltip = g_strdup_printf("Frequency: %d MHz\nGovernor: %s",
330 cf->cur_freq / 1000, cf->cur_governor);
331 gtk_tooltips_set_tip(cf->tip, cf->main, tooltip, NULL);
332 g_free(tooltip);
333 RET(TRUE);
334 }
335
336 static gboolean update_tooltip(gpointer user_data)
337 {
338 if (g_source_is_destroyed(g_main_current_source()))
339 return FALSE;
340 return _update_tooltip(user_data);
341 }
342
343 static int
344 cpufreq_constructor(Plugin *p, char** fp)
345 {
346 cpufreq *cf;
347 //GtkWidget *button;
348
349 ENTER;
350 cf = g_new0(cpufreq, 1);
351 cf->governors = NULL;
352 cf->cpus = NULL;
353 g_return_val_if_fail(cf != NULL, 0);
354 p->priv = cf;
355
356 p->pwid = gtk_event_box_new();
357 GTK_WIDGET_SET_FLAGS( p->pwid, GTK_NO_WINDOW );
358 gtk_container_set_border_width( GTK_CONTAINER(p->pwid), 2 );
359
360 cf->namew = gtk_image_new_from_file(PROC_ICON);
361 gtk_container_add(GTK_CONTAINER(p->pwid), cf->namew);
362
363 cf->main = p->pwid;
364 cf->tip = gtk_tooltips_new();
365
366 #if GLIB_CHECK_VERSION( 2, 10, 0 )
367 g_object_ref_sink( cf->tip );
368 #else
369 g_object_ref( cf->tip );
370 gtk_object_sink( cf->tip );
371 #endif
372
373 g_signal_connect (G_OBJECT (p->pwid), "button-press-event", G_CALLBACK (clicked), (gpointer) p);
374
375 cf->has_cpufreq = 0;
376
377 get_cpus(cf);
378
379 /* line s;
380 s.len = 256;
381
382 if (fp) {
383 while (lxpanel_get_line(fp, &s) != LINE_BLOCK_END) {
384 if (s.type == LINE_NONE) {
385 ERR( "cpufreq: illegal token %s\n", s.str);
386 goto error;
387 }
388 if (s.type == LINE_VAR) {
389 if (!g_ascii_strcasecmp(s.t[0], "DefaultGovernor")){
390 //cf->str_cl_normal = g_strdup(s.t[1]);
391 }else {
392 ERR( "cpufreq: unknown var %s\n", s.t[0]);
393 continue;
394 }
395 }
396 else {
397 ERR( "cpufreq: illegal in cfis context %s\n", s.str);
398 goto error;
399 }
400 }
401
402 }*/
403 _update_tooltip(cf);
404 cf->timer = g_timeout_add_seconds(2, update_tooltip, (gpointer)cf);
405
406 gtk_widget_show(cf->namew);
407
408 RET(TRUE);
409
410 /*error:
411 RET(FALSE);*/
412 }
413
414 static void applyConfig(Plugin* p) { }
415
416 static void config(Plugin *p, GtkWindow* parent) {
417 ENTER;
418
419 GtkWidget *dialog;
420 cpufreq *cf = (cpufreq *) p->priv;
421 dialog = create_generic_config_dlg(_(p->class->name),
422 GTK_WIDGET(parent),
423 (GSourceFunc) applyConfig, (gpointer) p,
424 _("Remember governor and frequency"), &cf->remember, CONF_TYPE_BOOL,
425 NULL);
426 gtk_window_present(GTK_WINDOW(dialog));
427
428 RET();
429 }
430
431 static void
432 cpufreq_destructor(Plugin *p)
433 {
434 cpufreq *cf = (cpufreq *)p->priv;
435 g_list_free ( cf->cpus );
436 g_list_free ( cf->governors );
437 g_source_remove(cf->timer);
438 g_free(cf);
439 }
440
441 /*static void save_config( Plugin* p, FILE* fp )
442 {
443 cpufreq *cf = (cpufreq *)p->priv;
444
445 lxpanel_put_bool( fp, "Remember", cf->remember);
446 lxpanel_put_str( fp, "Governor", cf->cur_governor );
447 lxpanel_put_int( fp, "Frequency", cf->cur_freq );
448 }*/
449
450 PluginClass cpufreq_plugin_class = {
451 PLUGINCLASS_VERSIONING,
452
453 .type = "cpufreq",
454 .name = N_("CPUFreq frontend"),
455 .version = "0.1",
456 .description = N_("Display CPU frequency and allow to change governors and frequency"),
457
458 .constructor = cpufreq_constructor,
459 .destructor = cpufreq_destructor,
460 .config = config,
461 .save = NULL,
462 .panel_configuration_changed = NULL
463 };