2 * Cpumem-applet - status area plugin
4 * Copyright (c) 2005-2009 Jakub Pavelek
5 * Copyright (c) 2009-2010 Tuomo Tanskanen
9 #include <hildon/hildon.h>
10 #include <glib/gerror.h>
14 typedef unsigned long long uint64_t;
16 #include "cpumem_status_area_item.h"
18 #define CPUMEM_ICON_WIDTH 16
19 #define CPUMEM_ICON_HEIGHT 16
20 #define CPUMEM_BOX_WIDTH 4
21 #define CPUMEM_BOX_HEIGHT 3
22 #define CPUMEM_CPU_MAX 5
26 #define CPUMEM_APPLET_STATUS_AREA_ITEM_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE (obj, CPUMEM_APPLET_TYPE_STATUS_AREA_ITEM, CpumemAppletStatusAreaItemPrivate))
28 struct _CpumemAppletStatusAreaItemPrivate {
30 gint lastU, lastN, lastIO, lastI;
31 guchar last_mem_level;
32 guchar last_cpu_level;
33 guchar last_net_level;
35 uint64_t last_out_oct;
38 GdkPixbuf *pixbuf_red;
39 GdkPixbuf *pixbuf_off;
44 HD_DEFINE_PLUGIN_MODULE (CpumemAppletStatusAreaItem, cpumem_applet_status_area_item, HD_TYPE_STATUS_PLUGIN_ITEM);
48 * Read current MEM usage and return indicator between 5 and 1 - how many bars are "full"
51 check_mem (CpumemAppletStatusAreaItemPrivate *priv)
53 #define MEMFILE "/proc/meminfo"
54 #define MAX_READ_CHARS 128
55 char read_buffer[MAX_READ_CHARS];
63 //Open the memory info file and get current free memory
64 fin = fopen(MEMFILE, "r");
66 g_warning("Can't open "MEMFILE"\n");
69 while (fgets(read_buffer, MAX_READ_CHARS, fin) != NULL) {
70 if (strncmp(read_buffer, "MemTotal", 8) == 0) {
71 sscanf(read_buffer + 10, "%d", &mem_total);
72 } else if (strncmp(read_buffer, "MemFree", 6) == 0) {
73 sscanf(read_buffer + 9, "%d", &mem_free);
74 } else if (strncmp(read_buffer, "Buffers", 6) == 0) {
75 sscanf(read_buffer + 9, "%d", &mem_buffers);
76 } else if (strncmp(read_buffer, "Cached", 6) == 0) {
77 sscanf(read_buffer + 8, "%d", &mem_cached);
83 mem_used = mem_total - mem_free - mem_buffers - mem_cached;
85 if (mem_used > 0.9*mem_total)
87 else if (mem_used > 0.7*mem_total)
89 else if (mem_used > 0.5*mem_total)
91 else if (mem_used > 0.3*mem_total)
99 * Read current CPU usage and return indicator between 5 and 1 - how many bars are "full"
102 check_cpu (CpumemAppletStatusAreaItemPrivate *priv)
104 #define CPUFILE "/proc/stat"
105 gint curU, curN, curIO, curI;
106 gint deltaU, deltaN, deltaIO, deltaI;
108 GError *error = NULL;
113 if (!g_file_get_contents (CPUFILE, &contents, &lenght, &error)) {
114 fprintf (stderr, "ERR: can't read file %s: %s\n", CPUFILE, error->message);
115 g_error_free (error);
119 splits = g_strsplit_set (contents, " ", -1);
121 sscanf(splits[2], "%d", &curU);
122 sscanf(splits[3], "%d", &curN);
123 sscanf(splits[4], "%d", &curIO);
124 sscanf(splits[5], "%d", &curI);
129 idle = (curI - priv->lastI);
130 if (idle == 0) load = 100;
131 else load = 100-idle;
132 if (load>100) load = 0;
133 deltaU = curU - priv->lastU;
134 deltaN = curN - priv->lastN;
135 deltaIO = curIO - priv->lastIO;
136 deltaI = curI - priv->lastI;
139 priv->lastIO = curIO;
155 check_net (CpumemAppletStatusAreaItemPrivate *priv)
157 #define NETFILE "/proc/net/dev"
158 uint64_t cur_in_oct, cur_out_oct;
164 uint64_t inoct, outoct;
167 if (!g_file_get_contents (NETFILE, &contents, NULL, &error)) {
168 fprintf (stderr, "ERR: can't read file %s: %s\n", NETFILE, error->message);
169 g_error_free (error);
173 cur_in_oct = cur_out_oct = 0;
175 token = strtok_r(contents, ":\n\r ", &pos);
176 while(token != NULL) {
177 if(!strcmp(token, "gprs0") || !strcmp(token, "wlan0")) {
183 cur_in_oct += strtoull(token, NULL, 10);
187 } else if(next == 2) {
189 cur_out_oct += strtoull(token, NULL, 10);
195 token = strtok_r(NULL, ":\n\r ", &pos);
199 inoct = cur_in_oct - priv->last_in_oct;
200 outoct = cur_out_oct - priv->last_out_oct;
201 if(inoct < outoct) {l=6; inoct = outoct;} else l=1;
203 if(inoct > 1024) l++;
204 if(inoct > 1024*10) l++;
205 if(inoct > 1024*100) l++;
206 priv->last_in_oct = cur_in_oct;
207 priv->last_out_oct = cur_out_oct;
213 * Compose and blit the current status of memory bars
216 blit_mem_bars(const guchar level, CpumemAppletStatusAreaItemPrivate *priv)
220 gdk_pixbuf_fill(priv->pixbuf, 0x00000000);
225 gdk_pixbuf_composite(priv->pixbuf_on, priv->pixbuf, x, y,
226 CPUMEM_BOX_WIDTH, CPUMEM_BOX_HEIGHT, x, y, 1, 1, GDK_INTERP_NEAREST, 255);
229 gdk_pixbuf_composite(priv->pixbuf_on, priv->pixbuf, x, y,
230 CPUMEM_BOX_WIDTH, CPUMEM_BOX_HEIGHT, x, y, 1, 1, GDK_INTERP_NEAREST, 255);
233 gdk_pixbuf_composite(priv->pixbuf_on, priv->pixbuf, x, y,
234 CPUMEM_BOX_WIDTH, CPUMEM_BOX_HEIGHT, x, y, 1, 1, GDK_INTERP_NEAREST, 255);
237 gdk_pixbuf_composite(priv->pixbuf_on, priv->pixbuf, x, y,
238 CPUMEM_BOX_WIDTH, CPUMEM_BOX_HEIGHT, x, y, 1, 1, GDK_INTERP_NEAREST, 255);
240 gdk_pixbuf_composite(priv->pixbuf_off, priv->pixbuf, x, y,
241 CPUMEM_BOX_WIDTH, CPUMEM_BOX_HEIGHT, x, y, 1, 1, GDK_INTERP_NEAREST, 255);
245 blit_net_bars(guchar level, CpumemAppletStatusAreaItemPrivate *priv)
252 if(level > 5) {color = priv->pixbuf_red; level -= 5;}
253 else color = priv->pixbuf_on;
255 gdk_pixbuf_composite(color, priv->pixbuf, x, y,
256 CPUMEM_BOX_WIDTH, CPUMEM_BOX_HEIGHT, x, y, 1, 1, GDK_INTERP_NEAREST, 255);
259 gdk_pixbuf_composite(color, priv->pixbuf, x, y,
260 CPUMEM_BOX_WIDTH, CPUMEM_BOX_HEIGHT, x, y, 1, 1, GDK_INTERP_NEAREST, 255);
263 gdk_pixbuf_composite(color, priv->pixbuf, x, y,
264 CPUMEM_BOX_WIDTH, CPUMEM_BOX_HEIGHT, x, y, 1, 1, GDK_INTERP_NEAREST, 255);
267 gdk_pixbuf_composite(color, priv->pixbuf, x, y,
268 CPUMEM_BOX_WIDTH, CPUMEM_BOX_HEIGHT, x, y, 1, 1, GDK_INTERP_NEAREST, 255);
270 gdk_pixbuf_composite(priv->pixbuf_off, priv->pixbuf, x, y,
271 CPUMEM_BOX_WIDTH, CPUMEM_BOX_HEIGHT, x, y, 1, 1, GDK_INTERP_NEAREST, 255);
276 * Compose and blit current status of CPU bars
279 blit_cpu_bars (const guchar level, CpumemAppletStatusAreaItemPrivate *priv)
287 if (priv->red == TRUE) {
288 gdk_pixbuf_composite(priv->pixbuf_red, priv->pixbuf, x, y,
289 CPUMEM_BOX_WIDTH, CPUMEM_BOX_HEIGHT, x, y, 1, 1, GDK_INTERP_NEAREST, 255);
292 gdk_pixbuf_composite(priv->pixbuf_on, priv->pixbuf, x, y,
293 CPUMEM_BOX_WIDTH, CPUMEM_BOX_HEIGHT, x, y, 1, 1, GDK_INTERP_NEAREST, 255);
299 gdk_pixbuf_composite(priv->pixbuf_on, priv->pixbuf, x, y,
300 CPUMEM_BOX_WIDTH, CPUMEM_BOX_HEIGHT, x, y, 1, 1, GDK_INTERP_NEAREST, 255);
303 gdk_pixbuf_composite(priv->pixbuf_on, priv->pixbuf, x, y,
304 CPUMEM_BOX_WIDTH, CPUMEM_BOX_HEIGHT, x, y, 1, 1, GDK_INTERP_NEAREST, 255);
307 gdk_pixbuf_composite(priv->pixbuf_on, priv->pixbuf, x, y,
308 CPUMEM_BOX_WIDTH, CPUMEM_BOX_HEIGHT, x, y, 1, 1, GDK_INTERP_NEAREST, 255);
310 gdk_pixbuf_composite(priv->pixbuf_off, priv->pixbuf, x, y,
311 CPUMEM_BOX_WIDTH, CPUMEM_BOX_HEIGHT, x, y, 1, 1, GDK_INTERP_NEAREST, 255);
316 * Ran to check and update the CPU and memory reading
319 check_load (gpointer data)
321 guchar current_cpu_level;
322 guchar current_mem_level;
323 guchar current_net_level;
324 CpumemAppletStatusAreaItem *item = (CpumemAppletStatusAreaItem*)data;
325 CpumemAppletStatusAreaItemPrivate *priv = (CpumemAppletStatusAreaItemPrivate*)item->priv;
327 current_cpu_level = check_cpu(priv);
328 current_net_level = check_net(priv);
329 current_mem_level = check_mem(priv);
330 //g_debug(g_strdup_printf("LOADAPLET - UPDATED CPU %d MEM %d", current_cpu_level, current_mem_level));
332 //Update and blit only if data changed!
333 if ((current_mem_level != priv->last_mem_level) || (current_cpu_level != priv->last_cpu_level)
334 || current_net_level != priv->last_net_level) {
335 blit_mem_bars (current_mem_level, priv);
336 blit_cpu_bars (current_cpu_level, priv);
337 blit_net_bars (current_net_level, priv);
338 if (current_cpu_level == CPUMEM_CPU_MAX)
340 hd_status_plugin_item_set_status_area_icon (HD_STATUS_PLUGIN_ITEM(data), priv->pixbuf);
341 priv->last_mem_level = current_mem_level;
342 priv->last_cpu_level = current_cpu_level;
343 priv->last_net_level = current_net_level;
344 } else if (current_cpu_level == CPUMEM_CPU_MAX) {
345 //Pulsate max CPU load icon also when CPU load stays at max
346 blit_cpu_bars (current_cpu_level, priv);
347 hd_status_plugin_item_set_status_area_icon (HD_STATUS_PLUGIN_ITEM(data), priv->pixbuf);
354 * Get callback when display state changes
357 cpumem_applet_status_area_item_display_cb(osso_display_state_t state, gpointer user_data)
359 CpumemAppletStatusAreaItem *item = CPUMEM_APPLET_STATUS_AREA_ITEM(user_data);
361 g_return_if_fail (item != NULL && item->priv != NULL);
363 if (state == OSSO_DISPLAY_ON)
365 //Restart the updates, do one right away
366 if (item->priv->timeout_id == 0)
368 item->priv->timeout_id = gtk_timeout_add(1000, check_load, item);
372 //Suspend the updates - screen is off
373 if (item->priv->timeout_id != 0) {
374 g_source_remove(item->priv->timeout_id);
375 item->priv->timeout_id = 0;
381 /*****************************************************************************
383 * Boilerplate code area - do not enter
385 *****************************************************************************/
388 cpumem_applet_status_area_item_set_area_icon (CpumemAppletStatusAreaItem *item)
390 item->priv = CPUMEM_APPLET_STATUS_AREA_ITEM_GET_PRIVATE (item);
392 hd_status_plugin_item_set_status_area_icon (HD_STATUS_PLUGIN_ITEM(item), item->priv->pixbuf);
397 cpumem_applet_status_area_item_class_finalize (CpumemAppletStatusAreaItemClass *klass)
404 cpumem_applet_status_area_item_finalize (GObject *object)
406 CpumemAppletStatusAreaItemPrivate *priv = CPUMEM_APPLET_STATUS_AREA_ITEM(object)->priv;
407 // Release and clean our stuff
408 G_OBJECT_CLASS (cpumem_applet_status_area_item_parent_class)->finalize (object);
411 osso_deinitialize(priv->osso);
420 cpumem_applet_status_area_item_class_init (CpumemAppletStatusAreaItemClass *klass)
422 GObjectClass *object_class = G_OBJECT_CLASS (klass);
424 object_class->finalize = cpumem_applet_status_area_item_finalize;
426 g_type_class_add_private (klass, sizeof (CpumemAppletStatusAreaItemPrivate));
431 cpumem_applet_status_area_item_init (CpumemAppletStatusAreaItem *item)
433 item->priv = CPUMEM_APPLET_STATUS_AREA_ITEM_GET_PRIVATE (item);
435 item->priv->last_mem_level = -1;
436 item->priv->last_cpu_level = -1;
437 item->priv->last_net_level = -1;
438 item->priv->timeout_id = -1;
439 item->priv->red = FALSE;
440 item->priv->pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, CPUMEM_ICON_WIDTH, CPUMEM_ICON_HEIGHT);
441 gdk_pixbuf_fill(item->priv->pixbuf, 0x00000000);
442 item->priv->pixbuf_on = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, CPUMEM_BOX_WIDTH, CPUMEM_BOX_HEIGHT);
443 gdk_pixbuf_fill(item->priv->pixbuf_on, 0xffffffff);
444 item->priv->pixbuf_red = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, CPUMEM_BOX_WIDTH, CPUMEM_BOX_HEIGHT);
445 gdk_pixbuf_fill(item->priv->pixbuf_red, 0xff0000ff);
446 item->priv->pixbuf_off = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, CPUMEM_BOX_WIDTH, CPUMEM_BOX_HEIGHT);
447 gdk_pixbuf_fill(item->priv->pixbuf_off, 0x777777ff);
448 cpumem_applet_status_area_item_set_area_icon(item);
450 item->priv->osso = osso_initialize ("cpumem_applet_status_area_item", "Maemo5", TRUE, NULL);
451 item->priv->timeout_id = gtk_timeout_add(1000, check_load, item);
452 osso_hw_set_display_event_cb (item->priv->osso, cpumem_applet_status_area_item_display_cb, item);