Vkeybd: use ArdourWidgets for all GUI elements
[ardour.git] / gtk2_ardour / idleometer.cc
1 /*
2  * Copyright (C) 2017 Robin Gareus <robin@gareus.org>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17  */
18
19 #include <glib.h>
20 #include <gtkmm/button.h>
21 #include <gtkmm/table.h>
22
23 #ifdef PLATFORM_WINDOWS
24 #include <pbd/windows_timer_utils.h>
25 #endif
26
27 #include "temporal/time.h"
28
29 #include "idleometer.h"
30 #include "pbd/i18n.h"
31
32 static int64_t _x_get_monotonic_usec() {
33 #ifdef PLATFORM_WINDOWS
34         return PBD::get_microseconds();
35 #endif
36         return g_get_monotonic_time();
37 }
38
39 using namespace Gtk;
40
41 IdleOMeter::IdleOMeter ()
42         : ArdourDialog (_("Idle O Meter"))
43 {
44         get_vbox()->set_spacing (8);
45         Label* l = manage (new Label (_("<b>GUI Idle Timing Statistics</b>"), ALIGN_CENTER));
46         l->set_use_markup ();
47
48         HBox* hbox = manage (new HBox ());
49         Table* t = manage (new Table ());
50         hbox->pack_start (*t, true, false);
51
52         Button* b = manage (new Button (_("Reset")));
53         b->signal_clicked().connect (sigc::mem_fun(*this, &IdleOMeter::reset));
54
55         get_vbox()->pack_start (*l, false, false);
56         get_vbox()->pack_start (*hbox, false, false);
57         get_vbox()->pack_start (*b, false, false);
58
59         _label_cur.set_alignment (ALIGN_RIGHT, ALIGN_CENTER);
60         _label_min.set_alignment (ALIGN_RIGHT, ALIGN_CENTER);
61         _label_max.set_alignment (ALIGN_RIGHT, ALIGN_CENTER);
62         _label_avg.set_alignment (ALIGN_RIGHT, ALIGN_CENTER);
63         _label_dev.set_alignment (ALIGN_RIGHT, ALIGN_CENTER);
64         _label_acq.set_alignment (ALIGN_CENTER, ALIGN_CENTER);
65
66         int row = 0;
67         t->attach (*manage (new Label (_("Current:"), ALIGN_RIGHT)), 0, 1, row, row + 1, FILL, SHRINK);
68         t->attach (_label_cur, 1, 2, row, row + 1, FILL, SHRINK);
69         ++row;
70         t->attach (*manage (new Label (_("Min:"),     ALIGN_RIGHT)), 0, 1, row, row + 1, FILL, SHRINK);
71         t->attach (_label_min, 1, 2, row, row + 1, FILL, SHRINK);
72         ++row;
73         t->attach (*manage (new Label (_("Max:"),     ALIGN_RIGHT)), 0, 1, row, row + 1, FILL, SHRINK);
74         t->attach (_label_max, 1, 2, row, row + 1, FILL, SHRINK);
75         ++row;
76         t->attach (*manage (new Label (_("Mean:"),    ALIGN_RIGHT)), 0, 1, row, row + 1, FILL, SHRINK);
77         t->attach (_label_avg, 1, 2, row, row + 1, FILL, SHRINK);
78         ++row;
79         t->attach (*manage (new Label (_("\u03c3:"),  ALIGN_RIGHT)), 0, 1, row, row + 1, FILL, SHRINK);
80         t->attach (_label_dev, 1, 2, row, row + 1, FILL, SHRINK);
81         ++row;
82         t->attach (*manage (new Label (_("Elapsed:"),  ALIGN_RIGHT)), 0, 1, row, row + 1, FILL, SHRINK);
83         t->attach (_label_acq, 1, 2, row, row + 1, FILL, SHRINK);
84 }
85
86 IdleOMeter::~IdleOMeter ()
87 {
88         _idle_connection.disconnect ();
89 }
90
91 bool
92 IdleOMeter::idle ()
93 {
94         const int64_t now = _x_get_monotonic_usec ();
95         const int64_t elapsed = now - _last;
96
97         _max = std::max (_max, elapsed);
98         _min = std::min (_min, elapsed);
99         _last = now;
100         _total += elapsed;
101         ++_cnt;
102
103         const double cnt = _cnt;
104
105         /* running variance */
106         if (_cnt <= 1) {
107                 _var_m = elapsed;
108                 _var_s = 0;
109         } else {
110                 const double var_m1 = _var_m;
111                 const double t = elapsed;
112                 _var_m += (t - _var_m) / cnt;
113                 _var_s += (t - _var_m) * (t - var_m1);
114         }
115
116         if (now - _last_display < 100000 || _cnt < 2) {
117                 return true;
118         }
119
120         const double avg = _total / cnt;
121         const double stddev = sqrt (_var_s / (_cnt - 1.0));
122         _last_display = now;
123
124         char buf[128];
125
126         snprintf (buf, sizeof(buf), "%8.2f ms", elapsed / 1000.0);
127         _label_cur.set_text (buf);
128         snprintf (buf, sizeof(buf), "%8.2f ms", _min / 1000.0);
129         _label_min.set_text (buf);
130         snprintf (buf, sizeof(buf), "%8.2f ms", _max / 1000.0);
131         _label_max.set_text (buf);
132         snprintf (buf, sizeof(buf), "%8.3f ms", avg / 1000.0);
133         _label_avg.set_text (buf);
134         snprintf (buf, sizeof(buf), "%8.3f ms", stddev / 1000.0);
135         _label_dev.set_text (buf);
136         _label_acq.set_text (Timecode::timecode_format_sampletime (now - _start, 1000000, 100, false));
137
138         return true;
139 }
140
141 void
142 IdleOMeter::reset ()
143 {
144         _last = _x_get_monotonic_usec ();
145         _last_display = _last;
146         _start = _last;
147         _max = 0;
148         _min = INT64_MAX;
149         _cnt = 0;
150         _total = _var_m = _var_s = 0;
151
152         _label_cur.set_text ("-");
153         _label_min.set_text ("-");
154         _label_max.set_text ("-");
155         _label_avg.set_text ("-");
156         _label_dev.set_text ("-");
157         _label_acq.set_text ("-");
158 }
159
160 void
161 IdleOMeter::on_show ()
162 {
163         ArdourDialog::on_show ();
164         reset ();
165         _idle_connection = Glib::signal_idle().connect (sigc::mem_fun (*this, &IdleOMeter::idle));
166 }
167
168 void
169 IdleOMeter::on_hide ()
170 {
171         _idle_connection.disconnect ();
172         ArdourDialog::on_hide ();
173 }