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),
85 frames_upper_info_label = manage (new Label);
86 frames_lower_info_label = manage (new Label);
87 smpte_upper_info_label = manage (new Label);
88 smpte_lower_info_label = manage (new Label);
89 bbt_upper_info_label = manage (new Label);
90 bbt_lower_info_label = manage (new Label);
92 frames_upper_info_label->set_name ("AudioClockFramesUpperInfo");
93 frames_lower_info_label->set_name ("AudioClockFramesLowerInfo");
94 smpte_upper_info_label->set_name ("AudioClockSMPTEUpperInfo");
95 smpte_lower_info_label->set_name ("AudioClockSMPTELowerInfo");
96 bbt_upper_info_label->set_name ("AudioClockBBTUpperInfo");
97 bbt_lower_info_label->set_name ("AudioClockBBTLowerInfo");
99 Gtkmm2ext::set_size_request_to_display_given_text(*smpte_upper_info_label, "23.98",0,0);
100 Gtkmm2ext::set_size_request_to_display_given_text(*smpte_lower_info_label, "NDF",0,0);
102 frames_info_box.pack_start (*frames_upper_info_label, true, true);
103 frames_info_box.pack_start (*frames_lower_info_label, true, true);
104 smpte_info_box.pack_start (*smpte_upper_info_label, true, true);
105 smpte_info_box.pack_start (*smpte_lower_info_label, true, true);
106 bbt_info_box.pack_start (*bbt_upper_info_label, true, true);
107 bbt_info_box.pack_start (*bbt_lower_info_label, true, true);
110 frames_upper_info_label = 0;
111 frames_lower_info_label = 0;
112 smpte_upper_info_label = 0;
113 smpte_lower_info_label = 0;
114 bbt_upper_info_label = 0;
115 bbt_lower_info_label = 0;
118 audio_frames_ebox.add (audio_frames_label);
120 frames_packer.set_homogeneous (false);
121 frames_packer.set_border_width (2);
122 frames_packer.pack_start (audio_frames_ebox, false, false);
125 frames_packer.pack_start (frames_info_box, false, false, 5);
128 frames_packer_hbox.pack_start (frames_packer, true, false);
130 hours_ebox.add (hours_label);
131 minutes_ebox.add (minutes_label);
132 seconds_ebox.add (seconds_label);
133 frames_ebox.add (frames_label);
134 bars_ebox.add (bars_label);
135 beats_ebox.add (beats_label);
136 ticks_ebox.add (ticks_label);
137 ms_hours_ebox.add (ms_hours_label);
138 ms_minutes_ebox.add (ms_minutes_label);
139 ms_seconds_ebox.add (ms_seconds_label);
141 smpte_packer.set_homogeneous (false);
142 smpte_packer.set_border_width (2);
143 smpte_packer.pack_start (hours_ebox, false, false);
144 smpte_packer.pack_start (colon1, false, false);
145 smpte_packer.pack_start (minutes_ebox, false, false);
146 smpte_packer.pack_start (colon2, false, false);
147 smpte_packer.pack_start (seconds_ebox, false, false);
148 smpte_packer.pack_start (colon3, false, false);
149 smpte_packer.pack_start (frames_ebox, false, false);
152 smpte_packer.pack_start (smpte_info_box, false, false, 5);
155 smpte_packer_hbox.pack_start (smpte_packer, true, false);
157 bbt_packer.set_homogeneous (false);
158 bbt_packer.set_border_width (2);
159 bbt_packer.pack_start (bars_ebox, false, false);
160 bbt_packer.pack_start (b1, false, false);
161 bbt_packer.pack_start (beats_ebox, false, false);
162 bbt_packer.pack_start (b2, false, false);
163 bbt_packer.pack_start (ticks_ebox, false, false);
166 bbt_packer.pack_start (bbt_info_box, false, false, 5);
169 bbt_packer_hbox.pack_start (bbt_packer, true, false);
171 minsec_packer.set_homogeneous (false);
172 minsec_packer.set_border_width (2);
173 minsec_packer.pack_start (ms_hours_ebox, false, false);
174 minsec_packer.pack_start (colon4, false, false);
175 minsec_packer.pack_start (ms_minutes_ebox, false, false);
176 minsec_packer.pack_start (colon5, false, false);
177 minsec_packer.pack_start (ms_seconds_ebox, false, false);
179 minsec_packer_hbox.pack_start (minsec_packer, true, false);
181 clock_frame.set_shadow_type (Gtk::SHADOW_IN);
182 clock_frame.set_name ("BaseFrame");
184 clock_frame.add (clock_base);
186 set_widget_name (widget_name);
188 _mode = BBT; /* lie to force mode switch */
191 pack_start (clock_frame, true, true);
193 /* the clock base handles button releases for menu popup regardless of
194 editable status. if the clock is editable, the clock base is where
195 we pass focus to after leaving the last editable "field", which
196 will then shutdown editing till the user starts it up again.
198 it does this because the focus out event on the field disables
199 keyboard event handling, and we don't connect anything up to
200 notice focus in on the clock base. hence, keyboard event handling
204 clock_base.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::SCROLL_MASK);
205 clock_base.signal_button_release_event().connect (bind (mem_fun (*this, &AudioClock::field_button_release_event), SMPTE_Hours));
207 Session::SMPTEOffsetChanged.connect (mem_fun (*this, &AudioClock::smpte_offset_changed));
213 set (last_when, true);
216 clocks.push_back (this);
221 AudioClock::set_widget_name (string name)
223 Widget::set_name (name);
225 clock_base.set_name (name);
227 audio_frames_label.set_name (name);
228 hours_label.set_name (name);
229 minutes_label.set_name (name);
230 seconds_label.set_name (name);
231 frames_label.set_name (name);
232 bars_label.set_name (name);
233 beats_label.set_name (name);
234 ticks_label.set_name (name);
235 ms_hours_label.set_name (name);
236 ms_minutes_label.set_name (name);
237 ms_seconds_label.set_name (name);
238 hours_ebox.set_name (name);
239 minutes_ebox.set_name (name);
240 seconds_ebox.set_name (name);
241 frames_ebox.set_name (name);
242 audio_frames_ebox.set_name (name);
243 bars_ebox.set_name (name);
244 beats_ebox.set_name (name);
245 ticks_ebox.set_name (name);
246 ms_hours_ebox.set_name (name);
247 ms_minutes_ebox.set_name (name);
248 ms_seconds_ebox.set_name (name);
250 colon1.set_name (name);
251 colon2.set_name (name);
252 colon3.set_name (name);
253 colon4.set_name (name);
254 colon5.set_name (name);
262 AudioClock::setup_events ()
264 clock_base.set_flags (Gtk::CAN_FOCUS);
266 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);
267 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);
268 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);
269 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);
270 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);
271 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);
272 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);
273 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);
274 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);
275 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);
276 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);
278 hours_ebox.set_flags (Gtk::CAN_FOCUS);
279 minutes_ebox.set_flags (Gtk::CAN_FOCUS);
280 seconds_ebox.set_flags (Gtk::CAN_FOCUS);
281 frames_ebox.set_flags (Gtk::CAN_FOCUS);
282 audio_frames_ebox.set_flags (Gtk::CAN_FOCUS);
283 bars_ebox.set_flags (Gtk::CAN_FOCUS);
284 beats_ebox.set_flags (Gtk::CAN_FOCUS);
285 ticks_ebox.set_flags (Gtk::CAN_FOCUS);
286 ms_hours_ebox.set_flags (Gtk::CAN_FOCUS);
287 ms_minutes_ebox.set_flags (Gtk::CAN_FOCUS);
288 ms_seconds_ebox.set_flags (Gtk::CAN_FOCUS);
290 hours_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), SMPTE_Hours));
291 minutes_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), SMPTE_Minutes));
292 seconds_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), SMPTE_Seconds));
293 frames_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), SMPTE_Frames));
294 audio_frames_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), AudioFrames));
295 bars_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), Bars));
296 beats_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), Beats));
297 ticks_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), Ticks));
298 ms_hours_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), MS_Hours));
299 ms_minutes_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), MS_Minutes));
300 ms_seconds_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), MS_Seconds));
302 hours_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), SMPTE_Hours));
303 minutes_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), SMPTE_Minutes));
304 seconds_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), SMPTE_Seconds));
305 frames_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), SMPTE_Frames));
306 audio_frames_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), AudioFrames));
307 bars_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), Bars));
308 beats_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), Beats));
309 ticks_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), Ticks));
310 ms_hours_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), MS_Hours));
311 ms_minutes_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), MS_Minutes));
312 ms_seconds_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), MS_Seconds));
314 hours_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), SMPTE_Hours));
315 minutes_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), SMPTE_Minutes));
316 seconds_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), SMPTE_Seconds));
317 frames_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), SMPTE_Frames));
318 audio_frames_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), AudioFrames));
319 bars_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), Bars));
320 beats_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), Beats));
321 ticks_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), Ticks));
322 ms_hours_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), MS_Hours));
323 ms_minutes_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), MS_Minutes));
324 ms_seconds_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), MS_Seconds));
326 hours_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), SMPTE_Hours));
327 minutes_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), SMPTE_Minutes));
328 seconds_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), SMPTE_Seconds));
329 frames_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), SMPTE_Frames));
330 audio_frames_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), AudioFrames));
331 bars_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), Bars));
332 beats_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), Beats));
333 ticks_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), Ticks));
334 ms_hours_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), MS_Hours));
335 ms_minutes_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), MS_Minutes));
336 ms_seconds_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), MS_Seconds));
338 hours_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), SMPTE_Hours));
339 minutes_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), SMPTE_Minutes));
340 seconds_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), SMPTE_Seconds));
341 frames_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), SMPTE_Frames));
342 audio_frames_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), AudioFrames));
343 bars_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), Bars));
344 beats_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), Beats));
345 ticks_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), Ticks));
346 ms_hours_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), MS_Hours));
347 ms_minutes_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), MS_Minutes));
348 ms_seconds_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), MS_Seconds));
350 hours_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), SMPTE_Hours));
351 minutes_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), SMPTE_Minutes));
352 seconds_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), SMPTE_Seconds));
353 frames_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), SMPTE_Frames));
354 audio_frames_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), AudioFrames));
355 bars_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), Bars));
356 beats_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), Beats));
357 ticks_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), Ticks));
358 ms_hours_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), MS_Hours));
359 ms_minutes_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), MS_Minutes));
360 ms_seconds_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), MS_Seconds));
362 hours_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), SMPTE_Hours));
363 minutes_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), SMPTE_Minutes));
364 seconds_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), SMPTE_Seconds));
365 frames_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), SMPTE_Frames));
366 audio_frames_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), AudioFrames));
367 bars_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), Bars));
368 beats_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), Beats));
369 ticks_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), Ticks));
370 ms_hours_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), MS_Hours));
371 ms_minutes_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), MS_Minutes));
372 ms_seconds_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), MS_Seconds));
376 AudioClock::on_realize ()
380 /* styles are not available until the widgets are bound to a window */
382 set_size_requests ();
386 AudioClock::set (nframes_t when, bool force)
389 if ((!force && !is_visible()) || session == 0) {
393 if (when == last_when && !force) {
399 set_smpte (when, force);
403 set_bbt (when, force);
407 set_minsec (when, force);
411 set_frames (when, force);
422 AudioClock::smpte_offset_changed ()
429 current = current_duration();
431 current = current_time ();
441 AudioClock::set_frames (nframes_t when, bool force)
444 snprintf (buf, sizeof (buf), "%u", when);
445 audio_frames_label.set_text (buf);
447 if (frames_upper_info_label) {
448 nframes_t rate = session->frame_rate();
450 if (fmod (rate, 1000.0) == 0.000) {
451 sprintf (buf, "%uK", rate/1000);
453 sprintf (buf, "%.3fK", rate/1000.0f);
456 frames_upper_info_label->set_text (buf);
458 float vid_pullup = Config->get_video_pullup();
460 if (vid_pullup == 0.0) {
461 frames_lower_info_label->set_text(_("none"));
463 sprintf (buf, "%-6.4f", vid_pullup);
464 frames_lower_info_label->set_text (buf);
470 AudioClock::set_minsec (nframes_t when, bool force)
479 hrs = (int) floor (left / (session->frame_rate() * 60.0f * 60.0f));
480 left -= (nframes_t) floor (hrs * session->frame_rate() * 60.0f * 60.0f);
481 mins = (int) floor (left / (session->frame_rate() * 60.0f));
482 left -= (nframes_t) floor (mins * session->frame_rate() * 60.0f);
483 secs = left / (float) session->frame_rate();
485 if (force || hrs != ms_last_hrs) {
486 sprintf (buf, "%02d", hrs);
487 ms_hours_label.set_text (buf);
491 if (force || mins != ms_last_mins) {
492 sprintf (buf, "%02d", mins);
493 ms_minutes_label.set_text (buf);
497 if (force || secs != ms_last_secs) {
498 sprintf (buf, "%06.3f", secs);
499 ms_seconds_label.set_text (buf);
505 AudioClock::set_smpte (nframes_t when, bool force)
511 session->smpte_duration (when, smpte);
513 session->smpte_time (when, smpte);
516 if (force || smpte.hours != last_hrs || smpte.negative != last_negative) {
517 if (smpte.negative) {
518 sprintf (buf, "-%02" PRIu32, smpte.hours);
520 sprintf (buf, " %02" PRIu32, smpte.hours);
522 hours_label.set_text (buf);
523 last_hrs = smpte.hours;
524 last_negative = smpte.negative;
527 if (force || smpte.minutes != last_mins) {
528 sprintf (buf, "%02" PRIu32, smpte.minutes);
529 minutes_label.set_text (buf);
530 last_mins = smpte.minutes;
533 if (force || smpte.seconds != last_secs) {
534 sprintf (buf, "%02" PRIu32, smpte.seconds);
535 seconds_label.set_text (buf);
536 last_secs = smpte.seconds;
539 if (force || smpte.frames != last_frames) {
540 sprintf (buf, "%02" PRIu32, smpte.frames);
541 frames_label.set_text (buf);
542 last_frames = smpte.frames;
545 if (smpte_upper_info_label) {
546 double smpte_frames = session->smpte_frames_per_second();
548 if ( fmod(smpte_frames, 1.0) == 0.0) {
549 sprintf (buf, "%u", int (smpte_frames));
551 sprintf (buf, "%.2f", smpte_frames);
554 smpte_upper_info_label->set_text (buf);
556 if (session->smpte_drop_frames()) {
559 sprintf (buf, "NDF");
562 smpte_lower_info_label->set_text (buf);
567 AudioClock::set_bbt (nframes_t when, bool force)
572 session->tempo_map().bbt_time (when, bbt);
573 sprintf (buf, "%03" PRIu32, bbt.bars);
574 bars_label.set_text (buf);
575 sprintf (buf, "%02" PRIu32, bbt.beats);
576 beats_label.set_text (buf);
577 sprintf (buf, "%04" PRIu32, bbt.ticks);
578 ticks_label.set_text (buf);
580 if (bbt_upper_info_label) {
581 TempoMap::Metric m (session->tempo_map().metric_at (when));
582 sprintf (buf, "%-5.2f", m.tempo().beats_per_minute());
583 bbt_lower_info_label->set_text (buf);
584 sprintf (buf, "%g|%g", m.meter().beats_per_bar(), m.meter().note_divisor());
585 bbt_upper_info_label->set_text (buf);
590 AudioClock::set_session (Session *s)
597 XMLNode* node = session->extra_xml (X_("ClockModes"));
598 AudioClock::Mode amode;
601 if ((prop = node->property (_name)) != 0) {
602 amode = AudioClock::Mode (string_2_enum (prop->value(), amode));
607 set (last_when, true);
612 AudioClock::field_key_release_event (GdkEventKey *ev, Field field)
617 bool move_on = false;
621 label = &hours_label;
624 label = &minutes_label;
627 label = &seconds_label;
630 label = &frames_label;
634 label = &audio_frames_label;
638 label = &ms_hours_label;
641 label = &ms_minutes_label;
644 label = &ms_seconds_label;
651 label = &beats_label;
654 label = &ticks_label;
660 switch (ev->keyval) {
704 if (_mode == MinSec && field == MS_Seconds) {
718 clock_base.grab_focus ();
727 if (key_entry_state == 0) {
729 /* initialize with a fresh new string */
731 if (field != AudioFrames) {
732 for (uint32_t xn = 0; xn < field_length[field] - 1; ++xn) {
741 string existing = label->get_text();
742 if (existing.length() >= field_length[field]) {
743 new_text = existing.substr (1, field_length[field] - 1);
745 new_text = existing.substr (0, field_length[field] - 1);
749 new_text += new_char;
750 label->set_text (new_text);
754 if (key_entry_state == field_length[field]) {
760 if (key_entry_state) {
767 // Check SMPTE fields for sanity (may also adjust fields)
768 smpte_sanitize_display();
773 // Bars or beats should never be 0
774 if (atoi(bars_label.get_text()) == 0) {
775 bars_label.set_text("001");
777 if (atoi(beats_label.get_text()) == 0) {
778 beats_label.set_text("01");
785 ValueChanged(); /* EMIT_SIGNAL */
788 /* move on to the next field.
796 minutes_ebox.grab_focus ();
799 seconds_ebox.grab_focus ();
802 frames_ebox.grab_focus ();
805 clock_base.grab_focus ();
810 clock_base.grab_focus ();
816 ms_minutes_ebox.grab_focus ();
819 ms_seconds_ebox.grab_focus ();
822 clock_base.grab_focus ();
828 beats_ebox.grab_focus ();
831 ticks_ebox.grab_focus ();
834 clock_base.grab_focus ();
847 AudioClock::field_focus_in_event (GdkEventFocus *ev, Field field)
853 hours_ebox.set_flags (Gtk::HAS_FOCUS);
854 hours_ebox.set_state (Gtk::STATE_ACTIVE);
857 minutes_ebox.set_flags (Gtk::HAS_FOCUS);
858 minutes_ebox.set_state (Gtk::STATE_ACTIVE);
861 seconds_ebox.set_flags (Gtk::HAS_FOCUS);
862 seconds_ebox.set_state (Gtk::STATE_ACTIVE);
865 frames_ebox.set_flags (Gtk::HAS_FOCUS);
866 frames_ebox.set_state (Gtk::STATE_ACTIVE);
870 audio_frames_ebox.set_flags (Gtk::HAS_FOCUS);
871 audio_frames_ebox.set_state (Gtk::STATE_ACTIVE);
875 ms_hours_ebox.set_flags (Gtk::HAS_FOCUS);
876 ms_hours_ebox.set_state (Gtk::STATE_ACTIVE);
879 ms_minutes_ebox.set_flags (Gtk::HAS_FOCUS);
880 ms_minutes_ebox.set_state (Gtk::STATE_ACTIVE);
883 ms_seconds_ebox.set_flags (Gtk::HAS_FOCUS);
884 ms_seconds_ebox.set_state (Gtk::STATE_ACTIVE);
887 bars_ebox.set_flags (Gtk::HAS_FOCUS);
888 bars_ebox.set_state (Gtk::STATE_ACTIVE);
891 beats_ebox.set_flags (Gtk::HAS_FOCUS);
892 beats_ebox.set_state (Gtk::STATE_ACTIVE);
895 ticks_ebox.set_flags (Gtk::HAS_FOCUS);
896 ticks_ebox.set_state (Gtk::STATE_ACTIVE);
904 AudioClock::field_focus_out_event (GdkEventFocus *ev, Field field)
909 hours_ebox.unset_flags (Gtk::HAS_FOCUS);
910 hours_ebox.set_state (Gtk::STATE_NORMAL);
913 minutes_ebox.unset_flags (Gtk::HAS_FOCUS);
914 minutes_ebox.set_state (Gtk::STATE_NORMAL);
917 seconds_ebox.unset_flags (Gtk::HAS_FOCUS);
918 seconds_ebox.set_state (Gtk::STATE_NORMAL);
921 frames_ebox.unset_flags (Gtk::HAS_FOCUS);
922 frames_ebox.set_state (Gtk::STATE_NORMAL);
926 audio_frames_ebox.unset_flags (Gtk::HAS_FOCUS);
927 audio_frames_ebox.set_state (Gtk::STATE_NORMAL);
931 ms_hours_ebox.unset_flags (Gtk::HAS_FOCUS);
932 ms_hours_ebox.set_state (Gtk::STATE_NORMAL);
935 ms_minutes_ebox.unset_flags (Gtk::HAS_FOCUS);
936 ms_minutes_ebox.set_state (Gtk::STATE_NORMAL);
939 ms_seconds_ebox.unset_flags (Gtk::HAS_FOCUS);
940 ms_seconds_ebox.set_state (Gtk::STATE_NORMAL);
944 bars_ebox.unset_flags (Gtk::HAS_FOCUS);
945 bars_ebox.set_state (Gtk::STATE_NORMAL);
948 beats_ebox.unset_flags (Gtk::HAS_FOCUS);
949 beats_ebox.set_state (Gtk::STATE_NORMAL);
952 ticks_ebox.unset_flags (Gtk::HAS_FOCUS);
953 ticks_ebox.set_state (Gtk::STATE_NORMAL);
961 AudioClock::field_button_release_event (GdkEventButton *ev, Field field)
966 gdk_pointer_ungrab(GDK_CURRENT_TIME);
968 if (ev->y > drag_start_y+1 || ev->y < drag_start_y-1 || Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)){
969 // we actually dragged so return without setting editing focus, or we shift clicked
979 ops_menu->popup (1, ev->time);
983 if (Keyboard::is_context_menu_event (ev)) {
987 ops_menu->popup (1, ev->time);
991 switch (ev->button) {
995 hours_ebox.grab_focus();
998 minutes_ebox.grab_focus();
1001 seconds_ebox.grab_focus();
1004 frames_ebox.grab_focus();
1008 audio_frames_ebox.grab_focus();
1012 ms_hours_ebox.grab_focus();
1015 ms_minutes_ebox.grab_focus();
1018 ms_seconds_ebox.grab_focus();
1022 bars_ebox.grab_focus ();
1025 beats_ebox.grab_focus ();
1028 ticks_ebox.grab_focus ();
1041 AudioClock::field_button_press_event (GdkEventButton *ev, Field field)
1043 if (session == 0) return FALSE;
1045 nframes_t frames = 0;
1047 switch (ev->button) {
1049 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
1051 ValueChanged (); /* EMIT_SIGNAL */
1054 /* make absolutely sure that the pointer is grabbed */
1055 gdk_pointer_grab(ev->window,FALSE ,
1056 GdkEventMask( Gdk::POINTER_MOTION_MASK | Gdk::BUTTON_PRESS_MASK |Gdk::BUTTON_RELEASE_MASK),
1057 NULL,NULL,ev->time);
1060 drag_start_y = ev->y;
1065 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
1067 ValueChanged (); /* EMIT_SIGNAL */
1072 /* used for context sensitive menu */
1077 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
1078 frames = get_frames (field);
1080 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
1083 set (current_time() + frames, true);
1084 ValueChanged (); /* EMIT_SIGNAL */
1090 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
1091 frames = get_frames (field);
1093 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
1097 if ((double)current_time() - (double)frames < 0.0) {
1101 set (current_time() - frames, true);
1104 ValueChanged (); /* EMIT_SIGNAL */
1118 AudioClock::field_button_scroll_event (GdkEventScroll *ev, Field field)
1120 if (session == 0) return FALSE;
1122 nframes_t frames = 0;
1124 switch (ev->direction) {
1127 frames = get_frames (field);
1129 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
1132 set (current_time() + frames, true);
1133 ValueChanged (); /* EMIT_SIGNAL */
1137 case GDK_SCROLL_DOWN:
1138 frames = get_frames (field);
1140 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
1144 if ((double)current_time() - (double)frames < 0.0) {
1147 set (current_time() - frames, true);
1150 ValueChanged (); /* EMIT_SIGNAL */
1163 AudioClock::field_motion_notify_event (GdkEventMotion *ev, Field field)
1165 if (session == 0 || !dragging) {
1169 float pixel_frame_scale_factor = 0.2f;
1172 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
1173 pixel_frame_scale_factor = 0.1f;
1177 if (Keyboard::modifier_state_contains (ev->state,
1178 Keyboard::Control|Keyboard::Alt)) {
1180 pixel_frame_scale_factor = 0.025f;
1183 double y_delta = ev->y - drag_y;
1185 drag_accum += y_delta*pixel_frame_scale_factor;
1189 if (trunc(drag_accum) != 0) {
1194 dir = (drag_accum < 0 ? 1:-1);
1195 pos = current_time();
1196 frames = get_frames (field,pos,dir);
1198 if (frames != 0 && frames * drag_accum < current_time()) {
1200 set ((nframes_t) floor (pos - drag_accum * frames), false); // minus because up is negative in computer-land
1208 ValueChanged(); /* EMIT_SIGNAL */
1217 AudioClock::get_frames (Field field,nframes_t pos,int dir)
1220 nframes_t frames = 0;
1224 frames = (nframes_t) floor (3600.0 * session->frame_rate());
1227 frames = (nframes_t) floor (60.0 * session->frame_rate());
1230 frames = session->frame_rate();
1233 frames = (nframes_t) floor (session->frame_rate() / session->smpte_frames_per_second());
1241 frames = (nframes_t) floor (3600.0 * session->frame_rate());
1244 frames = (nframes_t) floor (60.0 * session->frame_rate());
1247 frames = session->frame_rate();
1254 frames = session->tempo_map().bbt_duration_at(pos,bbt,dir);
1260 frames = session->tempo_map().bbt_duration_at(pos,bbt,dir);
1266 frames = session->tempo_map().bbt_duration_at(pos,bbt,dir);
1274 AudioClock::current_time (nframes_t pos) const
1280 ret = smpte_frame_from_display ();
1283 ret = bbt_frame_from_display (pos);
1287 ret = minsec_frame_from_display ();
1291 ret = audio_frame_from_display ();
1302 AudioClock::current_duration (nframes_t pos) const
1308 ret = smpte_frame_from_display ();
1311 ret = bbt_frame_duration_from_display (pos);
1315 ret = minsec_frame_from_display ();
1319 ret = audio_frame_from_display ();
1330 AudioClock::smpte_sanitize_display()
1332 // Check SMPTE fields for sanity, possibly adjusting values
1333 if (atoi(minutes_label.get_text()) > 59) {
1334 minutes_label.set_text("59");
1337 if (atoi(seconds_label.get_text()) > 59) {
1338 seconds_label.set_text("59");
1341 switch ((long)rint(session->smpte_frames_per_second())) {
1343 if (atoi(frames_label.get_text()) > 23) {
1344 frames_label.set_text("23");
1348 if (atoi(frames_label.get_text()) > 24) {
1349 frames_label.set_text("24");
1353 if (atoi(frames_label.get_text()) > 29) {
1354 frames_label.set_text("29");
1361 if (session->smpte_drop_frames()) {
1362 if ((atoi(minutes_label.get_text()) % 10) && (atoi(seconds_label.get_text()) == 0) && (atoi(frames_label.get_text()) < 2)) {
1363 frames_label.set_text("02");
1369 AudioClock::smpte_frame_from_display () const
1378 smpte.hours = atoi (hours_label.get_text());
1379 smpte.minutes = atoi (minutes_label.get_text());
1380 smpte.seconds = atoi (seconds_label.get_text());
1381 smpte.frames = atoi (frames_label.get_text());
1382 smpte.rate = session->smpte_frames_per_second();
1383 smpte.drop= session->smpte_drop_frames();
1385 session->smpte_to_sample( smpte, sample, false /* use_offset */, false /* use_subframes */ );
1389 #define SMPTE_SAMPLE_TEST_1
1390 #define SMPTE_SAMPLE_TEST_2
1391 #define SMPTE_SAMPLE_TEST_3
1392 #define SMPTE_SAMPLE_TEST_4
1393 #define SMPTE_SAMPLE_TEST_5
1394 #define SMPTE_SAMPLE_TEST_6
1395 #define SMPTE_SAMPLE_TEST_7
1397 // Testcode for smpte<->sample conversions (P.S.)
1400 nframes_t oldsample = 0;
1402 nframes_t sample_increment;
1404 sample_increment = (long)rint(session->frame_rate() / session->smpte_frames_per_second);
1406 #ifdef SMPTE_SAMPLE_TEST_1
1407 // Test 1: use_offset = false, use_subframes = false
1408 cout << "use_offset = false, use_subframes = false" << endl;
1409 for (int i = 0; i < 108003; i++) {
1410 session->smpte_to_sample( smpte1, sample1, false /* use_offset */, false /* use_subframes */ );
1411 session->sample_to_smpte( sample1, smpte2, false /* use_offset */, false /* use_subframes */ );
1413 if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
1414 cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1415 cout << "smpte1: " << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1416 cout << "sample: " << sample1 << endl;
1417 cout << "sample: " << sample1 << " -> ";
1418 cout << "smpte2: " << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1422 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1423 cout << "ERROR: smpte2 not equal smpte1" << endl;
1424 cout << "smpte1: " << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1425 cout << "sample: " << sample1 << endl;
1426 cout << "sample: " << sample1 << " -> ";
1427 cout << "smpte2: " << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1430 oldsample = sample1;
1431 session->smpte_increment( smpte1 );
1434 cout << "sample_increment: " << sample_increment << endl;
1435 cout << "sample: " << sample1 << " -> ";
1436 cout << "smpte: " << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1439 #ifdef SMPTE_SAMPLE_TEST_2
1440 // Test 2: use_offset = true, use_subframes = false
1441 cout << "use_offset = true, use_subframes = false" << endl;
1447 smpte1.subframes = 0;
1448 sample1 = oldsample = 0;
1450 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1451 cout << "Starting at sample: " << sample1 << " -> ";
1452 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1454 for (int i = 0; i < 108003; i++) {
1455 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1456 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1458 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1459 // cout << "sample: " << sample1 << endl;
1460 // cout << "sample: " << sample1 << " -> ";
1461 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1463 if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
1464 cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1465 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1466 cout << "sample: " << sample1 << endl;
1467 cout << "sample: " << sample1 << " -> ";
1468 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1472 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1473 cout << "ERROR: smpte2 not equal smpte1" << endl;
1474 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1475 cout << "sample: " << sample1 << endl;
1476 cout << "sample: " << sample1 << " -> ";
1477 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1480 oldsample = sample1;
1481 session->smpte_increment( smpte1 );
1484 cout << "sample_increment: " << sample_increment << endl;
1485 cout << "sample: " << sample1 << " -> ";
1486 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1489 #ifdef SMPTE_SAMPLE_TEST_3
1490 // Test 3: use_offset = true, use_subframes = false, decrement
1491 cout << "use_offset = true, use_subframes = false, decrement" << endl;
1493 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1494 cout << "Starting at sample: " << sample1 << " -> ";
1495 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1497 for (int i = 0; i < 108003; i++) {
1498 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1499 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1501 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1502 // cout << "sample: " << sample1 << endl;
1503 // cout << "sample: " << sample1 << " -> ";
1504 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1506 if ((i > 0) && ( ((oldsample - sample1) != sample_increment) && ((oldsample - sample1) != (sample_increment + 1)) && ((oldsample - sample1) != (sample_increment - 1)))) {
1507 cout << "ERROR: sample increment not right: " << (oldsample - sample1) << " != " << sample_increment << endl;
1508 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1509 cout << "sample: " << sample1 << endl;
1510 cout << "sample: " << sample1 << " -> ";
1511 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1515 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1516 cout << "ERROR: smpte2 not equal smpte1" << endl;
1517 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1518 cout << "sample: " << sample1 << endl;
1519 cout << "sample: " << sample1 << " -> ";
1520 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1523 oldsample = sample1;
1524 session->smpte_decrement( smpte1 );
1527 cout << "sample_decrement: " << sample_increment << endl;
1528 cout << "sample: " << sample1 << " -> ";
1529 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1533 #ifdef SMPTE_SAMPLE_TEST_4
1534 // Test 4: use_offset = true, use_subframes = true
1535 cout << "use_offset = true, use_subframes = true" << endl;
1537 for (long sub = 5; sub < 80; sub += 5) {
1542 smpte1.subframes = 0;
1543 sample1 = oldsample = (sample_increment * sub) / 80;
1545 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, true /* use_subframes */ );
1547 cout << "starting at sample: " << sample1 << " -> ";
1548 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1550 for (int i = 0; i < 108003; i++) {
1551 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, true /* use_subframes */ );
1552 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, true /* use_subframes */ );
1554 if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
1555 cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1556 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1557 cout << "sample: " << sample1 << endl;
1558 cout << "sample: " << sample1 << " -> ";
1559 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1563 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames || smpte2.subframes != smpte1.subframes) {
1564 cout << "ERROR: smpte2 not equal smpte1" << endl;
1565 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1566 cout << "sample: " << sample1 << endl;
1567 cout << "sample: " << sample1 << " -> ";
1568 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1571 oldsample = sample1;
1572 session->smpte_increment( smpte1 );
1575 cout << "sample_increment: " << sample_increment << endl;
1576 cout << "sample: " << sample1 << " -> ";
1577 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1579 for (int i = 0; i < 108003; i++) {
1580 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, true /* use_subframes */ );
1581 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, true /* use_subframes */ );
1583 if ((i > 0) && ( ((oldsample - sample1) != sample_increment) && ((oldsample - sample1) != (sample_increment + 1)) && ((oldsample - sample1) != (sample_increment - 1)))) {
1584 cout << "ERROR: sample increment not right: " << (oldsample - sample1) << " != " << sample_increment << endl;
1585 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1586 cout << "sample: " << sample1 << endl;
1587 cout << "sample: " << sample1 << " -> ";
1588 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1592 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames || smpte2.subframes != smpte1.subframes) {
1593 cout << "ERROR: smpte2 not equal smpte1" << endl;
1594 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1595 cout << "sample: " << sample1 << endl;
1596 cout << "sample: " << sample1 << " -> ";
1597 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1600 oldsample = sample1;
1601 session->smpte_decrement( smpte1 );
1604 cout << "sample_decrement: " << sample_increment << endl;
1605 cout << "sample: " << sample1 << " -> ";
1606 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1611 #ifdef SMPTE_SAMPLE_TEST_5
1612 // Test 5: use_offset = true, use_subframes = false, increment seconds
1613 cout << "use_offset = true, use_subframes = false, increment seconds" << endl;
1619 smpte1.subframes = 0;
1620 sample1 = oldsample = 0;
1621 sample_increment = session->frame_rate();
1623 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1624 cout << "Starting at sample: " << sample1 << " -> ";
1625 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1627 for (int i = 0; i < 3600; i++) {
1628 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1629 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1631 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1632 // cout << "sample: " << sample1 << endl;
1633 // cout << "sample: " << sample1 << " -> ";
1634 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1636 // if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1638 // cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1642 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1643 cout << "ERROR: smpte2 not equal smpte1" << endl;
1644 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1645 cout << "sample: " << sample1 << endl;
1646 cout << "sample: " << sample1 << " -> ";
1647 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1650 oldsample = sample1;
1651 session->smpte_increment_seconds( smpte1 );
1654 cout << "sample_increment: " << sample_increment << endl;
1655 cout << "sample: " << sample1 << " -> ";
1656 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1660 #ifdef SMPTE_SAMPLE_TEST_6
1661 // Test 6: use_offset = true, use_subframes = false, increment minutes
1662 cout << "use_offset = true, use_subframes = false, increment minutes" << endl;
1668 smpte1.subframes = 0;
1669 sample1 = oldsample = 0;
1670 sample_increment = session->frame_rate() * 60;
1672 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1673 cout << "Starting at sample: " << sample1 << " -> ";
1674 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1676 for (int i = 0; i < 60; i++) {
1677 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1678 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1680 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1681 // cout << "sample: " << sample1 << endl;
1682 // cout << "sample: " << sample1 << " -> ";
1683 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1685 // if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1687 // cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1691 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1692 cout << "ERROR: smpte2 not equal smpte1" << endl;
1693 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1694 cout << "sample: " << sample1 << endl;
1695 cout << "sample: " << sample1 << " -> ";
1696 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1699 oldsample = sample1;
1700 session->smpte_increment_minutes( smpte1 );
1703 cout << "sample_increment: " << sample_increment << endl;
1704 cout << "sample: " << sample1 << " -> ";
1705 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1708 #ifdef SMPTE_SAMPLE_TEST_7
1709 // Test 7: use_offset = true, use_subframes = false, increment hours
1710 cout << "use_offset = true, use_subframes = false, increment hours" << endl;
1716 smpte1.subframes = 0;
1717 sample1 = oldsample = 0;
1718 sample_increment = session->frame_rate() * 60 * 60;
1720 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1721 cout << "Starting at sample: " << sample1 << " -> ";
1722 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1724 for (int i = 0; i < 10; i++) {
1725 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1726 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1728 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1729 // cout << "sample: " << sample1 << endl;
1730 // cout << "sample: " << sample1 << " -> ";
1731 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1733 // if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1735 // cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1739 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1740 cout << "ERROR: smpte2 not equal smpte1" << endl;
1741 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1742 cout << "sample: " << sample1 << endl;
1743 cout << "sample: " << sample1 << " -> ";
1744 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1747 oldsample = sample1;
1748 session->smpte_increment_hours( smpte1 );
1751 cout << "sample_increment: " << sample_increment << endl;
1752 cout << "sample: " << sample1 << " -> ";
1753 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1762 AudioClock::minsec_frame_from_display () const
1768 int hrs = atoi (ms_hours_label.get_text());
1769 int mins = atoi (ms_minutes_label.get_text());
1770 float secs = atof (ms_seconds_label.get_text());
1772 nframes_t sr = session->frame_rate();
1774 return (nframes_t) floor ((hrs * 60.0f * 60.0f * sr) + (mins * 60.0f * sr) + (secs * sr));
1778 AudioClock::bbt_frame_from_display (nframes_t pos) const
1781 error << "AudioClock::current_time() called with BBT mode but without session!" << endmsg;
1786 any.type = AnyTime::BBT;
1788 any.bbt.bars = atoi (bars_label.get_text());
1789 any.bbt.beats = atoi (beats_label.get_text());
1790 any.bbt.ticks = atoi (ticks_label.get_text());
1792 nframes_t ret = session->convert_to_frames_at (pos, any);
1799 AudioClock::bbt_frame_duration_from_display (nframes_t pos) const
1802 error << "AudioClock::current_time() called with BBT mode but without session!" << endmsg;
1809 bbt.bars = atoi (bars_label.get_text());
1810 bbt.beats = atoi (beats_label.get_text());
1811 bbt.ticks = atoi (ticks_label.get_text());
1813 return session->tempo_map().bbt_duration_at(pos,bbt,1);
1817 AudioClock::audio_frame_from_display () const
1819 return (nframes_t) atoi (audio_frames_label.get_text());
1823 AudioClock::build_ops_menu ()
1825 using namespace Menu_Helpers;
1826 ops_menu = new Menu;
1827 MenuList& ops_items = ops_menu->items();
1828 ops_menu->set_name ("ArdourContextMenu");
1830 Menu *mode_menu = manage (new Menu);
1831 MenuList& mode_items = mode_menu->items();
1832 mode_menu->set_name ("ArdourContextMenu");
1834 mode_items.push_back (MenuElem (_("Timecode"), bind (mem_fun(*this, &AudioClock::set_mode), SMPTE)));
1835 mode_items.push_back (MenuElem (_("Bars:Beats"), bind (mem_fun(*this, &AudioClock::set_mode), BBT)));
1836 mode_items.push_back (MenuElem (_("Minutes:Seconds"), bind (mem_fun(*this, &AudioClock::set_mode), MinSec)));
1837 mode_items.push_back (MenuElem (_("Audio Frames"), bind (mem_fun(*this, &AudioClock::set_mode), Frames)));
1838 mode_items.push_back (MenuElem (_("Off"), bind (mem_fun(*this, &AudioClock::set_mode), Off)));
1840 ops_items.push_back (MenuElem (_("Mode"), *mode_menu));
1844 AudioClock::set_mode (Mode m)
1846 /* slightly tricky: this is called from within the ARDOUR_UI
1847 constructor by some of its clock members. at that time
1848 the instance pointer is unset, so we have to be careful.
1849 the main idea is to drop keyboard focus in case we had
1850 started editing the clock and then we switch clock mode.
1853 clock_base.grab_focus ();
1863 clock_base.remove ();
1873 clock_base.add (smpte_packer_hbox);
1877 clock_base.add (bbt_packer_hbox);
1881 clock_base.add (minsec_packer_hbox);
1885 clock_base.add (frames_packer_hbox);
1892 set_size_requests ();
1894 set (last_when, true);
1895 clock_base.show_all ();
1896 key_entry_state = 0;
1898 if (!is_transient) {
1899 ModeChanged (); /* EMIT SIGNAL */
1904 AudioClock::set_size_requests ()
1906 /* note that in some fonts, "88" is narrower than "00", hence the 2 pixel padding */
1910 Gtkmm2ext::set_size_request_to_display_given_text (hours_label, "-00", 5, 5);
1911 Gtkmm2ext::set_size_request_to_display_given_text (minutes_label, "00", 5, 5);
1912 Gtkmm2ext::set_size_request_to_display_given_text (seconds_label, "00", 5, 5);
1913 Gtkmm2ext::set_size_request_to_display_given_text (frames_label, "00", 5, 5);
1917 Gtkmm2ext::set_size_request_to_display_given_text (bars_label, "-000", 5, 5);
1918 Gtkmm2ext::set_size_request_to_display_given_text (beats_label, "00", 5, 5);
1919 Gtkmm2ext::set_size_request_to_display_given_text (ticks_label, "0000", 5, 5);
1923 Gtkmm2ext::set_size_request_to_display_given_text (ms_hours_label, "00", 5, 5);
1924 Gtkmm2ext::set_size_request_to_display_given_text (ms_minutes_label, "00", 5, 5);
1925 Gtkmm2ext::set_size_request_to_display_given_text (ms_seconds_label, "00.000", 5, 5);
1929 Gtkmm2ext::set_size_request_to_display_given_text (audio_frames_label, "0000000000", 5, 5);