This is an automated email from the git hooks/post-receive script.
git pushed a commit to branch master
in repository evisum.
View the commit online.
commit 292e7afe547e97f0d8390d8e1321cd8e5c8bc9ee
Author: Alastair Poole <[email protected]>
AuthorDate: Mon Apr 27 21:16:08 2026 +0100
evisum: of all the things I miss, I miss my mind the most.
Holy fucking shit we're in business.
---
src/bin/engine/evisum_engine.c | 310 ++++++++++++++++++++++++-
src/bin/engine/evisum_engine.h | 6 +
src/bin/enigmatic/client/Enigmatic_Client.h | 10 +
src/bin/enigmatic/client/enigmatic_client.c | 33 ++-
src/bin/ui/evisum_ui_process_list.c | 343 +++++++++++++++++++++++++++-
5 files changed, 685 insertions(+), 17 deletions(-)
diff --git a/src/bin/engine/evisum_engine.c b/src/bin/engine/evisum_engine.c
index 5c827e5..9370d30 100644
--- a/src/bin/engine/evisum_engine.c
+++ b/src/bin/engine/evisum_engine.c
@@ -4,9 +4,14 @@
#include "enigmatic/enigmatic_util.h"
#include <stdlib.h>
+#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
+#include <limits.h>
+#include <time.h>
+#include <dirent.h>
+#include <sys/stat.h>
#define LOCK() eina_lock_take(&_state.lock)
#define UNLOCK() eina_lock_release(&_state.lock)
@@ -20,8 +25,17 @@ typedef struct {
uint64_t snapshot_seq;
Enigmatic_Client *client;
+ Enigmatic_Client *history_client;
+ Eina_Bool history_enabled;
+ uint32_t history_time;
} Evisum_Engine_State;
+typedef struct {
+ char *path;
+ uint32_t start_time;
+ uint32_t end_time;
+} Evisum_Engine_History_Log;
+
static Evisum_Engine_State _state = {0};
static Eina_Bool
@@ -101,8 +115,14 @@ evisum_engine_shutdown(void)
enigmatic_client_del(_state.client);
_state.client = NULL;
}
+ if (_state.history_client) {
+ enigmatic_client_del(_state.history_client);
+ _state.history_client = NULL;
+ }
_state.started = EINA_FALSE;
+ _state.history_enabled = EINA_FALSE;
+ _state.history_time = 0;
if (_state.cond_init) eina_condition_broadcast(&_state.cond);
UNLOCK();
@@ -160,6 +180,288 @@ evisum_engine_daemon_running_get(void)
return enigmatic_running();
}
+static Enigmatic_Client *
+_engine_history_client_for_path_read(char *path, uint32_t time)
+{
+ Enigmatic_Client *client;
+
+ client = enigmatic_client_path_open(path);
+ if (!client) {
+ free(path);
+ return NULL;
+ }
+
+ enigmatic_client_replay_time_start_set(client, 0);
+ if (time) enigmatic_client_replay_time_end_set(client, time);
+ enigmatic_client_read(client);
+
+ return client;
+}
+
+static void
+_engine_history_log_free(Evisum_Engine_History_Log *log)
+{
+ if (!log) return;
+ free(log->path);
+ free(log);
+}
+
+static Eina_Bool
+_engine_history_archive_name_is_valid(const char *name)
+{
+ size_t len;
+ const char *p;
+
+ if (!name || !name[0]) return EINA_FALSE;
+ if (!strcmp(name, ".") || !strcmp(name, "..")) return EINA_FALSE;
+ if (!strcmp(name, "enigmatic.log")) return EINA_FALSE;
+ if (!strcmp(name, "enigmatic.lock") || !strcmp(name, "enigmatic.pid")) return EINA_FALSE;
+
+ len = strlen(name);
+ if (len > 5 && !strcmp(name + len - 5, ".size")) return EINA_FALSE;
+
+ if (len > 4 && !strcmp(name + len - 4, ".lz4")) len -= 4;
+ if (len < 2) return EINA_FALSE;
+
+ for (size_t i = 0; i < len; i++) {
+ if (name[i] == '-') continue;
+ if (name[i] < '0' || name[i] > '9') return EINA_FALSE;
+ }
+
+ p = strchr(name, '-');
+ if (p && (p >= name + len)) return EINA_FALSE;
+
+ return EINA_TRUE;
+}
+
+static int
+_engine_history_log_sort_cb(const void *d1, const void *d2)
+{
+ const Evisum_Engine_History_Log *a = d1;
+ const Evisum_Engine_History_Log *b = d2;
+
+ if (a->start_time < b->start_time) return -1;
+ if (a->start_time > b->start_time) return 1;
+ if (a->end_time < b->end_time) return -1;
+ if (a->end_time > b->end_time) return 1;
+
+ return 0;
+}
+
+static Eina_Bool
+_engine_history_log_add(Eina_List **logs, char *path)
+{
+ Enigmatic_Client *client;
+ Evisum_Engine_History_Log *log;
+ uint32_t start_time = 0, end_time = 0;
+
+ if (!logs || !path) {
+ free(path);
+ return EINA_FALSE;
+ }
+
+ client = _engine_history_client_for_path_read(strdup(path), 0);
+ if (!client) {
+ free(path);
+ return EINA_FALSE;
+ }
+
+ if (!enigmatic_client_time_bounds_get(client, &start_time, &end_time) || !start_time || !end_time) {
+ enigmatic_client_del(client);
+ free(path);
+ return EINA_FALSE;
+ }
+
+ enigmatic_client_del(client);
+
+ log = calloc(1, sizeof(*log));
+ if (!log) {
+ free(path);
+ return EINA_FALSE;
+ }
+
+ log->path = path;
+ log->start_time = start_time;
+ log->end_time = end_time;
+
+ *logs = eina_list_append(*logs, log);
+
+ return EINA_TRUE;
+}
+
+static Eina_List *
+_engine_history_logs_get(void)
+{
+ Eina_List *logs = NULL;
+ DIR *dp;
+ struct dirent *ent;
+ char *dir, *current_path;
+
+ current_path = enigmatic_log_path();
+ _engine_history_log_add(&logs, current_path);
+
+ dir = enigmatic_log_directory();
+ if (!dir) return logs;
+
+ dp = opendir(dir);
+ if (!dp) {
+ free(dir);
+ return logs;
+ }
+
+ while ((ent = readdir(dp))) {
+ char path[PATH_MAX];
+ struct stat st;
+
+ if (!_engine_history_archive_name_is_valid(ent->d_name)) continue;
+
+ snprintf(path, sizeof(path), "%s/%s", dir, ent->d_name);
+ if (stat(path, &st) == -1) continue;
+ if (!S_ISREG(st.st_mode)) continue;
+ if (access(path, R_OK) != 0) continue;
+
+ _engine_history_log_add(&logs, strdup(path));
+ }
+
+ closedir(dp);
+ free(dir);
+
+ return eina_list_sort(logs, eina_list_count(logs), _engine_history_log_sort_cb);
+}
+
+Eina_Bool
+evisum_engine_history_bounds_get(uint32_t *start_time, uint32_t *end_time)
+{
+ Eina_List *logs, *l;
+ Evisum_Engine_History_Log *log;
+ Eina_Bool ok = EINA_FALSE;
+
+ if (start_time) *start_time = 0;
+ if (end_time) *end_time = 0;
+ if (!evisum_engine_ensure_started()) return EINA_FALSE;
+
+ logs = _engine_history_logs_get();
+ if (!logs) return EINA_FALSE;
+
+ EINA_LIST_FOREACH(logs, l, log) {
+ if (!ok) {
+ if (start_time) *start_time = log->start_time;
+ if (end_time) *end_time = log->end_time;
+ ok = EINA_TRUE;
+ continue;
+ }
+ if (start_time && log->start_time < *start_time) *start_time = log->start_time;
+ if (end_time && log->end_time > *end_time) *end_time = log->end_time;
+ }
+
+ EINA_LIST_FREE(logs, log) _engine_history_log_free(log);
+
+ return EINA_TRUE;
+}
+
+Eina_Bool
+evisum_engine_history_time_set(uint32_t time)
+{
+ Enigmatic_Client *client, *old;
+ Eina_List *logs, *l;
+ Evisum_Engine_History_Log *log, *selected = NULL;
+
+ if (!time) return EINA_FALSE;
+ if (!evisum_engine_ensure_started()) return EINA_FALSE;
+
+ logs = _engine_history_logs_get();
+ EINA_LIST_FOREACH(logs, l, log) {
+ if ((time >= log->start_time) && (time <= log->end_time)) {
+ selected = log;
+ break;
+ }
+ if (time > log->end_time) selected = log;
+ }
+
+ if (!selected) {
+ EINA_LIST_FREE(logs, log) _engine_history_log_free(log);
+ return EINA_FALSE;
+ }
+
+ client = _engine_history_client_for_path_read(strdup(selected->path), time);
+ EINA_LIST_FREE(logs, log) _engine_history_log_free(log);
+ if (!client) return EINA_FALSE;
+
+ LOCK();
+ old = _state.history_client;
+ _state.history_client = client;
+ _state.history_enabled = EINA_TRUE;
+ _state.history_time = time;
+ _state.snapshot_seq++;
+ if (_state.cond_init) eina_condition_broadcast(&_state.cond);
+ UNLOCK();
+
+ if (old) enigmatic_client_del(old);
+
+ return EINA_TRUE;
+}
+
+void
+evisum_engine_history_live_set(void)
+{
+ Enigmatic_Client *old = NULL;
+
+ if (!_state.lock_init) return;
+
+ LOCK();
+ old = _state.history_client;
+ _state.history_client = NULL;
+ _state.history_enabled = EINA_FALSE;
+ _state.history_time = 0;
+ _state.snapshot_seq++;
+ if (_state.cond_init) eina_condition_broadcast(&_state.cond);
+ UNLOCK();
+
+ if (old) enigmatic_client_del(old);
+}
+
+Eina_Bool
+evisum_engine_history_live_get(void)
+{
+ Eina_Bool live = EINA_TRUE;
+
+ if (!_state.lock_init) return EINA_TRUE;
+
+ LOCK();
+ live = !_state.history_enabled;
+ UNLOCK();
+
+ return live;
+}
+
+uint32_t
+evisum_engine_history_time_get(void)
+{
+ uint32_t time = 0;
+
+ if (!_state.lock_init) return 0;
+
+ LOCK();
+ time = _state.history_time;
+ UNLOCK();
+
+ return time;
+}
+
+uint32_t
+evisum_engine_live_time_get(void)
+{
+ uint32_t time = 0;
+
+ if (!_state.lock_init) return 0;
+
+ LOCK();
+ if (_state.client) time = _state.client->snapshot.time;
+ UNLOCK();
+
+ return time;
+}
+
static Eina_Bool
_engine_snapshot_acquire(const Snapshot **out)
{
@@ -174,15 +476,17 @@ _engine_snapshot_acquire(const Snapshot **out)
return EINA_FALSE;
}
- *out = &_state.client->snapshot;
- UNLOCK();
+ if (_state.history_enabled && _state.history_client)
+ *out = &_state.history_client->snapshot;
+ else
+ *out = &_state.client->snapshot;
return EINA_TRUE;
}
static void
_engine_snapshot_release(void)
{
- (void) 0;
+ if (_state.lock_init) UNLOCK();
}
static Cpu_Core **
diff --git a/src/bin/engine/evisum_engine.h b/src/bin/engine/evisum_engine.h
index 2353ea3..b847830 100644
--- a/src/bin/engine/evisum_engine.h
+++ b/src/bin/engine/evisum_engine.h
@@ -28,6 +28,12 @@ Eina_Bool evisum_engine_status_get(Evisum_Engine_Status *status);
uint64_t evisum_engine_update_seq_get(void);
Eina_Bool evisum_engine_update_wait(uint64_t *seq);
Eina_Bool evisum_engine_daemon_running_get(void);
+Eina_Bool evisum_engine_history_bounds_get(uint32_t *start_time, uint32_t *end_time);
+Eina_Bool evisum_engine_history_time_set(uint32_t time);
+void evisum_engine_history_live_set(void);
+Eina_Bool evisum_engine_history_live_get(void);
+uint32_t evisum_engine_history_time_get(void);
+uint32_t evisum_engine_live_time_get(void);
int system_cpu_online_count_get(void);
int system_cpu_count_get(void);
diff --git a/src/bin/enigmatic/client/Enigmatic_Client.h b/src/bin/enigmatic/client/Enigmatic_Client.h
index d98e553..0fe9bcc 100644
--- a/src/bin/enigmatic/client/Enigmatic_Client.h
+++ b/src/bin/enigmatic/client/Enigmatic_Client.h
@@ -96,6 +96,13 @@ struct _Enigmatic_Client
uint32_t end_time;
} replay;
+ struct
+ {
+ Eina_Bool valid;
+ uint32_t start_time;
+ uint32_t end_time;
+ } bounds;
+
/* Public */
Event_Snapshot_Data event_snapshot;
@@ -184,4 +191,7 @@ enigmatic_client_replay_time_end_set(Enigmatic_Client *client, uint32_t secs);
Eina_Bool
enigmatic_client_replay(Enigmatic_Client *client);
+Eina_Bool
+enigmatic_client_time_bounds_get(Enigmatic_Client *client, uint32_t *start_time, uint32_t *end_time);
+
#endif
diff --git a/src/bin/enigmatic/client/enigmatic_client.c b/src/bin/enigmatic/client/enigmatic_client.c
index 5f05942..cc5e38f 100644
--- a/src/bin/enigmatic/client/enigmatic_client.c
+++ b/src/bin/enigmatic/client/enigmatic_client.c
@@ -103,6 +103,7 @@ enigmatic_client_reset(Enigmatic_Client *client)
client->offset = 0;
client->file_size = 0;
client->truncated = 0;
+ memset(&client->bounds, 0, sizeof(client->bounds));
free_snapshot(&client->snapshot);
}
@@ -1253,6 +1254,12 @@ static void
event_block_end(Enigmatic_Client *client)
{
client->snapshot.time = client->header.time;
+ if (!client->bounds.valid)
+ {
+ client->bounds.start_time = client->header.time;
+ client->bounds.valid = 1;
+ }
+ client->bounds.end_time = client->header.time;
if ((!client->follow) && (client->event_snapshot.callback) && (callback_fire(client)))
{
@@ -1408,6 +1415,7 @@ enigmatic_client_read(Enigmatic_Client *client)
struct stat st;
int n;
Eina_Bool eof = 0;
+ Eina_Bool stop = 0;
LZ4F_dctx *dctx = NULL;
size_t status = LZ4F_createDecompressionContext(&dctx, LZ4F_VERSION);
@@ -1448,7 +1456,7 @@ enigmatic_client_read(Enigmatic_Client *client)
client->changes = 0;
size_t offset = 0;
- while ((!eof) && ((st.st_size - client->offset) > 0))
+ while ((!eof) && (!stop) && ((st.st_size - client->offset) > 0))
{
client->zbuf.length = st.st_size - client->offset;
client->file_size = st.st_size;
@@ -1483,7 +1491,7 @@ enigmatic_client_read(Enigmatic_Client *client)
LZ4F_frameInfo_t info;
- while ((!eof) && (offset < client->zbuf.length))
+ while ((!eof) && (!stop) && (offset < client->zbuf.length))
{
uint8_t *src = "" + offset;
status = LZ4F_getFrameInfo(dctx, &info, src, &compressed_size);
@@ -1523,11 +1531,17 @@ enigmatic_client_read(Enigmatic_Client *client)
free(dst);
}
- while ((client->buf.length) && (client->buf.index <= (client->buf.length - sizeof(Header))))
+ while ((!stop) && (client->buf.length) && (client->buf.index <= (client->buf.length - sizeof(Header))))
{
memcpy(&client->header, &client->buf.data[client->buf.index], sizeof(Header));
client->buf.index += sizeof(Header);
if (client->compressed) client->offset = client->buf.index;
+ if ((client->replay.enabled) && (client->replay.end_time) &&
+ (client->header.time > client->replay.end_time))
+ {
+ stop = 1;
+ break;
+ }
switch (client->header.event)
{
case EVENT_ERROR:
@@ -1853,3 +1867,16 @@ enigmatic_client_replay_time_end_set(Enigmatic_Client *client, uint32_t secs)
{
client->replay.end_time = secs;
}
+
+Eina_Bool
+enigmatic_client_time_bounds_get(Enigmatic_Client *client, uint32_t *start_time, uint32_t *end_time)
+{
+ if (start_time) *start_time = 0;
+ if (end_time) *end_time = 0;
+ if (!client || !client->bounds.valid) return 0;
+
+ if (start_time) *start_time = client->bounds.start_time;
+ if (end_time) *end_time = client->bounds.end_time;
+
+ return 1;
+}
diff --git a/src/bin/ui/evisum_ui_process_list.c b/src/bin/ui/evisum_ui_process_list.c
index 329aa8f..494f0b8 100644
--- a/src/bin/ui/evisum_ui_process_list.c
+++ b/src/bin/ui/evisum_ui_process_list.c
@@ -13,6 +13,8 @@
#include <sys/types.h>
#include <sys/resource.h>
#include <pwd.h>
+#include <time.h>
+#include <unistd.h>
/* If you're reading this comment, God help you. */
@@ -58,8 +60,24 @@ typedef struct {
Evas_Object *hbx;
Evas_Object *pb_cpu;
Evas_Object *pb_mem;
+ Evas_Object *history_slider;
+ Evas_Object *history_live_btn;
} summary;
+ struct {
+ Eina_Lock lock;
+ Eina_Bool lock_init;
+ Eina_Bool live;
+ Eina_Bool pending;
+ Eina_Bool sliding;
+ Eina_Bool slider_updating;
+ Ecore_Timer *timer;
+ Ecore_Timer *apply_timer;
+ uint32_t start_time;
+ uint32_t end_time;
+ uint32_t requested_time;
+ } history;
+
Elm_Layout *indicator;
Evisum_Ui *ui;
@@ -618,32 +636,270 @@ _evisum_ui_process_list_content_get(void *data, Evas_Object *obj, const char *so
return row;
}
+static void
+_evisum_ui_process_list_history_time_format(uint32_t t, char *buf, size_t len) {
+ time_t when = (time_t) t;
+ struct tm tm_buf;
+
+ if (!buf || !len) return;
+ if (!t || !localtime_r(&when, &tm_buf)) {
+ snprintf(buf, len, "--:--:--");
+ return;
+ }
+
+ strftime(buf, len, "%Y-%m-%d %H:%M:%S", &tm_buf);
+}
+
+static char *
+_evisum_ui_process_list_history_indicator_format_cb(double value, void *data EINA_UNUSED) {
+ char buf[32];
+
+ _evisum_ui_process_list_history_time_format((uint32_t) (value + 0.5), buf, sizeof(buf));
+
+ return strdup(buf);
+}
+
+static void
+_evisum_ui_process_list_history_indicator_free_cb(char *str) {
+ free(str);
+}
+
+static void
+_evisum_ui_process_list_history_tooltip_set(Evisum_Ui_Process_List_View *view, uint32_t t) {
+ char time_buf[32];
+ char tip[128];
+
+ if (!view->summary.history_slider) return;
+
+ _evisum_ui_process_list_history_time_format(t, time_buf, sizeof(time_buf));
+ snprintf(tip, sizeof(tip), _("Process history: %s"), time_buf);
+ elm_object_tooltip_text_set(view->summary.history_slider, tip);
+}
+
+static Eina_Bool
+_evisum_ui_process_list_history_apply_timer_cb(void *data) {
+ Evisum_Ui_Process_List_View *view = data;
+
+ if (!view->history.lock_init) {
+ view->history.apply_timer = NULL;
+ return EINA_FALSE;
+ }
+
+ eina_lock_take(&view->history.lock);
+ view->history.pending = EINA_TRUE;
+ eina_lock_release(&view->history.lock);
+
+ view->skip_wait = 1;
+ view->skip_update = 0;
+ view->history.apply_timer = NULL;
+
+ return EINA_FALSE;
+}
+
+static void
+_evisum_ui_process_list_history_request_deferred(Evisum_Ui_Process_List_View *view, uint32_t t) {
+ if (!view->history.lock_init) return;
+
+ if (view->history.apply_timer) {
+ ecore_timer_del(view->history.apply_timer);
+ view->history.apply_timer = NULL;
+ }
+
+ eina_lock_take(&view->history.lock);
+ view->history.live = EINA_FALSE;
+ view->history.requested_time = t;
+ view->history.pending = EINA_FALSE;
+ eina_lock_release(&view->history.lock);
+
+ view->history.apply_timer = ecore_timer_add(0.5, _evisum_ui_process_list_history_apply_timer_cb, view);
+}
+
+static void
+_evisum_ui_process_list_history_state_get(Evisum_Ui_Process_List_View *view, Eina_Bool *live, Eina_Bool *pending,
+ uint32_t *requested_time) {
+ if (live) *live = EINA_TRUE;
+ if (pending) *pending = EINA_FALSE;
+ if (requested_time) *requested_time = 0;
+ if (!view->history.lock_init) return;
+
+ eina_lock_take(&view->history.lock);
+ if (live) *live = view->history.live;
+ if (pending) *pending = view->history.pending;
+ if (requested_time) *requested_time = view->history.requested_time;
+ eina_lock_release(&view->history.lock);
+}
+
+static void
+_evisum_ui_process_list_history_pending_clear(Evisum_Ui_Process_List_View *view, uint32_t requested_time) {
+ if (!view->history.lock_init) return;
+
+ eina_lock_take(&view->history.lock);
+ if (view->history.requested_time == requested_time) view->history.pending = EINA_FALSE;
+ eina_lock_release(&view->history.lock);
+}
+
+static void
+_evisum_ui_process_list_history_bounds_update(Evisum_Ui_Process_List_View *view) {
+ uint32_t start_time = 0, end_time = 0;
+ uint32_t live_time, now;
+ Eina_Bool live;
+
+ if (!view->summary.history_slider) return;
+
+ now = (uint32_t) time(NULL);
+ live_time = evisum_engine_live_time_get();
+ if ((view->history.start_time) && (now >= view->history.start_time)) {
+ start_time = view->history.start_time;
+ end_time = live_time > now ? live_time : now;
+ } else {
+ if (!evisum_engine_history_bounds_get(&start_time, &end_time)) {
+ elm_object_disabled_set(view->summary.history_slider, 1);
+ elm_object_disabled_set(view->summary.history_live_btn, 1);
+ return;
+ }
+ if ((now >= start_time) && (now > end_time))
+ end_time = now;
+ }
+
+ if (end_time <= start_time) end_time = start_time + 1;
+
+ view->history.start_time = start_time;
+ view->history.end_time = end_time;
+
+ elm_object_disabled_set(view->summary.history_slider, 0);
+ elm_slider_min_max_set(view->summary.history_slider, start_time, end_time);
+
+ _evisum_ui_process_list_history_state_get(view, &live, NULL, NULL);
+ elm_object_disabled_set(view->summary.history_live_btn, live);
+
+ if (live && !view->history.sliding) {
+ view->history.slider_updating = EINA_TRUE;
+ elm_slider_value_set(view->summary.history_slider, end_time);
+ view->history.slider_updating = EINA_FALSE;
+ _evisum_ui_process_list_history_tooltip_set(view, end_time);
+ }
+}
+
+static void
+_evisum_ui_process_list_history_slider_preview_cb(void *data, Evas_Object *obj, void *event_info EINA_UNUSED) {
+ Evisum_Ui_Process_List_View *view = data;
+ uint32_t t;
+
+ if (view->history.slider_updating) return;
+
+ t = (uint32_t) (elm_slider_value_get(obj) + 0.5);
+ if (view->history.start_time && (t < view->history.start_time)) t = view->history.start_time;
+ if (view->history.end_time && (t > view->history.end_time)) t = view->history.end_time;
+
+ elm_object_disabled_set(view->summary.history_live_btn, 0);
+ _evisum_ui_process_list_history_tooltip_set(view, t);
+}
+
+static void
+_evisum_ui_process_list_history_slider_drag_start_cb(void *data, Evas_Object *obj EINA_UNUSED,
+ void *event_info EINA_UNUSED) {
+ Evisum_Ui_Process_List_View *view = data;
+
+ view->history.sliding = EINA_TRUE;
+}
+
+static void
+_evisum_ui_process_list_history_slider_drag_stop_cb(void *data, Evas_Object *obj, void *event_info EINA_UNUSED) {
+ Evisum_Ui_Process_List_View *view = data;
+ uint32_t t;
+
+ view->history.sliding = EINA_FALSE;
+
+ t = (uint32_t) (elm_slider_value_get(obj) + 0.5);
+ if (view->history.start_time && (t < view->history.start_time)) t = view->history.start_time;
+ if (view->history.end_time && (t > view->history.end_time)) t = view->history.end_time;
+
+ elm_object_disabled_set(view->summary.history_live_btn, 0);
+ _evisum_ui_process_list_history_tooltip_set(view, t);
+ _evisum_ui_process_list_history_request_deferred(view, t);
+}
+
+static void
+_evisum_ui_process_list_history_live_clicked_cb(void *data, Evas_Object *obj EINA_UNUSED,
+ void *event_info EINA_UNUSED) {
+ Evisum_Ui_Process_List_View *view = data;
+
+ evisum_engine_history_live_set();
+
+ if (view->history.apply_timer) {
+ ecore_timer_del(view->history.apply_timer);
+ view->history.apply_timer = NULL;
+ }
+
+ eina_lock_take(&view->history.lock);
+ view->history.live = EINA_TRUE;
+ view->history.pending = EINA_FALSE;
+ view->history.sliding = EINA_FALSE;
+ view->history.requested_time = 0;
+ eina_lock_release(&view->history.lock);
+
+ elm_object_disabled_set(view->summary.history_live_btn, 1);
+ view->skip_wait = 1;
+ view->skip_update = 0;
+ _evisum_ui_process_list_history_bounds_update(view);
+}
+
+static Eina_Bool
+_evisum_ui_process_list_history_timer_cb(void *data) {
+ Evisum_Ui_Process_List_View *view = data;
+
+ if (!view->summary.visible || !view->summary.history_slider) {
+ view->history.timer = NULL;
+ return EINA_FALSE;
+ }
+
+ _evisum_ui_process_list_history_bounds_update(view);
+
+ return EINA_TRUE;
+}
+
static void
_evisum_ui_process_list_summary_update(Evisum_Ui_Process_List_View *view) {
Evisum_Ui *ui;
+ Evisum_Engine_Status status = {0};
Eina_Strbuf *buf;
+ uint64_t mem_used, mem_total;
+ double cpu_usage;
ui = view->ui;
if ((!ui->proc.show_statusbar) || (!view->summary.pb_cpu)) return;
+ if (evisum_engine_status_get(&status)) {
+ cpu_usage = status.cpu_usage;
+ mem_total = status.memory.total;
+ mem_used = status.memory.used;
+ if (status.zfs_mounted) mem_used += status.memory.zfs_arc_used;
+ } else {
+ cpu_usage = ui->cpu_usage;
+ mem_total = ui->mem_total;
+ mem_used = ui->mem_used;
+ }
+
buf = eina_strbuf_new();
- elm_progressbar_value_set(view->summary.pb_cpu, ui->cpu_usage / 100.0);
+ elm_progressbar_value_set(view->summary.pb_cpu, cpu_usage / 100.0);
- if (ui->mem_total) elm_progressbar_value_set(view->summary.pb_mem, (double) ui->mem_used / (double) ui->mem_total);
+ if (mem_total) elm_progressbar_value_set(view->summary.pb_mem, (double) mem_used / (double) mem_total);
else elm_progressbar_value_set(view->summary.pb_mem, 0.0);
- eina_strbuf_append_printf(buf, "%s / %s ", evisum_size_format(ui->mem_used, 0),
- evisum_size_format(ui->mem_total, 0));
+ eina_strbuf_append_printf(buf, "%s / %s ", evisum_size_format(mem_used, 0),
+ evisum_size_format(mem_total, 0));
elm_object_part_text_set(view->summary.pb_mem, "elm.text.status", eina_strbuf_string_get(buf));
eina_strbuf_free(buf);
+
+ _evisum_ui_process_list_history_bounds_update(view);
}
static void
_evisum_ui_process_list_summary_add(Evisum_Ui_Process_List_View *view) {
Evisum_Ui *ui = view->ui;
- Evas_Object *hbx, *ic, *pb, *bx;
+ Evas_Object *hbx, *ic, *pb, *sli, *btn;
if (!ui->proc.show_statusbar) return;
@@ -676,11 +932,29 @@ _evisum_ui_process_list_summary_add(Evisum_Ui_Process_List_View *view) {
evas_object_show(pb);
elm_box_pack_end(hbx, pb);
- bx = elm_box_add(view->win);
- evas_object_size_hint_weight_set(bx, EXPAND, EXPAND);
- evas_object_size_hint_align_set(bx, FILL, FILL);
- elm_box_pack_end(hbx, bx);
- evas_object_show(bx);
+ view->summary.history_slider = sli = elm_slider_add(hbx);
+ evas_object_size_hint_weight_set(sli, EXPAND, EXPAND);
+ evas_object_size_hint_align_set(sli, FILL, FILL);
+ elm_slider_indicator_visible_mode_set(sli, ELM_SLIDER_INDICATOR_VISIBLE_MODE_DEFAULT);
+ elm_slider_indicator_format_function_set_full(sli, _evisum_ui_process_list_history_indicator_format_cb,
+ _evisum_ui_process_list_history_indicator_free_cb, view);
+ elm_object_text_set(sli, NULL);
+ elm_slider_unit_format_set(sli, "");
+ evas_object_smart_callback_add(sli, "changed", _evisum_ui_process_list_history_slider_preview_cb, view);
+ evas_object_smart_callback_add(sli, "slider,drag,start", _evisum_ui_process_list_history_slider_drag_start_cb, view);
+ evas_object_smart_callback_add(sli, "slider,drag,stop", _evisum_ui_process_list_history_slider_drag_stop_cb, view);
+ elm_box_pack_end(hbx, sli);
+ evas_object_show(sli);
+
+ view->summary.history_live_btn = btn = evisum_ui_widget_exel_icon_button_add(hbx, "start", _("Live"), 0.0, FILL,
+ _evisum_ui_process_list_history_live_clicked_cb,
+ view);
+ elm_object_disabled_set(btn, 1);
+ elm_box_pack_end(hbx, btn);
+ evas_object_show(btn);
+
+ _evisum_ui_process_list_history_bounds_update(view);
+ if (!view->history.timer) view->history.timer = ecore_timer_add(1.0, _evisum_ui_process_list_history_timer_cb, view);
}
static Eina_List *
@@ -840,7 +1114,26 @@ _evisum_ui_process_list_process_list(void *data, Ecore_Thread *thread) {
ecore_thread_name_set(thread, "process_list");
while (!ecore_thread_check(thread)) {
- if (!first_run && !view->skip_wait) {
+ Eina_Bool history_live, history_pending;
+ uint32_t history_time;
+
+ _evisum_ui_process_list_history_state_get(view, &history_live, &history_pending, &history_time);
+ if (!history_live) {
+ if (!history_pending && !first_run && !view->skip_wait) {
+ usleep(50000);
+ continue;
+ }
+ if (history_time) {
+ Eina_Bool live_now;
+ if (!evisum_engine_history_time_set(history_time)) {
+ usleep(50000);
+ continue;
+ }
+ _evisum_ui_process_list_history_state_get(view, &live_now, NULL, NULL);
+ if (live_now) evisum_engine_history_live_set();
+ else _evisum_ui_process_list_history_pending_clear(view, history_time);
+ }
+ } else if (!first_run && !view->skip_wait) {
int delay_secs = view->ui->proc.poll_delay;
int target_ticks;
if (delay_secs < 1) delay_secs = 1;
@@ -1544,8 +1837,27 @@ _evisum_ui_process_list_config_changed_cb(void *data, int type EINA_UNUSED, void
if ((!view->summary.visible) && (ui->proc.show_statusbar)) _evisum_ui_process_list_summary_add(view);
else if ((view->summary.visible) && (!ui->proc.show_statusbar)) {
+ evisum_engine_history_live_set();
+ eina_lock_take(&view->history.lock);
+ view->history.live = EINA_TRUE;
+ view->history.pending = EINA_FALSE;
+ view->history.sliding = EINA_FALSE;
+ view->history.requested_time = 0;
+ eina_lock_release(&view->history.lock);
+ if (view->history.timer) {
+ ecore_timer_del(view->history.timer);
+ view->history.timer = NULL;
+ }
+ if (view->history.apply_timer) {
+ ecore_timer_del(view->history.apply_timer);
+ view->history.apply_timer = NULL;
+ }
elm_box_clear(view->summary.hbx);
view->summary.visible = 0;
+ view->summary.pb_cpu = NULL;
+ view->summary.pb_mem = NULL;
+ view->summary.history_slider = NULL;
+ view->summary.history_live_btn = NULL;
}
_evisum_ui_process_list_win_alpha_set(view);
@@ -1580,6 +1892,8 @@ _evisum_ui_process_list_win_del_cb(void *data EINA_UNUSED, Evas *e EINA_UNUSED,
if (view->search.timer) ecore_timer_del(view->search.timer);
if (view->resize_timer) ecore_timer_del(view->resize_timer);
if (view->main_menu_timer) ecore_timer_del(view->main_menu_timer);
+ if (view->history.timer) ecore_timer_del(view->history.timer);
+ if (view->history.apply_timer) ecore_timer_del(view->history.apply_timer);
if (view->menu) evas_object_del(view->menu);
if (view->main_menu) evas_object_del(view->main_menu);
@@ -1588,6 +1902,8 @@ _evisum_ui_process_list_win_del_cb(void *data EINA_UNUSED, Evas *e EINA_UNUSED,
if (view->thread) ecore_thread_wait(view->thread, 0.5);
+ evisum_engine_history_live_set();
+
if (view->handler) ecore_event_handler_del(view->handler);
if (view->icon_cache) evisum_icon_cache_del(view->icon_cache);
@@ -1599,6 +1915,7 @@ _evisum_ui_process_list_win_del_cb(void *data EINA_UNUSED, Evas *e EINA_UNUSED,
if (view->widget_exel) evisum_ui_widget_exel_free(view->widget_exel);
if (view->proc_usage_cache) eina_hash_free(view->proc_usage_cache);
+ if (view->history.lock_init) eina_lock_free(&view->history.lock);
free(view);
view = NULL;
@@ -1641,6 +1958,10 @@ evisum_ui_process_list_win_add(Evisum_Ui *ui) {
view->selected_pid = -1;
view->ui = ui;
+ eina_lock_new(&view->history.lock);
+ view->history.lock_init = EINA_TRUE;
+ view->history.live = EINA_TRUE;
+ evisum_engine_history_live_set();
view->handler
= ecore_event_handler_add(EVISUM_EVENT_CONFIG_CHANGED, _evisum_ui_process_list_config_changed_cb, view);
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.