2019-06-15 14:51:21 +00:00
|
|
|
#include <cpuid.h>
|
|
|
|
#include <gtk/gtk.h>
|
|
|
|
#include "gui.h"
|
|
|
|
#include "zenmonitor.h"
|
|
|
|
|
2019-06-18 19:20:28 +00:00
|
|
|
GtkWidget *window;
|
|
|
|
|
2019-06-15 14:51:21 +00:00
|
|
|
static GtkTreeModel *model = NULL;
|
|
|
|
static guint timeout = 0;
|
|
|
|
static SensorSource *sensor_sources;
|
2020-02-16 16:53:51 +00:00
|
|
|
static const guint defaultHeight = 350;
|
2019-06-15 14:51:21 +00:00
|
|
|
|
|
|
|
enum {
|
|
|
|
COLUMN_NAME,
|
|
|
|
COLUMN_VALUE,
|
2019-06-18 22:06:34 +00:00
|
|
|
COLUMN_MIN,
|
|
|
|
COLUMN_MAX,
|
2019-06-15 14:51:21 +00:00
|
|
|
NUM_COLUMNS
|
|
|
|
};
|
|
|
|
|
|
|
|
static void init_sensors() {
|
|
|
|
GtkTreeIter iter;
|
|
|
|
GSList *sensor;
|
|
|
|
GtkListStore *store;
|
|
|
|
SensorSource *source;
|
|
|
|
const SensorInit *data;
|
|
|
|
guint i = 0;
|
|
|
|
|
|
|
|
store = GTK_LIST_STORE(model);
|
|
|
|
for (source = sensor_sources; source->drv; source++) {
|
|
|
|
if (source->func_init()){
|
|
|
|
source->sensors = source->func_get_sensors();
|
|
|
|
if (source->sensors != NULL) {
|
|
|
|
source->enabled = TRUE;
|
|
|
|
|
|
|
|
sensor = source->sensors;
|
|
|
|
while (sensor) {
|
|
|
|
data = (SensorInit*)sensor->data;
|
|
|
|
gtk_list_store_append(store, &iter);
|
|
|
|
gtk_list_store_set(store, &iter,
|
2019-06-18 22:06:34 +00:00
|
|
|
COLUMN_NAME, data->label,
|
2019-06-15 14:51:21 +00:00
|
|
|
COLUMN_VALUE, " --- ",
|
2019-06-18 22:06:34 +00:00
|
|
|
COLUMN_MIN, " --- ",
|
|
|
|
COLUMN_MAX, " --- ",
|
2019-06-15 14:51:21 +00:00
|
|
|
-1);
|
|
|
|
sensor = sensor->next;
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static GtkTreeModel* create_model (void) {
|
|
|
|
GtkListStore *store;
|
2019-06-18 22:06:34 +00:00
|
|
|
store = gtk_list_store_new (NUM_COLUMNS, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
|
2019-06-15 14:51:21 +00:00
|
|
|
return GTK_TREE_MODEL (store);
|
|
|
|
}
|
|
|
|
|
2019-06-18 22:06:34 +00:00
|
|
|
static void set_list_column_value(float num, const gchar *printf_format, GtkTreeIter *iter, gint column){
|
|
|
|
gchar *value;
|
|
|
|
if (num != ERROR_VALUE)
|
|
|
|
value = g_strdup_printf(printf_format, num);
|
|
|
|
else
|
|
|
|
value = g_strdup(" ? ? ?");
|
|
|
|
gtk_list_store_set(GTK_LIST_STORE (model), iter, column, value, -1);
|
|
|
|
g_free(value);
|
|
|
|
}
|
|
|
|
|
2019-06-15 14:51:21 +00:00
|
|
|
static gboolean update_data (gpointer data) {
|
|
|
|
GtkTreeIter iter;
|
|
|
|
GSList *node;
|
|
|
|
SensorSource *source;
|
|
|
|
const SensorInit *sensorData;
|
|
|
|
|
|
|
|
if (model == NULL)
|
|
|
|
return G_SOURCE_REMOVE;
|
|
|
|
|
|
|
|
if (!gtk_tree_model_get_iter_first (model, &iter))
|
|
|
|
return G_SOURCE_REMOVE;
|
|
|
|
|
|
|
|
for (source = sensor_sources; source->drv; source++) {
|
|
|
|
if (!source->enabled)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
source->func_update();
|
|
|
|
if (source->sensors){
|
|
|
|
node = source->sensors;
|
|
|
|
|
|
|
|
while(node) {
|
|
|
|
sensorData = (SensorInit*)node->data;
|
2019-06-18 22:06:34 +00:00
|
|
|
set_list_column_value(*(sensorData->value), sensorData->printf_format, &iter, COLUMN_VALUE);
|
|
|
|
set_list_column_value(*(sensorData->min), sensorData->printf_format, &iter, COLUMN_MIN);
|
|
|
|
set_list_column_value(*(sensorData->max), sensorData->printf_format, &iter, COLUMN_MAX);
|
|
|
|
|
2019-06-15 14:51:21 +00:00
|
|
|
node = node->next;
|
|
|
|
if (!gtk_tree_model_iter_next(model, &iter))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return G_SOURCE_CONTINUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void add_columns (GtkTreeView *treeview) {
|
2019-06-18 22:06:34 +00:00
|
|
|
GtkCellRenderer *renderer;
|
|
|
|
GtkTreeViewColumn *column;
|
|
|
|
|
|
|
|
// NAME
|
|
|
|
renderer = gtk_cell_renderer_text_new ();
|
|
|
|
column = gtk_tree_view_column_new_with_attributes ("Sensor", renderer,
|
2019-06-15 14:51:21 +00:00
|
|
|
"text", COLUMN_NAME,
|
|
|
|
NULL);
|
2019-06-18 22:06:34 +00:00
|
|
|
g_object_set(renderer, "family", "monotype", NULL);
|
|
|
|
gtk_tree_view_append_column (treeview, column);
|
2019-06-15 14:51:21 +00:00
|
|
|
|
2019-06-18 22:06:34 +00:00
|
|
|
//VALUE
|
|
|
|
renderer = gtk_cell_renderer_text_new ();
|
|
|
|
column = gtk_tree_view_column_new_with_attributes ("Value", renderer,
|
2019-06-15 14:51:21 +00:00
|
|
|
"text", COLUMN_VALUE,
|
|
|
|
NULL);
|
2019-06-18 22:06:34 +00:00
|
|
|
g_object_set(renderer, "family", "monotype", NULL);
|
|
|
|
gtk_tree_view_append_column (treeview, column);
|
|
|
|
|
|
|
|
//MIN
|
|
|
|
renderer = gtk_cell_renderer_text_new ();
|
|
|
|
column = gtk_tree_view_column_new_with_attributes ("Min", renderer,
|
|
|
|
"text", COLUMN_MIN,
|
|
|
|
NULL);
|
|
|
|
g_object_set(renderer, "family", "monotype", NULL);
|
|
|
|
gtk_tree_view_append_column (treeview, column);
|
|
|
|
|
|
|
|
//MAX
|
|
|
|
renderer = gtk_cell_renderer_text_new ();
|
|
|
|
column = gtk_tree_view_column_new_with_attributes ("Max", renderer,
|
|
|
|
"text", COLUMN_MAX,
|
|
|
|
NULL);
|
|
|
|
g_object_set(renderer, "family", "monotype", NULL);
|
|
|
|
gtk_tree_view_append_column (treeview, column);
|
2019-06-15 14:51:21 +00:00
|
|
|
}
|
|
|
|
|
2019-06-18 19:20:28 +00:00
|
|
|
static void about_btn_clicked(GtkButton *button, gpointer user_data) {
|
|
|
|
GtkWidget *dialog;
|
|
|
|
const gchar *website = "https://github.com/ocerman/zenmonitor";
|
2020-02-16 17:01:54 +00:00
|
|
|
const gchar *msg = "<b>Zen Monitor</b> 1.4.0\n"
|
2019-06-18 19:20:28 +00:00
|
|
|
"Monitoring software for AMD Zen-based CPUs\n"
|
|
|
|
"<a href=\"%s\">%s</a>\n\n"
|
|
|
|
"Created by: Ondrej Čerman";
|
|
|
|
|
|
|
|
dialog = gtk_message_dialog_new_with_markup(GTK_WINDOW (window),
|
|
|
|
GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
|
|
|
|
GTK_MESSAGE_INFO, GTK_BUTTONS_OK,
|
|
|
|
msg, website, website);
|
|
|
|
|
|
|
|
gtk_dialog_run(GTK_DIALOG(dialog));
|
|
|
|
gtk_widget_destroy(dialog);
|
|
|
|
}
|
2019-06-15 14:51:21 +00:00
|
|
|
|
2019-06-18 22:29:40 +00:00
|
|
|
static void clear_btn_clicked(GtkButton *button, gpointer user_data) {
|
|
|
|
SensorSource *source;
|
|
|
|
|
|
|
|
for (source = sensor_sources; source->drv; source++) {
|
|
|
|
if (!source->enabled)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
source->func_clear_minmax();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-09 20:20:26 +00:00
|
|
|
static gboolean mid_search_eq_func(GtkTreeModel *model, gint column, const gchar *key, GtkTreeIter *iter) {
|
|
|
|
gchar *iter_string = NULL, *lc_iter_string = NULL, *lc_key = NULL;
|
|
|
|
gboolean result;
|
|
|
|
|
|
|
|
gtk_tree_model_get(model, iter, column, &iter_string, -1);
|
|
|
|
lc_iter_string = g_utf8_strdown(iter_string, -1);
|
|
|
|
lc_key = g_utf8_strdown(key, -1);
|
|
|
|
|
|
|
|
result = (g_strrstr(lc_iter_string, lc_key) == NULL);
|
|
|
|
|
|
|
|
g_free(iter_string);
|
|
|
|
g_free(lc_iter_string);
|
|
|
|
g_free(lc_key);
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2020-02-16 16:53:51 +00:00
|
|
|
static void resize_to_treeview(GtkWindow* window, GtkTreeView* treeview) {
|
2020-02-18 20:09:10 +00:00
|
|
|
gint uiHeight, cellHeight, vSeparator, rows;
|
2020-02-16 16:53:51 +00:00
|
|
|
GdkRectangle r;
|
|
|
|
|
|
|
|
GtkTreeViewColumn *col = gtk_tree_view_get_column(treeview, 0);
|
|
|
|
if (!col)
|
|
|
|
return;
|
|
|
|
|
|
|
|
gtk_tree_view_column_cell_get_size(col, NULL, NULL, NULL, NULL, &cellHeight);
|
2020-02-18 20:09:10 +00:00
|
|
|
gtk_widget_style_get(GTK_WIDGET(treeview), "vertical-separator", &vSeparator, NULL);
|
2020-02-16 16:53:51 +00:00
|
|
|
rows = gtk_tree_model_iter_n_children(gtk_tree_view_get_model(treeview), NULL);
|
|
|
|
|
|
|
|
gtk_tree_view_get_visible_rect(treeview, &r);
|
|
|
|
uiHeight = defaultHeight - r.height;
|
|
|
|
|
2020-02-18 20:09:10 +00:00
|
|
|
gtk_window_resize(window, 500, uiHeight + (vSeparator + cellHeight) * rows);
|
2020-02-16 16:53:51 +00:00
|
|
|
}
|
|
|
|
|
2019-06-15 14:51:21 +00:00
|
|
|
int start_gui (SensorSource *ss) {
|
2019-06-18 22:29:40 +00:00
|
|
|
GtkWidget *about_btn;
|
|
|
|
GtkWidget *clear_btn;
|
|
|
|
GtkWidget *box;
|
2019-06-18 19:20:28 +00:00
|
|
|
GtkWidget *header;
|
2019-06-15 14:51:21 +00:00
|
|
|
GtkWidget *treeview;
|
|
|
|
GtkWidget *sw;
|
|
|
|
GtkWidget *vbox;
|
|
|
|
GtkWidget *dialog;
|
2019-06-18 22:29:40 +00:00
|
|
|
|
2019-06-15 14:51:21 +00:00
|
|
|
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
|
|
|
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
|
2020-02-16 16:53:51 +00:00
|
|
|
gtk_window_set_default_size(GTK_WINDOW(window), 500, defaultHeight);
|
2019-06-15 14:51:21 +00:00
|
|
|
|
2019-06-18 19:20:28 +00:00
|
|
|
header = gtk_header_bar_new();
|
|
|
|
gtk_header_bar_set_show_close_button(GTK_HEADER_BAR (header), TRUE);
|
|
|
|
gtk_header_bar_set_title(GTK_HEADER_BAR (header), "Zen monitor");
|
2019-06-18 19:56:29 +00:00
|
|
|
gtk_header_bar_set_has_subtitle(GTK_HEADER_BAR (header), TRUE);
|
|
|
|
gtk_header_bar_set_subtitle(GTK_HEADER_BAR (header), cpu_model());
|
2019-06-18 19:20:28 +00:00
|
|
|
gtk_window_set_titlebar (GTK_WINDOW (window), header);
|
|
|
|
|
2019-06-18 22:29:40 +00:00
|
|
|
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
|
|
|
|
gtk_style_context_add_class (gtk_widget_get_style_context (box), "linked");
|
|
|
|
|
|
|
|
about_btn = gtk_button_new();
|
|
|
|
gtk_container_add(GTK_CONTAINER(about_btn), gtk_image_new_from_icon_name("dialog-information", GTK_ICON_SIZE_BUTTON));
|
|
|
|
gtk_container_add(GTK_CONTAINER(box), about_btn);
|
2020-01-09 20:16:39 +00:00
|
|
|
gtk_widget_set_tooltip_text(about_btn, "About Zen monitor");
|
2019-06-18 22:29:40 +00:00
|
|
|
|
|
|
|
clear_btn = gtk_button_new();
|
|
|
|
gtk_container_add(GTK_CONTAINER(clear_btn), gtk_image_new_from_icon_name("edit-clear-all", GTK_ICON_SIZE_BUTTON));
|
|
|
|
gtk_container_add(GTK_CONTAINER(box), clear_btn);
|
2020-01-09 20:16:39 +00:00
|
|
|
gtk_widget_set_tooltip_text(clear_btn, "Clear Min/Max");
|
2019-06-18 19:20:28 +00:00
|
|
|
|
2019-06-18 22:29:40 +00:00
|
|
|
gtk_header_bar_pack_start(GTK_HEADER_BAR(header), box);
|
|
|
|
g_signal_connect(about_btn, "clicked", G_CALLBACK(about_btn_clicked), NULL);
|
|
|
|
g_signal_connect(clear_btn, "clicked", G_CALLBACK(clear_btn_clicked), NULL);
|
2019-06-15 14:51:21 +00:00
|
|
|
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
|
|
|
|
|
|
|
|
vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 8);
|
|
|
|
gtk_container_add(GTK_CONTAINER (window), vbox);
|
|
|
|
|
|
|
|
sw = gtk_scrolled_window_new (NULL, NULL);
|
|
|
|
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW(sw), GTK_SHADOW_ETCHED_IN);
|
|
|
|
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW (sw), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
|
|
|
|
gtk_box_pack_start(GTK_BOX (vbox), sw, TRUE, TRUE, 0);
|
|
|
|
|
|
|
|
model = create_model();
|
|
|
|
treeview = gtk_tree_view_new_with_model(model);
|
|
|
|
|
|
|
|
gtk_container_add (GTK_CONTAINER(sw), treeview);
|
|
|
|
add_columns(GTK_TREE_VIEW(treeview));
|
|
|
|
gtk_widget_show_all(window);
|
|
|
|
|
2020-01-09 20:20:26 +00:00
|
|
|
gtk_tree_view_set_search_column(GTK_TREE_VIEW(treeview), COLUMN_NAME);
|
|
|
|
gtk_tree_view_set_search_equal_func(GTK_TREE_VIEW(treeview),
|
|
|
|
(GtkTreeViewSearchEqualFunc)mid_search_eq_func, model, NULL);
|
|
|
|
|
|
|
|
g_object_unref(model);
|
|
|
|
|
2019-06-15 14:51:21 +00:00
|
|
|
if (check_zen()){
|
|
|
|
sensor_sources = ss;
|
|
|
|
init_sensors();
|
2020-02-16 16:53:51 +00:00
|
|
|
|
|
|
|
resize_to_treeview(GTK_WINDOW(window), GTK_TREE_VIEW(treeview));
|
2019-06-15 14:51:21 +00:00
|
|
|
timeout = g_timeout_add(300, update_data, NULL);
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
dialog = gtk_message_dialog_new(GTK_WINDOW (window),
|
|
|
|
GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
|
|
|
|
GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
|
|
|
|
"Zen CPU not detected!");
|
|
|
|
gtk_dialog_run(GTK_DIALOG(dialog));
|
|
|
|
gtk_widget_destroy(dialog);
|
|
|
|
}
|
|
|
|
|
|
|
|
gtk_main();
|
|
|
|
return 0;
|
|
|
|
}
|