2 Copyright (C) 1999 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.
21 #include <cstdio> // for sprintf
24 #include <pbd/convert.h>
26 #include <gtkmm2ext/utils.h>
28 #include <ardour/ardour.h>
29 #include <ardour/session.h>
30 #include <ardour/tempo.h>
31 #include <sigc++/bind.h>
33 #include "ardour_ui.h"
34 #include "audio_clock.h"
39 using namespace ARDOUR;
45 const uint32_t AudioClock::field_length[(int) AudioClock::AudioFrames+1] = {
47 2, /* SMPTE_Minutes */
48 2, /* SMPTE_Seconds */
59 AudioClock::AudioClock (const string& name, bool allow_edit, bool duration, bool with_tempo_and_meter)
60 : is_duration (duration),
61 editable (allow_edit),
76 audio_frames_ebox.add (audio_frames_label);
77 frames_packer_hbox.set_border_width (2);
78 frames_packer_hbox.pack_start (audio_frames_ebox, false, false);
80 hours_ebox.add (hours_label);
81 minutes_ebox.add (minutes_label);
82 seconds_ebox.add (seconds_label);
83 frames_ebox.add (frames_label);
84 bars_ebox.add (bars_label);
85 beats_ebox.add (beats_label);
86 ticks_ebox.add (ticks_label);
87 ms_hours_ebox.add (ms_hours_label);
88 ms_minutes_ebox.add (ms_minutes_label);
89 ms_seconds_ebox.add (ms_seconds_label);
91 smpte_packer.set_homogeneous (false);
92 smpte_packer.set_border_width (2);
93 smpte_packer.pack_start (hours_ebox, false, false);
94 smpte_packer.pack_start (colon1, false, false);
95 smpte_packer.pack_start (minutes_ebox, false, false);
96 smpte_packer.pack_start (colon2, false, false);
97 smpte_packer.pack_start (seconds_ebox, false, false);
98 smpte_packer.pack_start (colon3, false, false);
99 smpte_packer.pack_start (frames_ebox, false, false);
101 smpte_packer_hbox.pack_start (smpte_packer, true, false);
103 bbt_packer.set_homogeneous (false);
104 bbt_packer.set_border_width (2);
105 bbt_packer.pack_start (bars_ebox, false, false);
106 bbt_packer.pack_start (b1, false, false);
107 bbt_packer.pack_start (beats_ebox, false, false);
108 bbt_packer.pack_start (b2, false, false);
109 bbt_packer.pack_start (ticks_ebox, false, false);
111 if (with_tempo_and_meter) {
112 meter_label = manage (new Label);
113 tempo_label = manage (new Label);
115 meter_label->set_name ("BBTMeterLabel");
116 tempo_label->set_name ("BBTTempoLabel");
118 tempo_meter_box.pack_start (*meter_label, true, true);
119 tempo_meter_box.pack_start (*tempo_label, true, true);
121 bbt_packer.pack_start (tempo_meter_box, false, false, 5);
127 bbt_packer_hbox.pack_start (bbt_packer, true, false);
129 minsec_packer.set_homogeneous (false);
130 minsec_packer.set_border_width (2);
131 minsec_packer.pack_start (ms_hours_ebox, false, false);
132 minsec_packer.pack_start (colon4, false, false);
133 minsec_packer.pack_start (ms_minutes_ebox, false, false);
134 minsec_packer.pack_start (colon5, false, false);
135 minsec_packer.pack_start (ms_seconds_ebox, false, false);
137 minsec_packer_hbox.pack_start (minsec_packer, true, false);
140 clock_base.set_name (name);
142 audio_frames_label.set_name (name);
143 hours_label.set_name (name);
144 minutes_label.set_name (name);
145 seconds_label.set_name (name);
146 frames_label.set_name (name);
147 bars_label.set_name (name);
148 beats_label.set_name (name);
149 ticks_label.set_name (name);
150 ms_hours_label.set_name (name);
151 ms_minutes_label.set_name (name);
152 ms_seconds_label.set_name (name);
153 hours_ebox.set_name (name);
154 minutes_ebox.set_name (name);
155 seconds_ebox.set_name (name);
156 frames_ebox.set_name (name);
157 audio_frames_ebox.set_name (name);
158 bars_ebox.set_name (name);
159 beats_ebox.set_name (name);
160 ticks_ebox.set_name (name);
161 ms_hours_ebox.set_name (name);
162 ms_minutes_ebox.set_name (name);
163 ms_seconds_ebox.set_name (name);
165 colon1.set_name (name);
166 colon2.set_name (name);
167 colon3.set_name (name);
168 colon4.set_name (name);
169 colon5.set_name (name);
173 clock_frame.set_shadow_type (Gtk::SHADOW_IN);
174 clock_frame.set_name ("BaseFrame");
176 clock_frame.add (clock_base);
178 _mode = BBT; /* lie to force mode switch */
181 pack_start (clock_frame, true, true);
183 /* the clock base handles button releases for menu popup regardless of
184 editable status. if the clock is editable, the clock base is where
185 we pass focus to after leaving the last editable "field", which
186 will then shutdown editing till the user starts it up again.
188 it does this because the focus out event on the field disables
189 keyboard event handling, and we don't connect anything up to
190 notice focus in on the clock base. hence, keyboard event handling
194 clock_base.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::SCROLL_MASK);
195 clock_base.signal_button_release_event().connect (bind (mem_fun (*this, &AudioClock::field_button_release_event), SMPTE_Hours));
201 set (last_when, true);
205 AudioClock::setup_events ()
207 clock_base.set_flags (Gtk::CAN_FOCUS);
209 hours_ebox.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK|Gdk::FOCUS_CHANGE_MASK|Gdk::POINTER_MOTION_MASK|Gdk::SCROLL_MASK);
210 minutes_ebox.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK|Gdk::FOCUS_CHANGE_MASK|Gdk::POINTER_MOTION_MASK|Gdk::SCROLL_MASK);
211 seconds_ebox.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK|Gdk::FOCUS_CHANGE_MASK|Gdk::POINTER_MOTION_MASK|Gdk::SCROLL_MASK);
212 frames_ebox.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK|Gdk::FOCUS_CHANGE_MASK|Gdk::POINTER_MOTION_MASK|Gdk::SCROLL_MASK);
213 bars_ebox.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK|Gdk::FOCUS_CHANGE_MASK|Gdk::POINTER_MOTION_MASK|Gdk::SCROLL_MASK);
214 beats_ebox.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK|Gdk::FOCUS_CHANGE_MASK|Gdk::POINTER_MOTION_MASK|Gdk::SCROLL_MASK);
215 ticks_ebox.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK|Gdk::FOCUS_CHANGE_MASK|Gdk::POINTER_MOTION_MASK|Gdk::SCROLL_MASK);
216 ms_hours_ebox.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK|Gdk::FOCUS_CHANGE_MASK|Gdk::POINTER_MOTION_MASK|Gdk::SCROLL_MASK);
217 ms_minutes_ebox.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK|Gdk::FOCUS_CHANGE_MASK|Gdk::POINTER_MOTION_MASK|Gdk::SCROLL_MASK);
218 ms_seconds_ebox.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK|Gdk::FOCUS_CHANGE_MASK|Gdk::POINTER_MOTION_MASK|Gdk::SCROLL_MASK);
219 audio_frames_ebox.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK|Gdk::FOCUS_CHANGE_MASK|Gdk::POINTER_MOTION_MASK|Gdk::SCROLL_MASK);
221 hours_ebox.set_flags (Gtk::CAN_FOCUS);
222 minutes_ebox.set_flags (Gtk::CAN_FOCUS);
223 seconds_ebox.set_flags (Gtk::CAN_FOCUS);
224 frames_ebox.set_flags (Gtk::CAN_FOCUS);
225 audio_frames_ebox.set_flags (Gtk::CAN_FOCUS);
226 bars_ebox.set_flags (Gtk::CAN_FOCUS);
227 beats_ebox.set_flags (Gtk::CAN_FOCUS);
228 ticks_ebox.set_flags (Gtk::CAN_FOCUS);
229 ms_hours_ebox.set_flags (Gtk::CAN_FOCUS);
230 ms_minutes_ebox.set_flags (Gtk::CAN_FOCUS);
231 ms_seconds_ebox.set_flags (Gtk::CAN_FOCUS);
233 hours_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), SMPTE_Hours));
234 minutes_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), SMPTE_Minutes));
235 seconds_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), SMPTE_Seconds));
236 frames_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), SMPTE_Frames));
237 audio_frames_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), AudioFrames));
238 bars_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), Bars));
239 beats_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), Beats));
240 ticks_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), Ticks));
241 ms_hours_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), MS_Hours));
242 ms_minutes_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), MS_Minutes));
243 ms_seconds_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), MS_Seconds));
245 hours_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), SMPTE_Hours));
246 minutes_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), SMPTE_Minutes));
247 seconds_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), SMPTE_Seconds));
248 frames_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), SMPTE_Frames));
249 audio_frames_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), AudioFrames));
250 bars_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), Bars));
251 beats_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), Beats));
252 ticks_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), Ticks));
253 ms_hours_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), MS_Hours));
254 ms_minutes_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), MS_Minutes));
255 ms_seconds_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), MS_Seconds));
257 hours_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), SMPTE_Hours));
258 minutes_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), SMPTE_Minutes));
259 seconds_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), SMPTE_Seconds));
260 frames_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), SMPTE_Frames));
261 audio_frames_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), AudioFrames));
262 bars_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), Bars));
263 beats_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), Beats));
264 ticks_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), Ticks));
265 ms_hours_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), MS_Hours));
266 ms_minutes_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), MS_Minutes));
267 ms_seconds_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), MS_Seconds));
269 hours_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), SMPTE_Hours));
270 minutes_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), SMPTE_Minutes));
271 seconds_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), SMPTE_Seconds));
272 frames_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), SMPTE_Frames));
273 audio_frames_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), AudioFrames));
274 bars_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), Bars));
275 beats_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), Beats));
276 ticks_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), Ticks));
277 ms_hours_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), MS_Hours));
278 ms_minutes_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), MS_Minutes));
279 ms_seconds_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), MS_Seconds));
281 hours_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), SMPTE_Hours));
282 minutes_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), SMPTE_Minutes));
283 seconds_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), SMPTE_Seconds));
284 frames_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), SMPTE_Frames));
285 audio_frames_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), AudioFrames));
286 bars_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), Bars));
287 beats_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), Beats));
288 ticks_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), Ticks));
289 ms_hours_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), MS_Hours));
290 ms_minutes_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), MS_Minutes));
291 ms_seconds_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), MS_Seconds));
293 hours_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), SMPTE_Hours));
294 minutes_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), SMPTE_Minutes));
295 seconds_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), SMPTE_Seconds));
296 frames_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), SMPTE_Frames));
297 audio_frames_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), AudioFrames));
298 bars_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), Bars));
299 beats_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), Beats));
300 ticks_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), Ticks));
301 ms_hours_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), MS_Hours));
302 ms_minutes_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), MS_Minutes));
303 ms_seconds_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), MS_Seconds));
305 hours_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), SMPTE_Hours));
306 minutes_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), SMPTE_Minutes));
307 seconds_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), SMPTE_Seconds));
308 frames_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), SMPTE_Frames));
309 audio_frames_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), AudioFrames));
310 bars_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), Bars));
311 beats_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), Beats));
312 ticks_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), Ticks));
313 ms_hours_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), MS_Hours));
314 ms_minutes_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), MS_Minutes));
315 ms_seconds_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), MS_Seconds));
319 AudioClock::on_realize ()
323 /* styles are not available until the widgets are bound to a window */
327 Gtkmm2ext::set_size_request_to_display_given_text (hours_label, "-88", 0, 2);
328 Gtkmm2ext::set_size_request_to_display_given_text (minutes_label, "88", 0, 2);
329 Gtkmm2ext::set_size_request_to_display_given_text (seconds_label, "88", 0, 2);
330 Gtkmm2ext::set_size_request_to_display_given_text (frames_label, "88", 0, 2);
334 Gtkmm2ext::set_size_request_to_display_given_text (bars_label, "-888", 0, 2);
335 Gtkmm2ext::set_size_request_to_display_given_text (beats_label, "88", 0, 2);
336 Gtkmm2ext::set_size_request_to_display_given_text (ticks_label, "8888", 0, 2);
340 Gtkmm2ext::set_size_request_to_display_given_text (ms_hours_label, "99", 0, 2);
341 Gtkmm2ext::set_size_request_to_display_given_text (ms_minutes_label, "99", 0, 2);
342 Gtkmm2ext::set_size_request_to_display_given_text (ms_seconds_label, "99", 0, 2);
346 Gtkmm2ext::set_size_request_to_display_given_text (audio_frames_label, "4294967296", 0, 2);
356 AudioClock::set (jack_nframes_t when, bool force)
359 if ((!force && !is_visible()) || session == 0) {
363 if (when == last_when && !force) {
369 set_smpte (when, force);
373 set_bbt (when, force);
377 set_minsec (when, force);
381 set_frames (when, force);
392 AudioClock::set_frames (jack_nframes_t when, bool force)
395 snprintf (buf, sizeof (buf), "%u", when);
396 audio_frames_label.set_text (buf);
400 AudioClock::set_minsec (jack_nframes_t when, bool force)
409 hrs = (int) floor (left / (session->frame_rate() * 60.0f * 60.0f));
410 left -= (jack_nframes_t) floor (hrs * session->frame_rate() * 60.0f * 60.0f);
411 mins = (int) floor (left / (session->frame_rate() * 60.0f));
412 left -= (jack_nframes_t) floor (mins * session->frame_rate() * 60.0f);
413 secs = left / (float) session->frame_rate();
415 if (force || hrs != ms_last_hrs) {
416 sprintf (buf, "%d", hrs);
417 ms_hours_label.set_text (buf);
421 if (force || mins != ms_last_mins) {
422 sprintf (buf, "%d", mins);
423 ms_minutes_label.set_text (buf);
427 if (force || secs != ms_last_secs) {
428 sprintf (buf, "%06.3f", secs);
429 ms_seconds_label.set_text (buf);
435 AudioClock::set_smpte (jack_nframes_t when, bool force)
441 session->smpte_duration (when, smpte);
443 session->smpte_time (when, smpte);
446 if (force || smpte.hours != last_hrs || smpte.negative != last_negative) {
447 if (smpte.negative) {
448 sprintf (buf, "-%02ld", smpte.hours);
450 sprintf (buf, " %02ld", smpte.hours);
452 hours_label.set_text (buf);
453 last_hrs = smpte.hours;
454 last_negative = smpte.negative;
457 if (force || smpte.minutes != last_mins) {
458 sprintf (buf, "%02ld", smpte.minutes);
459 minutes_label.set_text (buf);
460 last_mins = smpte.minutes;
463 if (force || smpte.seconds != last_secs) {
464 sprintf (buf, "%02ld", smpte.seconds);
465 seconds_label.set_text (buf);
466 last_secs = smpte.seconds;
469 if (force || smpte.frames != last_frames) {
470 sprintf (buf, "%02ld", smpte.frames);
471 frames_label.set_text (buf);
472 last_frames = smpte.frames;
477 AudioClock::set_bbt (jack_nframes_t when, bool force)
482 session->tempo_map().bbt_time (when, bbt);
483 sprintf (buf, "%03" PRIu32, bbt.bars);
484 bars_label.set_text (buf);
485 sprintf (buf, "%02" PRIu32, bbt.beats);
486 beats_label.set_text (buf);
487 sprintf (buf, "%04" PRIu32, bbt.ticks);
488 ticks_label.set_text (buf);
491 TempoMap::Metric m (session->tempo_map().metric_at (when));
492 sprintf (buf, "%-5.2f", m.tempo().beats_per_minute());
493 tempo_label->set_text (buf);
494 sprintf (buf, "%g|%g", m.meter().beats_per_bar(), m.meter().note_divisor());
495 meter_label->set_text (buf);
500 AudioClock::set_session (Session *s)
505 set (last_when, true);
510 AudioClock::field_key_release_event (GdkEventKey *ev, Field field)
515 bool move_on = false;
519 label = &hours_label;
522 label = &minutes_label;
525 label = &seconds_label;
528 label = &frames_label;
532 label = &audio_frames_label;
536 label = &ms_hours_label;
539 label = &ms_minutes_label;
542 label = &ms_seconds_label;
549 label = &beats_label;
552 label = &ticks_label;
558 switch (ev->keyval) {
602 if (_mode == MinSec && field == MS_Seconds) {
616 clock_base.grab_focus ();
625 if (key_entry_state == 0) {
627 /* initialize with a fresh new string */
629 if (field != AudioFrames) {
630 for (uint32_t xn = 0; xn < field_length[field] - 1; ++xn) {
639 string existing = label->get_text();
640 if (existing.length() >= field_length[field]) {
641 new_text = existing.substr (1, field_length[field] - 1);
643 new_text = existing.substr (0, field_length[field] - 1);
647 new_text += new_char;
648 label->set_text (new_text);
652 if (key_entry_state == field_length[field]) {
658 if (key_entry_state) {
665 // Check SMPTE fields for sanity (may also adjust fields)
666 smpte_sanitize_display();
672 ValueChanged(); /* EMIT_SIGNAL */
675 /* move on to the next field.
683 minutes_ebox.grab_focus ();
686 seconds_ebox.grab_focus ();
689 frames_ebox.grab_focus ();
692 clock_base.grab_focus ();
697 clock_base.grab_focus ();
703 ms_minutes_ebox.grab_focus ();
706 ms_seconds_ebox.grab_focus ();
709 clock_base.grab_focus ();
715 beats_ebox.grab_focus ();
718 ticks_ebox.grab_focus ();
721 clock_base.grab_focus ();
734 AudioClock::field_focus_in_event (GdkEventFocus *ev, Field field)
740 hours_ebox.set_flags (Gtk::HAS_FOCUS);
741 hours_ebox.set_state (Gtk::STATE_ACTIVE);
744 minutes_ebox.set_flags (Gtk::HAS_FOCUS);
745 minutes_ebox.set_state (Gtk::STATE_ACTIVE);
748 seconds_ebox.set_flags (Gtk::HAS_FOCUS);
749 seconds_ebox.set_state (Gtk::STATE_ACTIVE);
752 frames_ebox.set_flags (Gtk::HAS_FOCUS);
753 frames_ebox.set_state (Gtk::STATE_ACTIVE);
757 audio_frames_ebox.set_flags (Gtk::HAS_FOCUS);
758 audio_frames_ebox.set_state (Gtk::STATE_ACTIVE);
762 ms_hours_ebox.set_flags (Gtk::HAS_FOCUS);
763 ms_hours_ebox.set_state (Gtk::STATE_ACTIVE);
766 ms_minutes_ebox.set_flags (Gtk::HAS_FOCUS);
767 ms_minutes_ebox.set_state (Gtk::STATE_ACTIVE);
770 ms_seconds_ebox.set_flags (Gtk::HAS_FOCUS);
771 ms_seconds_ebox.set_state (Gtk::STATE_ACTIVE);
774 bars_ebox.set_flags (Gtk::HAS_FOCUS);
775 bars_ebox.set_state (Gtk::STATE_ACTIVE);
778 beats_ebox.set_flags (Gtk::HAS_FOCUS);
779 beats_ebox.set_state (Gtk::STATE_ACTIVE);
782 ticks_ebox.set_flags (Gtk::HAS_FOCUS);
783 ticks_ebox.set_state (Gtk::STATE_ACTIVE);
791 AudioClock::field_focus_out_event (GdkEventFocus *ev, Field field)
796 hours_ebox.unset_flags (Gtk::HAS_FOCUS);
797 hours_ebox.set_state (Gtk::STATE_NORMAL);
800 minutes_ebox.unset_flags (Gtk::HAS_FOCUS);
801 minutes_ebox.set_state (Gtk::STATE_NORMAL);
804 seconds_ebox.unset_flags (Gtk::HAS_FOCUS);
805 seconds_ebox.set_state (Gtk::STATE_NORMAL);
808 frames_ebox.unset_flags (Gtk::HAS_FOCUS);
809 frames_ebox.set_state (Gtk::STATE_NORMAL);
813 audio_frames_ebox.unset_flags (Gtk::HAS_FOCUS);
814 audio_frames_ebox.set_state (Gtk::STATE_NORMAL);
818 ms_hours_ebox.unset_flags (Gtk::HAS_FOCUS);
819 ms_hours_ebox.set_state (Gtk::STATE_NORMAL);
822 ms_minutes_ebox.unset_flags (Gtk::HAS_FOCUS);
823 ms_minutes_ebox.set_state (Gtk::STATE_NORMAL);
826 ms_seconds_ebox.unset_flags (Gtk::HAS_FOCUS);
827 ms_seconds_ebox.set_state (Gtk::STATE_NORMAL);
831 bars_ebox.unset_flags (Gtk::HAS_FOCUS);
832 bars_ebox.set_state (Gtk::STATE_NORMAL);
835 beats_ebox.unset_flags (Gtk::HAS_FOCUS);
836 beats_ebox.set_state (Gtk::STATE_NORMAL);
839 ticks_ebox.unset_flags (Gtk::HAS_FOCUS);
840 ticks_ebox.set_state (Gtk::STATE_NORMAL);
848 AudioClock::field_button_release_event (GdkEventButton *ev, Field field)
853 gdk_pointer_ungrab(GDK_CURRENT_TIME);
855 if (ev->y > drag_start_y+1 || ev->y < drag_start_y-1 || Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)){
856 // we actually dragged so return without setting editing focus, or we shift clicked
866 ops_menu->popup (1, ev->time);
870 if (Keyboard::is_context_menu_event (ev)) {
874 ops_menu->popup (1, ev->time);
878 switch (ev->button) {
882 hours_ebox.grab_focus();
885 minutes_ebox.grab_focus();
888 seconds_ebox.grab_focus();
891 frames_ebox.grab_focus();
895 audio_frames_ebox.grab_focus();
899 ms_hours_ebox.grab_focus();
902 ms_minutes_ebox.grab_focus();
905 ms_seconds_ebox.grab_focus();
909 bars_ebox.grab_focus ();
912 beats_ebox.grab_focus ();
915 ticks_ebox.grab_focus ();
928 AudioClock::field_button_press_event (GdkEventButton *ev, Field field)
930 if (session == 0) return FALSE;
932 jack_nframes_t frames = 0;
934 switch (ev->button) {
936 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
938 ValueChanged (); /* EMIT_SIGNAL */
941 /* make absolutely sure that the pointer is grabbed */
942 gdk_pointer_grab(ev->window,FALSE ,
943 GdkEventMask( Gdk::POINTER_MOTION_MASK | Gdk::BUTTON_PRESS_MASK |Gdk::BUTTON_RELEASE_MASK),
947 drag_start_y = ev->y;
952 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
954 ValueChanged (); /* EMIT_SIGNAL */
959 /* used for context sensitive menu */
964 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
965 frames = get_frames (field);
967 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
970 set (current_time() + frames, true);
971 ValueChanged (); /* EMIT_SIGNAL */
977 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
978 frames = get_frames (field);
980 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
984 if ((double)current_time() - (double)frames < 0.0) {
988 set (current_time() - frames, true);
991 ValueChanged (); /* EMIT_SIGNAL */
1005 AudioClock::field_button_scroll_event (GdkEventScroll *ev, Field field)
1007 if (session == 0) return FALSE;
1009 jack_nframes_t frames = 0;
1011 switch (ev->direction) {
1014 frames = get_frames (field);
1016 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
1019 set (current_time() + frames, true);
1020 ValueChanged (); /* EMIT_SIGNAL */
1024 case GDK_SCROLL_DOWN:
1025 frames = get_frames (field);
1027 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
1031 if ((double)current_time() - (double)frames < 0.0) {
1034 set (current_time() - frames, true);
1037 ValueChanged (); /* EMIT_SIGNAL */
1050 AudioClock::field_motion_notify_event (GdkEventMotion *ev, Field field)
1052 if (session == 0 || !dragging) {
1056 float pixel_frame_scale_factor = 0.2f;
1059 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
1060 pixel_frame_scale_factor = 0.1f;
1064 if (Keyboard::modifier_state_contains (ev->state,
1065 Keyboard::Control|Keyboard::Alt)) {
1067 pixel_frame_scale_factor = 0.025f;
1070 double y_delta = ev->y - drag_y;
1072 drag_accum += y_delta*pixel_frame_scale_factor;
1076 if (trunc(drag_accum) != 0) {
1078 jack_nframes_t frames;
1079 jack_nframes_t pos ;
1081 dir = (drag_accum < 0 ? 1:-1);
1082 pos = current_time();
1083 frames = get_frames (field,pos,dir);
1085 if (frames != 0 && frames * drag_accum < current_time()) {
1087 set ((jack_nframes_t) floor (pos - drag_accum * frames), false); // minus because up is negative in computer-land
1095 ValueChanged(); /* EMIT_SIGNAL */
1104 AudioClock::get_frames (Field field,jack_nframes_t pos,int dir)
1107 jack_nframes_t frames = 0;
1111 frames = (jack_nframes_t) floor (3600.0 * session->frame_rate());
1114 frames = (jack_nframes_t) floor (60.0 * session->frame_rate());
1117 frames = session->frame_rate();
1120 frames = (jack_nframes_t) floor (session->frame_rate() / session->smpte_frames_per_second);
1128 frames = (jack_nframes_t) floor (3600.0 * session->frame_rate());
1131 frames = (jack_nframes_t) floor (60.0 * session->frame_rate());
1134 frames = session->frame_rate();
1141 frames = session->tempo_map().bbt_duration_at(pos,bbt,dir);
1147 frames = session->tempo_map().bbt_duration_at(pos,bbt,dir);
1153 frames = session->tempo_map().bbt_duration_at(pos,bbt,dir);
1161 AudioClock::current_time (jack_nframes_t pos) const
1163 jack_nframes_t ret = 0;
1167 ret = smpte_frame_from_display ();
1170 ret = bbt_frame_from_display (pos);
1174 ret = minsec_frame_from_display ();
1178 ret = audio_frame_from_display ();
1189 AudioClock::current_duration (jack_nframes_t pos) const
1191 jack_nframes_t ret = 0;
1195 ret = smpte_frame_from_display ();
1198 ret = bbt_frame_duration_from_display (pos);
1202 ret = minsec_frame_from_display ();
1206 ret = audio_frame_from_display ();
1217 AudioClock::smpte_sanitize_display()
1219 // Check SMPTE fields for sanity, possibly adjusting values
1220 if (atoi(minutes_label.get_text()) > 59) {
1221 minutes_label.set_text("59");
1224 if (atoi(seconds_label.get_text()) > 59) {
1225 seconds_label.set_text("59");
1228 switch ((long)rint(session->smpte_frames_per_second)) {
1230 if (atoi(frames_label.get_text()) > 23) {
1231 frames_label.set_text("23");
1235 if (atoi(frames_label.get_text()) > 24) {
1236 frames_label.set_text("24");
1240 if (atoi(frames_label.get_text()) > 29) {
1241 frames_label.set_text("29");
1248 if (session->smpte_drop_frames) {
1249 if ((atoi(minutes_label.get_text()) % 10) && (atoi(seconds_label.get_text()) == 0) && (atoi(frames_label.get_text()) < 2)) {
1250 frames_label.set_text("02");
1256 AudioClock::smpte_frame_from_display () const
1263 jack_nframes_t sample;
1265 smpte.hours = atoi (hours_label.get_text());
1266 smpte.minutes = atoi (minutes_label.get_text());
1267 smpte.seconds = atoi (seconds_label.get_text());
1268 smpte.frames = atoi (frames_label.get_text());
1270 session->smpte_to_sample( smpte, sample, false /* use_offset */, false /* use_subframes */ );
1274 #define SMPTE_SAMPLE_TEST_1
1275 #define SMPTE_SAMPLE_TEST_2
1276 #define SMPTE_SAMPLE_TEST_3
1277 #define SMPTE_SAMPLE_TEST_4
1278 #define SMPTE_SAMPLE_TEST_5
1279 #define SMPTE_SAMPLE_TEST_6
1280 #define SMPTE_SAMPLE_TEST_7
1282 // Testcode for smpte<->sample conversions (P.S.)
1284 jack_nframes_t sample1;
1285 jack_nframes_t oldsample = 0;
1287 jack_nframes_t sample_increment;
1289 sample_increment = (long)rint(session->frame_rate() / SMPTE::frames_per_second);
1291 #ifdef SMPTE_SAMPLE_TEST_1
1292 // Test 1: use_offset = false, use_subframes = false
1293 cout << "use_offset = false, use_subframes = false" << endl;
1294 for (int i = 0; i < 108003; i++) {
1295 SMPTE::to_sample( smpte1, sample1, false /* use_offset */, false /* use_subframes */ );
1296 session->sample_to_smpte( sample1, smpte2, false /* use_offset */, false /* use_subframes */ );
1298 if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
1299 cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1300 cout << "smpte1: " << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1301 cout << "sample: " << sample1 << endl;
1302 cout << "sample: " << sample1 << " -> ";
1303 cout << "smpte2: " << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1307 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1308 cout << "ERROR: smpte2 not equal smpte1" << endl;
1309 cout << "smpte1: " << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1310 cout << "sample: " << sample1 << endl;
1311 cout << "sample: " << sample1 << " -> ";
1312 cout << "smpte2: " << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1315 oldsample = sample1;
1316 SMPTE::increment( smpte1 );
1319 cout << "sample_increment: " << sample_increment << endl;
1320 cout << "sample: " << sample1 << " -> ";
1321 cout << "smpte: " << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1324 #ifdef SMPTE_SAMPLE_TEST_2
1325 // Test 2: use_offset = true, use_subframes = false
1326 cout << "use_offset = true, use_subframes = false" << endl;
1332 smpte1.subframes = 0;
1333 sample1 = oldsample = 0;
1335 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1336 cout << "Starting at sample: " << sample1 << " -> ";
1337 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1339 for (int i = 0; i < 108003; i++) {
1340 SMPTE::to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1341 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1343 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1344 // cout << "sample: " << sample1 << endl;
1345 // cout << "sample: " << sample1 << " -> ";
1346 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1348 if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
1349 cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1350 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1351 cout << "sample: " << sample1 << endl;
1352 cout << "sample: " << sample1 << " -> ";
1353 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1357 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1358 cout << "ERROR: smpte2 not equal smpte1" << endl;
1359 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1360 cout << "sample: " << sample1 << endl;
1361 cout << "sample: " << sample1 << " -> ";
1362 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1365 oldsample = sample1;
1366 SMPTE::increment( smpte1 );
1369 cout << "sample_increment: " << sample_increment << endl;
1370 cout << "sample: " << sample1 << " -> ";
1371 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1374 #ifdef SMPTE_SAMPLE_TEST_3
1375 // Test 3: use_offset = true, use_subframes = false, decrement
1376 cout << "use_offset = true, use_subframes = false, decrement" << endl;
1378 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1379 cout << "Starting at sample: " << sample1 << " -> ";
1380 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1382 for (int i = 0; i < 108003; i++) {
1383 SMPTE::to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1384 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1386 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1387 // cout << "sample: " << sample1 << endl;
1388 // cout << "sample: " << sample1 << " -> ";
1389 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1391 if ((i > 0) && ( ((oldsample - sample1) != sample_increment) && ((oldsample - sample1) != (sample_increment + 1)) && ((oldsample - sample1) != (sample_increment - 1)))) {
1392 cout << "ERROR: sample increment not right: " << (oldsample - sample1) << " != " << sample_increment << endl;
1393 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1394 cout << "sample: " << sample1 << endl;
1395 cout << "sample: " << sample1 << " -> ";
1396 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1400 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1401 cout << "ERROR: smpte2 not equal smpte1" << endl;
1402 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1403 cout << "sample: " << sample1 << endl;
1404 cout << "sample: " << sample1 << " -> ";
1405 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1408 oldsample = sample1;
1409 SMPTE::decrement( smpte1 );
1412 cout << "sample_decrement: " << sample_increment << endl;
1413 cout << "sample: " << sample1 << " -> ";
1414 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1418 #ifdef SMPTE_SAMPLE_TEST_4
1419 // Test 4: use_offset = true, use_subframes = true
1420 cout << "use_offset = true, use_subframes = true" << endl;
1422 for (long sub = 5; sub < 80; sub += 5) {
1427 smpte1.subframes = 0;
1428 sample1 = oldsample = (sample_increment * sub) / 80;
1430 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, true /* use_subframes */ );
1432 cout << "starting at sample: " << sample1 << " -> ";
1433 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1435 for (int i = 0; i < 108003; i++) {
1436 SMPTE::to_sample( smpte1, sample1, true /* use_offset */, true /* use_subframes */ );
1437 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, true /* use_subframes */ );
1439 if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
1440 cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1441 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1442 cout << "sample: " << sample1 << endl;
1443 cout << "sample: " << sample1 << " -> ";
1444 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1448 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames || smpte2.subframes != smpte1.subframes) {
1449 cout << "ERROR: smpte2 not equal smpte1" << endl;
1450 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1451 cout << "sample: " << sample1 << endl;
1452 cout << "sample: " << sample1 << " -> ";
1453 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1456 oldsample = sample1;
1457 SMPTE::increment( smpte1 );
1460 cout << "sample_increment: " << sample_increment << endl;
1461 cout << "sample: " << sample1 << " -> ";
1462 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1464 for (int i = 0; i < 108003; i++) {
1465 SMPTE::to_sample( smpte1, sample1, true /* use_offset */, true /* use_subframes */ );
1466 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, true /* use_subframes */ );
1468 if ((i > 0) && ( ((oldsample - sample1) != sample_increment) && ((oldsample - sample1) != (sample_increment + 1)) && ((oldsample - sample1) != (sample_increment - 1)))) {
1469 cout << "ERROR: sample increment not right: " << (oldsample - sample1) << " != " << sample_increment << endl;
1470 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1471 cout << "sample: " << sample1 << endl;
1472 cout << "sample: " << sample1 << " -> ";
1473 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1477 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames || smpte2.subframes != smpte1.subframes) {
1478 cout << "ERROR: smpte2 not equal smpte1" << endl;
1479 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1480 cout << "sample: " << sample1 << endl;
1481 cout << "sample: " << sample1 << " -> ";
1482 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1485 oldsample = sample1;
1486 SMPTE::decrement( smpte1 );
1489 cout << "sample_decrement: " << sample_increment << endl;
1490 cout << "sample: " << sample1 << " -> ";
1491 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1496 #ifdef SMPTE_SAMPLE_TEST_5
1497 // Test 5: use_offset = true, use_subframes = false, increment seconds
1498 cout << "use_offset = true, use_subframes = false, increment seconds" << endl;
1504 smpte1.subframes = 0;
1505 sample1 = oldsample = 0;
1506 sample_increment = session->frame_rate();
1508 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1509 cout << "Starting at sample: " << sample1 << " -> ";
1510 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1512 for (int i = 0; i < 3600; i++) {
1513 SMPTE::to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1514 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1516 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1517 // cout << "sample: " << sample1 << endl;
1518 // cout << "sample: " << sample1 << " -> ";
1519 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1521 // if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1523 // cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1527 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1528 cout << "ERROR: smpte2 not equal smpte1" << endl;
1529 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1530 cout << "sample: " << sample1 << endl;
1531 cout << "sample: " << sample1 << " -> ";
1532 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1535 oldsample = sample1;
1536 SMPTE::increment_seconds( smpte1 );
1539 cout << "sample_increment: " << sample_increment << endl;
1540 cout << "sample: " << sample1 << " -> ";
1541 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1545 #ifdef SMPTE_SAMPLE_TEST_6
1546 // Test 6: use_offset = true, use_subframes = false, increment minutes
1547 cout << "use_offset = true, use_subframes = false, increment minutes" << endl;
1553 smpte1.subframes = 0;
1554 sample1 = oldsample = 0;
1555 sample_increment = session->frame_rate() * 60;
1557 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1558 cout << "Starting at sample: " << sample1 << " -> ";
1559 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1561 for (int i = 0; i < 60; i++) {
1562 SMPTE::to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1563 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1565 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1566 // cout << "sample: " << sample1 << endl;
1567 // cout << "sample: " << sample1 << " -> ";
1568 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1570 // if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1572 // cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1576 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1577 cout << "ERROR: smpte2 not equal smpte1" << endl;
1578 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1579 cout << "sample: " << sample1 << endl;
1580 cout << "sample: " << sample1 << " -> ";
1581 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1584 oldsample = sample1;
1585 SMPTE::increment_minutes( smpte1 );
1588 cout << "sample_increment: " << sample_increment << endl;
1589 cout << "sample: " << sample1 << " -> ";
1590 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1593 #ifdef SMPTE_SAMPLE_TEST_7
1594 // Test 7: use_offset = true, use_subframes = false, increment hours
1595 cout << "use_offset = true, use_subframes = false, increment hours" << endl;
1601 smpte1.subframes = 0;
1602 sample1 = oldsample = 0;
1603 sample_increment = session->frame_rate() * 60 * 60;
1605 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1606 cout << "Starting at sample: " << sample1 << " -> ";
1607 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1609 for (int i = 0; i < 10; i++) {
1610 SMPTE::to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1611 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1613 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1614 // cout << "sample: " << sample1 << endl;
1615 // cout << "sample: " << sample1 << " -> ";
1616 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1618 // if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1620 // cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1624 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1625 cout << "ERROR: smpte2 not equal smpte1" << endl;
1626 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1627 cout << "sample: " << sample1 << endl;
1628 cout << "sample: " << sample1 << " -> ";
1629 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1632 oldsample = sample1;
1633 SMPTE::increment_hours( smpte1 );
1636 cout << "sample_increment: " << sample_increment << endl;
1637 cout << "sample: " << sample1 << " -> ";
1638 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1647 AudioClock::minsec_frame_from_display () const
1653 int hrs = atoi (ms_hours_label.get_text());
1654 int mins = atoi (ms_minutes_label.get_text());
1655 float secs = atof (ms_seconds_label.get_text());
1657 jack_nframes_t sr = session->frame_rate();
1659 return (jack_nframes_t) floor ((hrs * 60.0f * 60.0f * sr) + (mins * 60.0f * sr) + (secs * sr));
1663 AudioClock::bbt_frame_from_display (jack_nframes_t pos) const
1666 error << "AudioClock::current_time() called with BBT mode but without session!" << endmsg;
1671 any.type = AnyTime::BBT;
1673 any.bbt.bars = atoi (bars_label.get_text());
1674 any.bbt.beats = atoi (beats_label.get_text());
1675 any.bbt.ticks = atoi (ticks_label.get_text());
1677 jack_nframes_t ret = session->convert_to_frames_at (pos, any);
1684 AudioClock::bbt_frame_duration_from_display (jack_nframes_t pos) const
1687 error << "AudioClock::current_time() called with BBT mode but without session!" << endmsg;
1694 bbt.bars = atoi (bars_label.get_text());
1695 bbt.beats = atoi (beats_label.get_text());
1696 bbt.ticks = atoi (ticks_label.get_text());
1698 return session->tempo_map().bbt_duration_at(pos,bbt,1);
1702 AudioClock::audio_frame_from_display () const
1704 return (jack_nframes_t) atoi (audio_frames_label.get_text());
1708 AudioClock::build_ops_menu ()
1710 using namespace Menu_Helpers;
1711 ops_menu = new Menu;
1712 MenuList& ops_items = ops_menu->items();
1713 ops_menu->set_name ("ArdourContextMenu");
1715 Menu *mode_menu = manage (new Menu);
1716 MenuList& mode_items = mode_menu->items();
1717 mode_menu->set_name ("ArdourContextMenu");
1719 mode_items.push_back (MenuElem (_("SMPTE"), bind (mem_fun(*this, &AudioClock::set_mode), SMPTE)));
1720 mode_items.push_back (MenuElem (_("Bars:Beats"), bind (mem_fun(*this, &AudioClock::set_mode), BBT)));
1721 mode_items.push_back (MenuElem (_("Minutes:Seconds"), bind (mem_fun(*this, &AudioClock::set_mode), MinSec)));
1722 mode_items.push_back (MenuElem (_("Audio Frames"), bind (mem_fun(*this, &AudioClock::set_mode), Frames)));
1723 mode_items.push_back (MenuElem (_("Off"), bind (mem_fun(*this, &AudioClock::set_mode), Off)));
1725 ops_items.push_back (MenuElem (_("Mode"), *mode_menu));
1729 AudioClock::set_mode (Mode m)
1731 /* slightly tricky: this is called from within the ARDOUR_UI
1732 constructor by some of its clock members. at that time
1733 the instance pointer is unset, so we have to be careful.
1734 the main idea is to drop keyboard focus in case we had
1735 started editing the clock and then we switch clock mode.
1738 clock_base.grab_focus ();
1748 clock_base.remove ();
1758 clock_base.add (smpte_packer_hbox);
1759 Gtkmm2ext::set_size_request_to_display_given_text (hours_label, "-88", 0, 2);
1760 Gtkmm2ext::set_size_request_to_display_given_text (minutes_label, "88", 0, 2);
1761 Gtkmm2ext::set_size_request_to_display_given_text (seconds_label, "88", 0, 2);
1762 Gtkmm2ext::set_size_request_to_display_given_text (frames_label, "88", 0, 2);
1766 clock_base.add (bbt_packer_hbox);
1767 Gtkmm2ext::set_size_request_to_display_given_text (bars_label, "-888", 0, 2);
1768 Gtkmm2ext::set_size_request_to_display_given_text (beats_label, "88", 0, 2);
1769 Gtkmm2ext::set_size_request_to_display_given_text (ticks_label, "8888", 0, 2);
1773 clock_base.add (minsec_packer_hbox);
1774 Gtkmm2ext::set_size_request_to_display_given_text (ms_hours_label, "99", 0, 2);
1775 Gtkmm2ext::set_size_request_to_display_given_text (ms_minutes_label, "99", 0, 2);
1776 Gtkmm2ext::set_size_request_to_display_given_text (ms_seconds_label, "99", 0, 2);
1780 clock_base.add (frames_packer_hbox);
1781 Gtkmm2ext::set_size_request_to_display_given_text (audio_frames_label, "4294967296", 0, 2);
1787 set (last_when, true);
1788 clock_base.show_all ();
1789 key_entry_state = 0;