2 Copyright (C) 1999 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #include <cstdio> // for sprintf
24 #include <pbd/convert.h>
25 #include <pbd/enumwriter.h>
27 #include <gtkmm2ext/utils.h>
29 #include <ardour/ardour.h>
30 #include <ardour/session.h>
31 #include <ardour/tempo.h>
32 #include <sigc++/bind.h>
34 #include "ardour_ui.h"
35 #include "audio_clock.h"
40 using namespace ARDOUR;
49 sigc::signal<void> AudioClock::ModeChanged;
50 vector<AudioClock*> AudioClock::clocks;
52 const uint32_t AudioClock::field_length[(int) AudioClock::AudioFrames+1] = {
54 2, /* SMPTE_Minutes */
55 2, /* SMPTE_Seconds */
66 AudioClock::AudioClock (std::string clock_name, bool transient, std::string widget_name, bool allow_edit, bool duration, bool with_info)
68 is_transient (transient),
69 is_duration (duration),
70 editable (allow_edit),
86 frames_upper_info_label = manage (new Label);
87 frames_lower_info_label = manage (new Label);
88 smpte_upper_info_label = manage (new Label);
89 smpte_lower_info_label = manage (new Label);
90 bbt_upper_info_label = manage (new Label);
91 bbt_lower_info_label = manage (new Label);
93 frames_upper_info_label->set_name ("AudioClockFramesUpperInfo");
94 frames_lower_info_label->set_name ("AudioClockFramesLowerInfo");
95 smpte_upper_info_label->set_name ("AudioClockSMPTEUpperInfo");
96 smpte_lower_info_label->set_name ("AudioClockSMPTELowerInfo");
97 bbt_upper_info_label->set_name ("AudioClockBBTUpperInfo");
98 bbt_lower_info_label->set_name ("AudioClockBBTLowerInfo");
100 Gtkmm2ext::set_size_request_to_display_given_text(*smpte_upper_info_label, "23.98",0,0);
101 Gtkmm2ext::set_size_request_to_display_given_text(*smpte_lower_info_label, "NDF",0,0);
103 frames_info_box.pack_start (*frames_upper_info_label, true, true);
104 frames_info_box.pack_start (*frames_lower_info_label, true, true);
105 smpte_info_box.pack_start (*smpte_upper_info_label, true, true);
106 smpte_info_box.pack_start (*smpte_lower_info_label, true, true);
107 bbt_info_box.pack_start (*bbt_upper_info_label, true, true);
108 bbt_info_box.pack_start (*bbt_lower_info_label, true, true);
111 frames_upper_info_label = 0;
112 frames_lower_info_label = 0;
113 smpte_upper_info_label = 0;
114 smpte_lower_info_label = 0;
115 bbt_upper_info_label = 0;
116 bbt_lower_info_label = 0;
119 audio_frames_ebox.add (audio_frames_label);
121 frames_packer.set_homogeneous (false);
122 frames_packer.set_border_width (2);
123 frames_packer.pack_start (audio_frames_ebox, false, false);
126 frames_packer.pack_start (frames_info_box, false, false, 5);
129 frames_packer_hbox.pack_start (frames_packer, true, false);
131 hours_ebox.add (hours_label);
132 minutes_ebox.add (minutes_label);
133 seconds_ebox.add (seconds_label);
134 frames_ebox.add (frames_label);
135 bars_ebox.add (bars_label);
136 beats_ebox.add (beats_label);
137 ticks_ebox.add (ticks_label);
138 ms_hours_ebox.add (ms_hours_label);
139 ms_minutes_ebox.add (ms_minutes_label);
140 ms_seconds_ebox.add (ms_seconds_label);
142 smpte_packer.set_homogeneous (false);
143 smpte_packer.set_border_width (2);
144 smpte_packer.pack_start (hours_ebox, false, false);
145 smpte_packer.pack_start (colon1, false, false);
146 smpte_packer.pack_start (minutes_ebox, false, false);
147 smpte_packer.pack_start (colon2, false, false);
148 smpte_packer.pack_start (seconds_ebox, false, false);
149 smpte_packer.pack_start (colon3, false, false);
150 smpte_packer.pack_start (frames_ebox, false, false);
153 smpte_packer.pack_start (smpte_info_box, false, false, 5);
156 smpte_packer_hbox.pack_start (smpte_packer, true, false);
158 bbt_packer.set_homogeneous (false);
159 bbt_packer.set_border_width (2);
160 bbt_packer.pack_start (bars_ebox, false, false);
161 bbt_packer.pack_start (b1, false, false);
162 bbt_packer.pack_start (beats_ebox, false, false);
163 bbt_packer.pack_start (b2, false, false);
164 bbt_packer.pack_start (ticks_ebox, false, false);
167 bbt_packer.pack_start (bbt_info_box, false, false, 5);
170 bbt_packer_hbox.pack_start (bbt_packer, true, false);
172 minsec_packer.set_homogeneous (false);
173 minsec_packer.set_border_width (2);
174 minsec_packer.pack_start (ms_hours_ebox, false, false);
175 minsec_packer.pack_start (colon4, false, false);
176 minsec_packer.pack_start (ms_minutes_ebox, false, false);
177 minsec_packer.pack_start (colon5, false, false);
178 minsec_packer.pack_start (ms_seconds_ebox, false, false);
180 minsec_packer_hbox.pack_start (minsec_packer, true, false);
182 clock_frame.set_shadow_type (Gtk::SHADOW_IN);
183 clock_frame.set_name ("BaseFrame");
185 clock_frame.add (clock_base);
187 set_widget_name (widget_name);
189 _mode = BBT; /* lie to force mode switch */
192 pack_start (clock_frame, true, true);
194 /* the clock base handles button releases for menu popup regardless of
195 editable status. if the clock is editable, the clock base is where
196 we pass focus to after leaving the last editable "field", which
197 will then shutdown editing till the user starts it up again.
199 it does this because the focus out event on the field disables
200 keyboard event handling, and we don't connect anything up to
201 notice focus in on the clock base. hence, keyboard event handling
205 clock_base.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::SCROLL_MASK);
206 clock_base.signal_button_release_event().connect (bind (mem_fun (*this, &AudioClock::field_button_release_event), SMPTE_Hours));
208 Session::SMPTEOffsetChanged.connect (mem_fun (*this, &AudioClock::smpte_offset_changed));
214 set (last_when, true);
217 clocks.push_back (this);
222 AudioClock::set_widget_name (string name)
224 Widget::set_name (name);
226 clock_base.set_name (name);
228 audio_frames_label.set_name (name);
229 hours_label.set_name (name);
230 minutes_label.set_name (name);
231 seconds_label.set_name (name);
232 frames_label.set_name (name);
233 bars_label.set_name (name);
234 beats_label.set_name (name);
235 ticks_label.set_name (name);
236 ms_hours_label.set_name (name);
237 ms_minutes_label.set_name (name);
238 ms_seconds_label.set_name (name);
239 hours_ebox.set_name (name);
240 minutes_ebox.set_name (name);
241 seconds_ebox.set_name (name);
242 frames_ebox.set_name (name);
243 audio_frames_ebox.set_name (name);
244 bars_ebox.set_name (name);
245 beats_ebox.set_name (name);
246 ticks_ebox.set_name (name);
247 ms_hours_ebox.set_name (name);
248 ms_minutes_ebox.set_name (name);
249 ms_seconds_ebox.set_name (name);
251 colon1.set_name (name);
252 colon2.set_name (name);
253 colon3.set_name (name);
254 colon4.set_name (name);
255 colon5.set_name (name);
263 AudioClock::setup_events ()
265 clock_base.set_flags (Gtk::CAN_FOCUS);
267 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);
268 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);
269 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);
270 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);
271 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);
272 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);
273 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);
274 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);
275 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);
276 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);
277 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);
279 hours_ebox.set_flags (Gtk::CAN_FOCUS);
280 minutes_ebox.set_flags (Gtk::CAN_FOCUS);
281 seconds_ebox.set_flags (Gtk::CAN_FOCUS);
282 frames_ebox.set_flags (Gtk::CAN_FOCUS);
283 audio_frames_ebox.set_flags (Gtk::CAN_FOCUS);
284 bars_ebox.set_flags (Gtk::CAN_FOCUS);
285 beats_ebox.set_flags (Gtk::CAN_FOCUS);
286 ticks_ebox.set_flags (Gtk::CAN_FOCUS);
287 ms_hours_ebox.set_flags (Gtk::CAN_FOCUS);
288 ms_minutes_ebox.set_flags (Gtk::CAN_FOCUS);
289 ms_seconds_ebox.set_flags (Gtk::CAN_FOCUS);
291 hours_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), SMPTE_Hours));
292 minutes_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), SMPTE_Minutes));
293 seconds_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), SMPTE_Seconds));
294 frames_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), SMPTE_Frames));
295 audio_frames_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), AudioFrames));
296 bars_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), Bars));
297 beats_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), Beats));
298 ticks_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), Ticks));
299 ms_hours_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), MS_Hours));
300 ms_minutes_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), MS_Minutes));
301 ms_seconds_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), MS_Seconds));
303 hours_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), SMPTE_Hours));
304 minutes_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), SMPTE_Minutes));
305 seconds_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), SMPTE_Seconds));
306 frames_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), SMPTE_Frames));
307 audio_frames_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), AudioFrames));
308 bars_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), Bars));
309 beats_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), Beats));
310 ticks_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), Ticks));
311 ms_hours_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), MS_Hours));
312 ms_minutes_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), MS_Minutes));
313 ms_seconds_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), MS_Seconds));
315 hours_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), SMPTE_Hours));
316 minutes_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), SMPTE_Minutes));
317 seconds_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), SMPTE_Seconds));
318 frames_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), SMPTE_Frames));
319 audio_frames_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), AudioFrames));
320 bars_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), Bars));
321 beats_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), Beats));
322 ticks_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), Ticks));
323 ms_hours_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), MS_Hours));
324 ms_minutes_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), MS_Minutes));
325 ms_seconds_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), MS_Seconds));
327 hours_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), SMPTE_Hours));
328 minutes_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), SMPTE_Minutes));
329 seconds_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), SMPTE_Seconds));
330 frames_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), SMPTE_Frames));
331 audio_frames_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), AudioFrames));
332 bars_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), Bars));
333 beats_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), Beats));
334 ticks_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), Ticks));
335 ms_hours_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), MS_Hours));
336 ms_minutes_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), MS_Minutes));
337 ms_seconds_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), MS_Seconds));
339 hours_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), SMPTE_Hours));
340 minutes_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), SMPTE_Minutes));
341 seconds_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), SMPTE_Seconds));
342 frames_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), SMPTE_Frames));
343 audio_frames_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), AudioFrames));
344 bars_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), Bars));
345 beats_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), Beats));
346 ticks_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), Ticks));
347 ms_hours_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), MS_Hours));
348 ms_minutes_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), MS_Minutes));
349 ms_seconds_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), MS_Seconds));
351 hours_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), SMPTE_Hours));
352 minutes_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), SMPTE_Minutes));
353 seconds_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), SMPTE_Seconds));
354 frames_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), SMPTE_Frames));
355 audio_frames_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), AudioFrames));
356 bars_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), Bars));
357 beats_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), Beats));
358 ticks_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), Ticks));
359 ms_hours_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), MS_Hours));
360 ms_minutes_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), MS_Minutes));
361 ms_seconds_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), MS_Seconds));
363 hours_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), SMPTE_Hours));
364 minutes_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), SMPTE_Minutes));
365 seconds_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), SMPTE_Seconds));
366 frames_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), SMPTE_Frames));
367 audio_frames_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), AudioFrames));
368 bars_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), Bars));
369 beats_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), Beats));
370 ticks_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), Ticks));
371 ms_hours_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), MS_Hours));
372 ms_minutes_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), MS_Minutes));
373 ms_seconds_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), MS_Seconds));
377 AudioClock::on_realize ()
381 /* styles are not available until the widgets are bound to a window */
383 set_size_requests ();
387 AudioClock::set (nframes_t when, bool force)
390 if ((!force && !is_visible()) || session == 0) {
394 if (when == last_when && !force) {
400 set_smpte (when, force);
404 set_bbt (when, force);
408 set_minsec (when, force);
412 set_frames (when, force);
423 AudioClock::smpte_offset_changed ()
430 current = current_duration();
432 current = current_time ();
442 AudioClock::set_frames (nframes_t when, bool force)
445 snprintf (buf, sizeof (buf), "%u", when);
446 audio_frames_label.set_text (buf);
448 if (frames_upper_info_label) {
449 nframes_t rate = session->frame_rate();
451 if (fmod (rate, 1000.0) == 0.000) {
452 sprintf (buf, "%uK", rate/1000);
454 sprintf (buf, "%.3fK", rate/1000.0f);
457 frames_upper_info_label->set_text (buf);
459 float vid_pullup = Config->get_video_pullup();
461 if (vid_pullup == 0.0) {
462 frames_lower_info_label->set_text(_("none"));
464 sprintf (buf, "%-6.4f", vid_pullup);
465 frames_lower_info_label->set_text (buf);
471 AudioClock::set_minsec (nframes_t when, bool force)
480 hrs = (int) floor (left / (session->frame_rate() * 60.0f * 60.0f));
481 left -= (nframes_t) floor (hrs * session->frame_rate() * 60.0f * 60.0f);
482 mins = (int) floor (left / (session->frame_rate() * 60.0f));
483 left -= (nframes_t) floor (mins * session->frame_rate() * 60.0f);
484 secs = left / (float) session->frame_rate();
486 if (force || hrs != ms_last_hrs) {
487 sprintf (buf, "%02d", hrs);
488 ms_hours_label.set_text (buf);
492 if (force || mins != ms_last_mins) {
493 sprintf (buf, "%02d", mins);
494 ms_minutes_label.set_text (buf);
498 if (force || secs != ms_last_secs) {
499 sprintf (buf, "%06.3f", secs);
500 ms_seconds_label.set_text (buf);
506 AudioClock::set_smpte (nframes_t when, bool force)
512 session->smpte_duration (when, smpte);
514 session->smpte_time (when, smpte);
517 if (force || smpte.hours != last_hrs || smpte.negative != last_negative) {
518 if (smpte.negative) {
519 sprintf (buf, "-%02" PRIu32, smpte.hours);
521 sprintf (buf, " %02" PRIu32, smpte.hours);
523 hours_label.set_text (buf);
524 last_hrs = smpte.hours;
525 last_negative = smpte.negative;
528 if (force || smpte.minutes != last_mins) {
529 sprintf (buf, "%02" PRIu32, smpte.minutes);
530 minutes_label.set_text (buf);
531 last_mins = smpte.minutes;
534 if (force || smpte.seconds != last_secs) {
535 sprintf (buf, "%02" PRIu32, smpte.seconds);
536 seconds_label.set_text (buf);
537 last_secs = smpte.seconds;
540 if (force || smpte.frames != last_frames) {
541 sprintf (buf, "%02" PRIu32, smpte.frames);
542 frames_label.set_text (buf);
543 last_frames = smpte.frames;
546 if (smpte_upper_info_label) {
547 double smpte_frames = session->smpte_frames_per_second();
549 if ( fmod(smpte_frames, 1.0) == 0.0) {
550 sprintf (buf, "%u", int (smpte_frames));
552 sprintf (buf, "%.2f", smpte_frames);
555 smpte_upper_info_label->set_text (buf);
557 if (session->smpte_drop_frames()) {
560 sprintf (buf, "NDF");
563 smpte_lower_info_label->set_text (buf);
568 AudioClock::set_bbt (nframes_t when, bool force)
573 session->tempo_map().bbt_time (when, bbt);
574 sprintf (buf, "%03" PRIu32, bbt.bars);
575 bars_label.set_text (buf);
576 sprintf (buf, "%02" PRIu32, bbt.beats);
577 beats_label.set_text (buf);
578 sprintf (buf, "%04" PRIu32, bbt.ticks);
579 ticks_label.set_text (buf);
581 if (bbt_upper_info_label) {
582 TempoMap::Metric m (session->tempo_map().metric_at (when));
583 sprintf (buf, "%-5.2f", m.tempo().beats_per_minute());
584 bbt_lower_info_label->set_text (buf);
585 sprintf (buf, "%g|%g", m.meter().beats_per_bar(), m.meter().note_divisor());
586 bbt_upper_info_label->set_text (buf);
591 AudioClock::set_session (Session *s)
598 XMLNode* node = session->extra_xml (X_("ClockModes"));
599 AudioClock::Mode amode;
602 if ((prop = node->property (_name.c_str())) != 0) {
603 amode = AudioClock::Mode (string_2_enum (prop->value(), amode));
608 set (last_when, true);
613 AudioClock::field_key_release_event (GdkEventKey *ev, Field field)
618 bool move_on = false;
622 label = &hours_label;
625 label = &minutes_label;
628 label = &seconds_label;
631 label = &frames_label;
635 label = &audio_frames_label;
639 label = &ms_hours_label;
642 label = &ms_minutes_label;
645 label = &ms_seconds_label;
652 label = &beats_label;
655 label = &ticks_label;
661 switch (ev->keyval) {
705 if (_mode == MinSec && field == MS_Seconds) {
719 clock_base.grab_focus ();
728 if (key_entry_state == 0) {
730 /* initialize with a fresh new string */
732 if (field != AudioFrames) {
733 for (uint32_t xn = 0; xn < field_length[field] - 1; ++xn) {
742 string existing = label->get_text();
743 if (existing.length() >= field_length[field]) {
744 new_text = existing.substr (1, field_length[field] - 1);
746 new_text = existing.substr (0, field_length[field] - 1);
750 new_text += new_char;
751 label->set_text (new_text);
755 if (key_entry_state == field_length[field]) {
761 if (key_entry_state) {
768 // Check SMPTE fields for sanity (may also adjust fields)
769 smpte_sanitize_display();
775 ValueChanged(); /* EMIT_SIGNAL */
778 /* move on to the next field.
786 minutes_ebox.grab_focus ();
789 seconds_ebox.grab_focus ();
792 frames_ebox.grab_focus ();
795 clock_base.grab_focus ();
800 clock_base.grab_focus ();
806 ms_minutes_ebox.grab_focus ();
809 ms_seconds_ebox.grab_focus ();
812 clock_base.grab_focus ();
818 beats_ebox.grab_focus ();
821 ticks_ebox.grab_focus ();
824 clock_base.grab_focus ();
837 AudioClock::field_focus_in_event (GdkEventFocus *ev, Field field)
843 hours_ebox.set_flags (Gtk::HAS_FOCUS);
844 hours_ebox.set_state (Gtk::STATE_ACTIVE);
847 minutes_ebox.set_flags (Gtk::HAS_FOCUS);
848 minutes_ebox.set_state (Gtk::STATE_ACTIVE);
851 seconds_ebox.set_flags (Gtk::HAS_FOCUS);
852 seconds_ebox.set_state (Gtk::STATE_ACTIVE);
855 frames_ebox.set_flags (Gtk::HAS_FOCUS);
856 frames_ebox.set_state (Gtk::STATE_ACTIVE);
860 audio_frames_ebox.set_flags (Gtk::HAS_FOCUS);
861 audio_frames_ebox.set_state (Gtk::STATE_ACTIVE);
865 ms_hours_ebox.set_flags (Gtk::HAS_FOCUS);
866 ms_hours_ebox.set_state (Gtk::STATE_ACTIVE);
869 ms_minutes_ebox.set_flags (Gtk::HAS_FOCUS);
870 ms_minutes_ebox.set_state (Gtk::STATE_ACTIVE);
873 ms_seconds_ebox.set_flags (Gtk::HAS_FOCUS);
874 ms_seconds_ebox.set_state (Gtk::STATE_ACTIVE);
877 bars_ebox.set_flags (Gtk::HAS_FOCUS);
878 bars_ebox.set_state (Gtk::STATE_ACTIVE);
881 beats_ebox.set_flags (Gtk::HAS_FOCUS);
882 beats_ebox.set_state (Gtk::STATE_ACTIVE);
885 ticks_ebox.set_flags (Gtk::HAS_FOCUS);
886 ticks_ebox.set_state (Gtk::STATE_ACTIVE);
894 AudioClock::field_focus_out_event (GdkEventFocus *ev, Field field)
899 hours_ebox.unset_flags (Gtk::HAS_FOCUS);
900 hours_ebox.set_state (Gtk::STATE_NORMAL);
903 minutes_ebox.unset_flags (Gtk::HAS_FOCUS);
904 minutes_ebox.set_state (Gtk::STATE_NORMAL);
907 seconds_ebox.unset_flags (Gtk::HAS_FOCUS);
908 seconds_ebox.set_state (Gtk::STATE_NORMAL);
911 frames_ebox.unset_flags (Gtk::HAS_FOCUS);
912 frames_ebox.set_state (Gtk::STATE_NORMAL);
916 audio_frames_ebox.unset_flags (Gtk::HAS_FOCUS);
917 audio_frames_ebox.set_state (Gtk::STATE_NORMAL);
921 ms_hours_ebox.unset_flags (Gtk::HAS_FOCUS);
922 ms_hours_ebox.set_state (Gtk::STATE_NORMAL);
925 ms_minutes_ebox.unset_flags (Gtk::HAS_FOCUS);
926 ms_minutes_ebox.set_state (Gtk::STATE_NORMAL);
929 ms_seconds_ebox.unset_flags (Gtk::HAS_FOCUS);
930 ms_seconds_ebox.set_state (Gtk::STATE_NORMAL);
934 bars_ebox.unset_flags (Gtk::HAS_FOCUS);
935 bars_ebox.set_state (Gtk::STATE_NORMAL);
938 beats_ebox.unset_flags (Gtk::HAS_FOCUS);
939 beats_ebox.set_state (Gtk::STATE_NORMAL);
942 ticks_ebox.unset_flags (Gtk::HAS_FOCUS);
943 ticks_ebox.set_state (Gtk::STATE_NORMAL);
951 AudioClock::field_button_release_event (GdkEventButton *ev, Field field)
956 gdk_pointer_ungrab(GDK_CURRENT_TIME);
958 if (ev->y > drag_start_y+1 || ev->y < drag_start_y-1 || Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)){
959 // we actually dragged so return without setting editing focus, or we shift clicked
969 ops_menu->popup (1, ev->time);
973 if (Keyboard::is_context_menu_event (ev)) {
977 ops_menu->popup (1, ev->time);
981 switch (ev->button) {
985 hours_ebox.grab_focus();
988 minutes_ebox.grab_focus();
991 seconds_ebox.grab_focus();
994 frames_ebox.grab_focus();
998 audio_frames_ebox.grab_focus();
1002 ms_hours_ebox.grab_focus();
1005 ms_minutes_ebox.grab_focus();
1008 ms_seconds_ebox.grab_focus();
1012 bars_ebox.grab_focus ();
1015 beats_ebox.grab_focus ();
1018 ticks_ebox.grab_focus ();
1031 AudioClock::field_button_press_event (GdkEventButton *ev, Field field)
1033 if (session == 0) return FALSE;
1035 nframes_t frames = 0;
1037 switch (ev->button) {
1039 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
1041 ValueChanged (); /* EMIT_SIGNAL */
1044 /* make absolutely sure that the pointer is grabbed */
1045 gdk_pointer_grab(ev->window,FALSE ,
1046 GdkEventMask( Gdk::POINTER_MOTION_MASK | Gdk::BUTTON_PRESS_MASK |Gdk::BUTTON_RELEASE_MASK),
1047 NULL,NULL,ev->time);
1050 drag_start_y = ev->y;
1055 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
1057 ValueChanged (); /* EMIT_SIGNAL */
1062 /* used for context sensitive menu */
1067 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
1068 frames = get_frames (field);
1070 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
1073 set (current_time() + frames, true);
1074 ValueChanged (); /* EMIT_SIGNAL */
1080 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
1081 frames = get_frames (field);
1083 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
1087 if ((double)current_time() - (double)frames < 0.0) {
1091 set (current_time() - frames, true);
1094 ValueChanged (); /* EMIT_SIGNAL */
1108 AudioClock::field_button_scroll_event (GdkEventScroll *ev, Field field)
1110 if (session == 0) return FALSE;
1112 nframes_t frames = 0;
1114 switch (ev->direction) {
1117 frames = get_frames (field);
1119 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
1122 set (current_time() + frames, true);
1123 ValueChanged (); /* EMIT_SIGNAL */
1127 case GDK_SCROLL_DOWN:
1128 frames = get_frames (field);
1130 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
1134 if ((double)current_time() - (double)frames < 0.0) {
1137 set (current_time() - frames, true);
1140 ValueChanged (); /* EMIT_SIGNAL */
1153 AudioClock::field_motion_notify_event (GdkEventMotion *ev, Field field)
1155 if (session == 0 || !dragging) {
1159 float pixel_frame_scale_factor = 0.2f;
1162 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
1163 pixel_frame_scale_factor = 0.1f;
1167 if (Keyboard::modifier_state_contains (ev->state,
1168 Keyboard::Control|Keyboard::Alt)) {
1170 pixel_frame_scale_factor = 0.025f;
1173 double y_delta = ev->y - drag_y;
1175 drag_accum += y_delta*pixel_frame_scale_factor;
1179 if (trunc(drag_accum) != 0) {
1184 dir = (drag_accum < 0 ? 1:-1);
1185 pos = current_time();
1186 frames = get_frames (field,pos,dir);
1188 if (frames != 0 && frames * drag_accum < current_time()) {
1190 set ((nframes_t) floor (pos - drag_accum * frames), false); // minus because up is negative in computer-land
1198 ValueChanged(); /* EMIT_SIGNAL */
1207 AudioClock::get_frames (Field field,nframes_t pos,int dir)
1210 nframes_t frames = 0;
1214 frames = (nframes_t) floor (3600.0 * session->frame_rate());
1217 frames = (nframes_t) floor (60.0 * session->frame_rate());
1220 frames = session->frame_rate();
1223 frames = (nframes_t) floor (session->frame_rate() / session->smpte_frames_per_second());
1231 frames = (nframes_t) floor (3600.0 * session->frame_rate());
1234 frames = (nframes_t) floor (60.0 * session->frame_rate());
1237 frames = session->frame_rate();
1244 frames = session->tempo_map().bbt_duration_at(pos,bbt,dir);
1250 frames = session->tempo_map().bbt_duration_at(pos,bbt,dir);
1256 frames = session->tempo_map().bbt_duration_at(pos,bbt,dir);
1264 AudioClock::current_time (nframes_t pos) const
1270 ret = smpte_frame_from_display ();
1273 ret = bbt_frame_from_display (pos);
1277 ret = minsec_frame_from_display ();
1281 ret = audio_frame_from_display ();
1292 AudioClock::current_duration (nframes_t pos) const
1298 ret = smpte_frame_from_display ();
1301 ret = bbt_frame_duration_from_display (pos);
1305 ret = minsec_frame_from_display ();
1309 ret = audio_frame_from_display ();
1320 AudioClock::smpte_sanitize_display()
1322 // Check SMPTE fields for sanity, possibly adjusting values
1323 if (atoi(minutes_label.get_text()) > 59) {
1324 minutes_label.set_text("59");
1327 if (atoi(seconds_label.get_text()) > 59) {
1328 seconds_label.set_text("59");
1331 switch ((long)rint(session->smpte_frames_per_second())) {
1333 if (atoi(frames_label.get_text()) > 23) {
1334 frames_label.set_text("23");
1338 if (atoi(frames_label.get_text()) > 24) {
1339 frames_label.set_text("24");
1343 if (atoi(frames_label.get_text()) > 29) {
1344 frames_label.set_text("29");
1351 if (session->smpte_drop_frames()) {
1352 if ((atoi(minutes_label.get_text()) % 10) && (atoi(seconds_label.get_text()) == 0) && (atoi(frames_label.get_text()) < 2)) {
1353 frames_label.set_text("02");
1359 AudioClock::smpte_frame_from_display () const
1368 smpte.hours = atoi (hours_label.get_text());
1369 smpte.minutes = atoi (minutes_label.get_text());
1370 smpte.seconds = atoi (seconds_label.get_text());
1371 smpte.frames = atoi (frames_label.get_text());
1372 smpte.rate = session->smpte_frames_per_second();
1373 smpte.drop= session->smpte_drop_frames();
1375 session->smpte_to_sample( smpte, sample, false /* use_offset */, false /* use_subframes */ );
1379 #define SMPTE_SAMPLE_TEST_1
1380 #define SMPTE_SAMPLE_TEST_2
1381 #define SMPTE_SAMPLE_TEST_3
1382 #define SMPTE_SAMPLE_TEST_4
1383 #define SMPTE_SAMPLE_TEST_5
1384 #define SMPTE_SAMPLE_TEST_6
1385 #define SMPTE_SAMPLE_TEST_7
1387 // Testcode for smpte<->sample conversions (P.S.)
1390 nframes_t oldsample = 0;
1392 nframes_t sample_increment;
1394 sample_increment = (long)rint(session->frame_rate() / session->smpte_frames_per_second);
1396 #ifdef SMPTE_SAMPLE_TEST_1
1397 // Test 1: use_offset = false, use_subframes = false
1398 cout << "use_offset = false, use_subframes = false" << endl;
1399 for (int i = 0; i < 108003; i++) {
1400 session->smpte_to_sample( smpte1, sample1, false /* use_offset */, false /* use_subframes */ );
1401 session->sample_to_smpte( sample1, smpte2, false /* use_offset */, false /* use_subframes */ );
1403 if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
1404 cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1405 cout << "smpte1: " << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1406 cout << "sample: " << sample1 << endl;
1407 cout << "sample: " << sample1 << " -> ";
1408 cout << "smpte2: " << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1412 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1413 cout << "ERROR: smpte2 not equal smpte1" << endl;
1414 cout << "smpte1: " << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1415 cout << "sample: " << sample1 << endl;
1416 cout << "sample: " << sample1 << " -> ";
1417 cout << "smpte2: " << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1420 oldsample = sample1;
1421 session->smpte_increment( smpte1 );
1424 cout << "sample_increment: " << sample_increment << endl;
1425 cout << "sample: " << sample1 << " -> ";
1426 cout << "smpte: " << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1429 #ifdef SMPTE_SAMPLE_TEST_2
1430 // Test 2: use_offset = true, use_subframes = false
1431 cout << "use_offset = true, use_subframes = false" << endl;
1437 smpte1.subframes = 0;
1438 sample1 = oldsample = 0;
1440 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1441 cout << "Starting at sample: " << sample1 << " -> ";
1442 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1444 for (int i = 0; i < 108003; i++) {
1445 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1446 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1448 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1449 // cout << "sample: " << sample1 << endl;
1450 // cout << "sample: " << sample1 << " -> ";
1451 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1453 if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
1454 cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1455 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1456 cout << "sample: " << sample1 << endl;
1457 cout << "sample: " << sample1 << " -> ";
1458 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1462 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1463 cout << "ERROR: smpte2 not equal smpte1" << endl;
1464 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1465 cout << "sample: " << sample1 << endl;
1466 cout << "sample: " << sample1 << " -> ";
1467 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1470 oldsample = sample1;
1471 session->smpte_increment( smpte1 );
1474 cout << "sample_increment: " << sample_increment << endl;
1475 cout << "sample: " << sample1 << " -> ";
1476 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1479 #ifdef SMPTE_SAMPLE_TEST_3
1480 // Test 3: use_offset = true, use_subframes = false, decrement
1481 cout << "use_offset = true, use_subframes = false, decrement" << endl;
1483 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1484 cout << "Starting at sample: " << sample1 << " -> ";
1485 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1487 for (int i = 0; i < 108003; i++) {
1488 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1489 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1491 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1492 // cout << "sample: " << sample1 << endl;
1493 // cout << "sample: " << sample1 << " -> ";
1494 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1496 if ((i > 0) && ( ((oldsample - sample1) != sample_increment) && ((oldsample - sample1) != (sample_increment + 1)) && ((oldsample - sample1) != (sample_increment - 1)))) {
1497 cout << "ERROR: sample increment not right: " << (oldsample - sample1) << " != " << sample_increment << endl;
1498 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1499 cout << "sample: " << sample1 << endl;
1500 cout << "sample: " << sample1 << " -> ";
1501 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1505 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1506 cout << "ERROR: smpte2 not equal smpte1" << endl;
1507 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1508 cout << "sample: " << sample1 << endl;
1509 cout << "sample: " << sample1 << " -> ";
1510 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1513 oldsample = sample1;
1514 session->smpte_decrement( smpte1 );
1517 cout << "sample_decrement: " << sample_increment << endl;
1518 cout << "sample: " << sample1 << " -> ";
1519 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1523 #ifdef SMPTE_SAMPLE_TEST_4
1524 // Test 4: use_offset = true, use_subframes = true
1525 cout << "use_offset = true, use_subframes = true" << endl;
1527 for (long sub = 5; sub < 80; sub += 5) {
1532 smpte1.subframes = 0;
1533 sample1 = oldsample = (sample_increment * sub) / 80;
1535 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, true /* use_subframes */ );
1537 cout << "starting at sample: " << sample1 << " -> ";
1538 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1540 for (int i = 0; i < 108003; i++) {
1541 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, true /* use_subframes */ );
1542 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, true /* use_subframes */ );
1544 if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
1545 cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1546 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1547 cout << "sample: " << sample1 << endl;
1548 cout << "sample: " << sample1 << " -> ";
1549 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1553 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames || smpte2.subframes != smpte1.subframes) {
1554 cout << "ERROR: smpte2 not equal smpte1" << endl;
1555 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1556 cout << "sample: " << sample1 << endl;
1557 cout << "sample: " << sample1 << " -> ";
1558 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1561 oldsample = sample1;
1562 session->smpte_increment( smpte1 );
1565 cout << "sample_increment: " << sample_increment << endl;
1566 cout << "sample: " << sample1 << " -> ";
1567 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1569 for (int i = 0; i < 108003; i++) {
1570 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, true /* use_subframes */ );
1571 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, true /* use_subframes */ );
1573 if ((i > 0) && ( ((oldsample - sample1) != sample_increment) && ((oldsample - sample1) != (sample_increment + 1)) && ((oldsample - sample1) != (sample_increment - 1)))) {
1574 cout << "ERROR: sample increment not right: " << (oldsample - sample1) << " != " << sample_increment << endl;
1575 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1576 cout << "sample: " << sample1 << endl;
1577 cout << "sample: " << sample1 << " -> ";
1578 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1582 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames || smpte2.subframes != smpte1.subframes) {
1583 cout << "ERROR: smpte2 not equal smpte1" << endl;
1584 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1585 cout << "sample: " << sample1 << endl;
1586 cout << "sample: " << sample1 << " -> ";
1587 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1590 oldsample = sample1;
1591 session->smpte_decrement( smpte1 );
1594 cout << "sample_decrement: " << sample_increment << endl;
1595 cout << "sample: " << sample1 << " -> ";
1596 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1601 #ifdef SMPTE_SAMPLE_TEST_5
1602 // Test 5: use_offset = true, use_subframes = false, increment seconds
1603 cout << "use_offset = true, use_subframes = false, increment seconds" << endl;
1609 smpte1.subframes = 0;
1610 sample1 = oldsample = 0;
1611 sample_increment = session->frame_rate();
1613 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1614 cout << "Starting at sample: " << sample1 << " -> ";
1615 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1617 for (int i = 0; i < 3600; i++) {
1618 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1619 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1621 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1622 // cout << "sample: " << sample1 << endl;
1623 // cout << "sample: " << sample1 << " -> ";
1624 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1626 // if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1628 // cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1632 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1633 cout << "ERROR: smpte2 not equal smpte1" << endl;
1634 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1635 cout << "sample: " << sample1 << endl;
1636 cout << "sample: " << sample1 << " -> ";
1637 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1640 oldsample = sample1;
1641 session->smpte_increment_seconds( smpte1 );
1644 cout << "sample_increment: " << sample_increment << endl;
1645 cout << "sample: " << sample1 << " -> ";
1646 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1650 #ifdef SMPTE_SAMPLE_TEST_6
1651 // Test 6: use_offset = true, use_subframes = false, increment minutes
1652 cout << "use_offset = true, use_subframes = false, increment minutes" << endl;
1658 smpte1.subframes = 0;
1659 sample1 = oldsample = 0;
1660 sample_increment = session->frame_rate() * 60;
1662 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1663 cout << "Starting at sample: " << sample1 << " -> ";
1664 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1666 for (int i = 0; i < 60; i++) {
1667 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1668 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1670 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1671 // cout << "sample: " << sample1 << endl;
1672 // cout << "sample: " << sample1 << " -> ";
1673 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1675 // if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1677 // cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1681 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1682 cout << "ERROR: smpte2 not equal smpte1" << endl;
1683 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1684 cout << "sample: " << sample1 << endl;
1685 cout << "sample: " << sample1 << " -> ";
1686 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1689 oldsample = sample1;
1690 session->smpte_increment_minutes( smpte1 );
1693 cout << "sample_increment: " << sample_increment << endl;
1694 cout << "sample: " << sample1 << " -> ";
1695 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1698 #ifdef SMPTE_SAMPLE_TEST_7
1699 // Test 7: use_offset = true, use_subframes = false, increment hours
1700 cout << "use_offset = true, use_subframes = false, increment hours" << endl;
1706 smpte1.subframes = 0;
1707 sample1 = oldsample = 0;
1708 sample_increment = session->frame_rate() * 60 * 60;
1710 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1711 cout << "Starting at sample: " << sample1 << " -> ";
1712 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1714 for (int i = 0; i < 10; i++) {
1715 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1716 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1718 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1719 // cout << "sample: " << sample1 << endl;
1720 // cout << "sample: " << sample1 << " -> ";
1721 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1723 // if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1725 // cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1729 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1730 cout << "ERROR: smpte2 not equal smpte1" << endl;
1731 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1732 cout << "sample: " << sample1 << endl;
1733 cout << "sample: " << sample1 << " -> ";
1734 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1737 oldsample = sample1;
1738 session->smpte_increment_hours( smpte1 );
1741 cout << "sample_increment: " << sample_increment << endl;
1742 cout << "sample: " << sample1 << " -> ";
1743 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1752 AudioClock::minsec_frame_from_display () const
1758 int hrs = atoi (ms_hours_label.get_text());
1759 int mins = atoi (ms_minutes_label.get_text());
1760 float secs = atof (ms_seconds_label.get_text());
1762 nframes_t sr = session->frame_rate();
1764 return (nframes_t) floor ((hrs * 60.0f * 60.0f * sr) + (mins * 60.0f * sr) + (secs * sr));
1768 AudioClock::bbt_frame_from_display (nframes_t pos) const
1771 error << "AudioClock::current_time() called with BBT mode but without session!" << endmsg;
1776 any.type = AnyTime::BBT;
1778 any.bbt.bars = atoi (bars_label.get_text());
1779 any.bbt.beats = atoi (beats_label.get_text());
1780 any.bbt.ticks = atoi (ticks_label.get_text());
1782 nframes_t ret = session->convert_to_frames_at (pos, any);
1789 AudioClock::bbt_frame_duration_from_display (nframes_t pos) const
1792 error << "AudioClock::current_time() called with BBT mode but without session!" << endmsg;
1799 bbt.bars = atoi (bars_label.get_text());
1800 bbt.beats = atoi (beats_label.get_text());
1801 bbt.ticks = atoi (ticks_label.get_text());
1803 return session->tempo_map().bbt_duration_at(pos,bbt,1);
1807 AudioClock::audio_frame_from_display () const
1809 return (nframes_t) atoi (audio_frames_label.get_text());
1813 AudioClock::build_ops_menu ()
1815 using namespace Menu_Helpers;
1816 ops_menu = new Menu;
1817 MenuList& ops_items = ops_menu->items();
1818 ops_menu->set_name ("ArdourContextMenu");
1820 Menu *mode_menu = manage (new Menu);
1821 MenuList& mode_items = mode_menu->items();
1822 mode_menu->set_name ("ArdourContextMenu");
1824 mode_items.push_back (MenuElem (_("Timecode"), bind (mem_fun(*this, &AudioClock::set_mode), SMPTE)));
1825 mode_items.push_back (MenuElem (_("Bars:Beats"), bind (mem_fun(*this, &AudioClock::set_mode), BBT)));
1826 mode_items.push_back (MenuElem (_("Minutes:Seconds"), bind (mem_fun(*this, &AudioClock::set_mode), MinSec)));
1827 mode_items.push_back (MenuElem (_("Audio Frames"), bind (mem_fun(*this, &AudioClock::set_mode), Frames)));
1828 mode_items.push_back (MenuElem (_("Off"), bind (mem_fun(*this, &AudioClock::set_mode), Off)));
1830 ops_items.push_back (MenuElem (_("Mode"), *mode_menu));
1834 AudioClock::set_mode (Mode m)
1836 /* slightly tricky: this is called from within the ARDOUR_UI
1837 constructor by some of its clock members. at that time
1838 the instance pointer is unset, so we have to be careful.
1839 the main idea is to drop keyboard focus in case we had
1840 started editing the clock and then we switch clock mode.
1843 clock_base.grab_focus ();
1853 clock_base.remove ();
1863 clock_base.add (smpte_packer_hbox);
1867 clock_base.add (bbt_packer_hbox);
1871 clock_base.add (minsec_packer_hbox);
1875 clock_base.add (frames_packer_hbox);
1882 set_size_requests ();
1884 set (last_when, true);
1885 clock_base.show_all ();
1886 key_entry_state = 0;
1888 if (!is_transient) {
1889 ModeChanged (); /* EMIT SIGNAL */
1894 AudioClock::set_size_requests ()
1896 /* note that in some fonts, "88" is narrower than "00", hence the 2 pixel padding */
1900 Gtkmm2ext::set_size_request_to_display_given_text (hours_label, "-00", 5, 5);
1901 Gtkmm2ext::set_size_request_to_display_given_text (minutes_label, "00", 5, 5);
1902 Gtkmm2ext::set_size_request_to_display_given_text (seconds_label, "00", 5, 5);
1903 Gtkmm2ext::set_size_request_to_display_given_text (frames_label, "00", 5, 5);
1907 Gtkmm2ext::set_size_request_to_display_given_text (bars_label, "-000", 5, 5);
1908 Gtkmm2ext::set_size_request_to_display_given_text (beats_label, "00", 5, 5);
1909 Gtkmm2ext::set_size_request_to_display_given_text (ticks_label, "0000", 5, 5);
1913 Gtkmm2ext::set_size_request_to_display_given_text (ms_hours_label, "00", 5, 5);
1914 Gtkmm2ext::set_size_request_to_display_given_text (ms_minutes_label, "00", 5, 5);
1915 Gtkmm2ext::set_size_request_to_display_given_text (ms_seconds_label, "00.000", 5, 5);
1919 Gtkmm2ext::set_size_request_to_display_given_text (audio_frames_label, "0000000000", 5, 5);