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