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;
47 const uint32_t AudioClock::field_length[(int) AudioClock::AudioFrames+1] = {
49 2, /* SMPTE_Minutes */
50 2, /* SMPTE_Seconds */
61 AudioClock::AudioClock (const string& name, bool allow_edit, bool duration, bool with_tempo_and_meter)
62 : is_duration (duration),
63 editable (allow_edit),
78 audio_frames_ebox.add (audio_frames_label);
79 frames_packer_hbox.set_border_width (2);
80 frames_packer_hbox.pack_start (audio_frames_ebox, false, false);
82 hours_ebox.add (hours_label);
83 minutes_ebox.add (minutes_label);
84 seconds_ebox.add (seconds_label);
85 frames_ebox.add (frames_label);
86 bars_ebox.add (bars_label);
87 beats_ebox.add (beats_label);
88 ticks_ebox.add (ticks_label);
89 ms_hours_ebox.add (ms_hours_label);
90 ms_minutes_ebox.add (ms_minutes_label);
91 ms_seconds_ebox.add (ms_seconds_label);
93 smpte_packer.set_homogeneous (false);
94 smpte_packer.set_border_width (2);
95 smpte_packer.pack_start (hours_ebox, false, false);
96 smpte_packer.pack_start (colon1, false, false);
97 smpte_packer.pack_start (minutes_ebox, false, false);
98 smpte_packer.pack_start (colon2, false, false);
99 smpte_packer.pack_start (seconds_ebox, false, false);
100 smpte_packer.pack_start (colon3, false, false);
101 smpte_packer.pack_start (frames_ebox, false, false);
103 smpte_packer_hbox.pack_start (smpte_packer, true, false);
105 bbt_packer.set_homogeneous (false);
106 bbt_packer.set_border_width (2);
107 bbt_packer.pack_start (bars_ebox, false, false);
108 bbt_packer.pack_start (b1, false, false);
109 bbt_packer.pack_start (beats_ebox, false, false);
110 bbt_packer.pack_start (b2, false, false);
111 bbt_packer.pack_start (ticks_ebox, false, false);
113 if (with_tempo_and_meter) {
114 meter_label = manage (new Label);
115 tempo_label = manage (new Label);
117 meter_label->set_name ("BBTMeterLabel");
118 tempo_label->set_name ("BBTTempoLabel");
120 tempo_meter_box.pack_start (*meter_label, true, true);
121 tempo_meter_box.pack_start (*tempo_label, true, true);
123 bbt_packer.pack_start (tempo_meter_box, false, false, 5);
129 bbt_packer_hbox.pack_start (bbt_packer, true, false);
131 minsec_packer.set_homogeneous (false);
132 minsec_packer.set_border_width (2);
133 minsec_packer.pack_start (ms_hours_ebox, false, false);
134 minsec_packer.pack_start (colon4, false, false);
135 minsec_packer.pack_start (ms_minutes_ebox, false, false);
136 minsec_packer.pack_start (colon5, false, false);
137 minsec_packer.pack_start (ms_seconds_ebox, false, false);
139 minsec_packer_hbox.pack_start (minsec_packer, true, false);
142 clock_base.set_name (name);
144 audio_frames_label.set_name (name);
145 hours_label.set_name (name);
146 minutes_label.set_name (name);
147 seconds_label.set_name (name);
148 frames_label.set_name (name);
149 bars_label.set_name (name);
150 beats_label.set_name (name);
151 ticks_label.set_name (name);
152 ms_hours_label.set_name (name);
153 ms_minutes_label.set_name (name);
154 ms_seconds_label.set_name (name);
155 hours_ebox.set_name (name);
156 minutes_ebox.set_name (name);
157 seconds_ebox.set_name (name);
158 frames_ebox.set_name (name);
159 audio_frames_ebox.set_name (name);
160 bars_ebox.set_name (name);
161 beats_ebox.set_name (name);
162 ticks_ebox.set_name (name);
163 ms_hours_ebox.set_name (name);
164 ms_minutes_ebox.set_name (name);
165 ms_seconds_ebox.set_name (name);
167 colon1.set_name (name);
168 colon2.set_name (name);
169 colon3.set_name (name);
170 colon4.set_name (name);
171 colon5.set_name (name);
175 clock_frame.set_shadow_type (Gtk::SHADOW_IN);
176 clock_frame.set_name ("BaseFrame");
178 clock_frame.add (clock_base);
180 _mode = BBT; /* lie to force mode switch */
183 pack_start (clock_frame, true, true);
185 /* the clock base handles button releases for menu popup regardless of
186 editable status. if the clock is editable, the clock base is where
187 we pass focus to after leaving the last editable "field", which
188 will then shutdown editing till the user starts it up again.
190 it does this because the focus out event on the field disables
191 keyboard event handling, and we don't connect anything up to
192 notice focus in on the clock base. hence, keyboard event handling
196 clock_base.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::SCROLL_MASK);
197 clock_base.signal_button_release_event().connect (bind (mem_fun (*this, &AudioClock::field_button_release_event), SMPTE_Hours));
199 Session::SMPTEOffsetChanged.connect (mem_fun (*this, &AudioClock::smpte_offset_changed));
205 set (last_when, true);
209 AudioClock::setup_events ()
211 clock_base.set_flags (Gtk::CAN_FOCUS);
213 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);
214 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);
215 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);
216 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);
217 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);
218 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);
219 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);
220 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);
221 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);
222 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);
223 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);
225 hours_ebox.set_flags (Gtk::CAN_FOCUS);
226 minutes_ebox.set_flags (Gtk::CAN_FOCUS);
227 seconds_ebox.set_flags (Gtk::CAN_FOCUS);
228 frames_ebox.set_flags (Gtk::CAN_FOCUS);
229 audio_frames_ebox.set_flags (Gtk::CAN_FOCUS);
230 bars_ebox.set_flags (Gtk::CAN_FOCUS);
231 beats_ebox.set_flags (Gtk::CAN_FOCUS);
232 ticks_ebox.set_flags (Gtk::CAN_FOCUS);
233 ms_hours_ebox.set_flags (Gtk::CAN_FOCUS);
234 ms_minutes_ebox.set_flags (Gtk::CAN_FOCUS);
235 ms_seconds_ebox.set_flags (Gtk::CAN_FOCUS);
237 hours_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), SMPTE_Hours));
238 minutes_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), SMPTE_Minutes));
239 seconds_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), SMPTE_Seconds));
240 frames_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), SMPTE_Frames));
241 audio_frames_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), AudioFrames));
242 bars_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), Bars));
243 beats_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), Beats));
244 ticks_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), Ticks));
245 ms_hours_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), MS_Hours));
246 ms_minutes_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), MS_Minutes));
247 ms_seconds_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), MS_Seconds));
249 hours_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), SMPTE_Hours));
250 minutes_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), SMPTE_Minutes));
251 seconds_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), SMPTE_Seconds));
252 frames_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), SMPTE_Frames));
253 audio_frames_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), AudioFrames));
254 bars_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), Bars));
255 beats_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), Beats));
256 ticks_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), Ticks));
257 ms_hours_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), MS_Hours));
258 ms_minutes_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), MS_Minutes));
259 ms_seconds_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), MS_Seconds));
261 hours_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), SMPTE_Hours));
262 minutes_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), SMPTE_Minutes));
263 seconds_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), SMPTE_Seconds));
264 frames_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), SMPTE_Frames));
265 audio_frames_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), AudioFrames));
266 bars_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), Bars));
267 beats_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), Beats));
268 ticks_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), Ticks));
269 ms_hours_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), MS_Hours));
270 ms_minutes_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), MS_Minutes));
271 ms_seconds_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), MS_Seconds));
273 hours_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), SMPTE_Hours));
274 minutes_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), SMPTE_Minutes));
275 seconds_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), SMPTE_Seconds));
276 frames_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), SMPTE_Frames));
277 audio_frames_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), AudioFrames));
278 bars_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), Bars));
279 beats_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), Beats));
280 ticks_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), Ticks));
281 ms_hours_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), MS_Hours));
282 ms_minutes_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), MS_Minutes));
283 ms_seconds_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), MS_Seconds));
285 hours_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), SMPTE_Hours));
286 minutes_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), SMPTE_Minutes));
287 seconds_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), SMPTE_Seconds));
288 frames_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), SMPTE_Frames));
289 audio_frames_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), AudioFrames));
290 bars_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), Bars));
291 beats_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), Beats));
292 ticks_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), Ticks));
293 ms_hours_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), MS_Hours));
294 ms_minutes_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), MS_Minutes));
295 ms_seconds_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), MS_Seconds));
297 hours_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), SMPTE_Hours));
298 minutes_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), SMPTE_Minutes));
299 seconds_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), SMPTE_Seconds));
300 frames_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), SMPTE_Frames));
301 audio_frames_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), AudioFrames));
302 bars_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), Bars));
303 beats_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), Beats));
304 ticks_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), Ticks));
305 ms_hours_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), MS_Hours));
306 ms_minutes_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), MS_Minutes));
307 ms_seconds_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), MS_Seconds));
309 hours_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), SMPTE_Hours));
310 minutes_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), SMPTE_Minutes));
311 seconds_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), SMPTE_Seconds));
312 frames_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), SMPTE_Frames));
313 audio_frames_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), AudioFrames));
314 bars_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), Bars));
315 beats_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), Beats));
316 ticks_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), Ticks));
317 ms_hours_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), MS_Hours));
318 ms_minutes_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), MS_Minutes));
319 ms_seconds_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), MS_Seconds));
323 AudioClock::on_realize ()
327 /* styles are not available until the widgets are bound to a window */
331 Gtkmm2ext::set_size_request_to_display_given_text (hours_label, "-88", 0, 2);
332 Gtkmm2ext::set_size_request_to_display_given_text (minutes_label, "88", 0, 2);
333 Gtkmm2ext::set_size_request_to_display_given_text (seconds_label, "88", 0, 2);
334 Gtkmm2ext::set_size_request_to_display_given_text (frames_label, "88", 0, 2);
338 Gtkmm2ext::set_size_request_to_display_given_text (bars_label, "-888", 0, 2);
339 Gtkmm2ext::set_size_request_to_display_given_text (beats_label, "88", 0, 2);
340 Gtkmm2ext::set_size_request_to_display_given_text (ticks_label, "8888", 0, 2);
344 Gtkmm2ext::set_size_request_to_display_given_text (ms_hours_label, "99", 0, 2);
345 Gtkmm2ext::set_size_request_to_display_given_text (ms_minutes_label, "99", 0, 2);
346 Gtkmm2ext::set_size_request_to_display_given_text (ms_seconds_label, "99", 0, 2);
350 Gtkmm2ext::set_size_request_to_display_given_text (audio_frames_label, "4294967296", 0, 2);
360 AudioClock::set (jack_nframes_t when, bool force)
363 if ((!force && !is_visible()) || session == 0) {
367 if (when == last_when && !force) {
373 set_smpte (when, force);
377 set_bbt (when, force);
381 set_minsec (when, force);
385 set_frames (when, force);
396 AudioClock::smpte_offset_changed ()
398 jack_nframes_t current;
403 current = current_duration();
405 current = current_time ();
415 AudioClock::set_frames (jack_nframes_t when, bool force)
418 snprintf (buf, sizeof (buf), "%u", when);
419 audio_frames_label.set_text (buf);
423 AudioClock::set_minsec (jack_nframes_t when, bool force)
432 hrs = (int) floor (left / (session->frame_rate() * 60.0f * 60.0f));
433 left -= (jack_nframes_t) floor (hrs * session->frame_rate() * 60.0f * 60.0f);
434 mins = (int) floor (left / (session->frame_rate() * 60.0f));
435 left -= (jack_nframes_t) floor (mins * session->frame_rate() * 60.0f);
436 secs = left / (float) session->frame_rate();
438 if (force || hrs != ms_last_hrs) {
439 sprintf (buf, "%d", hrs);
440 ms_hours_label.set_text (buf);
444 if (force || mins != ms_last_mins) {
445 sprintf (buf, "%d", mins);
446 ms_minutes_label.set_text (buf);
450 if (force || secs != ms_last_secs) {
451 sprintf (buf, "%06.3f", secs);
452 ms_seconds_label.set_text (buf);
458 AudioClock::set_smpte (jack_nframes_t when, bool force)
464 session->smpte_duration (when, smpte);
466 session->smpte_time (when, smpte);
469 if (force || smpte.hours != last_hrs || smpte.negative != last_negative) {
470 if (smpte.negative) {
471 sprintf (buf, "-%02" PRIu32, smpte.hours);
473 sprintf (buf, " %02" PRIu32, smpte.hours);
475 hours_label.set_text (buf);
476 last_hrs = smpte.hours;
477 last_negative = smpte.negative;
480 if (force || smpte.minutes != last_mins) {
481 sprintf (buf, "%02" PRIu32, smpte.minutes);
482 minutes_label.set_text (buf);
483 last_mins = smpte.minutes;
486 if (force || smpte.seconds != last_secs) {
487 sprintf (buf, "%02" PRIu32, smpte.seconds);
488 seconds_label.set_text (buf);
489 last_secs = smpte.seconds;
492 if (force || smpte.frames != last_frames) {
493 sprintf (buf, "%02" PRIu32, smpte.frames);
494 frames_label.set_text (buf);
495 last_frames = smpte.frames;
500 AudioClock::set_bbt (jack_nframes_t when, bool force)
505 session->tempo_map().bbt_time (when, bbt);
506 sprintf (buf, "%03" PRIu32, bbt.bars);
507 bars_label.set_text (buf);
508 sprintf (buf, "%02" PRIu32, bbt.beats);
509 beats_label.set_text (buf);
510 sprintf (buf, "%04" PRIu32, bbt.ticks);
511 ticks_label.set_text (buf);
514 TempoMap::Metric m (session->tempo_map().metric_at (when));
515 sprintf (buf, "%-5.2f", m.tempo().beats_per_minute());
516 tempo_label->set_text (buf);
517 sprintf (buf, "%g|%g", m.meter().beats_per_bar(), m.meter().note_divisor());
518 meter_label->set_text (buf);
523 AudioClock::set_session (Session *s)
528 set (last_when, true);
533 AudioClock::field_key_release_event (GdkEventKey *ev, Field field)
538 bool move_on = false;
542 label = &hours_label;
545 label = &minutes_label;
548 label = &seconds_label;
551 label = &frames_label;
555 label = &audio_frames_label;
559 label = &ms_hours_label;
562 label = &ms_minutes_label;
565 label = &ms_seconds_label;
572 label = &beats_label;
575 label = &ticks_label;
581 switch (ev->keyval) {
625 if (_mode == MinSec && field == MS_Seconds) {
639 clock_base.grab_focus ();
648 if (key_entry_state == 0) {
650 /* initialize with a fresh new string */
652 if (field != AudioFrames) {
653 for (uint32_t xn = 0; xn < field_length[field] - 1; ++xn) {
662 string existing = label->get_text();
663 if (existing.length() >= field_length[field]) {
664 new_text = existing.substr (1, field_length[field] - 1);
666 new_text = existing.substr (0, field_length[field] - 1);
670 new_text += new_char;
671 label->set_text (new_text);
675 if (key_entry_state == field_length[field]) {
681 if (key_entry_state) {
688 // Check SMPTE fields for sanity (may also adjust fields)
689 smpte_sanitize_display();
695 ValueChanged(); /* EMIT_SIGNAL */
698 /* move on to the next field.
706 minutes_ebox.grab_focus ();
709 seconds_ebox.grab_focus ();
712 frames_ebox.grab_focus ();
715 clock_base.grab_focus ();
720 clock_base.grab_focus ();
726 ms_minutes_ebox.grab_focus ();
729 ms_seconds_ebox.grab_focus ();
732 clock_base.grab_focus ();
738 beats_ebox.grab_focus ();
741 ticks_ebox.grab_focus ();
744 clock_base.grab_focus ();
757 AudioClock::field_focus_in_event (GdkEventFocus *ev, Field field)
763 hours_ebox.set_flags (Gtk::HAS_FOCUS);
764 hours_ebox.set_state (Gtk::STATE_ACTIVE);
767 minutes_ebox.set_flags (Gtk::HAS_FOCUS);
768 minutes_ebox.set_state (Gtk::STATE_ACTIVE);
771 seconds_ebox.set_flags (Gtk::HAS_FOCUS);
772 seconds_ebox.set_state (Gtk::STATE_ACTIVE);
775 frames_ebox.set_flags (Gtk::HAS_FOCUS);
776 frames_ebox.set_state (Gtk::STATE_ACTIVE);
780 audio_frames_ebox.set_flags (Gtk::HAS_FOCUS);
781 audio_frames_ebox.set_state (Gtk::STATE_ACTIVE);
785 ms_hours_ebox.set_flags (Gtk::HAS_FOCUS);
786 ms_hours_ebox.set_state (Gtk::STATE_ACTIVE);
789 ms_minutes_ebox.set_flags (Gtk::HAS_FOCUS);
790 ms_minutes_ebox.set_state (Gtk::STATE_ACTIVE);
793 ms_seconds_ebox.set_flags (Gtk::HAS_FOCUS);
794 ms_seconds_ebox.set_state (Gtk::STATE_ACTIVE);
797 bars_ebox.set_flags (Gtk::HAS_FOCUS);
798 bars_ebox.set_state (Gtk::STATE_ACTIVE);
801 beats_ebox.set_flags (Gtk::HAS_FOCUS);
802 beats_ebox.set_state (Gtk::STATE_ACTIVE);
805 ticks_ebox.set_flags (Gtk::HAS_FOCUS);
806 ticks_ebox.set_state (Gtk::STATE_ACTIVE);
814 AudioClock::field_focus_out_event (GdkEventFocus *ev, Field field)
819 hours_ebox.unset_flags (Gtk::HAS_FOCUS);
820 hours_ebox.set_state (Gtk::STATE_NORMAL);
823 minutes_ebox.unset_flags (Gtk::HAS_FOCUS);
824 minutes_ebox.set_state (Gtk::STATE_NORMAL);
827 seconds_ebox.unset_flags (Gtk::HAS_FOCUS);
828 seconds_ebox.set_state (Gtk::STATE_NORMAL);
831 frames_ebox.unset_flags (Gtk::HAS_FOCUS);
832 frames_ebox.set_state (Gtk::STATE_NORMAL);
836 audio_frames_ebox.unset_flags (Gtk::HAS_FOCUS);
837 audio_frames_ebox.set_state (Gtk::STATE_NORMAL);
841 ms_hours_ebox.unset_flags (Gtk::HAS_FOCUS);
842 ms_hours_ebox.set_state (Gtk::STATE_NORMAL);
845 ms_minutes_ebox.unset_flags (Gtk::HAS_FOCUS);
846 ms_minutes_ebox.set_state (Gtk::STATE_NORMAL);
849 ms_seconds_ebox.unset_flags (Gtk::HAS_FOCUS);
850 ms_seconds_ebox.set_state (Gtk::STATE_NORMAL);
854 bars_ebox.unset_flags (Gtk::HAS_FOCUS);
855 bars_ebox.set_state (Gtk::STATE_NORMAL);
858 beats_ebox.unset_flags (Gtk::HAS_FOCUS);
859 beats_ebox.set_state (Gtk::STATE_NORMAL);
862 ticks_ebox.unset_flags (Gtk::HAS_FOCUS);
863 ticks_ebox.set_state (Gtk::STATE_NORMAL);
871 AudioClock::field_button_release_event (GdkEventButton *ev, Field field)
876 gdk_pointer_ungrab(GDK_CURRENT_TIME);
878 if (ev->y > drag_start_y+1 || ev->y < drag_start_y-1 || Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)){
879 // we actually dragged so return without setting editing focus, or we shift clicked
889 ops_menu->popup (1, ev->time);
893 if (Keyboard::is_context_menu_event (ev)) {
897 ops_menu->popup (1, ev->time);
901 switch (ev->button) {
905 hours_ebox.grab_focus();
908 minutes_ebox.grab_focus();
911 seconds_ebox.grab_focus();
914 frames_ebox.grab_focus();
918 audio_frames_ebox.grab_focus();
922 ms_hours_ebox.grab_focus();
925 ms_minutes_ebox.grab_focus();
928 ms_seconds_ebox.grab_focus();
932 bars_ebox.grab_focus ();
935 beats_ebox.grab_focus ();
938 ticks_ebox.grab_focus ();
951 AudioClock::field_button_press_event (GdkEventButton *ev, Field field)
953 if (session == 0) return FALSE;
955 jack_nframes_t frames = 0;
957 switch (ev->button) {
959 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
961 ValueChanged (); /* EMIT_SIGNAL */
964 /* make absolutely sure that the pointer is grabbed */
965 gdk_pointer_grab(ev->window,FALSE ,
966 GdkEventMask( Gdk::POINTER_MOTION_MASK | Gdk::BUTTON_PRESS_MASK |Gdk::BUTTON_RELEASE_MASK),
970 drag_start_y = ev->y;
975 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
977 ValueChanged (); /* EMIT_SIGNAL */
982 /* used for context sensitive menu */
987 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
988 frames = get_frames (field);
990 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
993 set (current_time() + frames, true);
994 ValueChanged (); /* EMIT_SIGNAL */
1000 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
1001 frames = get_frames (field);
1003 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
1007 if ((double)current_time() - (double)frames < 0.0) {
1011 set (current_time() - frames, true);
1014 ValueChanged (); /* EMIT_SIGNAL */
1028 AudioClock::field_button_scroll_event (GdkEventScroll *ev, Field field)
1030 if (session == 0) return FALSE;
1032 jack_nframes_t frames = 0;
1034 switch (ev->direction) {
1037 frames = get_frames (field);
1039 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
1042 set (current_time() + frames, true);
1043 ValueChanged (); /* EMIT_SIGNAL */
1047 case GDK_SCROLL_DOWN:
1048 frames = get_frames (field);
1050 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
1054 if ((double)current_time() - (double)frames < 0.0) {
1057 set (current_time() - frames, true);
1060 ValueChanged (); /* EMIT_SIGNAL */
1073 AudioClock::field_motion_notify_event (GdkEventMotion *ev, Field field)
1075 if (session == 0 || !dragging) {
1079 float pixel_frame_scale_factor = 0.2f;
1082 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
1083 pixel_frame_scale_factor = 0.1f;
1087 if (Keyboard::modifier_state_contains (ev->state,
1088 Keyboard::Control|Keyboard::Alt)) {
1090 pixel_frame_scale_factor = 0.025f;
1093 double y_delta = ev->y - drag_y;
1095 drag_accum += y_delta*pixel_frame_scale_factor;
1099 if (trunc(drag_accum) != 0) {
1101 jack_nframes_t frames;
1102 jack_nframes_t pos ;
1104 dir = (drag_accum < 0 ? 1:-1);
1105 pos = current_time();
1106 frames = get_frames (field,pos,dir);
1108 if (frames != 0 && frames * drag_accum < current_time()) {
1110 set ((jack_nframes_t) floor (pos - drag_accum * frames), false); // minus because up is negative in computer-land
1118 ValueChanged(); /* EMIT_SIGNAL */
1127 AudioClock::get_frames (Field field,jack_nframes_t pos,int dir)
1130 jack_nframes_t frames = 0;
1134 frames = (jack_nframes_t) floor (3600.0 * session->frame_rate());
1137 frames = (jack_nframes_t) floor (60.0 * session->frame_rate());
1140 frames = session->frame_rate();
1143 frames = (jack_nframes_t) floor (session->frame_rate() / Config->get_smpte_frames_per_second());
1151 frames = (jack_nframes_t) floor (3600.0 * session->frame_rate());
1154 frames = (jack_nframes_t) floor (60.0 * session->frame_rate());
1157 frames = session->frame_rate();
1164 frames = session->tempo_map().bbt_duration_at(pos,bbt,dir);
1170 frames = session->tempo_map().bbt_duration_at(pos,bbt,dir);
1176 frames = session->tempo_map().bbt_duration_at(pos,bbt,dir);
1184 AudioClock::current_time (jack_nframes_t pos) const
1186 jack_nframes_t ret = 0;
1190 ret = smpte_frame_from_display ();
1193 ret = bbt_frame_from_display (pos);
1197 ret = minsec_frame_from_display ();
1201 ret = audio_frame_from_display ();
1212 AudioClock::current_duration (jack_nframes_t pos) const
1214 jack_nframes_t ret = 0;
1218 ret = smpte_frame_from_display ();
1221 ret = bbt_frame_duration_from_display (pos);
1225 ret = minsec_frame_from_display ();
1229 ret = audio_frame_from_display ();
1240 AudioClock::smpte_sanitize_display()
1242 // Check SMPTE fields for sanity, possibly adjusting values
1243 if (atoi(minutes_label.get_text()) > 59) {
1244 minutes_label.set_text("59");
1247 if (atoi(seconds_label.get_text()) > 59) {
1248 seconds_label.set_text("59");
1251 switch ((long)rint(Config->get_smpte_frames_per_second())) {
1253 if (atoi(frames_label.get_text()) > 23) {
1254 frames_label.set_text("23");
1258 if (atoi(frames_label.get_text()) > 24) {
1259 frames_label.set_text("24");
1263 if (atoi(frames_label.get_text()) > 29) {
1264 frames_label.set_text("29");
1271 if (Config->get_smpte_drop_frames()) {
1272 if ((atoi(minutes_label.get_text()) % 10) && (atoi(seconds_label.get_text()) == 0) && (atoi(frames_label.get_text()) < 2)) {
1273 frames_label.set_text("02");
1279 AudioClock::smpte_frame_from_display () const
1286 jack_nframes_t sample;
1288 smpte.hours = atoi (hours_label.get_text());
1289 smpte.minutes = atoi (minutes_label.get_text());
1290 smpte.seconds = atoi (seconds_label.get_text());
1291 smpte.frames = atoi (frames_label.get_text());
1293 session->smpte_to_sample( smpte, sample, false /* use_offset */, false /* use_subframes */ );
1297 #define SMPTE_SAMPLE_TEST_1
1298 #define SMPTE_SAMPLE_TEST_2
1299 #define SMPTE_SAMPLE_TEST_3
1300 #define SMPTE_SAMPLE_TEST_4
1301 #define SMPTE_SAMPLE_TEST_5
1302 #define SMPTE_SAMPLE_TEST_6
1303 #define SMPTE_SAMPLE_TEST_7
1305 // Testcode for smpte<->sample conversions (P.S.)
1307 jack_nframes_t sample1;
1308 jack_nframes_t oldsample = 0;
1310 jack_nframes_t sample_increment;
1312 sample_increment = (long)rint(session->frame_rate() / session->smpte_frames_per_second);
1314 #ifdef SMPTE_SAMPLE_TEST_1
1315 // Test 1: use_offset = false, use_subframes = false
1316 cout << "use_offset = false, use_subframes = false" << endl;
1317 for (int i = 0; i < 108003; i++) {
1318 session->smpte_to_sample( smpte1, sample1, false /* use_offset */, false /* use_subframes */ );
1319 session->sample_to_smpte( sample1, smpte2, false /* use_offset */, false /* use_subframes */ );
1321 if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
1322 cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1323 cout << "smpte1: " << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1324 cout << "sample: " << sample1 << endl;
1325 cout << "sample: " << sample1 << " -> ";
1326 cout << "smpte2: " << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1330 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1331 cout << "ERROR: smpte2 not equal smpte1" << endl;
1332 cout << "smpte1: " << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1333 cout << "sample: " << sample1 << endl;
1334 cout << "sample: " << sample1 << " -> ";
1335 cout << "smpte2: " << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1338 oldsample = sample1;
1339 session->smpte_increment( smpte1 );
1342 cout << "sample_increment: " << sample_increment << endl;
1343 cout << "sample: " << sample1 << " -> ";
1344 cout << "smpte: " << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1347 #ifdef SMPTE_SAMPLE_TEST_2
1348 // Test 2: use_offset = true, use_subframes = false
1349 cout << "use_offset = true, use_subframes = false" << endl;
1355 smpte1.subframes = 0;
1356 sample1 = oldsample = 0;
1358 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1359 cout << "Starting at sample: " << sample1 << " -> ";
1360 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1362 for (int i = 0; i < 108003; i++) {
1363 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1364 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1366 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1367 // cout << "sample: " << sample1 << endl;
1368 // cout << "sample: " << sample1 << " -> ";
1369 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1371 if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
1372 cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1373 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1374 cout << "sample: " << sample1 << endl;
1375 cout << "sample: " << sample1 << " -> ";
1376 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1380 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1381 cout << "ERROR: smpte2 not equal smpte1" << endl;
1382 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1383 cout << "sample: " << sample1 << endl;
1384 cout << "sample: " << sample1 << " -> ";
1385 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1388 oldsample = sample1;
1389 session->smpte_increment( smpte1 );
1392 cout << "sample_increment: " << sample_increment << endl;
1393 cout << "sample: " << sample1 << " -> ";
1394 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1397 #ifdef SMPTE_SAMPLE_TEST_3
1398 // Test 3: use_offset = true, use_subframes = false, decrement
1399 cout << "use_offset = true, use_subframes = false, decrement" << endl;
1401 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1402 cout << "Starting at sample: " << sample1 << " -> ";
1403 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1405 for (int i = 0; i < 108003; i++) {
1406 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1407 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1409 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1410 // cout << "sample: " << sample1 << endl;
1411 // cout << "sample: " << sample1 << " -> ";
1412 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1414 if ((i > 0) && ( ((oldsample - sample1) != sample_increment) && ((oldsample - sample1) != (sample_increment + 1)) && ((oldsample - sample1) != (sample_increment - 1)))) {
1415 cout << "ERROR: sample increment not right: " << (oldsample - sample1) << " != " << sample_increment << endl;
1416 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1417 cout << "sample: " << sample1 << endl;
1418 cout << "sample: " << sample1 << " -> ";
1419 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1423 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1424 cout << "ERROR: smpte2 not equal smpte1" << endl;
1425 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1426 cout << "sample: " << sample1 << endl;
1427 cout << "sample: " << sample1 << " -> ";
1428 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1431 oldsample = sample1;
1432 session->smpte_decrement( smpte1 );
1435 cout << "sample_decrement: " << sample_increment << endl;
1436 cout << "sample: " << sample1 << " -> ";
1437 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1441 #ifdef SMPTE_SAMPLE_TEST_4
1442 // Test 4: use_offset = true, use_subframes = true
1443 cout << "use_offset = true, use_subframes = true" << endl;
1445 for (long sub = 5; sub < 80; sub += 5) {
1450 smpte1.subframes = 0;
1451 sample1 = oldsample = (sample_increment * sub) / 80;
1453 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, true /* use_subframes */ );
1455 cout << "starting at sample: " << sample1 << " -> ";
1456 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1458 for (int i = 0; i < 108003; i++) {
1459 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, true /* use_subframes */ );
1460 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, true /* use_subframes */ );
1462 if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
1463 cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1464 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1465 cout << "sample: " << sample1 << endl;
1466 cout << "sample: " << sample1 << " -> ";
1467 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1471 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames || smpte2.subframes != smpte1.subframes) {
1472 cout << "ERROR: smpte2 not equal smpte1" << endl;
1473 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1474 cout << "sample: " << sample1 << endl;
1475 cout << "sample: " << sample1 << " -> ";
1476 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1479 oldsample = sample1;
1480 session->smpte_increment( smpte1 );
1483 cout << "sample_increment: " << sample_increment << endl;
1484 cout << "sample: " << sample1 << " -> ";
1485 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1487 for (int i = 0; i < 108003; i++) {
1488 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, true /* use_subframes */ );
1489 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, true /* use_subframes */ );
1491 if ((i > 0) && ( ((oldsample - sample1) != sample_increment) && ((oldsample - sample1) != (sample_increment + 1)) && ((oldsample - sample1) != (sample_increment - 1)))) {
1492 cout << "ERROR: sample increment not right: " << (oldsample - sample1) << " != " << sample_increment << endl;
1493 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1494 cout << "sample: " << sample1 << endl;
1495 cout << "sample: " << sample1 << " -> ";
1496 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1500 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames || smpte2.subframes != smpte1.subframes) {
1501 cout << "ERROR: smpte2 not equal smpte1" << endl;
1502 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1503 cout << "sample: " << sample1 << endl;
1504 cout << "sample: " << sample1 << " -> ";
1505 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1508 oldsample = sample1;
1509 session->smpte_decrement( smpte1 );
1512 cout << "sample_decrement: " << sample_increment << endl;
1513 cout << "sample: " << sample1 << " -> ";
1514 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1519 #ifdef SMPTE_SAMPLE_TEST_5
1520 // Test 5: use_offset = true, use_subframes = false, increment seconds
1521 cout << "use_offset = true, use_subframes = false, increment seconds" << endl;
1527 smpte1.subframes = 0;
1528 sample1 = oldsample = 0;
1529 sample_increment = session->frame_rate();
1531 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1532 cout << "Starting at sample: " << sample1 << " -> ";
1533 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1535 for (int i = 0; i < 3600; i++) {
1536 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1537 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1539 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1540 // cout << "sample: " << sample1 << endl;
1541 // cout << "sample: " << sample1 << " -> ";
1542 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1544 // if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1546 // cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1550 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1551 cout << "ERROR: smpte2 not equal smpte1" << endl;
1552 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1553 cout << "sample: " << sample1 << endl;
1554 cout << "sample: " << sample1 << " -> ";
1555 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1558 oldsample = sample1;
1559 session->smpte_increment_seconds( smpte1 );
1562 cout << "sample_increment: " << sample_increment << endl;
1563 cout << "sample: " << sample1 << " -> ";
1564 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1568 #ifdef SMPTE_SAMPLE_TEST_6
1569 // Test 6: use_offset = true, use_subframes = false, increment minutes
1570 cout << "use_offset = true, use_subframes = false, increment minutes" << endl;
1576 smpte1.subframes = 0;
1577 sample1 = oldsample = 0;
1578 sample_increment = session->frame_rate() * 60;
1580 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1581 cout << "Starting at sample: " << sample1 << " -> ";
1582 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1584 for (int i = 0; i < 60; i++) {
1585 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1586 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1588 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1589 // cout << "sample: " << sample1 << endl;
1590 // cout << "sample: " << sample1 << " -> ";
1591 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1593 // if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1595 // cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1599 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1600 cout << "ERROR: smpte2 not equal smpte1" << endl;
1601 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1602 cout << "sample: " << sample1 << endl;
1603 cout << "sample: " << sample1 << " -> ";
1604 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1607 oldsample = sample1;
1608 session->smpte_increment_minutes( smpte1 );
1611 cout << "sample_increment: " << sample_increment << endl;
1612 cout << "sample: " << sample1 << " -> ";
1613 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1616 #ifdef SMPTE_SAMPLE_TEST_7
1617 // Test 7: use_offset = true, use_subframes = false, increment hours
1618 cout << "use_offset = true, use_subframes = false, increment hours" << endl;
1624 smpte1.subframes = 0;
1625 sample1 = oldsample = 0;
1626 sample_increment = session->frame_rate() * 60 * 60;
1628 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1629 cout << "Starting at sample: " << sample1 << " -> ";
1630 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1632 for (int i = 0; i < 10; i++) {
1633 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1634 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1636 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1637 // cout << "sample: " << sample1 << endl;
1638 // cout << "sample: " << sample1 << " -> ";
1639 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1641 // if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1643 // cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1647 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1648 cout << "ERROR: smpte2 not equal smpte1" << endl;
1649 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1650 cout << "sample: " << sample1 << endl;
1651 cout << "sample: " << sample1 << " -> ";
1652 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1655 oldsample = sample1;
1656 session->smpte_increment_hours( smpte1 );
1659 cout << "sample_increment: " << sample_increment << endl;
1660 cout << "sample: " << sample1 << " -> ";
1661 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1670 AudioClock::minsec_frame_from_display () const
1676 int hrs = atoi (ms_hours_label.get_text());
1677 int mins = atoi (ms_minutes_label.get_text());
1678 float secs = atof (ms_seconds_label.get_text());
1680 jack_nframes_t sr = session->frame_rate();
1682 return (jack_nframes_t) floor ((hrs * 60.0f * 60.0f * sr) + (mins * 60.0f * sr) + (secs * sr));
1686 AudioClock::bbt_frame_from_display (jack_nframes_t pos) const
1689 error << "AudioClock::current_time() called with BBT mode but without session!" << endmsg;
1694 any.type = AnyTime::BBT;
1696 any.bbt.bars = atoi (bars_label.get_text());
1697 any.bbt.beats = atoi (beats_label.get_text());
1698 any.bbt.ticks = atoi (ticks_label.get_text());
1700 jack_nframes_t ret = session->convert_to_frames_at (pos, any);
1707 AudioClock::bbt_frame_duration_from_display (jack_nframes_t pos) const
1710 error << "AudioClock::current_time() called with BBT mode but without session!" << endmsg;
1717 bbt.bars = atoi (bars_label.get_text());
1718 bbt.beats = atoi (beats_label.get_text());
1719 bbt.ticks = atoi (ticks_label.get_text());
1721 return session->tempo_map().bbt_duration_at(pos,bbt,1);
1725 AudioClock::audio_frame_from_display () const
1727 return (jack_nframes_t) atoi (audio_frames_label.get_text());
1731 AudioClock::build_ops_menu ()
1733 using namespace Menu_Helpers;
1734 ops_menu = new Menu;
1735 MenuList& ops_items = ops_menu->items();
1736 ops_menu->set_name ("ArdourContextMenu");
1738 Menu *mode_menu = manage (new Menu);
1739 MenuList& mode_items = mode_menu->items();
1740 mode_menu->set_name ("ArdourContextMenu");
1742 mode_items.push_back (MenuElem (_("SMPTE"), bind (mem_fun(*this, &AudioClock::set_mode), SMPTE)));
1743 mode_items.push_back (MenuElem (_("Bars:Beats"), bind (mem_fun(*this, &AudioClock::set_mode), BBT)));
1744 mode_items.push_back (MenuElem (_("Minutes:Seconds"), bind (mem_fun(*this, &AudioClock::set_mode), MinSec)));
1745 mode_items.push_back (MenuElem (_("Audio Frames"), bind (mem_fun(*this, &AudioClock::set_mode), Frames)));
1746 mode_items.push_back (MenuElem (_("Off"), bind (mem_fun(*this, &AudioClock::set_mode), Off)));
1748 ops_items.push_back (MenuElem (_("Mode"), *mode_menu));
1752 AudioClock::set_mode (Mode m)
1754 /* slightly tricky: this is called from within the ARDOUR_UI
1755 constructor by some of its clock members. at that time
1756 the instance pointer is unset, so we have to be careful.
1757 the main idea is to drop keyboard focus in case we had
1758 started editing the clock and then we switch clock mode.
1761 clock_base.grab_focus ();
1771 clock_base.remove ();
1781 clock_base.add (smpte_packer_hbox);
1782 Gtkmm2ext::set_size_request_to_display_given_text (hours_label, "-88", 0, 2);
1783 Gtkmm2ext::set_size_request_to_display_given_text (minutes_label, "88", 0, 2);
1784 Gtkmm2ext::set_size_request_to_display_given_text (seconds_label, "88", 0, 2);
1785 Gtkmm2ext::set_size_request_to_display_given_text (frames_label, "88", 0, 2);
1789 clock_base.add (bbt_packer_hbox);
1790 Gtkmm2ext::set_size_request_to_display_given_text (bars_label, "-888", 0, 2);
1791 Gtkmm2ext::set_size_request_to_display_given_text (beats_label, "88", 0, 2);
1792 Gtkmm2ext::set_size_request_to_display_given_text (ticks_label, "8888", 0, 2);
1796 clock_base.add (minsec_packer_hbox);
1797 Gtkmm2ext::set_size_request_to_display_given_text (ms_hours_label, "99", 0, 2);
1798 Gtkmm2ext::set_size_request_to_display_given_text (ms_minutes_label, "99", 0, 2);
1799 Gtkmm2ext::set_size_request_to_display_given_text (ms_seconds_label, "99", 0, 2);
1803 clock_base.add (frames_packer_hbox);
1804 Gtkmm2ext::set_size_request_to_display_given_text (audio_frames_label, "4294967296", 0, 2);
1810 set (last_when, true);
1811 clock_base.show_all ();
1812 key_entry_state = 0;