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 <gtkmm/style.h>
27 #include <gtkmm2ext/utils.h>
29 #include "ardour/ardour.h"
30 #include "ardour/session.h"
31 #include "ardour/tempo.h"
32 #include "ardour/profile.h"
33 #include <sigc++/bind.h>
35 #include "ardour_ui.h"
36 #include "audio_clock.h"
39 #include "gui_thread.h"
42 using namespace ARDOUR;
47 using Gtkmm2ext::Keyboard;
52 sigc::signal<void> AudioClock::ModeChanged;
53 vector<AudioClock*> AudioClock::clocks;
55 const uint32_t AudioClock::field_length[(int) AudioClock::AudioFrames+1] = {
56 2, /* Timecode_Hours */
57 2, /* Timecode_Minutes */
58 2, /* Timecode_Seconds */
59 2, /* Timecode_Frames */
69 AudioClock::AudioClock (const string& clock_name, bool transient, const string& widget_name,
70 bool allow_edit, bool follows_playhead, bool duration, bool with_info)
72 is_transient (transient),
73 is_duration (duration),
74 editable (allow_edit),
75 _follows_playhead (follows_playhead),
91 bbt_reference_time = -1;
94 frames_upper_info_label = manage (new Label);
95 frames_lower_info_label = manage (new Label);
96 timecode_upper_info_label = manage (new Label);
97 timecode_lower_info_label = manage (new Label);
98 bbt_upper_info_label = manage (new Label);
99 bbt_lower_info_label = manage (new Label);
101 frames_upper_info_label->set_name ("AudioClockFramesUpperInfo");
102 frames_lower_info_label->set_name ("AudioClockFramesLowerInfo");
103 timecode_upper_info_label->set_name ("AudioClockTimecodeUpperInfo");
104 timecode_lower_info_label->set_name ("AudioClockTimecodeLowerInfo");
105 bbt_upper_info_label->set_name ("AudioClockBBTUpperInfo");
106 bbt_lower_info_label->set_name ("AudioClockBBTLowerInfo");
108 Gtkmm2ext::set_size_request_to_display_given_text(*timecode_upper_info_label, "23.98",0,0);
109 Gtkmm2ext::set_size_request_to_display_given_text(*timecode_lower_info_label, "NDF",0,0);
111 Gtkmm2ext::set_size_request_to_display_given_text(*bbt_upper_info_label, "88|88",0,0);
112 Gtkmm2ext::set_size_request_to_display_given_text(*bbt_lower_info_label, "888.88",0,0);
114 frames_info_box.pack_start (*frames_upper_info_label, true, true);
115 frames_info_box.pack_start (*frames_lower_info_label, true, true);
116 timecode_info_box.pack_start (*timecode_upper_info_label, true, true);
117 timecode_info_box.pack_start (*timecode_lower_info_label, true, true);
118 bbt_info_box.pack_start (*bbt_upper_info_label, true, true);
119 bbt_info_box.pack_start (*bbt_lower_info_label, true, true);
122 frames_upper_info_label = 0;
123 frames_lower_info_label = 0;
124 timecode_upper_info_label = 0;
125 timecode_lower_info_label = 0;
126 bbt_upper_info_label = 0;
127 bbt_lower_info_label = 0;
130 audio_frames_ebox.add (audio_frames_label);
132 frames_packer.set_homogeneous (false);
133 frames_packer.set_border_width (2);
134 frames_packer.pack_start (audio_frames_ebox, false, false);
137 frames_packer.pack_start (frames_info_box, false, false, 5);
140 frames_packer_hbox.pack_start (frames_packer, true, false);
142 hours_ebox.add (hours_label);
143 minutes_ebox.add (minutes_label);
144 seconds_ebox.add (seconds_label);
145 frames_ebox.add (frames_label);
146 bars_ebox.add (bars_label);
147 beats_ebox.add (beats_label);
148 ticks_ebox.add (ticks_label);
149 ms_hours_ebox.add (ms_hours_label);
150 ms_minutes_ebox.add (ms_minutes_label);
151 ms_seconds_ebox.add (ms_seconds_label);
153 timecode_packer.set_homogeneous (false);
154 timecode_packer.set_border_width (2);
155 timecode_packer.pack_start (hours_ebox, false, false);
156 timecode_packer.pack_start (colon1, false, false);
157 timecode_packer.pack_start (minutes_ebox, false, false);
158 timecode_packer.pack_start (colon2, false, false);
159 timecode_packer.pack_start (seconds_ebox, false, false);
160 timecode_packer.pack_start (colon3, false, false);
161 timecode_packer.pack_start (frames_ebox, false, false);
164 timecode_packer.pack_start (timecode_info_box, false, false, 5);
167 timecode_packer_hbox.pack_start (timecode_packer, true, false);
169 bbt_packer.set_homogeneous (false);
170 bbt_packer.set_border_width (2);
171 bbt_packer.pack_start (bars_ebox, false, false);
172 bbt_packer.pack_start (b1, false, false);
173 bbt_packer.pack_start (beats_ebox, false, false);
174 bbt_packer.pack_start (b2, false, false);
175 bbt_packer.pack_start (ticks_ebox, false, false);
178 bbt_packer.pack_start (bbt_info_box, false, false, 5);
181 bbt_packer_hbox.pack_start (bbt_packer, true, false);
183 minsec_packer.set_homogeneous (false);
184 minsec_packer.set_border_width (2);
185 minsec_packer.pack_start (ms_hours_ebox, false, false);
186 minsec_packer.pack_start (colon4, false, false);
187 minsec_packer.pack_start (ms_minutes_ebox, false, false);
188 minsec_packer.pack_start (colon5, false, false);
189 minsec_packer.pack_start (ms_seconds_ebox, false, false);
191 minsec_packer_hbox.pack_start (minsec_packer, true, false);
193 clock_frame.set_shadow_type (Gtk::SHADOW_IN);
194 clock_frame.set_name ("BaseFrame");
196 clock_frame.add (clock_base);
198 set_widget_name (widget_name);
200 _mode = BBT; /* lie to force mode switch */
203 pack_start (clock_frame, true, true);
205 /* the clock base handles button releases for menu popup regardless of
206 editable status. if the clock is editable, the clock base is where
207 we pass focus to after leaving the last editable "field", which
208 will then shutdown editing till the user starts it up again.
210 it does this because the focus out event on the field disables
211 keyboard event handling, and we don't connect anything up to
212 notice focus in on the clock base. hence, keyboard event handling
216 clock_base.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::SCROLL_MASK);
217 clock_base.signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &AudioClock::field_button_release_event), Timecode_Hours));
219 Session::TimecodeOffsetChanged.connect (_session_connections, invalidator (*this), boost::bind (&AudioClock::timecode_offset_changed, this), gui_context());
225 set (last_when, true);
228 clocks.push_back (this);
233 AudioClock::set_widget_name (string name)
235 Widget::set_name (name);
237 clock_base.set_name (name);
239 audio_frames_label.set_name (name);
240 hours_label.set_name (name);
241 minutes_label.set_name (name);
242 seconds_label.set_name (name);
243 frames_label.set_name (name);
244 bars_label.set_name (name);
245 beats_label.set_name (name);
246 ticks_label.set_name (name);
247 ms_hours_label.set_name (name);
248 ms_minutes_label.set_name (name);
249 ms_seconds_label.set_name (name);
250 hours_ebox.set_name (name);
251 minutes_ebox.set_name (name);
252 seconds_ebox.set_name (name);
253 frames_ebox.set_name (name);
254 audio_frames_ebox.set_name (name);
255 bars_ebox.set_name (name);
256 beats_ebox.set_name (name);
257 ticks_ebox.set_name (name);
258 ms_hours_ebox.set_name (name);
259 ms_minutes_ebox.set_name (name);
260 ms_seconds_ebox.set_name (name);
262 colon1.set_name (name);
263 colon2.set_name (name);
264 colon3.set_name (name);
265 colon4.set_name (name);
266 colon5.set_name (name);
274 AudioClock::setup_events ()
276 clock_base.set_flags (Gtk::CAN_FOCUS);
278 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);
279 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);
280 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);
281 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);
282 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);
283 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);
284 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);
285 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);
286 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);
287 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);
288 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);
290 hours_ebox.set_flags (Gtk::CAN_FOCUS);
291 minutes_ebox.set_flags (Gtk::CAN_FOCUS);
292 seconds_ebox.set_flags (Gtk::CAN_FOCUS);
293 frames_ebox.set_flags (Gtk::CAN_FOCUS);
294 audio_frames_ebox.set_flags (Gtk::CAN_FOCUS);
295 bars_ebox.set_flags (Gtk::CAN_FOCUS);
296 beats_ebox.set_flags (Gtk::CAN_FOCUS);
297 ticks_ebox.set_flags (Gtk::CAN_FOCUS);
298 ms_hours_ebox.set_flags (Gtk::CAN_FOCUS);
299 ms_minutes_ebox.set_flags (Gtk::CAN_FOCUS);
300 ms_seconds_ebox.set_flags (Gtk::CAN_FOCUS);
302 hours_ebox.signal_motion_notify_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_motion_notify_event), Timecode_Hours));
303 minutes_ebox.signal_motion_notify_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_motion_notify_event), Timecode_Minutes));
304 seconds_ebox.signal_motion_notify_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_motion_notify_event), Timecode_Seconds));
305 frames_ebox.signal_motion_notify_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_motion_notify_event), Timecode_Frames));
306 audio_frames_ebox.signal_motion_notify_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_motion_notify_event), AudioFrames));
307 bars_ebox.signal_motion_notify_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_motion_notify_event), Bars));
308 beats_ebox.signal_motion_notify_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_motion_notify_event), Beats));
309 ticks_ebox.signal_motion_notify_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_motion_notify_event), Ticks));
310 ms_hours_ebox.signal_motion_notify_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_motion_notify_event), MS_Hours));
311 ms_minutes_ebox.signal_motion_notify_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_motion_notify_event), MS_Minutes));
312 ms_seconds_ebox.signal_motion_notify_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_motion_notify_event), MS_Seconds));
314 hours_ebox.signal_button_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_press_event), Timecode_Hours));
315 minutes_ebox.signal_button_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_press_event), Timecode_Minutes));
316 seconds_ebox.signal_button_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_press_event), Timecode_Seconds));
317 frames_ebox.signal_button_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_press_event), Timecode_Frames));
318 audio_frames_ebox.signal_button_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_press_event), AudioFrames));
319 bars_ebox.signal_button_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_press_event), Bars));
320 beats_ebox.signal_button_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_press_event), Beats));
321 ticks_ebox.signal_button_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_press_event), Ticks));
322 ms_hours_ebox.signal_button_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_press_event), MS_Hours));
323 ms_minutes_ebox.signal_button_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_press_event), MS_Minutes));
324 ms_seconds_ebox.signal_button_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_press_event), MS_Seconds));
326 hours_ebox.signal_button_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_release_event), Timecode_Hours));
327 minutes_ebox.signal_button_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_release_event), Timecode_Minutes));
328 seconds_ebox.signal_button_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_release_event), Timecode_Seconds));
329 frames_ebox.signal_button_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_release_event), Timecode_Frames));
330 audio_frames_ebox.signal_button_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_release_event), AudioFrames));
331 bars_ebox.signal_button_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_release_event), Bars));
332 beats_ebox.signal_button_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_release_event), Beats));
333 ticks_ebox.signal_button_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_release_event), Ticks));
334 ms_hours_ebox.signal_button_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_release_event), MS_Hours));
335 ms_minutes_ebox.signal_button_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_release_event), MS_Minutes));
336 ms_seconds_ebox.signal_button_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_release_event), MS_Seconds));
338 hours_ebox.signal_scroll_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_scroll_event), Timecode_Hours));
339 minutes_ebox.signal_scroll_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_scroll_event), Timecode_Minutes));
340 seconds_ebox.signal_scroll_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_scroll_event), Timecode_Seconds));
341 frames_ebox.signal_scroll_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_scroll_event), Timecode_Frames));
342 audio_frames_ebox.signal_scroll_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_scroll_event), AudioFrames));
343 bars_ebox.signal_scroll_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_scroll_event), Bars));
344 beats_ebox.signal_scroll_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_scroll_event), Beats));
345 ticks_ebox.signal_scroll_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_scroll_event), Ticks));
346 ms_hours_ebox.signal_scroll_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_scroll_event), MS_Hours));
347 ms_minutes_ebox.signal_scroll_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_scroll_event), MS_Minutes));
348 ms_seconds_ebox.signal_scroll_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_scroll_event), MS_Seconds));
350 hours_ebox.signal_key_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_press_event), Timecode_Hours));
351 minutes_ebox.signal_key_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_press_event), Timecode_Minutes));
352 seconds_ebox.signal_key_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_press_event), Timecode_Seconds));
353 frames_ebox.signal_key_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_press_event), Timecode_Frames));
354 audio_frames_ebox.signal_key_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_press_event), AudioFrames));
355 bars_ebox.signal_key_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_press_event), Bars));
356 beats_ebox.signal_key_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_press_event), Beats));
357 ticks_ebox.signal_key_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_press_event), Ticks));
358 ms_hours_ebox.signal_key_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_press_event), MS_Hours));
359 ms_minutes_ebox.signal_key_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_press_event), MS_Minutes));
360 ms_seconds_ebox.signal_key_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_press_event), MS_Seconds));
362 hours_ebox.signal_key_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_release_event), Timecode_Hours));
363 minutes_ebox.signal_key_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_release_event), Timecode_Minutes));
364 seconds_ebox.signal_key_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_release_event), Timecode_Seconds));
365 frames_ebox.signal_key_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_release_event), Timecode_Frames));
366 audio_frames_ebox.signal_key_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_release_event), AudioFrames));
367 bars_ebox.signal_key_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_release_event), Bars));
368 beats_ebox.signal_key_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_release_event), Beats));
369 ticks_ebox.signal_key_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_release_event), Ticks));
370 ms_hours_ebox.signal_key_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_release_event), MS_Hours));
371 ms_minutes_ebox.signal_key_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_release_event), MS_Minutes));
372 ms_seconds_ebox.signal_key_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_release_event), MS_Seconds));
374 hours_ebox.signal_focus_in_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_in_event), Timecode_Hours));
375 minutes_ebox.signal_focus_in_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_in_event), Timecode_Minutes));
376 seconds_ebox.signal_focus_in_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_in_event), Timecode_Seconds));
377 frames_ebox.signal_focus_in_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_in_event), Timecode_Frames));
378 audio_frames_ebox.signal_focus_in_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_in_event), AudioFrames));
379 bars_ebox.signal_focus_in_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_in_event), Bars));
380 beats_ebox.signal_focus_in_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_in_event), Beats));
381 ticks_ebox.signal_focus_in_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_in_event), Ticks));
382 ms_hours_ebox.signal_focus_in_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_in_event), MS_Hours));
383 ms_minutes_ebox.signal_focus_in_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_in_event), MS_Minutes));
384 ms_seconds_ebox.signal_focus_in_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_in_event), MS_Seconds));
386 hours_ebox.signal_focus_out_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_out_event), Timecode_Hours));
387 minutes_ebox.signal_focus_out_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_out_event), Timecode_Minutes));
388 seconds_ebox.signal_focus_out_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_out_event), Timecode_Seconds));
389 frames_ebox.signal_focus_out_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_out_event), Timecode_Frames));
390 audio_frames_ebox.signal_focus_out_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_out_event), AudioFrames));
391 bars_ebox.signal_focus_out_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_out_event), Bars));
392 beats_ebox.signal_focus_out_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_out_event), Beats));
393 ticks_ebox.signal_focus_out_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_out_event), Ticks));
394 ms_hours_ebox.signal_focus_out_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_out_event), MS_Hours));
395 ms_minutes_ebox.signal_focus_out_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_out_event), MS_Minutes));
396 ms_seconds_ebox.signal_focus_out_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_out_event), MS_Seconds));
398 clock_base.signal_focus_in_event().connect (sigc::mem_fun (*this, &AudioClock::drop_focus_handler));
402 AudioClock::drop_focus_handler (GdkEventFocus*)
404 Keyboard::magic_widget_drop_focus ();
409 AudioClock::on_realize ()
413 /* styles are not available until the widgets are bound to a window */
415 set_size_requests ();
419 AudioClock::set (nframes_t when, bool force, nframes_t offset, char which)
422 if ((!force && !is_visible()) || _session == 0) {
426 if (when == last_when && !offset && !force) {
430 bool pdelta = Config->get_primary_clock_delta_edit_cursor();
431 bool sdelta = Config->get_secondary_clock_delta_edit_cursor();
433 if (offset && which == 'p' && pdelta) {
434 when = (when > offset) ? when - offset : offset - when;
435 } else if (offset && which == 's' && sdelta) {
436 when = (when > offset) ? when - offset : offset - when;
439 if (which == 'p' && pdelta && !last_pdelta) {
440 set_widget_name("TransportClockDisplayDelta");
442 } else if (which == 'p' && !pdelta && last_pdelta) {
443 set_widget_name("TransportClockDisplay");
445 } else if (which == 's' && sdelta && !last_sdelta) {
446 set_widget_name("SecondaryClockDisplayDelta");
448 } else if (which == 's' && !sdelta && last_sdelta) {
449 set_widget_name("SecondaryClockDisplay");
455 set_timecode (when, force);
459 set_bbt (when, force);
463 set_minsec (when, force);
467 set_frames (when, force);
478 AudioClock::timecode_offset_changed ()
485 current = current_duration();
487 current = current_time ();
497 AudioClock::set_frames (nframes_t when, bool /*force*/)
500 snprintf (buf, sizeof (buf), "%u", when);
501 audio_frames_label.set_text (buf);
503 if (frames_upper_info_label) {
504 nframes_t rate = _session->frame_rate();
506 if (fmod (rate, 1000.0) == 0.000) {
507 sprintf (buf, "%uK", rate/1000);
509 sprintf (buf, "%.3fK", rate/1000.0f);
512 if (frames_upper_info_label->get_text() != buf) {
513 frames_upper_info_label->set_text (buf);
516 float vid_pullup = _session->config.get_video_pullup();
518 if (vid_pullup == 0.0) {
519 if (frames_lower_info_label->get_text () != _("none")) {
520 frames_lower_info_label->set_text(_("none"));
523 sprintf (buf, "%-6.4f", vid_pullup);
524 if (frames_lower_info_label->get_text() != buf) {
525 frames_lower_info_label->set_text (buf);
532 AudioClock::set_minsec (nframes_t when, bool force)
541 hrs = (int) floor (left / (_session->frame_rate() * 60.0f * 60.0f));
542 left -= (nframes_t) floor (hrs * _session->frame_rate() * 60.0f * 60.0f);
543 mins = (int) floor (left / (_session->frame_rate() * 60.0f));
544 left -= (nframes_t) floor (mins * _session->frame_rate() * 60.0f);
545 secs = left / (float) _session->frame_rate();
547 if (force || hrs != ms_last_hrs) {
548 sprintf (buf, "%02d", hrs);
549 ms_hours_label.set_text (buf);
553 if (force || mins != ms_last_mins) {
554 sprintf (buf, "%02d", mins);
555 ms_minutes_label.set_text (buf);
559 if (force || secs != ms_last_secs) {
560 sprintf (buf, "%06.3f", secs);
561 ms_seconds_label.set_text (buf);
567 AudioClock::set_timecode (nframes_t when, bool force)
570 Timecode::Time timecode;
573 _session->timecode_duration (when, timecode);
575 _session->timecode_time (when, timecode);
578 if (force || timecode.hours != last_hrs || timecode.negative != last_negative) {
579 if (timecode.negative) {
580 sprintf (buf, "-%02" PRIu32, timecode.hours);
582 sprintf (buf, " %02" PRIu32, timecode.hours);
584 hours_label.set_text (buf);
585 last_hrs = timecode.hours;
586 last_negative = timecode.negative;
589 if (force || timecode.minutes != last_mins) {
590 sprintf (buf, "%02" PRIu32, timecode.minutes);
591 minutes_label.set_text (buf);
592 last_mins = timecode.minutes;
595 if (force || timecode.seconds != last_secs) {
596 sprintf (buf, "%02" PRIu32, timecode.seconds);
597 seconds_label.set_text (buf);
598 last_secs = timecode.seconds;
601 if (force || timecode.frames != last_frames) {
602 sprintf (buf, "%02" PRIu32, timecode.frames);
603 frames_label.set_text (buf);
604 last_frames = timecode.frames;
607 if (timecode_upper_info_label) {
608 double timecode_frames = _session->timecode_frames_per_second();
610 if ( fmod(timecode_frames, 1.0) == 0.0) {
611 sprintf (buf, "%u", int (timecode_frames));
613 sprintf (buf, "%.2f", timecode_frames);
616 if (timecode_upper_info_label->get_text() != buf) {
617 timecode_upper_info_label->set_text (buf);
620 if ((fabs(timecode_frames - 29.97) < 0.0001) || timecode_frames == 30) {
621 if (_session->timecode_drop_frames()) {
624 sprintf (buf, "NDF");
627 // there is no drop frame alternative
631 if (timecode_lower_info_label->get_text() != buf) {
632 timecode_lower_info_label->set_text (buf);
638 AudioClock::set_bbt (nframes_t when, bool force)
643 /* handle a common case */
650 _session->tempo_map().bbt_time (when, bbt);
655 _session->tempo_map().bbt_time (when, bbt);
658 sprintf (buf, "%03" PRIu32, bbt.bars);
659 if (force || bars_label.get_text () != buf) {
660 bars_label.set_text (buf);
662 sprintf (buf, "%02" PRIu32, bbt.beats);
663 if (force || beats_label.get_text () != buf) {
664 beats_label.set_text (buf);
666 sprintf (buf, "%04" PRIu32, bbt.ticks);
667 if (force || ticks_label.get_text () != buf) {
668 ticks_label.set_text (buf);
671 if (bbt_upper_info_label) {
674 if (bbt_reference_time < 0) {
677 pos = bbt_reference_time;
680 TempoMetric m (_session->tempo_map().metric_at (pos));
682 sprintf (buf, "%-5.2f", m.tempo().beats_per_minute());
683 if (bbt_lower_info_label->get_text() != buf) {
684 bbt_lower_info_label->set_text (buf);
686 sprintf (buf, "%g|%g", m.meter().beats_per_bar(), m.meter().note_divisor());
687 if (bbt_upper_info_label->get_text() != buf) {
688 bbt_upper_info_label->set_text (buf);
694 AudioClock::set_session (Session *s)
696 SessionHandlePtr::set_session (s);
701 XMLNode* node = _session->extra_xml (X_("ClockModes"));
702 AudioClock::Mode amode;
705 if ((prop = node->property (_name)) != 0) {
706 amode = AudioClock::Mode (string_2_enum (prop->value(), amode));
711 set (last_when, true);
720 hours_ebox.grab_focus ();
724 bars_ebox.grab_focus ();
728 ms_hours_ebox.grab_focus ();
732 frames_ebox.grab_focus ();
742 AudioClock::field_key_press_event (GdkEventKey */*ev*/, Field /*field*/)
744 /* all key activity is handled on key release */
749 AudioClock::field_key_release_event (GdkEventKey *ev, Field field)
754 bool move_on = false;
758 label = &hours_label;
760 case Timecode_Minutes:
761 label = &minutes_label;
763 case Timecode_Seconds:
764 label = &seconds_label;
766 case Timecode_Frames:
767 label = &frames_label;
771 label = &audio_frames_label;
775 label = &ms_hours_label;
778 label = &ms_minutes_label;
781 label = &ms_seconds_label;
788 label = &beats_label;
791 label = &ticks_label;
797 switch (ev->keyval) {
841 if (_mode == MinSec && field == MS_Seconds) {
856 clock_base.grab_focus ();
857 ChangeAborted(); /* EMIT SIGNAL */
866 if (key_entry_state == 0) {
868 /* initialize with a fresh new string */
870 if (field != AudioFrames) {
871 for (uint32_t xn = 0; xn < field_length[field] - 1; ++xn) {
880 string existing = label->get_text();
881 if (existing.length() >= field_length[field]) {
882 new_text = existing.substr (1, field_length[field] - 1);
884 new_text = existing.substr (0, field_length[field] - 1);
888 new_text += new_char;
889 label->set_text (new_text);
893 if (key_entry_state == field_length[field]) {
899 if (key_entry_state) {
903 case Timecode_Minutes:
904 case Timecode_Seconds:
905 case Timecode_Frames:
906 // Check Timecode fields for sanity (may also adjust fields)
907 timecode_sanitize_display();
912 // Bars should never be, unless this clock is for a duration
913 if (atoi(bars_label.get_text()) == 0 && !is_duration) {
914 bars_label.set_text("001");
916 // beats should never be 0, unless this clock is for a duration
917 if (atoi(beats_label.get_text()) == 0 && !is_duration) {
918 beats_label.set_text("01");
925 ValueChanged(); /* EMIT_SIGNAL */
928 /* move on to the next field.
936 minutes_ebox.grab_focus ();
938 case Timecode_Minutes:
939 seconds_ebox.grab_focus ();
941 case Timecode_Seconds:
942 frames_ebox.grab_focus ();
944 case Timecode_Frames:
945 clock_base.grab_focus ();
950 clock_base.grab_focus ();
956 ms_minutes_ebox.grab_focus ();
959 ms_seconds_ebox.grab_focus ();
962 clock_base.grab_focus ();
968 beats_ebox.grab_focus ();
971 ticks_ebox.grab_focus ();
974 clock_base.grab_focus ();
983 //if user hit Enter, lose focus
984 switch (ev->keyval) {
987 clock_base.grab_focus ();
994 AudioClock::field_focus_in_event (GdkEventFocus */*ev*/, Field field)
998 Keyboard::magic_widget_grab_focus ();
1001 case Timecode_Hours:
1002 hours_ebox.set_flags (Gtk::HAS_FOCUS);
1003 hours_ebox.set_state (Gtk::STATE_ACTIVE);
1005 case Timecode_Minutes:
1006 minutes_ebox.set_flags (Gtk::HAS_FOCUS);
1007 minutes_ebox.set_state (Gtk::STATE_ACTIVE);
1009 case Timecode_Seconds:
1010 seconds_ebox.set_flags (Gtk::HAS_FOCUS);
1011 seconds_ebox.set_state (Gtk::STATE_ACTIVE);
1013 case Timecode_Frames:
1014 frames_ebox.set_flags (Gtk::HAS_FOCUS);
1015 frames_ebox.set_state (Gtk::STATE_ACTIVE);
1019 audio_frames_ebox.set_flags (Gtk::HAS_FOCUS);
1020 audio_frames_ebox.set_state (Gtk::STATE_ACTIVE);
1024 ms_hours_ebox.set_flags (Gtk::HAS_FOCUS);
1025 ms_hours_ebox.set_state (Gtk::STATE_ACTIVE);
1028 ms_minutes_ebox.set_flags (Gtk::HAS_FOCUS);
1029 ms_minutes_ebox.set_state (Gtk::STATE_ACTIVE);
1032 ms_seconds_ebox.set_flags (Gtk::HAS_FOCUS);
1033 ms_seconds_ebox.set_state (Gtk::STATE_ACTIVE);
1036 bars_ebox.set_flags (Gtk::HAS_FOCUS);
1037 bars_ebox.set_state (Gtk::STATE_ACTIVE);
1040 beats_ebox.set_flags (Gtk::HAS_FOCUS);
1041 beats_ebox.set_state (Gtk::STATE_ACTIVE);
1044 ticks_ebox.set_flags (Gtk::HAS_FOCUS);
1045 ticks_ebox.set_state (Gtk::STATE_ACTIVE);
1053 AudioClock::field_focus_out_event (GdkEventFocus */*ev*/, Field field)
1057 case Timecode_Hours:
1058 hours_ebox.unset_flags (Gtk::HAS_FOCUS);
1059 hours_ebox.set_state (Gtk::STATE_NORMAL);
1061 case Timecode_Minutes:
1062 minutes_ebox.unset_flags (Gtk::HAS_FOCUS);
1063 minutes_ebox.set_state (Gtk::STATE_NORMAL);
1065 case Timecode_Seconds:
1066 seconds_ebox.unset_flags (Gtk::HAS_FOCUS);
1067 seconds_ebox.set_state (Gtk::STATE_NORMAL);
1069 case Timecode_Frames:
1070 frames_ebox.unset_flags (Gtk::HAS_FOCUS);
1071 frames_ebox.set_state (Gtk::STATE_NORMAL);
1075 audio_frames_ebox.unset_flags (Gtk::HAS_FOCUS);
1076 audio_frames_ebox.set_state (Gtk::STATE_NORMAL);
1080 ms_hours_ebox.unset_flags (Gtk::HAS_FOCUS);
1081 ms_hours_ebox.set_state (Gtk::STATE_NORMAL);
1084 ms_minutes_ebox.unset_flags (Gtk::HAS_FOCUS);
1085 ms_minutes_ebox.set_state (Gtk::STATE_NORMAL);
1088 ms_seconds_ebox.unset_flags (Gtk::HAS_FOCUS);
1089 ms_seconds_ebox.set_state (Gtk::STATE_NORMAL);
1093 bars_ebox.unset_flags (Gtk::HAS_FOCUS);
1094 bars_ebox.set_state (Gtk::STATE_NORMAL);
1097 beats_ebox.unset_flags (Gtk::HAS_FOCUS);
1098 beats_ebox.set_state (Gtk::STATE_NORMAL);
1101 ticks_ebox.unset_flags (Gtk::HAS_FOCUS);
1102 ticks_ebox.set_state (Gtk::STATE_NORMAL);
1106 Keyboard::magic_widget_drop_focus ();
1112 AudioClock::field_button_release_event (GdkEventButton *ev, Field field)
1115 cerr << "button event on clock but we are dragging\n";
1116 gdk_pointer_ungrab (GDK_CURRENT_TIME);
1118 if (ev->y > drag_start_y+1 || ev->y < drag_start_y-1 || Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)){
1119 // we actually dragged so return without setting editing focus, or we shift clicked
1125 if (ops_menu == 0) {
1128 ops_menu->popup (1, ev->time);
1132 if (Keyboard::is_context_menu_event (ev)) {
1133 cerr << "Context menu event on clock\n";
1134 if (ops_menu == 0) {
1137 ops_menu->popup (1, ev->time);
1141 switch (ev->button) {
1144 case Timecode_Hours:
1145 hours_ebox.grab_focus();
1147 case Timecode_Minutes:
1148 minutes_ebox.grab_focus();
1150 case Timecode_Seconds:
1151 seconds_ebox.grab_focus();
1153 case Timecode_Frames:
1154 frames_ebox.grab_focus();
1158 audio_frames_ebox.grab_focus();
1162 ms_hours_ebox.grab_focus();
1165 ms_minutes_ebox.grab_focus();
1168 ms_seconds_ebox.grab_focus();
1172 bars_ebox.grab_focus ();
1175 beats_ebox.grab_focus ();
1178 ticks_ebox.grab_focus ();
1191 AudioClock::field_button_press_event (GdkEventButton *ev, Field /*field*/)
1193 if (_session == 0) {
1197 nframes_t frames = 0;
1199 switch (ev->button) {
1201 if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
1203 ValueChanged (); /* EMIT_SIGNAL */
1206 /* make absolutely sure that the pointer is grabbed */
1207 gdk_pointer_grab(ev->window,false ,
1208 GdkEventMask( Gdk::POINTER_MOTION_MASK | Gdk::BUTTON_PRESS_MASK |Gdk::BUTTON_RELEASE_MASK),
1209 NULL,NULL,ev->time);
1212 drag_start_y = ev->y;
1217 if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
1219 ValueChanged (); /* EMIT_SIGNAL */
1224 /* used for context sensitive menu */
1237 AudioClock::field_button_scroll_event (GdkEventScroll *ev, Field field)
1239 if (_session == 0) {
1243 nframes_t frames = 0;
1245 switch (ev->direction) {
1248 frames = get_frames (field);
1250 if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
1253 set (current_time() + frames, true);
1254 ValueChanged (); /* EMIT_SIGNAL */
1258 case GDK_SCROLL_DOWN:
1259 frames = get_frames (field);
1261 if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
1265 if ((double)current_time() - (double)frames < 0.0) {
1268 set (current_time() - frames, true);
1271 ValueChanged (); /* EMIT_SIGNAL */
1284 AudioClock::field_motion_notify_event (GdkEventMotion *ev, Field field)
1286 if (_session == 0 || !dragging) {
1290 float pixel_frame_scale_factor = 0.2f;
1293 if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
1294 pixel_frame_scale_factor = 0.1f;
1298 if (Keyboard::modifier_state_contains (ev->state,
1299 Keyboard::PrimaryModifier|Keyboard::SecondaryModifier)) {
1301 pixel_frame_scale_factor = 0.025f;
1304 double y_delta = ev->y - drag_y;
1306 drag_accum += y_delta*pixel_frame_scale_factor;
1310 if (trunc(drag_accum) != 0) {
1315 dir = (drag_accum < 0 ? 1:-1);
1316 pos = current_time();
1317 frames = get_frames (field,pos,dir);
1319 if (frames != 0 && frames * drag_accum < current_time()) {
1321 set ((nframes_t) floor (pos - drag_accum * frames), false); // minus because up is negative in computer-land
1329 ValueChanged(); /* EMIT_SIGNAL */
1338 AudioClock::get_frames (Field field,nframes_t pos,int dir)
1341 nframes_t frames = 0;
1344 case Timecode_Hours:
1345 frames = (nframes_t) floor (3600.0 * _session->frame_rate());
1347 case Timecode_Minutes:
1348 frames = (nframes_t) floor (60.0 * _session->frame_rate());
1350 case Timecode_Seconds:
1351 frames = _session->frame_rate();
1353 case Timecode_Frames:
1354 frames = (nframes_t) floor (_session->frame_rate() / _session->timecode_frames_per_second());
1362 frames = (nframes_t) floor (3600.0 * _session->frame_rate());
1365 frames = (nframes_t) floor (60.0 * _session->frame_rate());
1368 frames = _session->frame_rate();
1375 frames = _session->tempo_map().bbt_duration_at(pos,bbt,dir);
1381 frames = _session->tempo_map().bbt_duration_at(pos,bbt,dir);
1387 frames = _session->tempo_map().bbt_duration_at(pos,bbt,dir);
1395 AudioClock::current_time (nframes_t pos) const
1401 ret = timecode_frame_from_display ();
1404 ret = bbt_frame_from_display (pos);
1408 ret = minsec_frame_from_display ();
1412 ret = audio_frame_from_display ();
1423 AudioClock::current_duration (nframes_t pos) const
1429 ret = timecode_frame_from_display ();
1432 ret = bbt_frame_duration_from_display (pos);
1436 ret = minsec_frame_from_display ();
1440 ret = audio_frame_from_display ();
1451 AudioClock::timecode_sanitize_display()
1453 // Check Timecode fields for sanity, possibly adjusting values
1454 if (atoi(minutes_label.get_text()) > 59) {
1455 minutes_label.set_text("59");
1458 if (atoi(seconds_label.get_text()) > 59) {
1459 seconds_label.set_text("59");
1462 switch ((long)rint(_session->timecode_frames_per_second())) {
1464 if (atoi(frames_label.get_text()) > 23) {
1465 frames_label.set_text("23");
1469 if (atoi(frames_label.get_text()) > 24) {
1470 frames_label.set_text("24");
1474 if (atoi(frames_label.get_text()) > 29) {
1475 frames_label.set_text("29");
1482 if (_session->timecode_drop_frames()) {
1483 if ((atoi(minutes_label.get_text()) % 10) && (atoi(seconds_label.get_text()) == 0) && (atoi(frames_label.get_text()) < 2)) {
1484 frames_label.set_text("02");
1490 AudioClock::timecode_frame_from_display () const
1492 if (_session == 0) {
1496 Timecode::Time timecode;
1499 timecode.hours = atoi (hours_label.get_text());
1500 timecode.minutes = atoi (minutes_label.get_text());
1501 timecode.seconds = atoi (seconds_label.get_text());
1502 timecode.frames = atoi (frames_label.get_text());
1503 timecode.rate = _session->timecode_frames_per_second();
1504 timecode.drop= _session->timecode_drop_frames();
1506 _session->timecode_to_sample( timecode, sample, false /* use_offset */, false /* use_subframes */ );
1510 #define Timecode_SAMPLE_TEST_1
1511 #define Timecode_SAMPLE_TEST_2
1512 #define Timecode_SAMPLE_TEST_3
1513 #define Timecode_SAMPLE_TEST_4
1514 #define Timecode_SAMPLE_TEST_5
1515 #define Timecode_SAMPLE_TEST_6
1516 #define Timecode_SAMPLE_TEST_7
1518 // Testcode for timecode<->sample conversions (P.S.)
1519 Timecode::Time timecode1;
1521 framepos_t oldsample = 0;
1522 Timecode::Time timecode2;
1523 framecnt_t sample_increment;
1525 sample_increment = (framecnt_t)rint(_session->frame_rate() / _session->timecode_frames_per_second);
1527 #ifdef Timecode_SAMPLE_TEST_1
1528 // Test 1: use_offset = false, use_subframes = false
1529 cout << "use_offset = false, use_subframes = false" << endl;
1530 for (int i = 0; i < 108003; i++) {
1531 _session->timecode_to_sample( timecode1, sample1, false /* use_offset */, false /* use_subframes */ );
1532 _session->sample_to_timecode( sample1, timecode2, false /* use_offset */, false /* use_subframes */ );
1534 if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
1535 cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1536 cout << "timecode1: " << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << " -> ";
1537 cout << "sample: " << sample1 << endl;
1538 cout << "sample: " << sample1 << " -> ";
1539 cout << "timecode2: " << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
1543 if (timecode2.hours != timecode1.hours || timecode2.minutes != timecode1.minutes || timecode2.seconds != timecode2.seconds || timecode2.frames != timecode1.frames) {
1544 cout << "ERROR: timecode2 not equal timecode1" << endl;
1545 cout << "timecode1: " << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << " -> ";
1546 cout << "sample: " << sample1 << endl;
1547 cout << "sample: " << sample1 << " -> ";
1548 cout << "timecode2: " << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
1551 oldsample = sample1;
1552 _session->timecode_increment( timecode1 );
1555 cout << "sample_increment: " << sample_increment << endl;
1556 cout << "sample: " << sample1 << " -> ";
1557 cout << "timecode: " << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
1560 #ifdef Timecode_SAMPLE_TEST_2
1561 // Test 2: use_offset = true, use_subframes = false
1562 cout << "use_offset = true, use_subframes = false" << endl;
1564 timecode1.hours = 0;
1565 timecode1.minutes = 0;
1566 timecode1.seconds = 0;
1567 timecode1.frames = 0;
1568 timecode1.subframes = 0;
1569 sample1 = oldsample = 0;
1571 _session->sample_to_timecode( sample1, timecode1, true /* use_offset */, false /* use_subframes */ );
1572 cout << "Starting at sample: " << sample1 << " -> ";
1573 cout << "timecode: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << endl;
1575 for (int i = 0; i < 108003; i++) {
1576 _session->timecode_to_sample( timecode1, sample1, true /* use_offset */, false /* use_subframes */ );
1577 _session->sample_to_timecode( sample1, timecode2, true /* use_offset */, false /* use_subframes */ );
1579 // cout << "timecode: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << " -> ";
1580 // cout << "sample: " << sample1 << endl;
1581 // cout << "sample: " << sample1 << " -> ";
1582 // cout << "timecode: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
1584 if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
1585 cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1586 cout << "timecode1: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << " -> ";
1587 cout << "sample: " << sample1 << endl;
1588 cout << "sample: " << sample1 << " -> ";
1589 cout << "timecode2: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
1593 if (timecode2.hours != timecode1.hours || timecode2.minutes != timecode1.minutes || timecode2.seconds != timecode2.seconds || timecode2.frames != timecode1.frames) {
1594 cout << "ERROR: timecode2 not equal timecode1" << endl;
1595 cout << "timecode1: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << " -> ";
1596 cout << "sample: " << sample1 << endl;
1597 cout << "sample: " << sample1 << " -> ";
1598 cout << "timecode2: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
1601 oldsample = sample1;
1602 _session->timecode_increment( timecode1 );
1605 cout << "sample_increment: " << sample_increment << endl;
1606 cout << "sample: " << sample1 << " -> ";
1607 cout << "timecode: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
1610 #ifdef Timecode_SAMPLE_TEST_3
1611 // Test 3: use_offset = true, use_subframes = false, decrement
1612 cout << "use_offset = true, use_subframes = false, decrement" << endl;
1614 _session->sample_to_timecode( sample1, timecode1, true /* use_offset */, false /* use_subframes */ );
1615 cout << "Starting at sample: " << sample1 << " -> ";
1616 cout << "timecode: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << endl;
1618 for (int i = 0; i < 108003; i++) {
1619 _session->timecode_to_sample( timecode1, sample1, true /* use_offset */, false /* use_subframes */ );
1620 _session->sample_to_timecode( sample1, timecode2, true /* use_offset */, false /* use_subframes */ );
1622 // cout << "timecode: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << " -> ";
1623 // cout << "sample: " << sample1 << endl;
1624 // cout << "sample: " << sample1 << " -> ";
1625 // cout << "timecode: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
1627 if ((i > 0) && ( ((oldsample - sample1) != sample_increment) && ((oldsample - sample1) != (sample_increment + 1)) && ((oldsample - sample1) != (sample_increment - 1)))) {
1628 cout << "ERROR: sample increment not right: " << (oldsample - sample1) << " != " << sample_increment << endl;
1629 cout << "timecode1: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << " -> ";
1630 cout << "sample: " << sample1 << endl;
1631 cout << "sample: " << sample1 << " -> ";
1632 cout << "timecode2: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
1636 if (timecode2.hours != timecode1.hours || timecode2.minutes != timecode1.minutes || timecode2.seconds != timecode2.seconds || timecode2.frames != timecode1.frames) {
1637 cout << "ERROR: timecode2 not equal timecode1" << endl;
1638 cout << "timecode1: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << " -> ";
1639 cout << "sample: " << sample1 << endl;
1640 cout << "sample: " << sample1 << " -> ";
1641 cout << "timecode2: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
1644 oldsample = sample1;
1645 _session->timecode_decrement( timecode1 );
1648 cout << "sample_decrement: " << sample_increment << endl;
1649 cout << "sample: " << sample1 << " -> ";
1650 cout << "timecode: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
1654 #ifdef Timecode_SAMPLE_TEST_4
1655 // Test 4: use_offset = true, use_subframes = true
1656 cout << "use_offset = true, use_subframes = true" << endl;
1658 for (long sub = 5; sub < 80; sub += 5) {
1659 timecode1.hours = 0;
1660 timecode1.minutes = 0;
1661 timecode1.seconds = 0;
1662 timecode1.frames = 0;
1663 timecode1.subframes = 0;
1664 sample1 = oldsample = (sample_increment * sub) / 80;
1666 _session->sample_to_timecode( sample1, timecode1, true /* use_offset */, true /* use_subframes */ );
1668 cout << "starting at sample: " << sample1 << " -> ";
1669 cout << "timecode: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << endl;
1671 for (int i = 0; i < 108003; i++) {
1672 _session->timecode_to_sample( timecode1, sample1, true /* use_offset */, true /* use_subframes */ );
1673 _session->sample_to_timecode( sample1, timecode2, true /* use_offset */, true /* use_subframes */ );
1675 if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
1676 cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1677 cout << "timecode1: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << " -> ";
1678 cout << "sample: " << sample1 << endl;
1679 cout << "sample: " << sample1 << " -> ";
1680 cout << "timecode2: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
1684 if (timecode2.hours != timecode1.hours || timecode2.minutes != timecode1.minutes || timecode2.seconds != timecode2.seconds || timecode2.frames != timecode1.frames || timecode2.subframes != timecode1.subframes) {
1685 cout << "ERROR: timecode2 not equal timecode1" << endl;
1686 cout << "timecode1: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << " -> ";
1687 cout << "sample: " << sample1 << endl;
1688 cout << "sample: " << sample1 << " -> ";
1689 cout << "timecode2: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
1692 oldsample = sample1;
1693 _session->timecode_increment( timecode1 );
1696 cout << "sample_increment: " << sample_increment << endl;
1697 cout << "sample: " << sample1 << " -> ";
1698 cout << "timecode: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
1700 for (int i = 0; i < 108003; i++) {
1701 _session->timecode_to_sample( timecode1, sample1, true /* use_offset */, true /* use_subframes */ );
1702 _session->sample_to_timecode( sample1, timecode2, true /* use_offset */, true /* use_subframes */ );
1704 if ((i > 0) && ( ((oldsample - sample1) != sample_increment) && ((oldsample - sample1) != (sample_increment + 1)) && ((oldsample - sample1) != (sample_increment - 1)))) {
1705 cout << "ERROR: sample increment not right: " << (oldsample - sample1) << " != " << sample_increment << endl;
1706 cout << "timecode1: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << " -> ";
1707 cout << "sample: " << sample1 << endl;
1708 cout << "sample: " << sample1 << " -> ";
1709 cout << "timecode2: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
1713 if (timecode2.hours != timecode1.hours || timecode2.minutes != timecode1.minutes || timecode2.seconds != timecode2.seconds || timecode2.frames != timecode1.frames || timecode2.subframes != timecode1.subframes) {
1714 cout << "ERROR: timecode2 not equal timecode1" << endl;
1715 cout << "timecode1: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << " -> ";
1716 cout << "sample: " << sample1 << endl;
1717 cout << "sample: " << sample1 << " -> ";
1718 cout << "timecode2: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
1721 oldsample = sample1;
1722 _session->timecode_decrement( timecode1 );
1725 cout << "sample_decrement: " << sample_increment << endl;
1726 cout << "sample: " << sample1 << " -> ";
1727 cout << "timecode: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
1732 #ifdef Timecode_SAMPLE_TEST_5
1733 // Test 5: use_offset = true, use_subframes = false, increment seconds
1734 cout << "use_offset = true, use_subframes = false, increment seconds" << endl;
1736 timecode1.hours = 0;
1737 timecode1.minutes = 0;
1738 timecode1.seconds = 0;
1739 timecode1.frames = 0;
1740 timecode1.subframes = 0;
1741 sample1 = oldsample = 0;
1742 sample_increment = _session->frame_rate();
1744 _session->sample_to_timecode( sample1, timecode1, true /* use_offset */, false /* use_subframes */ );
1745 cout << "Starting at sample: " << sample1 << " -> ";
1746 cout << "timecode: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << endl;
1748 for (int i = 0; i < 3600; i++) {
1749 _session->timecode_to_sample( timecode1, sample1, true /* use_offset */, false /* use_subframes */ );
1750 _session->sample_to_timecode( sample1, timecode2, true /* use_offset */, false /* use_subframes */ );
1752 // cout << "timecode: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << " -> ";
1753 // cout << "sample: " << sample1 << endl;
1754 // cout << "sample: " << sample1 << " -> ";
1755 // cout << "timecode: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
1757 // if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1759 // cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1763 if (timecode2.hours != timecode1.hours || timecode2.minutes != timecode1.minutes || timecode2.seconds != timecode2.seconds || timecode2.frames != timecode1.frames) {
1764 cout << "ERROR: timecode2 not equal timecode1" << endl;
1765 cout << "timecode: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << " -> ";
1766 cout << "sample: " << sample1 << endl;
1767 cout << "sample: " << sample1 << " -> ";
1768 cout << "timecode: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
1771 oldsample = sample1;
1772 _session->timecode_increment_seconds( timecode1 );
1775 cout << "sample_increment: " << sample_increment << endl;
1776 cout << "sample: " << sample1 << " -> ";
1777 cout << "timecode: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
1781 #ifdef Timecode_SAMPLE_TEST_6
1782 // Test 6: use_offset = true, use_subframes = false, increment minutes
1783 cout << "use_offset = true, use_subframes = false, increment minutes" << endl;
1785 timecode1.hours = 0;
1786 timecode1.minutes = 0;
1787 timecode1.seconds = 0;
1788 timecode1.frames = 0;
1789 timecode1.subframes = 0;
1790 sample1 = oldsample = 0;
1791 sample_increment = _session->frame_rate() * 60;
1793 _session->sample_to_timecode( sample1, timecode1, true /* use_offset */, false /* use_subframes */ );
1794 cout << "Starting at sample: " << sample1 << " -> ";
1795 cout << "timecode: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << endl;
1797 for (int i = 0; i < 60; i++) {
1798 _session->timecode_to_sample( timecode1, sample1, true /* use_offset */, false /* use_subframes */ );
1799 _session->sample_to_timecode( sample1, timecode2, true /* use_offset */, false /* use_subframes */ );
1801 // cout << "timecode: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << " -> ";
1802 // cout << "sample: " << sample1 << endl;
1803 // cout << "sample: " << sample1 << " -> ";
1804 // cout << "timecode: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
1806 // if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1808 // cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1812 if (timecode2.hours != timecode1.hours || timecode2.minutes != timecode1.minutes || timecode2.seconds != timecode2.seconds || timecode2.frames != timecode1.frames) {
1813 cout << "ERROR: timecode2 not equal timecode1" << endl;
1814 cout << "timecode: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << " -> ";
1815 cout << "sample: " << sample1 << endl;
1816 cout << "sample: " << sample1 << " -> ";
1817 cout << "timecode: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
1820 oldsample = sample1;
1821 _session->timecode_increment_minutes( timecode1 );
1824 cout << "sample_increment: " << sample_increment << endl;
1825 cout << "sample: " << sample1 << " -> ";
1826 cout << "timecode: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
1829 #ifdef Timecode_SAMPLE_TEST_7
1830 // Test 7: use_offset = true, use_subframes = false, increment hours
1831 cout << "use_offset = true, use_subframes = false, increment hours" << endl;
1833 timecode1.hours = 0;
1834 timecode1.minutes = 0;
1835 timecode1.seconds = 0;
1836 timecode1.frames = 0;
1837 timecode1.subframes = 0;
1838 sample1 = oldsample = 0;
1839 sample_increment = _session->frame_rate() * 60 * 60;
1841 _session->sample_to_timecode( sample1, timecode1, true /* use_offset */, false /* use_subframes */ );
1842 cout << "Starting at sample: " << sample1 << " -> ";
1843 cout << "timecode: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << endl;
1845 for (int i = 0; i < 10; i++) {
1846 _session->timecode_to_sample( timecode1, sample1, true /* use_offset */, false /* use_subframes */ );
1847 _session->sample_to_timecode( sample1, timecode2, true /* use_offset */, false /* use_subframes */ );
1849 // cout << "timecode: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << " -> ";
1850 // cout << "sample: " << sample1 << endl;
1851 // cout << "sample: " << sample1 << " -> ";
1852 // cout << "timecode: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
1854 // if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1856 // cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1860 if (timecode2.hours != timecode1.hours || timecode2.minutes != timecode1.minutes || timecode2.seconds != timecode2.seconds || timecode2.frames != timecode1.frames) {
1861 cout << "ERROR: timecode2 not equal timecode1" << endl;
1862 cout << "timecode: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << " -> ";
1863 cout << "sample: " << sample1 << endl;
1864 cout << "sample: " << sample1 << " -> ";
1865 cout << "timecode: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
1868 oldsample = sample1;
1869 _session->timecode_increment_hours( timecode1 );
1872 cout << "sample_increment: " << sample_increment << endl;
1873 cout << "sample: " << sample1 << " -> ";
1874 cout << "timecode: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
1883 AudioClock::minsec_frame_from_display () const
1885 if (_session == 0) {
1889 int hrs = atoi (ms_hours_label.get_text());
1890 int mins = atoi (ms_minutes_label.get_text());
1891 float secs = atof (ms_seconds_label.get_text());
1893 nframes_t sr = _session->frame_rate();
1895 return (nframes_t) floor ((hrs * 60.0f * 60.0f * sr) + (mins * 60.0f * sr) + (secs * sr));
1899 AudioClock::bbt_frame_from_display (nframes_t pos) const
1901 if (_session == 0) {
1902 error << "AudioClock::current_time() called with BBT mode but without session!" << endmsg;
1907 any.type = AnyTime::BBT;
1909 any.bbt.bars = atoi (bars_label.get_text());
1910 any.bbt.beats = atoi (beats_label.get_text());
1911 any.bbt.ticks = atoi (ticks_label.get_text());
1918 nframes_t ret = _session->convert_to_frames_at (pos, any);
1925 AudioClock::bbt_frame_duration_from_display (nframes_t pos) const
1927 if (_session == 0) {
1928 error << "AudioClock::current_time() called with BBT mode but without session!" << endmsg;
1935 bbt.bars = atoi (bars_label.get_text());
1936 bbt.beats = atoi (beats_label.get_text());
1937 bbt.ticks = atoi (ticks_label.get_text());
1939 return _session->tempo_map().bbt_duration_at(pos,bbt,1);
1943 AudioClock::audio_frame_from_display () const
1945 return (nframes_t) atoi (audio_frames_label.get_text());
1949 AudioClock::build_ops_menu ()
1951 using namespace Menu_Helpers;
1952 ops_menu = new Menu;
1953 MenuList& ops_items = ops_menu->items();
1954 ops_menu->set_name ("ArdourContextMenu");
1956 if (!Profile->get_sae()) {
1957 ops_items.push_back (MenuElem (_("Timecode"), sigc::bind (sigc::mem_fun(*this, &AudioClock::set_mode), Timecode)));
1959 ops_items.push_back (MenuElem (_("Bars:Beats"), sigc::bind (sigc::mem_fun(*this, &AudioClock::set_mode), BBT)));
1960 ops_items.push_back (MenuElem (_("Minutes:Seconds"), sigc::bind (sigc::mem_fun(*this, &AudioClock::set_mode), MinSec)));
1961 ops_items.push_back (MenuElem (_("Samples"), sigc::bind (sigc::mem_fun(*this, &AudioClock::set_mode), Frames)));
1962 ops_items.push_back (MenuElem (_("Off"), sigc::bind (sigc::mem_fun(*this, &AudioClock::set_mode), Off)));
1964 if (editable && !is_duration && !_follows_playhead) {
1965 ops_items.push_back (SeparatorElem());
1966 ops_items.push_back (MenuElem (_("Set From Playhead"), sigc::mem_fun(*this, &AudioClock::set_from_playhead)));
1967 ops_items.push_back (MenuElem (_("Locate to This Time"), sigc::mem_fun(*this, &AudioClock::locate)));
1972 AudioClock::set_from_playhead ()
1978 set (_session->transport_frame());
1982 AudioClock::locate ()
1984 if (!_session || is_duration) {
1988 _session->request_locate (current_time(), _session->transport_rolling ());
1992 AudioClock::set_mode (Mode m)
1994 /* slightly tricky: this is called from within the ARDOUR_UI
1995 constructor by some of its clock members. at that time
1996 the instance pointer is unset, so we have to be careful.
1997 the main idea is to drop keyboard focus in case we had
1998 started editing the clock and then we switch clock mode.
2001 clock_base.grab_focus ();
2007 clock_base.remove ();
2013 clock_base.add (timecode_packer_hbox);
2017 clock_base.add (bbt_packer_hbox);
2021 clock_base.add (minsec_packer_hbox);
2025 clock_base.add (frames_packer_hbox);
2029 clock_base.add (off_hbox);
2033 set_size_requests ();
2035 set (last_when, true);
2036 clock_base.show_all ();
2037 key_entry_state = 0;
2039 if (!is_transient) {
2040 ModeChanged (); /* EMIT SIGNAL */
2041 mode_changed (); /* EMIT SIGNAL */
2046 AudioClock::set_size_requests ()
2048 /* note that in some fonts, "88" is narrower than "00" */
2052 Gtkmm2ext::set_size_request_to_display_given_text (hours_label, "-88", 5, 5);
2053 Gtkmm2ext::set_size_request_to_display_given_text (minutes_label, "88", 5, 5);
2054 Gtkmm2ext::set_size_request_to_display_given_text (seconds_label, "88", 5, 5);
2055 Gtkmm2ext::set_size_request_to_display_given_text (frames_label, "88", 5, 5);
2059 Gtkmm2ext::set_size_request_to_display_given_text (bars_label, "-888", 5, 5);
2060 Gtkmm2ext::set_size_request_to_display_given_text (beats_label, "88", 5, 5);
2061 Gtkmm2ext::set_size_request_to_display_given_text (ticks_label, "8888", 5, 5);
2065 Gtkmm2ext::set_size_request_to_display_given_text (ms_hours_label, "88", 5, 5);
2066 Gtkmm2ext::set_size_request_to_display_given_text (ms_minutes_label, "88", 5, 5);
2067 Gtkmm2ext::set_size_request_to_display_given_text (ms_seconds_label, "88.888", 5, 5);
2071 Gtkmm2ext::set_size_request_to_display_given_text (audio_frames_label, "8888888888", 5, 5);
2075 Gtkmm2ext::set_size_request_to_display_given_text (off_hbox, "00000", 5, 5);
2082 AudioClock::set_bbt_reference (framepos_t pos)
2084 bbt_reference_time = pos;
2088 AudioClock::on_style_changed (const Glib::RefPtr<Gtk::Style>& old_style)
2090 HBox::on_style_changed (old_style);
2092 /* propagate style changes to all component widgets that should inherit the main one */
2094 Glib::RefPtr<RcStyle> rcstyle = get_modifier_style();
2096 clock_base.modify_style (rcstyle);
2097 audio_frames_label.modify_style (rcstyle);
2098 hours_label.modify_style (rcstyle);
2099 minutes_label.modify_style (rcstyle);
2100 seconds_label.modify_style (rcstyle);
2101 frames_label.modify_style (rcstyle);
2102 bars_label.modify_style (rcstyle);
2103 beats_label.modify_style (rcstyle);
2104 ticks_label.modify_style (rcstyle);
2105 ms_hours_label.modify_style (rcstyle);
2106 ms_minutes_label.modify_style (rcstyle);
2107 ms_seconds_label.modify_style (rcstyle);
2108 hours_ebox.modify_style (rcstyle);
2109 minutes_ebox.modify_style (rcstyle);
2110 seconds_ebox.modify_style (rcstyle);
2111 frames_ebox.modify_style (rcstyle);
2112 audio_frames_ebox.modify_style (rcstyle);
2113 bars_ebox.modify_style (rcstyle);
2114 beats_ebox.modify_style (rcstyle);
2115 ticks_ebox.modify_style (rcstyle);
2116 ms_hours_ebox.modify_style (rcstyle);
2117 ms_minutes_ebox.modify_style (rcstyle);
2118 ms_seconds_ebox.modify_style (rcstyle);
2120 colon1.modify_style (rcstyle);
2121 colon2.modify_style (rcstyle);
2122 colon3.modify_style (rcstyle);
2123 colon4.modify_style (rcstyle);
2124 colon5.modify_style (rcstyle);
2125 b1.modify_style (rcstyle);
2126 b2.modify_style (rcstyle);
2128 set_size_requests ();
2132 AudioClock::set_is_duration (bool yn)
2134 if (yn == is_duration) {
2139 set (last_when, true, 0, 's');