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));
223 set (last_when, true);
226 clocks.push_back (this);
231 AudioClock::set_widget_name (string name)
233 Widget::set_name (name);
235 clock_base.set_name (name);
237 audio_frames_label.set_name (name);
238 hours_label.set_name (name);
239 minutes_label.set_name (name);
240 seconds_label.set_name (name);
241 frames_label.set_name (name);
242 bars_label.set_name (name);
243 beats_label.set_name (name);
244 ticks_label.set_name (name);
245 ms_hours_label.set_name (name);
246 ms_minutes_label.set_name (name);
247 ms_seconds_label.set_name (name);
248 hours_ebox.set_name (name);
249 minutes_ebox.set_name (name);
250 seconds_ebox.set_name (name);
251 frames_ebox.set_name (name);
252 audio_frames_ebox.set_name (name);
253 bars_ebox.set_name (name);
254 beats_ebox.set_name (name);
255 ticks_ebox.set_name (name);
256 ms_hours_ebox.set_name (name);
257 ms_minutes_ebox.set_name (name);
258 ms_seconds_ebox.set_name (name);
260 colon1.set_name (name);
261 colon2.set_name (name);
262 colon3.set_name (name);
263 colon4.set_name (name);
264 colon5.set_name (name);
272 AudioClock::setup_events ()
274 clock_base.set_flags (Gtk::CAN_FOCUS);
276 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);
277 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);
278 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);
279 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 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);
281 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);
282 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);
283 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);
284 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);
285 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);
286 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);
288 hours_ebox.set_flags (Gtk::CAN_FOCUS);
289 minutes_ebox.set_flags (Gtk::CAN_FOCUS);
290 seconds_ebox.set_flags (Gtk::CAN_FOCUS);
291 frames_ebox.set_flags (Gtk::CAN_FOCUS);
292 audio_frames_ebox.set_flags (Gtk::CAN_FOCUS);
293 bars_ebox.set_flags (Gtk::CAN_FOCUS);
294 beats_ebox.set_flags (Gtk::CAN_FOCUS);
295 ticks_ebox.set_flags (Gtk::CAN_FOCUS);
296 ms_hours_ebox.set_flags (Gtk::CAN_FOCUS);
297 ms_minutes_ebox.set_flags (Gtk::CAN_FOCUS);
298 ms_seconds_ebox.set_flags (Gtk::CAN_FOCUS);
300 hours_ebox.signal_motion_notify_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_motion_notify_event), Timecode_Hours));
301 minutes_ebox.signal_motion_notify_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_motion_notify_event), Timecode_Minutes));
302 seconds_ebox.signal_motion_notify_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_motion_notify_event), Timecode_Seconds));
303 frames_ebox.signal_motion_notify_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_motion_notify_event), Timecode_Frames));
304 audio_frames_ebox.signal_motion_notify_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_motion_notify_event), AudioFrames));
305 bars_ebox.signal_motion_notify_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_motion_notify_event), Bars));
306 beats_ebox.signal_motion_notify_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_motion_notify_event), Beats));
307 ticks_ebox.signal_motion_notify_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_motion_notify_event), Ticks));
308 ms_hours_ebox.signal_motion_notify_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_motion_notify_event), MS_Hours));
309 ms_minutes_ebox.signal_motion_notify_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_motion_notify_event), MS_Minutes));
310 ms_seconds_ebox.signal_motion_notify_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_motion_notify_event), MS_Seconds));
312 hours_ebox.signal_button_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_press_event), Timecode_Hours));
313 minutes_ebox.signal_button_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_press_event), Timecode_Minutes));
314 seconds_ebox.signal_button_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_press_event), Timecode_Seconds));
315 frames_ebox.signal_button_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_press_event), Timecode_Frames));
316 audio_frames_ebox.signal_button_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_press_event), AudioFrames));
317 bars_ebox.signal_button_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_press_event), Bars));
318 beats_ebox.signal_button_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_press_event), Beats));
319 ticks_ebox.signal_button_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_press_event), Ticks));
320 ms_hours_ebox.signal_button_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_press_event), MS_Hours));
321 ms_minutes_ebox.signal_button_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_press_event), MS_Minutes));
322 ms_seconds_ebox.signal_button_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_press_event), MS_Seconds));
324 hours_ebox.signal_button_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_release_event), Timecode_Hours));
325 minutes_ebox.signal_button_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_release_event), Timecode_Minutes));
326 seconds_ebox.signal_button_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_release_event), Timecode_Seconds));
327 frames_ebox.signal_button_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_release_event), Timecode_Frames));
328 audio_frames_ebox.signal_button_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_release_event), AudioFrames));
329 bars_ebox.signal_button_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_release_event), Bars));
330 beats_ebox.signal_button_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_release_event), Beats));
331 ticks_ebox.signal_button_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_release_event), Ticks));
332 ms_hours_ebox.signal_button_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_release_event), MS_Hours));
333 ms_minutes_ebox.signal_button_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_release_event), MS_Minutes));
334 ms_seconds_ebox.signal_button_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_release_event), MS_Seconds));
336 hours_ebox.signal_scroll_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_scroll_event), Timecode_Hours));
337 minutes_ebox.signal_scroll_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_scroll_event), Timecode_Minutes));
338 seconds_ebox.signal_scroll_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_scroll_event), Timecode_Seconds));
339 frames_ebox.signal_scroll_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_scroll_event), Timecode_Frames));
340 audio_frames_ebox.signal_scroll_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_scroll_event), AudioFrames));
341 bars_ebox.signal_scroll_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_scroll_event), Bars));
342 beats_ebox.signal_scroll_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_scroll_event), Beats));
343 ticks_ebox.signal_scroll_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_scroll_event), Ticks));
344 ms_hours_ebox.signal_scroll_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_scroll_event), MS_Hours));
345 ms_minutes_ebox.signal_scroll_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_scroll_event), MS_Minutes));
346 ms_seconds_ebox.signal_scroll_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_scroll_event), MS_Seconds));
348 hours_ebox.signal_key_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_press_event), Timecode_Hours));
349 minutes_ebox.signal_key_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_press_event), Timecode_Minutes));
350 seconds_ebox.signal_key_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_press_event), Timecode_Seconds));
351 frames_ebox.signal_key_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_press_event), Timecode_Frames));
352 audio_frames_ebox.signal_key_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_press_event), AudioFrames));
353 bars_ebox.signal_key_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_press_event), Bars));
354 beats_ebox.signal_key_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_press_event), Beats));
355 ticks_ebox.signal_key_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_press_event), Ticks));
356 ms_hours_ebox.signal_key_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_press_event), MS_Hours));
357 ms_minutes_ebox.signal_key_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_press_event), MS_Minutes));
358 ms_seconds_ebox.signal_key_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_press_event), MS_Seconds));
360 hours_ebox.signal_key_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_release_event), Timecode_Hours));
361 minutes_ebox.signal_key_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_release_event), Timecode_Minutes));
362 seconds_ebox.signal_key_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_release_event), Timecode_Seconds));
363 frames_ebox.signal_key_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_release_event), Timecode_Frames));
364 audio_frames_ebox.signal_key_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_release_event), AudioFrames));
365 bars_ebox.signal_key_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_release_event), Bars));
366 beats_ebox.signal_key_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_release_event), Beats));
367 ticks_ebox.signal_key_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_release_event), Ticks));
368 ms_hours_ebox.signal_key_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_release_event), MS_Hours));
369 ms_minutes_ebox.signal_key_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_release_event), MS_Minutes));
370 ms_seconds_ebox.signal_key_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_release_event), MS_Seconds));
372 hours_ebox.signal_focus_in_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_in_event), Timecode_Hours));
373 minutes_ebox.signal_focus_in_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_in_event), Timecode_Minutes));
374 seconds_ebox.signal_focus_in_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_in_event), Timecode_Seconds));
375 frames_ebox.signal_focus_in_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_in_event), Timecode_Frames));
376 audio_frames_ebox.signal_focus_in_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_in_event), AudioFrames));
377 bars_ebox.signal_focus_in_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_in_event), Bars));
378 beats_ebox.signal_focus_in_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_in_event), Beats));
379 ticks_ebox.signal_focus_in_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_in_event), Ticks));
380 ms_hours_ebox.signal_focus_in_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_in_event), MS_Hours));
381 ms_minutes_ebox.signal_focus_in_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_in_event), MS_Minutes));
382 ms_seconds_ebox.signal_focus_in_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_in_event), MS_Seconds));
384 hours_ebox.signal_focus_out_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_out_event), Timecode_Hours));
385 minutes_ebox.signal_focus_out_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_out_event), Timecode_Minutes));
386 seconds_ebox.signal_focus_out_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_out_event), Timecode_Seconds));
387 frames_ebox.signal_focus_out_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_out_event), Timecode_Frames));
388 audio_frames_ebox.signal_focus_out_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_out_event), AudioFrames));
389 bars_ebox.signal_focus_out_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_out_event), Bars));
390 beats_ebox.signal_focus_out_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_out_event), Beats));
391 ticks_ebox.signal_focus_out_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_out_event), Ticks));
392 ms_hours_ebox.signal_focus_out_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_out_event), MS_Hours));
393 ms_minutes_ebox.signal_focus_out_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_out_event), MS_Minutes));
394 ms_seconds_ebox.signal_focus_out_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_out_event), MS_Seconds));
396 clock_base.signal_focus_in_event().connect (sigc::mem_fun (*this, &AudioClock::drop_focus_handler));
400 AudioClock::drop_focus_handler (GdkEventFocus*)
402 Keyboard::magic_widget_drop_focus ();
407 AudioClock::on_realize ()
411 /* styles are not available until the widgets are bound to a window */
413 set_size_requests ();
417 AudioClock::set (framepos_t when, bool force, framecnt_t offset, char which)
420 if ((!force && !is_visible()) || _session == 0) {
424 if (when == last_when && !offset && !force) {
428 bool pdelta = Config->get_primary_clock_delta_edit_cursor();
429 bool sdelta = Config->get_secondary_clock_delta_edit_cursor();
431 if (offset && which == 'p' && pdelta) {
432 when = (when > offset) ? when - offset : offset - when;
433 } else if (offset && which == 's' && sdelta) {
434 when = (when > offset) ? when - offset : offset - when;
437 if (which == 'p' && pdelta && !last_pdelta) {
438 set_widget_name("TransportClockDisplayDelta");
440 } else if (which == 'p' && !pdelta && last_pdelta) {
441 set_widget_name("TransportClockDisplay");
443 } else if (which == 's' && sdelta && !last_sdelta) {
444 set_widget_name("SecondaryClockDisplayDelta");
446 } else if (which == 's' && !sdelta && last_sdelta) {
447 set_widget_name("SecondaryClockDisplay");
453 set_timecode (when, force);
457 set_bbt (when, force);
461 set_minsec (when, force);
465 set_frames (when, force);
476 AudioClock::session_configuration_changed (std::string p)
478 if (p != "timecode-offset" && p != "timecode-offset-negative") {
487 current = current_duration ();
489 current = current_time ();
499 AudioClock::set_frames (framepos_t when, bool /*force*/)
502 snprintf (buf, sizeof (buf), "%" PRId64, when);
503 audio_frames_label.set_text (buf);
505 if (frames_upper_info_label) {
506 framecnt_t rate = _session->frame_rate();
508 if (fmod (rate, 1000.0) == 0.000) {
509 sprintf (buf, "%" PRId64 "K", rate/1000);
511 sprintf (buf, "%.3fK", rate/1000.0f);
514 if (frames_upper_info_label->get_text() != buf) {
515 frames_upper_info_label->set_text (buf);
518 float vid_pullup = _session->config.get_video_pullup();
520 if (vid_pullup == 0.0) {
521 if (frames_lower_info_label->get_text () != _("none")) {
522 frames_lower_info_label->set_text(_("none"));
525 sprintf (buf, "%-6.4f", vid_pullup);
526 if (frames_lower_info_label->get_text() != buf) {
527 frames_lower_info_label->set_text (buf);
534 AudioClock::set_minsec (framepos_t when, bool force)
543 hrs = (int) floor (left / (_session->frame_rate() * 60.0f * 60.0f));
544 left -= (framecnt_t) floor (hrs * _session->frame_rate() * 60.0f * 60.0f);
545 mins = (int) floor (left / (_session->frame_rate() * 60.0f));
546 left -= (framecnt_t) floor (mins * _session->frame_rate() * 60.0f);
547 secs = left / (float) _session->frame_rate();
549 if (force || hrs != ms_last_hrs) {
550 sprintf (buf, "%02d", hrs);
551 ms_hours_label.set_text (buf);
555 if (force || mins != ms_last_mins) {
556 sprintf (buf, "%02d", mins);
557 ms_minutes_label.set_text (buf);
561 if (force || secs != ms_last_secs) {
562 sprintf (buf, "%06.3f", secs);
563 ms_seconds_label.set_text (buf);
569 AudioClock::set_timecode (framepos_t when, bool force)
572 Timecode::Time timecode;
575 _session->timecode_duration (when, timecode);
577 _session->timecode_time (when, timecode);
580 if (force || timecode.hours != last_hrs || timecode.negative != last_negative) {
581 if (timecode.negative) {
582 sprintf (buf, "-%02" PRIu32, timecode.hours);
584 sprintf (buf, " %02" PRIu32, timecode.hours);
586 hours_label.set_text (buf);
587 last_hrs = timecode.hours;
588 last_negative = timecode.negative;
591 if (force || timecode.minutes != last_mins) {
592 sprintf (buf, "%02" PRIu32, timecode.minutes);
593 minutes_label.set_text (buf);
594 last_mins = timecode.minutes;
597 if (force || timecode.seconds != last_secs) {
598 sprintf (buf, "%02" PRIu32, timecode.seconds);
599 seconds_label.set_text (buf);
600 last_secs = timecode.seconds;
603 if (force || timecode.frames != last_frames) {
604 sprintf (buf, "%02" PRIu32, timecode.frames);
605 frames_label.set_text (buf);
606 last_frames = timecode.frames;
609 if (timecode_upper_info_label) {
610 double timecode_frames = _session->timecode_frames_per_second();
612 if ( fmod(timecode_frames, 1.0) == 0.0) {
613 sprintf (buf, "%u", int (timecode_frames));
615 sprintf (buf, "%.2f", timecode_frames);
618 if (timecode_upper_info_label->get_text() != buf) {
619 timecode_upper_info_label->set_text (buf);
622 if ((fabs(timecode_frames - 29.97) < 0.0001) || timecode_frames == 30) {
623 if (_session->timecode_drop_frames()) {
626 sprintf (buf, "NDF");
629 // there is no drop frame alternative
633 if (timecode_lower_info_label->get_text() != buf) {
634 timecode_lower_info_label->set_text (buf);
640 AudioClock::set_bbt (framepos_t when, bool force)
643 Timecode::BBT_Time bbt;
645 /* handle a common case */
652 _session->tempo_map().bbt_time (when, bbt);
657 _session->tempo_map().bbt_time (when, bbt);
660 sprintf (buf, "%03" PRIu32, bbt.bars);
661 if (force || bars_label.get_text () != buf) {
662 bars_label.set_text (buf);
664 sprintf (buf, "%02" PRIu32, bbt.beats);
665 if (force || beats_label.get_text () != buf) {
666 beats_label.set_text (buf);
668 sprintf (buf, "%04" PRIu32, bbt.ticks);
669 if (force || ticks_label.get_text () != buf) {
670 ticks_label.set_text (buf);
673 if (bbt_upper_info_label) {
676 if (bbt_reference_time < 0) {
679 pos = bbt_reference_time;
682 TempoMetric m (_session->tempo_map().metric_at (pos));
684 sprintf (buf, "%-5.2f", m.tempo().beats_per_minute());
685 if (bbt_lower_info_label->get_text() != buf) {
686 bbt_lower_info_label->set_text (buf);
688 sprintf (buf, "%g|%g", m.meter().beats_per_bar(), m.meter().note_divisor());
689 if (bbt_upper_info_label->get_text() != buf) {
690 bbt_upper_info_label->set_text (buf);
696 AudioClock::set_session (Session *s)
698 SessionHandlePtr::set_session (s);
702 _session->config.ParameterChanged.connect (_session_connections, invalidator (*this), boost::bind (&AudioClock::session_configuration_changed, this, _1), gui_context());
705 XMLNode* node = _session->extra_xml (X_("ClockModes"));
706 AudioClock::Mode amode;
709 if ((prop = node->property (_name)) != 0) {
710 amode = AudioClock::Mode (string_2_enum (prop->value(), amode));
715 set (last_when, true);
724 hours_ebox.grab_focus ();
728 bars_ebox.grab_focus ();
732 ms_hours_ebox.grab_focus ();
736 frames_ebox.grab_focus ();
746 AudioClock::field_key_press_event (GdkEventKey */*ev*/, Field /*field*/)
748 /* all key activity is handled on key release */
753 AudioClock::field_key_release_event (GdkEventKey *ev, Field field)
758 bool move_on = false;
762 label = &hours_label;
764 case Timecode_Minutes:
765 label = &minutes_label;
767 case Timecode_Seconds:
768 label = &seconds_label;
770 case Timecode_Frames:
771 label = &frames_label;
775 label = &audio_frames_label;
779 label = &ms_hours_label;
782 label = &ms_minutes_label;
785 label = &ms_seconds_label;
792 label = &beats_label;
795 label = &ticks_label;
801 switch (ev->keyval) {
845 if (_mode == MinSec && field == MS_Seconds) {
860 clock_base.grab_focus ();
861 ChangeAborted(); /* EMIT SIGNAL */
870 if (key_entry_state == 0) {
872 /* initialize with a fresh new string */
874 if (field != AudioFrames) {
875 for (uint32_t xn = 0; xn < field_length[field] - 1; ++xn) {
884 string existing = label->get_text();
885 if (existing.length() >= field_length[field]) {
886 new_text = existing.substr (1, field_length[field] - 1);
888 new_text = existing.substr (0, field_length[field] - 1);
892 new_text += new_char;
893 label->set_text (new_text);
897 if (key_entry_state == field_length[field]) {
903 if (key_entry_state) {
907 case Timecode_Minutes:
908 case Timecode_Seconds:
909 case Timecode_Frames:
910 // Check Timecode fields for sanity (may also adjust fields)
911 timecode_sanitize_display();
916 // Bars should never be, unless this clock is for a duration
917 if (atoi(bars_label.get_text()) == 0 && !is_duration) {
918 bars_label.set_text("001");
920 // beats should never be 0, unless this clock is for a duration
921 if (atoi(beats_label.get_text()) == 0 && !is_duration) {
922 beats_label.set_text("01");
929 ValueChanged(); /* EMIT_SIGNAL */
932 /* move on to the next field.
940 minutes_ebox.grab_focus ();
942 case Timecode_Minutes:
943 seconds_ebox.grab_focus ();
945 case Timecode_Seconds:
946 frames_ebox.grab_focus ();
948 case Timecode_Frames:
949 clock_base.grab_focus ();
954 clock_base.grab_focus ();
960 ms_minutes_ebox.grab_focus ();
963 ms_seconds_ebox.grab_focus ();
966 clock_base.grab_focus ();
972 beats_ebox.grab_focus ();
975 ticks_ebox.grab_focus ();
978 clock_base.grab_focus ();
987 //if user hit Enter, lose focus
988 switch (ev->keyval) {
991 clock_base.grab_focus ();
998 AudioClock::field_focus_in_event (GdkEventFocus */*ev*/, Field field)
1000 key_entry_state = 0;
1002 Keyboard::magic_widget_grab_focus ();
1005 case Timecode_Hours:
1006 hours_ebox.set_flags (Gtk::HAS_FOCUS);
1007 hours_ebox.set_state (Gtk::STATE_ACTIVE);
1009 case Timecode_Minutes:
1010 minutes_ebox.set_flags (Gtk::HAS_FOCUS);
1011 minutes_ebox.set_state (Gtk::STATE_ACTIVE);
1013 case Timecode_Seconds:
1014 seconds_ebox.set_flags (Gtk::HAS_FOCUS);
1015 seconds_ebox.set_state (Gtk::STATE_ACTIVE);
1017 case Timecode_Frames:
1018 frames_ebox.set_flags (Gtk::HAS_FOCUS);
1019 frames_ebox.set_state (Gtk::STATE_ACTIVE);
1023 audio_frames_ebox.set_flags (Gtk::HAS_FOCUS);
1024 audio_frames_ebox.set_state (Gtk::STATE_ACTIVE);
1028 ms_hours_ebox.set_flags (Gtk::HAS_FOCUS);
1029 ms_hours_ebox.set_state (Gtk::STATE_ACTIVE);
1032 ms_minutes_ebox.set_flags (Gtk::HAS_FOCUS);
1033 ms_minutes_ebox.set_state (Gtk::STATE_ACTIVE);
1036 ms_seconds_ebox.set_flags (Gtk::HAS_FOCUS);
1037 ms_seconds_ebox.set_state (Gtk::STATE_ACTIVE);
1040 bars_ebox.set_flags (Gtk::HAS_FOCUS);
1041 bars_ebox.set_state (Gtk::STATE_ACTIVE);
1044 beats_ebox.set_flags (Gtk::HAS_FOCUS);
1045 beats_ebox.set_state (Gtk::STATE_ACTIVE);
1048 ticks_ebox.set_flags (Gtk::HAS_FOCUS);
1049 ticks_ebox.set_state (Gtk::STATE_ACTIVE);
1057 AudioClock::field_focus_out_event (GdkEventFocus */*ev*/, Field field)
1061 case Timecode_Hours:
1062 hours_ebox.unset_flags (Gtk::HAS_FOCUS);
1063 hours_ebox.set_state (Gtk::STATE_NORMAL);
1065 case Timecode_Minutes:
1066 minutes_ebox.unset_flags (Gtk::HAS_FOCUS);
1067 minutes_ebox.set_state (Gtk::STATE_NORMAL);
1069 case Timecode_Seconds:
1070 seconds_ebox.unset_flags (Gtk::HAS_FOCUS);
1071 seconds_ebox.set_state (Gtk::STATE_NORMAL);
1073 case Timecode_Frames:
1074 frames_ebox.unset_flags (Gtk::HAS_FOCUS);
1075 frames_ebox.set_state (Gtk::STATE_NORMAL);
1079 audio_frames_ebox.unset_flags (Gtk::HAS_FOCUS);
1080 audio_frames_ebox.set_state (Gtk::STATE_NORMAL);
1084 ms_hours_ebox.unset_flags (Gtk::HAS_FOCUS);
1085 ms_hours_ebox.set_state (Gtk::STATE_NORMAL);
1088 ms_minutes_ebox.unset_flags (Gtk::HAS_FOCUS);
1089 ms_minutes_ebox.set_state (Gtk::STATE_NORMAL);
1092 ms_seconds_ebox.unset_flags (Gtk::HAS_FOCUS);
1093 ms_seconds_ebox.set_state (Gtk::STATE_NORMAL);
1097 bars_ebox.unset_flags (Gtk::HAS_FOCUS);
1098 bars_ebox.set_state (Gtk::STATE_NORMAL);
1101 beats_ebox.unset_flags (Gtk::HAS_FOCUS);
1102 beats_ebox.set_state (Gtk::STATE_NORMAL);
1105 ticks_ebox.unset_flags (Gtk::HAS_FOCUS);
1106 ticks_ebox.set_state (Gtk::STATE_NORMAL);
1110 Keyboard::magic_widget_drop_focus ();
1116 AudioClock::field_button_release_event (GdkEventButton *ev, Field field)
1119 cerr << "button event on clock but we are dragging\n";
1120 gdk_pointer_ungrab (GDK_CURRENT_TIME);
1122 if (ev->y > drag_start_y+1 || ev->y < drag_start_y-1 || Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)){
1123 // we actually dragged so return without setting editing focus, or we shift clicked
1129 if (ops_menu == 0) {
1132 ops_menu->popup (1, ev->time);
1136 if (Keyboard::is_context_menu_event (ev)) {
1137 cerr << "Context menu event on clock\n";
1138 if (ops_menu == 0) {
1141 ops_menu->popup (1, ev->time);
1145 switch (ev->button) {
1148 case Timecode_Hours:
1149 hours_ebox.grab_focus();
1151 case Timecode_Minutes:
1152 minutes_ebox.grab_focus();
1154 case Timecode_Seconds:
1155 seconds_ebox.grab_focus();
1157 case Timecode_Frames:
1158 frames_ebox.grab_focus();
1162 audio_frames_ebox.grab_focus();
1166 ms_hours_ebox.grab_focus();
1169 ms_minutes_ebox.grab_focus();
1172 ms_seconds_ebox.grab_focus();
1176 bars_ebox.grab_focus ();
1179 beats_ebox.grab_focus ();
1182 ticks_ebox.grab_focus ();
1195 AudioClock::field_button_press_event (GdkEventButton *ev, Field /*field*/)
1197 if (_session == 0) {
1201 framepos_t frames = 0;
1203 switch (ev->button) {
1205 if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
1207 ValueChanged (); /* EMIT_SIGNAL */
1210 /* make absolutely sure that the pointer is grabbed */
1211 gdk_pointer_grab(ev->window,false ,
1212 GdkEventMask( Gdk::POINTER_MOTION_MASK | Gdk::BUTTON_PRESS_MASK |Gdk::BUTTON_RELEASE_MASK),
1213 NULL,NULL,ev->time);
1216 drag_start_y = ev->y;
1221 if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
1223 ValueChanged (); /* EMIT_SIGNAL */
1228 /* used for context sensitive menu */
1241 AudioClock::field_button_scroll_event (GdkEventScroll *ev, Field field)
1243 if (_session == 0) {
1247 framepos_t frames = 0;
1249 switch (ev->direction) {
1252 frames = get_frames (field);
1254 if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
1257 set (current_time() + frames, true);
1258 ValueChanged (); /* EMIT_SIGNAL */
1262 case GDK_SCROLL_DOWN:
1263 frames = get_frames (field);
1265 if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
1269 if ((double)current_time() - (double)frames < 0.0) {
1272 set (current_time() - frames, true);
1275 ValueChanged (); /* EMIT_SIGNAL */
1288 AudioClock::field_motion_notify_event (GdkEventMotion *ev, Field field)
1290 if (_session == 0 || !dragging) {
1294 float pixel_frame_scale_factor = 0.2f;
1297 if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
1298 pixel_frame_scale_factor = 0.1f;
1302 if (Keyboard::modifier_state_contains (ev->state,
1303 Keyboard::PrimaryModifier|Keyboard::SecondaryModifier)) {
1305 pixel_frame_scale_factor = 0.025f;
1308 double y_delta = ev->y - drag_y;
1310 drag_accum += y_delta*pixel_frame_scale_factor;
1314 if (trunc(drag_accum) != 0) {
1319 dir = (drag_accum < 0 ? 1:-1);
1320 pos = current_time();
1321 frames = get_frames (field,pos,dir);
1323 if (frames != 0 && frames * drag_accum < current_time()) {
1325 set ((framepos_t) floor (pos - drag_accum * frames), false); // minus because up is negative in computer-land
1333 ValueChanged(); /* EMIT_SIGNAL */
1342 AudioClock::get_frames (Field field, framepos_t pos, int dir)
1344 framecnt_t frames = 0;
1345 Timecode::BBT_Time bbt;
1347 case Timecode_Hours:
1348 frames = (framecnt_t) floor (3600.0 * _session->frame_rate());
1350 case Timecode_Minutes:
1351 frames = (framecnt_t) floor (60.0 * _session->frame_rate());
1353 case Timecode_Seconds:
1354 frames = _session->frame_rate();
1356 case Timecode_Frames:
1357 frames = (framecnt_t) floor (_session->frame_rate() / _session->timecode_frames_per_second());
1365 frames = (framecnt_t) floor (3600.0 * _session->frame_rate());
1368 frames = (framecnt_t) floor (60.0 * _session->frame_rate());
1371 frames = _session->frame_rate();
1378 frames = _session->tempo_map().bbt_duration_at(pos,bbt,dir);
1384 frames = _session->tempo_map().bbt_duration_at(pos,bbt,dir);
1390 frames = _session->tempo_map().bbt_duration_at(pos,bbt,dir);
1398 AudioClock::current_time (framepos_t pos) const
1404 ret = timecode_frame_from_display ();
1407 ret = bbt_frame_from_display (pos);
1411 ret = minsec_frame_from_display ();
1415 ret = audio_frame_from_display ();
1426 AudioClock::current_duration (framepos_t pos) const
1432 ret = timecode_frame_from_display ();
1435 ret = bbt_frame_duration_from_display (pos);
1439 ret = minsec_frame_from_display ();
1443 ret = audio_frame_from_display ();
1454 AudioClock::timecode_sanitize_display()
1456 // Check Timecode fields for sanity, possibly adjusting values
1457 if (atoi(minutes_label.get_text()) > 59) {
1458 minutes_label.set_text("59");
1461 if (atoi(seconds_label.get_text()) > 59) {
1462 seconds_label.set_text("59");
1465 switch ((long)rint(_session->timecode_frames_per_second())) {
1467 if (atoi(frames_label.get_text()) > 23) {
1468 frames_label.set_text("23");
1472 if (atoi(frames_label.get_text()) > 24) {
1473 frames_label.set_text("24");
1477 if (atoi(frames_label.get_text()) > 29) {
1478 frames_label.set_text("29");
1485 if (_session->timecode_drop_frames()) {
1486 if ((atoi(minutes_label.get_text()) % 10) && (atoi(seconds_label.get_text()) == 0) && (atoi(frames_label.get_text()) < 2)) {
1487 frames_label.set_text("02");
1493 AudioClock::timecode_frame_from_display () const
1495 if (_session == 0) {
1499 Timecode::Time timecode;
1502 timecode.hours = atoi (hours_label.get_text());
1503 timecode.minutes = atoi (minutes_label.get_text());
1504 timecode.seconds = atoi (seconds_label.get_text());
1505 timecode.frames = atoi (frames_label.get_text());
1506 timecode.rate = _session->timecode_frames_per_second();
1507 timecode.drop= _session->timecode_drop_frames();
1509 _session->timecode_to_sample( timecode, sample, false /* use_offset */, false /* use_subframes */ );
1513 #define Timecode_SAMPLE_TEST_1
1514 #define Timecode_SAMPLE_TEST_2
1515 #define Timecode_SAMPLE_TEST_3
1516 #define Timecode_SAMPLE_TEST_4
1517 #define Timecode_SAMPLE_TEST_5
1518 #define Timecode_SAMPLE_TEST_6
1519 #define Timecode_SAMPLE_TEST_7
1521 // Testcode for timecode<->sample conversions (P.S.)
1522 Timecode::Time timecode1;
1524 framepos_t oldsample = 0;
1525 Timecode::Time timecode2;
1526 framecnt_t sample_increment;
1528 sample_increment = (framecnt_t)rint(_session->frame_rate() / _session->timecode_frames_per_second);
1530 #ifdef Timecode_SAMPLE_TEST_1
1531 // Test 1: use_offset = false, use_subframes = false
1532 cout << "use_offset = false, use_subframes = false" << endl;
1533 for (int i = 0; i < 108003; i++) {
1534 _session->timecode_to_sample( timecode1, sample1, false /* use_offset */, false /* use_subframes */ );
1535 _session->sample_to_timecode( sample1, timecode2, false /* use_offset */, false /* use_subframes */ );
1537 if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
1538 cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1539 cout << "timecode1: " << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << " -> ";
1540 cout << "sample: " << sample1 << endl;
1541 cout << "sample: " << sample1 << " -> ";
1542 cout << "timecode2: " << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
1546 if (timecode2.hours != timecode1.hours || timecode2.minutes != timecode1.minutes || timecode2.seconds != timecode2.seconds || timecode2.frames != timecode1.frames) {
1547 cout << "ERROR: timecode2 not equal timecode1" << endl;
1548 cout << "timecode1: " << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << " -> ";
1549 cout << "sample: " << sample1 << endl;
1550 cout << "sample: " << sample1 << " -> ";
1551 cout << "timecode2: " << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
1554 oldsample = sample1;
1555 _session->timecode_increment( timecode1 );
1558 cout << "sample_increment: " << sample_increment << endl;
1559 cout << "sample: " << sample1 << " -> ";
1560 cout << "timecode: " << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
1563 #ifdef Timecode_SAMPLE_TEST_2
1564 // Test 2: use_offset = true, use_subframes = false
1565 cout << "use_offset = true, use_subframes = false" << endl;
1567 timecode1.hours = 0;
1568 timecode1.minutes = 0;
1569 timecode1.seconds = 0;
1570 timecode1.frames = 0;
1571 timecode1.subframes = 0;
1572 sample1 = oldsample = 0;
1574 _session->sample_to_timecode( sample1, timecode1, true /* use_offset */, false /* use_subframes */ );
1575 cout << "Starting at sample: " << sample1 << " -> ";
1576 cout << "timecode: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << endl;
1578 for (int i = 0; i < 108003; i++) {
1579 _session->timecode_to_sample( timecode1, sample1, true /* use_offset */, false /* use_subframes */ );
1580 _session->sample_to_timecode( sample1, timecode2, true /* use_offset */, false /* use_subframes */ );
1582 // cout << "timecode: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << " -> ";
1583 // cout << "sample: " << sample1 << endl;
1584 // cout << "sample: " << sample1 << " -> ";
1585 // cout << "timecode: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
1587 if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
1588 cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1589 cout << "timecode1: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << " -> ";
1590 cout << "sample: " << sample1 << endl;
1591 cout << "sample: " << sample1 << " -> ";
1592 cout << "timecode2: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
1596 if (timecode2.hours != timecode1.hours || timecode2.minutes != timecode1.minutes || timecode2.seconds != timecode2.seconds || timecode2.frames != timecode1.frames) {
1597 cout << "ERROR: timecode2 not equal timecode1" << endl;
1598 cout << "timecode1: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << " -> ";
1599 cout << "sample: " << sample1 << endl;
1600 cout << "sample: " << sample1 << " -> ";
1601 cout << "timecode2: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
1604 oldsample = sample1;
1605 _session->timecode_increment( timecode1 );
1608 cout << "sample_increment: " << sample_increment << endl;
1609 cout << "sample: " << sample1 << " -> ";
1610 cout << "timecode: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
1613 #ifdef Timecode_SAMPLE_TEST_3
1614 // Test 3: use_offset = true, use_subframes = false, decrement
1615 cout << "use_offset = true, use_subframes = false, decrement" << endl;
1617 _session->sample_to_timecode( sample1, timecode1, true /* use_offset */, false /* use_subframes */ );
1618 cout << "Starting at sample: " << sample1 << " -> ";
1619 cout << "timecode: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << endl;
1621 for (int i = 0; i < 108003; i++) {
1622 _session->timecode_to_sample( timecode1, sample1, true /* use_offset */, false /* use_subframes */ );
1623 _session->sample_to_timecode( sample1, timecode2, true /* use_offset */, false /* use_subframes */ );
1625 // cout << "timecode: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << " -> ";
1626 // cout << "sample: " << sample1 << endl;
1627 // cout << "sample: " << sample1 << " -> ";
1628 // cout << "timecode: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
1630 if ((i > 0) && ( ((oldsample - sample1) != sample_increment) && ((oldsample - sample1) != (sample_increment + 1)) && ((oldsample - sample1) != (sample_increment - 1)))) {
1631 cout << "ERROR: sample increment not right: " << (oldsample - sample1) << " != " << sample_increment << endl;
1632 cout << "timecode1: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << " -> ";
1633 cout << "sample: " << sample1 << endl;
1634 cout << "sample: " << sample1 << " -> ";
1635 cout << "timecode2: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
1639 if (timecode2.hours != timecode1.hours || timecode2.minutes != timecode1.minutes || timecode2.seconds != timecode2.seconds || timecode2.frames != timecode1.frames) {
1640 cout << "ERROR: timecode2 not equal timecode1" << endl;
1641 cout << "timecode1: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << " -> ";
1642 cout << "sample: " << sample1 << endl;
1643 cout << "sample: " << sample1 << " -> ";
1644 cout << "timecode2: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
1647 oldsample = sample1;
1648 _session->timecode_decrement( timecode1 );
1651 cout << "sample_decrement: " << sample_increment << endl;
1652 cout << "sample: " << sample1 << " -> ";
1653 cout << "timecode: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
1657 #ifdef Timecode_SAMPLE_TEST_4
1658 // Test 4: use_offset = true, use_subframes = true
1659 cout << "use_offset = true, use_subframes = true" << endl;
1661 for (long sub = 5; sub < 80; sub += 5) {
1662 timecode1.hours = 0;
1663 timecode1.minutes = 0;
1664 timecode1.seconds = 0;
1665 timecode1.frames = 0;
1666 timecode1.subframes = 0;
1667 sample1 = oldsample = (sample_increment * sub) / 80;
1669 _session->sample_to_timecode( sample1, timecode1, true /* use_offset */, true /* use_subframes */ );
1671 cout << "starting at sample: " << sample1 << " -> ";
1672 cout << "timecode: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << endl;
1674 for (int i = 0; i < 108003; i++) {
1675 _session->timecode_to_sample( timecode1, sample1, true /* use_offset */, true /* use_subframes */ );
1676 _session->sample_to_timecode( sample1, timecode2, true /* use_offset */, true /* use_subframes */ );
1678 if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
1679 cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1680 cout << "timecode1: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << " -> ";
1681 cout << "sample: " << sample1 << endl;
1682 cout << "sample: " << sample1 << " -> ";
1683 cout << "timecode2: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
1687 if (timecode2.hours != timecode1.hours || timecode2.minutes != timecode1.minutes || timecode2.seconds != timecode2.seconds || timecode2.frames != timecode1.frames || timecode2.subframes != timecode1.subframes) {
1688 cout << "ERROR: timecode2 not equal timecode1" << endl;
1689 cout << "timecode1: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << " -> ";
1690 cout << "sample: " << sample1 << endl;
1691 cout << "sample: " << sample1 << " -> ";
1692 cout << "timecode2: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
1695 oldsample = sample1;
1696 _session->timecode_increment( timecode1 );
1699 cout << "sample_increment: " << sample_increment << endl;
1700 cout << "sample: " << sample1 << " -> ";
1701 cout << "timecode: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
1703 for (int i = 0; i < 108003; i++) {
1704 _session->timecode_to_sample( timecode1, sample1, true /* use_offset */, true /* use_subframes */ );
1705 _session->sample_to_timecode( sample1, timecode2, true /* use_offset */, true /* use_subframes */ );
1707 if ((i > 0) && ( ((oldsample - sample1) != sample_increment) && ((oldsample - sample1) != (sample_increment + 1)) && ((oldsample - sample1) != (sample_increment - 1)))) {
1708 cout << "ERROR: sample increment not right: " << (oldsample - sample1) << " != " << sample_increment << endl;
1709 cout << "timecode1: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << " -> ";
1710 cout << "sample: " << sample1 << endl;
1711 cout << "sample: " << sample1 << " -> ";
1712 cout << "timecode2: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
1716 if (timecode2.hours != timecode1.hours || timecode2.minutes != timecode1.minutes || timecode2.seconds != timecode2.seconds || timecode2.frames != timecode1.frames || timecode2.subframes != timecode1.subframes) {
1717 cout << "ERROR: timecode2 not equal timecode1" << endl;
1718 cout << "timecode1: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << " -> ";
1719 cout << "sample: " << sample1 << endl;
1720 cout << "sample: " << sample1 << " -> ";
1721 cout << "timecode2: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
1724 oldsample = sample1;
1725 _session->timecode_decrement( timecode1 );
1728 cout << "sample_decrement: " << sample_increment << endl;
1729 cout << "sample: " << sample1 << " -> ";
1730 cout << "timecode: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
1735 #ifdef Timecode_SAMPLE_TEST_5
1736 // Test 5: use_offset = true, use_subframes = false, increment seconds
1737 cout << "use_offset = true, use_subframes = false, increment seconds" << endl;
1739 timecode1.hours = 0;
1740 timecode1.minutes = 0;
1741 timecode1.seconds = 0;
1742 timecode1.frames = 0;
1743 timecode1.subframes = 0;
1744 sample1 = oldsample = 0;
1745 sample_increment = _session->frame_rate();
1747 _session->sample_to_timecode( sample1, timecode1, true /* use_offset */, false /* use_subframes */ );
1748 cout << "Starting at sample: " << sample1 << " -> ";
1749 cout << "timecode: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << endl;
1751 for (int i = 0; i < 3600; i++) {
1752 _session->timecode_to_sample( timecode1, sample1, true /* use_offset */, false /* use_subframes */ );
1753 _session->sample_to_timecode( sample1, timecode2, true /* use_offset */, false /* use_subframes */ );
1755 // cout << "timecode: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << " -> ";
1756 // cout << "sample: " << sample1 << endl;
1757 // cout << "sample: " << sample1 << " -> ";
1758 // cout << "timecode: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
1760 // if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1762 // cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1766 if (timecode2.hours != timecode1.hours || timecode2.minutes != timecode1.minutes || timecode2.seconds != timecode2.seconds || timecode2.frames != timecode1.frames) {
1767 cout << "ERROR: timecode2 not equal timecode1" << endl;
1768 cout << "timecode: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << " -> ";
1769 cout << "sample: " << sample1 << endl;
1770 cout << "sample: " << sample1 << " -> ";
1771 cout << "timecode: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
1774 oldsample = sample1;
1775 _session->timecode_increment_seconds( timecode1 );
1778 cout << "sample_increment: " << sample_increment << endl;
1779 cout << "sample: " << sample1 << " -> ";
1780 cout << "timecode: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
1784 #ifdef Timecode_SAMPLE_TEST_6
1785 // Test 6: use_offset = true, use_subframes = false, increment minutes
1786 cout << "use_offset = true, use_subframes = false, increment minutes" << endl;
1788 timecode1.hours = 0;
1789 timecode1.minutes = 0;
1790 timecode1.seconds = 0;
1791 timecode1.frames = 0;
1792 timecode1.subframes = 0;
1793 sample1 = oldsample = 0;
1794 sample_increment = _session->frame_rate() * 60;
1796 _session->sample_to_timecode( sample1, timecode1, true /* use_offset */, false /* use_subframes */ );
1797 cout << "Starting at sample: " << sample1 << " -> ";
1798 cout << "timecode: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << endl;
1800 for (int i = 0; i < 60; i++) {
1801 _session->timecode_to_sample( timecode1, sample1, true /* use_offset */, false /* use_subframes */ );
1802 _session->sample_to_timecode( sample1, timecode2, true /* use_offset */, false /* use_subframes */ );
1804 // cout << "timecode: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << " -> ";
1805 // cout << "sample: " << sample1 << endl;
1806 // cout << "sample: " << sample1 << " -> ";
1807 // cout << "timecode: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
1809 // if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1811 // cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1815 if (timecode2.hours != timecode1.hours || timecode2.minutes != timecode1.minutes || timecode2.seconds != timecode2.seconds || timecode2.frames != timecode1.frames) {
1816 cout << "ERROR: timecode2 not equal timecode1" << endl;
1817 cout << "timecode: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << " -> ";
1818 cout << "sample: " << sample1 << endl;
1819 cout << "sample: " << sample1 << " -> ";
1820 cout << "timecode: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
1823 oldsample = sample1;
1824 _session->timecode_increment_minutes( timecode1 );
1827 cout << "sample_increment: " << sample_increment << endl;
1828 cout << "sample: " << sample1 << " -> ";
1829 cout << "timecode: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
1832 #ifdef Timecode_SAMPLE_TEST_7
1833 // Test 7: use_offset = true, use_subframes = false, increment hours
1834 cout << "use_offset = true, use_subframes = false, increment hours" << endl;
1836 timecode1.hours = 0;
1837 timecode1.minutes = 0;
1838 timecode1.seconds = 0;
1839 timecode1.frames = 0;
1840 timecode1.subframes = 0;
1841 sample1 = oldsample = 0;
1842 sample_increment = _session->frame_rate() * 60 * 60;
1844 _session->sample_to_timecode( sample1, timecode1, true /* use_offset */, false /* use_subframes */ );
1845 cout << "Starting at sample: " << sample1 << " -> ";
1846 cout << "timecode: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << endl;
1848 for (int i = 0; i < 10; i++) {
1849 _session->timecode_to_sample( timecode1, sample1, true /* use_offset */, false /* use_subframes */ );
1850 _session->sample_to_timecode( sample1, timecode2, true /* use_offset */, false /* use_subframes */ );
1852 // cout << "timecode: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << " -> ";
1853 // cout << "sample: " << sample1 << endl;
1854 // cout << "sample: " << sample1 << " -> ";
1855 // cout << "timecode: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
1857 // if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1859 // cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1863 if (timecode2.hours != timecode1.hours || timecode2.minutes != timecode1.minutes || timecode2.seconds != timecode2.seconds || timecode2.frames != timecode1.frames) {
1864 cout << "ERROR: timecode2 not equal timecode1" << endl;
1865 cout << "timecode: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << " -> ";
1866 cout << "sample: " << sample1 << endl;
1867 cout << "sample: " << sample1 << " -> ";
1868 cout << "timecode: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
1871 oldsample = sample1;
1872 _session->timecode_increment_hours( timecode1 );
1875 cout << "sample_increment: " << sample_increment << endl;
1876 cout << "sample: " << sample1 << " -> ";
1877 cout << "timecode: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
1886 AudioClock::minsec_frame_from_display () const
1888 if (_session == 0) {
1892 int hrs = atoi (ms_hours_label.get_text());
1893 int mins = atoi (ms_minutes_label.get_text());
1894 float secs = atof (ms_seconds_label.get_text());
1896 framecnt_t sr = _session->frame_rate();
1898 return (framepos_t) floor ((hrs * 60.0f * 60.0f * sr) + (mins * 60.0f * sr) + (secs * sr));
1902 AudioClock::bbt_frame_from_display (framepos_t pos) const
1904 if (_session == 0) {
1905 error << "AudioClock::current_time() called with BBT mode but without session!" << endmsg;
1910 any.type = AnyTime::BBT;
1912 any.bbt.bars = atoi (bars_label.get_text());
1913 any.bbt.beats = atoi (beats_label.get_text());
1914 any.bbt.ticks = atoi (ticks_label.get_text());
1921 return _session->convert_to_frames_at (pos, any);
1926 AudioClock::bbt_frame_duration_from_display (framepos_t pos) const
1928 if (_session == 0) {
1929 error << "AudioClock::current_time() called with BBT mode but without session!" << endmsg;
1933 Timecode::BBT_Time bbt;
1936 bbt.bars = atoi (bars_label.get_text());
1937 bbt.beats = atoi (beats_label.get_text());
1938 bbt.ticks = atoi (ticks_label.get_text());
1940 return _session->tempo_map().bbt_duration_at(pos,bbt,1);
1944 AudioClock::audio_frame_from_display () const
1946 return (framepos_t) atoi (audio_frames_label.get_text());
1950 AudioClock::build_ops_menu ()
1952 using namespace Menu_Helpers;
1953 ops_menu = new Menu;
1954 MenuList& ops_items = ops_menu->items();
1955 ops_menu->set_name ("ArdourContextMenu");
1957 if (!Profile->get_sae()) {
1958 ops_items.push_back (MenuElem (_("Timecode"), sigc::bind (sigc::mem_fun(*this, &AudioClock::set_mode), Timecode)));
1960 ops_items.push_back (MenuElem (_("Bars:Beats"), sigc::bind (sigc::mem_fun(*this, &AudioClock::set_mode), BBT)));
1961 ops_items.push_back (MenuElem (_("Minutes:Seconds"), sigc::bind (sigc::mem_fun(*this, &AudioClock::set_mode), MinSec)));
1962 ops_items.push_back (MenuElem (_("Samples"), sigc::bind (sigc::mem_fun(*this, &AudioClock::set_mode), Frames)));
1963 ops_items.push_back (MenuElem (_("Off"), sigc::bind (sigc::mem_fun(*this, &AudioClock::set_mode), Off)));
1965 if (editable && !is_duration && !_follows_playhead) {
1966 ops_items.push_back (SeparatorElem());
1967 ops_items.push_back (MenuElem (_("Set From Playhead"), sigc::mem_fun(*this, &AudioClock::set_from_playhead)));
1968 ops_items.push_back (MenuElem (_("Locate to This Time"), sigc::mem_fun(*this, &AudioClock::locate)));
1973 AudioClock::set_from_playhead ()
1979 set (_session->transport_frame());
1983 AudioClock::locate ()
1985 if (!_session || is_duration) {
1989 _session->request_locate (current_time(), _session->transport_rolling ());
1993 AudioClock::set_mode (Mode m)
1995 /* slightly tricky: this is called from within the ARDOUR_UI
1996 constructor by some of its clock members. at that time
1997 the instance pointer is unset, so we have to be careful.
1998 the main idea is to drop keyboard focus in case we had
1999 started editing the clock and then we switch clock mode.
2002 clock_base.grab_focus ();
2008 clock_base.remove ();
2014 clock_base.add (timecode_packer_hbox);
2018 clock_base.add (bbt_packer_hbox);
2022 clock_base.add (minsec_packer_hbox);
2026 clock_base.add (frames_packer_hbox);
2030 clock_base.add (off_hbox);
2034 set_size_requests ();
2036 set (last_when, true);
2037 clock_base.show_all ();
2038 key_entry_state = 0;
2040 if (!is_transient) {
2041 ModeChanged (); /* EMIT SIGNAL */
2042 mode_changed (); /* EMIT SIGNAL */
2047 AudioClock::set_size_requests ()
2049 /* note that in some fonts, "88" is narrower than "00" */
2053 Gtkmm2ext::set_size_request_to_display_given_text (hours_label, "-88", 5, 5);
2054 Gtkmm2ext::set_size_request_to_display_given_text (minutes_label, "88", 5, 5);
2055 Gtkmm2ext::set_size_request_to_display_given_text (seconds_label, "88", 5, 5);
2056 Gtkmm2ext::set_size_request_to_display_given_text (frames_label, "88", 5, 5);
2060 Gtkmm2ext::set_size_request_to_display_given_text (bars_label, "-888", 5, 5);
2061 Gtkmm2ext::set_size_request_to_display_given_text (beats_label, "88", 5, 5);
2062 Gtkmm2ext::set_size_request_to_display_given_text (ticks_label, "8888", 5, 5);
2066 Gtkmm2ext::set_size_request_to_display_given_text (ms_hours_label, "88", 5, 5);
2067 Gtkmm2ext::set_size_request_to_display_given_text (ms_minutes_label, "88", 5, 5);
2068 Gtkmm2ext::set_size_request_to_display_given_text (ms_seconds_label, "88.888", 5, 5);
2072 Gtkmm2ext::set_size_request_to_display_given_text (audio_frames_label, "8888888888", 5, 5);
2076 Gtkmm2ext::set_size_request_to_display_given_text (off_hbox, "00000", 5, 5);
2083 AudioClock::set_bbt_reference (framepos_t pos)
2085 bbt_reference_time = pos;
2089 AudioClock::on_style_changed (const Glib::RefPtr<Gtk::Style>& old_style)
2091 HBox::on_style_changed (old_style);
2093 /* propagate style changes to all component widgets that should inherit the main one */
2095 Glib::RefPtr<RcStyle> rcstyle = get_modifier_style();
2097 clock_base.modify_style (rcstyle);
2098 audio_frames_label.modify_style (rcstyle);
2099 hours_label.modify_style (rcstyle);
2100 minutes_label.modify_style (rcstyle);
2101 seconds_label.modify_style (rcstyle);
2102 frames_label.modify_style (rcstyle);
2103 bars_label.modify_style (rcstyle);
2104 beats_label.modify_style (rcstyle);
2105 ticks_label.modify_style (rcstyle);
2106 ms_hours_label.modify_style (rcstyle);
2107 ms_minutes_label.modify_style (rcstyle);
2108 ms_seconds_label.modify_style (rcstyle);
2109 hours_ebox.modify_style (rcstyle);
2110 minutes_ebox.modify_style (rcstyle);
2111 seconds_ebox.modify_style (rcstyle);
2112 frames_ebox.modify_style (rcstyle);
2113 audio_frames_ebox.modify_style (rcstyle);
2114 bars_ebox.modify_style (rcstyle);
2115 beats_ebox.modify_style (rcstyle);
2116 ticks_ebox.modify_style (rcstyle);
2117 ms_hours_ebox.modify_style (rcstyle);
2118 ms_minutes_ebox.modify_style (rcstyle);
2119 ms_seconds_ebox.modify_style (rcstyle);
2121 colon1.modify_style (rcstyle);
2122 colon2.modify_style (rcstyle);
2123 colon3.modify_style (rcstyle);
2124 colon4.modify_style (rcstyle);
2125 colon5.modify_style (rcstyle);
2126 b1.modify_style (rcstyle);
2127 b2.modify_style (rcstyle);
2129 set_size_requests ();
2133 AudioClock::set_is_duration (bool yn)
2135 if (yn == is_duration) {
2140 set (last_when, true, 0, 's');