meter/tempo bars show again, fix tempo/meter dialogs, and more
[ardour.git] / gtk2_ardour / tempo_dialog.cc
1 #include <cstdio> // for snprintf, grrr 
2
3 #include <gtkmm/stock.h>
4 #include <gtkmm2ext/utils.h>
5
6 #include "tempo_dialog.h"
7 #include "utils.h"
8
9 #include "i18n.h"
10
11 using namespace Gtk;
12 using namespace Gtkmm2ext;
13 using namespace ARDOUR;
14
15 TempoDialog::TempoDialog (TempoMap& map, jack_nframes_t frame, string action)
16         : ArdourDialog ("tempo dialog"),
17           bpm_frame (_("Beats per minute")),
18           ok_button (action),
19           cancel_button (_("Cancel")),
20           when_bar_label (_("Bar")),
21           when_beat_label (_("Beat")),
22           when_table (2, 2),
23           when_frame (_("Location"))
24 {
25         BBT_Time when;
26         Tempo tempo (map.tempo_at (frame));
27         map.bbt_time (frame, when);
28
29         init (when, tempo.beats_per_minute(), true);
30 }
31
32 TempoDialog::TempoDialog (TempoSection& section, string action)
33         : ArdourDialog ("tempo dialog"),
34           bpm_frame (_("Beats per minute")),
35           ok_button (action),
36           cancel_button (_("Cancel")),
37           when_bar_label (_("Bar")),
38           when_beat_label (_("Beat")),
39           when_table (2, 2),
40           when_frame (_("Location"))
41 {
42         init (section.start(), section.beats_per_minute(), section.movable());
43 }
44
45 void
46 TempoDialog::init (const BBT_Time& when, double bpm, bool movable)
47 {
48         snprintf (buf, sizeof (buf), "%.2f", bpm);
49         bpm_entry.set_text (buf);
50         bpm_entry.select_region (0, -1);
51         
52         hspacer1.set_border_width (5);
53         hspacer1.pack_start (bpm_entry, false, false);
54         vspacer1.set_border_width (5);
55         vspacer1.pack_start (hspacer1, false, false);
56
57         bpm_frame.add (vspacer1);
58
59         if (movable) {
60                 snprintf (buf, sizeof (buf), "%" PRIu32, when.bars);
61                 when_bar_entry.set_text (buf);
62                 snprintf (buf, sizeof (buf), "%" PRIu32, when.beats);
63                 when_beat_entry.set_text (buf);
64                 
65                 when_bar_entry.set_name ("MetricEntry");
66                 when_beat_entry.set_name ("MetricEntry");
67                 
68                 when_bar_label.set_name ("MetricLabel");
69                 when_beat_label.set_name ("MetricLabel");
70                 
71                 Gtkmm2ext::set_size_request_to_display_given_text (when_bar_entry, "999g", 5, 7);
72                 Gtkmm2ext::set_size_request_to_display_given_text (when_beat_entry, "999g", 5, 7);
73                 
74                 when_table.set_homogeneous (true);
75                 when_table.set_row_spacings (2);
76                 when_table.set_col_spacings (2);
77                 when_table.set_border_width (5);
78                 
79                 when_table.attach (when_bar_label, 0, 1, 0, 1, Gtk::AttachOptions(0), Gtk::FILL|Gtk::EXPAND);
80                 when_table.attach (when_bar_entry, 0, 1, 1, 2, Gtk::AttachOptions(0), Gtk::FILL|Gtk::EXPAND);
81                 
82                 when_table.attach (when_beat_label, 1, 2, 0, 1, Gtk::AttachOptions(0), Gtk::AttachOptions(0));
83                 when_table.attach (when_beat_entry, 1, 2, 1, 2, Gtk::AttachOptions(0), Gtk::AttachOptions(0));
84                 
85                 when_frame.set_name ("MetricDialogFrame");
86                 when_frame.add (when_table);
87
88                 get_vbox()->pack_start (when_frame, false, false);
89         }
90
91         bpm_frame.set_name ("MetricDialogFrame");
92         bpm_entry.set_name ("MetricEntry");
93
94         get_vbox()->pack_start (bpm_frame, false, false);
95         
96         add_button (Stock::OK, RESPONSE_ACCEPT);
97         add_button (Stock::CANCEL, RESPONSE_CANCEL);
98
99         get_vbox()->show_all();
100         bpm_entry.show();
101
102         set_name ("MetricDialog");
103 }
104
105 double 
106 TempoDialog::get_bpm ()
107 {
108         double bpm;
109         
110         if (sscanf (bpm_entry.get_text().c_str(), "%lf", &bpm) != 1) {
111                 return 0;
112         }
113
114         return bpm;
115 }       
116
117 bool
118 TempoDialog::get_bbt_time (BBT_Time& requested)
119 {
120         if (sscanf (when_bar_entry.get_text().c_str(), "%" PRIu32, &requested.bars) != 1) {
121                 return false;
122         }
123         
124         if (sscanf (when_beat_entry.get_text().c_str(), "%" PRIu32, &requested.beats) != 1) {
125                 return false;
126         }
127
128         return true;
129 }
130
131
132 MeterDialog::MeterDialog (TempoMap& map, jack_nframes_t frame, string action)
133         : ArdourDialog ("meter dialog"),
134           note_frame (_("Meter denominator")),
135           bpb_frame (_("Beats per bar")),
136           ok_button (action),
137           cancel_button (_("Cancel")),
138           when_bar_label (_("Bar")),
139           when_beat_label (_("Beat")),
140           when_frame (_("Location"))
141 {
142         BBT_Time when;
143         frame = map.round_to_bar(frame,0); 
144         Meter meter (map.meter_at(frame));
145
146         map.bbt_time (frame, when);
147         init (when, meter.beats_per_bar(), meter.note_divisor(), true);
148 }
149
150 MeterDialog::MeterDialog (MeterSection& section, string action)
151         : ArdourDialog ("meter dialog"),
152           note_frame (_("Meter denominator")),
153           bpb_frame (_("Beats per bar")),
154           ok_button (action),
155           cancel_button (_("Cancel")),
156           when_bar_label (_("Bar")),
157           when_beat_label (_("Beat")),
158           when_frame (_("Location"))
159 {
160         init (section.start(), section.beats_per_bar(), section.note_divisor(), section.movable());
161 }
162
163 void
164 MeterDialog::init (const BBT_Time& when, double bpb, double note_type, bool movable)
165 {
166         snprintf (buf, sizeof (buf), "%.2f", bpb);
167         bpb_entry.set_text (buf);
168         bpb_entry.select_region (0, -1);
169         Gtkmm2ext::set_size_request_to_display_given_text (bpb_entry, "999999g", 5, 5);
170
171         strings.push_back (_("whole (1)"));
172         strings.push_back (_("second (2)"));
173         strings.push_back (_("third (3)"));
174         strings.push_back (_("quarter (4)"));
175         strings.push_back (_("eighth (8)"));
176         strings.push_back (_("sixteenth (16)"));
177         strings.push_back (_("thirty-second (32)"));
178         
179         set_popdown_strings (note_types, strings);
180
181         if (note_type==1.0f)
182                 note_types.set_active_text (_("whole (1)"));
183         else if (note_type==2.0f)
184                 note_types.set_active_text (_("second (2)"));
185         else if (note_type==3.0f)
186                 note_types.set_active_text (_("third (3)"));
187         else if (note_type==4.0f)
188                 note_types.set_active_text (_("quarter (4)"));
189         else if (note_type==8.0f)
190                 note_types.set_active_text (_("eighth (8)"));
191         else if (note_type==16.0f)
192                 note_types.set_active_text (_("sixteenth (16)"));
193         else if (note_type==32.0f)
194                 note_types.set_active_text (_("thirty-second (32)"));
195         else
196                 note_types.set_active_text (_("quarter (4)"));
197                 
198         /* strings.back() just happens to be the longest one to display */
199         // GTK2FIX
200         // Gtkmm2ext::set_size_request_to_display_given_text (*(note_types.get_entry()), strings.back(), 7, 7);
201
202         hspacer1.set_border_width (5);
203         hspacer1.pack_start (note_types, false, false);
204         vspacer1.set_border_width (5);
205         vspacer1.pack_start (hspacer1, false, false);
206
207         hspacer2.set_border_width (5);
208         hspacer2.pack_start (bpb_entry, false, false);
209         vspacer2.set_border_width (5);
210         vspacer2.pack_start (hspacer2, false, false);
211
212         note_frame.add (vspacer1);
213         bpb_frame.add (vspacer2);
214
215         if (movable) {
216                 snprintf (buf, sizeof (buf), "%" PRIu32, when.bars);
217                 when_bar_entry.set_text (buf);
218                 snprintf (buf, sizeof (buf), "%" PRIu32, when.beats);
219                 when_beat_entry.set_text (buf);
220                 
221                 when_bar_entry.set_name ("MetricEntry");
222                 when_beat_entry.set_name ("MetricEntry");
223                 
224                 when_bar_label.set_name ("MetricLabel");
225                 when_beat_label.set_name ("MetricLabel");
226                 
227                 Gtkmm2ext::set_size_request_to_display_given_text (when_bar_entry, "999g", 5, 7);
228                 Gtkmm2ext::set_size_request_to_display_given_text (when_beat_entry, "999g", 5, 7);
229                 
230                 when_table.set_homogeneous (true);
231                 when_table.set_row_spacings (2);
232                 when_table.set_col_spacings (2);
233                 when_table.set_border_width (5);
234                 
235                 when_table.attach (when_bar_label, 0, 1, 0, 1, Gtk::AttachOptions(0), Gtk::FILL|Gtk::EXPAND);
236                 when_table.attach (when_bar_entry, 0, 1, 1, 2, Gtk::AttachOptions(0), Gtk::FILL|Gtk::EXPAND);
237                 
238                 when_table.attach (when_beat_label, 1, 2, 0, 1, Gtk::AttachOptions(0), Gtk::AttachOptions(0));
239                 when_table.attach (when_beat_entry, 1, 2, 1, 2, Gtk::AttachOptions(0), Gtk::AttachOptions(0));
240                 
241                 when_frame.set_name ("MetricDialogFrame");
242                 when_frame.add (when_table);
243                 
244                 get_vbox()->pack_start (when_frame, false, false);
245         }
246
247         get_vbox()->pack_start (bpb_frame, false, false);
248         get_vbox()->pack_start (note_frame, false, false);
249         
250         bpb_frame.set_name ("MetricDialogFrame");
251         note_frame.set_name ("MetricDialogFrame");
252         bpb_entry.set_name ("MetricEntry");
253
254         add_button (Stock::OK, RESPONSE_ACCEPT);
255         add_button (Stock::CANCEL, RESPONSE_CANCEL);
256
257         get_vbox()->show_all ();
258         bpb_entry.show ();
259
260         set_name ("MetricDialog");
261 }
262
263 double
264 MeterDialog::get_bpb ()
265 {
266         double bpb = 0;
267         
268         if (sscanf (bpb_entry.get_text().c_str(), "%lf", &bpb) != 1) {
269                 return 0;
270         }
271
272         return bpb;
273 }
274         
275 double
276 MeterDialog::get_note_type ()
277 {
278         double note_type = 0;
279         vector<string>::iterator i;
280         string text = note_types.get_active_text();
281         
282         for (i = strings.begin(); i != strings.end(); ++i) {
283                 if (text == *i) {
284                         if (sscanf (text.c_str(), "%*[^0-9]%lf", &note_type) != 1) {
285                                 error << string_compose(_("garbaged note type entry (%1)"), text) << endmsg;
286                                 return 0;
287                         } else {
288                                 break;
289                         }
290                 }
291         } 
292         
293         if (i == strings.end()) {
294                 if (sscanf (text.c_str(), "%lf", &note_type) != 1) {
295                         error << string_compose(_("incomprehensible note type entry (%1)"), text) << endmsg;
296                         return 0;
297                 }
298         }
299
300         return note_type;
301 }
302
303 bool
304 MeterDialog::get_bbt_time (BBT_Time& requested)
305 {
306         requested.ticks = 0;
307
308         if (sscanf (when_bar_entry.get_text().c_str(), "%" PRIu32, &requested.bars) != 1) {
309                 return false;
310         }
311         
312         if (sscanf (when_beat_entry.get_text().c_str(), "%" PRIu32, &requested.beats) != 1) {
313                 return false;
314         }
315
316         return true;
317 }