Some small fixes to the latency GUI.
[ardour.git] / gtk2_ardour / latency_gui.cc
1 #define __STDC_FORMAT_MACROS 1
2 #include <inttypes.h>
3
4 #include <iomanip>
5 #include "ardour/latent.h"
6 #include <gtkmm2ext/utils.h>
7
8 #include "latency_gui.h"
9
10 #include "i18n.h"
11
12 using namespace PBD;
13 using namespace Gtk;
14 using namespace Gtkmm2ext;
15 using namespace sigc;
16 using namespace ARDOUR;
17
18
19 static const gchar *_unit_strings[] = {
20         N_("sample"),
21         N_("msec"),
22         N_("period"),
23         0
24 };
25
26 std::vector<std::string> LatencyGUI::unit_strings;
27
28 std::string
29 LatencyBarController::get_label (int&)
30 {
31         double const nframes = _latency_gui->adjustment.get_value();
32         std::stringstream s;
33
34         if (nframes < (_latency_gui->sample_rate / 1000.0)) {
35                 s << ((nframes64_t) rint (nframes)) << " samples";
36         } else {
37                 s << std::fixed << std::setprecision (2) << (nframes / (_latency_gui->sample_rate / 1000.0)) << " msecs";
38         }
39         
40         return s.str ();
41 }
42
43 LatencyGUI::LatencyGUI (Latent& l, nframes64_t sr, nframes64_t psz)
44         : _latent (l),
45           initial_value (_latent.signal_latency()),
46           sample_rate (sr),
47           period_size (psz),
48           ignored (new PBD::IgnorableControllable()),
49           /* max 1 second, step by frames, page by msecs */
50           adjustment (initial_value, 0.0, sample_rate, 1.0, sample_rate / 1000.0f),
51           bc (adjustment, this),
52           reset_button (_("Reset"))
53 {
54         Widget* w;
55
56         if (unit_strings.empty()) {
57                 unit_strings = I18N (_unit_strings);
58         }
59
60         set_popdown_strings (units_combo, unit_strings);        
61         units_combo.set_active_text (unit_strings.front());
62
63         w = manage (new Image (Stock::ADD, ICON_SIZE_BUTTON));
64         w->show ();
65         plus_button.add (*w);
66         w = manage (new Image (Stock::REMOVE, ICON_SIZE_BUTTON));
67         w->show ();
68         minus_button.add (*w);
69
70         hbox1.pack_start (bc, true, true);
71
72         hbox2.set_homogeneous (false);
73         hbox2.set_spacing (12);
74         hbox2.pack_start (reset_button);
75         hbox2.pack_start (minus_button);
76         hbox2.pack_start (plus_button);
77         hbox2.pack_start (units_combo, true, true);
78
79         minus_button.signal_clicked().connect (bind (mem_fun (*this, &LatencyGUI::change_latency_from_button), -1));
80         plus_button.signal_clicked().connect (bind (mem_fun (*this, &LatencyGUI::change_latency_from_button), 1));
81         reset_button.signal_clicked().connect (mem_fun (*this, &LatencyGUI::reset));
82
83         adjustment.signal_value_changed().connect (mem_fun (*this, &LatencyGUI::finish));
84
85         bc.set_size_request (-1, 25);
86         bc.set_style (BarController::LeftToRight);
87         bc.set_use_parent (true);
88         bc.set_name (X_("PluginSlider"));
89
90         set_spacing (12);
91         pack_start (hbox1, true, true);
92         pack_start (hbox2, true, true);
93 }
94
95 void
96 LatencyGUI::finish ()
97 {
98         nframes64_t new_value = (nframes64_t) adjustment.get_value();
99         if (new_value != initial_value) {
100                 _latent.set_user_latency (new_value);
101         }
102 }
103
104 void
105 LatencyGUI::reset ()
106 {
107         _latent.set_user_latency (0);
108         adjustment.set_value (initial_value);
109 }
110
111 void
112 LatencyGUI::refresh ()
113 {
114         initial_value = _latent.signal_latency();
115         adjustment.set_value (initial_value);
116 }
117
118 void
119 LatencyGUI::change_latency_from_button (int dir)
120 {
121         Glib::ustring unitstr = units_combo.get_active_text();
122         double shift = 0.0;
123
124         if (unitstr == unit_strings[0]) {
125                 shift = 1;
126         } else if (unitstr == unit_strings[1]) {
127                 shift = (sample_rate / 1000.0);
128         } else if (unitstr == unit_strings[2]) {
129                 shift = period_size;
130         } else {
131                 fatal << string_compose (_("programming error: %1 (%2)"), X_("illegal string in latency GUI units combo"), unitstr)
132                       << endmsg;
133                 /*NOTREACHED*/
134         }
135
136         if (dir > 0) {
137                 adjustment.set_value (adjustment.get_value() + shift);
138         } else {
139                 adjustment.set_value (adjustment.get_value() - shift);
140         }
141 }
142
143 LatencyDialog::LatencyDialog (const Glib::ustring& title, Latent& l, nframes64_t sr, nframes64_t psz)
144         : ArdourDialog (title, false, true),
145           lwidget (l, sr, psz)
146 {
147           
148         get_vbox()->pack_start (lwidget);
149         add_button (Stock::CANCEL, RESPONSE_CANCEL);
150         add_button (Stock::APPLY, RESPONSE_REJECT);
151         add_button (Stock::OK, RESPONSE_ACCEPT);
152
153         show_all ();
154         
155         while (true) {
156                 int ret = run ();
157
158                 switch (ret) {
159                 case RESPONSE_ACCEPT:
160                         return;
161                         break;
162
163                 case RESPONSE_REJECT:
164                         lwidget.finish ();
165                         break;
166                 default:
167                         return;
168                 }
169         }
170 }
171
172