mirror of
https://github.com/Syllo/nvtop.git
synced 2026-04-25 00:18:40 -04:00
861 lines
39 KiB
C
861 lines
39 KiB
C
/*
|
|
*
|
|
* Copyright (C) 2021 Maxime Schmitt <maxime.schmitt91@gmail.com>
|
|
*
|
|
* This file is part of Nvtop.
|
|
*
|
|
* Nvtop is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* Nvtop is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with nvtop. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
#include "nvtop/interface_setup_win.h"
|
|
#include "nvtop/interface.h"
|
|
#include "nvtop/interface_internal_common.h"
|
|
#include "nvtop/interface_options.h"
|
|
#include "nvtop/interface_ring_buffer.h"
|
|
|
|
#include <ncurses.h>
|
|
|
|
static char *setup_window_category_names[setup_window_selection_count] = {"General", "Devices", "Chart", "Processes",
|
|
"GPU Select"};
|
|
|
|
// All the windows used to display the setup
|
|
enum setup_window_type {
|
|
setup_window_type_setup,
|
|
setup_window_type_single,
|
|
setup_window_type_split_left,
|
|
setup_window_type_split_right,
|
|
setup_window_type_count
|
|
};
|
|
|
|
// General Options
|
|
|
|
enum setup_general_options {
|
|
setup_general_color,
|
|
setup_general_show_startup_support_messages,
|
|
setup_general_update_interval,
|
|
setup_general_options_count
|
|
};
|
|
|
|
static const char *setup_general_option_description[setup_general_options_count] = {
|
|
"Disable color (requires save and restart)", "Show support messages on startup", "Update interval (seconds)"};
|
|
|
|
// Header Options
|
|
|
|
enum setup_header_options {
|
|
setup_header_toggle_fahrenheit,
|
|
setup_header_enc_dec_timer,
|
|
setup_header_gpu_info_bar,
|
|
setup_header_options_count
|
|
};
|
|
|
|
static const char *setup_header_option_descriptions[setup_header_options_count] = {
|
|
"Temperature in fahrenheit", "Keep displaying Encoder/Decoder rate (after reaching an idle state)",
|
|
"Display extra GPU info bar"};
|
|
|
|
// Chart Options
|
|
|
|
enum setup_chart_options {
|
|
setup_chart_reverse,
|
|
setup_chart_all_gpu,
|
|
setup_chart_start_gpu_list,
|
|
setup_chart_options_count
|
|
};
|
|
|
|
static const char *setup_chart_options_descriptions[setup_chart_options_count] = {
|
|
"Reverse plot direction", "Displayed all GPUs", "Displayed GPU"};
|
|
|
|
static const char *setup_chart_gpu_value_descriptions[plot_information_count] = {
|
|
"GPU utilization rate", "GPU memory utilization rate", "GPU encoder rate", "GPU decoder rate",
|
|
"GPU temperature", "Power draw rate (current/max)", "Fan speed", "GPU clock rate",
|
|
"GPU memory clock rate"};
|
|
|
|
// Process List Options
|
|
|
|
enum setup_proc_list_options {
|
|
setup_proc_list_hide_process_list,
|
|
setup_proc_list_hide_nvtop_process,
|
|
setup_proc_list_sort_ascending,
|
|
setup_proc_list_sort_by,
|
|
setup_proc_list_display,
|
|
setup_proc_list_options_count
|
|
};
|
|
|
|
static const char *setup_proc_list_option_description[setup_proc_list_options_count] = {
|
|
"Don't display the process list", "Hide nvtop in the process list", "Sort Ascending", "Sort by", "Field Displayed"};
|
|
|
|
static const char *setup_proc_list_value_descriptions[process_field_count] = {
|
|
"Process Id", "User name", "Device Id", "Workload type", "GPU usage", "Encoder usage",
|
|
"Decoder usage", "GPU memory usage", "CPU usage", "CPU memory usage", "Command"};
|
|
|
|
static unsigned int sizeof_setup_windows[setup_window_type_count] = {[setup_window_type_setup] = 11,
|
|
[setup_window_type_single] = 0,
|
|
[setup_window_type_split_left] = 26,
|
|
[setup_window_type_split_right] = 0};
|
|
|
|
// For toggle options
|
|
// Show * if on, - if partial and nothing if off
|
|
enum option_state {
|
|
option_off,
|
|
option_on,
|
|
option_partially_active,
|
|
};
|
|
|
|
static char option_state_char(enum option_state state) {
|
|
switch (state) {
|
|
case option_on:
|
|
return '*';
|
|
case option_partially_active:
|
|
return '-';
|
|
case option_off:
|
|
return ' ';
|
|
default:
|
|
return ' ';
|
|
}
|
|
}
|
|
|
|
void alloc_setup_window(struct window_position *position, struct setup_window *setup_win) {
|
|
setup_win->visible = false;
|
|
setup_win->clean_space = newwin(position->sizeY, position->sizeX, position->posY, position->posX);
|
|
|
|
sizeof_setup_windows[setup_window_type_single] = position->sizeX - sizeof_setup_windows[setup_window_type_setup] - 1;
|
|
if (sizeof_setup_windows[setup_window_type_single] > position->sizeX)
|
|
sizeof_setup_windows[setup_window_type_single] = 0;
|
|
|
|
sizeof_setup_windows[setup_window_type_split_right] = position->sizeX -
|
|
sizeof_setup_windows[setup_window_type_setup] -
|
|
sizeof_setup_windows[setup_window_type_split_left] - 2;
|
|
if (sizeof_setup_windows[setup_window_type_split_right] > position->sizeX)
|
|
sizeof_setup_windows[setup_window_type_split_right] = 0;
|
|
|
|
setup_win->setup =
|
|
newwin(position->sizeY, sizeof_setup_windows[setup_window_type_setup], position->posY, position->posX);
|
|
|
|
setup_win->single = newwin(position->sizeY, sizeof_setup_windows[setup_window_type_single], position->posY,
|
|
position->posX + sizeof_setup_windows[setup_window_type_setup] + 1);
|
|
|
|
setup_win->split[0] = newwin(position->sizeY, sizeof_setup_windows[setup_window_type_split_left], position->posY,
|
|
position->posX + sizeof_setup_windows[setup_window_type_setup] + 1);
|
|
|
|
setup_win->split[1] = newwin(position->sizeY, sizeof_setup_windows[setup_window_type_split_right], position->posY,
|
|
position->posX + sizeof_setup_windows[setup_window_type_setup] +
|
|
sizeof_setup_windows[setup_window_type_split_left] + 2);
|
|
}
|
|
|
|
void free_setup_window(struct setup_window *setup_win) {
|
|
delwin(setup_win->clean_space);
|
|
delwin(setup_win->setup);
|
|
delwin(setup_win->single);
|
|
delwin(setup_win->split[0]);
|
|
delwin(setup_win->split[1]);
|
|
}
|
|
|
|
void show_setup_window(struct nvtop_interface *interface) {
|
|
interface->setup_win.visible = true;
|
|
touchwin(interface->setup_win.clean_space);
|
|
wnoutrefresh(interface->setup_win.clean_space);
|
|
interface->setup_win.selected_section = setup_general_selected;
|
|
interface->setup_win.indentation_level = 0;
|
|
interface->setup_win.options_selected[0] = 0;
|
|
interface->setup_win.options_selected[1] = 0;
|
|
}
|
|
|
|
void hide_setup_window(struct nvtop_interface *interface) { interface->setup_win.visible = false; }
|
|
|
|
static void draw_setup_window_setup(struct nvtop_interface *interface) {
|
|
werase(interface->setup_win.setup);
|
|
mvwprintw(interface->setup_win.setup, 0, 0, "Setup");
|
|
mvwchgat(interface->setup_win.setup, 0, 0, sizeof_setup_windows[setup_window_type_setup], A_STANDOUT, green_color,
|
|
NULL);
|
|
for (enum setup_window_section category = setup_general_selected; category < setup_window_selection_count;
|
|
++category) {
|
|
mvwprintw(interface->setup_win.setup, category + 1, 0, "%s", setup_window_category_names[category]);
|
|
if (interface->setup_win.selected_section == category) {
|
|
if (interface->setup_win.indentation_level == 0) {
|
|
set_attribute_between(interface->setup_win.setup, category + 1, 0,
|
|
sizeof_setup_windows[setup_window_type_setup], A_STANDOUT, cyan_color);
|
|
} else {
|
|
mvwprintw(interface->setup_win.setup, category + 1, sizeof_setup_windows[setup_window_type_setup] - 1, ">");
|
|
set_attribute_between(interface->setup_win.setup, category + 1, 0,
|
|
sizeof_setup_windows[setup_window_type_setup], A_BOLD, cyan_color);
|
|
}
|
|
}
|
|
}
|
|
wnoutrefresh(interface->setup_win.setup);
|
|
}
|
|
|
|
static void draw_setup_window_general(struct nvtop_interface *interface) {
|
|
if (interface->setup_win.indentation_level > 1)
|
|
interface->setup_win.indentation_level = 1;
|
|
if (interface->setup_win.indentation_level == 1 &&
|
|
interface->setup_win.options_selected[0] >= setup_general_options_count)
|
|
interface->setup_win.options_selected[0] = setup_general_options_count - 1;
|
|
|
|
wattr_set(interface->setup_win.single, A_STANDOUT, green_color, NULL);
|
|
mvwprintw(interface->setup_win.single, 0, 0, "General Options");
|
|
wstandend(interface->setup_win.single);
|
|
|
|
unsigned int cur_col, maxcols, tmp;
|
|
(void)tmp;
|
|
getmaxyx(interface->setup_win.single, tmp, maxcols);
|
|
getyx(interface->setup_win.single, tmp, cur_col);
|
|
mvwchgat(interface->setup_win.single, 0, cur_col, maxcols - cur_col, A_STANDOUT, green_color, NULL);
|
|
|
|
enum option_state option_state = !interface->options.use_color;
|
|
mvwprintw(interface->setup_win.single, setup_general_color + 1, 0, "[%c] %s", option_state_char(option_state),
|
|
setup_general_option_description[setup_general_color]);
|
|
if (interface->setup_win.indentation_level == 1 && interface->setup_win.options_selected[0] == setup_general_color) {
|
|
mvwchgat(interface->setup_win.single, setup_general_color + 1, 0, 3, A_STANDOUT, cyan_color, NULL);
|
|
}
|
|
option_state = interface->options.show_startup_messages;
|
|
mvwprintw(interface->setup_win.single, setup_general_show_startup_support_messages + 1, 0, "[%c] %s",
|
|
option_state_char(option_state),
|
|
setup_general_option_description[setup_general_show_startup_support_messages]);
|
|
if (interface->setup_win.indentation_level == 1 &&
|
|
interface->setup_win.options_selected[0] == setup_general_show_startup_support_messages) {
|
|
mvwchgat(interface->setup_win.single, setup_general_show_startup_support_messages + 1, 0, 3, A_STANDOUT, cyan_color,
|
|
NULL);
|
|
}
|
|
|
|
int update_deciseconds = (interface->options.update_interval / 100) % 10;
|
|
int update_seconds = interface->options.update_interval / 1000;
|
|
mvwprintw(interface->setup_win.single, setup_general_update_interval + 1, 0, "[%2u.%u] %s", update_seconds,
|
|
update_deciseconds, setup_general_option_description[setup_general_update_interval]);
|
|
if (interface->setup_win.indentation_level == 1 &&
|
|
interface->setup_win.options_selected[0] == setup_general_update_interval) {
|
|
mvwchgat(interface->setup_win.single, setup_general_update_interval + 1, 0, 6, A_STANDOUT, cyan_color, NULL);
|
|
}
|
|
wnoutrefresh(interface->setup_win.single);
|
|
}
|
|
|
|
static void draw_setup_window_header(struct nvtop_interface *interface) {
|
|
if (interface->setup_win.indentation_level > 1)
|
|
interface->setup_win.indentation_level = 1;
|
|
if (interface->setup_win.options_selected[0] >= setup_header_options_count)
|
|
interface->setup_win.options_selected[0] = setup_header_options_count - 1;
|
|
|
|
WINDOW *options_win = interface->setup_win.single;
|
|
|
|
wattr_set(options_win, A_STANDOUT, green_color, NULL);
|
|
mvwprintw(options_win, 0, 0, "Devices Display Options");
|
|
wstandend(options_win);
|
|
|
|
unsigned int cur_col, maxcols, tmp;
|
|
(void)tmp;
|
|
getmaxyx(options_win, tmp, maxcols);
|
|
getyx(options_win, tmp, cur_col);
|
|
mvwchgat(options_win, 0, cur_col, maxcols - cur_col, A_STANDOUT, green_color, NULL);
|
|
|
|
enum option_state option_state;
|
|
|
|
// Fahrenheit Option
|
|
option_state = interface->options.temperature_in_fahrenheit;
|
|
mvwprintw(options_win, setup_header_toggle_fahrenheit + 1, 0, "[%c] %s", option_state_char(option_state),
|
|
setup_header_option_descriptions[setup_header_toggle_fahrenheit]);
|
|
if (interface->setup_win.indentation_level == 1 &&
|
|
interface->setup_win.options_selected[0] == setup_header_toggle_fahrenheit) {
|
|
mvwchgat(options_win, setup_header_toggle_fahrenheit + 1, 0, 3, A_STANDOUT, cyan_color, NULL);
|
|
}
|
|
|
|
// Encode/Decode hiding timer
|
|
if (interface->options.encode_decode_hiding_timer > 0) {
|
|
mvwprintw(options_win, setup_header_enc_dec_timer + 1, 0, "[%3.0fsec] %s",
|
|
interface->options.encode_decode_hiding_timer,
|
|
setup_header_option_descriptions[setup_header_enc_dec_timer]);
|
|
} else {
|
|
mvwprintw(options_win, setup_header_enc_dec_timer + 1, 0, "[always] %s",
|
|
setup_header_option_descriptions[setup_header_enc_dec_timer]);
|
|
}
|
|
if (interface->setup_win.indentation_level == 1 &&
|
|
interface->setup_win.options_selected[0] == setup_header_enc_dec_timer) {
|
|
mvwchgat(options_win, setup_header_enc_dec_timer + 1, 0, 8, A_STANDOUT, cyan_color, NULL);
|
|
}
|
|
|
|
// Extra GPU info bar
|
|
option_state = interface->options.has_gpu_info_bar;
|
|
mvwprintw(options_win, setup_header_gpu_info_bar + 1, 0, "[%c] %s", option_state_char(option_state),
|
|
setup_header_option_descriptions[setup_header_gpu_info_bar]);
|
|
if (interface->setup_win.indentation_level == 1 &&
|
|
interface->setup_win.options_selected[0] == setup_header_gpu_info_bar) {
|
|
mvwchgat(options_win, setup_header_gpu_info_bar + 1, 0, 3, A_STANDOUT, cyan_color, NULL);
|
|
}
|
|
wnoutrefresh(options_win);
|
|
}
|
|
|
|
static void draw_setup_window_chart(unsigned devices_count, struct list_head *devices,
|
|
struct nvtop_interface *interface) {
|
|
WINDOW *option_list_win;
|
|
|
|
// Fix indices for this window
|
|
if (interface->setup_win.options_selected[0] > devices_count + 1)
|
|
interface->setup_win.options_selected[0] = devices_count + 1;
|
|
if (interface->setup_win.options_selected[0] > 0) {
|
|
if (interface->setup_win.options_selected[1] >= plot_information_count)
|
|
interface->setup_win.options_selected[1] = plot_information_count - 1;
|
|
option_list_win = interface->setup_win.split[0];
|
|
} else {
|
|
if (interface->setup_win.indentation_level > 1)
|
|
interface->setup_win.indentation_level = 1;
|
|
option_list_win = interface->setup_win.single;
|
|
}
|
|
werase(interface->setup_win.single);
|
|
wnoutrefresh(interface->setup_win.single);
|
|
touchwin(interface->setup_win.split[0]);
|
|
touchwin(interface->setup_win.split[1]);
|
|
|
|
wattr_set(option_list_win, A_STANDOUT, green_color, NULL);
|
|
mvwprintw(option_list_win, 0, 0, "Chart Options");
|
|
wstandend(option_list_win);
|
|
|
|
unsigned int cur_col, maxcols, tmp;
|
|
(void)tmp;
|
|
getmaxyx(option_list_win, tmp, maxcols);
|
|
getyx(option_list_win, tmp, cur_col);
|
|
mvwchgat(option_list_win, 0, cur_col, maxcols - cur_col, A_STANDOUT, green_color, NULL);
|
|
|
|
enum option_state option_state;
|
|
|
|
// Reverse plot
|
|
option_state = interface->options.plot_left_to_right;
|
|
mvwprintw(option_list_win, setup_chart_reverse + 1, 0, "[%c] %s", option_state_char(option_state),
|
|
setup_chart_options_descriptions[setup_chart_reverse]);
|
|
if (interface->setup_win.indentation_level == 1 && interface->setup_win.options_selected[0] == setup_chart_reverse) {
|
|
mvwchgat(option_list_win, setup_chart_reverse + 1, 0, 3, A_STANDOUT, cyan_color, NULL);
|
|
}
|
|
|
|
// Set for all GPUs at once
|
|
if (interface->setup_win.options_selected[0] == setup_chart_all_gpu) {
|
|
if (interface->setup_win.indentation_level == 1)
|
|
wattr_set(option_list_win, A_STANDOUT, cyan_color, NULL);
|
|
if (interface->setup_win.indentation_level == 2)
|
|
wattr_set(option_list_win, A_BOLD, cyan_color, NULL);
|
|
}
|
|
mvwaddch(option_list_win, setup_chart_all_gpu + 1, 1, ACS_HLINE);
|
|
waddch(option_list_win, '>');
|
|
wstandend(option_list_win);
|
|
wprintw(option_list_win, " %s", setup_chart_options_descriptions[setup_chart_all_gpu]);
|
|
|
|
// GPUs as a list
|
|
for (unsigned i = 0; i < devices_count; ++i) {
|
|
if (interface->setup_win.options_selected[0] == setup_chart_start_gpu_list + i) {
|
|
if (interface->setup_win.indentation_level == 1)
|
|
wattr_set(option_list_win, A_STANDOUT, cyan_color, NULL);
|
|
if (interface->setup_win.indentation_level == 2)
|
|
wattr_set(option_list_win, A_BOLD, cyan_color, NULL);
|
|
}
|
|
mvwaddch(option_list_win, setup_chart_start_gpu_list + 1 + i, 1, ACS_HLINE);
|
|
waddch(option_list_win, '>');
|
|
wstandend(option_list_win);
|
|
wprintw(option_list_win, " %s %u", setup_chart_options_descriptions[setup_chart_start_gpu_list], i);
|
|
}
|
|
wnoutrefresh(option_list_win);
|
|
|
|
// Window of list of metric to display in chart (4 maximum)
|
|
if (interface->setup_win.options_selected[0] >= setup_chart_all_gpu) {
|
|
WINDOW *value_list_win = interface->setup_win.split[1];
|
|
wattr_set(value_list_win, A_STANDOUT, green_color, NULL);
|
|
mvwprintw(value_list_win, 0, 0, "Metric Displayed in Graph");
|
|
getmaxyx(value_list_win, tmp, maxcols);
|
|
unsigned selected_gpu = interface->setup_win.options_selected[0] - setup_chart_start_gpu_list;
|
|
if (interface->setup_win.options_selected[0] == setup_chart_all_gpu) {
|
|
wprintw(value_list_win, " (All GPUs)");
|
|
} else {
|
|
// Get the selected device
|
|
struct gpu_info *device;
|
|
unsigned index = 0;
|
|
list_for_each_entry(device, devices, list) {
|
|
if (index == selected_gpu)
|
|
break;
|
|
index++;
|
|
}
|
|
if (IS_VALID(gpuinfo_device_name_valid, device->static_info.valid)) {
|
|
getyx(value_list_win, tmp, cur_col);
|
|
wprintw(value_list_win, " (%.*s)", maxcols - cur_col - 3, device->static_info.device_name);
|
|
} else
|
|
wprintw(value_list_win, " (GPU %u)", selected_gpu);
|
|
}
|
|
wclrtoeol(value_list_win);
|
|
getyx(value_list_win, tmp, cur_col);
|
|
mvwchgat(value_list_win, 0, cur_col, maxcols - cur_col, A_STANDOUT, green_color, NULL);
|
|
wattr_set(value_list_win, A_NORMAL, magenta_color, NULL);
|
|
mvwprintw(value_list_win, 1, 0, "Maximum of 4 metrics per GPU");
|
|
wstandend(value_list_win);
|
|
|
|
for (enum plot_information i = plot_gpu_rate; i < plot_information_count; ++i) {
|
|
if (interface->setup_win.options_selected[0] == setup_chart_all_gpu) {
|
|
plot_info_to_draw draw_union = 0, draw_intersection = 0xffff;
|
|
for (unsigned j = 0; j < devices_count; ++j) {
|
|
draw_union |= interface->options.gpu_specific_opts[j].to_draw;
|
|
draw_intersection = draw_intersection & interface->options.gpu_specific_opts[j].to_draw;
|
|
}
|
|
if (plot_isset_draw_info(i, draw_intersection)) {
|
|
option_state = option_on;
|
|
} else {
|
|
if (plot_isset_draw_info(i, draw_union))
|
|
option_state = option_partially_active;
|
|
else
|
|
option_state = option_off;
|
|
}
|
|
} else {
|
|
option_state = plot_isset_draw_info(i, interface->options.gpu_specific_opts[selected_gpu].to_draw);
|
|
}
|
|
mvwprintw(value_list_win, i + 2, 0, "[%c] %s", option_state_char(option_state),
|
|
setup_chart_gpu_value_descriptions[i]);
|
|
if (interface->setup_win.indentation_level == 2 && interface->setup_win.options_selected[1] == i) {
|
|
mvwchgat(value_list_win, i + 2, 0, 3, A_STANDOUT, cyan_color, NULL);
|
|
}
|
|
}
|
|
wnoutrefresh(value_list_win);
|
|
}
|
|
}
|
|
|
|
static void draw_setup_window_proc_list(struct nvtop_interface *interface) {
|
|
WINDOW *option_list_win;
|
|
if (interface->setup_win.options_selected[0] >= setup_proc_list_options_count)
|
|
interface->setup_win.options_selected[0] = setup_proc_list_options_count - 1;
|
|
if (interface->setup_win.options_selected[0] < setup_proc_list_sort_by) {
|
|
option_list_win = interface->setup_win.single;
|
|
if (interface->setup_win.indentation_level > 1)
|
|
interface->setup_win.indentation_level = 1;
|
|
} else {
|
|
option_list_win = interface->setup_win.split[0];
|
|
if (interface->setup_win.options_selected[0] == setup_proc_list_sort_by) {
|
|
unsigned fields_count = process_field_displayed_count(interface->options.process_fields_displayed);
|
|
if (!fields_count) {
|
|
if (interface->setup_win.indentation_level > 1)
|
|
interface->setup_win.indentation_level = 1;
|
|
} else {
|
|
if (interface->setup_win.options_selected[1] >= fields_count)
|
|
interface->setup_win.options_selected[1] = fields_count - 1;
|
|
}
|
|
}
|
|
if (interface->setup_win.options_selected[0] == setup_proc_list_display) {
|
|
if (interface->setup_win.options_selected[1] >= process_field_count)
|
|
interface->setup_win.options_selected[1] = process_field_count - 1;
|
|
}
|
|
}
|
|
|
|
werase(interface->setup_win.single);
|
|
wnoutrefresh(interface->setup_win.single);
|
|
touchwin(interface->setup_win.split[0]);
|
|
touchwin(interface->setup_win.split[1]);
|
|
|
|
wattr_set(option_list_win, A_STANDOUT, green_color, NULL);
|
|
mvwprintw(option_list_win, 0, 0, "Process List Options");
|
|
wstandend(option_list_win);
|
|
unsigned int cur_col, maxcols, tmp;
|
|
(void)tmp;
|
|
getmaxyx(option_list_win, tmp, maxcols);
|
|
getyx(option_list_win, tmp, cur_col);
|
|
mvwchgat(option_list_win, 0, cur_col, maxcols - cur_col, A_STANDOUT, green_color, NULL);
|
|
|
|
// Sort Ascending
|
|
enum option_state option_state = interface->options.hide_processes_list;
|
|
mvwprintw(option_list_win, setup_proc_list_hide_process_list + 1, 0, "[%c] %s", option_state_char(option_state),
|
|
setup_proc_list_option_description[setup_proc_list_hide_process_list]);
|
|
if (interface->setup_win.indentation_level == 1 &&
|
|
interface->setup_win.options_selected[0] == setup_proc_list_hide_process_list) {
|
|
mvwchgat(option_list_win, setup_proc_list_hide_process_list + 1, 0, 3, A_STANDOUT, cyan_color, NULL);
|
|
}
|
|
option_state = interface->options.filter_nvtop_pid;
|
|
mvwprintw(option_list_win, setup_proc_list_hide_nvtop_process + 1, 0, "[%c] %s", option_state_char(option_state),
|
|
setup_proc_list_option_description[setup_proc_list_hide_nvtop_process]);
|
|
if (interface->setup_win.indentation_level == 1 &&
|
|
interface->setup_win.options_selected[0] == setup_proc_list_hide_nvtop_process) {
|
|
mvwchgat(option_list_win, setup_proc_list_hide_nvtop_process + 1, 0, 3, A_STANDOUT, cyan_color, NULL);
|
|
}
|
|
option_state = !interface->options.sort_descending_order;
|
|
mvwprintw(option_list_win, setup_proc_list_sort_ascending + 1, 0, "[%c] %s", option_state_char(option_state),
|
|
setup_proc_list_option_description[setup_proc_list_sort_ascending]);
|
|
if (interface->setup_win.indentation_level == 1 &&
|
|
interface->setup_win.options_selected[0] == setup_proc_list_sort_ascending) {
|
|
mvwchgat(option_list_win, setup_proc_list_sort_ascending + 1, 0, 3, A_STANDOUT, cyan_color, NULL);
|
|
}
|
|
|
|
for (enum setup_proc_list_options i = setup_proc_list_sort_by; i < setup_proc_list_options_count; ++i) {
|
|
if (interface->setup_win.options_selected[0] == i) {
|
|
if (interface->setup_win.indentation_level == 1)
|
|
wattr_set(option_list_win, A_STANDOUT, cyan_color, NULL);
|
|
if (interface->setup_win.indentation_level == 2)
|
|
wattr_set(option_list_win, A_BOLD, cyan_color, NULL);
|
|
}
|
|
mvwaddch(option_list_win, i + 1, 1, ACS_HLINE);
|
|
waddch(option_list_win, '>');
|
|
wstandend(option_list_win);
|
|
wprintw(option_list_win, " %s", setup_proc_list_option_description[i]);
|
|
wnoutrefresh(option_list_win);
|
|
}
|
|
|
|
if (interface->setup_win.options_selected[0] >= setup_proc_list_sort_by) {
|
|
WINDOW *value_list_win = interface->setup_win.split[1];
|
|
// Sort by
|
|
if (interface->setup_win.options_selected[0] == setup_proc_list_sort_by) {
|
|
wattr_set(value_list_win, A_STANDOUT, green_color, NULL);
|
|
mvwprintw(value_list_win, 0, 0, "Processes are sorted by:");
|
|
wstandend(value_list_win);
|
|
wclrtoeol(value_list_win);
|
|
getmaxyx(value_list_win, tmp, maxcols);
|
|
getyx(value_list_win, tmp, cur_col);
|
|
mvwchgat(value_list_win, 0, cur_col, maxcols - cur_col, A_STANDOUT, green_color, NULL);
|
|
unsigned index = 0;
|
|
for (enum process_field field = process_pid; field < process_field_count; ++field) {
|
|
if (process_is_field_displayed(field, interface->options.process_fields_displayed)) {
|
|
option_state = interface->options.sort_processes_by == field;
|
|
mvwprintw(value_list_win, index + 1, 0, "[%c] %s", option_state_char(option_state),
|
|
setup_proc_list_value_descriptions[field]);
|
|
wclrtoeol(value_list_win);
|
|
if (interface->setup_win.indentation_level == 2 && interface->setup_win.options_selected[1] == index) {
|
|
mvwchgat(value_list_win, index + 1, 0, 3, A_STANDOUT, cyan_color, NULL);
|
|
wmove(value_list_win, field + 2, 0);
|
|
}
|
|
index++;
|
|
}
|
|
}
|
|
if (!index) {
|
|
// Nothing displayed
|
|
wcolor_set(value_list_win, magenta_color, NULL);
|
|
mvwprintw(value_list_win, 1, 0, "Nothing to sort: none of the process fields are displayed");
|
|
wstandend(value_list_win);
|
|
}
|
|
}
|
|
// Process field displayed
|
|
if (interface->setup_win.options_selected[0] == setup_proc_list_display) {
|
|
wattr_set(value_list_win, A_STANDOUT, green_color, NULL);
|
|
mvwprintw(value_list_win, 0, 0, "Process Field Displayed:");
|
|
wstandend(value_list_win);
|
|
wclrtoeol(value_list_win);
|
|
getmaxyx(value_list_win, tmp, maxcols);
|
|
getyx(value_list_win, tmp, cur_col);
|
|
mvwchgat(value_list_win, 0, cur_col, maxcols - cur_col, A_STANDOUT, green_color, NULL);
|
|
for (enum process_field field = process_pid; field < process_field_count; ++field) {
|
|
option_state = process_is_field_displayed(field, interface->options.process_fields_displayed);
|
|
mvwprintw(value_list_win, field + 1, 0, "[%c] %s", option_state_char(option_state),
|
|
setup_proc_list_value_descriptions[field]);
|
|
wclrtoeol(value_list_win);
|
|
if (interface->setup_win.indentation_level == 2 && interface->setup_win.options_selected[1] == field) {
|
|
mvwchgat(value_list_win, field + 1, 0, 3, A_STANDOUT, cyan_color, NULL);
|
|
wmove(value_list_win, field + 2, 0);
|
|
}
|
|
}
|
|
}
|
|
wclrtobot(value_list_win);
|
|
wnoutrefresh(value_list_win);
|
|
}
|
|
}
|
|
|
|
static void draw_setup_window_gpu_select(struct nvtop_interface *interface) {
|
|
if (interface->setup_win.indentation_level > 1)
|
|
interface->setup_win.indentation_level = 1;
|
|
if (interface->setup_win.indentation_level == 1 &&
|
|
interface->setup_win.options_selected[0] >= interface->total_dev_count)
|
|
interface->setup_win.options_selected[0] = interface->total_dev_count - 1;
|
|
|
|
wattr_set(interface->setup_win.single, A_STANDOUT, green_color, NULL);
|
|
mvwprintw(interface->setup_win.single, 0, 0, "Select Monitored GPUs");
|
|
wstandend(interface->setup_win.single);
|
|
unsigned int cur_col, maxcols, tmp;
|
|
(void)tmp;
|
|
getmaxyx(interface->setup_win.single, tmp, maxcols);
|
|
getyx(interface->setup_win.single, tmp, cur_col);
|
|
mvwchgat(interface->setup_win.single, 0, cur_col, maxcols - cur_col, A_STANDOUT, green_color, NULL);
|
|
|
|
for (unsigned devId = 0; devId < interface->total_dev_count; ++devId) {
|
|
mvwprintw(interface->setup_win.single, devId + 1, 0, "[%c] %s",
|
|
option_state_char(!interface->options.gpu_specific_opts[devId].doNotMonitor),
|
|
interface->options.gpu_specific_opts[devId].linkedGpu->static_info.device_name);
|
|
if (interface->setup_win.indentation_level == 1 && interface->setup_win.options_selected[0] == devId)
|
|
mvwchgat(interface->setup_win.single, devId + 1, 0, 3, A_STANDOUT, cyan_color, NULL);
|
|
}
|
|
|
|
wnoutrefresh(interface->setup_win.single);
|
|
}
|
|
|
|
static const char *setup_window_shortcuts[] = {"Enter", "ESC", "Arrow keys", "+/-", "F12"};
|
|
|
|
static const char *setup_window_shortcut_description[] = {"Toggle", "Exit", "Navigate Menu",
|
|
"Increment/Decrement Values", "Save Config"};
|
|
|
|
void draw_setup_window_shortcuts(struct nvtop_interface *interface) {
|
|
WINDOW *window = interface->shortcut_window;
|
|
|
|
wmove(window, 0, 0);
|
|
for (size_t i = 0; i < ARRAY_SIZE(setup_window_shortcuts); ++i) {
|
|
wprintw(window, "%s", setup_window_shortcuts[i]);
|
|
wattr_set(window, A_STANDOUT, cyan_color, NULL);
|
|
wprintw(window, "%s ", setup_window_shortcut_description[i]);
|
|
wstandend(window);
|
|
}
|
|
wclrtoeol(window);
|
|
unsigned int cur_col, tmp;
|
|
(void)tmp;
|
|
getyx(window, tmp, cur_col);
|
|
mvwchgat(window, 0, cur_col, -1, A_STANDOUT, cyan_color, NULL);
|
|
wnoutrefresh(window);
|
|
}
|
|
|
|
void draw_setup_window(unsigned devices_count, struct list_head *devices, struct nvtop_interface *interface) {
|
|
draw_setup_window_setup(interface);
|
|
switch (interface->setup_win.selected_section) {
|
|
case setup_general_selected:
|
|
draw_setup_window_general(interface);
|
|
break;
|
|
case setup_header_selected:
|
|
draw_setup_window_header(interface);
|
|
break;
|
|
case setup_chart_selected:
|
|
draw_setup_window_chart(devices_count, devices, interface);
|
|
break;
|
|
case setup_process_list_selected:
|
|
draw_setup_window_proc_list(interface);
|
|
break;
|
|
case setup_monitored_gpu_list_selected:
|
|
draw_setup_window_gpu_select(interface);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void handle_setup_win_keypress(int keyId, struct nvtop_interface *interface) {
|
|
if (interface->setup_win.visible) {
|
|
switch (keyId) {
|
|
|
|
case 'l':
|
|
case KEY_RIGHT:
|
|
if (interface->setup_win.indentation_level < 2)
|
|
interface->setup_win.indentation_level++;
|
|
break;
|
|
|
|
case 'h':
|
|
case KEY_LEFT:
|
|
if (interface->setup_win.indentation_level > 0)
|
|
interface->setup_win.indentation_level--;
|
|
break;
|
|
|
|
case 'k':
|
|
case KEY_UP:
|
|
if (interface->setup_win.indentation_level == 0) {
|
|
if (interface->setup_win.selected_section != setup_general_selected) {
|
|
interface->setup_win.selected_section--;
|
|
interface->setup_win.options_selected[0] = 0;
|
|
interface->setup_win.options_selected[1] = 0;
|
|
werase(interface->setup_win.single);
|
|
werase(interface->setup_win.split[0]);
|
|
werase(interface->setup_win.split[1]);
|
|
wnoutrefresh(interface->setup_win.single);
|
|
}
|
|
} else {
|
|
if (interface->setup_win.indentation_level == 1)
|
|
interface->setup_win.options_selected[1] = 0;
|
|
if (interface->setup_win.options_selected[interface->setup_win.indentation_level - 1] != 0)
|
|
interface->setup_win.options_selected[interface->setup_win.indentation_level - 1]--;
|
|
}
|
|
break;
|
|
|
|
case 'j':
|
|
case KEY_DOWN:
|
|
if (interface->setup_win.indentation_level == 0) {
|
|
if (interface->setup_win.selected_section + 1 != setup_window_selection_count) {
|
|
|
|
interface->setup_win.selected_section++;
|
|
interface->setup_win.options_selected[0] = 0;
|
|
interface->setup_win.options_selected[1] = 0;
|
|
werase(interface->setup_win.single);
|
|
werase(interface->setup_win.split[0]);
|
|
werase(interface->setup_win.split[1]);
|
|
wnoutrefresh(interface->setup_win.single);
|
|
}
|
|
} else {
|
|
if (interface->setup_win.indentation_level == 1)
|
|
interface->setup_win.options_selected[1] = 0;
|
|
interface->setup_win.options_selected[interface->setup_win.indentation_level - 1]++;
|
|
}
|
|
break;
|
|
|
|
case '+':
|
|
// General Options
|
|
if (interface->setup_win.selected_section == setup_general_selected) {
|
|
if (interface->setup_win.options_selected[0] == setup_general_update_interval) {
|
|
if (interface->options.update_interval <= 99800)
|
|
interface->options.update_interval += 100;
|
|
}
|
|
}
|
|
// Header options
|
|
if (interface->setup_win.selected_section == setup_header_selected) {
|
|
if (interface->setup_win.indentation_level == 1) {
|
|
if (interface->setup_win.options_selected[0] == setup_header_enc_dec_timer) {
|
|
interface->options.encode_decode_hiding_timer += 5.;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case '-':
|
|
// General Options
|
|
if (interface->setup_win.selected_section == setup_general_selected) {
|
|
if (interface->setup_win.options_selected[0] == setup_general_update_interval) {
|
|
if (interface->options.update_interval >= 200)
|
|
interface->options.update_interval -= 100;
|
|
}
|
|
}
|
|
// Header options
|
|
if (interface->setup_win.selected_section == setup_header_selected) {
|
|
if (interface->setup_win.indentation_level == 1) {
|
|
if (interface->setup_win.options_selected[0] == setup_header_enc_dec_timer) {
|
|
interface->options.encode_decode_hiding_timer -= 5.;
|
|
if (interface->options.encode_decode_hiding_timer < 0.) {
|
|
interface->options.encode_decode_hiding_timer = 0.;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case '\n':
|
|
case KEY_ENTER:
|
|
if (interface->setup_win.indentation_level == 0) {
|
|
handle_setup_win_keypress(KEY_RIGHT, interface);
|
|
return;
|
|
}
|
|
// General Options
|
|
if (interface->setup_win.selected_section == setup_general_selected) {
|
|
if (interface->setup_win.options_selected[0] == setup_general_color) {
|
|
interface->options.use_color = !interface->options.use_color;
|
|
}
|
|
if (interface->setup_win.options_selected[0] == setup_general_show_startup_support_messages) {
|
|
interface->options.show_startup_messages = !interface->options.show_startup_messages;
|
|
}
|
|
if (interface->setup_win.options_selected[0] == setup_general_update_interval) {
|
|
}
|
|
}
|
|
// Header Options
|
|
if (interface->setup_win.selected_section == setup_header_selected) {
|
|
if (interface->setup_win.indentation_level == 1) {
|
|
if (interface->setup_win.options_selected[0] == setup_header_toggle_fahrenheit) {
|
|
interface->options.temperature_in_fahrenheit = !interface->options.temperature_in_fahrenheit;
|
|
}
|
|
if (interface->setup_win.options_selected[0] == setup_header_enc_dec_timer) {
|
|
if (interface->options.encode_decode_hiding_timer > 0.) {
|
|
interface->options.encode_decode_hiding_timer = 0.;
|
|
} else {
|
|
interface->options.encode_decode_hiding_timer = 30.;
|
|
}
|
|
}
|
|
if (interface->setup_win.options_selected[0] == setup_header_gpu_info_bar) {
|
|
interface->options.has_gpu_info_bar = !interface->options.has_gpu_info_bar;
|
|
}
|
|
}
|
|
}
|
|
// Chart Options
|
|
if (interface->setup_win.selected_section == setup_chart_selected) {
|
|
if (interface->setup_win.indentation_level == 1) {
|
|
if (interface->setup_win.options_selected[0] == setup_chart_reverse) {
|
|
interface->options.plot_left_to_right = !interface->options.plot_left_to_right;
|
|
}
|
|
if (interface->setup_win.options_selected[0] >= setup_chart_all_gpu) {
|
|
handle_setup_win_keypress(KEY_RIGHT, interface);
|
|
}
|
|
} else if (interface->setup_win.indentation_level == 2) {
|
|
if (interface->setup_win.options_selected[0] == setup_chart_all_gpu) {
|
|
plot_info_to_draw draw_intersection = 0xffff;
|
|
for (unsigned j = 0; j < interface->monitored_dev_count; ++j) {
|
|
draw_intersection = draw_intersection & interface->options.gpu_specific_opts[j].to_draw;
|
|
}
|
|
if (plot_isset_draw_info(interface->setup_win.options_selected[1], draw_intersection)) {
|
|
for (unsigned i = 0; i < interface->monitored_dev_count; ++i) {
|
|
interface->options.gpu_specific_opts[i].to_draw = plot_remove_draw_info(
|
|
interface->setup_win.options_selected[1], interface->options.gpu_specific_opts[i].to_draw);
|
|
interface_ring_buffer_empty(&interface->saved_data_ring, i);
|
|
}
|
|
} else {
|
|
for (unsigned i = 0; i < interface->monitored_dev_count; ++i) {
|
|
interface->options.gpu_specific_opts[i].to_draw = plot_add_draw_info(
|
|
interface->setup_win.options_selected[1], interface->options.gpu_specific_opts[i].to_draw);
|
|
interface_ring_buffer_empty(&interface->saved_data_ring, i);
|
|
}
|
|
}
|
|
}
|
|
if (interface->setup_win.options_selected[0] > setup_chart_all_gpu) {
|
|
unsigned selected_gpu = interface->setup_win.options_selected[0] - setup_chart_start_gpu_list;
|
|
if (plot_isset_draw_info(interface->setup_win.options_selected[1],
|
|
interface->options.gpu_specific_opts[selected_gpu].to_draw))
|
|
interface->options.gpu_specific_opts[selected_gpu].to_draw = plot_remove_draw_info(
|
|
interface->setup_win.options_selected[1], interface->options.gpu_specific_opts[selected_gpu].to_draw);
|
|
else
|
|
interface->options.gpu_specific_opts[selected_gpu].to_draw = plot_add_draw_info(
|
|
interface->setup_win.options_selected[1], interface->options.gpu_specific_opts[selected_gpu].to_draw);
|
|
interface_ring_buffer_empty(&interface->saved_data_ring, selected_gpu);
|
|
}
|
|
}
|
|
}
|
|
// Process List Options
|
|
if (interface->setup_win.selected_section == setup_process_list_selected) {
|
|
if (interface->setup_win.indentation_level == 1) {
|
|
if (interface->setup_win.options_selected[0] == setup_proc_list_sort_ascending) {
|
|
interface->options.sort_descending_order = !interface->options.sort_descending_order;
|
|
} else if (interface->setup_win.options_selected[0] == setup_proc_list_hide_nvtop_process) {
|
|
interface->options.filter_nvtop_pid = !interface->options.filter_nvtop_pid;
|
|
} else if (interface->setup_win.options_selected[0] == setup_proc_list_hide_process_list) {
|
|
interface->options.hide_processes_list = !interface->options.hide_processes_list;
|
|
} else if (interface->setup_win.options_selected[0] == setup_proc_list_sort_by) {
|
|
handle_setup_win_keypress(KEY_RIGHT, interface);
|
|
}
|
|
} else if (interface->setup_win.indentation_level == 2) {
|
|
if (interface->setup_win.options_selected[0] == setup_proc_list_sort_by) {
|
|
unsigned index = 0;
|
|
for (enum process_field field = process_pid; field < process_field_count; ++field) {
|
|
if (process_is_field_displayed(field, interface->options.process_fields_displayed)) {
|
|
if (index == interface->setup_win.options_selected[1])
|
|
interface->options.sort_processes_by = field;
|
|
index++;
|
|
}
|
|
}
|
|
}
|
|
if (interface->setup_win.options_selected[0] == setup_proc_list_display) {
|
|
if (process_is_field_displayed(interface->setup_win.options_selected[1],
|
|
interface->options.process_fields_displayed)) {
|
|
interface->options.process_fields_displayed = process_remove_field_to_display(
|
|
interface->setup_win.options_selected[1], interface->options.process_fields_displayed);
|
|
} else {
|
|
interface->options.process_fields_displayed = process_add_field_to_display(
|
|
interface->setup_win.options_selected[1], interface->options.process_fields_displayed);
|
|
}
|
|
if (!process_is_field_displayed(interface->options.sort_processes_by,
|
|
interface->options.process_fields_displayed)) {
|
|
interface->options.sort_processes_by =
|
|
process_default_sort_by_from(interface->options.process_fields_displayed);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (interface->setup_win.selected_section == setup_monitored_gpu_list_selected) {
|
|
if (interface->setup_win.indentation_level == 1) {
|
|
interface->options.gpu_specific_opts[interface->setup_win.options_selected[0]].doNotMonitor =
|
|
!interface->options.gpu_specific_opts[interface->setup_win.options_selected[0]].doNotMonitor;
|
|
interface->options.has_monitored_set_changed = true;
|
|
}
|
|
}
|
|
break;
|
|
case KEY_F(2):
|
|
case 27:
|
|
interface->setup_win.visible = false;
|
|
update_window_size_to_terminal_size(interface);
|
|
break;
|
|
case KEY_F(12):
|
|
save_interface_options_to_config_file(interface->total_dev_count, &interface->options);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|