2 Copyright (C) 2000-2007 Paul Davis
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.
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.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include <cstdio> // for snprintf, grrr
22 #include <gtkmm/stock.h>
23 #include <gtkmm2ext/utils.h>
25 #include "tempo_dialog.h"
32 using namespace Gtkmm2ext
;
33 using namespace ARDOUR
;
36 TempoDialog::TempoDialog (TempoMap
& map
, framepos_t frame
, const string
& action
)
37 : ArdourDialog (_("New Tempo")),
38 bpm_adjustment (60.0, 1.0, 999.9, 0.1, 1.0),
39 bpm_spinner (bpm_adjustment
),
41 cancel_button (_("Cancel")),
42 when_bar_label (_("bar:"), ALIGN_LEFT
, ALIGN_CENTER
),
43 when_beat_label (_("beat:"), ALIGN_LEFT
, ALIGN_CENTER
)
45 Timecode::BBT_Time when
;
46 Tempo
tempo (map
.tempo_at (frame
));
47 map
.bbt_time (frame
, when
);
49 init (when
, tempo
.beats_per_minute(), tempo
.note_type(), true);
52 TempoDialog::TempoDialog (TempoSection
& section
, const string
& action
)
53 : ArdourDialog ("Edit Tempo"),
54 bpm_adjustment (60.0, 1.0, 999.9, 0.1, 1.0),
55 bpm_spinner (bpm_adjustment
),
57 cancel_button (_("Cancel")),
58 when_bar_label (_("bar:"), ALIGN_LEFT
, ALIGN_CENTER
),
59 when_beat_label (_("beat:"), ALIGN_LEFT
, ALIGN_CENTER
)
61 init (section
.start(), section
.beats_per_minute(), section
.note_type(), section
.movable());
65 TempoDialog::init (const Timecode::BBT_Time
& when
, double bpm
, double note_type
, bool movable
)
67 bpm_spinner
.set_numeric (true);
68 bpm_spinner
.set_digits (2);
69 bpm_spinner
.set_wrap (true);
70 bpm_spinner
.set_value (bpm
);
72 strings
.push_back (_("whole (1)"));
73 strings
.push_back (_("second (2)"));
74 strings
.push_back (_("third (3)"));
75 strings
.push_back (_("quarter (4)"));
76 strings
.push_back (_("eighth (8)"));
77 strings
.push_back (_("sixteenth (16)"));
78 strings
.push_back (_("thirty-second (32)"));
80 set_popdown_strings (note_types
, strings
, true);
82 if (note_type
== 1.0f
) {
83 note_types
.set_active_text (_("whole (1)"));
84 } else if (note_type
== 2.0f
) {
85 note_types
.set_active_text (_("second (2)"));
86 } else if (note_type
== 3.0f
) {
87 note_types
.set_active_text (_("third (3)"));
88 } else if (note_type
== 4.0f
) {
89 note_types
.set_active_text (_("quarter (4)"));
90 } else if (note_type
== 8.0f
) {
91 note_types
.set_active_text (_("eighth (8)"));
92 } else if (note_type
== 16.0f
) {
93 note_types
.set_active_text (_("sixteenth (16)"));
94 } else if (note_type
== 32.0f
) {
95 note_types
.set_active_text (_("thirty-second (32)"));
97 note_types
.set_active_text (_("quarter (4)"));
100 Table
* table
= manage (new Table (3, 3));
101 table
->set_spacings (6);
103 Label
* bpm_label
= manage (new Label(_("Beats per minute:"), ALIGN_LEFT
, ALIGN_CENTER
));
104 table
->attach (*bpm_label
, 0, 2, 0, 1);
105 table
->attach (bpm_spinner
, 2, 3, 0, 1);
108 snprintf (buf
, sizeof (buf
), "%" PRIu32
, when
.bars
);
109 when_bar_entry
.set_text (buf
);
110 snprintf (buf
, sizeof (buf
), "%" PRIu32
, when
.beats
);
111 when_beat_entry
.set_text (buf
);
113 when_bar_entry
.set_name ("MetricEntry");
114 when_beat_entry
.set_name ("MetricEntry");
116 when_bar_label
.set_name ("MetricLabel");
117 when_beat_label
.set_name ("MetricLabel");
119 table
->attach (when_bar_label
, 1, 2, 2, 3);
120 table
->attach (when_bar_entry
, 2, 3, 2, 3);
122 table
->attach (when_beat_label
, 1, 2, 1, 2);
123 table
->attach (when_beat_entry
, 2, 3, 1, 2);
125 Label
* when_label
= manage (new Label(_("Tempo begins at"), ALIGN_LEFT
, ALIGN_CENTER
));
126 table
->attach (*when_label
, 0, 1, 1, 2);
129 get_vbox()->set_border_width (12);
130 get_vbox()->pack_end (*table
);
133 add_button (Stock::CANCEL
, RESPONSE_CANCEL
);
134 add_button (Stock::APPLY
, RESPONSE_ACCEPT
);
135 set_response_sensitive (RESPONSE_ACCEPT
, false);
136 set_default_response (RESPONSE_ACCEPT
);
140 set_name ("MetricDialog");
142 bpm_spinner
.signal_activate().connect (sigc::bind (sigc::mem_fun (*this, &TempoDialog::response
), RESPONSE_ACCEPT
));
143 bpm_spinner
.signal_button_press_event().connect (sigc::mem_fun (*this, &TempoDialog::bpm_button_press
), false);
144 bpm_spinner
.signal_button_release_event().connect (sigc::mem_fun (*this, &TempoDialog::bpm_button_release
), false);
145 bpm_spinner
.signal_changed().connect (sigc::mem_fun (*this, &TempoDialog::bpm_changed
));
146 when_bar_entry
.signal_activate().connect (sigc::bind (sigc::mem_fun (*this, &TempoDialog::response
), RESPONSE_ACCEPT
));
147 when_bar_entry
.signal_key_release_event().connect (sigc::mem_fun (*this, &TempoDialog::entry_key_release
), false);
148 when_beat_entry
.signal_activate().connect (sigc::bind (sigc::mem_fun (*this, &TempoDialog::response
), RESPONSE_ACCEPT
));
149 when_beat_entry
.signal_key_release_event().connect (sigc::mem_fun (*this, &TempoDialog::entry_key_release
), false);
150 note_types
.signal_changed().connect (sigc::mem_fun (*this, &TempoDialog::note_types_change
));
154 TempoDialog::bpm_changed ()
156 set_response_sensitive (RESPONSE_ACCEPT
, true);
160 TempoDialog::bpm_button_press (GdkEventButton
*)
166 TempoDialog::bpm_button_release (GdkEventButton
*)
168 /* the value has been modified, accept should work now */
170 set_response_sensitive (RESPONSE_ACCEPT
, true);
175 TempoDialog::entry_key_release (GdkEventKey
*)
177 if (when_beat_entry
.get_text() != "" && when_bar_entry
.get_text() != "") {
178 set_response_sensitive (RESPONSE_ACCEPT
, true);
180 set_response_sensitive (RESPONSE_ACCEPT
, false);
186 TempoDialog::get_bpm ()
188 return bpm_spinner
.get_value ();
192 TempoDialog::get_bbt_time (Timecode::BBT_Time
& requested
)
194 if (sscanf (when_bar_entry
.get_text().c_str(), "%" PRIu32
, &requested
.bars
) != 1) {
198 if (sscanf (when_beat_entry
.get_text().c_str(), "%" PRIu32
, &requested
.beats
) != 1) {
208 TempoDialog::get_note_type ()
210 double note_type
= 0;
211 vector
<string
>::iterator i
;
212 string text
= note_types
.get_active_text();
214 for (i
= strings
.begin(); i
!= strings
.end(); ++i
) {
216 if (sscanf (text
.c_str(), "%*[^0-9]%lf", ¬e_type
) != 1) {
217 error
<< string_compose(_("garbaged note type entry (%1)"), text
) << endmsg
;
225 if (i
== strings
.end()) {
226 if (sscanf (text
.c_str(), "%lf", ¬e_type
) != 1) {
227 error
<< string_compose(_("incomprehensible note type entry (%1)"), text
) << endmsg
;
236 TempoDialog::note_types_change ()
238 set_response_sensitive (RESPONSE_ACCEPT
, true);
242 MeterDialog::MeterDialog (TempoMap
& map
, framepos_t frame
, const string
& action
)
243 : ArdourDialog ("New Meter"),
245 cancel_button (_("Cancel"))
247 Timecode::BBT_Time when
;
248 frame
= map
.round_to_bar(frame
,0);
249 Meter
meter (map
.meter_at(frame
));
251 map
.bbt_time (frame
, when
);
252 init (when
, meter
.beats_per_bar(), meter
.note_divisor(), true);
255 MeterDialog::MeterDialog (MeterSection
& section
, const string
& action
)
256 : ArdourDialog ("Edit Meter"),
258 cancel_button (_("Cancel"))
260 init (section
.start(), section
.beats_per_bar(), section
.note_divisor(), section
.movable());
264 MeterDialog::init (const Timecode::BBT_Time
& when
, double bpb
, double note_type
, bool movable
)
266 snprintf (buf
, sizeof (buf
), "%.2f", bpb
);
267 bpb_entry
.set_text (buf
);
268 bpb_entry
.select_region (0, -1);
270 strings
.push_back (_("whole (1)"));
271 strings
.push_back (_("second (2)"));
272 strings
.push_back (_("third (3)"));
273 strings
.push_back (_("quarter (4)"));
274 strings
.push_back (_("eighth (8)"));
275 strings
.push_back (_("sixteenth (16)"));
276 strings
.push_back (_("thirty-second (32)"));
278 set_popdown_strings (note_types
, strings
, true);
280 if (note_type
== 1.0f
) {
281 note_types
.set_active_text (_("whole (1)"));
282 } else if (note_type
== 2.0f
) {
283 note_types
.set_active_text (_("second (2)"));
284 } else if (note_type
== 3.0f
) {
285 note_types
.set_active_text (_("third (3)"));
286 } else if (note_type
== 4.0f
) {
287 note_types
.set_active_text (_("quarter (4)"));
288 } else if (note_type
== 8.0f
) {
289 note_types
.set_active_text (_("eighth (8)"));
290 } else if (note_type
== 16.0f
) {
291 note_types
.set_active_text (_("sixteenth (16)"));
292 } else if (note_type
== 32.0f
) {
293 note_types
.set_active_text (_("thirty-second (32)"));
295 note_types
.set_active_text (_("quarter (4)"));
298 Label
* note_label
= manage (new Label (_("Note value:"), ALIGN_LEFT
, ALIGN_CENTER
));
299 Label
* bpb_label
= manage (new Label (_("Beats per bar:"), ALIGN_LEFT
, ALIGN_CENTER
));
300 Table
* table
= manage (new Table (3, 2));
301 table
->set_spacings (6);
303 table
->attach (*bpb_label
, 0, 1, 0, 1, FILL
|EXPAND
, FILL
|EXPAND
);
304 table
->attach (bpb_entry
, 1, 2, 0, 1, FILL
|EXPAND
, FILL
|EXPAND
);
305 table
->attach (*note_label
, 0, 1, 1, 2, FILL
|EXPAND
, FILL
|EXPAND
);
306 table
->attach (note_types
, 1, 2, 1, 2, FILL
|EXPAND
, SHRINK
);
309 snprintf (buf
, sizeof (buf
), "%" PRIu32
, when
.bars
);
310 when_bar_entry
.set_text (buf
);
311 when_bar_entry
.set_name ("MetricEntry");
313 Label
* when_label
= manage (new Label(_("Meter begins at bar:"), ALIGN_LEFT
, ALIGN_CENTER
));
315 table
->attach (*when_label
, 0, 1, 2, 3, FILL
| EXPAND
, FILL
| EXPAND
);
316 table
->attach (when_bar_entry
, 1, 2, 2, 3, FILL
| EXPAND
, FILL
| EXPAND
);
318 when_bar_entry
.set_text ("0");
321 get_vbox()->set_border_width (12);
322 get_vbox()->pack_start (*table
, false, false);
324 bpb_entry
.set_name ("MetricEntry");
326 add_button (Stock::CANCEL
, RESPONSE_CANCEL
);
327 add_button (Stock::APPLY
, RESPONSE_ACCEPT
);
328 set_response_sensitive (RESPONSE_ACCEPT
, false);
329 set_default_response (RESPONSE_ACCEPT
);
331 get_vbox()->show_all ();
333 set_name ("MetricDialog");
334 bpb_entry
.signal_activate().connect (sigc::bind (sigc::mem_fun (*this, &MeterDialog::response
), RESPONSE_ACCEPT
));
335 bpb_entry
.signal_key_press_event().connect (sigc::mem_fun (*this, &MeterDialog::entry_key_press
), false);
336 bpb_entry
.signal_key_release_event().connect (sigc::mem_fun (*this, &MeterDialog::entry_key_release
));
337 when_bar_entry
.signal_activate().connect (sigc::bind (sigc::mem_fun (*this, &MeterDialog::response
), RESPONSE_ACCEPT
));
338 when_bar_entry
.signal_key_press_event().connect (sigc::mem_fun (*this, &MeterDialog::entry_key_press
), false);
339 when_bar_entry
.signal_key_release_event().connect (sigc::mem_fun (*this, &MeterDialog::entry_key_release
));
341 note_types
.signal_changed().connect (sigc::mem_fun (*this, &MeterDialog::note_types_change
));
345 MeterDialog::entry_key_press (GdkEventKey
* ev
)
348 switch (ev
->keyval
) {
393 MeterDialog::entry_key_release (GdkEventKey
*)
395 if (when_bar_entry
.get_text() != "" && bpb_entry
.get_text() != "") {
396 set_response_sensitive (RESPONSE_ACCEPT
, true);
398 set_response_sensitive (RESPONSE_ACCEPT
, false);
404 MeterDialog::note_types_change ()
406 set_response_sensitive (RESPONSE_ACCEPT
, true);
410 MeterDialog::get_bpb ()
414 if (sscanf (bpb_entry
.get_text().c_str(), "%lf", &bpb
) != 1) {
422 MeterDialog::get_note_type ()
424 double note_type
= 0;
425 vector
<string
>::iterator i
;
426 string text
= note_types
.get_active_text();
428 for (i
= strings
.begin(); i
!= strings
.end(); ++i
) {
430 if (sscanf (text
.c_str(), "%*[^0-9]%lf", ¬e_type
) != 1) {
431 error
<< string_compose(_("garbaged note type entry (%1)"), text
) << endmsg
;
439 if (i
== strings
.end()) {
440 if (sscanf (text
.c_str(), "%lf", ¬e_type
) != 1) {
441 error
<< string_compose(_("incomprehensible note type entry (%1)"), text
) << endmsg
;
450 MeterDialog::get_bbt_time (Timecode::BBT_Time
& requested
)
452 if (sscanf (when_bar_entry
.get_text().c_str(), "%" PRIu32
, &requested
.bars
) != 1) {