2 Copyright (C) 1999 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include <cstdio> // for sprintf
23 #include <pbd/convert.h>
24 #include <pbd/enumwriter.h>
26 #include <gtkmm2ext/utils.h>
28 #include <ardour/ardour.h>
29 #include <ardour/session.h>
30 #include <ardour/tempo.h>
31 #include <sigc++/bind.h>
33 #include "ardour_ui.h"
34 #include "audio_clock.h"
39 using namespace ARDOUR;
48 sigc::signal<void> AudioClock::ModeChanged;
49 vector<AudioClock*> AudioClock::clocks;
51 const uint32_t AudioClock::field_length[(int) AudioClock::AudioFrames+1] = {
53 2, /* SMPTE_Minutes */
54 2, /* SMPTE_Seconds */
65 AudioClock::AudioClock (std::string clock_name, bool transient, std::string widget_name, bool allow_edit, bool duration, bool with_info)
67 is_transient (transient),
68 is_duration (duration),
69 editable (allow_edit),
87 frames_upper_info_label = manage (new Label);
88 frames_lower_info_label = manage (new Label);
89 smpte_upper_info_label = manage (new Label);
90 smpte_lower_info_label = manage (new Label);
91 bbt_upper_info_label = manage (new Label);
92 bbt_lower_info_label = manage (new Label);
94 frames_upper_info_label->set_name ("AudioClockFramesUpperInfo");
95 frames_lower_info_label->set_name ("AudioClockFramesLowerInfo");
96 smpte_upper_info_label->set_name ("AudioClockSMPTEUpperInfo");
97 smpte_lower_info_label->set_name ("AudioClockSMPTELowerInfo");
98 bbt_upper_info_label->set_name ("AudioClockBBTUpperInfo");
99 bbt_lower_info_label->set_name ("AudioClockBBTLowerInfo");
101 Gtkmm2ext::set_size_request_to_display_given_text(*smpte_upper_info_label, "23.98",0,0);
102 Gtkmm2ext::set_size_request_to_display_given_text(*smpte_lower_info_label, "NDF",0,0);
104 frames_info_box.pack_start (*frames_upper_info_label, true, true);
105 frames_info_box.pack_start (*frames_lower_info_label, true, true);
106 smpte_info_box.pack_start (*smpte_upper_info_label, true, true);
107 smpte_info_box.pack_start (*smpte_lower_info_label, true, true);
108 bbt_info_box.pack_start (*bbt_upper_info_label, true, true);
109 bbt_info_box.pack_start (*bbt_lower_info_label, true, true);
112 frames_upper_info_label = 0;
113 frames_lower_info_label = 0;
114 smpte_upper_info_label = 0;
115 smpte_lower_info_label = 0;
116 bbt_upper_info_label = 0;
117 bbt_lower_info_label = 0;
120 audio_frames_ebox.add (audio_frames_label);
122 frames_packer.set_homogeneous (false);
123 frames_packer.set_border_width (2);
124 frames_packer.pack_start (audio_frames_ebox, false, false);
127 frames_packer.pack_start (frames_info_box, false, false, 5);
130 frames_packer_hbox.pack_start (frames_packer, true, false);
132 hours_ebox.add (hours_label);
133 minutes_ebox.add (minutes_label);
134 seconds_ebox.add (seconds_label);
135 frames_ebox.add (frames_label);
136 bars_ebox.add (bars_label);
137 beats_ebox.add (beats_label);
138 ticks_ebox.add (ticks_label);
139 ms_hours_ebox.add (ms_hours_label);
140 ms_minutes_ebox.add (ms_minutes_label);
141 ms_seconds_ebox.add (ms_seconds_label);
143 smpte_packer.set_homogeneous (false);
144 smpte_packer.set_border_width (2);
145 smpte_packer.pack_start (hours_ebox, false, false);
146 smpte_packer.pack_start (colon1, false, false);
147 smpte_packer.pack_start (minutes_ebox, false, false);
148 smpte_packer.pack_start (colon2, false, false);
149 smpte_packer.pack_start (seconds_ebox, false, false);
150 smpte_packer.pack_start (colon3, false, false);
151 smpte_packer.pack_start (frames_ebox, false, false);
154 smpte_packer.pack_start (smpte_info_box, false, false, 5);
157 smpte_packer_hbox.pack_start (smpte_packer, true, false);
159 bbt_packer.set_homogeneous (false);
160 bbt_packer.set_border_width (2);
161 bbt_packer.pack_start (bars_ebox, false, false);
162 bbt_packer.pack_start (b1, false, false);
163 bbt_packer.pack_start (beats_ebox, false, false);
164 bbt_packer.pack_start (b2, false, false);
165 bbt_packer.pack_start (ticks_ebox, false, false);
168 bbt_packer.pack_start (bbt_info_box, false, false, 5);
171 bbt_packer_hbox.pack_start (bbt_packer, true, false);
173 minsec_packer.set_homogeneous (false);
174 minsec_packer.set_border_width (2);
175 minsec_packer.pack_start (ms_hours_ebox, false, false);
176 minsec_packer.pack_start (colon4, false, false);
177 minsec_packer.pack_start (ms_minutes_ebox, false, false);
178 minsec_packer.pack_start (colon5, false, false);
179 minsec_packer.pack_start (ms_seconds_ebox, false, false);
181 minsec_packer_hbox.pack_start (minsec_packer, true, false);
183 clock_frame.set_shadow_type (Gtk::SHADOW_IN);
184 clock_frame.set_name ("BaseFrame");
186 clock_frame.add (clock_base);
188 set_widget_name (widget_name);
190 _mode = BBT; /* lie to force mode switch */
193 pack_start (clock_frame, true, true);
195 /* the clock base handles button releases for menu popup regardless of
196 editable status. if the clock is editable, the clock base is where
197 we pass focus to after leaving the last editable "field", which
198 will then shutdown editing till the user starts it up again.
200 it does this because the focus out event on the field disables
201 keyboard event handling, and we don't connect anything up to
202 notice focus in on the clock base. hence, keyboard event handling
206 clock_base.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::SCROLL_MASK);
207 clock_base.signal_button_release_event().connect (bind (mem_fun (*this, &AudioClock::field_button_release_event), SMPTE_Hours));
209 Session::SMPTEOffsetChanged.connect (mem_fun (*this, &AudioClock::smpte_offset_changed));
215 set (last_when, true);
218 clocks.push_back (this);
223 AudioClock::set_widget_name (string name)
225 Widget::set_name (name);
227 clock_base.set_name (name);
229 audio_frames_label.set_name (name);
230 hours_label.set_name (name);
231 minutes_label.set_name (name);
232 seconds_label.set_name (name);
233 frames_label.set_name (name);
234 bars_label.set_name (name);
235 beats_label.set_name (name);
236 ticks_label.set_name (name);
237 ms_hours_label.set_name (name);
238 ms_minutes_label.set_name (name);
239 ms_seconds_label.set_name (name);
240 hours_ebox.set_name (name);
241 minutes_ebox.set_name (name);
242 seconds_ebox.set_name (name);
243 frames_ebox.set_name (name);
244 audio_frames_ebox.set_name (name);
245 bars_ebox.set_name (name);
246 beats_ebox.set_name (name);
247 ticks_ebox.set_name (name);
248 ms_hours_ebox.set_name (name);
249 ms_minutes_ebox.set_name (name);
250 ms_seconds_ebox.set_name (name);
252 colon1.set_name (name);
253 colon2.set_name (name);
254 colon3.set_name (name);
255 colon4.set_name (name);
256 colon5.set_name (name);
264 AudioClock::setup_events ()
266 clock_base.set_flags (Gtk::CAN_FOCUS);
268 hours_ebox.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK|Gdk::FOCUS_CHANGE_MASK|Gdk::POINTER_MOTION_MASK|Gdk::SCROLL_MASK);
269 minutes_ebox.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK|Gdk::FOCUS_CHANGE_MASK|Gdk::POINTER_MOTION_MASK|Gdk::SCROLL_MASK);
270 seconds_ebox.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK|Gdk::FOCUS_CHANGE_MASK|Gdk::POINTER_MOTION_MASK|Gdk::SCROLL_MASK);
271 frames_ebox.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK|Gdk::FOCUS_CHANGE_MASK|Gdk::POINTER_MOTION_MASK|Gdk::SCROLL_MASK);
272 bars_ebox.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK|Gdk::FOCUS_CHANGE_MASK|Gdk::POINTER_MOTION_MASK|Gdk::SCROLL_MASK);
273 beats_ebox.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK|Gdk::FOCUS_CHANGE_MASK|Gdk::POINTER_MOTION_MASK|Gdk::SCROLL_MASK);
274 ticks_ebox.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK|Gdk::FOCUS_CHANGE_MASK|Gdk::POINTER_MOTION_MASK|Gdk::SCROLL_MASK);
275 ms_hours_ebox.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK|Gdk::FOCUS_CHANGE_MASK|Gdk::POINTER_MOTION_MASK|Gdk::SCROLL_MASK);
276 ms_minutes_ebox.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK|Gdk::FOCUS_CHANGE_MASK|Gdk::POINTER_MOTION_MASK|Gdk::SCROLL_MASK);
277 ms_seconds_ebox.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK|Gdk::FOCUS_CHANGE_MASK|Gdk::POINTER_MOTION_MASK|Gdk::SCROLL_MASK);
278 audio_frames_ebox.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::KEY_PRESS_MASK|Gdk::KEY_RELEASE_MASK|Gdk::FOCUS_CHANGE_MASK|Gdk::POINTER_MOTION_MASK|Gdk::SCROLL_MASK);
280 hours_ebox.set_flags (Gtk::CAN_FOCUS);
281 minutes_ebox.set_flags (Gtk::CAN_FOCUS);
282 seconds_ebox.set_flags (Gtk::CAN_FOCUS);
283 frames_ebox.set_flags (Gtk::CAN_FOCUS);
284 audio_frames_ebox.set_flags (Gtk::CAN_FOCUS);
285 bars_ebox.set_flags (Gtk::CAN_FOCUS);
286 beats_ebox.set_flags (Gtk::CAN_FOCUS);
287 ticks_ebox.set_flags (Gtk::CAN_FOCUS);
288 ms_hours_ebox.set_flags (Gtk::CAN_FOCUS);
289 ms_minutes_ebox.set_flags (Gtk::CAN_FOCUS);
290 ms_seconds_ebox.set_flags (Gtk::CAN_FOCUS);
292 hours_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), SMPTE_Hours));
293 minutes_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), SMPTE_Minutes));
294 seconds_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), SMPTE_Seconds));
295 frames_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), SMPTE_Frames));
296 audio_frames_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), AudioFrames));
297 bars_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), Bars));
298 beats_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), Beats));
299 ticks_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), Ticks));
300 ms_hours_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), MS_Hours));
301 ms_minutes_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), MS_Minutes));
302 ms_seconds_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), MS_Seconds));
304 hours_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), SMPTE_Hours));
305 minutes_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), SMPTE_Minutes));
306 seconds_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), SMPTE_Seconds));
307 frames_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), SMPTE_Frames));
308 audio_frames_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), AudioFrames));
309 bars_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), Bars));
310 beats_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), Beats));
311 ticks_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), Ticks));
312 ms_hours_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), MS_Hours));
313 ms_minutes_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), MS_Minutes));
314 ms_seconds_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), MS_Seconds));
316 hours_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), SMPTE_Hours));
317 minutes_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), SMPTE_Minutes));
318 seconds_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), SMPTE_Seconds));
319 frames_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), SMPTE_Frames));
320 audio_frames_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), AudioFrames));
321 bars_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), Bars));
322 beats_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), Beats));
323 ticks_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), Ticks));
324 ms_hours_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), MS_Hours));
325 ms_minutes_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), MS_Minutes));
326 ms_seconds_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), MS_Seconds));
328 hours_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), SMPTE_Hours));
329 minutes_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), SMPTE_Minutes));
330 seconds_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), SMPTE_Seconds));
331 frames_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), SMPTE_Frames));
332 audio_frames_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), AudioFrames));
333 bars_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), Bars));
334 beats_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), Beats));
335 ticks_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), Ticks));
336 ms_hours_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), MS_Hours));
337 ms_minutes_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), MS_Minutes));
338 ms_seconds_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), MS_Seconds));
340 hours_ebox.signal_key_press_event().connect (bind (mem_fun(*this, &AudioClock::field_key_press_event), SMPTE_Hours));
341 minutes_ebox.signal_key_press_event().connect (bind (mem_fun(*this, &AudioClock::field_key_press_event), SMPTE_Minutes));
342 seconds_ebox.signal_key_press_event().connect (bind (mem_fun(*this, &AudioClock::field_key_press_event), SMPTE_Seconds));
343 frames_ebox.signal_key_press_event().connect (bind (mem_fun(*this, &AudioClock::field_key_press_event), SMPTE_Frames));
344 audio_frames_ebox.signal_key_press_event().connect (bind (mem_fun(*this, &AudioClock::field_key_press_event), AudioFrames));
345 bars_ebox.signal_key_press_event().connect (bind (mem_fun(*this, &AudioClock::field_key_press_event), Bars));
346 beats_ebox.signal_key_press_event().connect (bind (mem_fun(*this, &AudioClock::field_key_press_event), Beats));
347 ticks_ebox.signal_key_press_event().connect (bind (mem_fun(*this, &AudioClock::field_key_press_event), Ticks));
348 ms_hours_ebox.signal_key_press_event().connect (bind (mem_fun(*this, &AudioClock::field_key_press_event), MS_Hours));
349 ms_minutes_ebox.signal_key_press_event().connect (bind (mem_fun(*this, &AudioClock::field_key_press_event), MS_Minutes));
350 ms_seconds_ebox.signal_key_press_event().connect (bind (mem_fun(*this, &AudioClock::field_key_press_event), MS_Seconds));
352 hours_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), SMPTE_Hours));
353 minutes_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), SMPTE_Minutes));
354 seconds_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), SMPTE_Seconds));
355 frames_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), SMPTE_Frames));
356 audio_frames_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), AudioFrames));
357 bars_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), Bars));
358 beats_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), Beats));
359 ticks_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), Ticks));
360 ms_hours_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), MS_Hours));
361 ms_minutes_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), MS_Minutes));
362 ms_seconds_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), MS_Seconds));
364 hours_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), SMPTE_Hours));
365 minutes_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), SMPTE_Minutes));
366 seconds_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), SMPTE_Seconds));
367 frames_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), SMPTE_Frames));
368 audio_frames_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), AudioFrames));
369 bars_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), Bars));
370 beats_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), Beats));
371 ticks_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), Ticks));
372 ms_hours_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), MS_Hours));
373 ms_minutes_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), MS_Minutes));
374 ms_seconds_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), MS_Seconds));
376 hours_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), SMPTE_Hours));
377 minutes_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), SMPTE_Minutes));
378 seconds_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), SMPTE_Seconds));
379 frames_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), SMPTE_Frames));
380 audio_frames_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), AudioFrames));
381 bars_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), Bars));
382 beats_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), Beats));
383 ticks_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), Ticks));
384 ms_hours_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), MS_Hours));
385 ms_minutes_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), MS_Minutes));
386 ms_seconds_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), MS_Seconds));
388 clock_base.signal_focus_in_event().connect (mem_fun (*this, &AudioClock::drop_focus_handler));
392 AudioClock::drop_focus_handler (GdkEventFocus* ignored)
394 Keyboard::magic_widget_drop_focus ();
399 AudioClock::on_realize ()
403 /* styles are not available until the widgets are bound to a window */
405 set_size_requests ();
409 AudioClock::set (nframes_t when, bool force, nframes_t offset, char which)
412 if ((!force && !is_visible()) || session == 0) {
416 if (when == last_when && !offset && !force) {
420 bool pdelta = Config->get_primary_clock_delta_edit_cursor();
421 bool sdelta = Config->get_secondary_clock_delta_edit_cursor();
423 if (offset && which == 'p' && pdelta) {
424 when = (when > offset) ? when - offset : offset - when;
425 } else if (offset && which == 's' && sdelta) {
426 when = (when > offset) ? when - offset : offset - when;
429 if (which == 'p' && pdelta && !last_pdelta) {
430 set_widget_name("TransportClockDisplayDelta");
432 } else if (which == 'p' && !pdelta && last_pdelta) {
433 set_widget_name("TransportClockDisplay");
435 } else if (which == 's' && sdelta && !last_sdelta) {
436 set_widget_name("SecondaryClockDisplayDelta");
438 } else if (which == 's' && !sdelta && last_sdelta) {
439 set_widget_name("SecondaryClockDisplay");
445 set_smpte (when, force);
449 set_bbt (when, force);
453 set_minsec (when, force);
457 set_frames (when, force);
468 AudioClock::smpte_offset_changed ()
475 current = current_duration();
477 current = current_time ();
487 AudioClock::set_frames (nframes_t when, bool force)
490 snprintf (buf, sizeof (buf), "%u", when);
491 audio_frames_label.set_text (buf);
493 if (frames_upper_info_label) {
494 nframes_t rate = session->frame_rate();
496 if (fmod (rate, 1000.0) == 0.000) {
497 sprintf (buf, "%uK", rate/1000);
499 sprintf (buf, "%.3fK", rate/1000.0f);
502 frames_upper_info_label->set_text (buf);
504 float vid_pullup = Config->get_video_pullup();
506 if (vid_pullup == 0.0) {
507 frames_lower_info_label->set_text(_("none"));
509 sprintf (buf, "%-6.4f", vid_pullup);
510 frames_lower_info_label->set_text (buf);
516 AudioClock::set_minsec (nframes_t when, bool force)
525 hrs = (int) floor (left / (session->frame_rate() * 60.0f * 60.0f));
526 left -= (nframes_t) floor (hrs * session->frame_rate() * 60.0f * 60.0f);
527 mins = (int) floor (left / (session->frame_rate() * 60.0f));
528 left -= (nframes_t) floor (mins * session->frame_rate() * 60.0f);
529 secs = left / (float) session->frame_rate();
531 if (force || hrs != ms_last_hrs) {
532 sprintf (buf, "%02d", hrs);
533 ms_hours_label.set_text (buf);
537 if (force || mins != ms_last_mins) {
538 sprintf (buf, "%02d", mins);
539 ms_minutes_label.set_text (buf);
543 if (force || secs != ms_last_secs) {
544 sprintf (buf, "%06.3f", secs);
545 ms_seconds_label.set_text (buf);
551 AudioClock::set_smpte (nframes_t when, bool force)
557 session->smpte_duration (when, smpte);
559 session->smpte_time (when, smpte);
562 if (force || smpte.hours != last_hrs || smpte.negative != last_negative) {
563 if (smpte.negative) {
564 sprintf (buf, "-%02" PRIu32, smpte.hours);
566 sprintf (buf, " %02" PRIu32, smpte.hours);
568 hours_label.set_text (buf);
569 last_hrs = smpte.hours;
570 last_negative = smpte.negative;
573 if (force || smpte.minutes != last_mins) {
574 sprintf (buf, "%02" PRIu32, smpte.minutes);
575 minutes_label.set_text (buf);
576 last_mins = smpte.minutes;
579 if (force || smpte.seconds != last_secs) {
580 sprintf (buf, "%02" PRIu32, smpte.seconds);
581 seconds_label.set_text (buf);
582 last_secs = smpte.seconds;
585 if (force || smpte.frames != last_frames) {
586 sprintf (buf, "%02" PRIu32, smpte.frames);
587 frames_label.set_text (buf);
588 last_frames = smpte.frames;
591 if (smpte_upper_info_label) {
592 double smpte_frames = session->smpte_frames_per_second();
594 if ( fmod(smpte_frames, 1.0) == 0.0) {
595 sprintf (buf, "%u", int (smpte_frames));
597 sprintf (buf, "%.2f", smpte_frames);
600 smpte_upper_info_label->set_text (buf);
602 if ((fabs(smpte_frames - 29.97) < 0.0001) || smpte_frames == 30) {
603 if (session->smpte_drop_frames()) {
606 sprintf (buf, "NDF");
609 // there is no drop frame alternative
613 smpte_lower_info_label->set_text (buf);
618 AudioClock::set_bbt (nframes_t when, bool force)
623 session->tempo_map().bbt_time (when, bbt);
624 sprintf (buf, "%03" PRIu32, bbt.bars);
625 bars_label.set_text (buf);
626 sprintf (buf, "%02" PRIu32, bbt.beats);
627 beats_label.set_text (buf);
628 sprintf (buf, "%04" PRIu32, bbt.ticks);
629 ticks_label.set_text (buf);
631 if (bbt_upper_info_label) {
632 TempoMap::Metric m (session->tempo_map().metric_at (when));
633 sprintf (buf, "%-5.2f", m.tempo().beats_per_minute());
634 bbt_lower_info_label->set_text (buf);
635 sprintf (buf, "%g|%g", m.meter().beats_per_bar(), m.meter().note_divisor());
636 bbt_upper_info_label->set_text (buf);
641 AudioClock::set_session (Session *s)
648 XMLNode* node = session->extra_xml (X_("ClockModes"));
649 AudioClock::Mode amode;
652 if ((prop = node->property (_name)) != 0) {
653 amode = AudioClock::Mode (string_2_enum (prop->value(), amode));
658 set (last_when, true);
667 hours_ebox.grab_focus ();
671 bars_ebox.grab_focus ();
675 ms_hours_ebox.grab_focus ();
679 frames_ebox.grab_focus ();
689 AudioClock::field_key_press_event (GdkEventKey *ev, Field field)
691 /* all key activity is handled on key release */
696 AudioClock::field_key_release_event (GdkEventKey *ev, Field field)
701 bool move_on = false;
705 label = &hours_label;
708 label = &minutes_label;
711 label = &seconds_label;
714 label = &frames_label;
718 label = &audio_frames_label;
722 label = &ms_hours_label;
725 label = &ms_minutes_label;
728 label = &ms_seconds_label;
735 label = &beats_label;
738 label = &ticks_label;
744 switch (ev->keyval) {
788 if (_mode == MinSec && field == MS_Seconds) {
802 clock_base.grab_focus ();
811 if (key_entry_state == 0) {
813 /* initialize with a fresh new string */
815 if (field != AudioFrames) {
816 for (uint32_t xn = 0; xn < field_length[field] - 1; ++xn) {
825 string existing = label->get_text();
826 if (existing.length() >= field_length[field]) {
827 new_text = existing.substr (1, field_length[field] - 1);
829 new_text = existing.substr (0, field_length[field] - 1);
833 new_text += new_char;
834 label->set_text (new_text);
838 if (key_entry_state == field_length[field]) {
844 if (key_entry_state) {
851 // Check SMPTE fields for sanity (may also adjust fields)
852 smpte_sanitize_display();
857 // Bars or beats should never be 0
858 if (atoi(bars_label.get_text()) == 0) {
859 bars_label.set_text("001");
861 if (atoi(beats_label.get_text()) == 0) {
862 beats_label.set_text("01");
869 ValueChanged(); /* EMIT_SIGNAL */
872 /* move on to the next field.
880 minutes_ebox.grab_focus ();
883 seconds_ebox.grab_focus ();
886 frames_ebox.grab_focus ();
889 clock_base.grab_focus ();
894 clock_base.grab_focus ();
900 ms_minutes_ebox.grab_focus ();
903 ms_seconds_ebox.grab_focus ();
906 clock_base.grab_focus ();
912 beats_ebox.grab_focus ();
915 ticks_ebox.grab_focus ();
918 clock_base.grab_focus ();
931 AudioClock::field_focus_in_event (GdkEventFocus *ev, Field field)
935 Keyboard::magic_widget_grab_focus ();
939 hours_ebox.set_flags (Gtk::HAS_FOCUS);
940 hours_ebox.set_state (Gtk::STATE_ACTIVE);
943 minutes_ebox.set_flags (Gtk::HAS_FOCUS);
944 minutes_ebox.set_state (Gtk::STATE_ACTIVE);
947 seconds_ebox.set_flags (Gtk::HAS_FOCUS);
948 seconds_ebox.set_state (Gtk::STATE_ACTIVE);
951 frames_ebox.set_flags (Gtk::HAS_FOCUS);
952 frames_ebox.set_state (Gtk::STATE_ACTIVE);
956 audio_frames_ebox.set_flags (Gtk::HAS_FOCUS);
957 audio_frames_ebox.set_state (Gtk::STATE_ACTIVE);
961 ms_hours_ebox.set_flags (Gtk::HAS_FOCUS);
962 ms_hours_ebox.set_state (Gtk::STATE_ACTIVE);
965 ms_minutes_ebox.set_flags (Gtk::HAS_FOCUS);
966 ms_minutes_ebox.set_state (Gtk::STATE_ACTIVE);
969 ms_seconds_ebox.set_flags (Gtk::HAS_FOCUS);
970 ms_seconds_ebox.set_state (Gtk::STATE_ACTIVE);
973 bars_ebox.set_flags (Gtk::HAS_FOCUS);
974 bars_ebox.set_state (Gtk::STATE_ACTIVE);
977 beats_ebox.set_flags (Gtk::HAS_FOCUS);
978 beats_ebox.set_state (Gtk::STATE_ACTIVE);
981 ticks_ebox.set_flags (Gtk::HAS_FOCUS);
982 ticks_ebox.set_state (Gtk::STATE_ACTIVE);
990 AudioClock::field_focus_out_event (GdkEventFocus *ev, Field field)
995 hours_ebox.unset_flags (Gtk::HAS_FOCUS);
996 hours_ebox.set_state (Gtk::STATE_NORMAL);
999 minutes_ebox.unset_flags (Gtk::HAS_FOCUS);
1000 minutes_ebox.set_state (Gtk::STATE_NORMAL);
1003 seconds_ebox.unset_flags (Gtk::HAS_FOCUS);
1004 seconds_ebox.set_state (Gtk::STATE_NORMAL);
1007 frames_ebox.unset_flags (Gtk::HAS_FOCUS);
1008 frames_ebox.set_state (Gtk::STATE_NORMAL);
1012 audio_frames_ebox.unset_flags (Gtk::HAS_FOCUS);
1013 audio_frames_ebox.set_state (Gtk::STATE_NORMAL);
1017 ms_hours_ebox.unset_flags (Gtk::HAS_FOCUS);
1018 ms_hours_ebox.set_state (Gtk::STATE_NORMAL);
1021 ms_minutes_ebox.unset_flags (Gtk::HAS_FOCUS);
1022 ms_minutes_ebox.set_state (Gtk::STATE_NORMAL);
1025 ms_seconds_ebox.unset_flags (Gtk::HAS_FOCUS);
1026 ms_seconds_ebox.set_state (Gtk::STATE_NORMAL);
1030 bars_ebox.unset_flags (Gtk::HAS_FOCUS);
1031 bars_ebox.set_state (Gtk::STATE_NORMAL);
1034 beats_ebox.unset_flags (Gtk::HAS_FOCUS);
1035 beats_ebox.set_state (Gtk::STATE_NORMAL);
1038 ticks_ebox.unset_flags (Gtk::HAS_FOCUS);
1039 ticks_ebox.set_state (Gtk::STATE_NORMAL);
1043 Keyboard::magic_widget_drop_focus ();
1049 AudioClock::field_button_release_event (GdkEventButton *ev, Field field)
1052 gdk_pointer_ungrab (GDK_CURRENT_TIME);
1054 if (ev->y > drag_start_y+1 || ev->y < drag_start_y-1 || Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)){
1055 // we actually dragged so return without setting editing focus, or we shift clicked
1061 if (ops_menu == 0) {
1064 ops_menu->popup (1, ev->time);
1068 if (Keyboard::is_context_menu_event (ev)) {
1069 if (ops_menu == 0) {
1072 ops_menu->popup (1, ev->time);
1076 switch (ev->button) {
1080 hours_ebox.grab_focus();
1083 minutes_ebox.grab_focus();
1086 seconds_ebox.grab_focus();
1089 frames_ebox.grab_focus();
1093 audio_frames_ebox.grab_focus();
1097 ms_hours_ebox.grab_focus();
1100 ms_minutes_ebox.grab_focus();
1103 ms_seconds_ebox.grab_focus();
1107 bars_ebox.grab_focus ();
1110 beats_ebox.grab_focus ();
1113 ticks_ebox.grab_focus ();
1126 AudioClock::field_button_press_event (GdkEventButton *ev, Field field)
1128 if (session == 0) return false;
1130 nframes_t frames = 0;
1132 switch (ev->button) {
1134 if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
1136 ValueChanged (); /* EMIT_SIGNAL */
1139 /* make absolutely sure that the pointer is grabbed */
1140 gdk_pointer_grab(ev->window,false ,
1141 GdkEventMask( Gdk::POINTER_MOTION_MASK | Gdk::BUTTON_PRESS_MASK |Gdk::BUTTON_RELEASE_MASK),
1142 NULL,NULL,ev->time);
1145 drag_start_y = ev->y;
1150 if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
1152 ValueChanged (); /* EMIT_SIGNAL */
1157 /* used for context sensitive menu */
1170 AudioClock::field_button_scroll_event (GdkEventScroll *ev, Field field)
1176 nframes_t frames = 0;
1178 switch (ev->direction) {
1181 frames = get_frames (field);
1183 if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
1186 set (current_time() + frames, true);
1187 ValueChanged (); /* EMIT_SIGNAL */
1191 case GDK_SCROLL_DOWN:
1192 frames = get_frames (field);
1194 if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
1198 if ((double)current_time() - (double)frames < 0.0) {
1201 set (current_time() - frames, true);
1204 ValueChanged (); /* EMIT_SIGNAL */
1217 AudioClock::field_motion_notify_event (GdkEventMotion *ev, Field field)
1219 if (session == 0 || !dragging) {
1223 float pixel_frame_scale_factor = 0.2f;
1226 if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
1227 pixel_frame_scale_factor = 0.1f;
1231 if (Keyboard::modifier_state_contains (ev->state,
1232 Keyboard::PrimaryModifier|Keyboard::SecondaryModifier)) {
1234 pixel_frame_scale_factor = 0.025f;
1237 double y_delta = ev->y - drag_y;
1239 drag_accum += y_delta*pixel_frame_scale_factor;
1243 if (trunc(drag_accum) != 0) {
1248 dir = (drag_accum < 0 ? 1:-1);
1249 pos = current_time();
1250 frames = get_frames (field,pos,dir);
1252 if (frames != 0 && frames * drag_accum < current_time()) {
1254 set ((nframes_t) floor (pos - drag_accum * frames), false); // minus because up is negative in computer-land
1262 ValueChanged(); /* EMIT_SIGNAL */
1271 AudioClock::get_frames (Field field,nframes_t pos,int dir)
1274 nframes_t frames = 0;
1278 frames = (nframes_t) floor (3600.0 * session->frame_rate());
1281 frames = (nframes_t) floor (60.0 * session->frame_rate());
1284 frames = session->frame_rate();
1287 frames = (nframes_t) floor (session->frame_rate() / session->smpte_frames_per_second());
1295 frames = (nframes_t) floor (3600.0 * session->frame_rate());
1298 frames = (nframes_t) floor (60.0 * session->frame_rate());
1301 frames = session->frame_rate();
1308 frames = session->tempo_map().bbt_duration_at(pos,bbt,dir);
1314 frames = session->tempo_map().bbt_duration_at(pos,bbt,dir);
1320 frames = session->tempo_map().bbt_duration_at(pos,bbt,dir);
1328 AudioClock::current_time (nframes_t pos) const
1334 ret = smpte_frame_from_display ();
1337 ret = bbt_frame_from_display (pos);
1341 ret = minsec_frame_from_display ();
1345 ret = audio_frame_from_display ();
1356 AudioClock::current_duration (nframes_t pos) const
1362 ret = smpte_frame_from_display ();
1365 ret = bbt_frame_duration_from_display (pos);
1369 ret = minsec_frame_from_display ();
1373 ret = audio_frame_from_display ();
1384 AudioClock::smpte_sanitize_display()
1386 // Check SMPTE fields for sanity, possibly adjusting values
1387 if (atoi(minutes_label.get_text()) > 59) {
1388 minutes_label.set_text("59");
1391 if (atoi(seconds_label.get_text()) > 59) {
1392 seconds_label.set_text("59");
1395 switch ((long)rint(session->smpte_frames_per_second())) {
1397 if (atoi(frames_label.get_text()) > 23) {
1398 frames_label.set_text("23");
1402 if (atoi(frames_label.get_text()) > 24) {
1403 frames_label.set_text("24");
1407 if (atoi(frames_label.get_text()) > 29) {
1408 frames_label.set_text("29");
1415 if (session->smpte_drop_frames()) {
1416 if ((atoi(minutes_label.get_text()) % 10) && (atoi(seconds_label.get_text()) == 0) && (atoi(frames_label.get_text()) < 2)) {
1417 frames_label.set_text("02");
1423 AudioClock::smpte_frame_from_display () const
1432 smpte.hours = atoi (hours_label.get_text());
1433 smpte.minutes = atoi (minutes_label.get_text());
1434 smpte.seconds = atoi (seconds_label.get_text());
1435 smpte.frames = atoi (frames_label.get_text());
1436 smpte.rate = session->smpte_frames_per_second();
1437 smpte.drop= session->smpte_drop_frames();
1439 session->smpte_to_sample( smpte, sample, false /* use_offset */, false /* use_subframes */ );
1443 #define SMPTE_SAMPLE_TEST_1
1444 #define SMPTE_SAMPLE_TEST_2
1445 #define SMPTE_SAMPLE_TEST_3
1446 #define SMPTE_SAMPLE_TEST_4
1447 #define SMPTE_SAMPLE_TEST_5
1448 #define SMPTE_SAMPLE_TEST_6
1449 #define SMPTE_SAMPLE_TEST_7
1451 // Testcode for smpte<->sample conversions (P.S.)
1454 nframes_t oldsample = 0;
1456 nframes_t sample_increment;
1458 sample_increment = (long)rint(session->frame_rate() / session->smpte_frames_per_second);
1460 #ifdef SMPTE_SAMPLE_TEST_1
1461 // Test 1: use_offset = false, use_subframes = false
1462 cout << "use_offset = false, use_subframes = false" << endl;
1463 for (int i = 0; i < 108003; i++) {
1464 session->smpte_to_sample( smpte1, sample1, false /* use_offset */, false /* use_subframes */ );
1465 session->sample_to_smpte( sample1, smpte2, false /* use_offset */, false /* use_subframes */ );
1467 if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
1468 cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1469 cout << "smpte1: " << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1470 cout << "sample: " << sample1 << endl;
1471 cout << "sample: " << sample1 << " -> ";
1472 cout << "smpte2: " << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1476 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1477 cout << "ERROR: smpte2 not equal smpte1" << endl;
1478 cout << "smpte1: " << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1479 cout << "sample: " << sample1 << endl;
1480 cout << "sample: " << sample1 << " -> ";
1481 cout << "smpte2: " << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1484 oldsample = sample1;
1485 session->smpte_increment( smpte1 );
1488 cout << "sample_increment: " << sample_increment << endl;
1489 cout << "sample: " << sample1 << " -> ";
1490 cout << "smpte: " << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1493 #ifdef SMPTE_SAMPLE_TEST_2
1494 // Test 2: use_offset = true, use_subframes = false
1495 cout << "use_offset = true, use_subframes = false" << endl;
1501 smpte1.subframes = 0;
1502 sample1 = oldsample = 0;
1504 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1505 cout << "Starting at sample: " << sample1 << " -> ";
1506 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1508 for (int i = 0; i < 108003; i++) {
1509 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1510 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1512 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1513 // cout << "sample: " << sample1 << endl;
1514 // cout << "sample: " << sample1 << " -> ";
1515 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1517 if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
1518 cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1519 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1520 cout << "sample: " << sample1 << endl;
1521 cout << "sample: " << sample1 << " -> ";
1522 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1526 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1527 cout << "ERROR: smpte2 not equal smpte1" << endl;
1528 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1529 cout << "sample: " << sample1 << endl;
1530 cout << "sample: " << sample1 << " -> ";
1531 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1534 oldsample = sample1;
1535 session->smpte_increment( smpte1 );
1538 cout << "sample_increment: " << sample_increment << endl;
1539 cout << "sample: " << sample1 << " -> ";
1540 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1543 #ifdef SMPTE_SAMPLE_TEST_3
1544 // Test 3: use_offset = true, use_subframes = false, decrement
1545 cout << "use_offset = true, use_subframes = false, decrement" << endl;
1547 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* 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 */, false /* use_subframes */ );
1553 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1555 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1556 // cout << "sample: " << sample1 << endl;
1557 // cout << "sample: " << sample1 << " -> ";
1558 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1560 if ((i > 0) && ( ((oldsample - sample1) != sample_increment) && ((oldsample - sample1) != (sample_increment + 1)) && ((oldsample - sample1) != (sample_increment - 1)))) {
1561 cout << "ERROR: sample increment not right: " << (oldsample - sample1) << " != " << sample_increment << endl;
1562 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1563 cout << "sample: " << sample1 << endl;
1564 cout << "sample: " << sample1 << " -> ";
1565 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1569 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1570 cout << "ERROR: smpte2 not equal smpte1" << endl;
1571 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1572 cout << "sample: " << sample1 << endl;
1573 cout << "sample: " << sample1 << " -> ";
1574 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1577 oldsample = sample1;
1578 session->smpte_decrement( smpte1 );
1581 cout << "sample_decrement: " << sample_increment << endl;
1582 cout << "sample: " << sample1 << " -> ";
1583 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1587 #ifdef SMPTE_SAMPLE_TEST_4
1588 // Test 4: use_offset = true, use_subframes = true
1589 cout << "use_offset = true, use_subframes = true" << endl;
1591 for (long sub = 5; sub < 80; sub += 5) {
1596 smpte1.subframes = 0;
1597 sample1 = oldsample = (sample_increment * sub) / 80;
1599 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, true /* use_subframes */ );
1601 cout << "starting at sample: " << sample1 << " -> ";
1602 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1604 for (int i = 0; i < 108003; i++) {
1605 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, true /* use_subframes */ );
1606 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, true /* use_subframes */ );
1608 if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
1609 cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1610 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1611 cout << "sample: " << sample1 << endl;
1612 cout << "sample: " << sample1 << " -> ";
1613 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1617 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames || smpte2.subframes != smpte1.subframes) {
1618 cout << "ERROR: smpte2 not equal smpte1" << endl;
1619 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1620 cout << "sample: " << sample1 << endl;
1621 cout << "sample: " << sample1 << " -> ";
1622 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1625 oldsample = sample1;
1626 session->smpte_increment( smpte1 );
1629 cout << "sample_increment: " << sample_increment << endl;
1630 cout << "sample: " << sample1 << " -> ";
1631 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1633 for (int i = 0; i < 108003; i++) {
1634 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, true /* use_subframes */ );
1635 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, true /* use_subframes */ );
1637 if ((i > 0) && ( ((oldsample - sample1) != sample_increment) && ((oldsample - sample1) != (sample_increment + 1)) && ((oldsample - sample1) != (sample_increment - 1)))) {
1638 cout << "ERROR: sample increment not right: " << (oldsample - sample1) << " != " << sample_increment << endl;
1639 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1640 cout << "sample: " << sample1 << endl;
1641 cout << "sample: " << sample1 << " -> ";
1642 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1646 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames || smpte2.subframes != smpte1.subframes) {
1647 cout << "ERROR: smpte2 not equal smpte1" << endl;
1648 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1649 cout << "sample: " << sample1 << endl;
1650 cout << "sample: " << sample1 << " -> ";
1651 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1654 oldsample = sample1;
1655 session->smpte_decrement( smpte1 );
1658 cout << "sample_decrement: " << sample_increment << endl;
1659 cout << "sample: " << sample1 << " -> ";
1660 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1665 #ifdef SMPTE_SAMPLE_TEST_5
1666 // Test 5: use_offset = true, use_subframes = false, increment seconds
1667 cout << "use_offset = true, use_subframes = false, increment seconds" << endl;
1673 smpte1.subframes = 0;
1674 sample1 = oldsample = 0;
1675 sample_increment = session->frame_rate();
1677 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1678 cout << "Starting at sample: " << sample1 << " -> ";
1679 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1681 for (int i = 0; i < 3600; i++) {
1682 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1683 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1685 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1686 // cout << "sample: " << sample1 << endl;
1687 // cout << "sample: " << sample1 << " -> ";
1688 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1690 // if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1692 // cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1696 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1697 cout << "ERROR: smpte2 not equal smpte1" << endl;
1698 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1699 cout << "sample: " << sample1 << endl;
1700 cout << "sample: " << sample1 << " -> ";
1701 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1704 oldsample = sample1;
1705 session->smpte_increment_seconds( smpte1 );
1708 cout << "sample_increment: " << sample_increment << endl;
1709 cout << "sample: " << sample1 << " -> ";
1710 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1714 #ifdef SMPTE_SAMPLE_TEST_6
1715 // Test 6: use_offset = true, use_subframes = false, increment minutes
1716 cout << "use_offset = true, use_subframes = false, increment minutes" << endl;
1722 smpte1.subframes = 0;
1723 sample1 = oldsample = 0;
1724 sample_increment = session->frame_rate() * 60;
1726 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1727 cout << "Starting at sample: " << sample1 << " -> ";
1728 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1730 for (int i = 0; i < 60; i++) {
1731 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1732 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1734 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1735 // cout << "sample: " << sample1 << endl;
1736 // cout << "sample: " << sample1 << " -> ";
1737 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1739 // if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1741 // cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1745 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1746 cout << "ERROR: smpte2 not equal smpte1" << endl;
1747 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1748 cout << "sample: " << sample1 << endl;
1749 cout << "sample: " << sample1 << " -> ";
1750 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1753 oldsample = sample1;
1754 session->smpte_increment_minutes( smpte1 );
1757 cout << "sample_increment: " << sample_increment << endl;
1758 cout << "sample: " << sample1 << " -> ";
1759 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1762 #ifdef SMPTE_SAMPLE_TEST_7
1763 // Test 7: use_offset = true, use_subframes = false, increment hours
1764 cout << "use_offset = true, use_subframes = false, increment hours" << endl;
1770 smpte1.subframes = 0;
1771 sample1 = oldsample = 0;
1772 sample_increment = session->frame_rate() * 60 * 60;
1774 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1775 cout << "Starting at sample: " << sample1 << " -> ";
1776 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1778 for (int i = 0; i < 10; i++) {
1779 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1780 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1782 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1783 // cout << "sample: " << sample1 << endl;
1784 // cout << "sample: " << sample1 << " -> ";
1785 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1787 // if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1789 // cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1793 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1794 cout << "ERROR: smpte2 not equal smpte1" << endl;
1795 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1796 cout << "sample: " << sample1 << endl;
1797 cout << "sample: " << sample1 << " -> ";
1798 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1801 oldsample = sample1;
1802 session->smpte_increment_hours( smpte1 );
1805 cout << "sample_increment: " << sample_increment << endl;
1806 cout << "sample: " << sample1 << " -> ";
1807 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1816 AudioClock::minsec_frame_from_display () const
1822 int hrs = atoi (ms_hours_label.get_text());
1823 int mins = atoi (ms_minutes_label.get_text());
1824 float secs = atof (ms_seconds_label.get_text());
1826 nframes_t sr = session->frame_rate();
1828 return (nframes_t) floor ((hrs * 60.0f * 60.0f * sr) + (mins * 60.0f * sr) + (secs * sr));
1832 AudioClock::bbt_frame_from_display (nframes_t pos) const
1835 error << "AudioClock::current_time() called with BBT mode but without session!" << endmsg;
1840 any.type = AnyTime::BBT;
1842 any.bbt.bars = atoi (bars_label.get_text());
1843 any.bbt.beats = atoi (beats_label.get_text());
1844 any.bbt.ticks = atoi (ticks_label.get_text());
1846 nframes_t ret = session->convert_to_frames_at (pos, any);
1853 AudioClock::bbt_frame_duration_from_display (nframes_t pos) const
1856 error << "AudioClock::current_time() called with BBT mode but without session!" << endmsg;
1863 bbt.bars = atoi (bars_label.get_text());
1864 bbt.beats = atoi (beats_label.get_text());
1865 bbt.ticks = atoi (ticks_label.get_text());
1867 return session->tempo_map().bbt_duration_at(pos,bbt,1);
1871 AudioClock::audio_frame_from_display () const
1873 return (nframes_t) atoi (audio_frames_label.get_text());
1877 AudioClock::build_ops_menu ()
1879 using namespace Menu_Helpers;
1880 ops_menu = new Menu;
1881 MenuList& ops_items = ops_menu->items();
1882 ops_menu->set_name ("ArdourContextMenu");
1884 ops_items.push_back (MenuElem (_("Timecode"), bind (mem_fun(*this, &AudioClock::set_mode), SMPTE)));
1885 ops_items.push_back (MenuElem (_("Bars:Beats"), bind (mem_fun(*this, &AudioClock::set_mode), BBT)));
1886 ops_items.push_back (MenuElem (_("Minutes:Seconds"), bind (mem_fun(*this, &AudioClock::set_mode), MinSec)));
1887 ops_items.push_back (MenuElem (_("Samples"), bind (mem_fun(*this, &AudioClock::set_mode), Frames)));
1888 ops_items.push_back (MenuElem (_("Off"), bind (mem_fun(*this, &AudioClock::set_mode), Off)));
1892 AudioClock::set_mode (Mode m)
1894 /* slightly tricky: this is called from within the ARDOUR_UI
1895 constructor by some of its clock members. at that time
1896 the instance pointer is unset, so we have to be careful.
1897 the main idea is to drop keyboard focus in case we had
1898 started editing the clock and then we switch clock mode.
1901 clock_base.grab_focus ();
1907 clock_base.remove ();
1913 clock_base.add (smpte_packer_hbox);
1917 clock_base.add (bbt_packer_hbox);
1921 clock_base.add (minsec_packer_hbox);
1925 clock_base.add (frames_packer_hbox);
1929 clock_base.add (off_hbox);
1933 set_size_requests ();
1935 set (last_when, true);
1936 clock_base.show_all ();
1937 key_entry_state = 0;
1939 if (!is_transient) {
1940 ModeChanged (); /* EMIT SIGNAL */
1945 AudioClock::set_size_requests ()
1947 /* note that in some fonts, "88" is narrower than "00", hence the 2 pixel padding */
1951 Gtkmm2ext::set_size_request_to_display_given_text (hours_label, "-00", 5, 5);
1952 Gtkmm2ext::set_size_request_to_display_given_text (minutes_label, "00", 5, 5);
1953 Gtkmm2ext::set_size_request_to_display_given_text (seconds_label, "00", 5, 5);
1954 Gtkmm2ext::set_size_request_to_display_given_text (frames_label, "00", 5, 5);
1958 Gtkmm2ext::set_size_request_to_display_given_text (bars_label, "-000", 5, 5);
1959 Gtkmm2ext::set_size_request_to_display_given_text (beats_label, "00", 5, 5);
1960 Gtkmm2ext::set_size_request_to_display_given_text (ticks_label, "0000", 5, 5);
1964 Gtkmm2ext::set_size_request_to_display_given_text (ms_hours_label, "00", 5, 5);
1965 Gtkmm2ext::set_size_request_to_display_given_text (ms_minutes_label, "00", 5, 5);
1966 Gtkmm2ext::set_size_request_to_display_given_text (ms_seconds_label, "00.000", 5, 5);
1970 Gtkmm2ext::set_size_request_to_display_given_text (audio_frames_label, "0000000000", 5, 5);
1974 Gtkmm2ext::set_size_request_to_display_given_text (off_hbox, "00000", 5, 5);