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 */
329 set_size_requests ();
333 AudioClock::set (nframes_t when, bool force)
336 if ((!force && !is_visible()) || session == 0) {
340 if (when == last_when && !force) {
346 set_smpte (when, force);
350 set_bbt (when, force);
354 set_minsec (when, force);
358 set_frames (when, force);
369 AudioClock::smpte_offset_changed ()
376 current = current_duration();
378 current = current_time ();
388 AudioClock::set_frames (nframes_t when, bool force)
391 snprintf (buf, sizeof (buf), "%u", when);
392 audio_frames_label.set_text (buf);
396 AudioClock::set_minsec (nframes_t when, bool force)
405 hrs = (int) floor (left / (session->frame_rate() * 60.0f * 60.0f));
406 left -= (nframes_t) floor (hrs * session->frame_rate() * 60.0f * 60.0f);
407 mins = (int) floor (left / (session->frame_rate() * 60.0f));
408 left -= (nframes_t) floor (mins * session->frame_rate() * 60.0f);
409 secs = left / (float) session->frame_rate();
411 if (force || hrs != ms_last_hrs) {
412 sprintf (buf, "%02d", hrs);
413 ms_hours_label.set_text (buf);
417 if (force || mins != ms_last_mins) {
418 sprintf (buf, "%02d", mins);
419 ms_minutes_label.set_text (buf);
423 if (force || secs != ms_last_secs) {
424 sprintf (buf, "%06.3f", secs);
425 ms_seconds_label.set_text (buf);
431 AudioClock::set_smpte (nframes_t when, bool force)
437 session->smpte_duration (when, smpte);
439 session->smpte_time (when, smpte);
442 if (force || smpte.hours != last_hrs || smpte.negative != last_negative) {
443 if (smpte.negative) {
444 sprintf (buf, "-%02" PRIu32, smpte.hours);
446 sprintf (buf, " %02" PRIu32, smpte.hours);
448 hours_label.set_text (buf);
449 last_hrs = smpte.hours;
450 last_negative = smpte.negative;
453 if (force || smpte.minutes != last_mins) {
454 sprintf (buf, "%02" PRIu32, smpte.minutes);
455 minutes_label.set_text (buf);
456 last_mins = smpte.minutes;
459 if (force || smpte.seconds != last_secs) {
460 sprintf (buf, "%02" PRIu32, smpte.seconds);
461 seconds_label.set_text (buf);
462 last_secs = smpte.seconds;
465 if (force || smpte.frames != last_frames) {
466 sprintf (buf, "%02" PRIu32, smpte.frames);
467 frames_label.set_text (buf);
468 last_frames = smpte.frames;
473 AudioClock::set_bbt (nframes_t when, bool force)
478 session->tempo_map().bbt_time (when, bbt);
479 sprintf (buf, "%03" PRIu32, bbt.bars);
480 bars_label.set_text (buf);
481 sprintf (buf, "%02" PRIu32, bbt.beats);
482 beats_label.set_text (buf);
483 sprintf (buf, "%04" PRIu32, bbt.ticks);
484 ticks_label.set_text (buf);
487 TempoMap::Metric m (session->tempo_map().metric_at (when));
488 sprintf (buf, "%-5.2f", m.tempo().beats_per_minute());
489 tempo_label->set_text (buf);
490 sprintf (buf, "%g|%g", m.meter().beats_per_bar(), m.meter().note_divisor());
491 meter_label->set_text (buf);
496 AudioClock::set_session (Session *s)
501 set (last_when, true);
506 AudioClock::field_key_release_event (GdkEventKey *ev, Field field)
511 bool move_on = false;
515 label = &hours_label;
518 label = &minutes_label;
521 label = &seconds_label;
524 label = &frames_label;
528 label = &audio_frames_label;
532 label = &ms_hours_label;
535 label = &ms_minutes_label;
538 label = &ms_seconds_label;
545 label = &beats_label;
548 label = &ticks_label;
554 switch (ev->keyval) {
598 if (_mode == MinSec && field == MS_Seconds) {
612 clock_base.grab_focus ();
621 if (key_entry_state == 0) {
623 /* initialize with a fresh new string */
625 if (field != AudioFrames) {
626 for (uint32_t xn = 0; xn < field_length[field] - 1; ++xn) {
635 string existing = label->get_text();
636 if (existing.length() >= field_length[field]) {
637 new_text = existing.substr (1, field_length[field] - 1);
639 new_text = existing.substr (0, field_length[field] - 1);
643 new_text += new_char;
644 label->set_text (new_text);
648 if (key_entry_state == field_length[field]) {
654 if (key_entry_state) {
661 // Check SMPTE fields for sanity (may also adjust fields)
662 smpte_sanitize_display();
668 ValueChanged(); /* EMIT_SIGNAL */
671 /* move on to the next field.
679 minutes_ebox.grab_focus ();
682 seconds_ebox.grab_focus ();
685 frames_ebox.grab_focus ();
688 clock_base.grab_focus ();
693 clock_base.grab_focus ();
699 ms_minutes_ebox.grab_focus ();
702 ms_seconds_ebox.grab_focus ();
705 clock_base.grab_focus ();
711 beats_ebox.grab_focus ();
714 ticks_ebox.grab_focus ();
717 clock_base.grab_focus ();
730 AudioClock::field_focus_in_event (GdkEventFocus *ev, Field field)
736 hours_ebox.set_flags (Gtk::HAS_FOCUS);
737 hours_ebox.set_state (Gtk::STATE_ACTIVE);
740 minutes_ebox.set_flags (Gtk::HAS_FOCUS);
741 minutes_ebox.set_state (Gtk::STATE_ACTIVE);
744 seconds_ebox.set_flags (Gtk::HAS_FOCUS);
745 seconds_ebox.set_state (Gtk::STATE_ACTIVE);
748 frames_ebox.set_flags (Gtk::HAS_FOCUS);
749 frames_ebox.set_state (Gtk::STATE_ACTIVE);
753 audio_frames_ebox.set_flags (Gtk::HAS_FOCUS);
754 audio_frames_ebox.set_state (Gtk::STATE_ACTIVE);
758 ms_hours_ebox.set_flags (Gtk::HAS_FOCUS);
759 ms_hours_ebox.set_state (Gtk::STATE_ACTIVE);
762 ms_minutes_ebox.set_flags (Gtk::HAS_FOCUS);
763 ms_minutes_ebox.set_state (Gtk::STATE_ACTIVE);
766 ms_seconds_ebox.set_flags (Gtk::HAS_FOCUS);
767 ms_seconds_ebox.set_state (Gtk::STATE_ACTIVE);
770 bars_ebox.set_flags (Gtk::HAS_FOCUS);
771 bars_ebox.set_state (Gtk::STATE_ACTIVE);
774 beats_ebox.set_flags (Gtk::HAS_FOCUS);
775 beats_ebox.set_state (Gtk::STATE_ACTIVE);
778 ticks_ebox.set_flags (Gtk::HAS_FOCUS);
779 ticks_ebox.set_state (Gtk::STATE_ACTIVE);
787 AudioClock::field_focus_out_event (GdkEventFocus *ev, Field field)
792 hours_ebox.unset_flags (Gtk::HAS_FOCUS);
793 hours_ebox.set_state (Gtk::STATE_NORMAL);
796 minutes_ebox.unset_flags (Gtk::HAS_FOCUS);
797 minutes_ebox.set_state (Gtk::STATE_NORMAL);
800 seconds_ebox.unset_flags (Gtk::HAS_FOCUS);
801 seconds_ebox.set_state (Gtk::STATE_NORMAL);
804 frames_ebox.unset_flags (Gtk::HAS_FOCUS);
805 frames_ebox.set_state (Gtk::STATE_NORMAL);
809 audio_frames_ebox.unset_flags (Gtk::HAS_FOCUS);
810 audio_frames_ebox.set_state (Gtk::STATE_NORMAL);
814 ms_hours_ebox.unset_flags (Gtk::HAS_FOCUS);
815 ms_hours_ebox.set_state (Gtk::STATE_NORMAL);
818 ms_minutes_ebox.unset_flags (Gtk::HAS_FOCUS);
819 ms_minutes_ebox.set_state (Gtk::STATE_NORMAL);
822 ms_seconds_ebox.unset_flags (Gtk::HAS_FOCUS);
823 ms_seconds_ebox.set_state (Gtk::STATE_NORMAL);
827 bars_ebox.unset_flags (Gtk::HAS_FOCUS);
828 bars_ebox.set_state (Gtk::STATE_NORMAL);
831 beats_ebox.unset_flags (Gtk::HAS_FOCUS);
832 beats_ebox.set_state (Gtk::STATE_NORMAL);
835 ticks_ebox.unset_flags (Gtk::HAS_FOCUS);
836 ticks_ebox.set_state (Gtk::STATE_NORMAL);
844 AudioClock::field_button_release_event (GdkEventButton *ev, Field field)
849 gdk_pointer_ungrab(GDK_CURRENT_TIME);
851 if (ev->y > drag_start_y+1 || ev->y < drag_start_y-1 || Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)){
852 // we actually dragged so return without setting editing focus, or we shift clicked
862 ops_menu->popup (1, ev->time);
866 if (Keyboard::is_context_menu_event (ev)) {
870 ops_menu->popup (1, ev->time);
874 switch (ev->button) {
878 hours_ebox.grab_focus();
881 minutes_ebox.grab_focus();
884 seconds_ebox.grab_focus();
887 frames_ebox.grab_focus();
891 audio_frames_ebox.grab_focus();
895 ms_hours_ebox.grab_focus();
898 ms_minutes_ebox.grab_focus();
901 ms_seconds_ebox.grab_focus();
905 bars_ebox.grab_focus ();
908 beats_ebox.grab_focus ();
911 ticks_ebox.grab_focus ();
924 AudioClock::field_button_press_event (GdkEventButton *ev, Field field)
926 if (session == 0) return FALSE;
928 nframes_t frames = 0;
930 switch (ev->button) {
932 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
934 ValueChanged (); /* EMIT_SIGNAL */
937 /* make absolutely sure that the pointer is grabbed */
938 gdk_pointer_grab(ev->window,FALSE ,
939 GdkEventMask( Gdk::POINTER_MOTION_MASK | Gdk::BUTTON_PRESS_MASK |Gdk::BUTTON_RELEASE_MASK),
943 drag_start_y = ev->y;
948 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
950 ValueChanged (); /* EMIT_SIGNAL */
955 /* used for context sensitive menu */
960 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
961 frames = get_frames (field);
963 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
966 set (current_time() + frames, true);
967 ValueChanged (); /* EMIT_SIGNAL */
973 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
974 frames = get_frames (field);
976 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
980 if ((double)current_time() - (double)frames < 0.0) {
984 set (current_time() - frames, true);
987 ValueChanged (); /* EMIT_SIGNAL */
1001 AudioClock::field_button_scroll_event (GdkEventScroll *ev, Field field)
1003 if (session == 0) return FALSE;
1005 nframes_t frames = 0;
1007 switch (ev->direction) {
1010 frames = get_frames (field);
1012 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
1015 set (current_time() + frames, true);
1016 ValueChanged (); /* EMIT_SIGNAL */
1020 case GDK_SCROLL_DOWN:
1021 frames = get_frames (field);
1023 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
1027 if ((double)current_time() - (double)frames < 0.0) {
1030 set (current_time() - frames, true);
1033 ValueChanged (); /* EMIT_SIGNAL */
1046 AudioClock::field_motion_notify_event (GdkEventMotion *ev, Field field)
1048 if (session == 0 || !dragging) {
1052 float pixel_frame_scale_factor = 0.2f;
1055 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
1056 pixel_frame_scale_factor = 0.1f;
1060 if (Keyboard::modifier_state_contains (ev->state,
1061 Keyboard::Control|Keyboard::Alt)) {
1063 pixel_frame_scale_factor = 0.025f;
1066 double y_delta = ev->y - drag_y;
1068 drag_accum += y_delta*pixel_frame_scale_factor;
1072 if (trunc(drag_accum) != 0) {
1077 dir = (drag_accum < 0 ? 1:-1);
1078 pos = current_time();
1079 frames = get_frames (field,pos,dir);
1081 if (frames != 0 && frames * drag_accum < current_time()) {
1083 set ((nframes_t) floor (pos - drag_accum * frames), false); // minus because up is negative in computer-land
1091 ValueChanged(); /* EMIT_SIGNAL */
1100 AudioClock::get_frames (Field field,nframes_t pos,int dir)
1103 nframes_t frames = 0;
1107 frames = (nframes_t) floor (3600.0 * session->frame_rate());
1110 frames = (nframes_t) floor (60.0 * session->frame_rate());
1113 frames = session->frame_rate();
1116 frames = (nframes_t) floor (session->frame_rate() / Config->get_smpte_frames_per_second());
1124 frames = (nframes_t) floor (3600.0 * session->frame_rate());
1127 frames = (nframes_t) floor (60.0 * session->frame_rate());
1130 frames = session->frame_rate();
1137 frames = session->tempo_map().bbt_duration_at(pos,bbt,dir);
1143 frames = session->tempo_map().bbt_duration_at(pos,bbt,dir);
1149 frames = session->tempo_map().bbt_duration_at(pos,bbt,dir);
1157 AudioClock::current_time (nframes_t pos) const
1163 ret = smpte_frame_from_display ();
1166 ret = bbt_frame_from_display (pos);
1170 ret = minsec_frame_from_display ();
1174 ret = audio_frame_from_display ();
1185 AudioClock::current_duration (nframes_t pos) const
1191 ret = smpte_frame_from_display ();
1194 ret = bbt_frame_duration_from_display (pos);
1198 ret = minsec_frame_from_display ();
1202 ret = audio_frame_from_display ();
1213 AudioClock::smpte_sanitize_display()
1215 // Check SMPTE fields for sanity, possibly adjusting values
1216 if (atoi(minutes_label.get_text()) > 59) {
1217 minutes_label.set_text("59");
1220 if (atoi(seconds_label.get_text()) > 59) {
1221 seconds_label.set_text("59");
1224 switch ((long)rint(Config->get_smpte_frames_per_second())) {
1226 if (atoi(frames_label.get_text()) > 23) {
1227 frames_label.set_text("23");
1231 if (atoi(frames_label.get_text()) > 24) {
1232 frames_label.set_text("24");
1236 if (atoi(frames_label.get_text()) > 29) {
1237 frames_label.set_text("29");
1244 if (Config->get_smpte_drop_frames()) {
1245 if ((atoi(minutes_label.get_text()) % 10) && (atoi(seconds_label.get_text()) == 0) && (atoi(frames_label.get_text()) < 2)) {
1246 frames_label.set_text("02");
1252 AudioClock::smpte_frame_from_display () const
1261 smpte.hours = atoi (hours_label.get_text());
1262 smpte.minutes = atoi (minutes_label.get_text());
1263 smpte.seconds = atoi (seconds_label.get_text());
1264 smpte.frames = atoi (frames_label.get_text());
1266 session->smpte_to_sample( smpte, sample, false /* use_offset */, false /* use_subframes */ );
1270 #define SMPTE_SAMPLE_TEST_1
1271 #define SMPTE_SAMPLE_TEST_2
1272 #define SMPTE_SAMPLE_TEST_3
1273 #define SMPTE_SAMPLE_TEST_4
1274 #define SMPTE_SAMPLE_TEST_5
1275 #define SMPTE_SAMPLE_TEST_6
1276 #define SMPTE_SAMPLE_TEST_7
1278 // Testcode for smpte<->sample conversions (P.S.)
1281 nframes_t oldsample = 0;
1283 nframes_t sample_increment;
1285 sample_increment = (long)rint(session->frame_rate() / session->smpte_frames_per_second);
1287 #ifdef SMPTE_SAMPLE_TEST_1
1288 // Test 1: use_offset = false, use_subframes = false
1289 cout << "use_offset = false, use_subframes = false" << endl;
1290 for (int i = 0; i < 108003; i++) {
1291 session->smpte_to_sample( smpte1, sample1, false /* use_offset */, false /* use_subframes */ );
1292 session->sample_to_smpte( sample1, smpte2, false /* use_offset */, false /* use_subframes */ );
1294 if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
1295 cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1296 cout << "smpte1: " << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1297 cout << "sample: " << sample1 << endl;
1298 cout << "sample: " << sample1 << " -> ";
1299 cout << "smpte2: " << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1303 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1304 cout << "ERROR: smpte2 not equal smpte1" << endl;
1305 cout << "smpte1: " << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1306 cout << "sample: " << sample1 << endl;
1307 cout << "sample: " << sample1 << " -> ";
1308 cout << "smpte2: " << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1311 oldsample = sample1;
1312 session->smpte_increment( smpte1 );
1315 cout << "sample_increment: " << sample_increment << endl;
1316 cout << "sample: " << sample1 << " -> ";
1317 cout << "smpte: " << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1320 #ifdef SMPTE_SAMPLE_TEST_2
1321 // Test 2: use_offset = true, use_subframes = false
1322 cout << "use_offset = true, use_subframes = false" << endl;
1328 smpte1.subframes = 0;
1329 sample1 = oldsample = 0;
1331 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1332 cout << "Starting at sample: " << sample1 << " -> ";
1333 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1335 for (int i = 0; i < 108003; i++) {
1336 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1337 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1339 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1340 // cout << "sample: " << sample1 << endl;
1341 // cout << "sample: " << sample1 << " -> ";
1342 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1344 if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
1345 cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1346 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1347 cout << "sample: " << sample1 << endl;
1348 cout << "sample: " << sample1 << " -> ";
1349 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1353 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1354 cout << "ERROR: smpte2 not equal smpte1" << endl;
1355 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1356 cout << "sample: " << sample1 << endl;
1357 cout << "sample: " << sample1 << " -> ";
1358 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1361 oldsample = sample1;
1362 session->smpte_increment( smpte1 );
1365 cout << "sample_increment: " << sample_increment << endl;
1366 cout << "sample: " << sample1 << " -> ";
1367 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1370 #ifdef SMPTE_SAMPLE_TEST_3
1371 // Test 3: use_offset = true, use_subframes = false, decrement
1372 cout << "use_offset = true, use_subframes = false, decrement" << endl;
1374 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1375 cout << "Starting at sample: " << sample1 << " -> ";
1376 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1378 for (int i = 0; i < 108003; i++) {
1379 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1380 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1382 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1383 // cout << "sample: " << sample1 << endl;
1384 // cout << "sample: " << sample1 << " -> ";
1385 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1387 if ((i > 0) && ( ((oldsample - sample1) != sample_increment) && ((oldsample - sample1) != (sample_increment + 1)) && ((oldsample - sample1) != (sample_increment - 1)))) {
1388 cout << "ERROR: sample increment not right: " << (oldsample - sample1) << " != " << sample_increment << endl;
1389 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1390 cout << "sample: " << sample1 << endl;
1391 cout << "sample: " << sample1 << " -> ";
1392 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1396 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1397 cout << "ERROR: smpte2 not equal smpte1" << endl;
1398 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1399 cout << "sample: " << sample1 << endl;
1400 cout << "sample: " << sample1 << " -> ";
1401 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1404 oldsample = sample1;
1405 session->smpte_decrement( smpte1 );
1408 cout << "sample_decrement: " << sample_increment << endl;
1409 cout << "sample: " << sample1 << " -> ";
1410 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1414 #ifdef SMPTE_SAMPLE_TEST_4
1415 // Test 4: use_offset = true, use_subframes = true
1416 cout << "use_offset = true, use_subframes = true" << endl;
1418 for (long sub = 5; sub < 80; sub += 5) {
1423 smpte1.subframes = 0;
1424 sample1 = oldsample = (sample_increment * sub) / 80;
1426 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, true /* use_subframes */ );
1428 cout << "starting at sample: " << sample1 << " -> ";
1429 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1431 for (int i = 0; i < 108003; i++) {
1432 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, true /* use_subframes */ );
1433 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, true /* use_subframes */ );
1435 if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
1436 cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1437 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1438 cout << "sample: " << sample1 << endl;
1439 cout << "sample: " << sample1 << " -> ";
1440 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1444 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames || smpte2.subframes != smpte1.subframes) {
1445 cout << "ERROR: smpte2 not equal smpte1" << endl;
1446 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1447 cout << "sample: " << sample1 << endl;
1448 cout << "sample: " << sample1 << " -> ";
1449 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1452 oldsample = sample1;
1453 session->smpte_increment( smpte1 );
1456 cout << "sample_increment: " << sample_increment << endl;
1457 cout << "sample: " << sample1 << " -> ";
1458 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1460 for (int i = 0; i < 108003; i++) {
1461 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, true /* use_subframes */ );
1462 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, true /* use_subframes */ );
1464 if ((i > 0) && ( ((oldsample - sample1) != sample_increment) && ((oldsample - sample1) != (sample_increment + 1)) && ((oldsample - sample1) != (sample_increment - 1)))) {
1465 cout << "ERROR: sample increment not right: " << (oldsample - sample1) << " != " << sample_increment << endl;
1466 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1467 cout << "sample: " << sample1 << endl;
1468 cout << "sample: " << sample1 << " -> ";
1469 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1473 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames || smpte2.subframes != smpte1.subframes) {
1474 cout << "ERROR: smpte2 not equal smpte1" << endl;
1475 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1476 cout << "sample: " << sample1 << endl;
1477 cout << "sample: " << sample1 << " -> ";
1478 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1481 oldsample = sample1;
1482 session->smpte_decrement( smpte1 );
1485 cout << "sample_decrement: " << sample_increment << endl;
1486 cout << "sample: " << sample1 << " -> ";
1487 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1492 #ifdef SMPTE_SAMPLE_TEST_5
1493 // Test 5: use_offset = true, use_subframes = false, increment seconds
1494 cout << "use_offset = true, use_subframes = false, increment seconds" << endl;
1500 smpte1.subframes = 0;
1501 sample1 = oldsample = 0;
1502 sample_increment = session->frame_rate();
1504 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1505 cout << "Starting at sample: " << sample1 << " -> ";
1506 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1508 for (int i = 0; i < 3600; i++) {
1509 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1510 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1512 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1513 // cout << "sample: " << sample1 << endl;
1514 // cout << "sample: " << sample1 << " -> ";
1515 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1517 // if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1519 // cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1523 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1524 cout << "ERROR: smpte2 not equal smpte1" << endl;
1525 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1526 cout << "sample: " << sample1 << endl;
1527 cout << "sample: " << sample1 << " -> ";
1528 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1531 oldsample = sample1;
1532 session->smpte_increment_seconds( smpte1 );
1535 cout << "sample_increment: " << sample_increment << endl;
1536 cout << "sample: " << sample1 << " -> ";
1537 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1541 #ifdef SMPTE_SAMPLE_TEST_6
1542 // Test 6: use_offset = true, use_subframes = false, increment minutes
1543 cout << "use_offset = true, use_subframes = false, increment minutes" << endl;
1549 smpte1.subframes = 0;
1550 sample1 = oldsample = 0;
1551 sample_increment = session->frame_rate() * 60;
1553 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1554 cout << "Starting at sample: " << sample1 << " -> ";
1555 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1557 for (int i = 0; i < 60; i++) {
1558 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1559 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1561 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1562 // cout << "sample: " << sample1 << endl;
1563 // cout << "sample: " << sample1 << " -> ";
1564 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1566 // if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1568 // cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1572 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1573 cout << "ERROR: smpte2 not equal smpte1" << endl;
1574 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1575 cout << "sample: " << sample1 << endl;
1576 cout << "sample: " << sample1 << " -> ";
1577 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1580 oldsample = sample1;
1581 session->smpte_increment_minutes( smpte1 );
1584 cout << "sample_increment: " << sample_increment << endl;
1585 cout << "sample: " << sample1 << " -> ";
1586 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1589 #ifdef SMPTE_SAMPLE_TEST_7
1590 // Test 7: use_offset = true, use_subframes = false, increment hours
1591 cout << "use_offset = true, use_subframes = false, increment hours" << endl;
1597 smpte1.subframes = 0;
1598 sample1 = oldsample = 0;
1599 sample_increment = session->frame_rate() * 60 * 60;
1601 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1602 cout << "Starting at sample: " << sample1 << " -> ";
1603 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1605 for (int i = 0; i < 10; i++) {
1606 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1607 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1609 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1610 // cout << "sample: " << sample1 << endl;
1611 // cout << "sample: " << sample1 << " -> ";
1612 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1614 // if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1616 // cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1620 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1621 cout << "ERROR: smpte2 not equal smpte1" << endl;
1622 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1623 cout << "sample: " << sample1 << endl;
1624 cout << "sample: " << sample1 << " -> ";
1625 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1628 oldsample = sample1;
1629 session->smpte_increment_hours( smpte1 );
1632 cout << "sample_increment: " << sample_increment << endl;
1633 cout << "sample: " << sample1 << " -> ";
1634 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1643 AudioClock::minsec_frame_from_display () const
1649 int hrs = atoi (ms_hours_label.get_text());
1650 int mins = atoi (ms_minutes_label.get_text());
1651 float secs = atof (ms_seconds_label.get_text());
1653 nframes_t sr = session->frame_rate();
1655 return (nframes_t) floor ((hrs * 60.0f * 60.0f * sr) + (mins * 60.0f * sr) + (secs * sr));
1659 AudioClock::bbt_frame_from_display (nframes_t pos) const
1662 error << "AudioClock::current_time() called with BBT mode but without session!" << endmsg;
1667 any.type = AnyTime::BBT;
1669 any.bbt.bars = atoi (bars_label.get_text());
1670 any.bbt.beats = atoi (beats_label.get_text());
1671 any.bbt.ticks = atoi (ticks_label.get_text());
1673 nframes_t ret = session->convert_to_frames_at (pos, any);
1680 AudioClock::bbt_frame_duration_from_display (nframes_t pos) const
1683 error << "AudioClock::current_time() called with BBT mode but without session!" << endmsg;
1690 bbt.bars = atoi (bars_label.get_text());
1691 bbt.beats = atoi (beats_label.get_text());
1692 bbt.ticks = atoi (ticks_label.get_text());
1694 return session->tempo_map().bbt_duration_at(pos,bbt,1);
1698 AudioClock::audio_frame_from_display () const
1700 return (nframes_t) atoi (audio_frames_label.get_text());
1704 AudioClock::build_ops_menu ()
1706 using namespace Menu_Helpers;
1707 ops_menu = new Menu;
1708 MenuList& ops_items = ops_menu->items();
1709 ops_menu->set_name ("ArdourContextMenu");
1711 Menu *mode_menu = manage (new Menu);
1712 MenuList& mode_items = mode_menu->items();
1713 mode_menu->set_name ("ArdourContextMenu");
1715 mode_items.push_back (MenuElem (_("Timecode"), bind (mem_fun(*this, &AudioClock::set_mode), SMPTE)));
1716 mode_items.push_back (MenuElem (_("Bars:Beats"), bind (mem_fun(*this, &AudioClock::set_mode), BBT)));
1717 mode_items.push_back (MenuElem (_("Minutes:Seconds"), bind (mem_fun(*this, &AudioClock::set_mode), MinSec)));
1718 mode_items.push_back (MenuElem (_("Audio Frames"), bind (mem_fun(*this, &AudioClock::set_mode), Frames)));
1719 mode_items.push_back (MenuElem (_("Off"), bind (mem_fun(*this, &AudioClock::set_mode), Off)));
1721 ops_items.push_back (MenuElem (_("Mode"), *mode_menu));
1725 AudioClock::set_mode (Mode m)
1727 /* slightly tricky: this is called from within the ARDOUR_UI
1728 constructor by some of its clock members. at that time
1729 the instance pointer is unset, so we have to be careful.
1730 the main idea is to drop keyboard focus in case we had
1731 started editing the clock and then we switch clock mode.
1734 clock_base.grab_focus ();
1744 clock_base.remove ();
1754 clock_base.add (smpte_packer_hbox);
1758 clock_base.add (bbt_packer_hbox);
1762 clock_base.add (minsec_packer_hbox);
1766 clock_base.add (frames_packer_hbox);
1773 set_size_requests ();
1775 set (last_when, true);
1776 clock_base.show_all ();
1777 key_entry_state = 0;
1781 AudioClock::set_size_requests ()
1783 /* note that in some fonts, "88" is narrower than "00", hence the 2 pixel padding */
1787 Gtkmm2ext::set_size_request_to_display_given_text (hours_label, "-88", 2, 2);
1788 Gtkmm2ext::set_size_request_to_display_given_text (minutes_label, "88", 2, 2);
1789 Gtkmm2ext::set_size_request_to_display_given_text (seconds_label, "88", 2, 2);
1790 Gtkmm2ext::set_size_request_to_display_given_text (frames_label, "88", 2, 2);
1794 Gtkmm2ext::set_size_request_to_display_given_text (bars_label, "-888", 2, 2);
1795 Gtkmm2ext::set_size_request_to_display_given_text (beats_label, "88", 2, 2);
1796 Gtkmm2ext::set_size_request_to_display_given_text (ticks_label, "8888", 2, 2);
1800 Gtkmm2ext::set_size_request_to_display_given_text (ms_hours_label, "99", 2, 2);
1801 Gtkmm2ext::set_size_request_to_display_given_text (ms_minutes_label, "99", 2, 2);
1802 Gtkmm2ext::set_size_request_to_display_given_text (ms_seconds_label, "99.999", 2, 2);
1806 Gtkmm2ext::set_size_request_to_display_given_text (audio_frames_label, "4294967296", 2, 2);