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)) != 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();
774 // Bars or beats should never be 0
775 if (atoi(bars_label.get_text()) == 0) {
776 bars_label.set_text("001");
778 if (atoi(beats_label.get_text()) == 0) {
779 beats_label.set_text("01");
786 ValueChanged(); /* EMIT_SIGNAL */
789 /* move on to the next field.
797 minutes_ebox.grab_focus ();
800 seconds_ebox.grab_focus ();
803 frames_ebox.grab_focus ();
806 clock_base.grab_focus ();
811 clock_base.grab_focus ();
817 ms_minutes_ebox.grab_focus ();
820 ms_seconds_ebox.grab_focus ();
823 clock_base.grab_focus ();
829 beats_ebox.grab_focus ();
832 ticks_ebox.grab_focus ();
835 clock_base.grab_focus ();
848 AudioClock::field_focus_in_event (GdkEventFocus *ev, Field field)
854 hours_ebox.set_flags (Gtk::HAS_FOCUS);
855 hours_ebox.set_state (Gtk::STATE_ACTIVE);
858 minutes_ebox.set_flags (Gtk::HAS_FOCUS);
859 minutes_ebox.set_state (Gtk::STATE_ACTIVE);
862 seconds_ebox.set_flags (Gtk::HAS_FOCUS);
863 seconds_ebox.set_state (Gtk::STATE_ACTIVE);
866 frames_ebox.set_flags (Gtk::HAS_FOCUS);
867 frames_ebox.set_state (Gtk::STATE_ACTIVE);
871 audio_frames_ebox.set_flags (Gtk::HAS_FOCUS);
872 audio_frames_ebox.set_state (Gtk::STATE_ACTIVE);
876 ms_hours_ebox.set_flags (Gtk::HAS_FOCUS);
877 ms_hours_ebox.set_state (Gtk::STATE_ACTIVE);
880 ms_minutes_ebox.set_flags (Gtk::HAS_FOCUS);
881 ms_minutes_ebox.set_state (Gtk::STATE_ACTIVE);
884 ms_seconds_ebox.set_flags (Gtk::HAS_FOCUS);
885 ms_seconds_ebox.set_state (Gtk::STATE_ACTIVE);
888 bars_ebox.set_flags (Gtk::HAS_FOCUS);
889 bars_ebox.set_state (Gtk::STATE_ACTIVE);
892 beats_ebox.set_flags (Gtk::HAS_FOCUS);
893 beats_ebox.set_state (Gtk::STATE_ACTIVE);
896 ticks_ebox.set_flags (Gtk::HAS_FOCUS);
897 ticks_ebox.set_state (Gtk::STATE_ACTIVE);
905 AudioClock::field_focus_out_event (GdkEventFocus *ev, Field field)
910 hours_ebox.unset_flags (Gtk::HAS_FOCUS);
911 hours_ebox.set_state (Gtk::STATE_NORMAL);
914 minutes_ebox.unset_flags (Gtk::HAS_FOCUS);
915 minutes_ebox.set_state (Gtk::STATE_NORMAL);
918 seconds_ebox.unset_flags (Gtk::HAS_FOCUS);
919 seconds_ebox.set_state (Gtk::STATE_NORMAL);
922 frames_ebox.unset_flags (Gtk::HAS_FOCUS);
923 frames_ebox.set_state (Gtk::STATE_NORMAL);
927 audio_frames_ebox.unset_flags (Gtk::HAS_FOCUS);
928 audio_frames_ebox.set_state (Gtk::STATE_NORMAL);
932 ms_hours_ebox.unset_flags (Gtk::HAS_FOCUS);
933 ms_hours_ebox.set_state (Gtk::STATE_NORMAL);
936 ms_minutes_ebox.unset_flags (Gtk::HAS_FOCUS);
937 ms_minutes_ebox.set_state (Gtk::STATE_NORMAL);
940 ms_seconds_ebox.unset_flags (Gtk::HAS_FOCUS);
941 ms_seconds_ebox.set_state (Gtk::STATE_NORMAL);
945 bars_ebox.unset_flags (Gtk::HAS_FOCUS);
946 bars_ebox.set_state (Gtk::STATE_NORMAL);
949 beats_ebox.unset_flags (Gtk::HAS_FOCUS);
950 beats_ebox.set_state (Gtk::STATE_NORMAL);
953 ticks_ebox.unset_flags (Gtk::HAS_FOCUS);
954 ticks_ebox.set_state (Gtk::STATE_NORMAL);
962 AudioClock::field_button_release_event (GdkEventButton *ev, Field field)
967 gdk_pointer_ungrab(GDK_CURRENT_TIME);
969 if (ev->y > drag_start_y+1 || ev->y < drag_start_y-1 || Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)){
970 // we actually dragged so return without setting editing focus, or we shift clicked
980 ops_menu->popup (1, ev->time);
984 if (Keyboard::is_context_menu_event (ev)) {
988 ops_menu->popup (1, ev->time);
992 switch (ev->button) {
996 hours_ebox.grab_focus();
999 minutes_ebox.grab_focus();
1002 seconds_ebox.grab_focus();
1005 frames_ebox.grab_focus();
1009 audio_frames_ebox.grab_focus();
1013 ms_hours_ebox.grab_focus();
1016 ms_minutes_ebox.grab_focus();
1019 ms_seconds_ebox.grab_focus();
1023 bars_ebox.grab_focus ();
1026 beats_ebox.grab_focus ();
1029 ticks_ebox.grab_focus ();
1042 AudioClock::field_button_press_event (GdkEventButton *ev, Field field)
1044 if (session == 0) return FALSE;
1046 nframes_t frames = 0;
1048 switch (ev->button) {
1050 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
1052 ValueChanged (); /* EMIT_SIGNAL */
1055 /* make absolutely sure that the pointer is grabbed */
1056 gdk_pointer_grab(ev->window,FALSE ,
1057 GdkEventMask( Gdk::POINTER_MOTION_MASK | Gdk::BUTTON_PRESS_MASK |Gdk::BUTTON_RELEASE_MASK),
1058 NULL,NULL,ev->time);
1061 drag_start_y = ev->y;
1066 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
1068 ValueChanged (); /* EMIT_SIGNAL */
1073 /* used for context sensitive menu */
1078 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
1079 frames = get_frames (field);
1081 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
1084 set (current_time() + frames, true);
1085 ValueChanged (); /* EMIT_SIGNAL */
1091 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
1092 frames = get_frames (field);
1094 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
1098 if ((double)current_time() - (double)frames < 0.0) {
1102 set (current_time() - frames, true);
1105 ValueChanged (); /* EMIT_SIGNAL */
1119 AudioClock::field_button_scroll_event (GdkEventScroll *ev, Field field)
1121 if (session == 0) return FALSE;
1123 nframes_t frames = 0;
1125 switch (ev->direction) {
1128 frames = get_frames (field);
1130 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
1133 set (current_time() + frames, true);
1134 ValueChanged (); /* EMIT_SIGNAL */
1138 case GDK_SCROLL_DOWN:
1139 frames = get_frames (field);
1141 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
1145 if ((double)current_time() - (double)frames < 0.0) {
1148 set (current_time() - frames, true);
1151 ValueChanged (); /* EMIT_SIGNAL */
1164 AudioClock::field_motion_notify_event (GdkEventMotion *ev, Field field)
1166 if (session == 0 || !dragging) {
1170 float pixel_frame_scale_factor = 0.2f;
1173 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
1174 pixel_frame_scale_factor = 0.1f;
1178 if (Keyboard::modifier_state_contains (ev->state,
1179 Keyboard::Control|Keyboard::Alt)) {
1181 pixel_frame_scale_factor = 0.025f;
1184 double y_delta = ev->y - drag_y;
1186 drag_accum += y_delta*pixel_frame_scale_factor;
1190 if (trunc(drag_accum) != 0) {
1195 dir = (drag_accum < 0 ? 1:-1);
1196 pos = current_time();
1197 frames = get_frames (field,pos,dir);
1199 if (frames != 0 && frames * drag_accum < current_time()) {
1201 set ((nframes_t) floor (pos - drag_accum * frames), false); // minus because up is negative in computer-land
1209 ValueChanged(); /* EMIT_SIGNAL */
1218 AudioClock::get_frames (Field field,nframes_t pos,int dir)
1221 nframes_t frames = 0;
1225 frames = (nframes_t) floor (3600.0 * session->frame_rate());
1228 frames = (nframes_t) floor (60.0 * session->frame_rate());
1231 frames = session->frame_rate();
1234 frames = (nframes_t) floor (session->frame_rate() / session->smpte_frames_per_second());
1242 frames = (nframes_t) floor (3600.0 * session->frame_rate());
1245 frames = (nframes_t) floor (60.0 * session->frame_rate());
1248 frames = session->frame_rate();
1255 frames = session->tempo_map().bbt_duration_at(pos,bbt,dir);
1261 frames = session->tempo_map().bbt_duration_at(pos,bbt,dir);
1267 frames = session->tempo_map().bbt_duration_at(pos,bbt,dir);
1275 AudioClock::current_time (nframes_t pos) const
1281 ret = smpte_frame_from_display ();
1284 ret = bbt_frame_from_display (pos);
1288 ret = minsec_frame_from_display ();
1292 ret = audio_frame_from_display ();
1303 AudioClock::current_duration (nframes_t pos) const
1309 ret = smpte_frame_from_display ();
1312 ret = bbt_frame_duration_from_display (pos);
1316 ret = minsec_frame_from_display ();
1320 ret = audio_frame_from_display ();
1331 AudioClock::smpte_sanitize_display()
1333 // Check SMPTE fields for sanity, possibly adjusting values
1334 if (atoi(minutes_label.get_text()) > 59) {
1335 minutes_label.set_text("59");
1338 if (atoi(seconds_label.get_text()) > 59) {
1339 seconds_label.set_text("59");
1342 switch ((long)rint(session->smpte_frames_per_second())) {
1344 if (atoi(frames_label.get_text()) > 23) {
1345 frames_label.set_text("23");
1349 if (atoi(frames_label.get_text()) > 24) {
1350 frames_label.set_text("24");
1354 if (atoi(frames_label.get_text()) > 29) {
1355 frames_label.set_text("29");
1362 if (session->smpte_drop_frames()) {
1363 if ((atoi(minutes_label.get_text()) % 10) && (atoi(seconds_label.get_text()) == 0) && (atoi(frames_label.get_text()) < 2)) {
1364 frames_label.set_text("02");
1370 AudioClock::smpte_frame_from_display () const
1379 smpte.hours = atoi (hours_label.get_text());
1380 smpte.minutes = atoi (minutes_label.get_text());
1381 smpte.seconds = atoi (seconds_label.get_text());
1382 smpte.frames = atoi (frames_label.get_text());
1383 smpte.rate = session->smpte_frames_per_second();
1384 smpte.drop= session->smpte_drop_frames();
1386 session->smpte_to_sample( smpte, sample, false /* use_offset */, false /* use_subframes */ );
1390 #define SMPTE_SAMPLE_TEST_1
1391 #define SMPTE_SAMPLE_TEST_2
1392 #define SMPTE_SAMPLE_TEST_3
1393 #define SMPTE_SAMPLE_TEST_4
1394 #define SMPTE_SAMPLE_TEST_5
1395 #define SMPTE_SAMPLE_TEST_6
1396 #define SMPTE_SAMPLE_TEST_7
1398 // Testcode for smpte<->sample conversions (P.S.)
1401 nframes_t oldsample = 0;
1403 nframes_t sample_increment;
1405 sample_increment = (long)rint(session->frame_rate() / session->smpte_frames_per_second);
1407 #ifdef SMPTE_SAMPLE_TEST_1
1408 // Test 1: use_offset = false, use_subframes = false
1409 cout << "use_offset = false, use_subframes = false" << endl;
1410 for (int i = 0; i < 108003; i++) {
1411 session->smpte_to_sample( smpte1, sample1, false /* use_offset */, false /* use_subframes */ );
1412 session->sample_to_smpte( sample1, smpte2, false /* use_offset */, false /* use_subframes */ );
1414 if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
1415 cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1416 cout << "smpte1: " << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1417 cout << "sample: " << sample1 << endl;
1418 cout << "sample: " << sample1 << " -> ";
1419 cout << "smpte2: " << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1423 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1424 cout << "ERROR: smpte2 not equal smpte1" << endl;
1425 cout << "smpte1: " << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1426 cout << "sample: " << sample1 << endl;
1427 cout << "sample: " << sample1 << " -> ";
1428 cout << "smpte2: " << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1431 oldsample = sample1;
1432 session->smpte_increment( smpte1 );
1435 cout << "sample_increment: " << sample_increment << endl;
1436 cout << "sample: " << sample1 << " -> ";
1437 cout << "smpte: " << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1440 #ifdef SMPTE_SAMPLE_TEST_2
1441 // Test 2: use_offset = true, use_subframes = false
1442 cout << "use_offset = true, use_subframes = false" << endl;
1448 smpte1.subframes = 0;
1449 sample1 = oldsample = 0;
1451 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1452 cout << "Starting at sample: " << sample1 << " -> ";
1453 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1455 for (int i = 0; i < 108003; i++) {
1456 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1457 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1459 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1460 // cout << "sample: " << sample1 << endl;
1461 // cout << "sample: " << sample1 << " -> ";
1462 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1464 if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
1465 cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1466 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1467 cout << "sample: " << sample1 << endl;
1468 cout << "sample: " << sample1 << " -> ";
1469 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1473 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1474 cout << "ERROR: smpte2 not equal smpte1" << endl;
1475 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1476 cout << "sample: " << sample1 << endl;
1477 cout << "sample: " << sample1 << " -> ";
1478 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1481 oldsample = sample1;
1482 session->smpte_increment( smpte1 );
1485 cout << "sample_increment: " << sample_increment << endl;
1486 cout << "sample: " << sample1 << " -> ";
1487 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1490 #ifdef SMPTE_SAMPLE_TEST_3
1491 // Test 3: use_offset = true, use_subframes = false, decrement
1492 cout << "use_offset = true, use_subframes = false, decrement" << endl;
1494 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1495 cout << "Starting at sample: " << sample1 << " -> ";
1496 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1498 for (int i = 0; i < 108003; i++) {
1499 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1500 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1502 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1503 // cout << "sample: " << sample1 << endl;
1504 // cout << "sample: " << sample1 << " -> ";
1505 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1507 if ((i > 0) && ( ((oldsample - sample1) != sample_increment) && ((oldsample - sample1) != (sample_increment + 1)) && ((oldsample - sample1) != (sample_increment - 1)))) {
1508 cout << "ERROR: sample increment not right: " << (oldsample - sample1) << " != " << sample_increment << endl;
1509 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1510 cout << "sample: " << sample1 << endl;
1511 cout << "sample: " << sample1 << " -> ";
1512 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1516 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1517 cout << "ERROR: smpte2 not equal smpte1" << endl;
1518 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1519 cout << "sample: " << sample1 << endl;
1520 cout << "sample: " << sample1 << " -> ";
1521 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1524 oldsample = sample1;
1525 session->smpte_decrement( smpte1 );
1528 cout << "sample_decrement: " << sample_increment << endl;
1529 cout << "sample: " << sample1 << " -> ";
1530 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1534 #ifdef SMPTE_SAMPLE_TEST_4
1535 // Test 4: use_offset = true, use_subframes = true
1536 cout << "use_offset = true, use_subframes = true" << endl;
1538 for (long sub = 5; sub < 80; sub += 5) {
1543 smpte1.subframes = 0;
1544 sample1 = oldsample = (sample_increment * sub) / 80;
1546 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, true /* use_subframes */ );
1548 cout << "starting at sample: " << sample1 << " -> ";
1549 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1551 for (int i = 0; i < 108003; i++) {
1552 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, true /* use_subframes */ );
1553 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, true /* use_subframes */ );
1555 if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
1556 cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1557 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1558 cout << "sample: " << sample1 << endl;
1559 cout << "sample: " << sample1 << " -> ";
1560 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1564 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames || smpte2.subframes != smpte1.subframes) {
1565 cout << "ERROR: smpte2 not equal smpte1" << endl;
1566 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1567 cout << "sample: " << sample1 << endl;
1568 cout << "sample: " << sample1 << " -> ";
1569 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1572 oldsample = sample1;
1573 session->smpte_increment( smpte1 );
1576 cout << "sample_increment: " << sample_increment << endl;
1577 cout << "sample: " << sample1 << " -> ";
1578 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1580 for (int i = 0; i < 108003; i++) {
1581 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, true /* use_subframes */ );
1582 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, true /* use_subframes */ );
1584 if ((i > 0) && ( ((oldsample - sample1) != sample_increment) && ((oldsample - sample1) != (sample_increment + 1)) && ((oldsample - sample1) != (sample_increment - 1)))) {
1585 cout << "ERROR: sample increment not right: " << (oldsample - sample1) << " != " << sample_increment << endl;
1586 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1587 cout << "sample: " << sample1 << endl;
1588 cout << "sample: " << sample1 << " -> ";
1589 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1593 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames || smpte2.subframes != smpte1.subframes) {
1594 cout << "ERROR: smpte2 not equal smpte1" << endl;
1595 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1596 cout << "sample: " << sample1 << endl;
1597 cout << "sample: " << sample1 << " -> ";
1598 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1601 oldsample = sample1;
1602 session->smpte_decrement( smpte1 );
1605 cout << "sample_decrement: " << sample_increment << endl;
1606 cout << "sample: " << sample1 << " -> ";
1607 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1612 #ifdef SMPTE_SAMPLE_TEST_5
1613 // Test 5: use_offset = true, use_subframes = false, increment seconds
1614 cout << "use_offset = true, use_subframes = false, increment seconds" << endl;
1620 smpte1.subframes = 0;
1621 sample1 = oldsample = 0;
1622 sample_increment = session->frame_rate();
1624 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1625 cout << "Starting at sample: " << sample1 << " -> ";
1626 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1628 for (int i = 0; i < 3600; i++) {
1629 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1630 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1632 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1633 // cout << "sample: " << sample1 << endl;
1634 // cout << "sample: " << sample1 << " -> ";
1635 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1637 // if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1639 // cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1643 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1644 cout << "ERROR: smpte2 not equal smpte1" << endl;
1645 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1646 cout << "sample: " << sample1 << endl;
1647 cout << "sample: " << sample1 << " -> ";
1648 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1651 oldsample = sample1;
1652 session->smpte_increment_seconds( smpte1 );
1655 cout << "sample_increment: " << sample_increment << endl;
1656 cout << "sample: " << sample1 << " -> ";
1657 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1661 #ifdef SMPTE_SAMPLE_TEST_6
1662 // Test 6: use_offset = true, use_subframes = false, increment minutes
1663 cout << "use_offset = true, use_subframes = false, increment minutes" << endl;
1669 smpte1.subframes = 0;
1670 sample1 = oldsample = 0;
1671 sample_increment = session->frame_rate() * 60;
1673 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1674 cout << "Starting at sample: " << sample1 << " -> ";
1675 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1677 for (int i = 0; i < 60; i++) {
1678 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1679 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1681 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1682 // cout << "sample: " << sample1 << endl;
1683 // cout << "sample: " << sample1 << " -> ";
1684 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1686 // if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1688 // cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1692 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1693 cout << "ERROR: smpte2 not equal smpte1" << endl;
1694 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1695 cout << "sample: " << sample1 << endl;
1696 cout << "sample: " << sample1 << " -> ";
1697 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1700 oldsample = sample1;
1701 session->smpte_increment_minutes( smpte1 );
1704 cout << "sample_increment: " << sample_increment << endl;
1705 cout << "sample: " << sample1 << " -> ";
1706 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1709 #ifdef SMPTE_SAMPLE_TEST_7
1710 // Test 7: use_offset = true, use_subframes = false, increment hours
1711 cout << "use_offset = true, use_subframes = false, increment hours" << endl;
1717 smpte1.subframes = 0;
1718 sample1 = oldsample = 0;
1719 sample_increment = session->frame_rate() * 60 * 60;
1721 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1722 cout << "Starting at sample: " << sample1 << " -> ";
1723 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1725 for (int i = 0; i < 10; i++) {
1726 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1727 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1729 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1730 // cout << "sample: " << sample1 << endl;
1731 // cout << "sample: " << sample1 << " -> ";
1732 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1734 // if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1736 // cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1740 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1741 cout << "ERROR: smpte2 not equal smpte1" << endl;
1742 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1743 cout << "sample: " << sample1 << endl;
1744 cout << "sample: " << sample1 << " -> ";
1745 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1748 oldsample = sample1;
1749 session->smpte_increment_hours( smpte1 );
1752 cout << "sample_increment: " << sample_increment << endl;
1753 cout << "sample: " << sample1 << " -> ";
1754 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1763 AudioClock::minsec_frame_from_display () const
1769 int hrs = atoi (ms_hours_label.get_text());
1770 int mins = atoi (ms_minutes_label.get_text());
1771 float secs = atof (ms_seconds_label.get_text());
1773 nframes_t sr = session->frame_rate();
1775 return (nframes_t) floor ((hrs * 60.0f * 60.0f * sr) + (mins * 60.0f * sr) + (secs * sr));
1779 AudioClock::bbt_frame_from_display (nframes_t pos) const
1782 error << "AudioClock::current_time() called with BBT mode but without session!" << endmsg;
1787 any.type = AnyTime::BBT;
1789 any.bbt.bars = atoi (bars_label.get_text());
1790 any.bbt.beats = atoi (beats_label.get_text());
1791 any.bbt.ticks = atoi (ticks_label.get_text());
1793 nframes_t ret = session->convert_to_frames_at (pos, any);
1800 AudioClock::bbt_frame_duration_from_display (nframes_t pos) const
1803 error << "AudioClock::current_time() called with BBT mode but without session!" << endmsg;
1810 bbt.bars = atoi (bars_label.get_text());
1811 bbt.beats = atoi (beats_label.get_text());
1812 bbt.ticks = atoi (ticks_label.get_text());
1814 return session->tempo_map().bbt_duration_at(pos,bbt,1);
1818 AudioClock::audio_frame_from_display () const
1820 return (nframes_t) atoi (audio_frames_label.get_text());
1824 AudioClock::build_ops_menu ()
1826 using namespace Menu_Helpers;
1827 ops_menu = new Menu;
1828 MenuList& ops_items = ops_menu->items();
1829 ops_menu->set_name ("ArdourContextMenu");
1831 Menu *mode_menu = manage (new Menu);
1832 MenuList& mode_items = mode_menu->items();
1833 mode_menu->set_name ("ArdourContextMenu");
1835 mode_items.push_back (MenuElem (_("Timecode"), bind (mem_fun(*this, &AudioClock::set_mode), SMPTE)));
1836 mode_items.push_back (MenuElem (_("Bars:Beats"), bind (mem_fun(*this, &AudioClock::set_mode), BBT)));
1837 mode_items.push_back (MenuElem (_("Minutes:Seconds"), bind (mem_fun(*this, &AudioClock::set_mode), MinSec)));
1838 mode_items.push_back (MenuElem (_("Audio Frames"), bind (mem_fun(*this, &AudioClock::set_mode), Frames)));
1839 mode_items.push_back (MenuElem (_("Off"), bind (mem_fun(*this, &AudioClock::set_mode), Off)));
1841 ops_items.push_back (MenuElem (_("Mode"), *mode_menu));
1845 AudioClock::set_mode (Mode m)
1847 /* slightly tricky: this is called from within the ARDOUR_UI
1848 constructor by some of its clock members. at that time
1849 the instance pointer is unset, so we have to be careful.
1850 the main idea is to drop keyboard focus in case we had
1851 started editing the clock and then we switch clock mode.
1854 clock_base.grab_focus ();
1864 clock_base.remove ();
1874 clock_base.add (smpte_packer_hbox);
1878 clock_base.add (bbt_packer_hbox);
1882 clock_base.add (minsec_packer_hbox);
1886 clock_base.add (frames_packer_hbox);
1893 set_size_requests ();
1895 set (last_when, true);
1896 clock_base.show_all ();
1897 key_entry_state = 0;
1899 if (!is_transient) {
1900 ModeChanged (); /* EMIT SIGNAL */
1905 AudioClock::set_size_requests ()
1907 /* note that in some fonts, "88" is narrower than "00", hence the 2 pixel padding */
1911 Gtkmm2ext::set_size_request_to_display_given_text (hours_label, "-00", 5, 5);
1912 Gtkmm2ext::set_size_request_to_display_given_text (minutes_label, "00", 5, 5);
1913 Gtkmm2ext::set_size_request_to_display_given_text (seconds_label, "00", 5, 5);
1914 Gtkmm2ext::set_size_request_to_display_given_text (frames_label, "00", 5, 5);
1918 Gtkmm2ext::set_size_request_to_display_given_text (bars_label, "-000", 5, 5);
1919 Gtkmm2ext::set_size_request_to_display_given_text (beats_label, "00", 5, 5);
1920 Gtkmm2ext::set_size_request_to_display_given_text (ticks_label, "0000", 5, 5);
1924 Gtkmm2ext::set_size_request_to_display_given_text (ms_hours_label, "00", 5, 5);
1925 Gtkmm2ext::set_size_request_to_display_given_text (ms_minutes_label, "00", 5, 5);
1926 Gtkmm2ext::set_size_request_to_display_given_text (ms_seconds_label, "00.000", 5, 5);
1930 Gtkmm2ext::set_size_request_to_display_given_text (audio_frames_label, "0000000000", 5, 5);