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 */
1085 AudioClock::field_button_scroll_event (GdkEventScroll *ev, Field field)
1087 if (session == 0) return FALSE;
1089 nframes_t frames = 0;
1091 switch (ev->direction) {
1094 frames = get_frames (field);
1096 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
1099 set (current_time() + frames, true);
1100 ValueChanged (); /* EMIT_SIGNAL */
1104 case GDK_SCROLL_DOWN:
1105 frames = get_frames (field);
1107 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
1111 if ((double)current_time() - (double)frames < 0.0) {
1114 set (current_time() - frames, true);
1117 ValueChanged (); /* EMIT_SIGNAL */
1130 AudioClock::field_motion_notify_event (GdkEventMotion *ev, Field field)
1132 if (session == 0 || !dragging) {
1136 float pixel_frame_scale_factor = 0.2f;
1139 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
1140 pixel_frame_scale_factor = 0.1f;
1144 if (Keyboard::modifier_state_contains (ev->state,
1145 Keyboard::Control|Keyboard::Alt)) {
1147 pixel_frame_scale_factor = 0.025f;
1150 double y_delta = ev->y - drag_y;
1152 drag_accum += y_delta*pixel_frame_scale_factor;
1156 if (trunc(drag_accum) != 0) {
1161 dir = (drag_accum < 0 ? 1:-1);
1162 pos = current_time();
1163 frames = get_frames (field,pos,dir);
1165 if (frames != 0 && frames * drag_accum < current_time()) {
1167 set ((nframes_t) floor (pos - drag_accum * frames), false); // minus because up is negative in computer-land
1175 ValueChanged(); /* EMIT_SIGNAL */
1184 AudioClock::get_frames (Field field,nframes_t pos,int dir)
1187 nframes_t frames = 0;
1191 frames = (nframes_t) floor (3600.0 * session->frame_rate());
1194 frames = (nframes_t) floor (60.0 * session->frame_rate());
1197 frames = session->frame_rate();
1200 frames = (nframes_t) floor (session->frame_rate() / session->smpte_frames_per_second());
1208 frames = (nframes_t) floor (3600.0 * session->frame_rate());
1211 frames = (nframes_t) floor (60.0 * session->frame_rate());
1214 frames = session->frame_rate();
1221 frames = session->tempo_map().bbt_duration_at(pos,bbt,dir);
1227 frames = session->tempo_map().bbt_duration_at(pos,bbt,dir);
1233 frames = session->tempo_map().bbt_duration_at(pos,bbt,dir);
1241 AudioClock::current_time (nframes_t pos) const
1247 ret = smpte_frame_from_display ();
1250 ret = bbt_frame_from_display (pos);
1254 ret = minsec_frame_from_display ();
1258 ret = audio_frame_from_display ();
1269 AudioClock::current_duration (nframes_t pos) const
1275 ret = smpte_frame_from_display ();
1278 ret = bbt_frame_duration_from_display (pos);
1282 ret = minsec_frame_from_display ();
1286 ret = audio_frame_from_display ();
1297 AudioClock::smpte_sanitize_display()
1299 // Check SMPTE fields for sanity, possibly adjusting values
1300 if (atoi(minutes_label.get_text()) > 59) {
1301 minutes_label.set_text("59");
1304 if (atoi(seconds_label.get_text()) > 59) {
1305 seconds_label.set_text("59");
1308 switch ((long)rint(session->smpte_frames_per_second())) {
1310 if (atoi(frames_label.get_text()) > 23) {
1311 frames_label.set_text("23");
1315 if (atoi(frames_label.get_text()) > 24) {
1316 frames_label.set_text("24");
1320 if (atoi(frames_label.get_text()) > 29) {
1321 frames_label.set_text("29");
1328 if (session->smpte_drop_frames()) {
1329 if ((atoi(minutes_label.get_text()) % 10) && (atoi(seconds_label.get_text()) == 0) && (atoi(frames_label.get_text()) < 2)) {
1330 frames_label.set_text("02");
1336 AudioClock::smpte_frame_from_display () const
1345 smpte.hours = atoi (hours_label.get_text());
1346 smpte.minutes = atoi (minutes_label.get_text());
1347 smpte.seconds = atoi (seconds_label.get_text());
1348 smpte.frames = atoi (frames_label.get_text());
1349 smpte.rate = session->smpte_frames_per_second();
1350 smpte.drop= session->smpte_drop_frames();
1352 session->smpte_to_sample( smpte, sample, false /* use_offset */, false /* use_subframes */ );
1356 #define SMPTE_SAMPLE_TEST_1
1357 #define SMPTE_SAMPLE_TEST_2
1358 #define SMPTE_SAMPLE_TEST_3
1359 #define SMPTE_SAMPLE_TEST_4
1360 #define SMPTE_SAMPLE_TEST_5
1361 #define SMPTE_SAMPLE_TEST_6
1362 #define SMPTE_SAMPLE_TEST_7
1364 // Testcode for smpte<->sample conversions (P.S.)
1367 nframes_t oldsample = 0;
1369 nframes_t sample_increment;
1371 sample_increment = (long)rint(session->frame_rate() / session->smpte_frames_per_second);
1373 #ifdef SMPTE_SAMPLE_TEST_1
1374 // Test 1: use_offset = false, use_subframes = false
1375 cout << "use_offset = false, use_subframes = false" << endl;
1376 for (int i = 0; i < 108003; i++) {
1377 session->smpte_to_sample( smpte1, sample1, false /* use_offset */, false /* use_subframes */ );
1378 session->sample_to_smpte( sample1, smpte2, false /* use_offset */, false /* use_subframes */ );
1380 if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
1381 cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1382 cout << "smpte1: " << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1383 cout << "sample: " << sample1 << endl;
1384 cout << "sample: " << sample1 << " -> ";
1385 cout << "smpte2: " << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1389 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1390 cout << "ERROR: smpte2 not equal smpte1" << endl;
1391 cout << "smpte1: " << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1392 cout << "sample: " << sample1 << endl;
1393 cout << "sample: " << sample1 << " -> ";
1394 cout << "smpte2: " << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1397 oldsample = sample1;
1398 session->smpte_increment( smpte1 );
1401 cout << "sample_increment: " << sample_increment << endl;
1402 cout << "sample: " << sample1 << " -> ";
1403 cout << "smpte: " << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1406 #ifdef SMPTE_SAMPLE_TEST_2
1407 // Test 2: use_offset = true, use_subframes = false
1408 cout << "use_offset = true, use_subframes = false" << endl;
1414 smpte1.subframes = 0;
1415 sample1 = oldsample = 0;
1417 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1418 cout << "Starting at sample: " << sample1 << " -> ";
1419 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1421 for (int i = 0; i < 108003; i++) {
1422 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1423 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1425 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1426 // cout << "sample: " << sample1 << endl;
1427 // cout << "sample: " << sample1 << " -> ";
1428 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1430 if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
1431 cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1432 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1433 cout << "sample: " << sample1 << endl;
1434 cout << "sample: " << sample1 << " -> ";
1435 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1439 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1440 cout << "ERROR: smpte2 not equal smpte1" << endl;
1441 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1442 cout << "sample: " << sample1 << endl;
1443 cout << "sample: " << sample1 << " -> ";
1444 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1447 oldsample = sample1;
1448 session->smpte_increment( smpte1 );
1451 cout << "sample_increment: " << sample_increment << endl;
1452 cout << "sample: " << sample1 << " -> ";
1453 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1456 #ifdef SMPTE_SAMPLE_TEST_3
1457 // Test 3: use_offset = true, use_subframes = false, decrement
1458 cout << "use_offset = true, use_subframes = false, decrement" << endl;
1460 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1461 cout << "Starting at sample: " << sample1 << " -> ";
1462 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1464 for (int i = 0; i < 108003; i++) {
1465 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1466 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1468 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1469 // cout << "sample: " << sample1 << endl;
1470 // cout << "sample: " << sample1 << " -> ";
1471 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1473 if ((i > 0) && ( ((oldsample - sample1) != sample_increment) && ((oldsample - sample1) != (sample_increment + 1)) && ((oldsample - sample1) != (sample_increment - 1)))) {
1474 cout << "ERROR: sample increment not right: " << (oldsample - sample1) << " != " << sample_increment << endl;
1475 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1476 cout << "sample: " << sample1 << endl;
1477 cout << "sample: " << sample1 << " -> ";
1478 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1482 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1483 cout << "ERROR: smpte2 not equal smpte1" << endl;
1484 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1485 cout << "sample: " << sample1 << endl;
1486 cout << "sample: " << sample1 << " -> ";
1487 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1490 oldsample = sample1;
1491 session->smpte_decrement( smpte1 );
1494 cout << "sample_decrement: " << sample_increment << endl;
1495 cout << "sample: " << sample1 << " -> ";
1496 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1500 #ifdef SMPTE_SAMPLE_TEST_4
1501 // Test 4: use_offset = true, use_subframes = true
1502 cout << "use_offset = true, use_subframes = true" << endl;
1504 for (long sub = 5; sub < 80; sub += 5) {
1509 smpte1.subframes = 0;
1510 sample1 = oldsample = (sample_increment * sub) / 80;
1512 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, true /* use_subframes */ );
1514 cout << "starting at sample: " << sample1 << " -> ";
1515 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1517 for (int i = 0; i < 108003; i++) {
1518 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, true /* use_subframes */ );
1519 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, true /* use_subframes */ );
1521 if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
1522 cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1523 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1524 cout << "sample: " << sample1 << endl;
1525 cout << "sample: " << sample1 << " -> ";
1526 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1530 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames || smpte2.subframes != smpte1.subframes) {
1531 cout << "ERROR: smpte2 not equal smpte1" << endl;
1532 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1533 cout << "sample: " << sample1 << endl;
1534 cout << "sample: " << sample1 << " -> ";
1535 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1538 oldsample = sample1;
1539 session->smpte_increment( smpte1 );
1542 cout << "sample_increment: " << sample_increment << endl;
1543 cout << "sample: " << sample1 << " -> ";
1544 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1546 for (int i = 0; i < 108003; i++) {
1547 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, true /* use_subframes */ );
1548 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, true /* use_subframes */ );
1550 if ((i > 0) && ( ((oldsample - sample1) != sample_increment) && ((oldsample - sample1) != (sample_increment + 1)) && ((oldsample - sample1) != (sample_increment - 1)))) {
1551 cout << "ERROR: sample increment not right: " << (oldsample - sample1) << " != " << sample_increment << endl;
1552 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1553 cout << "sample: " << sample1 << endl;
1554 cout << "sample: " << sample1 << " -> ";
1555 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1559 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames || smpte2.subframes != smpte1.subframes) {
1560 cout << "ERROR: smpte2 not equal smpte1" << endl;
1561 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1562 cout << "sample: " << sample1 << endl;
1563 cout << "sample: " << sample1 << " -> ";
1564 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1567 oldsample = sample1;
1568 session->smpte_decrement( smpte1 );
1571 cout << "sample_decrement: " << sample_increment << endl;
1572 cout << "sample: " << sample1 << " -> ";
1573 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1578 #ifdef SMPTE_SAMPLE_TEST_5
1579 // Test 5: use_offset = true, use_subframes = false, increment seconds
1580 cout << "use_offset = true, use_subframes = false, increment seconds" << endl;
1586 smpte1.subframes = 0;
1587 sample1 = oldsample = 0;
1588 sample_increment = session->frame_rate();
1590 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1591 cout << "Starting at sample: " << sample1 << " -> ";
1592 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1594 for (int i = 0; i < 3600; i++) {
1595 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1596 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1598 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1599 // cout << "sample: " << sample1 << endl;
1600 // cout << "sample: " << sample1 << " -> ";
1601 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1603 // if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1605 // cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1609 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1610 cout << "ERROR: smpte2 not equal smpte1" << endl;
1611 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1612 cout << "sample: " << sample1 << endl;
1613 cout << "sample: " << sample1 << " -> ";
1614 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1617 oldsample = sample1;
1618 session->smpte_increment_seconds( smpte1 );
1621 cout << "sample_increment: " << sample_increment << endl;
1622 cout << "sample: " << sample1 << " -> ";
1623 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1627 #ifdef SMPTE_SAMPLE_TEST_6
1628 // Test 6: use_offset = true, use_subframes = false, increment minutes
1629 cout << "use_offset = true, use_subframes = false, increment minutes" << endl;
1635 smpte1.subframes = 0;
1636 sample1 = oldsample = 0;
1637 sample_increment = session->frame_rate() * 60;
1639 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1640 cout << "Starting at sample: " << sample1 << " -> ";
1641 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1643 for (int i = 0; i < 60; i++) {
1644 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1645 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1647 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1648 // cout << "sample: " << sample1 << endl;
1649 // cout << "sample: " << sample1 << " -> ";
1650 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1652 // if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1654 // cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1658 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1659 cout << "ERROR: smpte2 not equal smpte1" << endl;
1660 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1661 cout << "sample: " << sample1 << endl;
1662 cout << "sample: " << sample1 << " -> ";
1663 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1666 oldsample = sample1;
1667 session->smpte_increment_minutes( smpte1 );
1670 cout << "sample_increment: " << sample_increment << endl;
1671 cout << "sample: " << sample1 << " -> ";
1672 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1675 #ifdef SMPTE_SAMPLE_TEST_7
1676 // Test 7: use_offset = true, use_subframes = false, increment hours
1677 cout << "use_offset = true, use_subframes = false, increment hours" << endl;
1683 smpte1.subframes = 0;
1684 sample1 = oldsample = 0;
1685 sample_increment = session->frame_rate() * 60 * 60;
1687 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1688 cout << "Starting at sample: " << sample1 << " -> ";
1689 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1691 for (int i = 0; i < 10; i++) {
1692 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1693 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1695 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1696 // cout << "sample: " << sample1 << endl;
1697 // cout << "sample: " << sample1 << " -> ";
1698 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1700 // if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1702 // cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1706 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1707 cout << "ERROR: smpte2 not equal smpte1" << endl;
1708 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1709 cout << "sample: " << sample1 << endl;
1710 cout << "sample: " << sample1 << " -> ";
1711 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1714 oldsample = sample1;
1715 session->smpte_increment_hours( smpte1 );
1718 cout << "sample_increment: " << sample_increment << endl;
1719 cout << "sample: " << sample1 << " -> ";
1720 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1729 AudioClock::minsec_frame_from_display () const
1735 int hrs = atoi (ms_hours_label.get_text());
1736 int mins = atoi (ms_minutes_label.get_text());
1737 float secs = atof (ms_seconds_label.get_text());
1739 nframes_t sr = session->frame_rate();
1741 return (nframes_t) floor ((hrs * 60.0f * 60.0f * sr) + (mins * 60.0f * sr) + (secs * sr));
1745 AudioClock::bbt_frame_from_display (nframes_t pos) const
1748 error << "AudioClock::current_time() called with BBT mode but without session!" << endmsg;
1753 any.type = AnyTime::BBT;
1755 any.bbt.bars = atoi (bars_label.get_text());
1756 any.bbt.beats = atoi (beats_label.get_text());
1757 any.bbt.ticks = atoi (ticks_label.get_text());
1759 nframes_t ret = session->convert_to_frames_at (pos, any);
1766 AudioClock::bbt_frame_duration_from_display (nframes_t pos) const
1769 error << "AudioClock::current_time() called with BBT mode but without session!" << endmsg;
1776 bbt.bars = atoi (bars_label.get_text());
1777 bbt.beats = atoi (beats_label.get_text());
1778 bbt.ticks = atoi (ticks_label.get_text());
1780 return session->tempo_map().bbt_duration_at(pos,bbt,1);
1784 AudioClock::audio_frame_from_display () const
1786 return (nframes_t) atoi (audio_frames_label.get_text());
1790 AudioClock::build_ops_menu ()
1792 using namespace Menu_Helpers;
1793 ops_menu = new Menu;
1794 MenuList& ops_items = ops_menu->items();
1795 ops_menu->set_name ("ArdourContextMenu");
1797 Menu *mode_menu = manage (new Menu);
1798 MenuList& mode_items = mode_menu->items();
1799 mode_menu->set_name ("ArdourContextMenu");
1801 mode_items.push_back (MenuElem (_("Timecode"), bind (mem_fun(*this, &AudioClock::set_mode), SMPTE)));
1802 mode_items.push_back (MenuElem (_("Bars:Beats"), bind (mem_fun(*this, &AudioClock::set_mode), BBT)));
1803 mode_items.push_back (MenuElem (_("Minutes:Seconds"), bind (mem_fun(*this, &AudioClock::set_mode), MinSec)));
1804 mode_items.push_back (MenuElem (_("Audio Frames"), bind (mem_fun(*this, &AudioClock::set_mode), Frames)));
1805 mode_items.push_back (MenuElem (_("Off"), bind (mem_fun(*this, &AudioClock::set_mode), Off)));
1807 ops_items.push_back (MenuElem (_("Mode"), *mode_menu));
1811 AudioClock::set_mode (Mode m)
1813 /* slightly tricky: this is called from within the ARDOUR_UI
1814 constructor by some of its clock members. at that time
1815 the instance pointer is unset, so we have to be careful.
1816 the main idea is to drop keyboard focus in case we had
1817 started editing the clock and then we switch clock mode.
1820 clock_base.grab_focus ();
1830 clock_base.remove ();
1840 clock_base.add (smpte_packer_hbox);
1844 clock_base.add (bbt_packer_hbox);
1848 clock_base.add (minsec_packer_hbox);
1852 clock_base.add (frames_packer_hbox);
1859 set_size_requests ();
1861 set (last_when, true);
1862 clock_base.show_all ();
1863 key_entry_state = 0;
1865 if (!is_transient) {
1866 ModeChanged (); /* EMIT SIGNAL */
1871 AudioClock::set_size_requests ()
1873 /* note that in some fonts, "88" is narrower than "00", hence the 2 pixel padding */
1877 Gtkmm2ext::set_size_request_to_display_given_text (hours_label, "-00", 5, 5);
1878 Gtkmm2ext::set_size_request_to_display_given_text (minutes_label, "00", 5, 5);
1879 Gtkmm2ext::set_size_request_to_display_given_text (seconds_label, "00", 5, 5);
1880 Gtkmm2ext::set_size_request_to_display_given_text (frames_label, "00", 5, 5);
1884 Gtkmm2ext::set_size_request_to_display_given_text (bars_label, "-000", 5, 5);
1885 Gtkmm2ext::set_size_request_to_display_given_text (beats_label, "00", 5, 5);
1886 Gtkmm2ext::set_size_request_to_display_given_text (ticks_label, "0000", 5, 5);
1890 Gtkmm2ext::set_size_request_to_display_given_text (ms_hours_label, "00", 5, 5);
1891 Gtkmm2ext::set_size_request_to_display_given_text (ms_minutes_label, "00", 5, 5);
1892 Gtkmm2ext::set_size_request_to_display_given_text (ms_seconds_label, "00.000", 5, 5);
1896 Gtkmm2ext::set_size_request_to_display_given_text (audio_frames_label, "0000000000", 5, 5);