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 (session->smpte_drop_frames()) {
605 sprintf (buf, "NDF");
608 smpte_lower_info_label->set_text (buf);
613 AudioClock::set_bbt (nframes_t when, bool force)
618 session->tempo_map().bbt_time (when, bbt);
619 sprintf (buf, "%03" PRIu32, bbt.bars);
620 bars_label.set_text (buf);
621 sprintf (buf, "%02" PRIu32, bbt.beats);
622 beats_label.set_text (buf);
623 sprintf (buf, "%04" PRIu32, bbt.ticks);
624 ticks_label.set_text (buf);
626 if (bbt_upper_info_label) {
627 TempoMap::Metric m (session->tempo_map().metric_at (when));
628 sprintf (buf, "%-5.2f", m.tempo().beats_per_minute());
629 bbt_lower_info_label->set_text (buf);
630 sprintf (buf, "%g|%g", m.meter().beats_per_bar(), m.meter().note_divisor());
631 bbt_upper_info_label->set_text (buf);
636 AudioClock::set_session (Session *s)
643 XMLNode* node = session->extra_xml (X_("ClockModes"));
644 AudioClock::Mode amode;
647 if ((prop = node->property (_name)) != 0) {
648 amode = AudioClock::Mode (string_2_enum (prop->value(), amode));
653 set (last_when, true);
658 AudioClock::field_key_press_event (GdkEventKey *ev, Field field)
660 /* all key activity is handled on key release */
665 AudioClock::field_key_release_event (GdkEventKey *ev, Field field)
670 bool move_on = false;
674 label = &hours_label;
677 label = &minutes_label;
680 label = &seconds_label;
683 label = &frames_label;
687 label = &audio_frames_label;
691 label = &ms_hours_label;
694 label = &ms_minutes_label;
697 label = &ms_seconds_label;
704 label = &beats_label;
707 label = &ticks_label;
713 switch (ev->keyval) {
757 if (_mode == MinSec && field == MS_Seconds) {
771 clock_base.grab_focus ();
780 if (key_entry_state == 0) {
782 /* initialize with a fresh new string */
784 if (field != AudioFrames) {
785 for (uint32_t xn = 0; xn < field_length[field] - 1; ++xn) {
794 string existing = label->get_text();
795 if (existing.length() >= field_length[field]) {
796 new_text = existing.substr (1, field_length[field] - 1);
798 new_text = existing.substr (0, field_length[field] - 1);
802 new_text += new_char;
803 label->set_text (new_text);
807 if (key_entry_state == field_length[field]) {
813 if (key_entry_state) {
820 // Check SMPTE fields for sanity (may also adjust fields)
821 smpte_sanitize_display();
826 // Bars or beats should never be 0
827 if (atoi(bars_label.get_text()) == 0) {
828 bars_label.set_text("001");
830 if (atoi(beats_label.get_text()) == 0) {
831 beats_label.set_text("01");
838 ValueChanged(); /* EMIT_SIGNAL */
841 /* move on to the next field.
849 minutes_ebox.grab_focus ();
852 seconds_ebox.grab_focus ();
855 frames_ebox.grab_focus ();
858 clock_base.grab_focus ();
863 clock_base.grab_focus ();
869 ms_minutes_ebox.grab_focus ();
872 ms_seconds_ebox.grab_focus ();
875 clock_base.grab_focus ();
881 beats_ebox.grab_focus ();
884 ticks_ebox.grab_focus ();
887 clock_base.grab_focus ();
900 AudioClock::field_focus_in_event (GdkEventFocus *ev, Field field)
904 Keyboard::magic_widget_grab_focus ();
908 hours_ebox.set_flags (Gtk::HAS_FOCUS);
909 hours_ebox.set_state (Gtk::STATE_ACTIVE);
912 minutes_ebox.set_flags (Gtk::HAS_FOCUS);
913 minutes_ebox.set_state (Gtk::STATE_ACTIVE);
916 seconds_ebox.set_flags (Gtk::HAS_FOCUS);
917 seconds_ebox.set_state (Gtk::STATE_ACTIVE);
920 frames_ebox.set_flags (Gtk::HAS_FOCUS);
921 frames_ebox.set_state (Gtk::STATE_ACTIVE);
925 audio_frames_ebox.set_flags (Gtk::HAS_FOCUS);
926 audio_frames_ebox.set_state (Gtk::STATE_ACTIVE);
930 ms_hours_ebox.set_flags (Gtk::HAS_FOCUS);
931 ms_hours_ebox.set_state (Gtk::STATE_ACTIVE);
934 ms_minutes_ebox.set_flags (Gtk::HAS_FOCUS);
935 ms_minutes_ebox.set_state (Gtk::STATE_ACTIVE);
938 ms_seconds_ebox.set_flags (Gtk::HAS_FOCUS);
939 ms_seconds_ebox.set_state (Gtk::STATE_ACTIVE);
942 bars_ebox.set_flags (Gtk::HAS_FOCUS);
943 bars_ebox.set_state (Gtk::STATE_ACTIVE);
946 beats_ebox.set_flags (Gtk::HAS_FOCUS);
947 beats_ebox.set_state (Gtk::STATE_ACTIVE);
950 ticks_ebox.set_flags (Gtk::HAS_FOCUS);
951 ticks_ebox.set_state (Gtk::STATE_ACTIVE);
959 AudioClock::field_focus_out_event (GdkEventFocus *ev, Field field)
964 hours_ebox.unset_flags (Gtk::HAS_FOCUS);
965 hours_ebox.set_state (Gtk::STATE_NORMAL);
968 minutes_ebox.unset_flags (Gtk::HAS_FOCUS);
969 minutes_ebox.set_state (Gtk::STATE_NORMAL);
972 seconds_ebox.unset_flags (Gtk::HAS_FOCUS);
973 seconds_ebox.set_state (Gtk::STATE_NORMAL);
976 frames_ebox.unset_flags (Gtk::HAS_FOCUS);
977 frames_ebox.set_state (Gtk::STATE_NORMAL);
981 audio_frames_ebox.unset_flags (Gtk::HAS_FOCUS);
982 audio_frames_ebox.set_state (Gtk::STATE_NORMAL);
986 ms_hours_ebox.unset_flags (Gtk::HAS_FOCUS);
987 ms_hours_ebox.set_state (Gtk::STATE_NORMAL);
990 ms_minutes_ebox.unset_flags (Gtk::HAS_FOCUS);
991 ms_minutes_ebox.set_state (Gtk::STATE_NORMAL);
994 ms_seconds_ebox.unset_flags (Gtk::HAS_FOCUS);
995 ms_seconds_ebox.set_state (Gtk::STATE_NORMAL);
999 bars_ebox.unset_flags (Gtk::HAS_FOCUS);
1000 bars_ebox.set_state (Gtk::STATE_NORMAL);
1003 beats_ebox.unset_flags (Gtk::HAS_FOCUS);
1004 beats_ebox.set_state (Gtk::STATE_NORMAL);
1007 ticks_ebox.unset_flags (Gtk::HAS_FOCUS);
1008 ticks_ebox.set_state (Gtk::STATE_NORMAL);
1012 Keyboard::magic_widget_drop_focus ();
1018 AudioClock::field_button_release_event (GdkEventButton *ev, Field field)
1021 gdk_pointer_ungrab (GDK_CURRENT_TIME);
1023 if (ev->y > drag_start_y+1 || ev->y < drag_start_y-1 || Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)){
1024 // we actually dragged so return without setting editing focus, or we shift clicked
1030 if (ops_menu == 0) {
1033 ops_menu->popup (1, ev->time);
1037 if (Keyboard::is_context_menu_event (ev)) {
1038 if (ops_menu == 0) {
1041 ops_menu->popup (1, ev->time);
1045 switch (ev->button) {
1049 hours_ebox.grab_focus();
1052 minutes_ebox.grab_focus();
1055 seconds_ebox.grab_focus();
1058 frames_ebox.grab_focus();
1062 audio_frames_ebox.grab_focus();
1066 ms_hours_ebox.grab_focus();
1069 ms_minutes_ebox.grab_focus();
1072 ms_seconds_ebox.grab_focus();
1076 bars_ebox.grab_focus ();
1079 beats_ebox.grab_focus ();
1082 ticks_ebox.grab_focus ();
1095 AudioClock::field_button_press_event (GdkEventButton *ev, Field field)
1097 if (session == 0) return false;
1099 nframes_t frames = 0;
1101 switch (ev->button) {
1103 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
1105 ValueChanged (); /* EMIT_SIGNAL */
1108 /* make absolutely sure that the pointer is grabbed */
1109 gdk_pointer_grab(ev->window,false ,
1110 GdkEventMask( Gdk::POINTER_MOTION_MASK | Gdk::BUTTON_PRESS_MASK |Gdk::BUTTON_RELEASE_MASK),
1111 NULL,NULL,ev->time);
1114 drag_start_y = ev->y;
1119 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
1121 ValueChanged (); /* EMIT_SIGNAL */
1126 /* used for context sensitive menu */
1139 AudioClock::field_button_scroll_event (GdkEventScroll *ev, Field field)
1145 nframes_t frames = 0;
1147 switch (ev->direction) {
1150 frames = get_frames (field);
1152 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
1155 set (current_time() + frames, true);
1156 ValueChanged (); /* EMIT_SIGNAL */
1160 case GDK_SCROLL_DOWN:
1161 frames = get_frames (field);
1163 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
1167 if ((double)current_time() - (double)frames < 0.0) {
1170 set (current_time() - frames, true);
1173 ValueChanged (); /* EMIT_SIGNAL */
1186 AudioClock::field_motion_notify_event (GdkEventMotion *ev, Field field)
1188 if (session == 0 || !dragging) {
1192 float pixel_frame_scale_factor = 0.2f;
1195 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
1196 pixel_frame_scale_factor = 0.1f;
1200 if (Keyboard::modifier_state_contains (ev->state,
1201 Keyboard::Control|Keyboard::Alt)) {
1203 pixel_frame_scale_factor = 0.025f;
1206 double y_delta = ev->y - drag_y;
1208 drag_accum += y_delta*pixel_frame_scale_factor;
1212 if (trunc(drag_accum) != 0) {
1217 dir = (drag_accum < 0 ? 1:-1);
1218 pos = current_time();
1219 frames = get_frames (field,pos,dir);
1221 if (frames != 0 && frames * drag_accum < current_time()) {
1223 set ((nframes_t) floor (pos - drag_accum * frames), false); // minus because up is negative in computer-land
1231 ValueChanged(); /* EMIT_SIGNAL */
1240 AudioClock::get_frames (Field field,nframes_t pos,int dir)
1243 nframes_t frames = 0;
1247 frames = (nframes_t) floor (3600.0 * session->frame_rate());
1250 frames = (nframes_t) floor (60.0 * session->frame_rate());
1253 frames = session->frame_rate();
1256 frames = (nframes_t) floor (session->frame_rate() / session->smpte_frames_per_second());
1264 frames = (nframes_t) floor (3600.0 * session->frame_rate());
1267 frames = (nframes_t) floor (60.0 * session->frame_rate());
1270 frames = session->frame_rate();
1277 frames = session->tempo_map().bbt_duration_at(pos,bbt,dir);
1283 frames = session->tempo_map().bbt_duration_at(pos,bbt,dir);
1289 frames = session->tempo_map().bbt_duration_at(pos,bbt,dir);
1297 AudioClock::current_time (nframes_t pos) const
1303 ret = smpte_frame_from_display ();
1306 ret = bbt_frame_from_display (pos);
1310 ret = minsec_frame_from_display ();
1314 ret = audio_frame_from_display ();
1325 AudioClock::current_duration (nframes_t pos) const
1331 ret = smpte_frame_from_display ();
1334 ret = bbt_frame_duration_from_display (pos);
1338 ret = minsec_frame_from_display ();
1342 ret = audio_frame_from_display ();
1353 AudioClock::smpte_sanitize_display()
1355 // Check SMPTE fields for sanity, possibly adjusting values
1356 if (atoi(minutes_label.get_text()) > 59) {
1357 minutes_label.set_text("59");
1360 if (atoi(seconds_label.get_text()) > 59) {
1361 seconds_label.set_text("59");
1364 switch ((long)rint(session->smpte_frames_per_second())) {
1366 if (atoi(frames_label.get_text()) > 23) {
1367 frames_label.set_text("23");
1371 if (atoi(frames_label.get_text()) > 24) {
1372 frames_label.set_text("24");
1376 if (atoi(frames_label.get_text()) > 29) {
1377 frames_label.set_text("29");
1384 if (session->smpte_drop_frames()) {
1385 if ((atoi(minutes_label.get_text()) % 10) && (atoi(seconds_label.get_text()) == 0) && (atoi(frames_label.get_text()) < 2)) {
1386 frames_label.set_text("02");
1392 AudioClock::smpte_frame_from_display () const
1401 smpte.hours = atoi (hours_label.get_text());
1402 smpte.minutes = atoi (minutes_label.get_text());
1403 smpte.seconds = atoi (seconds_label.get_text());
1404 smpte.frames = atoi (frames_label.get_text());
1405 smpte.rate = session->smpte_frames_per_second();
1406 smpte.drop= session->smpte_drop_frames();
1408 session->smpte_to_sample( smpte, sample, false /* use_offset */, false /* use_subframes */ );
1412 #define SMPTE_SAMPLE_TEST_1
1413 #define SMPTE_SAMPLE_TEST_2
1414 #define SMPTE_SAMPLE_TEST_3
1415 #define SMPTE_SAMPLE_TEST_4
1416 #define SMPTE_SAMPLE_TEST_5
1417 #define SMPTE_SAMPLE_TEST_6
1418 #define SMPTE_SAMPLE_TEST_7
1420 // Testcode for smpte<->sample conversions (P.S.)
1423 nframes_t oldsample = 0;
1425 nframes_t sample_increment;
1427 sample_increment = (long)rint(session->frame_rate() / session->smpte_frames_per_second);
1429 #ifdef SMPTE_SAMPLE_TEST_1
1430 // Test 1: use_offset = false, use_subframes = false
1431 cout << "use_offset = false, use_subframes = false" << endl;
1432 for (int i = 0; i < 108003; i++) {
1433 session->smpte_to_sample( smpte1, sample1, false /* use_offset */, false /* use_subframes */ );
1434 session->sample_to_smpte( sample1, smpte2, false /* use_offset */, false /* use_subframes */ );
1436 if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
1437 cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1438 cout << "smpte1: " << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1439 cout << "sample: " << sample1 << endl;
1440 cout << "sample: " << sample1 << " -> ";
1441 cout << "smpte2: " << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1445 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1446 cout << "ERROR: smpte2 not equal smpte1" << endl;
1447 cout << "smpte1: " << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1448 cout << "sample: " << sample1 << endl;
1449 cout << "sample: " << sample1 << " -> ";
1450 cout << "smpte2: " << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1453 oldsample = sample1;
1454 session->smpte_increment( smpte1 );
1457 cout << "sample_increment: " << sample_increment << endl;
1458 cout << "sample: " << sample1 << " -> ";
1459 cout << "smpte: " << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1462 #ifdef SMPTE_SAMPLE_TEST_2
1463 // Test 2: use_offset = true, use_subframes = false
1464 cout << "use_offset = true, use_subframes = false" << endl;
1470 smpte1.subframes = 0;
1471 sample1 = oldsample = 0;
1473 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1474 cout << "Starting at sample: " << sample1 << " -> ";
1475 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1477 for (int i = 0; i < 108003; i++) {
1478 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1479 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1481 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1482 // cout << "sample: " << sample1 << endl;
1483 // cout << "sample: " << sample1 << " -> ";
1484 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1486 if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
1487 cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1488 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1489 cout << "sample: " << sample1 << endl;
1490 cout << "sample: " << sample1 << " -> ";
1491 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1495 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1496 cout << "ERROR: smpte2 not equal smpte1" << endl;
1497 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1498 cout << "sample: " << sample1 << endl;
1499 cout << "sample: " << sample1 << " -> ";
1500 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1503 oldsample = sample1;
1504 session->smpte_increment( smpte1 );
1507 cout << "sample_increment: " << sample_increment << endl;
1508 cout << "sample: " << sample1 << " -> ";
1509 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1512 #ifdef SMPTE_SAMPLE_TEST_3
1513 // Test 3: use_offset = true, use_subframes = false, decrement
1514 cout << "use_offset = true, use_subframes = false, decrement" << endl;
1516 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1517 cout << "Starting at sample: " << sample1 << " -> ";
1518 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1520 for (int i = 0; i < 108003; i++) {
1521 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1522 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1524 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1525 // cout << "sample: " << sample1 << endl;
1526 // cout << "sample: " << sample1 << " -> ";
1527 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1529 if ((i > 0) && ( ((oldsample - sample1) != sample_increment) && ((oldsample - sample1) != (sample_increment + 1)) && ((oldsample - sample1) != (sample_increment - 1)))) {
1530 cout << "ERROR: sample increment not right: " << (oldsample - sample1) << " != " << sample_increment << endl;
1531 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1532 cout << "sample: " << sample1 << endl;
1533 cout << "sample: " << sample1 << " -> ";
1534 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1538 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1539 cout << "ERROR: smpte2 not equal smpte1" << endl;
1540 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1541 cout << "sample: " << sample1 << endl;
1542 cout << "sample: " << sample1 << " -> ";
1543 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1546 oldsample = sample1;
1547 session->smpte_decrement( smpte1 );
1550 cout << "sample_decrement: " << sample_increment << endl;
1551 cout << "sample: " << sample1 << " -> ";
1552 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1556 #ifdef SMPTE_SAMPLE_TEST_4
1557 // Test 4: use_offset = true, use_subframes = true
1558 cout << "use_offset = true, use_subframes = true" << endl;
1560 for (long sub = 5; sub < 80; sub += 5) {
1565 smpte1.subframes = 0;
1566 sample1 = oldsample = (sample_increment * sub) / 80;
1568 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, true /* use_subframes */ );
1570 cout << "starting at sample: " << sample1 << " -> ";
1571 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1573 for (int i = 0; i < 108003; i++) {
1574 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, true /* use_subframes */ );
1575 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, true /* use_subframes */ );
1577 if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
1578 cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1579 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1580 cout << "sample: " << sample1 << endl;
1581 cout << "sample: " << sample1 << " -> ";
1582 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1586 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames || smpte2.subframes != smpte1.subframes) {
1587 cout << "ERROR: smpte2 not equal smpte1" << endl;
1588 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1589 cout << "sample: " << sample1 << endl;
1590 cout << "sample: " << sample1 << " -> ";
1591 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1594 oldsample = sample1;
1595 session->smpte_increment( smpte1 );
1598 cout << "sample_increment: " << sample_increment << endl;
1599 cout << "sample: " << sample1 << " -> ";
1600 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1602 for (int i = 0; i < 108003; i++) {
1603 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, true /* use_subframes */ );
1604 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, true /* use_subframes */ );
1606 if ((i > 0) && ( ((oldsample - sample1) != sample_increment) && ((oldsample - sample1) != (sample_increment + 1)) && ((oldsample - sample1) != (sample_increment - 1)))) {
1607 cout << "ERROR: sample increment not right: " << (oldsample - sample1) << " != " << sample_increment << endl;
1608 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1609 cout << "sample: " << sample1 << endl;
1610 cout << "sample: " << sample1 << " -> ";
1611 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1615 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames || smpte2.subframes != smpte1.subframes) {
1616 cout << "ERROR: smpte2 not equal smpte1" << endl;
1617 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1618 cout << "sample: " << sample1 << endl;
1619 cout << "sample: " << sample1 << " -> ";
1620 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1623 oldsample = sample1;
1624 session->smpte_decrement( smpte1 );
1627 cout << "sample_decrement: " << sample_increment << endl;
1628 cout << "sample: " << sample1 << " -> ";
1629 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1634 #ifdef SMPTE_SAMPLE_TEST_5
1635 // Test 5: use_offset = true, use_subframes = false, increment seconds
1636 cout << "use_offset = true, use_subframes = false, increment seconds" << endl;
1642 smpte1.subframes = 0;
1643 sample1 = oldsample = 0;
1644 sample_increment = session->frame_rate();
1646 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1647 cout << "Starting at sample: " << sample1 << " -> ";
1648 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1650 for (int i = 0; i < 3600; i++) {
1651 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1652 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1654 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1655 // cout << "sample: " << sample1 << endl;
1656 // cout << "sample: " << sample1 << " -> ";
1657 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1659 // if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1661 // cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1665 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1666 cout << "ERROR: smpte2 not equal smpte1" << endl;
1667 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1668 cout << "sample: " << sample1 << endl;
1669 cout << "sample: " << sample1 << " -> ";
1670 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1673 oldsample = sample1;
1674 session->smpte_increment_seconds( smpte1 );
1677 cout << "sample_increment: " << sample_increment << endl;
1678 cout << "sample: " << sample1 << " -> ";
1679 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1683 #ifdef SMPTE_SAMPLE_TEST_6
1684 // Test 6: use_offset = true, use_subframes = false, increment minutes
1685 cout << "use_offset = true, use_subframes = false, increment minutes" << endl;
1691 smpte1.subframes = 0;
1692 sample1 = oldsample = 0;
1693 sample_increment = session->frame_rate() * 60;
1695 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1696 cout << "Starting at sample: " << sample1 << " -> ";
1697 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1699 for (int i = 0; i < 60; i++) {
1700 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1701 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1703 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1704 // cout << "sample: " << sample1 << endl;
1705 // cout << "sample: " << sample1 << " -> ";
1706 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1708 // if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1710 // cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1714 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1715 cout << "ERROR: smpte2 not equal smpte1" << endl;
1716 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1717 cout << "sample: " << sample1 << endl;
1718 cout << "sample: " << sample1 << " -> ";
1719 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1722 oldsample = sample1;
1723 session->smpte_increment_minutes( smpte1 );
1726 cout << "sample_increment: " << sample_increment << endl;
1727 cout << "sample: " << sample1 << " -> ";
1728 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1731 #ifdef SMPTE_SAMPLE_TEST_7
1732 // Test 7: use_offset = true, use_subframes = false, increment hours
1733 cout << "use_offset = true, use_subframes = false, increment hours" << endl;
1739 smpte1.subframes = 0;
1740 sample1 = oldsample = 0;
1741 sample_increment = session->frame_rate() * 60 * 60;
1743 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1744 cout << "Starting at sample: " << sample1 << " -> ";
1745 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1747 for (int i = 0; i < 10; i++) {
1748 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1749 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1751 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1752 // cout << "sample: " << sample1 << endl;
1753 // cout << "sample: " << sample1 << " -> ";
1754 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1756 // if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1758 // cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1762 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1763 cout << "ERROR: smpte2 not equal smpte1" << endl;
1764 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1765 cout << "sample: " << sample1 << endl;
1766 cout << "sample: " << sample1 << " -> ";
1767 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1770 oldsample = sample1;
1771 session->smpte_increment_hours( smpte1 );
1774 cout << "sample_increment: " << sample_increment << endl;
1775 cout << "sample: " << sample1 << " -> ";
1776 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1785 AudioClock::minsec_frame_from_display () const
1791 int hrs = atoi (ms_hours_label.get_text());
1792 int mins = atoi (ms_minutes_label.get_text());
1793 float secs = atof (ms_seconds_label.get_text());
1795 nframes_t sr = session->frame_rate();
1797 return (nframes_t) floor ((hrs * 60.0f * 60.0f * sr) + (mins * 60.0f * sr) + (secs * sr));
1801 AudioClock::bbt_frame_from_display (nframes_t pos) const
1804 error << "AudioClock::current_time() called with BBT mode but without session!" << endmsg;
1809 any.type = AnyTime::BBT;
1811 any.bbt.bars = atoi (bars_label.get_text());
1812 any.bbt.beats = atoi (beats_label.get_text());
1813 any.bbt.ticks = atoi (ticks_label.get_text());
1815 nframes_t ret = session->convert_to_frames_at (pos, any);
1822 AudioClock::bbt_frame_duration_from_display (nframes_t pos) const
1825 error << "AudioClock::current_time() called with BBT mode but without session!" << endmsg;
1832 bbt.bars = atoi (bars_label.get_text());
1833 bbt.beats = atoi (beats_label.get_text());
1834 bbt.ticks = atoi (ticks_label.get_text());
1836 return session->tempo_map().bbt_duration_at(pos,bbt,1);
1840 AudioClock::audio_frame_from_display () const
1842 return (nframes_t) atoi (audio_frames_label.get_text());
1846 AudioClock::build_ops_menu ()
1848 using namespace Menu_Helpers;
1849 ops_menu = new Menu;
1850 MenuList& ops_items = ops_menu->items();
1851 ops_menu->set_name ("ArdourContextMenu");
1853 ops_items.push_back (MenuElem (_("Timecode"), bind (mem_fun(*this, &AudioClock::set_mode), SMPTE)));
1854 ops_items.push_back (MenuElem (_("Bars:Beats"), bind (mem_fun(*this, &AudioClock::set_mode), BBT)));
1855 ops_items.push_back (MenuElem (_("Minutes:Seconds"), bind (mem_fun(*this, &AudioClock::set_mode), MinSec)));
1856 ops_items.push_back (MenuElem (_("Audio Frames"), bind (mem_fun(*this, &AudioClock::set_mode), Frames)));
1857 ops_items.push_back (MenuElem (_("Off"), bind (mem_fun(*this, &AudioClock::set_mode), Off)));
1861 AudioClock::set_mode (Mode m)
1863 /* slightly tricky: this is called from within the ARDOUR_UI
1864 constructor by some of its clock members. at that time
1865 the instance pointer is unset, so we have to be careful.
1866 the main idea is to drop keyboard focus in case we had
1867 started editing the clock and then we switch clock mode.
1870 clock_base.grab_focus ();
1880 clock_base.remove ();
1890 clock_base.add (smpte_packer_hbox);
1894 clock_base.add (bbt_packer_hbox);
1898 clock_base.add (minsec_packer_hbox);
1902 clock_base.add (frames_packer_hbox);
1909 set_size_requests ();
1911 set (last_when, true);
1912 clock_base.show_all ();
1913 key_entry_state = 0;
1915 if (!is_transient) {
1916 ModeChanged (); /* EMIT SIGNAL */
1921 AudioClock::set_size_requests ()
1923 /* note that in some fonts, "88" is narrower than "00", hence the 2 pixel padding */
1927 Gtkmm2ext::set_size_request_to_display_given_text (hours_label, "-00", 5, 5);
1928 Gtkmm2ext::set_size_request_to_display_given_text (minutes_label, "00", 5, 5);
1929 Gtkmm2ext::set_size_request_to_display_given_text (seconds_label, "00", 5, 5);
1930 Gtkmm2ext::set_size_request_to_display_given_text (frames_label, "00", 5, 5);
1934 Gtkmm2ext::set_size_request_to_display_given_text (bars_label, "-000", 5, 5);
1935 Gtkmm2ext::set_size_request_to_display_given_text (beats_label, "00", 5, 5);
1936 Gtkmm2ext::set_size_request_to_display_given_text (ticks_label, "0000", 5, 5);
1940 Gtkmm2ext::set_size_request_to_display_given_text (ms_hours_label, "00", 5, 5);
1941 Gtkmm2ext::set_size_request_to_display_given_text (ms_minutes_label, "00", 5, 5);
1942 Gtkmm2ext::set_size_request_to_display_given_text (ms_seconds_label, "00.000", 5, 5);
1946 Gtkmm2ext::set_size_request_to_display_given_text (audio_frames_label, "0000000000", 5, 5);