diff options
Diffstat (limited to 'src/load-graph.cpp')
-rw-r--r-- | src/load-graph.cpp | 1136 |
1 files changed, 568 insertions, 568 deletions
diff --git a/src/load-graph.cpp b/src/load-graph.cpp index 3a387d3..fd4afc1 100644 --- a/src/load-graph.cpp +++ b/src/load-graph.cpp @@ -31,175 +31,175 @@ void LoadGraph::clear_background() { - if (this->background) { + if (this->background) { #if GTK_CHECK_VERSION(3,0,0) - cairo_surface_destroy (this->background); + cairo_surface_destroy (this->background); #else - g_object_unref(this->background); + g_object_unref(this->background); #endif - this->background = NULL; - } + this->background = NULL; + } } unsigned LoadGraph::num_bars() const { - unsigned n; - - // keep 100 % num_bars == 0 - switch (static_cast<int>(this->draw_height / (this->fontsize + 14))) - { - case 0: - case 1: - n = 1; - break; - case 2: - case 3: - n = 2; - break; - case 4: - n = 4; - break; - default: - n = 5; - } - - return n; + unsigned n; + + // keep 100 % num_bars == 0 + switch (static_cast<int>(this->draw_height / (this->fontsize + 14))) + { + case 0: + case 1: + n = 1; + break; + case 2: + case 3: + n = 2; + break; + case 4: + n = 4; + break; + default: + n = 5; + } + + return n; } #define FRAME_WIDTH 4 static void draw_background(LoadGraph *g) { - GtkAllocation allocation; - double dash[2] = { 1.0, 2.0 }; - cairo_t *cr; - guint i; - unsigned num_bars; - char *caption; - cairo_text_extents_t extents; - - num_bars = g->num_bars(); - g->graph_dely = (g->draw_height - 15) / num_bars; /* round to int to avoid AA blur */ - g->real_draw_height = g->graph_dely * num_bars; - g->graph_delx = (g->draw_width - 2.0 - g->rmargin - g->indent) / (LoadGraph::NUM_POINTS - 3); - g->graph_buffer_offset = (int) (1.5 * g->graph_delx) + FRAME_WIDTH ; - - gtk_widget_get_allocation (g->disp, &allocation); + GtkAllocation allocation; + double dash[2] = { 1.0, 2.0 }; + cairo_t *cr; + guint i; + unsigned num_bars; + char *caption; + cairo_text_extents_t extents; + + num_bars = g->num_bars(); + g->graph_dely = (g->draw_height - 15) / num_bars; /* round to int to avoid AA blur */ + g->real_draw_height = g->graph_dely * num_bars; + g->graph_delx = (g->draw_width - 2.0 - g->rmargin - g->indent) / (LoadGraph::NUM_POINTS - 3); + g->graph_buffer_offset = (int) (1.5 * g->graph_delx) + FRAME_WIDTH ; + + gtk_widget_get_allocation (g->disp, &allocation); #if GTK_CHECK_VERSION(3,0,0) - g->background = gdk_window_create_similar_surface (gtk_widget_get_window (g->disp), CAIRO_CONTENT_COLOR_ALPHA, allocation.width, allocation.height); - cr = cairo_create (g->background); + g->background = gdk_window_create_similar_surface (gtk_widget_get_window (g->disp), CAIRO_CONTENT_COLOR_ALPHA, allocation.width, allocation.height); + cr = cairo_create (g->background); #else - g->background = gdk_pixmap_new (GDK_DRAWABLE (gtk_widget_get_window (g->disp)), allocation.width, allocation.height, -1); - cr = gdk_cairo_create (g->background); + g->background = gdk_pixmap_new (GDK_DRAWABLE (gtk_widget_get_window (g->disp)), allocation.width, allocation.height, -1); + cr = gdk_cairo_create (g->background); #endif - // set the background colour - GtkStyle *style = gtk_widget_get_style (ProcData::get_instance()->notebook); - gdk_cairo_set_source_color (cr, &style->bg[GTK_STATE_NORMAL]); - cairo_paint (cr); - - /* draw frame */ - cairo_translate (cr, FRAME_WIDTH, FRAME_WIDTH); - - /* Draw background rectangle */ - cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); - cairo_rectangle (cr, g->rmargin + g->indent, 0, - g->draw_width - g->rmargin - g->indent, g->real_draw_height); - cairo_fill(cr); - - cairo_set_line_width (cr, 1.0); - cairo_set_dash (cr, dash, 2, 0); - cairo_set_font_size (cr, g->fontsize); - - for (i = 0; i <= num_bars; ++i) { - double y; - - if (i == 0) - y = 0.5 + g->fontsize / 2.0; - else if (i == num_bars) - y = i * g->graph_dely + 0.5; - else - y = i * g->graph_dely + g->fontsize / 2.0; - - gdk_cairo_set_source_color (cr, &style->fg[GTK_STATE_NORMAL]); - if (g->type == LOAD_GRAPH_NET) { - // operation orders matters so it's 0 if i == num_bars - unsigned rate = g->net.max - (i * g->net.max / num_bars); - const std::string caption(procman::format_network_rate(rate, g->net.max)); - cairo_text_extents (cr, caption.c_str(), &extents); - cairo_move_to (cr, g->indent - extents.width + 20, y); - cairo_show_text (cr, caption.c_str()); - } else { - // operation orders matters so it's 0 if i == num_bars - caption = g_strdup_printf("%d %%", 100 - i * (100 / num_bars)); - cairo_text_extents (cr, caption, &extents); - cairo_move_to (cr, g->indent - extents.width + 20, y); - cairo_show_text (cr, caption); - g_free (caption); - } - - cairo_set_source_rgba (cr, 0, 0, 0, 0.75); - cairo_move_to (cr, g->rmargin + g->indent - 3, i * g->graph_dely + 0.5); - cairo_line_to (cr, g->draw_width - 0.5, i * g->graph_dely + 0.5); - } - cairo_stroke (cr); - - cairo_set_dash (cr, dash, 2, 1.5); - - const unsigned total_seconds = g->speed * (LoadGraph::NUM_POINTS - 2) / 1000; - - for (unsigned int i = 0; i < 7; i++) { - double x = (i) * (g->draw_width - g->rmargin - g->indent) / 6; - cairo_set_source_rgba (cr, 0, 0, 0, 0.75); - cairo_move_to (cr, (ceil(x) + 0.5) + g->rmargin + g->indent, 0.5); - cairo_line_to (cr, (ceil(x) + 0.5) + g->rmargin + g->indent, g->real_draw_height + 4.5); - cairo_stroke(cr); - unsigned seconds = total_seconds - i * total_seconds / 6; - const char* format; - if (i == 0) - format = dngettext(GETTEXT_PACKAGE, "%u second", "%u seconds", seconds); - else - format = "%u"; - caption = g_strdup_printf(format, seconds); - cairo_text_extents (cr, caption, &extents); - cairo_move_to (cr, ((ceil(x) + 0.5) + g->rmargin + g->indent) - (extents.width/2), g->draw_height); - gdk_cairo_set_source_color (cr, &style->fg[GTK_STATE_NORMAL]); - cairo_show_text (cr, caption); - g_free (caption); - } - - cairo_stroke (cr); - cairo_destroy (cr); + // set the background colour + GtkStyle *style = gtk_widget_get_style (ProcData::get_instance()->notebook); + gdk_cairo_set_source_color (cr, &style->bg[GTK_STATE_NORMAL]); + cairo_paint (cr); + + /* draw frame */ + cairo_translate (cr, FRAME_WIDTH, FRAME_WIDTH); + + /* Draw background rectangle */ + cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); + cairo_rectangle (cr, g->rmargin + g->indent, 0, + g->draw_width - g->rmargin - g->indent, g->real_draw_height); + cairo_fill(cr); + + cairo_set_line_width (cr, 1.0); + cairo_set_dash (cr, dash, 2, 0); + cairo_set_font_size (cr, g->fontsize); + + for (i = 0; i <= num_bars; ++i) { + double y; + + if (i == 0) + y = 0.5 + g->fontsize / 2.0; + else if (i == num_bars) + y = i * g->graph_dely + 0.5; + else + y = i * g->graph_dely + g->fontsize / 2.0; + + gdk_cairo_set_source_color (cr, &style->fg[GTK_STATE_NORMAL]); + if (g->type == LOAD_GRAPH_NET) { + // operation orders matters so it's 0 if i == num_bars + unsigned rate = g->net.max - (i * g->net.max / num_bars); + const std::string caption(procman::format_network_rate(rate, g->net.max)); + cairo_text_extents (cr, caption.c_str(), &extents); + cairo_move_to (cr, g->indent - extents.width + 20, y); + cairo_show_text (cr, caption.c_str()); + } else { + // operation orders matters so it's 0 if i == num_bars + caption = g_strdup_printf("%d %%", 100 - i * (100 / num_bars)); + cairo_text_extents (cr, caption, &extents); + cairo_move_to (cr, g->indent - extents.width + 20, y); + cairo_show_text (cr, caption); + g_free (caption); + } + + cairo_set_source_rgba (cr, 0, 0, 0, 0.75); + cairo_move_to (cr, g->rmargin + g->indent - 3, i * g->graph_dely + 0.5); + cairo_line_to (cr, g->draw_width - 0.5, i * g->graph_dely + 0.5); + } + cairo_stroke (cr); + + cairo_set_dash (cr, dash, 2, 1.5); + + const unsigned total_seconds = g->speed * (LoadGraph::NUM_POINTS - 2) / 1000; + + for (unsigned int i = 0; i < 7; i++) { + double x = (i) * (g->draw_width - g->rmargin - g->indent) / 6; + cairo_set_source_rgba (cr, 0, 0, 0, 0.75); + cairo_move_to (cr, (ceil(x) + 0.5) + g->rmargin + g->indent, 0.5); + cairo_line_to (cr, (ceil(x) + 0.5) + g->rmargin + g->indent, g->real_draw_height + 4.5); + cairo_stroke(cr); + unsigned seconds = total_seconds - i * total_seconds / 6; + const char* format; + if (i == 0) + format = dngettext(GETTEXT_PACKAGE, "%u second", "%u seconds", seconds); + else + format = "%u"; + caption = g_strdup_printf(format, seconds); + cairo_text_extents (cr, caption, &extents); + cairo_move_to (cr, ((ceil(x) + 0.5) + g->rmargin + g->indent) - (extents.width/2), g->draw_height); + gdk_cairo_set_source_color (cr, &style->fg[GTK_STATE_NORMAL]); + cairo_show_text (cr, caption); + g_free (caption); + } + + cairo_stroke (cr); + cairo_destroy (cr); } /* Redraws the backing buffer for the load graph and updates the window */ void load_graph_queue_draw (LoadGraph *g) { - /* repaint */ - gtk_widget_queue_draw (g->disp); + /* repaint */ + gtk_widget_queue_draw (g->disp); } static int load_graph_update (gpointer user_data); // predeclare load_graph_update so we can compile ;) static gboolean load_graph_configure (GtkWidget *widget, - GdkEventConfigure *event, - gpointer data_ptr) + GdkEventConfigure *event, + gpointer data_ptr) { - GtkAllocation allocation; - LoadGraph * const g = static_cast<LoadGraph*>(data_ptr); + GtkAllocation allocation; + LoadGraph * const g = static_cast<LoadGraph*>(data_ptr); - gtk_widget_get_allocation (widget, &allocation); - g->draw_width = allocation.width - 2 * FRAME_WIDTH; - g->draw_height = allocation.height - 2 * FRAME_WIDTH; + gtk_widget_get_allocation (widget, &allocation); + g->draw_width = allocation.width - 2 * FRAME_WIDTH; + g->draw_height = allocation.height - 2 * FRAME_WIDTH; - g->clear_background(); + g->clear_background(); - load_graph_queue_draw (g); + load_graph_queue_draw (g); - return TRUE; + return TRUE; } #if GTK_CHECK_VERSION(3,0,0) @@ -208,119 +208,119 @@ static gboolean load_graph_draw (GtkWidget *widget, cairo_t *context, gpointer d static gboolean load_graph_expose (GtkWidget *widget, GdkEventExpose *event, gpointer data_ptr) #endif { - LoadGraph * const g = static_cast<LoadGraph*>(data_ptr); - GtkAllocation allocation; - GdkWindow *window; + LoadGraph * const g = static_cast<LoadGraph*>(data_ptr); + GtkAllocation allocation; + GdkWindow *window; - guint i, j; - gdouble sample_width, x_offset; + guint i, j; + gdouble sample_width, x_offset; - window = gtk_widget_get_window (g->disp); - gtk_widget_get_allocation (g->disp, &allocation); + window = gtk_widget_get_window (g->disp); + gtk_widget_get_allocation (g->disp, &allocation); - if (g->background == NULL) { - draw_background(g); + if (g->background == NULL) { + draw_background(g); #if GTK_CHECK_VERSION(3,0,0) - cairo_pattern_t *pattern = cairo_pattern_create_for_surface (g->background); - gdk_window_set_background_pattern (window, pattern); - cairo_pattern_destroy (pattern); + cairo_pattern_t *pattern = cairo_pattern_create_for_surface (g->background); + gdk_window_set_background_pattern (window, pattern); + cairo_pattern_destroy (pattern); #else - gdk_window_set_back_pixmap (window, g->background, FALSE); + gdk_window_set_back_pixmap (window, g->background, FALSE); #endif - } - - /* Number of pixels wide for one graph point */ - sample_width = (float)(g->draw_width - g->rmargin - g->indent) / (float)LoadGraph::NUM_POINTS; - /* General offset */ - x_offset = g->draw_width - g->rmargin + (sample_width*2); - - /* Subframe offset */ - x_offset += g->rmargin - ((sample_width / g->frames_per_unit) * g->render_counter); - - /* draw the graph */ - cairo_t* cr; - - cr = gdk_cairo_create (window); - - cairo_set_line_width (cr, 1); - cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND); - cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND); - cairo_rectangle (cr, g->rmargin + g->indent + FRAME_WIDTH + 1, FRAME_WIDTH - 1, - g->draw_width - g->rmargin - g->indent - 1, g->real_draw_height + FRAME_WIDTH - 1); - cairo_clip(cr); - - for (j = 0; j < g->n; ++j) { - cairo_move_to (cr, x_offset, (1.0f - g->data[0][j]) * g->real_draw_height); - gdk_cairo_set_source_color (cr, &(g->colors [j])); - - for (i = 1; i < LoadGraph::NUM_POINTS; ++i) { - if (g->data[i][j] == -1.0f) - continue; - cairo_curve_to (cr, - x_offset - ((i - 0.5f) * g->graph_delx), - (1.0f - g->data[i-1][j]) * g->real_draw_height + 3.5f, - x_offset - ((i - 0.5f) * g->graph_delx), - (1.0f - g->data[i][j]) * g->real_draw_height + 3.5f, - x_offset - (i * g->graph_delx), - (1.0f - g->data[i][j]) * g->real_draw_height + 3.5f); - } - cairo_stroke (cr); - - } - - cairo_destroy (cr); - - return TRUE; + } + + /* Number of pixels wide for one graph point */ + sample_width = (float)(g->draw_width - g->rmargin - g->indent) / (float)LoadGraph::NUM_POINTS; + /* General offset */ + x_offset = g->draw_width - g->rmargin + (sample_width*2); + + /* Subframe offset */ + x_offset += g->rmargin - ((sample_width / g->frames_per_unit) * g->render_counter); + + /* draw the graph */ + cairo_t* cr; + + cr = gdk_cairo_create (window); + + cairo_set_line_width (cr, 1); + cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND); + cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND); + cairo_rectangle (cr, g->rmargin + g->indent + FRAME_WIDTH + 1, FRAME_WIDTH - 1, + g->draw_width - g->rmargin - g->indent - 1, g->real_draw_height + FRAME_WIDTH - 1); + cairo_clip(cr); + + for (j = 0; j < g->n; ++j) { + cairo_move_to (cr, x_offset, (1.0f - g->data[0][j]) * g->real_draw_height); + gdk_cairo_set_source_color (cr, &(g->colors [j])); + + for (i = 1; i < LoadGraph::NUM_POINTS; ++i) { + if (g->data[i][j] == -1.0f) + continue; + cairo_curve_to (cr, + x_offset - ((i - 0.5f) * g->graph_delx), + (1.0f - g->data[i-1][j]) * g->real_draw_height + 3.5f, + x_offset - ((i - 0.5f) * g->graph_delx), + (1.0f - g->data[i][j]) * g->real_draw_height + 3.5f, + x_offset - (i * g->graph_delx), + (1.0f - g->data[i][j]) * g->real_draw_height + 3.5f); + } + cairo_stroke (cr); + + } + + cairo_destroy (cr); + + return TRUE; } static void get_load (LoadGraph *g) { - guint i; - glibtop_cpu cpu; + guint i; + glibtop_cpu cpu; - glibtop_get_cpu (&cpu); + glibtop_get_cpu (&cpu); #undef NOW #undef LAST #define NOW (g->cpu.times[g->cpu.now]) #define LAST (g->cpu.times[g->cpu.now ^ 1]) - if (g->n == 1) { - NOW[0][CPU_TOTAL] = cpu.total; - NOW[0][CPU_USED] = cpu.user + cpu.nice + cpu.sys; - } else { - for (i = 0; i < g->n; i++) { - NOW[i][CPU_TOTAL] = cpu.xcpu_total[i]; - NOW[i][CPU_USED] = cpu.xcpu_user[i] + cpu.xcpu_nice[i] - + cpu.xcpu_sys[i]; - } - } - - // on the first call, LAST is 0 - // which means data is set to the average load since boot - // that value has no meaning, we just want all the - // graphs to be aligned, so the CPU graph needs to start - // immediately - - for (i = 0; i < g->n; i++) { - float load; - float total, used; - gchar *text; - - total = NOW[i][CPU_TOTAL] - LAST[i][CPU_TOTAL]; - used = NOW[i][CPU_USED] - LAST[i][CPU_USED]; - - load = used / MAX(total, 1.0f); - g->data[0][i] = load; - - /* Update label */ - text = g_strdup_printf("%.1f%%", load * 100.0f); - gtk_label_set_text(GTK_LABEL(g->labels.cpu[i]), text); - g_free(text); - } - - g->cpu.now ^= 1; + if (g->n == 1) { + NOW[0][CPU_TOTAL] = cpu.total; + NOW[0][CPU_USED] = cpu.user + cpu.nice + cpu.sys; + } else { + for (i = 0; i < g->n; i++) { + NOW[i][CPU_TOTAL] = cpu.xcpu_total[i]; + NOW[i][CPU_USED] = cpu.xcpu_user[i] + cpu.xcpu_nice[i] + + cpu.xcpu_sys[i]; + } + } + + // on the first call, LAST is 0 + // which means data is set to the average load since boot + // that value has no meaning, we just want all the + // graphs to be aligned, so the CPU graph needs to start + // immediately + + for (i = 0; i < g->n; i++) { + float load; + float total, used; + gchar *text; + + total = NOW[i][CPU_TOTAL] - LAST[i][CPU_TOTAL]; + used = NOW[i][CPU_USED] - LAST[i][CPU_USED]; + + load = used / MAX(total, 1.0f); + g->data[0][i] = load; + + /* Update label */ + text = g_strdup_printf("%.1f%%", load * 100.0f); + gtk_label_set_text(GTK_LABEL(g->labels.cpu[i]), text); + g_free(text); + } + + g->cpu.now ^= 1; #undef NOW #undef LAST @@ -330,225 +330,225 @@ get_load (LoadGraph *g) namespace { - void set_memory_label_and_picker(GtkLabel* label, GSMColorButton* picker, - guint64 used, guint64 total, double percent) - { - char* used_text; - char* total_text; - char* text; - - used_text = procman::format_size(used); - total_text = procman::format_size(total); - // xgettext: 540MiB (53 %) of 1.0 GiB - text = g_strdup_printf(_("%s (%.1f %%) of %s"), used_text, 100.0 * percent, total_text); - gtk_label_set_text(label, text); - g_free(used_text); - g_free(total_text); - g_free(text); - - if (picker) - gsm_color_button_set_fraction(picker, percent); - } + void set_memory_label_and_picker(GtkLabel* label, GSMColorButton* picker, + guint64 used, guint64 total, double percent) + { + char* used_text; + char* total_text; + char* text; + + used_text = procman::format_size(used); + total_text = procman::format_size(total); + // xgettext: 540MiB (53 %) of 1.0 GiB + text = g_strdup_printf(_("%s (%.1f %%) of %s"), used_text, 100.0 * percent, total_text); + gtk_label_set_text(label, text); + g_free(used_text); + g_free(total_text); + g_free(text); + + if (picker) + gsm_color_button_set_fraction(picker, percent); + } } static void get_memory (LoadGraph *g) { - float mempercent, swappercent; + float mempercent, swappercent; - glibtop_mem mem; - glibtop_swap swap; + glibtop_mem mem; + glibtop_swap swap; - glibtop_get_mem (&mem); - glibtop_get_swap (&swap); + glibtop_get_mem (&mem); + glibtop_get_swap (&swap); - /* There's no swap on LiveCD : 0.0f is better than NaN :) */ - swappercent = (swap.total ? (float)swap.used / (float)swap.total : 0.0f); - mempercent = (float)mem.user / (float)mem.total; + /* There's no swap on LiveCD : 0.0f is better than NaN :) */ + swappercent = (swap.total ? (float)swap.used / (float)swap.total : 0.0f); + mempercent = (float)mem.user / (float)mem.total; - set_memory_label_and_picker(GTK_LABEL(g->labels.memory), - GSM_COLOR_BUTTON(g->mem_color_picker), - mem.user, mem.total, mempercent); + set_memory_label_and_picker(GTK_LABEL(g->labels.memory), + GSM_COLOR_BUTTON(g->mem_color_picker), + mem.user, mem.total, mempercent); - set_memory_label_and_picker(GTK_LABEL(g->labels.swap), - GSM_COLOR_BUTTON(g->swap_color_picker), - swap.used, swap.total, swappercent); + set_memory_label_and_picker(GTK_LABEL(g->labels.swap), + GSM_COLOR_BUTTON(g->swap_color_picker), + swap.used, swap.total, swappercent); - g->data[0][0] = mempercent; - g->data[0][1] = swappercent; + g->data[0][0] = mempercent; + g->data[0][1] = swappercent; } static void net_scale (LoadGraph *g, guint64 din, guint64 dout) { - g->data[0][0] = 1.0f * din / g->net.max; - g->data[0][1] = 1.0f * dout / g->net.max; - - guint64 dmax = std::max(din, dout); - g->net.values[g->net.cur] = dmax; - g->net.cur = (g->net.cur + 1) % LoadGraph::NUM_POINTS; - - guint64 new_max; - // both way, new_max is the greatest value - if (dmax >= g->net.max) - new_max = dmax; - else - new_max = *std::max_element(&g->net.values[0], - &g->net.values[LoadGraph::NUM_POINTS]); - - // - // Round network maximum - // - - const guint64 bak_max(new_max); - - if (ProcData::get_instance()->config.network_in_bits) { - // TODO: fix logic to give a nice scale with bits - - // round up to get some extra space - // yes, it can overflow - new_max = 1.1 * new_max; - // make sure max is not 0 to avoid / 0 - // default to 125 bytes == 1kbit - new_max = std::max(new_max, G_GUINT64_CONSTANT(125)); - - } else { - // round up to get some extra space - // yes, it can overflow - new_max = 1.1 * new_max; - // make sure max is not 0 to avoid / 0 - // default to 1 KiB - new_max = std::max(new_max, G_GUINT64_CONSTANT(1024)); - - // decompose new_max = coef10 * 2**(base10 * 10) - // where coef10 and base10 are integers and coef10 < 2**10 - // - // e.g: ceil(100.5 KiB) = 101 KiB = 101 * 2**(1 * 10) - // where base10 = 1, coef10 = 101, pow2 = 16 - - guint64 pow2 = std::floor(log2(new_max)); - guint64 base10 = pow2 / 10.0; - guint64 coef10 = std::ceil(new_max / double(G_GUINT64_CONSTANT(1) << (base10 * 10))); - g_assert(new_max <= (coef10 * (G_GUINT64_CONSTANT(1) << (base10 * 10)))); - - // then decompose coef10 = x * 10**factor10 - // where factor10 is integer and x < 10 - // so we new_max has only 1 significant digit - - guint64 factor10 = std::pow(10.0, std::floor(std::log10(coef10))); - coef10 = std::ceil(coef10 / double(factor10)) * factor10; - - // then make coef10 divisible by num_bars - if (coef10 % g->num_bars() != 0) - coef10 = coef10 + (g->num_bars() - coef10 % g->num_bars()); - g_assert(coef10 % g->num_bars() == 0); - new_max = coef10 * (G_GUINT64_CONSTANT(1) << guint64(base10 * 10)); - procman_debug("bak %" G_GUINT64_FORMAT " new_max %" G_GUINT64_FORMAT - "pow2 %" G_GUINT64_FORMAT " coef10 %" G_GUINT64_FORMAT, - bak_max, new_max, pow2, coef10); - } - - if (bak_max > new_max) { - procman_debug("overflow detected: bak=%" G_GUINT64_FORMAT - " new=%" G_GUINT64_FORMAT, - bak_max, new_max); - new_max = bak_max; - } - - // if max is the same or has decreased but not so much, don't - // do anything to avoid rescaling - if ((0.8 * g->net.max) < new_max && new_max <= g->net.max) - return; - - const double scale = 1.0f * g->net.max / new_max; - - for (size_t i = 0; i < LoadGraph::NUM_POINTS; i++) { - if (g->data[i][0] >= 0.0f) { - g->data[i][0] *= scale; - g->data[i][1] *= scale; - } - } - - procman_debug("rescale dmax = %" G_GUINT64_FORMAT - " max = %" G_GUINT64_FORMAT - " new_max = %" G_GUINT64_FORMAT, - dmax, g->net.max, new_max); - - g->net.max = new_max; - - // force the graph background to be redrawn now that scale has changed - g->clear_background(); + g->data[0][0] = 1.0f * din / g->net.max; + g->data[0][1] = 1.0f * dout / g->net.max; + + guint64 dmax = std::max(din, dout); + g->net.values[g->net.cur] = dmax; + g->net.cur = (g->net.cur + 1) % LoadGraph::NUM_POINTS; + + guint64 new_max; + // both way, new_max is the greatest value + if (dmax >= g->net.max) + new_max = dmax; + else + new_max = *std::max_element(&g->net.values[0], + &g->net.values[LoadGraph::NUM_POINTS]); + + // + // Round network maximum + // + + const guint64 bak_max(new_max); + + if (ProcData::get_instance()->config.network_in_bits) { + // TODO: fix logic to give a nice scale with bits + + // round up to get some extra space + // yes, it can overflow + new_max = 1.1 * new_max; + // make sure max is not 0 to avoid / 0 + // default to 125 bytes == 1kbit + new_max = std::max(new_max, G_GUINT64_CONSTANT(125)); + + } else { + // round up to get some extra space + // yes, it can overflow + new_max = 1.1 * new_max; + // make sure max is not 0 to avoid / 0 + // default to 1 KiB + new_max = std::max(new_max, G_GUINT64_CONSTANT(1024)); + + // decompose new_max = coef10 * 2**(base10 * 10) + // where coef10 and base10 are integers and coef10 < 2**10 + // + // e.g: ceil(100.5 KiB) = 101 KiB = 101 * 2**(1 * 10) + // where base10 = 1, coef10 = 101, pow2 = 16 + + guint64 pow2 = std::floor(log2(new_max)); + guint64 base10 = pow2 / 10.0; + guint64 coef10 = std::ceil(new_max / double(G_GUINT64_CONSTANT(1) << (base10 * 10))); + g_assert(new_max <= (coef10 * (G_GUINT64_CONSTANT(1) << (base10 * 10)))); + + // then decompose coef10 = x * 10**factor10 + // where factor10 is integer and x < 10 + // so we new_max has only 1 significant digit + + guint64 factor10 = std::pow(10.0, std::floor(std::log10(coef10))); + coef10 = std::ceil(coef10 / double(factor10)) * factor10; + + // then make coef10 divisible by num_bars + if (coef10 % g->num_bars() != 0) + coef10 = coef10 + (g->num_bars() - coef10 % g->num_bars()); + g_assert(coef10 % g->num_bars() == 0); + new_max = coef10 * (G_GUINT64_CONSTANT(1) << guint64(base10 * 10)); + procman_debug("bak %" G_GUINT64_FORMAT " new_max %" G_GUINT64_FORMAT + "pow2 %" G_GUINT64_FORMAT " coef10 %" G_GUINT64_FORMAT, + bak_max, new_max, pow2, coef10); + } + + if (bak_max > new_max) { + procman_debug("overflow detected: bak=%" G_GUINT64_FORMAT + " new=%" G_GUINT64_FORMAT, + bak_max, new_max); + new_max = bak_max; + } + + // if max is the same or has decreased but not so much, don't + // do anything to avoid rescaling + if ((0.8 * g->net.max) < new_max && new_max <= g->net.max) + return; + + const double scale = 1.0f * g->net.max / new_max; + + for (size_t i = 0; i < LoadGraph::NUM_POINTS; i++) { + if (g->data[i][0] >= 0.0f) { + g->data[i][0] *= scale; + g->data[i][1] *= scale; + } + } + + procman_debug("rescale dmax = %" G_GUINT64_FORMAT + " max = %" G_GUINT64_FORMAT + " new_max = %" G_GUINT64_FORMAT, + dmax, g->net.max, new_max); + + g->net.max = new_max; + + // force the graph background to be redrawn now that scale has changed + g->clear_background(); } static void get_net (LoadGraph *g) { - glibtop_netlist netlist; - char **ifnames; - guint32 i; - guint64 in = 0, out = 0; - GTimeVal time; - guint64 din, dout; - - ifnames = glibtop_get_netlist(&netlist); - - for (i = 0; i < netlist.number; ++i) - { - glibtop_netload netload; - glibtop_get_netload (&netload, ifnames[i]); - - if (netload.if_flags & (1 << GLIBTOP_IF_FLAGS_LOOPBACK)) - continue; - - /* Skip interfaces without any IPv4/IPv6 address (or - those with only a LINK ipv6 addr) However we need to - be able to exclude these while still keeping the - value so when they get online (with NetworkManager - for example) we don't get a suddent peak. Once we're - able to get this, ignoring down interfaces will be - possible too. */ - if (not (netload.flags & (1 << GLIBTOP_NETLOAD_ADDRESS6) - and netload.scope6 != GLIBTOP_IF_IN6_SCOPE_LINK) - and not (netload.flags & (1 << GLIBTOP_NETLOAD_ADDRESS))) - continue; - - /* Don't skip interfaces that are down (GLIBTOP_IF_FLAGS_UP) - to avoid spikes when they are brought up */ - - in += netload.bytes_in; - out += netload.bytes_out; - } - - g_strfreev(ifnames); - - g_get_current_time (&time); - - if (in >= g->net.last_in && out >= g->net.last_out && - g->net.time.tv_sec != 0) { - float dtime; - dtime = time.tv_sec - g->net.time.tv_sec + - (double) (time.tv_usec - g->net.time.tv_usec) / G_USEC_PER_SEC; - din = static_cast<guint64>((in - g->net.last_in) / dtime); - dout = static_cast<guint64>((out - g->net.last_out) / dtime); - } else { - /* Don't calc anything if new data is less than old (interface - removed, counters reset, ...) or if it is the first time */ - din = 0; - dout = 0; - } - - g->net.last_in = in; - g->net.last_out = out; - g->net.time = time; - - net_scale(g, din, dout); - - - gtk_label_set_text (GTK_LABEL (g->labels.net_in), procman::format_network_rate(din).c_str()); - gtk_label_set_text (GTK_LABEL (g->labels.net_in_total), procman::format_network(in).c_str()); - - gtk_label_set_text (GTK_LABEL (g->labels.net_out), procman::format_network_rate(dout).c_str()); - gtk_label_set_text (GTK_LABEL (g->labels.net_out_total), procman::format_network(out).c_str()); + glibtop_netlist netlist; + char **ifnames; + guint32 i; + guint64 in = 0, out = 0; + GTimeVal time; + guint64 din, dout; + + ifnames = glibtop_get_netlist(&netlist); + + for (i = 0; i < netlist.number; ++i) + { + glibtop_netload netload; + glibtop_get_netload (&netload, ifnames[i]); + + if (netload.if_flags & (1 << GLIBTOP_IF_FLAGS_LOOPBACK)) + continue; + + /* Skip interfaces without any IPv4/IPv6 address (or + those with only a LINK ipv6 addr) However we need to + be able to exclude these while still keeping the + value so when they get online (with NetworkManager + for example) we don't get a suddent peak. Once we're + able to get this, ignoring down interfaces will be + possible too. */ + if (not (netload.flags & (1 << GLIBTOP_NETLOAD_ADDRESS6) + and netload.scope6 != GLIBTOP_IF_IN6_SCOPE_LINK) + and not (netload.flags & (1 << GLIBTOP_NETLOAD_ADDRESS))) + continue; + + /* Don't skip interfaces that are down (GLIBTOP_IF_FLAGS_UP) + to avoid spikes when they are brought up */ + + in += netload.bytes_in; + out += netload.bytes_out; + } + + g_strfreev(ifnames); + + g_get_current_time (&time); + + if (in >= g->net.last_in && out >= g->net.last_out && + g->net.time.tv_sec != 0) { + float dtime; + dtime = time.tv_sec - g->net.time.tv_sec + + (double) (time.tv_usec - g->net.time.tv_usec) / G_USEC_PER_SEC; + din = static_cast<guint64>((in - g->net.last_in) / dtime); + dout = static_cast<guint64>((out - g->net.last_out) / dtime); + } else { + /* Don't calc anything if new data is less than old (interface + removed, counters reset, ...) or if it is the first time */ + din = 0; + dout = 0; + } + + g->net.last_in = in; + g->net.last_out = out; + g->net.time = time; + + net_scale(g, din, dout); + + + gtk_label_set_text (GTK_LABEL (g->labels.net_in), procman::format_network_rate(din).c_str()); + gtk_label_set_text (GTK_LABEL (g->labels.net_in_total), procman::format_network(in).c_str()); + + gtk_label_set_text (GTK_LABEL (g->labels.net_out), procman::format_network_rate(dout).c_str()); + gtk_label_set_text (GTK_LABEL (g->labels.net_out_total), procman::format_network(out).c_str()); } @@ -556,35 +556,35 @@ get_net (LoadGraph *g) static gboolean load_graph_update (gpointer user_data) { - LoadGraph * const g = static_cast<LoadGraph*>(user_data); - - if (g->render_counter == g->frames_per_unit - 1) { - std::rotate(&g->data[0], &g->data[LoadGraph::NUM_POINTS - 1], &g->data[LoadGraph::NUM_POINTS]); - - switch (g->type) { - case LOAD_GRAPH_CPU: - get_load(g); - break; - case LOAD_GRAPH_MEM: - get_memory(g); - break; - case LOAD_GRAPH_NET: - get_net(g); - break; - default: - g_assert_not_reached(); - } - } - - if (g->draw) - load_graph_queue_draw (g); - - g->render_counter++; - - if (g->render_counter >= g->frames_per_unit) - g->render_counter = 0; - - return TRUE; + LoadGraph * const g = static_cast<LoadGraph*>(user_data); + + if (g->render_counter == g->frames_per_unit - 1) { + std::rotate(&g->data[0], &g->data[LoadGraph::NUM_POINTS - 1], &g->data[LoadGraph::NUM_POINTS]); + + switch (g->type) { + case LOAD_GRAPH_CPU: + get_load(g); + break; + case LOAD_GRAPH_MEM: + get_memory(g); + break; + case LOAD_GRAPH_NET: + get_net(g); + break; + default: + g_assert_not_reached(); + } + } + + if (g->draw) + load_graph_queue_draw (g); + + g->render_counter++; + + if (g->render_counter >= g->frames_per_unit) + g->render_counter = 0; + + return TRUE; } @@ -604,11 +604,11 @@ LoadGraph::~LoadGraph() static gboolean load_graph_destroy (GtkWidget *widget, gpointer data_ptr) { - LoadGraph * const g = static_cast<LoadGraph*>(data_ptr); + LoadGraph * const g = static_cast<LoadGraph*>(data_ptr); - delete g; + delete g; - return FALSE; + return FALSE; } @@ -635,165 +635,165 @@ LoadGraph::LoadGraph(guint type) mem_color_picker(NULL), swap_color_picker(NULL) { - LoadGraph * const g = this; - - // FIXME: - // on configure, g->frames_per_unit = g->draw_width/(LoadGraph::NUM_POINTS); - // knock FRAMES down to 5 until cairo gets faster - g->frames_per_unit = 10; // this will be changed but needs initialising - g->fontsize = 8.0; - g->rmargin = 3.5 * g->fontsize; - g->indent = 24.0; - - g->type = type; - switch (type) { - case LOAD_GRAPH_CPU: - memset(&this->cpu, 0, sizeof g->cpu); - g->n = ProcData::get_instance()->config.num_cpus; - - for(guint i = 0; i < G_N_ELEMENTS(g->labels.cpu); ++i) - g->labels.cpu[i] = gtk_label_new(NULL); - - break; - - case LOAD_GRAPH_MEM: - g->n = 2; - g->labels.memory = gtk_label_new(NULL); - g->labels.swap = gtk_label_new(NULL); - break; - - case LOAD_GRAPH_NET: - memset(&this->net, 0, sizeof g->net); - g->n = 2; - g->net.max = 1; - g->labels.net_in = gtk_label_new(NULL); - g->labels.net_in_total = gtk_label_new(NULL); - g->labels.net_out = gtk_label_new(NULL); - g->labels.net_out_total = gtk_label_new(NULL); - break; - } - - g->speed = ProcData::get_instance()->config.graph_update_interval; - - g->colors.resize(g->n); - - switch (type) { - case LOAD_GRAPH_CPU: - memcpy(&g->colors[0], ProcData::get_instance()->config.cpu_color, - g->n * sizeof g->colors[0]); - break; - case LOAD_GRAPH_MEM: - g->colors[0] = ProcData::get_instance()->config.mem_color; - g->colors[1] = ProcData::get_instance()->config.swap_color; - g->mem_color_picker = gsm_color_button_new (&g->colors[0], - GSMCP_TYPE_PIE); - g->swap_color_picker = gsm_color_button_new (&g->colors[1], - GSMCP_TYPE_PIE); - break; - case LOAD_GRAPH_NET: - g->colors[0] = ProcData::get_instance()->config.net_in_color; - g->colors[1] = ProcData::get_instance()->config.net_out_color; - break; - } - - g->timer_index = 0; - g->render_counter = (g->frames_per_unit - 1); - g->draw = FALSE; - - g->main_widget = gtk_vbox_new (FALSE, FALSE); - gtk_widget_set_size_request(g->main_widget, -1, LoadGraph::GRAPH_MIN_HEIGHT); - gtk_widget_show (g->main_widget); - - g->disp = gtk_drawing_area_new (); - gtk_widget_show (g->disp); + LoadGraph * const g = this; + + // FIXME: + // on configure, g->frames_per_unit = g->draw_width/(LoadGraph::NUM_POINTS); + // knock FRAMES down to 5 until cairo gets faster + g->frames_per_unit = 10; // this will be changed but needs initialising + g->fontsize = 8.0; + g->rmargin = 3.5 * g->fontsize; + g->indent = 24.0; + + g->type = type; + switch (type) { + case LOAD_GRAPH_CPU: + memset(&this->cpu, 0, sizeof g->cpu); + g->n = ProcData::get_instance()->config.num_cpus; + + for(guint i = 0; i < G_N_ELEMENTS(g->labels.cpu); ++i) + g->labels.cpu[i] = gtk_label_new(NULL); + + break; + + case LOAD_GRAPH_MEM: + g->n = 2; + g->labels.memory = gtk_label_new(NULL); + g->labels.swap = gtk_label_new(NULL); + break; + + case LOAD_GRAPH_NET: + memset(&this->net, 0, sizeof g->net); + g->n = 2; + g->net.max = 1; + g->labels.net_in = gtk_label_new(NULL); + g->labels.net_in_total = gtk_label_new(NULL); + g->labels.net_out = gtk_label_new(NULL); + g->labels.net_out_total = gtk_label_new(NULL); + break; + } + + g->speed = ProcData::get_instance()->config.graph_update_interval; + + g->colors.resize(g->n); + + switch (type) { + case LOAD_GRAPH_CPU: + memcpy(&g->colors[0], ProcData::get_instance()->config.cpu_color, + g->n * sizeof g->colors[0]); + break; + case LOAD_GRAPH_MEM: + g->colors[0] = ProcData::get_instance()->config.mem_color; + g->colors[1] = ProcData::get_instance()->config.swap_color; + g->mem_color_picker = gsm_color_button_new (&g->colors[0], + GSMCP_TYPE_PIE); + g->swap_color_picker = gsm_color_button_new (&g->colors[1], + GSMCP_TYPE_PIE); + break; + case LOAD_GRAPH_NET: + g->colors[0] = ProcData::get_instance()->config.net_in_color; + g->colors[1] = ProcData::get_instance()->config.net_out_color; + break; + } + + g->timer_index = 0; + g->render_counter = (g->frames_per_unit - 1); + g->draw = FALSE; + + g->main_widget = gtk_vbox_new (FALSE, FALSE); + gtk_widget_set_size_request(g->main_widget, -1, LoadGraph::GRAPH_MIN_HEIGHT); + gtk_widget_show (g->main_widget); + + g->disp = gtk_drawing_area_new (); + gtk_widget_show (g->disp); #if GTK_CHECK_VERSION(3,0,0) - g_signal_connect (G_OBJECT (g->disp), "draw", G_CALLBACK (load_graph_draw), g); + g_signal_connect (G_OBJECT (g->disp), "draw", G_CALLBACK (load_graph_draw), g); #else - g_signal_connect (G_OBJECT (g->disp), "expose_event", G_CALLBACK (load_graph_expose), g); + g_signal_connect (G_OBJECT (g->disp), "expose_event", G_CALLBACK (load_graph_expose), g); #endif - g_signal_connect (G_OBJECT(g->disp), "configure_event", - G_CALLBACK (load_graph_configure), g); - g_signal_connect (G_OBJECT(g->disp), "destroy", - G_CALLBACK (load_graph_destroy), g); + g_signal_connect (G_OBJECT(g->disp), "configure_event", + G_CALLBACK (load_graph_configure), g); + g_signal_connect (G_OBJECT(g->disp), "destroy", + G_CALLBACK (load_graph_destroy), g); - gtk_widget_set_events (g->disp, GDK_EXPOSURE_MASK); + gtk_widget_set_events (g->disp, GDK_EXPOSURE_MASK); - gtk_box_pack_start (GTK_BOX (g->main_widget), g->disp, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (g->main_widget), g->disp, TRUE, TRUE, 0); - /* Allocate data in a contiguous block */ - g->data_block = std::vector<float>(g->n * LoadGraph::NUM_POINTS, -1.0f); + /* Allocate data in a contiguous block */ + g->data_block = std::vector<float>(g->n * LoadGraph::NUM_POINTS, -1.0f); - for (guint i = 0; i < LoadGraph::NUM_POINTS; ++i) - g->data[i] = &g->data_block[0] + i * g->n; + for (guint i = 0; i < LoadGraph::NUM_POINTS; ++i) + g->data[i] = &g->data_block[0] + i * g->n; - gtk_widget_show_all (g->main_widget); + gtk_widget_show_all (g->main_widget); } void load_graph_start (LoadGraph *g) { - if(!g->timer_index) { + if(!g->timer_index) { - load_graph_update(g); + load_graph_update(g); - g->timer_index = g_timeout_add (g->speed / g->frames_per_unit, - load_graph_update, - g); - } + g->timer_index = g_timeout_add (g->speed / g->frames_per_unit, + load_graph_update, + g); + } - g->draw = TRUE; + g->draw = TRUE; } void load_graph_stop (LoadGraph *g) { - /* don't draw anymore, but continue to poll */ - g->draw = FALSE; + /* don't draw anymore, but continue to poll */ + g->draw = FALSE; } void load_graph_change_speed (LoadGraph *g, - guint new_speed) + guint new_speed) { - if (g->speed == new_speed) - return; + if (g->speed == new_speed) + return; - g->speed = new_speed; + g->speed = new_speed; - g_assert(g->timer_index); + g_assert(g->timer_index); - if(g->timer_index) { - g_source_remove (g->timer_index); - g->timer_index = g_timeout_add (g->speed / g->frames_per_unit, - load_graph_update, - g); - } + if(g->timer_index) { + g_source_remove (g->timer_index); + g->timer_index = g_timeout_add (g->speed / g->frames_per_unit, + load_graph_update, + g); + } - g->clear_background(); + g->clear_background(); } LoadGraphLabels* load_graph_get_labels (LoadGraph *g) { - return &g->labels; + return &g->labels; } GtkWidget* load_graph_get_widget (LoadGraph *g) { - return g->main_widget; + return g->main_widget; } GtkWidget* load_graph_get_mem_color_picker(LoadGraph *g) { - return g->mem_color_picker; + return g->mem_color_picker; } GtkWidget* load_graph_get_swap_color_picker(LoadGraph *g) { - return g->swap_color_picker; + return g->swap_color_picker; } |