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.
20 #include <cstdio> // for sprintf
23 #include <pbd/convert.h>
24 #include <pbd/enumwriter.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;
48 sigc::signal<void> AudioClock::ModeChanged;
49 vector<AudioClock*> AudioClock::clocks;
51 const uint32_t AudioClock::field_length[(int) AudioClock::AudioFrames+1] = {
53 2, /* SMPTE_Minutes */
54 2, /* SMPTE_Seconds */
65 AudioClock::AudioClock (std::string clock_name, bool transient, std::string widget_name, bool allow_edit, bool duration, bool with_info)
67 is_transient (transient),
68 is_duration (duration),
69 editable (allow_edit),
87 frames_upper_info_label = manage (new Label);
88 frames_lower_info_label = manage (new Label);
89 smpte_upper_info_label = manage (new Label);
90 smpte_lower_info_label = manage (new Label);
91 bbt_upper_info_label = manage (new Label);
92 bbt_lower_info_label = manage (new Label);
94 frames_upper_info_label->set_name ("AudioClockFramesUpperInfo");
95 frames_lower_info_label->set_name ("AudioClockFramesLowerInfo");
96 smpte_upper_info_label->set_name ("AudioClockSMPTEUpperInfo");
97 smpte_lower_info_label->set_name ("AudioClockSMPTELowerInfo");
98 bbt_upper_info_label->set_name ("AudioClockBBTUpperInfo");
99 bbt_lower_info_label->set_name ("AudioClockBBTLowerInfo");
101 Gtkmm2ext::set_size_request_to_display_given_text(*smpte_upper_info_label, "23.98",0,0);
102 Gtkmm2ext::set_size_request_to_display_given_text(*smpte_lower_info_label, "NDF",0,0);
104 frames_info_box.pack_start (*frames_upper_info_label, true, true);
105 frames_info_box.pack_start (*frames_lower_info_label, true, true);
106 smpte_info_box.pack_start (*smpte_upper_info_label, true, true);
107 smpte_info_box.pack_start (*smpte_lower_info_label, true, true);
108 bbt_info_box.pack_start (*bbt_upper_info_label, true, true);
109 bbt_info_box.pack_start (*bbt_lower_info_label, true, true);
112 frames_upper_info_label = 0;
113 frames_lower_info_label = 0;
114 smpte_upper_info_label = 0;
115 smpte_lower_info_label = 0;
116 bbt_upper_info_label = 0;
117 bbt_lower_info_label = 0;
120 audio_frames_ebox.add (audio_frames_label);
122 frames_packer.set_homogeneous (false);
123 frames_packer.set_border_width (2);
124 frames_packer.pack_start (audio_frames_ebox, false, false);
127 frames_packer.pack_start (frames_info_box, false, false, 5);
130 frames_packer_hbox.pack_start (frames_packer, true, false);
132 hours_ebox.add (hours_label);
133 minutes_ebox.add (minutes_label);
134 seconds_ebox.add (seconds_label);
135 frames_ebox.add (frames_label);
136 bars_ebox.add (bars_label);
137 beats_ebox.add (beats_label);
138 ticks_ebox.add (ticks_label);
139 ms_hours_ebox.add (ms_hours_label);
140 ms_minutes_ebox.add (ms_minutes_label);
141 ms_seconds_ebox.add (ms_seconds_label);
143 smpte_packer.set_homogeneous (false);
144 smpte_packer.set_border_width (2);
145 smpte_packer.pack_start (hours_ebox, false, false);
146 smpte_packer.pack_start (colon1, false, false);
147 smpte_packer.pack_start (minutes_ebox, false, false);
148 smpte_packer.pack_start (colon2, false, false);
149 smpte_packer.pack_start (seconds_ebox, false, false);
150 smpte_packer.pack_start (colon3, false, false);
151 smpte_packer.pack_start (frames_ebox, false, false);
154 smpte_packer.pack_start (smpte_info_box, false, false, 5);
157 smpte_packer_hbox.pack_start (smpte_packer, true, false);
159 bbt_packer.set_homogeneous (false);
160 bbt_packer.set_border_width (2);
161 bbt_packer.pack_start (bars_ebox, false, false);
162 bbt_packer.pack_start (b1, false, false);
163 bbt_packer.pack_start (beats_ebox, false, false);
164 bbt_packer.pack_start (b2, false, false);
165 bbt_packer.pack_start (ticks_ebox, false, false);
168 bbt_packer.pack_start (bbt_info_box, false, false, 5);
171 bbt_packer_hbox.pack_start (bbt_packer, true, false);
173 minsec_packer.set_homogeneous (false);
174 minsec_packer.set_border_width (2);
175 minsec_packer.pack_start (ms_hours_ebox, false, false);
176 minsec_packer.pack_start (colon4, false, false);
177 minsec_packer.pack_start (ms_minutes_ebox, false, false);
178 minsec_packer.pack_start (colon5, false, false);
179 minsec_packer.pack_start (ms_seconds_ebox, false, false);
181 minsec_packer_hbox.pack_start (minsec_packer, true, false);
183 clock_frame.set_shadow_type (Gtk::SHADOW_IN);
184 clock_frame.set_name ("BaseFrame");
186 clock_frame.add (clock_base);
188 set_widget_name (widget_name);
190 _mode = BBT; /* lie to force mode switch */
193 pack_start (clock_frame, true, true);
195 /* the clock base handles button releases for menu popup regardless of
196 editable status. if the clock is editable, the clock base is where
197 we pass focus to after leaving the last editable "field", which
198 will then shutdown editing till the user starts it up again.
200 it does this because the focus out event on the field disables
201 keyboard event handling, and we don't connect anything up to
202 notice focus in on the clock base. hence, keyboard event handling
206 clock_base.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::SCROLL_MASK);
207 clock_base.signal_button_release_event().connect (bind (mem_fun (*this, &AudioClock::field_button_release_event), SMPTE_Hours));
209 Session::SMPTEOffsetChanged.connect (mem_fun (*this, &AudioClock::smpte_offset_changed));
215 set (last_when, true);
218 clocks.push_back (this);
223 AudioClock::set_widget_name (string name)
225 Widget::set_name (name);
227 clock_base.set_name (name);
229 audio_frames_label.set_name (name);
230 hours_label.set_name (name);
231 minutes_label.set_name (name);
232 seconds_label.set_name (name);
233 frames_label.set_name (name);
234 bars_label.set_name (name);
235 beats_label.set_name (name);
236 ticks_label.set_name (name);
237 ms_hours_label.set_name (name);
238 ms_minutes_label.set_name (name);
239 ms_seconds_label.set_name (name);
240 hours_ebox.set_name (name);
241 minutes_ebox.set_name (name);
242 seconds_ebox.set_name (name);
243 frames_ebox.set_name (name);
244 audio_frames_ebox.set_name (name);
245 bars_ebox.set_name (name);
246 beats_ebox.set_name (name);
247 ticks_ebox.set_name (name);
248 ms_hours_ebox.set_name (name);
249 ms_minutes_ebox.set_name (name);
250 ms_seconds_ebox.set_name (name);
252 colon1.set_name (name);
253 colon2.set_name (name);
254 colon3.set_name (name);
255 colon4.set_name (name);
256 colon5.set_name (name);
264 AudioClock::setup_events ()
266 clock_base.set_flags (Gtk::CAN_FOCUS);
268 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);
269 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);
270 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);
271 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);
272 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);
273 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);
274 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);
275 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);
276 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);
277 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);
278 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);
280 hours_ebox.set_flags (Gtk::CAN_FOCUS);
281 minutes_ebox.set_flags (Gtk::CAN_FOCUS);
282 seconds_ebox.set_flags (Gtk::CAN_FOCUS);
283 frames_ebox.set_flags (Gtk::CAN_FOCUS);
284 audio_frames_ebox.set_flags (Gtk::CAN_FOCUS);
285 bars_ebox.set_flags (Gtk::CAN_FOCUS);
286 beats_ebox.set_flags (Gtk::CAN_FOCUS);
287 ticks_ebox.set_flags (Gtk::CAN_FOCUS);
288 ms_hours_ebox.set_flags (Gtk::CAN_FOCUS);
289 ms_minutes_ebox.set_flags (Gtk::CAN_FOCUS);
290 ms_seconds_ebox.set_flags (Gtk::CAN_FOCUS);
292 hours_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), SMPTE_Hours));
293 minutes_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), SMPTE_Minutes));
294 seconds_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), SMPTE_Seconds));
295 frames_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), SMPTE_Frames));
296 audio_frames_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), AudioFrames));
297 bars_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), Bars));
298 beats_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), Beats));
299 ticks_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), Ticks));
300 ms_hours_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), MS_Hours));
301 ms_minutes_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), MS_Minutes));
302 ms_seconds_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), MS_Seconds));
304 hours_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), SMPTE_Hours));
305 minutes_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), SMPTE_Minutes));
306 seconds_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), SMPTE_Seconds));
307 frames_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), SMPTE_Frames));
308 audio_frames_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), AudioFrames));
309 bars_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), Bars));
310 beats_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), Beats));
311 ticks_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), Ticks));
312 ms_hours_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), MS_Hours));
313 ms_minutes_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), MS_Minutes));
314 ms_seconds_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), MS_Seconds));
316 hours_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), SMPTE_Hours));
317 minutes_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), SMPTE_Minutes));
318 seconds_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), SMPTE_Seconds));
319 frames_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), SMPTE_Frames));
320 audio_frames_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), AudioFrames));
321 bars_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), Bars));
322 beats_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), Beats));
323 ticks_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), Ticks));
324 ms_hours_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), MS_Hours));
325 ms_minutes_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), MS_Minutes));
326 ms_seconds_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), MS_Seconds));
328 hours_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), SMPTE_Hours));
329 minutes_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), SMPTE_Minutes));
330 seconds_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), SMPTE_Seconds));
331 frames_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), SMPTE_Frames));
332 audio_frames_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), AudioFrames));
333 bars_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), Bars));
334 beats_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), Beats));
335 ticks_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), Ticks));
336 ms_hours_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), MS_Hours));
337 ms_minutes_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), MS_Minutes));
338 ms_seconds_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), MS_Seconds));
340 hours_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), SMPTE_Hours));
341 minutes_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), SMPTE_Minutes));
342 seconds_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), SMPTE_Seconds));
343 frames_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), SMPTE_Frames));
344 audio_frames_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), AudioFrames));
345 bars_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), Bars));
346 beats_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), Beats));
347 ticks_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), Ticks));
348 ms_hours_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), MS_Hours));
349 ms_minutes_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), MS_Minutes));
350 ms_seconds_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), MS_Seconds));
352 hours_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), SMPTE_Hours));
353 minutes_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), SMPTE_Minutes));
354 seconds_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), SMPTE_Seconds));
355 frames_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), SMPTE_Frames));
356 audio_frames_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), AudioFrames));
357 bars_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), Bars));
358 beats_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), Beats));
359 ticks_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), Ticks));
360 ms_hours_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), MS_Hours));
361 ms_minutes_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), MS_Minutes));
362 ms_seconds_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), MS_Seconds));
364 hours_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), SMPTE_Hours));
365 minutes_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), SMPTE_Minutes));
366 seconds_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), SMPTE_Seconds));
367 frames_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), SMPTE_Frames));
368 audio_frames_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), AudioFrames));
369 bars_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), Bars));
370 beats_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), Beats));
371 ticks_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), Ticks));
372 ms_hours_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), MS_Hours));
373 ms_minutes_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), MS_Minutes));
374 ms_seconds_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), MS_Seconds));
378 AudioClock::on_realize ()
382 /* styles are not available until the widgets are bound to a window */
384 set_size_requests ();
388 AudioClock::set (nframes_t when, bool force, nframes_t offset, char which)
391 if ((!force && !is_visible()) || session == 0) {
395 if (when == last_when && !offset && !force) {
399 bool pdelta = Config->get_primary_clock_delta_edit_cursor();
400 bool sdelta = Config->get_secondary_clock_delta_edit_cursor();
402 if (offset && which == 'p' && pdelta) {
403 when = (when > offset) ? when - offset : offset - when;
404 } else if (offset && which == 's' && sdelta) {
405 when = (when > offset) ? when - offset : offset - when;
408 if (which == 'p' && pdelta && !last_pdelta) {
409 set_widget_name("TransportClockDisplayDelta");
411 } else if (which == 'p' && !pdelta && last_pdelta) {
412 set_widget_name("TransportClockDisplay");
414 } else if (which == 's' && sdelta && !last_sdelta) {
415 set_widget_name("SecondaryClockDisplayDelta");
417 } else if (which == 's' && !sdelta && last_sdelta) {
418 set_widget_name("SecondaryClockDisplay");
424 set_smpte (when, force);
428 set_bbt (when, force);
432 set_minsec (when, force);
436 set_frames (when, force);
447 AudioClock::smpte_offset_changed ()
454 current = current_duration();
456 current = current_time ();
466 AudioClock::set_frames (nframes_t when, bool force)
469 snprintf (buf, sizeof (buf), "%u", when);
470 audio_frames_label.set_text (buf);
472 if (frames_upper_info_label) {
473 nframes_t rate = session->frame_rate();
475 if (fmod (rate, 1000.0) == 0.000) {
476 sprintf (buf, "%uK", rate/1000);
478 sprintf (buf, "%.3fK", rate/1000.0f);
481 frames_upper_info_label->set_text (buf);
483 float vid_pullup = Config->get_video_pullup();
485 if (vid_pullup == 0.0) {
486 frames_lower_info_label->set_text(_("none"));
488 sprintf (buf, "%-6.4f", vid_pullup);
489 frames_lower_info_label->set_text (buf);
495 AudioClock::set_minsec (nframes_t when, bool force)
504 hrs = (int) floor (left / (session->frame_rate() * 60.0f * 60.0f));
505 left -= (nframes_t) floor (hrs * session->frame_rate() * 60.0f * 60.0f);
506 mins = (int) floor (left / (session->frame_rate() * 60.0f));
507 left -= (nframes_t) floor (mins * session->frame_rate() * 60.0f);
508 secs = left / (float) session->frame_rate();
510 if (force || hrs != ms_last_hrs) {
511 sprintf (buf, "%02d", hrs);
512 ms_hours_label.set_text (buf);
516 if (force || mins != ms_last_mins) {
517 sprintf (buf, "%02d", mins);
518 ms_minutes_label.set_text (buf);
522 if (force || secs != ms_last_secs) {
523 sprintf (buf, "%06.3f", secs);
524 ms_seconds_label.set_text (buf);
530 AudioClock::set_smpte (nframes_t when, bool force)
536 session->smpte_duration (when, smpte);
538 session->smpte_time (when, smpte);
541 if (force || smpte.hours != last_hrs || smpte.negative != last_negative) {
542 if (smpte.negative) {
543 sprintf (buf, "-%02" PRIu32, smpte.hours);
545 sprintf (buf, " %02" PRIu32, smpte.hours);
547 hours_label.set_text (buf);
548 last_hrs = smpte.hours;
549 last_negative = smpte.negative;
552 if (force || smpte.minutes != last_mins) {
553 sprintf (buf, "%02" PRIu32, smpte.minutes);
554 minutes_label.set_text (buf);
555 last_mins = smpte.minutes;
558 if (force || smpte.seconds != last_secs) {
559 sprintf (buf, "%02" PRIu32, smpte.seconds);
560 seconds_label.set_text (buf);
561 last_secs = smpte.seconds;
564 if (force || smpte.frames != last_frames) {
565 sprintf (buf, "%02" PRIu32, smpte.frames);
566 frames_label.set_text (buf);
567 last_frames = smpte.frames;
570 if (smpte_upper_info_label) {
571 double smpte_frames = session->smpte_frames_per_second();
573 if ( fmod(smpte_frames, 1.0) == 0.0) {
574 sprintf (buf, "%u", int (smpte_frames));
576 sprintf (buf, "%.2f", smpte_frames);
579 smpte_upper_info_label->set_text (buf);
581 if (session->smpte_drop_frames()) {
584 sprintf (buf, "NDF");
587 smpte_lower_info_label->set_text (buf);
592 AudioClock::set_bbt (nframes_t when, bool force)
597 session->tempo_map().bbt_time (when, bbt);
598 sprintf (buf, "%03" PRIu32, bbt.bars);
599 bars_label.set_text (buf);
600 sprintf (buf, "%02" PRIu32, bbt.beats);
601 beats_label.set_text (buf);
602 sprintf (buf, "%04" PRIu32, bbt.ticks);
603 ticks_label.set_text (buf);
605 if (bbt_upper_info_label) {
606 TempoMap::Metric m (session->tempo_map().metric_at (when));
607 sprintf (buf, "%-5.2f", m.tempo().beats_per_minute());
608 bbt_lower_info_label->set_text (buf);
609 sprintf (buf, "%g|%g", m.meter().beats_per_bar(), m.meter().note_divisor());
610 bbt_upper_info_label->set_text (buf);
615 AudioClock::set_session (Session *s)
622 XMLNode* node = session->extra_xml (X_("ClockModes"));
623 AudioClock::Mode amode;
626 if ((prop = node->property (_name)) != 0) {
627 amode = AudioClock::Mode (string_2_enum (prop->value(), amode));
632 set (last_when, true);
637 AudioClock::field_key_release_event (GdkEventKey *ev, Field field)
642 bool move_on = false;
646 label = &hours_label;
649 label = &minutes_label;
652 label = &seconds_label;
655 label = &frames_label;
659 label = &audio_frames_label;
663 label = &ms_hours_label;
666 label = &ms_minutes_label;
669 label = &ms_seconds_label;
676 label = &beats_label;
679 label = &ticks_label;
685 switch (ev->keyval) {
729 if (_mode == MinSec && field == MS_Seconds) {
743 clock_base.grab_focus ();
752 if (key_entry_state == 0) {
754 /* initialize with a fresh new string */
756 if (field != AudioFrames) {
757 for (uint32_t xn = 0; xn < field_length[field] - 1; ++xn) {
766 string existing = label->get_text();
767 if (existing.length() >= field_length[field]) {
768 new_text = existing.substr (1, field_length[field] - 1);
770 new_text = existing.substr (0, field_length[field] - 1);
774 new_text += new_char;
775 label->set_text (new_text);
779 if (key_entry_state == field_length[field]) {
785 if (key_entry_state) {
792 // Check SMPTE fields for sanity (may also adjust fields)
793 smpte_sanitize_display();
798 // Bars or beats should never be 0
799 if (atoi(bars_label.get_text()) == 0) {
800 bars_label.set_text("001");
802 if (atoi(beats_label.get_text()) == 0) {
803 beats_label.set_text("01");
810 ValueChanged(); /* EMIT_SIGNAL */
813 /* move on to the next field.
821 minutes_ebox.grab_focus ();
824 seconds_ebox.grab_focus ();
827 frames_ebox.grab_focus ();
830 clock_base.grab_focus ();
835 clock_base.grab_focus ();
841 ms_minutes_ebox.grab_focus ();
844 ms_seconds_ebox.grab_focus ();
847 clock_base.grab_focus ();
853 beats_ebox.grab_focus ();
856 ticks_ebox.grab_focus ();
859 clock_base.grab_focus ();
872 AudioClock::field_focus_in_event (GdkEventFocus *ev, Field field)
878 hours_ebox.set_flags (Gtk::HAS_FOCUS);
879 hours_ebox.set_state (Gtk::STATE_ACTIVE);
882 minutes_ebox.set_flags (Gtk::HAS_FOCUS);
883 minutes_ebox.set_state (Gtk::STATE_ACTIVE);
886 seconds_ebox.set_flags (Gtk::HAS_FOCUS);
887 seconds_ebox.set_state (Gtk::STATE_ACTIVE);
890 frames_ebox.set_flags (Gtk::HAS_FOCUS);
891 frames_ebox.set_state (Gtk::STATE_ACTIVE);
895 audio_frames_ebox.set_flags (Gtk::HAS_FOCUS);
896 audio_frames_ebox.set_state (Gtk::STATE_ACTIVE);
900 ms_hours_ebox.set_flags (Gtk::HAS_FOCUS);
901 ms_hours_ebox.set_state (Gtk::STATE_ACTIVE);
904 ms_minutes_ebox.set_flags (Gtk::HAS_FOCUS);
905 ms_minutes_ebox.set_state (Gtk::STATE_ACTIVE);
908 ms_seconds_ebox.set_flags (Gtk::HAS_FOCUS);
909 ms_seconds_ebox.set_state (Gtk::STATE_ACTIVE);
912 bars_ebox.set_flags (Gtk::HAS_FOCUS);
913 bars_ebox.set_state (Gtk::STATE_ACTIVE);
916 beats_ebox.set_flags (Gtk::HAS_FOCUS);
917 beats_ebox.set_state (Gtk::STATE_ACTIVE);
920 ticks_ebox.set_flags (Gtk::HAS_FOCUS);
921 ticks_ebox.set_state (Gtk::STATE_ACTIVE);
929 AudioClock::field_focus_out_event (GdkEventFocus *ev, Field field)
934 hours_ebox.unset_flags (Gtk::HAS_FOCUS);
935 hours_ebox.set_state (Gtk::STATE_NORMAL);
938 minutes_ebox.unset_flags (Gtk::HAS_FOCUS);
939 minutes_ebox.set_state (Gtk::STATE_NORMAL);
942 seconds_ebox.unset_flags (Gtk::HAS_FOCUS);
943 seconds_ebox.set_state (Gtk::STATE_NORMAL);
946 frames_ebox.unset_flags (Gtk::HAS_FOCUS);
947 frames_ebox.set_state (Gtk::STATE_NORMAL);
951 audio_frames_ebox.unset_flags (Gtk::HAS_FOCUS);
952 audio_frames_ebox.set_state (Gtk::STATE_NORMAL);
956 ms_hours_ebox.unset_flags (Gtk::HAS_FOCUS);
957 ms_hours_ebox.set_state (Gtk::STATE_NORMAL);
960 ms_minutes_ebox.unset_flags (Gtk::HAS_FOCUS);
961 ms_minutes_ebox.set_state (Gtk::STATE_NORMAL);
964 ms_seconds_ebox.unset_flags (Gtk::HAS_FOCUS);
965 ms_seconds_ebox.set_state (Gtk::STATE_NORMAL);
969 bars_ebox.unset_flags (Gtk::HAS_FOCUS);
970 bars_ebox.set_state (Gtk::STATE_NORMAL);
973 beats_ebox.unset_flags (Gtk::HAS_FOCUS);
974 beats_ebox.set_state (Gtk::STATE_NORMAL);
977 ticks_ebox.unset_flags (Gtk::HAS_FOCUS);
978 ticks_ebox.set_state (Gtk::STATE_NORMAL);
986 AudioClock::field_button_release_event (GdkEventButton *ev, Field field)
991 gdk_pointer_ungrab(GDK_CURRENT_TIME);
993 if (ev->y > drag_start_y+1 || ev->y < drag_start_y-1 || Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)){
994 // we actually dragged so return without setting editing focus, or we shift clicked
1001 if (ops_menu == 0) {
1004 ops_menu->popup (1, ev->time);
1008 if (Keyboard::is_context_menu_event (ev)) {
1009 if (ops_menu == 0) {
1012 ops_menu->popup (1, ev->time);
1016 switch (ev->button) {
1020 hours_ebox.grab_focus();
1023 minutes_ebox.grab_focus();
1026 seconds_ebox.grab_focus();
1029 frames_ebox.grab_focus();
1033 audio_frames_ebox.grab_focus();
1037 ms_hours_ebox.grab_focus();
1040 ms_minutes_ebox.grab_focus();
1043 ms_seconds_ebox.grab_focus();
1047 bars_ebox.grab_focus ();
1050 beats_ebox.grab_focus ();
1053 ticks_ebox.grab_focus ();
1066 AudioClock::field_button_press_event (GdkEventButton *ev, Field field)
1068 if (session == 0) return FALSE;
1070 nframes_t frames = 0;
1072 switch (ev->button) {
1074 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
1076 ValueChanged (); /* EMIT_SIGNAL */
1079 /* make absolutely sure that the pointer is grabbed */
1080 gdk_pointer_grab(ev->window,FALSE ,
1081 GdkEventMask( Gdk::POINTER_MOTION_MASK | Gdk::BUTTON_PRESS_MASK |Gdk::BUTTON_RELEASE_MASK),
1082 NULL,NULL,ev->time);
1085 drag_start_y = ev->y;
1090 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
1092 ValueChanged (); /* EMIT_SIGNAL */
1097 /* used for context sensitive menu */
1110 AudioClock::field_button_scroll_event (GdkEventScroll *ev, Field field)
1112 if (session == 0) return FALSE;
1114 nframes_t frames = 0;
1116 switch (ev->direction) {
1119 frames = get_frames (field);
1121 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
1124 set (current_time() + frames, true);
1125 ValueChanged (); /* EMIT_SIGNAL */
1129 case GDK_SCROLL_DOWN:
1130 frames = get_frames (field);
1132 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
1136 if ((double)current_time() - (double)frames < 0.0) {
1139 set (current_time() - frames, true);
1142 ValueChanged (); /* EMIT_SIGNAL */
1155 AudioClock::field_motion_notify_event (GdkEventMotion *ev, Field field)
1157 if (session == 0 || !dragging) {
1161 float pixel_frame_scale_factor = 0.2f;
1164 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
1165 pixel_frame_scale_factor = 0.1f;
1169 if (Keyboard::modifier_state_contains (ev->state,
1170 Keyboard::Control|Keyboard::Alt)) {
1172 pixel_frame_scale_factor = 0.025f;
1175 double y_delta = ev->y - drag_y;
1177 drag_accum += y_delta*pixel_frame_scale_factor;
1181 if (trunc(drag_accum) != 0) {
1186 dir = (drag_accum < 0 ? 1:-1);
1187 pos = current_time();
1188 frames = get_frames (field,pos,dir);
1190 if (frames != 0 && frames * drag_accum < current_time()) {
1192 set ((nframes_t) floor (pos - drag_accum * frames), false); // minus because up is negative in computer-land
1200 ValueChanged(); /* EMIT_SIGNAL */
1209 AudioClock::get_frames (Field field,nframes_t pos,int dir)
1212 nframes_t frames = 0;
1216 frames = (nframes_t) floor (3600.0 * session->frame_rate());
1219 frames = (nframes_t) floor (60.0 * session->frame_rate());
1222 frames = session->frame_rate();
1225 frames = (nframes_t) floor (session->frame_rate() / session->smpte_frames_per_second());
1233 frames = (nframes_t) floor (3600.0 * session->frame_rate());
1236 frames = (nframes_t) floor (60.0 * session->frame_rate());
1239 frames = session->frame_rate();
1246 frames = session->tempo_map().bbt_duration_at(pos,bbt,dir);
1252 frames = session->tempo_map().bbt_duration_at(pos,bbt,dir);
1258 frames = session->tempo_map().bbt_duration_at(pos,bbt,dir);
1266 AudioClock::current_time (nframes_t pos) const
1272 ret = smpte_frame_from_display ();
1275 ret = bbt_frame_from_display (pos);
1279 ret = minsec_frame_from_display ();
1283 ret = audio_frame_from_display ();
1294 AudioClock::current_duration (nframes_t pos) const
1300 ret = smpte_frame_from_display ();
1303 ret = bbt_frame_duration_from_display (pos);
1307 ret = minsec_frame_from_display ();
1311 ret = audio_frame_from_display ();
1322 AudioClock::smpte_sanitize_display()
1324 // Check SMPTE fields for sanity, possibly adjusting values
1325 if (atoi(minutes_label.get_text()) > 59) {
1326 minutes_label.set_text("59");
1329 if (atoi(seconds_label.get_text()) > 59) {
1330 seconds_label.set_text("59");
1333 switch ((long)rint(session->smpte_frames_per_second())) {
1335 if (atoi(frames_label.get_text()) > 23) {
1336 frames_label.set_text("23");
1340 if (atoi(frames_label.get_text()) > 24) {
1341 frames_label.set_text("24");
1345 if (atoi(frames_label.get_text()) > 29) {
1346 frames_label.set_text("29");
1353 if (session->smpte_drop_frames()) {
1354 if ((atoi(minutes_label.get_text()) % 10) && (atoi(seconds_label.get_text()) == 0) && (atoi(frames_label.get_text()) < 2)) {
1355 frames_label.set_text("02");
1361 AudioClock::smpte_frame_from_display () const
1370 smpte.hours = atoi (hours_label.get_text());
1371 smpte.minutes = atoi (minutes_label.get_text());
1372 smpte.seconds = atoi (seconds_label.get_text());
1373 smpte.frames = atoi (frames_label.get_text());
1374 smpte.rate = session->smpte_frames_per_second();
1375 smpte.drop= session->smpte_drop_frames();
1377 session->smpte_to_sample( smpte, sample, false /* use_offset */, false /* use_subframes */ );
1381 #define SMPTE_SAMPLE_TEST_1
1382 #define SMPTE_SAMPLE_TEST_2
1383 #define SMPTE_SAMPLE_TEST_3
1384 #define SMPTE_SAMPLE_TEST_4
1385 #define SMPTE_SAMPLE_TEST_5
1386 #define SMPTE_SAMPLE_TEST_6
1387 #define SMPTE_SAMPLE_TEST_7
1389 // Testcode for smpte<->sample conversions (P.S.)
1392 nframes_t oldsample = 0;
1394 nframes_t sample_increment;
1396 sample_increment = (long)rint(session->frame_rate() / session->smpte_frames_per_second);
1398 #ifdef SMPTE_SAMPLE_TEST_1
1399 // Test 1: use_offset = false, use_subframes = false
1400 cout << "use_offset = false, use_subframes = false" << endl;
1401 for (int i = 0; i < 108003; i++) {
1402 session->smpte_to_sample( smpte1, sample1, false /* use_offset */, false /* use_subframes */ );
1403 session->sample_to_smpte( sample1, smpte2, false /* use_offset */, false /* use_subframes */ );
1405 if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
1406 cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1407 cout << "smpte1: " << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1408 cout << "sample: " << sample1 << endl;
1409 cout << "sample: " << sample1 << " -> ";
1410 cout << "smpte2: " << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1414 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1415 cout << "ERROR: smpte2 not equal smpte1" << endl;
1416 cout << "smpte1: " << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1417 cout << "sample: " << sample1 << endl;
1418 cout << "sample: " << sample1 << " -> ";
1419 cout << "smpte2: " << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1422 oldsample = sample1;
1423 session->smpte_increment( smpte1 );
1426 cout << "sample_increment: " << sample_increment << endl;
1427 cout << "sample: " << sample1 << " -> ";
1428 cout << "smpte: " << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1431 #ifdef SMPTE_SAMPLE_TEST_2
1432 // Test 2: use_offset = true, use_subframes = false
1433 cout << "use_offset = true, use_subframes = false" << endl;
1439 smpte1.subframes = 0;
1440 sample1 = oldsample = 0;
1442 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1443 cout << "Starting at sample: " << sample1 << " -> ";
1444 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1446 for (int i = 0; i < 108003; i++) {
1447 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1448 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1450 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1451 // cout << "sample: " << sample1 << endl;
1452 // cout << "sample: " << sample1 << " -> ";
1453 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1455 if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
1456 cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1457 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1458 cout << "sample: " << sample1 << endl;
1459 cout << "sample: " << sample1 << " -> ";
1460 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1464 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1465 cout << "ERROR: smpte2 not equal smpte1" << 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;
1472 oldsample = sample1;
1473 session->smpte_increment( smpte1 );
1476 cout << "sample_increment: " << sample_increment << endl;
1477 cout << "sample: " << sample1 << " -> ";
1478 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1481 #ifdef SMPTE_SAMPLE_TEST_3
1482 // Test 3: use_offset = true, use_subframes = false, decrement
1483 cout << "use_offset = true, use_subframes = false, decrement" << endl;
1485 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1486 cout << "Starting at sample: " << sample1 << " -> ";
1487 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1489 for (int i = 0; i < 108003; i++) {
1490 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1491 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1493 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1494 // cout << "sample: " << sample1 << endl;
1495 // cout << "sample: " << sample1 << " -> ";
1496 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1498 if ((i > 0) && ( ((oldsample - sample1) != sample_increment) && ((oldsample - sample1) != (sample_increment + 1)) && ((oldsample - sample1) != (sample_increment - 1)))) {
1499 cout << "ERROR: sample increment not right: " << (oldsample - sample1) << " != " << sample_increment << endl;
1500 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1501 cout << "sample: " << sample1 << endl;
1502 cout << "sample: " << sample1 << " -> ";
1503 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1507 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1508 cout << "ERROR: smpte2 not equal smpte1" << endl;
1509 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1510 cout << "sample: " << sample1 << endl;
1511 cout << "sample: " << sample1 << " -> ";
1512 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1515 oldsample = sample1;
1516 session->smpte_decrement( smpte1 );
1519 cout << "sample_decrement: " << sample_increment << endl;
1520 cout << "sample: " << sample1 << " -> ";
1521 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1525 #ifdef SMPTE_SAMPLE_TEST_4
1526 // Test 4: use_offset = true, use_subframes = true
1527 cout << "use_offset = true, use_subframes = true" << endl;
1529 for (long sub = 5; sub < 80; sub += 5) {
1534 smpte1.subframes = 0;
1535 sample1 = oldsample = (sample_increment * sub) / 80;
1537 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, true /* use_subframes */ );
1539 cout << "starting at sample: " << sample1 << " -> ";
1540 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1542 for (int i = 0; i < 108003; i++) {
1543 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, true /* use_subframes */ );
1544 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, true /* use_subframes */ );
1546 if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
1547 cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1548 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1549 cout << "sample: " << sample1 << endl;
1550 cout << "sample: " << sample1 << " -> ";
1551 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1555 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames || smpte2.subframes != smpte1.subframes) {
1556 cout << "ERROR: smpte2 not equal smpte1" << endl;
1557 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1558 cout << "sample: " << sample1 << endl;
1559 cout << "sample: " << sample1 << " -> ";
1560 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1563 oldsample = sample1;
1564 session->smpte_increment( smpte1 );
1567 cout << "sample_increment: " << sample_increment << endl;
1568 cout << "sample: " << sample1 << " -> ";
1569 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1571 for (int i = 0; i < 108003; i++) {
1572 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, true /* use_subframes */ );
1573 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, true /* use_subframes */ );
1575 if ((i > 0) && ( ((oldsample - sample1) != sample_increment) && ((oldsample - sample1) != (sample_increment + 1)) && ((oldsample - sample1) != (sample_increment - 1)))) {
1576 cout << "ERROR: sample increment not right: " << (oldsample - sample1) << " != " << sample_increment << endl;
1577 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1578 cout << "sample: " << sample1 << endl;
1579 cout << "sample: " << sample1 << " -> ";
1580 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1584 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames || smpte2.subframes != smpte1.subframes) {
1585 cout << "ERROR: smpte2 not equal smpte1" << endl;
1586 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1587 cout << "sample: " << sample1 << endl;
1588 cout << "sample: " << sample1 << " -> ";
1589 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1592 oldsample = sample1;
1593 session->smpte_decrement( smpte1 );
1596 cout << "sample_decrement: " << sample_increment << endl;
1597 cout << "sample: " << sample1 << " -> ";
1598 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1603 #ifdef SMPTE_SAMPLE_TEST_5
1604 // Test 5: use_offset = true, use_subframes = false, increment seconds
1605 cout << "use_offset = true, use_subframes = false, increment seconds" << endl;
1611 smpte1.subframes = 0;
1612 sample1 = oldsample = 0;
1613 sample_increment = session->frame_rate();
1615 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1616 cout << "Starting at sample: " << sample1 << " -> ";
1617 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1619 for (int i = 0; i < 3600; i++) {
1620 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1621 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1623 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1624 // cout << "sample: " << sample1 << endl;
1625 // cout << "sample: " << sample1 << " -> ";
1626 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1628 // if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1630 // cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1634 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1635 cout << "ERROR: smpte2 not equal smpte1" << endl;
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;
1642 oldsample = sample1;
1643 session->smpte_increment_seconds( smpte1 );
1646 cout << "sample_increment: " << sample_increment << endl;
1647 cout << "sample: " << sample1 << " -> ";
1648 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1652 #ifdef SMPTE_SAMPLE_TEST_6
1653 // Test 6: use_offset = true, use_subframes = false, increment minutes
1654 cout << "use_offset = true, use_subframes = false, increment minutes" << endl;
1660 smpte1.subframes = 0;
1661 sample1 = oldsample = 0;
1662 sample_increment = session->frame_rate() * 60;
1664 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1665 cout << "Starting at sample: " << sample1 << " -> ";
1666 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1668 for (int i = 0; i < 60; i++) {
1669 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1670 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1672 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1673 // cout << "sample: " << sample1 << endl;
1674 // cout << "sample: " << sample1 << " -> ";
1675 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1677 // if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1679 // cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1683 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1684 cout << "ERROR: smpte2 not equal smpte1" << endl;
1685 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1686 cout << "sample: " << sample1 << endl;
1687 cout << "sample: " << sample1 << " -> ";
1688 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1691 oldsample = sample1;
1692 session->smpte_increment_minutes( smpte1 );
1695 cout << "sample_increment: " << sample_increment << endl;
1696 cout << "sample: " << sample1 << " -> ";
1697 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1700 #ifdef SMPTE_SAMPLE_TEST_7
1701 // Test 7: use_offset = true, use_subframes = false, increment hours
1702 cout << "use_offset = true, use_subframes = false, increment hours" << endl;
1708 smpte1.subframes = 0;
1709 sample1 = oldsample = 0;
1710 sample_increment = session->frame_rate() * 60 * 60;
1712 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1713 cout << "Starting at sample: " << sample1 << " -> ";
1714 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1716 for (int i = 0; i < 10; i++) {
1717 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1718 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1720 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1721 // cout << "sample: " << sample1 << endl;
1722 // cout << "sample: " << sample1 << " -> ";
1723 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1725 // if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1727 // cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1731 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1732 cout << "ERROR: smpte2 not equal smpte1" << endl;
1733 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1734 cout << "sample: " << sample1 << endl;
1735 cout << "sample: " << sample1 << " -> ";
1736 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1739 oldsample = sample1;
1740 session->smpte_increment_hours( smpte1 );
1743 cout << "sample_increment: " << sample_increment << endl;
1744 cout << "sample: " << sample1 << " -> ";
1745 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1754 AudioClock::minsec_frame_from_display () const
1760 int hrs = atoi (ms_hours_label.get_text());
1761 int mins = atoi (ms_minutes_label.get_text());
1762 float secs = atof (ms_seconds_label.get_text());
1764 nframes_t sr = session->frame_rate();
1766 return (nframes_t) floor ((hrs * 60.0f * 60.0f * sr) + (mins * 60.0f * sr) + (secs * sr));
1770 AudioClock::bbt_frame_from_display (nframes_t pos) const
1773 error << "AudioClock::current_time() called with BBT mode but without session!" << endmsg;
1778 any.type = AnyTime::BBT;
1780 any.bbt.bars = atoi (bars_label.get_text());
1781 any.bbt.beats = atoi (beats_label.get_text());
1782 any.bbt.ticks = atoi (ticks_label.get_text());
1784 nframes_t ret = session->convert_to_frames_at (pos, any);
1791 AudioClock::bbt_frame_duration_from_display (nframes_t pos) const
1794 error << "AudioClock::current_time() called with BBT mode but without session!" << endmsg;
1801 bbt.bars = atoi (bars_label.get_text());
1802 bbt.beats = atoi (beats_label.get_text());
1803 bbt.ticks = atoi (ticks_label.get_text());
1805 return session->tempo_map().bbt_duration_at(pos,bbt,1);
1809 AudioClock::audio_frame_from_display () const
1811 return (nframes_t) atoi (audio_frames_label.get_text());
1815 AudioClock::build_ops_menu ()
1817 using namespace Menu_Helpers;
1818 ops_menu = new Menu;
1819 MenuList& ops_items = ops_menu->items();
1820 ops_menu->set_name ("ArdourContextMenu");
1822 Menu *mode_menu = manage (new Menu);
1823 MenuList& mode_items = mode_menu->items();
1824 mode_menu->set_name ("ArdourContextMenu");
1826 mode_items.push_back (MenuElem (_("Timecode"), bind (mem_fun(*this, &AudioClock::set_mode), SMPTE)));
1827 mode_items.push_back (MenuElem (_("Bars:Beats"), bind (mem_fun(*this, &AudioClock::set_mode), BBT)));
1828 mode_items.push_back (MenuElem (_("Minutes:Seconds"), bind (mem_fun(*this, &AudioClock::set_mode), MinSec)));
1829 mode_items.push_back (MenuElem (_("Audio Frames"), bind (mem_fun(*this, &AudioClock::set_mode), Frames)));
1830 mode_items.push_back (MenuElem (_("Off"), bind (mem_fun(*this, &AudioClock::set_mode), Off)));
1832 ops_items.push_back (MenuElem (_("Mode"), *mode_menu));
1836 AudioClock::set_mode (Mode m)
1838 /* slightly tricky: this is called from within the ARDOUR_UI
1839 constructor by some of its clock members. at that time
1840 the instance pointer is unset, so we have to be careful.
1841 the main idea is to drop keyboard focus in case we had
1842 started editing the clock and then we switch clock mode.
1845 clock_base.grab_focus ();
1855 clock_base.remove ();
1865 clock_base.add (smpte_packer_hbox);
1869 clock_base.add (bbt_packer_hbox);
1873 clock_base.add (minsec_packer_hbox);
1877 clock_base.add (frames_packer_hbox);
1884 set_size_requests ();
1886 set (last_when, true);
1887 clock_base.show_all ();
1888 key_entry_state = 0;
1890 if (!is_transient) {
1891 ModeChanged (); /* EMIT SIGNAL */
1896 AudioClock::set_size_requests ()
1898 /* note that in some fonts, "88" is narrower than "00", hence the 2 pixel padding */
1902 Gtkmm2ext::set_size_request_to_display_given_text (hours_label, "-00", 5, 5);
1903 Gtkmm2ext::set_size_request_to_display_given_text (minutes_label, "00", 5, 5);
1904 Gtkmm2ext::set_size_request_to_display_given_text (seconds_label, "00", 5, 5);
1905 Gtkmm2ext::set_size_request_to_display_given_text (frames_label, "00", 5, 5);
1909 Gtkmm2ext::set_size_request_to_display_given_text (bars_label, "-000", 5, 5);
1910 Gtkmm2ext::set_size_request_to_display_given_text (beats_label, "00", 5, 5);
1911 Gtkmm2ext::set_size_request_to_display_given_text (ticks_label, "0000", 5, 5);
1915 Gtkmm2ext::set_size_request_to_display_given_text (ms_hours_label, "00", 5, 5);
1916 Gtkmm2ext::set_size_request_to_display_given_text (ms_minutes_label, "00", 5, 5);
1917 Gtkmm2ext::set_size_request_to_display_given_text (ms_seconds_label, "00.000", 5, 5);
1921 Gtkmm2ext::set_size_request_to_display_given_text (audio_frames_label, "0000000000", 5, 5);