merge from 2.0-ongoing @ 3581
[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           ignored (new PBD::IgnorableControllable()),
45           /* max 1 second, step by frames, page by msecs */
46           adjustment (initial_value, 0.0, sample_rate, 1.0, sample_rate / 1000.0f),
47           bc (adjustment, ignored, sigc::mem_fun (*this, &LatencyGUI::latency_printer)),
48           reset_button (_("Automatic"))
49 {
50         Widget* w;
51
52         if (unit_strings.empty()) {
53                 unit_strings = I18N (_unit_strings);
54         }
55
56         set_popdown_strings (units_combo, unit_strings);        
57         units_combo.set_active_text (unit_strings.front());
58
59         w = manage (new Image (Stock::ADD, ICON_SIZE_BUTTON));
60         w->show ();
61         plus_button.add (*w);
62         w = manage (new Image (Stock::REMOVE, ICON_SIZE_BUTTON));
63         w->show ();
64         minus_button.add (*w);
65
66         hbox1.pack_start (bc, true, true);
67
68         hbox2.set_homogeneous (false);
69         hbox2.set_spacing (12);
70         hbox2.pack_start (reset_button);
71         hbox2.pack_start (minus_button);
72         hbox2.pack_start (plus_button);
73         hbox2.pack_start (units_combo, true, true);
74
75         minus_button.signal_clicked().connect (bind (mem_fun (*this, &LatencyGUI::change_latency_from_button), -1));
76         plus_button.signal_clicked().connect (bind (mem_fun (*this, &LatencyGUI::change_latency_from_button), 1));
77         reset_button.signal_clicked().connect (mem_fun (*this, &LatencyGUI::reset));
78
79         adjustment.signal_value_changed().connect (mem_fun (*this, &LatencyGUI::finish));
80
81         bc.set_size_request (-1, 25);
82         bc.set_style (BarController::LeftToRight);
83         bc.set_use_parent (true);
84         bc.set_name (X_("PluginSlider"));
85
86         set_spacing (12);
87         pack_start (hbox1, true, true);
88         pack_start (hbox2, true, true);
89 }
90
91 void
92 LatencyGUI::finish ()
93 {
94         nframes64_t new_value = (nframes64_t) adjustment.get_value();
95         if (new_value != initial_value) {
96                 _latent.set_user_latency (new_value);
97         }
98 }
99
100 void
101 LatencyGUI::reset ()
102 {
103         _latent.set_user_latency (0);
104         adjustment.set_value (initial_value);
105 }
106
107 void
108 LatencyGUI::refresh ()
109 {
110         initial_value = _latent.signal_latency();
111         adjustment.set_value (initial_value);
112 }
113
114 void
115 LatencyGUI::change_latency_from_button (int dir)
116 {
117         Glib::ustring unitstr = units_combo.get_active_text();
118         double shift = 0.0;
119
120         if (unitstr == unit_strings[0]) {
121                 shift = 1;
122         } else if (unitstr == unit_strings[1]) {
123                 shift = (sample_rate / 1000.0);
124         } else if (unitstr == unit_strings[2]) {
125                 shift = period_size;
126         } else {
127                 fatal << string_compose (_("programming error: %1 (%2)"), X_("illegal string in latency GUI units combo"), unitstr)
128                       << endmsg;
129                 /*NOTREACHED*/
130         }
131
132         if (dir > 0) {
133                 adjustment.set_value (adjustment.get_value() + shift);
134         } else {
135                 adjustment.set_value (adjustment.get_value() - shift);
136         }
137 }
138
139 LatencyDialog::LatencyDialog (const Glib::ustring& title, Latent& l, nframes64_t sr, nframes64_t psz)
140         : ArdourDialog (title, false, true),
141           lwidget (l, sr, psz)
142 {
143           
144         get_vbox()->pack_start (lwidget);
145         add_button (Stock::CANCEL, RESPONSE_CANCEL);
146         add_button (Stock::APPLY, RESPONSE_REJECT);
147         add_button (Stock::OK, RESPONSE_ACCEPT);
148
149         show_all ();
150         
151         while (true) {
152                 int ret = run ();
153
154                 switch (ret) {
155                 case RESPONSE_ACCEPT:
156                         return;
157                         break;
158
159                 case RESPONSE_REJECT:
160                         lwidget.finish ();
161                         break;
162                 default:
163                         return;
164                 }
165         }
166 }
167
168