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"
31 using namespace Gtkmm2ext
;
32 using namespace ARDOUR
;
35 TempoDialog::TempoDialog (TempoMap
& map
, nframes_t frame
, const string
& action
)
36 : ArdourDialog (_("edit tempo")),
37 bpm_adjustment (60.0, 1.0, 999.9, 0.1, 1.0, 1.0),
38 bpm_spinner (bpm_adjustment
),
39 bpm_frame (_("Tempo")),
41 cancel_button (_("Cancel")),
42 when_bar_label (_("Bar"), ALIGN_LEFT
, ALIGN_CENTER
),
43 when_beat_label (_("Beat"), ALIGN_LEFT
, ALIGN_CENTER
),
45 when_frame (_("Location"))
48 Tempo
tempo (map
.tempo_at (frame
));
49 map
.bbt_time (frame
, when
);
51 init (when
, tempo
.beats_per_minute(), tempo
.note_type(), true);
54 TempoDialog::TempoDialog (TempoSection
& section
, const string
& action
)
55 : ArdourDialog ("tempo dialog"),
56 bpm_adjustment (60.0, 1.0, 999.9, 0.1, 1.0, 1.0),
57 bpm_spinner (bpm_adjustment
),
58 bpm_frame (_("Tempo")),
60 cancel_button (_("Cancel")),
61 when_bar_label (_("Bar"), ALIGN_LEFT
, ALIGN_CENTER
),
62 when_beat_label (_("Beat"), ALIGN_LEFT
, ALIGN_CENTER
),
64 when_frame (_("Location"))
66 init (section
.start(), section
.beats_per_minute(), section
.note_type(), section
.movable());
70 TempoDialog::init (const BBT_Time
& when
, double bpm
, double note_type
, bool movable
)
72 bpm_spinner
.set_numeric (true);
73 bpm_spinner
.set_digits (2);
74 bpm_spinner
.set_wrap (true);
75 bpm_spinner
.set_value (bpm
);
77 strings
.push_back (_("whole (1)"));
78 strings
.push_back (_("second (2)"));
79 strings
.push_back (_("third (3)"));
80 strings
.push_back (_("quarter (4)"));
81 strings
.push_back (_("eighth (8)"));
82 strings
.push_back (_("sixteenth (16)"));
83 strings
.push_back (_("thirty-second (32)"));
85 set_popdown_strings (note_types
, strings
, true);
88 note_types
.set_active_text (_("whole (1)"));
89 else if (note_type
==2.0f
)
90 note_types
.set_active_text (_("second (2)"));
91 else if (note_type
==3.0f
)
92 note_types
.set_active_text (_("third (3)"));
93 else if (note_type
==4.0f
)
94 note_types
.set_active_text (_("quarter (4)"));
95 else if (note_type
==8.0f
)
96 note_types
.set_active_text (_("eighth (8)"));
97 else if (note_type
==16.0f
)
98 note_types
.set_active_text (_("sixteenth (16)"));
99 else if (note_type
==32.0f
)
100 note_types
.set_active_text (_("thirty-second (32)"));
102 note_types
.set_active_text (_("quarter (4)"));
104 Label
* bpm_label
= manage(new Label(_("Beats Per Minute:"), ALIGN_LEFT
, ALIGN_CENTER
));
106 hspacer1
.set_border_width (6);
107 hspacer1
.pack_end (bpm_spinner
, PACK_EXPAND_PADDING
);
108 hspacer1
.pack_start (*bpm_label
, PACK_EXPAND_PADDING
);
109 vspacer1
.set_border_width (6);
110 vspacer1
.pack_start (hspacer1
, PACK_EXPAND_PADDING
);
112 hspacer2
.set_border_width (6);
113 hspacer2
.pack_start (note_types
, PACK_EXPAND_PADDING
);
115 bpm_frame
.add (vspacer1
);
118 snprintf (buf
, sizeof (buf
), "%" PRIu32
, when
.bars
);
119 when_bar_entry
.set_text (buf
);
120 snprintf (buf
, sizeof (buf
), "%" PRIu32
, when
.beats
);
121 when_beat_entry
.set_text (buf
);
123 when_bar_entry
.set_name ("MetricEntry");
124 when_beat_entry
.set_name ("MetricEntry");
126 when_bar_label
.set_name ("MetricLabel");
127 when_beat_label
.set_name ("MetricLabel");
129 Gtkmm2ext::set_size_request_to_display_given_text (when_bar_entry
, "999g", 5, 7);
130 Gtkmm2ext::set_size_request_to_display_given_text (when_beat_entry
, "999g", 5, 7);
132 when_table
.set_homogeneous (true);
133 when_table
.set_row_spacings (2);
134 when_table
.set_col_spacings (2);
135 when_table
.set_border_width (0);
137 when_table
.attach (when_bar_label
, 0, 1, 0, 1, AttachOptions(0), FILL
|EXPAND
);
138 when_table
.attach (when_bar_entry
, 1, 2, 0, 1, AttachOptions(0), FILL
|EXPAND
);
140 when_table
.attach (when_beat_label
, 0, 1, 1, 2, AttachOptions(0), AttachOptions(0));
141 when_table
.attach (when_beat_entry
, 1, 2, 1, 2, AttachOptions(0), AttachOptions(0));
143 HBox
* when_hbox
= manage (new HBox());
144 Label
* when_label
= manage(new Label(_("Tempo Begins at:"), ALIGN_LEFT
, ALIGN_TOP
));
145 when_hbox
->pack_end(when_table
, PACK_EXPAND_PADDING
, 6);
146 when_hbox
->pack_start(*when_label
, PACK_EXPAND_PADDING
, 6);
148 when_frame
.set_name ("MetricDialogFrame");
149 when_frame
.add (*when_hbox
);
151 get_vbox()->pack_end (when_frame
, false, false);
152 when_frame
.show_all();
156 bpm_frame
.set_name ("MetricDialogFrame");
157 bpm_spinner
.set_name ("MetricEntry");
159 get_vbox()->set_border_width (12);
160 get_vbox()->pack_end (bpm_frame
, false, false);
162 add_button (Stock::CANCEL
, RESPONSE_CANCEL
);
163 add_button (Stock::APPLY
, RESPONSE_ACCEPT
);
164 set_response_sensitive (RESPONSE_ACCEPT
, false);
165 set_default_response (RESPONSE_ACCEPT
);
167 bpm_frame
.show_all ();
170 set_name ("MetricDialog");
172 bpm_spinner
.signal_activate().connect (bind (mem_fun (*this, &TempoDialog::response
), RESPONSE_ACCEPT
));
173 bpm_spinner
.signal_button_press_event().connect (mem_fun (*this, &TempoDialog::bpm_button_press
), false);
174 bpm_spinner
.signal_button_release_event().connect (mem_fun (*this, &TempoDialog::bpm_button_release
), false);
175 when_bar_entry
.signal_activate().connect (bind (mem_fun (*this, &TempoDialog::response
), RESPONSE_ACCEPT
));
176 when_bar_entry
.signal_key_release_event().connect (mem_fun (*this, &TempoDialog::entry_key_release
), false);
177 when_beat_entry
.signal_activate().connect (bind (mem_fun (*this, &TempoDialog::response
), RESPONSE_ACCEPT
));
178 when_beat_entry
.signal_key_release_event().connect (mem_fun (*this, &TempoDialog::entry_key_release
), false);
179 note_types
.signal_changed().connect (mem_fun (*this, &TempoDialog::note_types_change
));
183 TempoDialog::bpm_button_press (GdkEventButton
* ev
)
189 TempoDialog::bpm_button_release (GdkEventButton
* ev
)
191 /* the value has been modified, accept should work now */
193 set_response_sensitive (RESPONSE_ACCEPT
, true);
198 TempoDialog::entry_key_release (GdkEventKey
* ev
)
200 if (when_beat_entry
.get_text() != "" && when_bar_entry
.get_text() != "") {
201 set_response_sensitive (RESPONSE_ACCEPT
, true);
203 set_response_sensitive (RESPONSE_ACCEPT
, false);
209 TempoDialog::get_bpm ()
211 return bpm_spinner
.get_value ();
215 TempoDialog::get_bbt_time (BBT_Time
& requested
)
217 if (sscanf (when_bar_entry
.get_text().c_str(), "%" PRIu32
, &requested
.bars
) != 1) {
221 if (sscanf (when_beat_entry
.get_text().c_str(), "%" PRIu32
, &requested
.beats
) != 1) {
231 TempoDialog::get_note_type ()
233 double note_type
= 0;
234 vector
<string
>::iterator i
;
235 string text
= note_types
.get_active_text();
237 for (i
= strings
.begin(); i
!= strings
.end(); ++i
) {
239 if (sscanf (text
.c_str(), "%*[^0-9]%lf", ¬e_type
) != 1) {
240 error
<< string_compose(_("garbaged note type entry (%1)"), text
) << endmsg
;
248 if (i
== strings
.end()) {
249 if (sscanf (text
.c_str(), "%lf", ¬e_type
) != 1) {
250 error
<< string_compose(_("incomprehensible note type entry (%1)"), text
) << endmsg
;
259 TempoDialog::note_types_change ()
261 set_response_sensitive (RESPONSE_ACCEPT
, true);
265 MeterDialog::MeterDialog (TempoMap
& map
, nframes_t frame
, const string
& action
)
266 : ArdourDialog ("meter dialog"),
267 bpb_frame (_("Meter")),
269 cancel_button (_("Cancel")),
270 when_frame (_("Location"))
273 frame
= map
.round_to_bar(frame
,0);
274 Meter
meter (map
.meter_at(frame
));
276 map
.bbt_time (frame
, when
);
277 init (when
, meter
.beats_per_bar(), meter
.note_divisor(), true);
280 MeterDialog::MeterDialog (MeterSection
& section
, const string
& action
)
281 : ArdourDialog ("meter dialog"),
282 bpb_frame (_("Meter")),
284 cancel_button (_("Cancel")),
285 when_frame (_("Location"))
287 init (section
.start(), section
.beats_per_bar(), section
.note_divisor(), section
.movable());
291 MeterDialog::init (const BBT_Time
& when
, double bpb
, double note_type
, bool movable
)
293 snprintf (buf
, sizeof (buf
), "%.2f", bpb
);
294 bpb_entry
.set_text (buf
);
295 bpb_entry
.select_region (0, -1);
296 Gtkmm2ext::set_size_request_to_display_given_text (bpb_entry
, "999999g", 5, 5);
298 strings
.push_back (_("whole (1)"));
299 strings
.push_back (_("second (2)"));
300 strings
.push_back (_("third (3)"));
301 strings
.push_back (_("quarter (4)"));
302 strings
.push_back (_("eighth (8)"));
303 strings
.push_back (_("sixteenth (16)"));
304 strings
.push_back (_("thirty-second (32)"));
306 set_popdown_strings (note_types
, strings
, true);
309 note_types
.set_active_text (_("whole (1)"));
310 else if (note_type
==2.0f
)
311 note_types
.set_active_text (_("second (2)"));
312 else if (note_type
==3.0f
)
313 note_types
.set_active_text (_("third (3)"));
314 else if (note_type
==4.0f
)
315 note_types
.set_active_text (_("quarter (4)"));
316 else if (note_type
==8.0f
)
317 note_types
.set_active_text (_("eighth (8)"));
318 else if (note_type
==16.0f
)
319 note_types
.set_active_text (_("sixteenth (16)"));
320 else if (note_type
==32.0f
)
321 note_types
.set_active_text (_("thirty-second (32)"));
323 note_types
.set_active_text (_("quarter (4)"));
325 Label
* note_label
= manage(new Label(_("Note Value:"), ALIGN_LEFT
, ALIGN_CENTER
));
326 Label
* bpb_label
= manage(new Label(_("Beats Per Bar:"), ALIGN_LEFT
, ALIGN_CENTER
));
327 Table
* bpb_table
= manage (new Table(2, 2));
329 bpb_table
->attach (*bpb_label
, 0, 1, 0, 1, FILL
|EXPAND
, FILL
|EXPAND
, 6, 6);
330 bpb_table
->attach (bpb_entry
, 1, 2, 0, 1, FILL
|EXPAND
, FILL
|EXPAND
, 6, 6);
331 bpb_table
->attach (*note_label
, 0, 1, 1, 2, FILL
|EXPAND
, FILL
|EXPAND
, 6, 6);
332 bpb_table
->attach (note_types
, 1, 2, 1, 2, FILL
|EXPAND
, SHRINK
, 6, 6);
333 bpb_frame
.add (*bpb_table
);
336 snprintf (buf
, sizeof (buf
), "%" PRIu32
, when
.bars
);
337 when_bar_entry
.set_text (buf
);
339 when_bar_entry
.set_name ("MetricEntry");
341 Gtkmm2ext::set_size_request_to_display_given_text (when_bar_entry
, "999g", 5, 7);
343 HBox
* when_hbox
= manage (new HBox());
344 Label
* when_label
= manage(new Label(_("Meter Begins at Bar:"), ALIGN_LEFT
, ALIGN_TOP
));
345 when_hbox
->pack_end(when_bar_entry
, PACK_EXPAND_PADDING
, 6);
346 when_hbox
->pack_start(*when_label
, PACK_EXPAND_PADDING
, 6);
348 when_frame
.set_name ("MetricDialogFrame");
349 when_frame
.add (*when_hbox
);
351 get_vbox()->pack_end (when_frame
, false, false);
353 when_bar_entry
.set_text ("0");
356 get_vbox()->set_border_width (12);
357 get_vbox()->pack_start (bpb_frame
, false, false);
359 bpb_frame
.set_name ("MetricDialogFrame");
360 bpb_entry
.set_name ("MetricEntry");
362 add_button (Stock::CANCEL
, RESPONSE_CANCEL
);
363 add_button (Stock::APPLY
, RESPONSE_ACCEPT
);
364 set_response_sensitive (RESPONSE_ACCEPT
, false);
365 set_default_response (RESPONSE_ACCEPT
);
367 get_vbox()->show_all ();
369 set_name ("MetricDialog");
370 bpb_entry
.signal_activate().connect (bind (mem_fun (*this, &MeterDialog::response
), RESPONSE_ACCEPT
));
371 bpb_entry
.signal_key_press_event().connect (mem_fun (*this, &MeterDialog::entry_key_press
), false);
372 bpb_entry
.signal_key_release_event().connect (mem_fun (*this, &MeterDialog::entry_key_release
));
373 when_bar_entry
.signal_activate().connect (bind (mem_fun (*this, &MeterDialog::response
), RESPONSE_ACCEPT
));
374 when_bar_entry
.signal_key_press_event().connect (mem_fun (*this, &MeterDialog::entry_key_press
), false);
375 when_bar_entry
.signal_key_release_event().connect (mem_fun (*this, &MeterDialog::entry_key_release
));
377 note_types
.signal_changed().connect (mem_fun (*this, &MeterDialog::note_types_change
));
381 MeterDialog::entry_key_press (GdkEventKey
* ev
)
384 switch (ev
->keyval
) {
429 MeterDialog::entry_key_release (GdkEventKey
* ev
)
431 if (when_bar_entry
.get_text() != "" && bpb_entry
.get_text() != "") {
432 set_response_sensitive (RESPONSE_ACCEPT
, true);
434 set_response_sensitive (RESPONSE_ACCEPT
, false);
440 MeterDialog::note_types_change ()
442 set_response_sensitive (RESPONSE_ACCEPT
, true);
446 MeterDialog::get_bpb ()
450 if (sscanf (bpb_entry
.get_text().c_str(), "%lf", &bpb
) != 1) {
458 MeterDialog::get_note_type ()
460 double note_type
= 0;
461 vector
<string
>::iterator i
;
462 string text
= note_types
.get_active_text();
464 for (i
= strings
.begin(); i
!= strings
.end(); ++i
) {
466 if (sscanf (text
.c_str(), "%*[^0-9]%lf", ¬e_type
) != 1) {
467 error
<< string_compose(_("garbaged note type entry (%1)"), text
) << endmsg
;
475 if (i
== strings
.end()) {
476 if (sscanf (text
.c_str(), "%lf", ¬e_type
) != 1) {
477 error
<< string_compose(_("incomprehensible note type entry (%1)"), text
) << endmsg
;
486 MeterDialog::get_bbt_time (BBT_Time
& requested
)
489 if (sscanf (when_bar_entry
.get_text().c_str(), "%" PRIu32
, &requested
.bars
) != 1) {