summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlastair Poole <mail@alastairpoole.com>2021-11-02 19:50:19 +0000
committerAlastair Poole <mail@alastairpoole.com>2021-11-02 19:50:19 +0000
commite24890f736f7d080da050827f30dc55ba162b428 (patch)
tree388176686ef31ac3477be53dba95bb955f76cebe
parent20fb0d6ede4fddb51c6d0adaeaf67e89c97e0d03 (diff)
WIP: this needs work...
but 2 visuals.
-rw-r--r--src/bin/evisum_config.c64
-rw-r--r--src/bin/evisum_config.h3
-rw-r--r--src/bin/evisum_server.c1
-rw-r--r--src/bin/ui/evisum_ui.c53
-rw-r--r--src/bin/ui/evisum_ui.h1
-rw-r--r--src/bin/ui/meson.build2
-rw-r--r--src/bin/ui/ui_cpu.c876
-rw-r--r--src/bin/ui/ui_cpu.h50
-rw-r--r--src/bin/ui/ui_process_list.c3
-rw-r--r--src/bin/ui/visuals/cpu_basic.c130
-rw-r--r--src/bin/ui/visuals/cpu_basic.h9
-rw-r--r--src/bin/ui/visuals/cpu_default.c591
-rw-r--r--src/bin/ui/visuals/cpu_default.h9
-rw-r--r--src/bin/ui/visuals/meson.build6
-rw-r--r--src/bin/ui/visuals/visuals.x7
15 files changed, 1090 insertions, 715 deletions
diff --git a/src/bin/evisum_config.c b/src/bin/evisum_config.c
index abb63f0..4d8050c 100644
--- a/src/bin/evisum_config.c
+++ b/src/bin/evisum_config.c
@@ -6,6 +6,8 @@
6 6
7Evisum_Config *_evisum_config; 7Evisum_Config *_evisum_config;
8 8
9static Eet_Data_Descriptor *_evisum_conf_descriptor = NULL;
10
9static const char * 11static const char *
10_config_file_path(void) 12_config_file_path(void)
11{ 13{
@@ -22,7 +24,60 @@ _config_file_path(void)
22void 24void
23config_init(void) 25config_init(void)
24{ 26{
27 Eet_Data_Descriptor_Class eddc;
25 efreet_init(); 28 efreet_init();
29
30 EET_EINA_STREAM_DATA_DESCRIPTOR_CLASS_SET(&eddc, Evisum_Config);
31 _evisum_conf_descriptor = eet_data_descriptor_stream_new(&eddc);
32 EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, "version", version, EET_T_INT);
33 EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, "effects", effects, EET_T_UCHAR);
34 EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, "backgrounds", backgrounds, EET_T_UCHAR);
35 EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, "proc.width", proc.width, EET_T_INT);
36 EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, "proc.height", proc.height, EET_T_INT);
37 EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, "proc.x", proc.x, EET_T_INT);
38 EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, "proc.y", proc.y, EET_T_INT);
39 EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, "proc.restart", proc.restart, EET_T_UCHAR);
40 EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, "proc.show_kthreads", proc.show_kthreads, EET_T_UCHAR);
41 EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, "proc.show_user", proc.show_user, EET_T_UCHAR);
42 EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, "proc.sort_type", proc.sort_type, EET_T_UCHAR);
43 EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, "proc.sort_reverse", proc.sort_reverse, EET_T_UCHAR);
44 EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, "proc.poll_delay", proc.poll_delay, EET_T_UCHAR);
45 EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, "proc.fields", proc.fields, EET_T_INT);
46 EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, "proc.show_statusbar", proc.show_statusbar, EET_T_UCHAR);
47 EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, "proc.show_scroller", proc.show_scroller, EET_T_UCHAR);
48 EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, "proc.transparent", proc.transparent, EET_T_UCHAR);
49 EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, "proc.alpha", proc.alpha, EET_T_UCHAR);
50
51 EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, "cpu.width", cpu.width, EET_T_INT);
52 EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, "cpu.height", cpu.height, EET_T_INT);
53 EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, "cpu.x", cpu.x, EET_T_INT);
54 EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, "cpu.y", cpu.y, EET_T_INT);
55 EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, "cpu.restart", cpu.restart, EET_T_UCHAR);
56 EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, "cpu.visual", cpu.visual, EET_T_STRING);
57
58 EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, "mem.width", mem.width, EET_T_INT);
59 EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, "mem.height", mem.height, EET_T_INT);
60 EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, "mem.x", mem.x, EET_T_INT);
61 EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, "mem.y", mem.y, EET_T_INT);
62 EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, "mem.restart", mem.restart, EET_T_UCHAR);
63
64 EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, "disk.width", disk.width, EET_T_INT);
65 EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, "disk.height", disk.height, EET_T_INT);
66 EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, "disk.x", disk.x, EET_T_INT);
67 EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, "disk.y", disk.y, EET_T_INT);
68 EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, "disk.restart", disk.restart, EET_T_UCHAR);
69
70 EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, "sensors.width", sensors.width, EET_T_INT);
71 EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, "sensors.height", sensors.height, EET_T_INT);
72 EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, "sensors.x", sensors.x, EET_T_INT);
73 EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, "sensors.y", sensors.y, EET_T_INT);
74 EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, "sensors.restart", sensors.restart, EET_T_UCHAR);
75
76 EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, "network.width", network.width, EET_T_INT);
77 EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, "network.height", network.height, EET_T_INT);
78 EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, "network.x", network.x, EET_T_INT);
79 EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, "network.y", network.y, EET_T_INT);
80 EET_DATA_DESCRIPTOR_ADD_BASIC(_evisum_conf_descriptor, Evisum_Config, "network.restart", network.restart, EET_T_UCHAR);
26} 81}
27 82
28void 83void
@@ -67,6 +122,8 @@ _config_init()
67 cfg->proc.fields = 0xffffe24f; 122 cfg->proc.fields = 0xffffe24f;
68 cfg->proc.alpha = 100; 123 cfg->proc.alpha = 100;
69 124
125 cfg->cpu.visual = strdup("default");
126
70 return cfg; 127 return cfg;
71} 128}
72 129
@@ -74,7 +131,6 @@ Evisum_Config *
74config_load(void) 131config_load(void)
75{ 132{
76 Eet_File *f; 133 Eet_File *f;
77 int size;
78 Evisum_Config *cfg = NULL; 134 Evisum_Config *cfg = NULL;
79 135
80 const char *path = _config_file_path(); 136 const char *path = _config_file_path();
@@ -84,14 +140,14 @@ config_load(void)
84 140
85 f = eet_open(path, EET_FILE_MODE_WRITE); 141 f = eet_open(path, EET_FILE_MODE_WRITE);
86 if (!f) _config_fail("create"); 142 if (!f) _config_fail("create");
87 eet_write(f, "Config", cfg, sizeof(Evisum_Config), 0); 143 eet_data_write(f, _evisum_conf_descriptor, "Config", cfg, EINA_TRUE);
88 eet_close(f); 144 eet_close(f);
89 } 145 }
90 else 146 else
91 { 147 {
92 f = eet_open(path, EET_FILE_MODE_READ); 148 f = eet_open(path, EET_FILE_MODE_READ);
93 if (!f) _config_fail("read"); 149 if (!f) _config_fail("read");
94 cfg = eet_read(f, "Config", &size); 150 cfg = eet_data_read(f, _evisum_conf_descriptor, "Config");
95 151
96 if (cfg->version < CONFIG_VERSION) 152 if (cfg->version < CONFIG_VERSION)
97 { 153 {
@@ -116,7 +172,7 @@ config_save(Evisum_Config *cfg)
116 const char *path = _config_file_path(); 172 const char *path = _config_file_path();
117 f = eet_open(path, EET_FILE_MODE_WRITE); 173 f = eet_open(path, EET_FILE_MODE_WRITE);
118 if (!f) exit(127); 174 if (!f) exit(127);
119 eet_write(f, "Config", cfg, sizeof(Evisum_Config), 0); 175 eet_data_write(f, _evisum_conf_descriptor, "Config", cfg, EINA_TRUE);
120 eet_close(f); 176 eet_close(f);
121 177
122 return 1; 178 return 1;
diff --git a/src/bin/evisum_config.h b/src/bin/evisum_config.h
index 0d54096..2819172 100644
--- a/src/bin/evisum_config.h
+++ b/src/bin/evisum_config.h
@@ -3,7 +3,7 @@
3 3
4#include "ui/evisum_ui.h" 4#include "ui/evisum_ui.h"
5 5
6#define CONFIG_VERSION 0x0012 6#define CONFIG_VERSION 0x0013
7 7
8typedef struct _Evisum_Config 8typedef struct _Evisum_Config
9{ 9{
@@ -39,6 +39,7 @@ typedef struct _Evisum_Config
39 int height; 39 int height;
40 int x, y; 40 int x, y;
41 Eina_Bool restart; 41 Eina_Bool restart;
42 char *visual;
42 } cpu; 43 } cpu;
43 44
44 struct 45 struct
diff --git a/src/bin/evisum_server.c b/src/bin/evisum_server.c
index eb4cf13..326aff0 100644
--- a/src/bin/evisum_server.c
+++ b/src/bin/evisum_server.c
@@ -7,6 +7,7 @@
7#include <Ecore_Con.h> 7#include <Ecore_Con.h>
8#include "evisum_server.h" 8#include "evisum_server.h"
9#include "src/bin/ui/evisum_ui.h" 9#include "src/bin/ui/evisum_ui.h"
10#include "evisum_config.h"
10 11
11#define LISTEN_SOCKET_NAME "evisum_server" 12#define LISTEN_SOCKET_NAME "evisum_server"
12#define WANTED "bonjour monde" 13#define WANTED "bonjour monde"
diff --git a/src/bin/ui/evisum_ui.c b/src/bin/ui/evisum_ui.c
index d183a60..84a01f4 100644
--- a/src/bin/ui/evisum_ui.c
+++ b/src/bin/ui/evisum_ui.c
@@ -67,6 +67,7 @@ evisum_ui_config_save(Evisum_Ui *ui)
67 config()->cpu.x = ui->cpu.x; 67 config()->cpu.x = ui->cpu.x;
68 config()->cpu.y = ui->cpu.y; 68 config()->cpu.y = ui->cpu.y;
69 config()->cpu.restart = ui->cpu.restart; 69 config()->cpu.restart = ui->cpu.restart;
70 config()->cpu.visual = ui->cpu.visual;
70 } 71 }
71 72
72 if (ui->mem.win) 73 if (ui->mem.win)
@@ -153,6 +154,7 @@ evisum_ui_config_load(Evisum_Ui *ui)
153 ui->cpu.x = config()->cpu.x; 154 ui->cpu.x = config()->cpu.x;
154 ui->cpu.y = config()->cpu.y; 155 ui->cpu.y = config()->cpu.y;
155 ui->cpu.restart = config()->cpu.restart; 156 ui->cpu.restart = config()->cpu.restart;
157 ui->cpu.visual = strdup(config()->cpu.visual);
156 158
157 ui->mem.width = config()->mem.width; 159 ui->mem.width = config()->mem.width;
158 ui->mem.height = config()->mem.height; 160 ui->mem.height = config()->mem.height;
@@ -408,6 +410,21 @@ _main_menu_focus_timer_cb(void *data)
408 return 0; 410 return 0;
409} 411}
410 412
413static void
414_cpu_visual_clicked_cb(void *data EINA_UNUSED, Evas_Object *obj,
415 void *event_info EINA_UNUSED)
416{
417 Evisum_Ui *ui;
418 const char *txt;
419
420 ui = data;
421 txt = elm_object_text_get(obj);
422
423 if (ui->cpu.visual) free(ui->cpu.visual);
424 ui->cpu.visual = strdup(txt);
425 evisum_ui_restart(ui);
426}
427
411Evas_Object * 428Evas_Object *
412evisum_ui_main_menu_create(Evisum_Ui *ui, Evas_Object *parent, Evas_Object *obj) 429evisum_ui_main_menu_create(Evisum_Ui *ui, Evas_Object *parent, Evas_Object *obj)
413{ 430{
@@ -530,6 +547,40 @@ evisum_ui_main_menu_create(Evisum_Ui *ui, Evas_Object *parent, Evas_Object *obj)
530 evas_object_move(o, ox + (ow / 2), oy + oh); 547 evas_object_move(o, ox + (ow / 2), oy + oh);
531 evas_object_show(o); 548 evas_object_show(o);
532 549
550
551 if (parent == ui->cpu.win)
552 {
553 fr = elm_frame_add(o);
554 evas_object_size_hint_weight_set(fr, EXPAND, EXPAND);
555 evas_object_size_hint_align_set(fr, FILL, FILL);
556 elm_object_text_set(fr, _("Visuals"));
557 elm_box_pack_end(obx, fr);
558 evas_object_show(fr);
559
560 bx = elm_box_add(o);
561 evas_object_size_hint_weight_set(bx, EXPAND, EXPAND);
562 evas_object_size_hint_align_set(bx, FILL, FILL);
563 elm_object_content_set(fr, bx);
564 evas_object_show(bx);
565
566 Eina_List *visuals = ui_cpu_visuals_get();
567 char *name;
568
569 EINA_LIST_FREE(visuals, name)
570 {
571 btn = elm_button_add(o);
572 evas_object_size_hint_weight_set(btn, EXPAND, 0);
573 evas_object_size_hint_align_set(btn, FILL, FILL);
574 elm_object_text_set(btn, name);
575 if (!strcmp(name, ui->cpu.visual)) elm_object_disabled_set(btn, 1);
576 elm_box_pack_end(bx, btn);
577 evas_object_show(btn);
578 evas_object_smart_callback_add(btn, "clicked", _cpu_visual_clicked_cb, ui);
579 }
580
581 return o;
582 }
583
533 if (parent != ui->proc.win) return o; 584 if (parent != ui->proc.win) return o;
534 585
535 fr = elm_frame_add(o); 586 fr = elm_frame_add(o);
@@ -768,6 +819,7 @@ evisum_ui_shutdown(Evisum_Ui *ui)
768 ecore_thread_cancel(ui->background_poll_thread); 819 ecore_thread_cancel(ui->background_poll_thread);
769 ecore_thread_wait(ui->background_poll_thread, 0.5); 820 ecore_thread_wait(ui->background_poll_thread, 0.5);
770 821
822 if (ui->cpu.visual) free(ui->cpu.visual);
771 free(ui); 823 free(ui);
772} 824}
773 825
@@ -785,6 +837,7 @@ evisum_ui_init(void)
785 837
786 EVISUM_EVENT_CONFIG_CHANGED = ecore_event_type_new(); 838 EVISUM_EVENT_CONFIG_CHANGED = ecore_event_type_new();
787 839
840 config_init();
788 evisum_ui_config_load(ui); 841 evisum_ui_config_load(ui);
789 842
790 _ui_init_system_probe(ui); 843 _ui_init_system_probe(ui);
diff --git a/src/bin/ui/evisum_ui.h b/src/bin/ui/evisum_ui.h
index 2a73fc1..fa6e18e 100644
--- a/src/bin/ui/evisum_ui.h
+++ b/src/bin/ui/evisum_ui.h
@@ -65,6 +65,7 @@ typedef struct _Evisum_Ui
65 int height; 65 int height;
66 int x, y; 66 int x, y;
67 Eina_Bool restart; 67 Eina_Bool restart;
68 char *visual;
68 } cpu; 69 } cpu;
69 70
70 struct 71 struct
diff --git a/src/bin/ui/meson.build b/src/bin/ui/meson.build
index 35a8caf..bf638f9 100644
--- a/src/bin/ui/meson.build
+++ b/src/bin/ui/meson.build
@@ -1,3 +1,5 @@
1subdir('visuals')
2
1src += files([ 3src += files([
2 'gettext.h', 4 'gettext.h',
3 'evisum_ui.h', 5 'evisum_ui.h',
diff --git a/src/bin/ui/ui_cpu.c b/src/bin/ui/ui_cpu.c
index 681c572..19e65cd 100644
--- a/src/bin/ui/ui_cpu.c
+++ b/src/bin/ui/ui_cpu.c
@@ -1,67 +1,26 @@
1#include "ui_cpu.h" 1#include "ui_cpu.h"
2#include "config.h" 2#include "config.h"
3 3
4typedef struct { 4// Templates for visualisations.
5 short id; 5#include "visuals/visuals.x"
6 short percent;
7 unsigned int freq;
8 unsigned int temp;
9} Core;
10
11typedef struct {
12 Ecore_Thread *thread;
13
14 Evas_Object *win;
15 Evas_Object *menu;
16 Elm_Layout *btn_menu;
17 Eina_Bool btn_visible;
18 Evas_Object *bg;
19 Evas_Object *obj;
20
21 Evas_Object *colors;
22 int cpu_count;
23 int *cpu_order;
24
25 Eina_Bool show_cpufreq;
26 // Have cpu scaling
27 Eina_Bool cpu_freq;
28 int freq_min;
29 int freq_max;
30
31 Eina_Bool show_cputemp;
32 // Have temp readings.
33 Eina_Bool cpu_temp;
34 int temp_min;
35 int temp_max;
36
37 Eina_Bool confused;
38 Eina_List *explainers;
39
40 Evisum_Ui *ui;
41} Animate;
42
43typedef struct _Color_Point {
44 unsigned int val;
45 unsigned int color;
46} Color_Point;
47 6
48// config for colors/sizing 7// config for colors/sizing
49#define COLOR_CPU_NUM 5 8#define COLOR_CPU_NUM 5
50static const Color_Point cpu_colormap_in[] = { 9static const Color_Point cpu_colormap_in[] = {
51 { 0, 0xff202020 }, // 0 10 { 0, 0xff202020 },
52 { 25, 0xff2030a0 }, // 1 11 { 25, 0xff2030a0 },
53 { 50, 0xffa040a0 }, // 2 12 { 50, 0xffa040a0 },
54 { 75, 0xffff9040 }, // 3 13 { 75, 0xffff9040 },
55 { 100, 0xffffffff }, // 4 14 { 100, 0xffffffff },
56 { 256, 0xffffffff } // overflow to avoid if's 15 { 256, 0xffffffff }
57}; 16};
58#define COLOR_FREQ_NUM 4 17#define COLOR_FREQ_NUM 4
59static const Color_Point freq_colormap_in[] = { 18static const Color_Point freq_colormap_in[] = {
60 { 0, 0xff202020 }, // 0 19 { 0, 0xff202020 },
61 { 33, 0xff285020 }, // 1 20 { 33, 0xff285020 },
62 { 67, 0xff30a060 }, // 2 21 { 67, 0xff30a060 },
63 { 100, 0xffa0ff80 }, // 3 22 { 100, 0xffa0ff80 },
64 { 256, 0xffa0ff80 } // overflow to avoid if's 23 { 256, 0xffa0ff80 }
65}; 24};
66 25
67#define COLOR_TEMP_NUM 5 26#define COLOR_TEMP_NUM 5
@@ -74,281 +33,82 @@ static const Color_Point temp_colormap_in[] = {
74 { 256, 0xffdd776e } 33 { 256, 0xffdd776e }
75}; 34};
76 35
77#define BAR_HEIGHT 3 36unsigned int cpu_colormap[256];
78#define COLORS_HEIGHT 32 37unsigned int freq_colormap[256];
79#define CORES_MANY 16 38unsigned int temp_colormap[256];
80
81// stored colormap tables
82static unsigned int cpu_colormap[256];
83static unsigned int freq_colormap[256];
84static unsigned int temp_colormap[256];
85
86// handy macros to access argb values from pixels
87#define AVAL(x) (((x) >> 24) & 0xff)
88#define RVAL(x) (((x) >> 16) & 0xff)
89#define GVAL(x) (((x) >> 8) & 0xff)
90#define BVAL(x) (((x) ) & 0xff)
91#define ARGB(a, r, g, b) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))
92 39
93static void 40static void
94_color_init(const Color_Point *col_in, unsigned int n, unsigned int *col) 41_win_mouse_move_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
95{
96 unsigned int pos, interp, val, dist, d;
97 unsigned int a, r, g, b;
98 unsigned int a1, r1, g1, b1, v1;
99 unsigned int a2, r2, g2, b2, v2;
100
101 // wal colormap_in until colormap table is full
102 for (pos = 0, val = 0; pos < n; pos++)
103 {
104 // get first color and value position
105 v1 = col_in[pos].val;
106 a1 = AVAL(col_in[pos].color);
107 r1 = RVAL(col_in[pos].color);
108 g1 = GVAL(col_in[pos].color);
109 b1 = BVAL(col_in[pos].color);
110 // get second color and valuje position
111 v2 = col_in[pos + 1].val;
112 a2 = AVAL(col_in[pos + 1].color);
113 r2 = RVAL(col_in[pos + 1].color);
114 g2 = GVAL(col_in[pos + 1].color);
115 b2 = BVAL(col_in[pos + 1].color);
116 // get distance between values (how many entires to fill)
117 dist = v2 - v1;
118 // walk over the span of colors from point a to point b
119 for (interp = v1; interp < v2; interp++)
120 {
121 // distance from starting point
122 d = interp - v1;
123 // calculate linear interpolation between start and given d
124 a = ((d * a2) + ((dist - d) * a1)) / dist;
125 r = ((d * r2) + ((dist - d) * r1)) / dist;
126 g = ((d * g2) + ((dist - d) * g1)) / dist;
127 b = ((d * b2) + ((dist - d) * b1)) / dist;
128 // write out resulting color value
129 col[val] = ARGB(a, r, g, b);
130 val++;
131 }
132 }
133}
134
135static void
136_core_times_main_cb(void *data, Ecore_Thread *thread)
137{ 42{
138 Animate *ad = data; 43 Evas_Coord w, h;
139 int ncpu; 44 Evas_Event_Mouse_Move *ev;
140 45 Cpu_Visual *vis = data;
141 if (!system_cpu_frequency_min_max_get(&ad->freq_min, &ad->freq_max))
142 ad->cpu_freq = 1;
143 46
144 system_cpu_temperature_min_max_get(&ad->temp_min, &ad->temp_max); 47 ev = event_info;
145 if ((system_cpu_n_temperature_get(0)) != -1) 48 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
146 ad->cpu_temp = 1;
147 49
148 while (!ecore_thread_check(thread)) 50 if ((ev->cur.canvas.x >= (w - 128)) && (ev->cur.canvas.y <= 128))
149 { 51 {
150 cpu_core_t **cores = system_cpu_usage_delayed_get(&ncpu, 100000); 52 if (!vis->btn_visible)
151 Core *cores_out = calloc(ncpu, sizeof(Core)); 53 {
152 54 elm_object_signal_emit(vis->btn_menu, "menu,show", "evisum/menu");
153 if (cores_out) 55 vis->btn_visible = 1;
154 { 56 }
155 for (int n = 0; n < ncpu; n++)
156 {
157 int id = ad->cpu_order[n];
158 Core *core = &(cores_out[n]);
159 core->id = id;
160 core->percent = cores[id]->percent;
161 if (ad->cpu_freq)
162 core->freq = system_cpu_n_frequency_get(id);
163 if (ad->cpu_temp)
164 core->temp = system_cpu_n_temperature_get(id);
165 free(cores[id]);
166 }
167 ecore_thread_feedback(thread, cores_out);
168 }
169 free(cores);
170 } 57 }
58 else if ((vis->btn_visible) && (!vis->menu))
59 {
60 elm_object_signal_emit(vis->btn_menu, "menu,hide", "evisum/menu");
61 vis->btn_visible = 0;
62 }
171} 63}
172 64
173static void 65static void
174_update(Animate *ad, Core *cores) 66_win_key_down_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
175{ 67{
176 Evas_Object *obj = ad->obj; 68 Evas_Event_Key_Down *ev;
177 unsigned int *pixels, *pix; 69 Evisum_Ui *ui;
178 Evas_Coord x, y, w, h;
179 int iw, stride;
180 Eina_Bool clear = 0;
181
182 evas_object_geometry_get(obj, &x, &y, &w, &h);
183 evas_object_image_size_get(obj, &iw, NULL);
184 // if image pixel size doesn't match geom - we need to resize, so set
185 // new size and mark it for clearing when we fill
186 if (iw != w)
187 {
188 evas_object_image_size_set(obj, w, ad->cpu_count * 3);
189 clear = 1;
190 }
191
192 // get pixel data ptr
193 pixels = evas_object_image_data_get(obj, 1);
194 if (!pixels) return;
195 // get stride (# of bytes per line)
196 stride = evas_object_image_stride_get(obj);
197
198 for (y = 0; y < ad->cpu_count; y++)
199 {
200 Core *core = &(cores[y]);
201 unsigned int c1, c2;
202 70
203 // our pix ptr is the pixel row and y is both y pixel coord and core 71 ui = data;
204 if (clear) 72 ev = event_info;
205 {
206 // clear/fill with 0 value from colormap
207 pix = &(pixels[(y * 3) * (stride / 4)]);
208 for (x = 0; x < (w - 1); x++) pix[x] = cpu_colormap[0];
209 pix = &(pixels[((y * 3) + 1) * (stride / 4)]);
210 for (x = 0; x < (w - 1); x++) pix[x] = freq_colormap[0];
211 pix = &(pixels[((y * 3) + 2) * (stride / 4)]);
212 for (x = 0; x < (w - 1); x++) pix[x] = cpu_colormap[0];
213 }
214 else
215 {
216 // scroll pixels 1 to the left
217 pix = &(pixels[(y * 3) * (stride / 4)]);
218 for (x = 0; x < (w - 1); x++) pix[x] = pix[x + 1];
219 pix = &(pixels[((y * 3) + 1) * (stride / 4)]);
220 for (x = 0; x < (w - 1); x++) pix[x] = pix[x + 1];
221 pix = &(pixels[((y * 3) + 2) * (stride / 4)]);
222 for (x = 0; x < (w - 1); x++) pix[x] = pix[x + 1];
223 }
224 // final pixel on end of each row... set it to a new value
225 // get color from cpu colormap
226 // last pixel == resulting pixel color
227 c1 = cpu_colormap[core->percent & 0xff];
228 pix = &(pixels[(y * 3) * (stride / 4)]);
229 pix[x] = c1;
230 // 2nd row of pixles for freq
231 if ((ad->show_cpufreq) && (ad->cpu_freq))
232 {
233 int v = core->freq - ad->freq_min;
234 int d = ad->freq_max - ad->freq_min;
235
236 // if there is a difference between min and max ... a range
237 if (d > 0)
238 {
239 v = (100 * v) / d;
240 if (v < 0) v = 0;
241 else if (v > 100) v = 100;
242 // v now is 0->100 as a percentage of possible frequency
243 // the cpu can do
244 c2 = freq_colormap[v & 0xff];
245 }
246 else c2 = freq_colormap[0];
247 pix = &(pixels[((y * 3) + 1) * (stride / 4)]);
248 pix[x] = c2;
249 }
250 73
251 if (ad->show_cputemp && ad->cpu_temp) 74 if (!ev || !ev->keyname)
252 { 75 return;
253 pix = &(pixels[((y * 3) + 2) * (stride / 4)]);
254 pix[x] = temp_colormap[core->temp & 0xff];
255 }
256 76
257 if (!ad->show_cpufreq) 77 if (!strcmp(ev->keyname, "Escape"))
258 { 78 {
259 // no freq show - then just repeat cpu usage color 79 evas_object_del(ui->cpu.win);
260 pix = &(pixels[((y * 3) + 1) * (stride / 4)]);
261 pix[x] = c1;
262 }
263 if (!ad->show_cputemp)
264 {
265 pix = &(pixels[((y * 3) + 2) * (stride / 4)]);
266 pix[x] = c1;
267 }
268 } 80 }
269 // hand back pixel data ptr so evas knows we are done with it
270 evas_object_image_data_set(obj, pixels);
271 // now add update region for all pixels in the image at the end as we
272 // changed everything
273 evas_object_image_data_update_add(obj, 0, 0, w, ad->cpu_count * 3);
274} 81}
275 82
276typedef struct
277{
278 Evas_Object *lb;
279 Evas_Object *rec;
280} Explainer;
281
282static void 83static void
283_explain(Animate *ad, Core *cores) 84_btn_menu_clicked_cb(void *data, Evas_Object *obj,
85 void *event_info EINA_UNUSED)
284{ 86{
285 Eina_Strbuf *buf; 87 Evisum_Ui *ui;
286 Explainer *exp; 88 Cpu_Visual *vis = data;
287 Evas_Object *lb, *rec;
288
289 if (!ad->explainers) return;
290
291 buf = eina_strbuf_new();
292 89
293 for (int i = 0; i < ad->cpu_count; i++) 90 ui = vis->ui;
91 if (!vis->menu)
92 vis->menu = evisum_ui_main_menu_create(ui, ui->cpu.win, obj);
93 else
294 { 94 {
295 Core *core = &(cores[i]); 95 evas_object_del(vis->menu);
296 exp = eina_list_nth(ad->explainers, i); 96 vis->menu = NULL;
297
298 lb = exp->lb;
299 rec = exp->rec;
300 if (!ad->confused)
301 {
302 evas_object_hide(rec);
303 evas_object_hide(lb);
304 }
305 else
306 {
307 eina_strbuf_append_printf(buf, "<b><color=#fff>%i%% ", core->percent);
308 if (ad->cpu_freq)
309 eina_strbuf_append_printf(buf, "%1.1fGHz ", (double) core->freq / 1000000);
310 if (ad->cpu_temp)
311 eina_strbuf_append_printf(buf, "%i°C", core->temp);
312 eina_strbuf_append(buf, "</></>");
313
314 elm_object_text_set(lb, eina_strbuf_string_get(buf));
315 eina_strbuf_reset(buf);
316 evas_object_show(rec);
317 evas_object_show(lb);
318 }
319 } 97 }
320 eina_strbuf_free(buf);
321} 98}
322 99
323static void 100static void
324_core_times_feedback_cb(void *data, Ecore_Thread *thread EINA_UNUSED, void *msgdata) 101_win_resize_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
325{ 102{
326 Animate *ad; 103 Evisum_Ui *ui = data;
327 Core *cores;
328 static Eina_Bool was_confused = 0;
329
330 ad = data;
331 cores = msgdata;
332
333 _update(ad, cores);
334
335 if (ad->confused || was_confused)
336 {
337 _explain(ad, cores);
338 was_confused = 1;
339 }
340 104
341 free(cores); 105 evas_object_geometry_get(obj, NULL, NULL, &ui->cpu.width, &ui->cpu.height);
342} 106}
343 107
344static void 108static void
345_win_move_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED) 109_win_move_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info EINA_UNUSED)
346{ 110{
347 Animate *ad; 111 Evisum_Ui *ui = data;
348 Evisum_Ui *ui;
349
350 ad = data;
351 ui = ad->ui;
352 112
353 evas_object_geometry_get(obj, &ui->cpu.x, &ui->cpu.y, NULL, NULL); 113 evas_object_geometry_get(obj, &ui->cpu.x, &ui->cpu.y, NULL, NULL);
354} 114}
@@ -356,444 +116,102 @@ _win_move_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void *event_info
356static void 116static void
357_win_del_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED) 117_win_del_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUSED)
358{ 118{
359 Explainer *exp; 119 Cpu_Visual *vis = data;
360 Animate *ad = data; 120 Evisum_Ui *ui = vis->ui;
361 Evisum_Ui *ui = ad->ui;
362 121
363 evisum_ui_config_save(ui); 122 evisum_ui_config_save(ui);
364 ecore_thread_cancel(ad->thread); 123 ecore_thread_cancel(vis->thread);
365 ecore_thread_wait(ad->thread, 0.5); 124 ecore_thread_wait(vis->thread, 0.5);
366 125
367 EINA_LIST_FREE(ad->explainers, exp) 126 if (vis->ext_free_cb)
368 { 127 vis->ext_free_cb(vis->ext);
369 free(exp);
370 }
371 128
372 ad->explainers = NULL; 129 free(vis);
373 free(ad->cpu_order);
374 free(ad);
375 ui->cpu.win = NULL; 130 ui->cpu.win = NULL;
376} 131}
377 132
378static void 133static void
379_check_changed_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED, 134_color_init(const Color_Point *col_in, unsigned int n, unsigned int *col)
380 void *event_info EINA_UNUSED)
381{
382 Animate *ad = data;
383
384 ad->show_cpufreq = elm_check_state_get(obj);
385}
386
387static void
388_temp_check_changed_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
389 void *event_info EINA_UNUSED)
390{
391 Animate *ad = data;
392
393 ad->show_cputemp = elm_check_state_get(obj);
394}
395
396static void
397_confused_check_changed_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
398 void *event_info EINA_UNUSED)
399{
400 Animate *ad = data;
401
402 ad->confused = elm_check_state_get(obj);
403}
404
405static void
406_colors_fill(Evas_Object *colors)
407{
408 // fill a 3 pixel high (and 100 wide) image with 3 gradients matching
409 // the colormaps we calculated as a legend
410 int x, stride;
411 unsigned int *pixels;
412
413 evas_object_image_size_set(colors, 101, 3);
414 pixels = evas_object_image_data_get(colors, 1);
415 if (!pixels) return;
416 stride = evas_object_image_stride_get(colors);
417 // cpu percent (first row)
418 for (x = 0; x <= 100; x++) pixels[x] = cpu_colormap[x];
419 // cpu freq (next row)
420 for (x = 0; x <= 100; x++) pixels[x + (stride / 4)] = freq_colormap[x];
421 // cpu temp (next row)
422 for (x = 0; x <= 100; x++) pixels[x + (stride / 2)] = temp_colormap[x];
423
424 evas_object_image_data_set(colors, pixels);
425 evas_object_image_data_update_add(colors, 0, 0, 101, 1);
426}
427
428static void
429_win_mouse_move_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
430{ 135{
431 Evas_Coord w, h; 136 unsigned int pos, interp, val, dist, d;
432 Evas_Event_Mouse_Move *ev; 137 unsigned int a, r, g, b;
433 Animate *ad = data; 138 unsigned int a1, r1, g1, b1, v1;
434 139 unsigned int a2, r2, g2, b2, v2;
435 ev = event_info;
436 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
437 140
438 if ((ev->cur.canvas.x >= (w - 128)) && (ev->cur.canvas.y <= 128)) 141 // wal colormap_in until colormap table is full
142 for (pos = 0, val = 0; pos < n; pos++)
439 { 143 {
440 if (!ad->btn_visible) 144 // get first color and value position
441 { 145 v1 = col_in[pos].val;
442 elm_object_signal_emit(ad->btn_menu, "menu,show", "evisum/menu"); 146 a1 = AVAL(col_in[pos].color);
443 ad->btn_visible = 1; 147 r1 = RVAL(col_in[pos].color);
444 } 148 g1 = GVAL(col_in[pos].color);
149 b1 = BVAL(col_in[pos].color);
150 // get second color and valuje position
151 v2 = col_in[pos + 1].val;
152 a2 = AVAL(col_in[pos + 1].color);
153 r2 = RVAL(col_in[pos + 1].color);
154 g2 = GVAL(col_in[pos + 1].color);
155 b2 = BVAL(col_in[pos + 1].color);
156 // get distance between values (how many entires to fill)
157 dist = v2 - v1;
158 // walk over the span of colors from point a to point b
159 for (interp = v1; interp < v2; interp++)
160 {
161 // distance from starting point
162 d = interp - v1;
163 // calculate linear interpolation between start and given d
164 a = ((d * a2) + ((dist - d) * a1)) / dist;
165 r = ((d * r2) + ((dist - d) * r1)) / dist;
166 g = ((d * g2) + ((dist - d) * g1)) / dist;
167 b = ((d * b2) + ((dist - d) * b1)) / dist;
168 // write out resulting color value
169 col[val] = ARGB(a, r, g, b);
170 val++;
171 }
445 } 172 }
446 else if ((ad->btn_visible) && (!ad->menu))
447 {
448 elm_object_signal_emit(ad->btn_menu, "menu,hide", "evisum/menu");
449 ad->btn_visible = 0;
450 }
451} 173}
452 174
453static void 175Eina_List *
454_win_key_down_cb(void *data, Evas *e, Evas_Object *obj, void *event_info) 176ui_cpu_visuals_get(void)
455{ 177{
456 Evas_Event_Key_Down *ev; 178 Eina_List *l = NULL;
457 Animate *ad;
458 179
459 ad = data; 180 for (int i = 0; (i < sizeof(visualizations) / sizeof(Visualization)); i++)
460 ev = event_info;
461
462 if (!ev || !ev->keyname)
463 return;
464
465 if (!strcmp(ev->keyname, "Escape"))
466 evas_object_del(ad->ui->cpu.win);
467}
468
469static void
470_btn_menu_clicked_cb(void *data, Evas_Object *obj,
471 void *event_info EINA_UNUSED)
472{
473 Evisum_Ui *ui;
474 Animate *ad = data;
475
476 ui = ad->ui;
477 if (!ad->menu)
478 ad->menu = evisum_ui_main_menu_create(ui, ui->cpu.win, obj);
479 else
480 { 181 {
481 evas_object_del(ad->menu); 182 l = eina_list_append(l, strdup(visualizations[i].name));
482 ad->menu = NULL;
483 } 183 }
184
185 return l;
484} 186}
485 187
486static Animate * 188Visualization *
487_graph(Evisum_Ui *ui, Evas_Object *parent) 189ui_cpu_visual_by_name(const char *name)
488{ 190{
489 Evas_Object *tbl, *tbl2, *box, *obj, *ic, *lb, *rec; 191 for (int i = 0; (i < sizeof(visualizations) / sizeof(Visualization)); i++)
490 Evas_Object *fr, *bx, *hbx, *colors, *check, *btn;
491 Elm_Layout *lay;
492 int i, f;
493 char buf[128];
494 Eina_Bool show_icons = 1;
495
496 Animate *ad = calloc(1, sizeof(Animate));
497 if (!ad) return NULL;
498
499 ad->win = ui->cpu.win;
500 ad->cpu_count = system_cpu_count_get();
501 if (!system_cpu_frequency_min_max_get(&ad->freq_min, &ad->freq_max))
502 ad->cpu_freq = 1;
503
504 system_cpu_temperature_min_max_get(&ad->temp_min, &ad->temp_max);
505 if ((system_cpu_n_temperature_get(0)) != -1)
506 ad->cpu_temp = 1;
507
508 ad->cpu_order = malloc((ad->cpu_count) * sizeof(int));
509 for (i = 0; i < ad->cpu_count; i++)
510 ad->cpu_order[i] = i;
511 system_cpu_topology_get(ad->cpu_order, ad->cpu_count);
512
513 // init colormaps from a small # of points
514 _color_init(cpu_colormap_in, COLOR_CPU_NUM, cpu_colormap);
515 _color_init(freq_colormap_in, COLOR_FREQ_NUM, freq_colormap);
516 _color_init(temp_colormap_in, COLOR_TEMP_NUM, temp_colormap);
517
518 box = parent;
519
520 tbl = elm_table_add(box);
521 evas_object_size_hint_align_set(tbl, FILL, FILL);
522 evas_object_size_hint_weight_set(tbl, EXPAND, EXPAND);
523 evas_object_show(tbl);
524
525 obj = evas_object_image_add(evas_object_evas_get(parent));
526 evas_object_size_hint_align_set(obj, FILL, FILL);
527 evas_object_size_hint_weight_set(obj, EXPAND, EXPAND);
528 evas_object_image_smooth_scale_set(obj, 0);
529 evas_object_image_filled_set(obj, 1);
530 evas_object_image_alpha_set(obj, 0);
531 evas_object_show(obj);
532
533 elm_table_pack(tbl, obj, 0, 0, 5, ad->cpu_count);
534
535 if (ad->cpu_count > CORES_MANY)
536 show_icons = 0;
537
538 if (show_icons)
539 {
540 rec = evas_object_rectangle_add(evas_object_evas_get(parent));
541 evas_object_size_hint_align_set(rec, FILL, FILL);
542 evas_object_size_hint_weight_set(rec, EXPAND, EXPAND);
543 evas_object_color_set(rec, 0, 0, 0, 64);
544 evas_object_show(rec);
545 elm_table_pack(tbl, rec, 0, 0, 4, ad->cpu_count);
546 }
547
548 for (i = 0; show_icons && (i < ad->cpu_count); i++)
549 { 192 {
550 rec = evas_object_rectangle_add(evas_object_evas_get(parent)); 193 if (!strcmp(name, visualizations[i].name))
551 evas_object_color_set(rec, 0, 0, 0, 0); 194 return &visualizations[i];
552 evas_object_size_hint_min_set(rec, ELM_SCALE_SIZE(8), ELM_SCALE_SIZE(8));
553 evas_object_size_hint_weight_set(rec, 0.0, EXPAND);
554 elm_table_pack(tbl, rec, 0, i, 1, 1);
555
556 rec = evas_object_rectangle_add(evas_object_evas_get(parent));
557 evas_object_color_set(rec, 0, 0, 0, 0);
558 evas_object_size_hint_min_set(rec, ELM_SCALE_SIZE(24), ELM_SCALE_SIZE(24));
559 evas_object_size_hint_weight_set(rec, 0.0, EXPAND);
560 elm_table_pack(tbl, rec, 1, i, 1, 1);
561
562 ic = elm_icon_add(parent);
563 elm_icon_standard_set(ic, evisum_icon_path_get("cpu"));
564 evas_object_size_hint_align_set(ic, FILL, FILL);
565 evas_object_size_hint_weight_set(ic, 0.0, EXPAND);
566 elm_table_pack(tbl, ic, 1, i, 1, 1);
567 evas_object_show(ic);
568
569 rec = evas_object_rectangle_add(evas_object_evas_get(parent));
570 evas_object_color_set(rec, 0, 0, 0, 0);
571 evas_object_size_hint_min_set(rec, ELM_SCALE_SIZE(8), ELM_SCALE_SIZE(8));
572 evas_object_size_hint_weight_set(rec, 0.0, EXPAND);
573 elm_table_pack(tbl, rec, 2, i, 1, 1);
574
575 rec = evas_object_rectangle_add(evas_object_evas_get(parent));
576 evas_object_color_set(rec, 0, 0, 0, 0);
577 evas_object_size_hint_min_set(rec, ELM_SCALE_SIZE(16), ELM_SCALE_SIZE(16));
578 evas_object_size_hint_weight_set(rec, 0.0, EXPAND);
579 elm_table_pack(tbl, rec, 3, i, 1, 1);
580
581 lb = elm_label_add(parent);
582 snprintf(buf, sizeof(buf), "<b><color=#fff>%i</></>", ad->cpu_order[i]);
583 elm_object_text_set(lb, buf);
584 evas_object_size_hint_align_set(lb, 0.0, 0.5);
585 evas_object_size_hint_weight_set(lb, 0.0, EXPAND);
586 elm_table_pack(tbl, lb, 3, i, 1, 1);
587 evas_object_show(lb);
588
589 // Begin explainer label overlay.
590
591 tbl2 = elm_table_add(parent);
592 evas_object_size_hint_align_set(tbl2, 0.7, 0.5);
593 evas_object_size_hint_weight_set(tbl2, EXPAND, EXPAND);
594 evas_object_show(tbl2);
595
596 rec = evas_object_rectangle_add(evas_object_evas_get(parent));
597 evas_object_color_set(rec, 0, 0, 0, 128);
598 evas_object_size_hint_align_set(rec, FILL, FILL);
599 evas_object_size_hint_weight_set(rec, EXPAND, EXPAND);
600 elm_table_pack(tbl2, rec, 0, 0, 1, 1);
601
602 lb = elm_label_add(parent);
603 evas_object_size_hint_align_set(lb, FILL, FILL);
604 evas_object_size_hint_weight_set(lb, EXPAND, EXPAND);
605 elm_object_text_set(lb, buf);
606 elm_table_pack(tbl2, lb, 0, 0, 1, 1);
607 elm_table_pack(tbl, tbl2, 4, i, 1, 1);
608
609 Explainer *exp = malloc(sizeof(Explainer));
610 exp->rec = rec;
611 exp->lb = lb;
612
613 ad->explainers = eina_list_append(ad->explainers, exp);
614 } 195 }
615 196 return NULL;
616 btn = elm_button_add(parent);
617 ic = elm_icon_add(btn);
618 elm_icon_standard_set(ic, evisum_icon_path_get("menu"));
619 elm_object_part_content_set(btn, "icon", ic);
620 evas_object_show(ic);
621 elm_object_focus_allow_set(btn, 0);
622 evas_object_size_hint_min_set(btn, ELM_SCALE_SIZE(BTN_HEIGHT), ELM_SCALE_SIZE(BTN_HEIGHT));
623 evas_object_smart_callback_add(btn, "clicked", _btn_menu_clicked_cb, ad);
624
625 ad->btn_menu = lay = elm_layout_add(parent);
626 evas_object_size_hint_weight_set(lay, 1.0, 1.0);
627 evas_object_size_hint_align_set(lay, 0.99, 0.01);
628 elm_layout_file_set(lay, PACKAGE_DATA_DIR "/themes/evisum.edj", "cpu");
629 elm_layout_content_set(lay, "evisum/menu", btn);
630 elm_table_pack(tbl, lay, 0, 0, 5, ad->cpu_count);
631 evas_object_show(lay);
632
633 bx = elm_box_add(box);
634 evas_object_size_hint_align_set(bx, FILL, FILL);
635 evas_object_size_hint_weight_set(bx, EXPAND, EXPAND);
636 evas_object_show(bx);
637 elm_box_pack_end(bx, tbl);
638
639 // Set the main content.
640 elm_box_pack_end(box, bx);
641
642 tbl = elm_table_add(box);
643 evas_object_size_hint_align_set(tbl, FILL, FILL);
644 evas_object_size_hint_weight_set(tbl, EXPAND, 0);
645 evas_object_show(tbl);
646
647 fr = elm_frame_add(box);
648 evas_object_size_hint_align_set(fr, FILL, FILL);
649 evas_object_size_hint_weight_set(fr, EXPAND, 0);
650 evas_object_show(fr);
651 elm_object_text_set(fr, _("Legend"));
652 elm_object_content_set(fr, tbl);
653
654 colors = evas_object_image_add(evas_object_evas_get(fr));
655 evas_object_size_hint_min_set
656 (colors, 100, COLORS_HEIGHT * elm_config_scale_get());
657 evas_object_size_hint_align_set(colors, FILL, FILL);
658 evas_object_size_hint_weight_set(colors, EXPAND, EXPAND);
659 evas_object_image_smooth_scale_set(colors, 0);
660 evas_object_image_filled_set(colors, 1);
661 evas_object_image_alpha_set(colors, 0);
662 _colors_fill(colors);
663 elm_table_pack(tbl, colors, 0, 0, 2, 3);
664 evas_object_show(colors);
665
666 lb = elm_label_add(parent);
667 elm_object_text_set(lb, "<b><color=#fff> 0%</></>");
668 evas_object_size_hint_align_set(lb, 0.0, 0.5);
669 evas_object_size_hint_weight_set(lb, EXPAND, EXPAND);
670 elm_table_pack(tbl, lb, 0, 0, 1, 1);
671 evas_object_show(lb);
672
673 lb = elm_label_add(parent);
674 f = (ad->freq_min + 500) / 1000;
675 if (f < 1000)
676 snprintf(buf, sizeof(buf), "<b><color=#fff> %iMHz</></>", f);
677 else
678 snprintf(buf, sizeof(buf), "<b><color=#fff> %1.1fGHz</></>", ((double)f + 0.05) / 1000.0);
679 elm_object_text_set(lb, buf);
680 evas_object_size_hint_align_set(lb, 0.0, 0.5);
681 evas_object_size_hint_weight_set(lb, EXPAND, EXPAND);
682 elm_table_pack(tbl, lb, 0, 1, 1, 1);
683 evas_object_show(lb);
684
685 lb = elm_label_add(parent);
686 elm_object_text_set(lb, "<b><color=#fff>100%</></>");
687 evas_object_size_hint_align_set(lb, 0.99, 0.5);
688 evas_object_size_hint_weight_set(lb, EXPAND, EXPAND);
689 elm_table_pack(tbl, lb, 1, 0, 1, 1);
690 evas_object_show(lb);
691
692 lb = elm_label_add(parent);
693 f = (ad->freq_max + 500) / 1000;
694 if (f < 1000)
695 snprintf(buf, sizeof(buf), "<b><color=#fff>%iMHz</></>", f);
696 else
697 snprintf(buf, sizeof(buf), "<b><color=#fff>%1.1fGHz</></>", ((double)f + 0.05) / 1000.0);
698 elm_object_text_set(lb, buf);
699 evas_object_size_hint_align_set(lb, 0.99, 0.5);
700 evas_object_size_hint_weight_set(lb, EXPAND, EXPAND);
701 elm_table_pack(tbl, lb, 1, 1, 1, 1);
702 evas_object_show(lb);
703
704 lb = elm_label_add(parent);
705 snprintf(buf, sizeof(buf), "<b><color=#fff> %i°C</></>", ad->temp_min);
706 elm_object_text_set(lb, buf);
707 evas_object_size_hint_align_set(lb, 0.0, 0.5);
708 evas_object_size_hint_weight_set(lb, EXPAND, EXPAND);
709 elm_table_pack(tbl, lb, 0, 2, 1, 1);
710 evas_object_show(lb);
711
712 lb = elm_label_add(parent);
713 snprintf(buf, sizeof(buf), "<b><color=#fff>%i°C</></>", ad->temp_max);
714 elm_object_text_set(lb, buf);
715 evas_object_size_hint_align_set(lb, 0.99, 0.5);
716 evas_object_size_hint_weight_set(lb, EXPAND, EXPAND);
717 elm_table_pack(tbl, lb, 1, 2, 1, 1);
718 evas_object_show(lb);
719
720 elm_box_pack_end(box, fr);
721
722 fr = elm_frame_add(box);
723 elm_frame_autocollapse_set(fr, 1);
724 evas_object_size_hint_align_set(fr, FILL, FILL);
725 evas_object_size_hint_weight_set(fr, EXPAND, 0);
726 evas_object_show(fr);
727 elm_frame_collapse_set(fr, 0);
728 elm_object_text_set(fr, _("Options"));
729 elm_box_pack_end(box, fr);
730
731 hbx = elm_box_add(fr);
732 evas_object_size_hint_align_set(hbx, FILL, FILL);
733 evas_object_size_hint_weight_set(hbx, EXPAND, 0);
734 elm_box_horizontal_set(hbx, 1);
735 evas_object_show(hbx);
736 elm_object_content_set(fr, hbx);
737
738 check = elm_check_add(fr);
739 evas_object_size_hint_align_set(check, FILL, FILL);
740 evas_object_size_hint_weight_set(check, EXPAND, 0);
741 elm_object_text_set(check, _("Overlay CPU frequency?"));
742 if (!ad->cpu_freq) elm_object_disabled_set(check, 1);
743 evas_object_show(check);
744 elm_box_pack_end(hbx, check);
745 evas_object_smart_callback_add(check, "changed", _check_changed_cb, ad);
746
747 check = elm_check_add(fr);
748 evas_object_size_hint_align_set(check, FILL, FILL);
749 evas_object_size_hint_weight_set(check, EXPAND, 0);
750 elm_object_text_set(check, _("Overlay CPU temperatures?"));
751 if (!ad->cpu_temp) elm_object_disabled_set(check, 1);
752 evas_object_smart_callback_add(check, "changed", _temp_check_changed_cb, ad);
753 evas_object_show(check);
754 elm_box_pack_end(hbx, check);
755
756 check = elm_check_add(fr);
757 evas_object_size_hint_align_set(check, FILL, FILL);
758 evas_object_size_hint_weight_set(check, EXPAND, 0);
759 elm_object_text_set(check, _("Confused?"));
760 evas_object_smart_callback_add(check, "changed", _confused_check_changed_cb, ad);
761 evas_object_show(check);
762 elm_box_pack_end(hbx, check);
763
764 ad->obj = obj;
765 ad->ui = ui;
766 ad->colors = colors;
767
768 // min size of cpu color graph to show all cores.
769 evas_object_size_hint_min_set
770 (obj, 100, (BAR_HEIGHT * ad->cpu_count) * elm_config_scale_get());
771
772 evas_object_event_callback_add(ui->cpu.win, EVAS_CALLBACK_DEL, _win_del_cb, ad);
773 evas_object_event_callback_add(ui->cpu.win, EVAS_CALLBACK_MOVE, _win_move_cb, ad);
774
775 // run a feedback thread that sends feedback to the mainloop
776 ad->thread = ecore_thread_feedback_run(_core_times_main_cb,
777 _core_times_feedback_cb,
778 NULL,
779 NULL,
780 ad, 1);
781 return ad;
782} 197}
783 198
784 static void 199void
785_win_resize_cb(void *data, Evas *e, Evas_Object *obj, void *event_info) 200ui_cpu_win_restart(Evisum_Ui *ui)
786{ 201{
787 Evisum_Ui *ui = data; 202 evas_object_del(ui->cpu.win);
788 203 ui_cpu_win_add(ui);
789 evas_object_geometry_get(obj, NULL, NULL, &ui->cpu.width, &ui->cpu.height);
790} 204}
791 205
792void 206void
793ui_cpu_win_add(Evisum_Ui *ui) 207ui_cpu_win_add(Evisum_Ui *ui)
794{ 208{
795 Animate *ad; 209 Cpu_Visual *vis;
796 Evas_Object *win, *box, *scr; 210 Evas_Object *win, *box, *scr, *btn, *ic;
211 Evas_Object *tb;
212 Elm_Layout *lay;
213 Visualization *visualization;
214 static Eina_Bool init = 0;
797 215
798 if (ui->cpu.win) 216 if (ui->cpu.win)
799 { 217 {
@@ -801,13 +219,20 @@ ui_cpu_win_add(Evisum_Ui *ui)
801 return; 219 return;
802 } 220 }
803 221
222 if (!init)
223 {
224 // init colormaps from a small # of points
225 _color_init(cpu_colormap_in, COLOR_CPU_NUM, cpu_colormap);
226 _color_init(freq_colormap_in, COLOR_FREQ_NUM, freq_colormap);
227 _color_init(temp_colormap_in, COLOR_TEMP_NUM, temp_colormap);
228 init = 1;
229 }
230
804 ui->cpu.win = win = elm_win_util_standard_add("evisum", 231 ui->cpu.win = win = elm_win_util_standard_add("evisum",
805 _("CPU Activity")); 232 _("CPU Activity"));
806 elm_win_autodel_set(win, 1); 233 elm_win_autodel_set(win, 1);
807 evas_object_size_hint_weight_set(win, EXPAND, EXPAND); 234 evas_object_size_hint_weight_set(win, EXPAND, EXPAND);
808 evas_object_size_hint_align_set(win, FILL, FILL); 235 evas_object_size_hint_align_set(win, FILL, FILL);
809 evas_object_event_callback_add(win, EVAS_CALLBACK_RESIZE,
810 _win_resize_cb, ui);
811 236
812 scr = elm_scroller_add(win); 237 scr = elm_scroller_add(win);
813 evas_object_size_hint_weight_set(scr, EXPAND, EXPAND); 238 evas_object_size_hint_weight_set(scr, EXPAND, EXPAND);
@@ -816,17 +241,48 @@ ui_cpu_win_add(Evisum_Ui *ui)
816 ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_AUTO); 241 ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_AUTO);
817 evas_object_show(scr); 242 evas_object_show(scr);
818 243
244 tb = elm_table_add(win);
245 evas_object_size_hint_align_set(tb, FILL, FILL);
246 evas_object_size_hint_weight_set(tb, EXPAND, EXPAND);
247 evas_object_show(tb);
248
819 box = elm_box_add(win); 249 box = elm_box_add(win);
820 evas_object_size_hint_align_set(box, FILL, FILL); 250 evas_object_size_hint_align_set(box, FILL, FILL);
821 evas_object_size_hint_weight_set(box, EXPAND, EXPAND); 251 evas_object_size_hint_weight_set(box, EXPAND, EXPAND);
822 evas_object_show(box); 252 evas_object_show(box);
823 253
824 ad = _graph(ui, box); 254 elm_table_pack(tb, box, 0, 0, 1, 1);
825 evas_object_event_callback_add(scr, EVAS_CALLBACK_KEY_DOWN, _win_key_down_cb, ad); 255
826 evas_object_event_callback_add(scr, EVAS_CALLBACK_MOUSE_MOVE, _win_mouse_move_cb, ad); 256 visualization = ui_cpu_visual_by_name(ui->cpu.visual);
827 elm_object_content_set(scr, box); 257 vis = visualization->func(box);
258 vis->ui = ui;
259
260 elm_object_content_set(scr, tb);
828 elm_object_content_set(win, scr); 261 elm_object_content_set(win, scr);
829 262
263 btn = elm_button_add(win);
264 ic = elm_icon_add(btn);
265 elm_icon_standard_set(ic, evisum_icon_path_get("menu"));
266 elm_object_part_content_set(btn, "icon", ic);
267 evas_object_show(ic);
268 elm_object_focus_allow_set(btn, 0);
269 evas_object_size_hint_min_set(btn, ELM_SCALE_SIZE(BTN_HEIGHT), ELM_SCALE_SIZE(BTN_HEIGHT));
270 evas_object_smart_callback_add(btn, "clicked", _btn_menu_clicked_cb, vis);
271
272 vis->btn_menu = lay = elm_layout_add(win);
273 evas_object_size_hint_weight_set(lay, 1.0, 1.0);
274 evas_object_size_hint_align_set(lay, 0.99, 0.01);
275 elm_layout_file_set(lay, PACKAGE_DATA_DIR "/themes/evisum.edj", "cpu");
276 elm_layout_content_set(lay, "evisum/menu", btn);
277 elm_table_pack(tb, lay, 0, 0, 1, 1);
278 evas_object_show(lay);
279
280 evas_object_event_callback_add(scr, EVAS_CALLBACK_MOUSE_MOVE, _win_mouse_move_cb, vis);
281 evas_object_event_callback_add(scr, EVAS_CALLBACK_KEY_DOWN, _win_key_down_cb, ui);
282 evas_object_event_callback_add(win, EVAS_CALLBACK_RESIZE, _win_resize_cb, ui);
283 evas_object_event_callback_add(win, EVAS_CALLBACK_RESIZE, _win_move_cb, ui);
284 evas_object_event_callback_add(win, EVAS_CALLBACK_DEL, _win_del_cb, vis);
285
830 if ((ui->cpu.width > 0) && (ui->cpu.height > 0)) 286 if ((ui->cpu.width > 0) && (ui->cpu.height > 0))
831 evas_object_resize(win, ui->cpu.width, ui->cpu.height); 287 evas_object_resize(win, ui->cpu.width, ui->cpu.height);
832 else 288 else
diff --git a/src/bin/ui/ui_cpu.h b/src/bin/ui/ui_cpu.h
index bffbcc0..9f31a6b 100644
--- a/src/bin/ui/ui_cpu.h
+++ b/src/bin/ui/ui_cpu.h
@@ -4,7 +4,57 @@
4#include "evisum_ui.h" 4#include "evisum_ui.h"
5#include "../system/machine.h" 5#include "../system/machine.h"
6 6
7typedef struct _Color_Point {
8 unsigned int val;
9 unsigned int color;
10} Color_Point;
11
12extern unsigned int cpu_colormap[256];
13extern unsigned int freq_colormap[256];
14extern unsigned int temp_colormap[256];
15
16#define AVAL(x) (((x) >> 24) & 0xff)
17#define RVAL(x) (((x) >> 16) & 0xff)
18#define GVAL(x) (((x) >> 8) & 0xff)
19#define BVAL(x) (((x) ) & 0xff)
20#define ARGB(a, r, g, b) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))
21
22typedef struct {
23 short id;
24 short percent;
25 unsigned int freq;
26 unsigned int temp;
27} Core;
28
29typedef struct {
30 Evisum_Ui *ui;
31 Ecore_Thread *thread;
32
33 Evas_Object *menu;
34 Elm_Layout *btn_menu;
35 Eina_Bool btn_visible;
36
37 // Callback to free user data.
38 void (*ext_free_cb)(void *);
39 void *ext;
40
41} Cpu_Visual;
42
43typedef struct {
44 const char *name;
45 Cpu_Visual *(*func)(Evas_Object *parent);
46} Visualization;
47
7void 48void
8ui_cpu_win_add(Evisum_Ui *ui); 49ui_cpu_win_add(Evisum_Ui *ui);
9 50
51void
52ui_cpu_win_restart(Evisum_Ui *ui);
53
54Eina_List *
55ui_cpu_visuals_get(void);
56
57Visualization *
58ui_cpu_visual_by_name(const char *name);
59
10#endif 60#endif
diff --git a/src/bin/ui/ui_process_list.c b/src/bin/ui/ui_process_list.c
index 01fe399..b9cead5 100644
--- a/src/bin/ui/ui_process_list.c
+++ b/src/bin/ui/ui_process_list.c
@@ -2317,6 +2317,9 @@ _win_del_cb(void *data EINA_UNUSED, Evas *e EINA_UNUSED,
2317 2317
2318 evisum_ui_config_save(ui); 2318 evisum_ui_config_save(ui);
2319 2319
2320 if (wd->fields_timer)
2321 ecore_timer_del(wd->fields_timer);
2322
2320 if (wd->search.timer) 2323 if (wd->search.timer)
2321 ecore_timer_del(wd->search.timer); 2324 ecore_timer_del(wd->search.timer);
2322 2325
diff --git a/src/bin/ui/visuals/cpu_basic.c b/src/bin/ui/visuals/cpu_basic.c
new file mode 100644
index 0000000..a69ac28
--- /dev/null
+++ b/src/bin/ui/visuals/cpu_basic.c
@@ -0,0 +1,130 @@
1#include "cpu_basic.h"
2
3typedef struct {
4 int cpu_count;
5 int *cpu_order;
6 Eina_List *objects;
7} Ext;
8
9static void
10_core_times_main_cb(void *data, Ecore_Thread *thread)
11{
12 int ncpu;
13 Cpu_Visual *vis = data;
14 Ext *ext = vis->ext;
15
16 while (!ecore_thread_check(thread))
17 {
18 cpu_core_t **cores = system_cpu_usage_delayed_get(&ncpu, 100000);
19 Core *cores_out = calloc(ncpu, sizeof(Core));
20
21 if (cores_out)
22 {
23 for (int n = 0; n < ncpu; n++)
24 {
25 int id = ext->cpu_order[n];
26 Core *core = &(cores_out[n]);
27 core->id = id;
28 core->percent = cores[id]->percent;
29 free(cores[id]);
30 }
31 ecore_thread_feedback(thread, cores_out);
32 }
33 free(cores);
34 }
35}
36
37static void
38_core_times_feedback_cb(void *data, Ecore_Thread *thread EINA_UNUSED, void *msgdata)
39{
40 Cpu_Visual *vis;
41 Core *cores;
42 Ext *ext;
43
44 vis = data;
45 ext = vis->ext;
46 cores = msgdata;
47
48 for (int i = 0; i < ext->cpu_count; i++)
49 {
50 Core *core = &cores[i];
51 Evas_Object *lb = eina_list_nth(ext->objects, i);
52 Evas_Object *rec = evas_object_data_get(lb, "r");
53 int c = cpu_colormap[core->percent & 0xff];
54 evas_object_color_set(rec, RVAL(c), GVAL(c), BVAL(c), AVAL(c));
55
56 elm_object_text_set(lb, eina_slstr_printf("%d%%", core->percent));
57 }
58
59 free(cores);
60}
61
62static void
63_cb_free(void *data)
64{
65 Ext *ext = data;
66
67 eina_list_free(ext->objects);
68
69 free(ext->cpu_order);
70 free(ext);
71}
72
73Cpu_Visual *
74cpu_visual_basic(Evas_Object *parent_bx)
75{
76 Evas_Object *tb;
77 Ext *ext;
78
79 Cpu_Visual *vis = calloc(1, sizeof(Cpu_Visual));
80 if (!vis) return NULL;
81
82 vis->ext = ext = calloc(1, sizeof(Ext));
83 EINA_SAFETY_ON_NULL_RETURN_VAL(ext, NULL);
84 vis->ext_free_cb = _cb_free;
85
86 /* Populate lookup table to match id with topology core id */
87 ext->cpu_count = system_cpu_count_get();
88 ext->cpu_order = malloc((ext->cpu_count) * sizeof(int));
89 for (int i = 0; i < ext->cpu_count; i++)
90 ext->cpu_order[i] = i;
91 system_cpu_topology_get(ext->cpu_order, ext->cpu_count);
92
93 tb = elm_table_add(parent_bx);
94 evas_object_size_hint_weight_set(tb, EXPAND, EXPAND);
95 evas_object_size_hint_align_set(tb, 0.5, 0.5);
96 evas_object_show(tb);
97
98 int row = 0, col = 0;
99 int w = sqrt(ext->cpu_count);
100 for (int i = 0; i < ext->cpu_count; i++)
101 {
102 if (!(i % w))
103 {
104 row++;
105 col = 0;
106 }
107 else col++;
108 Evas_Object *rec = evas_object_rectangle_add(evas_object_evas_get(tb));
109 evas_object_size_hint_min_set(rec, ELM_SCALE_SIZE(64), ELM_SCALE_SIZE(64));
110 elm_table_pack(tb, rec, col, row, 1, 1);
111 evas_object_show(rec);
112 Evas_Object *lb = elm_label_add(tb);
113 evas_object_size_hint_weight_set(lb, EXPAND, EXPAND);
114 evas_object_size_hint_align_set(lb, FILL, FILL);
115 elm_table_pack(tb, lb, col, row, 1, 1);
116 evas_object_show(lb);
117 evas_object_data_set(lb, "r", rec);
118 ext->objects = eina_list_append(ext->objects, lb);
119 }
120
121 elm_box_pack_end(parent_bx, tb);
122
123 vis->thread = ecore_thread_feedback_run(_core_times_main_cb,
124 _core_times_feedback_cb,
125 NULL,
126 NULL,
127 vis, 1);
128 return vis;
129}
130
diff --git a/src/bin/ui/visuals/cpu_basic.h b/src/bin/ui/visuals/cpu_basic.h
new file mode 100644
index 0000000..c3c6396
--- /dev/null
+++ b/src/bin/ui/visuals/cpu_basic.h
@@ -0,0 +1,9 @@
1#ifndef CPU_BASIC_H
2#define CPU_BASIC_H
3
4#include "ui/ui_cpu.h"
5
6Cpu_Visual *
7cpu_visual_basic(Evas_Object *parent);
8
9#endif
diff --git a/src/bin/ui/visuals/cpu_default.c b/src/bin/ui/visuals/cpu_default.c
new file mode 100644
index 0000000..e39f135
--- /dev/null
+++ b/src/bin/ui/visuals/cpu_default.c
@@ -0,0 +1,591 @@
1#include "cpu_default.h"
2
3#define BAR_HEIGHT 3
4#define COLORS_HEIGHT 32
5#define CORES_MANY 16
6
7typedef struct {
8 Evas_Object *obj;
9 Evas_Object *bg;
10 Evas_Object *colors;
11 int cpu_count;
12
13 Eina_Bool show_cpufreq;
14 // Have cpu scaling
15 Eina_Bool cpu_freq;
16 int freq_min;
17 int freq_max;
18
19 Eina_Bool show_cputemp;
20 // Have temp readings
21 Eina_Bool cpu_temp;
22 int temp_min;
23 int temp_max;
24
25 Eina_List *explainers;
26 int *cpu_order;
27 Eina_Bool confused;
28} Ext;
29
30static void
31_core_times_main_cb(void *data, Ecore_Thread *thread)
32{
33 Cpu_Visual *vis = data;
34 int ncpu;
35 Ext *ext = vis->ext;
36
37 if (!system_cpu_frequency_min_max_get(&ext->freq_min, &ext->freq_max))
38 ext->cpu_freq = 1;
39
40 system_cpu_temperature_min_max_get(&ext->temp_min, &ext->temp_max);
41 if ((system_cpu_n_temperature_get(0)) != -1)
42 ext->cpu_temp = 1;
43
44 while (!ecore_thread_check(thread))
45 {
46 cpu_core_t **cores = system_cpu_usage_delayed_get(&ncpu, 100000);
47 Core *cores_out = calloc(ncpu, sizeof(Core));
48
49 if (cores_out)
50 {
51 for (int n = 0; n < ncpu; n++)
52 {
53 int id = ext->cpu_order[n];
54 Core *core = &(cores_out[n]);
55 core->id = id;
56 core->percent = cores[id]->percent;
57 if (ext->cpu_freq)
58 core->freq = system_cpu_n_frequency_get(id);
59 if (ext->cpu_temp)
60 core->temp = system_cpu_n_temperature_get(id);
61 free(cores[id]);
62 }
63 ecore_thread_feedback(thread, cores_out);
64 }
65 free(cores);
66 }
67}
68
69static void
70_update(Cpu_Visual *vis, Core *cores)
71{
72 Evas_Object *obj;
73 unsigned int *pixels, *pix;
74 Evas_Coord x, y, w, h;
75 int iw, stride;
76 Eina_Bool clear = 0;
77 Ext *ext = vis->ext;
78 obj = ext->obj;
79
80 evas_object_geometry_get(obj, &x, &y, &w, &h);
81 evas_object_image_size_get(obj, &iw, NULL);
82 // if image pixel size doesn't match geom - we need to resize, so set
83 // new size and mark it for clearing when we fill
84 if (iw != w)
85 {
86 evas_object_image_size_set(obj, w, ext->cpu_count * 3);
87 clear = 1;
88 }
89
90 // get pixel data ptr
91 pixels = evas_object_image_data_get(obj, 1);
92 if (!pixels) return;
93 // get stride (# of bytes per line)
94 stride = evas_object_image_stride_get(obj);
95
96 for (y = 0; y < ext->cpu_count; y++)
97 {
98 Core *core = &(cores[y]);
99 unsigned int c1, c2;
100
101 // our pix ptr is the pixel row and y is both y pixel coord and core
102 if (clear)
103 {
104 // clear/fill with 0 value from colormap
105 pix = &(pixels[(y * 3) * (stride / 4)]);
106 for (x = 0; x < (w - 1); x++) pix[x] = cpu_colormap[0];
107 pix = &(pixels[((y * 3) + 1) * (stride / 4)]);
108 for (x = 0; x < (w - 1); x++) pix[x] = freq_colormap[0];
109 pix = &(pixels[((y * 3) + 2) * (stride / 4)]);
110 for (x = 0; x < (w - 1); x++) pix[x] = cpu_colormap[0];
111 }
112 else
113 {
114 // scroll pixels 1 to the left
115 pix = &(pixels[(y * 3) * (stride / 4)]);
116 for (x = 0; x < (w - 1); x++) pix[x] = pix[x + 1];
117 pix = &(pixels[((y * 3) + 1) * (stride / 4)]);
118 for (x = 0; x < (w - 1); x++) pix[x] = pix[x + 1];
119 pix = &(pixels[((y * 3) + 2) * (stride / 4)]);
120 for (x = 0; x < (w - 1); x++) pix[x] = pix[x + 1];
121 }
122 // final pixel on end of each row... set it to a new value
123 // get color from cpu colormap
124 // last pixel == resulting pixel color
125 c1 = cpu_colormap[core->percent & 0xff];
126 pix = &(pixels[(y * 3) * (stride / 4)]);
127 pix[x] = c1;
128 // 2nd row of pixles for freq
129 if ((ext->show_cpufreq) && (ext->cpu_freq))
130 {
131 int v = core->freq - ext->freq_min;
132 int d = ext->freq_max - ext->freq_min;
133
134 // if there is a difference between min and max ... a range
135 if (d > 0)
136 {
137 v = (100 * v) / d;
138 if (v < 0) v = 0;
139 else if (v > 100) v = 100;
140 // v now is 0->100 as a percentage of possible frequency
141 // the cpu can do
142 c2 = freq_colormap[v & 0xff];
143 }
144 else c2 = freq_colormap[0];
145 pix = &(pixels[((y * 3) + 1) * (stride / 4)]);
146 pix[x] = c2;
147 }
148
149 if (ext->show_cputemp && ext->cpu_temp)
150 {
151 pix = &(pixels[((y * 3) + 2) * (stride / 4)]);
152 pix[x] = temp_colormap[core->temp & 0xff];
153 }
154
155 if (!ext->show_cpufreq)
156 {
157 // no freq show - then just repeat cpu usage color
158 pix = &(pixels[((y * 3) + 1) * (stride / 4)]);
159 pix[x] = c1;
160 }
161 if (!ext->show_cputemp)
162 {
163 pix = &(pixels[((y * 3) + 2) * (stride / 4)]);
164 pix[x] = c1;
165 }
166 }
167 // hand back pixel data ptr so evas knows we are done with it
168 evas_object_image_data_set(obj, pixels);
169 // now visd update region for all pixels in the image at the end as we
170 // changed everything
171 evas_object_image_data_update_add(obj, 0, 0, w, ext->cpu_count * 3);
172}
173
174typedef struct
175{
176 Evas_Object *lb;
177 Evas_Object *rec;
178} Explainer;
179
180static void
181_explain(Cpu_Visual *vis, Core *cores)
182{
183 Eina_Strbuf *buf;
184 Explainer *exp;
185 Ext *ext;
186 Evas_Object *lb, *rec;
187
188 ext = vis->ext;
189
190 if (!ext->explainers) return;
191
192 buf = eina_strbuf_new();
193
194 for (int i = 0; i < ext->cpu_count; i++)
195 {
196 Core *core = &(cores[i]);
197 exp = eina_list_nth(ext->explainers, i);
198
199 lb = exp->lb;
200 rec = exp->rec;
201 if (!ext->confused)
202 {
203 evas_object_hide(rec);
204 evas_object_hide(lb);
205 }
206 else
207 {
208 eina_strbuf_append_printf(buf, "<b><color=#fff>%i%% ", core->percent);
209 if (ext->cpu_freq)
210 eina_strbuf_append_printf(buf, "%1.1fGHz ", (double) core->freq / 1000000);
211 if (ext->cpu_temp)
212 eina_strbuf_append_printf(buf, "%i°C", core->temp);
213 eina_strbuf_append(buf, "</></>");
214
215 elm_object_text_set(lb, eina_strbuf_string_get(buf));
216 eina_strbuf_reset(buf);
217 evas_object_show(rec);
218 evas_object_show(lb);
219 }
220 }
221 eina_strbuf_free(buf);
222}
223
224static void
225_core_times_feedback_cb(void *data, Ecore_Thread *thread EINA_UNUSED, void *msgdata)
226{
227 Cpu_Visual *vis;
228 Core *cores;
229 Ext *ext;
230 static Eina_Bool was_confused = 0;
231
232 vis = data;
233 ext = vis->ext;
234 cores = msgdata;
235
236 _update(vis, cores);
237
238 if (ext->confused || was_confused)
239 {
240 _explain(vis, cores);
241 was_confused = 1;
242 }
243
244 free(cores);
245}
246
247static void
248_cb_free(void *data)
249{
250 Explainer *exp;
251 Ext *ext = data;
252
253 EINA_LIST_FREE(ext->explainers, exp)
254 free(exp);
255
256 free(ext->cpu_order);
257
258 free(ext);
259}
260
261static void
262_check_changed_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
263 void *event_info EINA_UNUSED)
264{
265 Cpu_Visual *vis = data;
266 Ext *ext = vis->ext;
267
268 ext->show_cpufreq = elm_check_state_get(obj);
269}
270
271static void
272_temp_check_changed_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
273 void *event_info EINA_UNUSED)
274{
275 Cpu_Visual *vis = data;
276 Ext *ext = vis->ext;
277
278 ext->show_cputemp = elm_check_state_get(obj);
279}
280
281static void
282_confused_check_changed_cb(void *data EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
283 void *event_info EINA_UNUSED)
284{
285 Cpu_Visual *vis = data;
286 Ext *ext = vis->ext;
287
288 ext->confused = elm_check_state_get(obj);
289}
290
291static void
292_colors_fill(Evas_Object *colors)
293{
294 // fill a 3 pixel high (and 100 wide) image with 3 grvisients matching
295 // the colormaps we calculated as a legend
296 int x, stride;
297 unsigned int *pixels;
298
299 evas_object_image_size_set(colors, 101, 3);
300 pixels = evas_object_image_data_get(colors, 1);
301 if (!pixels) return;
302 stride = evas_object_image_stride_get(colors);
303 // cpu percent (first row)
304 for (x = 0; x <= 100; x++) pixels[x] = cpu_colormap[x];
305 // cpu freq (next row)
306 for (x = 0; x <= 100; x++) pixels[x + (stride / 4)] = freq_colormap[x];
307 // cpu temp (next row)
308 for (x = 0; x <= 100; x++) pixels[x + (stride / 2)] = temp_colormap[x];
309
310 evas_object_image_data_set(colors, pixels);
311 evas_object_image_data_update_add(colors, 0, 0, 101, 1);
312}
313
314Cpu_Visual *
315cpu_visual_default(Evas_Object *parent_box)
316{
317 Evas_Object *tbl, *tbl2, *box, *obj, *ic, *lb, *rec;
318 Evas_Object *fr, *bx, *hbx, *colors, *check;
319 Ext *ext;
320 int *cpu_order;
321 int i, f;
322 char buf[128];
323 Eina_Bool show_icons = 1;
324
325 Cpu_Visual *vis = calloc(1, sizeof(Cpu_Visual));
326 if (!vis) return NULL;
327
328 vis->ext = ext = calloc(1, sizeof(Ext));
329 EINA_SAFETY_ON_NULL_RETURN_VAL(ext, NULL);
330
331 ext->cpu_count = system_cpu_count_get();
332 if (!system_cpu_frequency_min_max_get(&ext->freq_min, &ext->freq_max))
333 ext->cpu_freq = 1;
334
335 system_cpu_temperature_min_max_get(&ext->temp_min, &ext->temp_max);
336 if ((system_cpu_n_temperature_get(0)) != -1)
337 ext->cpu_temp = 1;
338
339 ext->cpu_order = cpu_order = malloc((ext->cpu_count) * sizeof(int));
340 for (i = 0; i < ext->cpu_count; i++)
341 cpu_order[i] = i;
342 system_cpu_topology_get(cpu_order, ext->cpu_count);
343
344 box = parent_box;
345
346 tbl = elm_table_add(box);
347 evas_object_size_hint_align_set(tbl, FILL, FILL);
348 evas_object_size_hint_weight_set(tbl, EXPAND, EXPAND);
349 evas_object_show(tbl);
350
351 obj = evas_object_image_add(evas_object_evas_get(box));
352 evas_object_size_hint_align_set(obj, FILL, FILL);
353 evas_object_size_hint_weight_set(obj, EXPAND, EXPAND);
354 evas_object_image_smooth_scale_set(obj, 0);
355 evas_object_image_filled_set(obj, 1);
356 evas_object_image_alpha_set(obj, 0);
357 evas_object_show(obj);
358
359 elm_table_pack(tbl, obj, 0, 0, 5, ext->cpu_count);
360
361 if (ext->cpu_count > CORES_MANY)
362 show_icons = 0;
363
364 if (show_icons)
365 {
366 rec = evas_object_rectangle_add(evas_object_evas_get(box));
367 evas_object_size_hint_align_set(rec, FILL, FILL);
368 evas_object_size_hint_weight_set(rec, EXPAND, EXPAND);
369 evas_object_color_set(rec, 0, 0, 0, 64);
370 evas_object_show(rec);
371 elm_table_pack(tbl, rec, 0, 0, 4, ext->cpu_count);
372 }
373
374 for (i = 0; show_icons && (i < ext->cpu_count); i++)
375 {
376 rec = evas_object_rectangle_add(evas_object_evas_get(box));
377 evas_object_color_set(rec, 0, 0, 0, 0);
378 evas_object_size_hint_min_set(rec, ELM_SCALE_SIZE(8), ELM_SCALE_SIZE(8));
379 evas_object_size_hint_weight_set(rec, 0.0, EXPAND);
380 elm_table_pack(tbl, rec, 0, i, 1, 1);
381
382 rec = evas_object_rectangle_add(evas_object_evas_get(box));
383 evas_object_color_set(rec, 0, 0, 0, 0);
384 evas_object_size_hint_min_set(rec, ELM_SCALE_SIZE(24), ELM_SCALE_SIZE(24));
385 evas_object_size_hint_weight_set(rec, 0.0, EXPAND);
386 elm_table_pack(tbl, rec, 1, i, 1, 1);
387
388 ic = elm_icon_add(box);
389 elm_icon_standard_set(ic, evisum_icon_path_get("cpu"));
390 evas_object_size_hint_align_set(ic, FILL, FILL);
391 evas_object_size_hint_weight_set(ic, 0.0, EXPAND);
392 elm_table_pack(tbl, ic, 1, i, 1, 1);
393 evas_object_show(ic);
394
395 rec = evas_object_rectangle_add(evas_object_evas_get(box));
396 evas_object_color_set(rec, 0, 0, 0, 0);
397 evas_object_size_hint_min_set(rec, ELM_SCALE_SIZE(8), ELM_SCALE_SIZE(8));
398 evas_object_size_hint_weight_set(rec, 0.0, EXPAND);
399 elm_table_pack(tbl, rec, 2, i, 1, 1);
400
401 rec = evas_object_rectangle_add(evas_object_evas_get(box));
402 evas_object_color_set(rec, 0, 0, 0, 0);
403 evas_object_size_hint_min_set(rec, ELM_SCALE_SIZE(16), ELM_SCALE_SIZE(16));
404 evas_object_size_hint_weight_set(rec, 0.0, EXPAND);
405 elm_table_pack(tbl, rec, 3, i, 1, 1);
406
407 lb = elm_label_add(box);
408 snprintf(buf, sizeof(buf), "<b><color=#fff>%i</></>", cpu_order[i]);
409 elm_object_text_set(lb, buf);
410 evas_object_size_hint_align_set(lb, 0.0, 0.5);
411 evas_object_size_hint_weight_set(lb, 0.0, EXPAND);
412 elm_table_pack(tbl, lb, 3, i, 1, 1);
413 evas_object_show(lb);
414
415 // Begin explainer label overlay.
416
417 tbl2 = elm_table_add(box);
418 evas_object_size_hint_align_set(tbl2, 0.7, 0.5);
419 evas_object_size_hint_weight_set(tbl2, EXPAND, EXPAND);
420 evas_object_show(tbl2);
421
422 rec = evas_object_rectangle_add(evas_object_evas_get(box));
423 evas_object_color_set(rec, 0, 0, 0, 128);
424 evas_object_size_hint_align_set(rec, FILL, FILL);
425 evas_object_size_hint_weight_set(rec, EXPAND, EXPAND);
426 elm_table_pack(tbl2, rec, 0, 0, 1, 1);
427
428 lb = elm_label_add(box);
429 evas_object_size_hint_align_set(lb, FILL, FILL);
430 evas_object_size_hint_weight_set(lb, EXPAND, EXPAND);
431 elm_object_text_set(lb, buf);
432 elm_table_pack(tbl2, lb, 0, 0, 1, 1);
433 elm_table_pack(tbl, tbl2, 4, i, 1, 1);
434
435 Explainer *exp = malloc(sizeof(Explainer));
436 exp->rec = rec;
437 exp->lb = lb;
438
439 ext->explainers = eina_list_append(ext->explainers, exp);
440 }
441
442 // Callback to free anything extra we pass around via the ext pointer in (Cpu_Visual *).
443 vis->ext_free_cb = _cb_free;
444
445 bx = elm_box_add(box);
446 evas_object_size_hint_align_set(bx, FILL, FILL);
447 evas_object_size_hint_weight_set(bx, EXPAND, EXPAND);
448 evas_object_show(bx);
449 elm_box_pack_end(bx, tbl);
450
451 // Set the main content.
452 elm_box_pack_end(box, bx);
453
454 tbl = elm_table_add(box);
455 evas_object_size_hint_align_set(tbl, FILL, FILL);
456 evas_object_size_hint_weight_set(tbl, EXPAND, 0);
457 evas_object_show(tbl);
458
459 fr = elm_frame_add(box);
460 evas_object_size_hint_align_set(fr, FILL, FILL);
461 evas_object_size_hint_weight_set(fr, EXPAND, 0);
462 evas_object_show(fr);
463 elm_object_text_set(fr, _("Legend"));
464 elm_object_content_set(fr, tbl);
465
466 colors = evas_object_image_add(evas_object_evas_get(fr));
467 evas_object_size_hint_min_set
468 (colors, 100, COLORS_HEIGHT * elm_config_scale_get());
469 evas_object_size_hint_align_set(colors, FILL, FILL);
470 evas_object_size_hint_weight_set(colors, EXPAND, EXPAND);
471 evas_object_image_smooth_scale_set(colors, 0);
472 evas_object_image_filled_set(colors, 1);
473 evas_object_image_alpha_set(colors, 0);
474 _colors_fill(colors);
475 elm_table_pack(tbl, colors, 0, 0, 2, 3);
476 evas_object_show(colors);
477
478 lb = elm_label_add(box);
479 elm_object_text_set(lb, "<b><color=#fff> 0%</></>");
480 evas_object_size_hint_align_set(lb, 0.0, 0.5);
481 evas_object_size_hint_weight_set(lb, EXPAND, EXPAND);
482 elm_table_pack(tbl, lb, 0, 0, 1, 1);
483 evas_object_show(lb);
484
485 lb = elm_label_add(box);
486 f = (ext->freq_min + 500) / 1000;
487 if (f < 1000)
488 snprintf(buf, sizeof(buf), "<b><color=#fff> %iMHz</></>", f);
489 else
490 snprintf(buf, sizeof(buf), "<b><color=#fff> %1.1fGHz</></>", ((double)f + 0.05) / 1000.0);
491 elm_object_text_set(lb, buf);
492 evas_object_size_hint_align_set(lb, 0.0, 0.5);
493 evas_object_size_hint_weight_set(lb, EXPAND, EXPAND);
494 elm_table_pack(tbl, lb, 0, 1, 1, 1);
495 evas_object_show(lb);
496
497 lb = elm_label_add(box);
498 elm_object_text_set(lb, "<b><color=#fff>100%</></>");
499 evas_object_size_hint_align_set(lb, 0.99, 0.5);
500 evas_object_size_hint_weight_set(lb, EXPAND, EXPAND);
501 elm_table_pack(tbl, lb, 1, 0, 1, 1);
502 evas_object_show(lb);
503
504 lb = elm_label_add(box);
505 f = (ext->freq_max + 500) / 1000;
506 if (f < 1000)
507 snprintf(buf, sizeof(buf), "<b><color=#fff>%iMHz</></>", f);
508 else
509 snprintf(buf, sizeof(buf), "<b><color=#fff>%1.1fGHz</></>", ((double)f + 0.05) / 1000.0);
510 elm_object_text_set(lb, buf);
511 evas_object_size_hint_align_set(lb, 0.99, 0.5);
512 evas_object_size_hint_weight_set(lb, EXPAND, EXPAND);
513 elm_table_pack(tbl, lb, 1, 1, 1, 1);
514 evas_object_show(lb);
515
516 lb = elm_label_add(box);
517 snprintf(buf, sizeof(buf), "<b><color=#fff> %i°C</></>", ext->temp_min);
518 elm_object_text_set(lb, buf);
519 evas_object_size_hint_align_set(lb, 0.0, 0.5);
520 evas_object_size_hint_weight_set(lb, EXPAND, EXPAND);
521 elm_table_pack(tbl, lb, 0, 2, 1, 1);
522 evas_object_show(lb);
523
524 lb = elm_label_add(box);
525 snprintf(buf, sizeof(buf), "<b><color=#fff>%i°C</></>", ext->temp_max);
526 elm_object_text_set(lb, buf);
527 evas_object_size_hint_align_set(lb, 0.99, 0.5);
528 evas_object_size_hint_weight_set(lb, EXPAND, EXPAND);
529 elm_table_pack(tbl, lb, 1, 2, 1, 1);
530 evas_object_show(lb);
531
532 elm_box_pack_end(box, fr);
533
534 fr = elm_frame_add(box);
535 elm_frame_autocollapse_set(fr, 1);
536 evas_object_size_hint_align_set(fr, FILL, FILL);
537 evas_object_size_hint_weight_set(fr, EXPAND, 0);
538 evas_object_show(fr);
539 elm_frame_collapse_set(fr, 0);
540 elm_object_text_set(fr, _("Options"));
541 elm_box_pack_end(box, fr);
542
543 hbx = elm_box_add(fr);
544 evas_object_size_hint_align_set(hbx, FILL, FILL);
545 evas_object_size_hint_weight_set(hbx, EXPAND, 0);
546 elm_box_horizontal_set(hbx, 1);
547 evas_object_show(hbx);
548 elm_object_content_set(fr, hbx);
549
550 check = elm_check_add(fr);
551 evas_object_size_hint_align_set(check, FILL, FILL);
552 evas_object_size_hint_weight_set(check, EXPAND, 0);
553 elm_object_text_set(check, _("Overlay CPU frequency?"));
554 if (!ext->cpu_freq) elm_object_disabled_set(check, 1);
555 evas_object_show(check);
556 elm_box_pack_end(hbx, check);
557 evas_object_smart_callback_add(check, "changed", _check_changed_cb, vis);
558
559 check = elm_check_add(fr);
560 evas_object_size_hint_align_set(check, FILL, FILL);
561 evas_object_size_hint_weight_set(check, EXPAND, 0);
562 elm_object_text_set(check, _("Overlay CPU temperatures?"));
563 if (!ext->cpu_temp) elm_object_disabled_set(check, 1);
564 evas_object_smart_callback_add(check, "changed", _temp_check_changed_cb, vis);
565 evas_object_show(check);
566 elm_box_pack_end(hbx, check);
567
568 check = elm_check_add(fr);
569 evas_object_size_hint_align_set(check, FILL, FILL);
570 evas_object_size_hint_weight_set(check, EXPAND, 0);
571 elm_object_text_set(check, _("Confused?"));
572 evas_object_smart_callback_add(check, "changed", _confused_check_changed_cb, vis);
573 evas_object_show(check);
574 elm_box_pack_end(hbx, check);
575
576 ext->obj = obj;
577 ext->colors = colors;
578
579 // min size of cpu color graph to show all cores.
580 evas_object_size_hint_min_set
581 (obj, 100, (BAR_HEIGHT * ext->cpu_count) * elm_config_scale_get());
582
583 // run a feedback thread that sends feedback to the mainloop
584 vis->thread = ecore_thread_feedback_run(_core_times_main_cb,
585 _core_times_feedback_cb,
586 NULL,
587 NULL,
588 vis, 1);
589 return vis;
590}
591
diff --git a/src/bin/ui/visuals/cpu_default.h b/src/bin/ui/visuals/cpu_default.h
new file mode 100644
index 0000000..86e05c9
--- /dev/null
+++ b/src/bin/ui/visuals/cpu_default.h
@@ -0,0 +1,9 @@
1#ifndef CPU_VISUAL_H
2#define CPU_VISUAL_H
3
4#include "ui/ui_cpu.h"
5
6Cpu_Visual *
7cpu_visual_default(Evas_Object *parent);
8
9#endif
diff --git a/src/bin/ui/visuals/meson.build b/src/bin/ui/visuals/meson.build
new file mode 100644
index 0000000..f00a2a7
--- /dev/null
+++ b/src/bin/ui/visuals/meson.build
@@ -0,0 +1,6 @@
1src += files([
2 'cpu_default.c',
3 'cpu_default.h',
4 'cpu_basic.c',
5 'cpu_basic.h',
6])
diff --git a/src/bin/ui/visuals/visuals.x b/src/bin/ui/visuals/visuals.x
new file mode 100644
index 0000000..429d297
--- /dev/null
+++ b/src/bin/ui/visuals/visuals.x
@@ -0,0 +1,7 @@
1#include "cpu_default.h"
2#include "cpu_basic.h"
3
4Visualization visualizations[] = {
5 { .name = "default", .func = cpu_visual_default },
6 { .name = "basic", .func = cpu_visual_basic },
7};