2 Copyright (C) 1999 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include <cstdio> // for sprintf
23 #include "pbd/convert.h"
24 #include "pbd/enumwriter.h"
26 #include <gtkmm2ext/utils.h>
28 #include "ardour/ardour.h"
29 #include "ardour/session.h"
30 #include "ardour/tempo.h"
31 #include "ardour/profile.h"
32 #include <sigc++/bind.h>
34 #include "ardour_ui.h"
35 #include "audio_clock.h"
38 #include "gui_thread.h"
41 using namespace ARDOUR
;
46 using Gtkmm2ext::Keyboard
;
51 sigc::signal
<void> AudioClock::ModeChanged
;
52 vector
<AudioClock
*> AudioClock::clocks
;
54 const uint32_t AudioClock::field_length
[(int) AudioClock::AudioFrames
+1] = {
55 2, /* Timecode_Hours */
56 2, /* Timecode_Minutes */
57 2, /* Timecode_Seconds */
58 2, /* Timecode_Frames */
68 AudioClock::AudioClock (const string
& clock_name
, bool transient
, const string
& widget_name
,
69 bool allow_edit
, bool follows_playhead
, bool duration
, bool with_info
)
71 is_transient (transient
),
72 is_duration (duration
),
73 editable (allow_edit
),
74 _follows_playhead (follows_playhead
),
90 bbt_reference_time
= -1;
93 frames_upper_info_label
= manage (new Label
);
94 frames_lower_info_label
= manage (new Label
);
95 timecode_upper_info_label
= manage (new Label
);
96 timecode_lower_info_label
= manage (new Label
);
97 bbt_upper_info_label
= manage (new Label
);
98 bbt_lower_info_label
= manage (new Label
);
100 frames_upper_info_label
->set_name ("AudioClockFramesUpperInfo");
101 frames_lower_info_label
->set_name ("AudioClockFramesLowerInfo");
102 timecode_upper_info_label
->set_name ("AudioClockTimecodeUpperInfo");
103 timecode_lower_info_label
->set_name ("AudioClockTimecodeLowerInfo");
104 bbt_upper_info_label
->set_name ("AudioClockBBTUpperInfo");
105 bbt_lower_info_label
->set_name ("AudioClockBBTLowerInfo");
107 Gtkmm2ext::set_size_request_to_display_given_text(*timecode_upper_info_label
, "23.98",0,0);
108 Gtkmm2ext::set_size_request_to_display_given_text(*timecode_lower_info_label
, "NDF",0,0);
110 Gtkmm2ext::set_size_request_to_display_given_text(*bbt_upper_info_label
, "88|88",0,0);
111 Gtkmm2ext::set_size_request_to_display_given_text(*bbt_lower_info_label
, "888.88",0,0);
113 frames_info_box
.pack_start (*frames_upper_info_label
, true, true);
114 frames_info_box
.pack_start (*frames_lower_info_label
, true, true);
115 timecode_info_box
.pack_start (*timecode_upper_info_label
, true, true);
116 timecode_info_box
.pack_start (*timecode_lower_info_label
, true, true);
117 bbt_info_box
.pack_start (*bbt_upper_info_label
, true, true);
118 bbt_info_box
.pack_start (*bbt_lower_info_label
, true, true);
121 frames_upper_info_label
= 0;
122 frames_lower_info_label
= 0;
123 timecode_upper_info_label
= 0;
124 timecode_lower_info_label
= 0;
125 bbt_upper_info_label
= 0;
126 bbt_lower_info_label
= 0;
129 audio_frames_ebox
.add (audio_frames_label
);
131 frames_packer
.set_homogeneous (false);
132 frames_packer
.set_border_width (2);
133 frames_packer
.pack_start (audio_frames_ebox
, false, false);
136 frames_packer
.pack_start (frames_info_box
, false, false, 5);
139 frames_packer_hbox
.pack_start (frames_packer
, true, false);
141 hours_ebox
.add (hours_label
);
142 minutes_ebox
.add (minutes_label
);
143 seconds_ebox
.add (seconds_label
);
144 frames_ebox
.add (frames_label
);
145 bars_ebox
.add (bars_label
);
146 beats_ebox
.add (beats_label
);
147 ticks_ebox
.add (ticks_label
);
148 ms_hours_ebox
.add (ms_hours_label
);
149 ms_minutes_ebox
.add (ms_minutes_label
);
150 ms_seconds_ebox
.add (ms_seconds_label
);
152 timecode_packer
.set_homogeneous (false);
153 timecode_packer
.set_border_width (2);
154 timecode_packer
.pack_start (hours_ebox
, false, false);
155 timecode_packer
.pack_start (colon1
, false, false);
156 timecode_packer
.pack_start (minutes_ebox
, false, false);
157 timecode_packer
.pack_start (colon2
, false, false);
158 timecode_packer
.pack_start (seconds_ebox
, false, false);
159 timecode_packer
.pack_start (colon3
, false, false);
160 timecode_packer
.pack_start (frames_ebox
, false, false);
163 timecode_packer
.pack_start (timecode_info_box
, false, false, 5);
166 timecode_packer_hbox
.pack_start (timecode_packer
, true, false);
168 bbt_packer
.set_homogeneous (false);
169 bbt_packer
.set_border_width (2);
170 bbt_packer
.pack_start (bars_ebox
, false, false);
171 bbt_packer
.pack_start (b1
, false, false);
172 bbt_packer
.pack_start (beats_ebox
, false, false);
173 bbt_packer
.pack_start (b2
, false, false);
174 bbt_packer
.pack_start (ticks_ebox
, false, false);
177 bbt_packer
.pack_start (bbt_info_box
, false, false, 5);
180 bbt_packer_hbox
.pack_start (bbt_packer
, true, false);
182 minsec_packer
.set_homogeneous (false);
183 minsec_packer
.set_border_width (2);
184 minsec_packer
.pack_start (ms_hours_ebox
, false, false);
185 minsec_packer
.pack_start (colon4
, false, false);
186 minsec_packer
.pack_start (ms_minutes_ebox
, false, false);
187 minsec_packer
.pack_start (colon5
, false, false);
188 minsec_packer
.pack_start (ms_seconds_ebox
, false, false);
190 minsec_packer_hbox
.pack_start (minsec_packer
, true, false);
192 clock_frame
.set_shadow_type (Gtk::SHADOW_IN
);
193 clock_frame
.set_name ("BaseFrame");
195 clock_frame
.add (clock_base
);
197 set_widget_name (widget_name
);
199 _mode
= BBT
; /* lie to force mode switch */
202 pack_start (clock_frame
, true, true);
204 /* the clock base handles button releases for menu popup regardless of
205 editable status. if the clock is editable, the clock base is where
206 we pass focus to after leaving the last editable "field", which
207 will then shutdown editing till the user starts it up again.
209 it does this because the focus out event on the field disables
210 keyboard event handling, and we don't connect anything up to
211 notice focus in on the clock base. hence, keyboard event handling
215 clock_base
.add_events (Gdk::BUTTON_PRESS_MASK
|Gdk::BUTTON_RELEASE_MASK
|Gdk::SCROLL_MASK
);
216 clock_base
.signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &AudioClock::field_button_release_event
), Timecode_Hours
));
218 Session::TimecodeOffsetChanged
.connect (_session_connections
, invalidator (*this), boost::bind (&AudioClock::timecode_offset_changed
, this), gui_context());
224 set (last_when
, true);
227 clocks
.push_back (this);
232 AudioClock::set_widget_name (string name
)
234 Widget::set_name (name
);
236 clock_base
.set_name (name
);
238 audio_frames_label
.set_name (name
);
239 hours_label
.set_name (name
);
240 minutes_label
.set_name (name
);
241 seconds_label
.set_name (name
);
242 frames_label
.set_name (name
);
243 bars_label
.set_name (name
);
244 beats_label
.set_name (name
);
245 ticks_label
.set_name (name
);
246 ms_hours_label
.set_name (name
);
247 ms_minutes_label
.set_name (name
);
248 ms_seconds_label
.set_name (name
);
249 hours_ebox
.set_name (name
);
250 minutes_ebox
.set_name (name
);
251 seconds_ebox
.set_name (name
);
252 frames_ebox
.set_name (name
);
253 audio_frames_ebox
.set_name (name
);
254 bars_ebox
.set_name (name
);
255 beats_ebox
.set_name (name
);
256 ticks_ebox
.set_name (name
);
257 ms_hours_ebox
.set_name (name
);
258 ms_minutes_ebox
.set_name (name
);
259 ms_seconds_ebox
.set_name (name
);
261 colon1
.set_name (name
);
262 colon2
.set_name (name
);
263 colon3
.set_name (name
);
264 colon4
.set_name (name
);
265 colon5
.set_name (name
);
273 AudioClock::setup_events ()
275 clock_base
.set_flags (Gtk::CAN_FOCUS
);
277 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
);
278 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
);
279 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
);
280 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
);
281 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
);
282 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
);
283 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
);
284 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
);
285 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
);
286 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
);
287 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
);
289 hours_ebox
.set_flags (Gtk::CAN_FOCUS
);
290 minutes_ebox
.set_flags (Gtk::CAN_FOCUS
);
291 seconds_ebox
.set_flags (Gtk::CAN_FOCUS
);
292 frames_ebox
.set_flags (Gtk::CAN_FOCUS
);
293 audio_frames_ebox
.set_flags (Gtk::CAN_FOCUS
);
294 bars_ebox
.set_flags (Gtk::CAN_FOCUS
);
295 beats_ebox
.set_flags (Gtk::CAN_FOCUS
);
296 ticks_ebox
.set_flags (Gtk::CAN_FOCUS
);
297 ms_hours_ebox
.set_flags (Gtk::CAN_FOCUS
);
298 ms_minutes_ebox
.set_flags (Gtk::CAN_FOCUS
);
299 ms_seconds_ebox
.set_flags (Gtk::CAN_FOCUS
);
301 hours_ebox
.signal_motion_notify_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_motion_notify_event
), Timecode_Hours
));
302 minutes_ebox
.signal_motion_notify_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_motion_notify_event
), Timecode_Minutes
));
303 seconds_ebox
.signal_motion_notify_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_motion_notify_event
), Timecode_Seconds
));
304 frames_ebox
.signal_motion_notify_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_motion_notify_event
), Timecode_Frames
));
305 audio_frames_ebox
.signal_motion_notify_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_motion_notify_event
), AudioFrames
));
306 bars_ebox
.signal_motion_notify_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_motion_notify_event
), Bars
));
307 beats_ebox
.signal_motion_notify_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_motion_notify_event
), Beats
));
308 ticks_ebox
.signal_motion_notify_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_motion_notify_event
), Ticks
));
309 ms_hours_ebox
.signal_motion_notify_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_motion_notify_event
), MS_Hours
));
310 ms_minutes_ebox
.signal_motion_notify_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_motion_notify_event
), MS_Minutes
));
311 ms_seconds_ebox
.signal_motion_notify_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_motion_notify_event
), MS_Seconds
));
313 hours_ebox
.signal_button_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_press_event
), Timecode_Hours
));
314 minutes_ebox
.signal_button_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_press_event
), Timecode_Minutes
));
315 seconds_ebox
.signal_button_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_press_event
), Timecode_Seconds
));
316 frames_ebox
.signal_button_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_press_event
), Timecode_Frames
));
317 audio_frames_ebox
.signal_button_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_press_event
), AudioFrames
));
318 bars_ebox
.signal_button_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_press_event
), Bars
));
319 beats_ebox
.signal_button_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_press_event
), Beats
));
320 ticks_ebox
.signal_button_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_press_event
), Ticks
));
321 ms_hours_ebox
.signal_button_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_press_event
), MS_Hours
));
322 ms_minutes_ebox
.signal_button_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_press_event
), MS_Minutes
));
323 ms_seconds_ebox
.signal_button_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_press_event
), MS_Seconds
));
325 hours_ebox
.signal_button_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_release_event
), Timecode_Hours
));
326 minutes_ebox
.signal_button_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_release_event
), Timecode_Minutes
));
327 seconds_ebox
.signal_button_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_release_event
), Timecode_Seconds
));
328 frames_ebox
.signal_button_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_release_event
), Timecode_Frames
));
329 audio_frames_ebox
.signal_button_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_release_event
), AudioFrames
));
330 bars_ebox
.signal_button_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_release_event
), Bars
));
331 beats_ebox
.signal_button_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_release_event
), Beats
));
332 ticks_ebox
.signal_button_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_release_event
), Ticks
));
333 ms_hours_ebox
.signal_button_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_release_event
), MS_Hours
));
334 ms_minutes_ebox
.signal_button_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_release_event
), MS_Minutes
));
335 ms_seconds_ebox
.signal_button_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_release_event
), MS_Seconds
));
337 hours_ebox
.signal_scroll_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_scroll_event
), Timecode_Hours
));
338 minutes_ebox
.signal_scroll_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_scroll_event
), Timecode_Minutes
));
339 seconds_ebox
.signal_scroll_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_scroll_event
), Timecode_Seconds
));
340 frames_ebox
.signal_scroll_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_scroll_event
), Timecode_Frames
));
341 audio_frames_ebox
.signal_scroll_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_scroll_event
), AudioFrames
));
342 bars_ebox
.signal_scroll_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_scroll_event
), Bars
));
343 beats_ebox
.signal_scroll_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_scroll_event
), Beats
));
344 ticks_ebox
.signal_scroll_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_scroll_event
), Ticks
));
345 ms_hours_ebox
.signal_scroll_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_scroll_event
), MS_Hours
));
346 ms_minutes_ebox
.signal_scroll_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_scroll_event
), MS_Minutes
));
347 ms_seconds_ebox
.signal_scroll_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_scroll_event
), MS_Seconds
));
349 hours_ebox
.signal_key_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_press_event
), Timecode_Hours
));
350 minutes_ebox
.signal_key_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_press_event
), Timecode_Minutes
));
351 seconds_ebox
.signal_key_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_press_event
), Timecode_Seconds
));
352 frames_ebox
.signal_key_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_press_event
), Timecode_Frames
));
353 audio_frames_ebox
.signal_key_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_press_event
), AudioFrames
));
354 bars_ebox
.signal_key_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_press_event
), Bars
));
355 beats_ebox
.signal_key_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_press_event
), Beats
));
356 ticks_ebox
.signal_key_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_press_event
), Ticks
));
357 ms_hours_ebox
.signal_key_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_press_event
), MS_Hours
));
358 ms_minutes_ebox
.signal_key_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_press_event
), MS_Minutes
));
359 ms_seconds_ebox
.signal_key_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_press_event
), MS_Seconds
));
361 hours_ebox
.signal_key_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_release_event
), Timecode_Hours
));
362 minutes_ebox
.signal_key_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_release_event
), Timecode_Minutes
));
363 seconds_ebox
.signal_key_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_release_event
), Timecode_Seconds
));
364 frames_ebox
.signal_key_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_release_event
), Timecode_Frames
));
365 audio_frames_ebox
.signal_key_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_release_event
), AudioFrames
));
366 bars_ebox
.signal_key_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_release_event
), Bars
));
367 beats_ebox
.signal_key_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_release_event
), Beats
));
368 ticks_ebox
.signal_key_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_release_event
), Ticks
));
369 ms_hours_ebox
.signal_key_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_release_event
), MS_Hours
));
370 ms_minutes_ebox
.signal_key_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_release_event
), MS_Minutes
));
371 ms_seconds_ebox
.signal_key_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_release_event
), MS_Seconds
));
373 hours_ebox
.signal_focus_in_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_in_event
), Timecode_Hours
));
374 minutes_ebox
.signal_focus_in_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_in_event
), Timecode_Minutes
));
375 seconds_ebox
.signal_focus_in_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_in_event
), Timecode_Seconds
));
376 frames_ebox
.signal_focus_in_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_in_event
), Timecode_Frames
));
377 audio_frames_ebox
.signal_focus_in_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_in_event
), AudioFrames
));
378 bars_ebox
.signal_focus_in_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_in_event
), Bars
));
379 beats_ebox
.signal_focus_in_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_in_event
), Beats
));
380 ticks_ebox
.signal_focus_in_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_in_event
), Ticks
));
381 ms_hours_ebox
.signal_focus_in_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_in_event
), MS_Hours
));
382 ms_minutes_ebox
.signal_focus_in_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_in_event
), MS_Minutes
));
383 ms_seconds_ebox
.signal_focus_in_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_in_event
), MS_Seconds
));
385 hours_ebox
.signal_focus_out_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_out_event
), Timecode_Hours
));
386 minutes_ebox
.signal_focus_out_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_out_event
), Timecode_Minutes
));
387 seconds_ebox
.signal_focus_out_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_out_event
), Timecode_Seconds
));
388 frames_ebox
.signal_focus_out_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_out_event
), Timecode_Frames
));
389 audio_frames_ebox
.signal_focus_out_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_out_event
), AudioFrames
));
390 bars_ebox
.signal_focus_out_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_out_event
), Bars
));
391 beats_ebox
.signal_focus_out_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_out_event
), Beats
));
392 ticks_ebox
.signal_focus_out_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_out_event
), Ticks
));
393 ms_hours_ebox
.signal_focus_out_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_out_event
), MS_Hours
));
394 ms_minutes_ebox
.signal_focus_out_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_out_event
), MS_Minutes
));
395 ms_seconds_ebox
.signal_focus_out_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_out_event
), MS_Seconds
));
397 clock_base
.signal_focus_in_event().connect (sigc::mem_fun (*this, &AudioClock::drop_focus_handler
));
401 AudioClock::drop_focus_handler (GdkEventFocus
*)
403 Keyboard::magic_widget_drop_focus ();
408 AudioClock::on_realize ()
412 /* styles are not available until the widgets are bound to a window */
414 set_size_requests ();
418 AudioClock::set (nframes_t when
, bool force
, nframes_t offset
, char which
)
421 if ((!force
&& !is_visible()) || _session
== 0) {
425 if (when
== last_when
&& !offset
&& !force
) {
429 bool pdelta
= Config
->get_primary_clock_delta_edit_cursor();
430 bool sdelta
= Config
->get_secondary_clock_delta_edit_cursor();
432 if (offset
&& which
== 'p' && pdelta
) {
433 when
= (when
> offset
) ? when
- offset
: offset
- when
;
434 } else if (offset
&& which
== 's' && sdelta
) {
435 when
= (when
> offset
) ? when
- offset
: offset
- when
;
438 if (which
== 'p' && pdelta
&& !last_pdelta
) {
439 set_widget_name("TransportClockDisplayDelta");
441 } else if (which
== 'p' && !pdelta
&& last_pdelta
) {
442 set_widget_name("TransportClockDisplay");
444 } else if (which
== 's' && sdelta
&& !last_sdelta
) {
445 set_widget_name("SecondaryClockDisplayDelta");
447 } else if (which
== 's' && !sdelta
&& last_sdelta
) {
448 set_widget_name("SecondaryClockDisplay");
454 set_timecode (when
, force
);
458 set_bbt (when
, force
);
462 set_minsec (when
, force
);
466 set_frames (when
, force
);
477 AudioClock::timecode_offset_changed ()
484 current
= current_duration();
486 current
= current_time ();
496 AudioClock::set_frames (nframes_t when
, bool /*force*/)
499 snprintf (buf
, sizeof (buf
), "%u", when
);
500 audio_frames_label
.set_text (buf
);
502 if (frames_upper_info_label
) {
503 nframes_t rate
= _session
->frame_rate();
505 if (fmod (rate
, 1000.0) == 0.000) {
506 sprintf (buf
, "%uK", rate
/1000);
508 sprintf (buf
, "%.3fK", rate
/1000.0f
);
511 if (frames_upper_info_label
->get_text() != buf
) {
512 frames_upper_info_label
->set_text (buf
);
515 float vid_pullup
= _session
->config
.get_video_pullup();
517 if (vid_pullup
== 0.0) {
518 if (frames_lower_info_label
->get_text () != _("none")) {
519 frames_lower_info_label
->set_text(_("none"));
522 sprintf (buf
, "%-6.4f", vid_pullup
);
523 if (frames_lower_info_label
->get_text() != buf
) {
524 frames_lower_info_label
->set_text (buf
);
531 AudioClock::set_minsec (nframes_t when
, bool force
)
540 hrs
= (int) floor (left
/ (_session
->frame_rate() * 60.0f
* 60.0f
));
541 left
-= (nframes_t
) floor (hrs
* _session
->frame_rate() * 60.0f
* 60.0f
);
542 mins
= (int) floor (left
/ (_session
->frame_rate() * 60.0f
));
543 left
-= (nframes_t
) floor (mins
* _session
->frame_rate() * 60.0f
);
544 secs
= left
/ (float) _session
->frame_rate();
546 if (force
|| hrs
!= ms_last_hrs
) {
547 sprintf (buf
, "%02d", hrs
);
548 ms_hours_label
.set_text (buf
);
552 if (force
|| mins
!= ms_last_mins
) {
553 sprintf (buf
, "%02d", mins
);
554 ms_minutes_label
.set_text (buf
);
558 if (force
|| secs
!= ms_last_secs
) {
559 sprintf (buf
, "%06.3f", secs
);
560 ms_seconds_label
.set_text (buf
);
566 AudioClock::set_timecode (nframes_t when
, bool force
)
569 Timecode::Time timecode
;
572 _session
->timecode_duration (when
, timecode
);
574 _session
->timecode_time (when
, timecode
);
577 if (force
|| timecode
.hours
!= last_hrs
|| timecode
.negative
!= last_negative
) {
578 if (timecode
.negative
) {
579 sprintf (buf
, "-%02" PRIu32
, timecode
.hours
);
581 sprintf (buf
, " %02" PRIu32
, timecode
.hours
);
583 hours_label
.set_text (buf
);
584 last_hrs
= timecode
.hours
;
585 last_negative
= timecode
.negative
;
588 if (force
|| timecode
.minutes
!= last_mins
) {
589 sprintf (buf
, "%02" PRIu32
, timecode
.minutes
);
590 minutes_label
.set_text (buf
);
591 last_mins
= timecode
.minutes
;
594 if (force
|| timecode
.seconds
!= last_secs
) {
595 sprintf (buf
, "%02" PRIu32
, timecode
.seconds
);
596 seconds_label
.set_text (buf
);
597 last_secs
= timecode
.seconds
;
600 if (force
|| timecode
.frames
!= last_frames
) {
601 sprintf (buf
, "%02" PRIu32
, timecode
.frames
);
602 frames_label
.set_text (buf
);
603 last_frames
= timecode
.frames
;
606 if (timecode_upper_info_label
) {
607 double timecode_frames
= _session
->timecode_frames_per_second();
609 if ( fmod(timecode_frames
, 1.0) == 0.0) {
610 sprintf (buf
, "%u", int (timecode_frames
));
612 sprintf (buf
, "%.2f", timecode_frames
);
615 if (timecode_upper_info_label
->get_text() != buf
) {
616 timecode_upper_info_label
->set_text (buf
);
619 if ((fabs(timecode_frames
- 29.97) < 0.0001) || timecode_frames
== 30) {
620 if (_session
->timecode_drop_frames()) {
623 sprintf (buf
, "NDF");
626 // there is no drop frame alternative
630 if (timecode_lower_info_label
->get_text() != buf
) {
631 timecode_lower_info_label
->set_text (buf
);
637 AudioClock::set_bbt (nframes_t when
, bool force
)
642 /* handle a common case */
649 _session
->tempo_map().bbt_time (when
, bbt
);
654 _session
->tempo_map().bbt_time (when
, bbt
);
657 sprintf (buf
, "%03" PRIu32
, bbt
.bars
);
658 if (force
|| bars_label
.get_text () != buf
) {
659 bars_label
.set_text (buf
);
661 sprintf (buf
, "%02" PRIu32
, bbt
.beats
);
662 if (force
|| beats_label
.get_text () != buf
) {
663 beats_label
.set_text (buf
);
665 sprintf (buf
, "%04" PRIu32
, bbt
.ticks
);
666 if (force
|| ticks_label
.get_text () != buf
) {
667 ticks_label
.set_text (buf
);
670 if (bbt_upper_info_label
) {
673 if (bbt_reference_time
< 0) {
676 pos
= bbt_reference_time
;
679 TempoMetric
m (_session
->tempo_map().metric_at (pos
));
681 sprintf (buf
, "%-5.2f", m
.tempo().beats_per_minute());
682 if (bbt_lower_info_label
->get_text() != buf
) {
683 bbt_lower_info_label
->set_text (buf
);
685 sprintf (buf
, "%g|%g", m
.meter().beats_per_bar(), m
.meter().note_divisor());
686 if (bbt_upper_info_label
->get_text() != buf
) {
687 bbt_upper_info_label
->set_text (buf
);
693 AudioClock::set_session (Session
*s
)
695 SessionHandlePtr::set_session (s
);
700 XMLNode
* node
= _session
->extra_xml (X_("ClockModes"));
701 AudioClock::Mode amode
;
704 if ((prop
= node
->property (_name
)) != 0) {
705 amode
= AudioClock::Mode (string_2_enum (prop
->value(), amode
));
710 set (last_when
, true);
719 hours_ebox
.grab_focus ();
723 bars_ebox
.grab_focus ();
727 ms_hours_ebox
.grab_focus ();
731 frames_ebox
.grab_focus ();
741 AudioClock::field_key_press_event (GdkEventKey */
*ev*/
, Field
/*field*/)
743 /* all key activity is handled on key release */
748 AudioClock::field_key_release_event (GdkEventKey
*ev
, Field field
)
753 bool move_on
= false;
757 label
= &hours_label
;
759 case Timecode_Minutes
:
760 label
= &minutes_label
;
762 case Timecode_Seconds
:
763 label
= &seconds_label
;
765 case Timecode_Frames
:
766 label
= &frames_label
;
770 label
= &audio_frames_label
;
774 label
= &ms_hours_label
;
777 label
= &ms_minutes_label
;
780 label
= &ms_seconds_label
;
787 label
= &beats_label
;
790 label
= &ticks_label
;
796 switch (ev
->keyval
) {
840 if (_mode
== MinSec
&& field
== MS_Seconds
) {
855 clock_base
.grab_focus ();
856 ChangeAborted(); /* EMIT SIGNAL */
865 if (key_entry_state
== 0) {
867 /* initialize with a fresh new string */
869 if (field
!= AudioFrames
) {
870 for (uint32_t xn
= 0; xn
< field_length
[field
] - 1; ++xn
) {
879 string existing
= label
->get_text();
880 if (existing
.length() >= field_length
[field
]) {
881 new_text
= existing
.substr (1, field_length
[field
] - 1);
883 new_text
= existing
.substr (0, field_length
[field
] - 1);
887 new_text
+= new_char
;
888 label
->set_text (new_text
);
892 if (key_entry_state
== field_length
[field
]) {
898 if (key_entry_state
) {
902 case Timecode_Minutes
:
903 case Timecode_Seconds
:
904 case Timecode_Frames
:
905 // Check Timecode fields for sanity (may also adjust fields)
906 timecode_sanitize_display();
911 // Bars should never be, unless this clock is for a duration
912 if (atoi(bars_label
.get_text()) == 0 && !is_duration
) {
913 bars_label
.set_text("001");
915 // beats should never be 0, unless this clock is for a duration
916 if (atoi(beats_label
.get_text()) == 0 && !is_duration
) {
917 beats_label
.set_text("01");
924 ValueChanged(); /* EMIT_SIGNAL */
927 /* move on to the next field.
935 minutes_ebox
.grab_focus ();
937 case Timecode_Minutes
:
938 seconds_ebox
.grab_focus ();
940 case Timecode_Seconds
:
941 frames_ebox
.grab_focus ();
943 case Timecode_Frames
:
944 clock_base
.grab_focus ();
949 clock_base
.grab_focus ();
955 ms_minutes_ebox
.grab_focus ();
958 ms_seconds_ebox
.grab_focus ();
961 clock_base
.grab_focus ();
967 beats_ebox
.grab_focus ();
970 ticks_ebox
.grab_focus ();
973 clock_base
.grab_focus ();
982 //if user hit Enter, lose focus
983 switch (ev
->keyval
) {
986 clock_base
.grab_focus ();
993 AudioClock::field_focus_in_event (GdkEventFocus */
*ev*/
, Field field
)
997 Keyboard::magic_widget_grab_focus ();
1000 case Timecode_Hours
:
1001 hours_ebox
.set_flags (Gtk::HAS_FOCUS
);
1002 hours_ebox
.set_state (Gtk::STATE_ACTIVE
);
1004 case Timecode_Minutes
:
1005 minutes_ebox
.set_flags (Gtk::HAS_FOCUS
);
1006 minutes_ebox
.set_state (Gtk::STATE_ACTIVE
);
1008 case Timecode_Seconds
:
1009 seconds_ebox
.set_flags (Gtk::HAS_FOCUS
);
1010 seconds_ebox
.set_state (Gtk::STATE_ACTIVE
);
1012 case Timecode_Frames
:
1013 frames_ebox
.set_flags (Gtk::HAS_FOCUS
);
1014 frames_ebox
.set_state (Gtk::STATE_ACTIVE
);
1018 audio_frames_ebox
.set_flags (Gtk::HAS_FOCUS
);
1019 audio_frames_ebox
.set_state (Gtk::STATE_ACTIVE
);
1023 ms_hours_ebox
.set_flags (Gtk::HAS_FOCUS
);
1024 ms_hours_ebox
.set_state (Gtk::STATE_ACTIVE
);
1027 ms_minutes_ebox
.set_flags (Gtk::HAS_FOCUS
);
1028 ms_minutes_ebox
.set_state (Gtk::STATE_ACTIVE
);
1031 ms_seconds_ebox
.set_flags (Gtk::HAS_FOCUS
);
1032 ms_seconds_ebox
.set_state (Gtk::STATE_ACTIVE
);
1035 bars_ebox
.set_flags (Gtk::HAS_FOCUS
);
1036 bars_ebox
.set_state (Gtk::STATE_ACTIVE
);
1039 beats_ebox
.set_flags (Gtk::HAS_FOCUS
);
1040 beats_ebox
.set_state (Gtk::STATE_ACTIVE
);
1043 ticks_ebox
.set_flags (Gtk::HAS_FOCUS
);
1044 ticks_ebox
.set_state (Gtk::STATE_ACTIVE
);
1052 AudioClock::field_focus_out_event (GdkEventFocus */
*ev*/
, Field field
)
1056 case Timecode_Hours
:
1057 hours_ebox
.unset_flags (Gtk::HAS_FOCUS
);
1058 hours_ebox
.set_state (Gtk::STATE_NORMAL
);
1060 case Timecode_Minutes
:
1061 minutes_ebox
.unset_flags (Gtk::HAS_FOCUS
);
1062 minutes_ebox
.set_state (Gtk::STATE_NORMAL
);
1064 case Timecode_Seconds
:
1065 seconds_ebox
.unset_flags (Gtk::HAS_FOCUS
);
1066 seconds_ebox
.set_state (Gtk::STATE_NORMAL
);
1068 case Timecode_Frames
:
1069 frames_ebox
.unset_flags (Gtk::HAS_FOCUS
);
1070 frames_ebox
.set_state (Gtk::STATE_NORMAL
);
1074 audio_frames_ebox
.unset_flags (Gtk::HAS_FOCUS
);
1075 audio_frames_ebox
.set_state (Gtk::STATE_NORMAL
);
1079 ms_hours_ebox
.unset_flags (Gtk::HAS_FOCUS
);
1080 ms_hours_ebox
.set_state (Gtk::STATE_NORMAL
);
1083 ms_minutes_ebox
.unset_flags (Gtk::HAS_FOCUS
);
1084 ms_minutes_ebox
.set_state (Gtk::STATE_NORMAL
);
1087 ms_seconds_ebox
.unset_flags (Gtk::HAS_FOCUS
);
1088 ms_seconds_ebox
.set_state (Gtk::STATE_NORMAL
);
1092 bars_ebox
.unset_flags (Gtk::HAS_FOCUS
);
1093 bars_ebox
.set_state (Gtk::STATE_NORMAL
);
1096 beats_ebox
.unset_flags (Gtk::HAS_FOCUS
);
1097 beats_ebox
.set_state (Gtk::STATE_NORMAL
);
1100 ticks_ebox
.unset_flags (Gtk::HAS_FOCUS
);
1101 ticks_ebox
.set_state (Gtk::STATE_NORMAL
);
1105 Keyboard::magic_widget_drop_focus ();
1111 AudioClock::field_button_release_event (GdkEventButton
*ev
, Field field
)
1114 cerr
<< "button event on clock but we are dragging\n";
1115 gdk_pointer_ungrab (GDK_CURRENT_TIME
);
1117 if (ev
->y
> drag_start_y
+1 || ev
->y
< drag_start_y
-1 || Keyboard::modifier_state_equals (ev
->state
, Keyboard::TertiaryModifier
)){
1118 // we actually dragged so return without setting editing focus, or we shift clicked
1124 if (ops_menu
== 0) {
1127 ops_menu
->popup (1, ev
->time
);
1131 if (Keyboard::is_context_menu_event (ev
)) {
1132 cerr
<< "Context menu event on clock\n";
1133 if (ops_menu
== 0) {
1136 ops_menu
->popup (1, ev
->time
);
1140 switch (ev
->button
) {
1143 case Timecode_Hours
:
1144 hours_ebox
.grab_focus();
1146 case Timecode_Minutes
:
1147 minutes_ebox
.grab_focus();
1149 case Timecode_Seconds
:
1150 seconds_ebox
.grab_focus();
1152 case Timecode_Frames
:
1153 frames_ebox
.grab_focus();
1157 audio_frames_ebox
.grab_focus();
1161 ms_hours_ebox
.grab_focus();
1164 ms_minutes_ebox
.grab_focus();
1167 ms_seconds_ebox
.grab_focus();
1171 bars_ebox
.grab_focus ();
1174 beats_ebox
.grab_focus ();
1177 ticks_ebox
.grab_focus ();
1190 AudioClock::field_button_press_event (GdkEventButton
*ev
, Field
/*field*/)
1192 if (_session
== 0) {
1196 nframes_t frames
= 0;
1198 switch (ev
->button
) {
1200 if (Keyboard::modifier_state_equals (ev
->state
, Keyboard::TertiaryModifier
)) {
1202 ValueChanged (); /* EMIT_SIGNAL */
1205 /* make absolutely sure that the pointer is grabbed */
1206 gdk_pointer_grab(ev
->window
,false ,
1207 GdkEventMask( Gdk::POINTER_MOTION_MASK
| Gdk::BUTTON_PRESS_MASK
|Gdk::BUTTON_RELEASE_MASK
),
1208 NULL
,NULL
,ev
->time
);
1211 drag_start_y
= ev
->y
;
1216 if (Keyboard::modifier_state_equals (ev
->state
, Keyboard::TertiaryModifier
)) {
1218 ValueChanged (); /* EMIT_SIGNAL */
1223 /* used for context sensitive menu */
1236 AudioClock::field_button_scroll_event (GdkEventScroll
*ev
, Field field
)
1238 if (_session
== 0) {
1242 nframes_t frames
= 0;
1244 switch (ev
->direction
) {
1247 frames
= get_frames (field
);
1249 if (Keyboard::modifier_state_equals (ev
->state
, Keyboard::PrimaryModifier
)) {
1252 set (current_time() + frames
, true);
1253 ValueChanged (); /* EMIT_SIGNAL */
1257 case GDK_SCROLL_DOWN
:
1258 frames
= get_frames (field
);
1260 if (Keyboard::modifier_state_equals (ev
->state
, Keyboard::PrimaryModifier
)) {
1264 if ((double)current_time() - (double)frames
< 0.0) {
1267 set (current_time() - frames
, true);
1270 ValueChanged (); /* EMIT_SIGNAL */
1283 AudioClock::field_motion_notify_event (GdkEventMotion
*ev
, Field field
)
1285 if (_session
== 0 || !dragging
) {
1289 float pixel_frame_scale_factor
= 0.2f
;
1292 if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
1293 pixel_frame_scale_factor = 0.1f;
1297 if (Keyboard::modifier_state_contains (ev->state,
1298 Keyboard::PrimaryModifier|Keyboard::SecondaryModifier)) {
1300 pixel_frame_scale_factor = 0.025f;
1303 double y_delta
= ev
->y
- drag_y
;
1305 drag_accum
+= y_delta
*pixel_frame_scale_factor
;
1309 if (trunc(drag_accum
) != 0) {
1314 dir
= (drag_accum
< 0 ? 1:-1);
1315 pos
= current_time();
1316 frames
= get_frames (field
,pos
,dir
);
1318 if (frames
!= 0 && frames
* drag_accum
< current_time()) {
1320 set ((nframes_t
) floor (pos
- drag_accum
* frames
), false); // minus because up is negative in computer-land
1328 ValueChanged(); /* EMIT_SIGNAL */
1337 AudioClock::get_frames (Field field
,nframes_t pos
,int dir
)
1340 nframes_t frames
= 0;
1343 case Timecode_Hours
:
1344 frames
= (nframes_t
) floor (3600.0 * _session
->frame_rate());
1346 case Timecode_Minutes
:
1347 frames
= (nframes_t
) floor (60.0 * _session
->frame_rate());
1349 case Timecode_Seconds
:
1350 frames
= _session
->frame_rate();
1352 case Timecode_Frames
:
1353 frames
= (nframes_t
) floor (_session
->frame_rate() / _session
->timecode_frames_per_second());
1361 frames
= (nframes_t
) floor (3600.0 * _session
->frame_rate());
1364 frames
= (nframes_t
) floor (60.0 * _session
->frame_rate());
1367 frames
= _session
->frame_rate();
1374 frames
= _session
->tempo_map().bbt_duration_at(pos
,bbt
,dir
);
1380 frames
= _session
->tempo_map().bbt_duration_at(pos
,bbt
,dir
);
1386 frames
= _session
->tempo_map().bbt_duration_at(pos
,bbt
,dir
);
1394 AudioClock::current_time (nframes_t pos
) const
1400 ret
= timecode_frame_from_display ();
1403 ret
= bbt_frame_from_display (pos
);
1407 ret
= minsec_frame_from_display ();
1411 ret
= audio_frame_from_display ();
1422 AudioClock::current_duration (nframes_t pos
) const
1428 ret
= timecode_frame_from_display ();
1431 ret
= bbt_frame_duration_from_display (pos
);
1435 ret
= minsec_frame_from_display ();
1439 ret
= audio_frame_from_display ();
1450 AudioClock::timecode_sanitize_display()
1452 // Check Timecode fields for sanity, possibly adjusting values
1453 if (atoi(minutes_label
.get_text()) > 59) {
1454 minutes_label
.set_text("59");
1457 if (atoi(seconds_label
.get_text()) > 59) {
1458 seconds_label
.set_text("59");
1461 switch ((long)rint(_session
->timecode_frames_per_second())) {
1463 if (atoi(frames_label
.get_text()) > 23) {
1464 frames_label
.set_text("23");
1468 if (atoi(frames_label
.get_text()) > 24) {
1469 frames_label
.set_text("24");
1473 if (atoi(frames_label
.get_text()) > 29) {
1474 frames_label
.set_text("29");
1481 if (_session
->timecode_drop_frames()) {
1482 if ((atoi(minutes_label
.get_text()) % 10) && (atoi(seconds_label
.get_text()) == 0) && (atoi(frames_label
.get_text()) < 2)) {
1483 frames_label
.set_text("02");
1489 AudioClock::timecode_frame_from_display () const
1491 if (_session
== 0) {
1495 Timecode::Time timecode
;
1498 timecode
.hours
= atoi (hours_label
.get_text());
1499 timecode
.minutes
= atoi (minutes_label
.get_text());
1500 timecode
.seconds
= atoi (seconds_label
.get_text());
1501 timecode
.frames
= atoi (frames_label
.get_text());
1502 timecode
.rate
= _session
->timecode_frames_per_second();
1503 timecode
.drop
= _session
->timecode_drop_frames();
1505 _session
->timecode_to_sample( timecode
, sample
, false /* use_offset */, false /* use_subframes */ );
1509 #define Timecode_SAMPLE_TEST_1
1510 #define Timecode_SAMPLE_TEST_2
1511 #define Timecode_SAMPLE_TEST_3
1512 #define Timecode_SAMPLE_TEST_4
1513 #define Timecode_SAMPLE_TEST_5
1514 #define Timecode_SAMPLE_TEST_6
1515 #define Timecode_SAMPLE_TEST_7
1517 // Testcode for timecode<->sample conversions (P.S.)
1518 Timecode::Time timecode1
;
1520 nframes_t oldsample
= 0;
1521 Timecode::Time timecode2
;
1522 nframes_t sample_increment
;
1524 sample_increment
= (long)rint(_session
->frame_rate() / _session
->timecode_frames_per_second
);
1526 #ifdef Timecode_SAMPLE_TEST_1
1527 // Test 1: use_offset = false, use_subframes = false
1528 cout
<< "use_offset = false, use_subframes = false" << endl
;
1529 for (int i
= 0; i
< 108003; i
++) {
1530 _session
->timecode_to_sample( timecode1
, sample1
, false /* use_offset */, false /* use_subframes */ );
1531 _session
->sample_to_timecode( sample1
, timecode2
, false /* use_offset */, false /* use_subframes */ );
1533 if ((i
> 0) && ( ((sample1
- oldsample
) != sample_increment
) && ((sample1
- oldsample
) != (sample_increment
+ 1)) && ((sample1
- oldsample
) != (sample_increment
- 1)))) {
1534 cout
<< "ERROR: sample increment not right: " << (sample1
- oldsample
) << " != " << sample_increment
<< endl
;
1535 cout
<< "timecode1: " << timecode1
.hours
<< ":" << timecode1
.minutes
<< ":" << timecode1
.seconds
<< ":" << timecode1
.frames
<< "::" << timecode1
.subframes
<< " -> ";
1536 cout
<< "sample: " << sample1
<< endl
;
1537 cout
<< "sample: " << sample1
<< " -> ";
1538 cout
<< "timecode2: " << timecode2
.hours
<< ":" << timecode2
.minutes
<< ":" << timecode2
.seconds
<< ":" << timecode2
.frames
<< "::" << timecode2
.subframes
<< endl
;
1542 if (timecode2
.hours
!= timecode1
.hours
|| timecode2
.minutes
!= timecode1
.minutes
|| timecode2
.seconds
!= timecode2
.seconds
|| timecode2
.frames
!= timecode1
.frames
) {
1543 cout
<< "ERROR: timecode2 not equal timecode1" << endl
;
1544 cout
<< "timecode1: " << timecode1
.hours
<< ":" << timecode1
.minutes
<< ":" << timecode1
.seconds
<< ":" << timecode1
.frames
<< "::" << timecode1
.subframes
<< " -> ";
1545 cout
<< "sample: " << sample1
<< endl
;
1546 cout
<< "sample: " << sample1
<< " -> ";
1547 cout
<< "timecode2: " << timecode2
.hours
<< ":" << timecode2
.minutes
<< ":" << timecode2
.seconds
<< ":" << timecode2
.frames
<< "::" << timecode2
.subframes
<< endl
;
1550 oldsample
= sample1
;
1551 _session
->timecode_increment( timecode1
);
1554 cout
<< "sample_increment: " << sample_increment
<< endl
;
1555 cout
<< "sample: " << sample1
<< " -> ";
1556 cout
<< "timecode: " << timecode2
.hours
<< ":" << timecode2
.minutes
<< ":" << timecode2
.seconds
<< ":" << timecode2
.frames
<< "::" << timecode2
.subframes
<< endl
;
1559 #ifdef Timecode_SAMPLE_TEST_2
1560 // Test 2: use_offset = true, use_subframes = false
1561 cout
<< "use_offset = true, use_subframes = false" << endl
;
1563 timecode1
.hours
= 0;
1564 timecode1
.minutes
= 0;
1565 timecode1
.seconds
= 0;
1566 timecode1
.frames
= 0;
1567 timecode1
.subframes
= 0;
1568 sample1
= oldsample
= 0;
1570 _session
->sample_to_timecode( sample1
, timecode1
, true /* use_offset */, false /* use_subframes */ );
1571 cout
<< "Starting at sample: " << sample1
<< " -> ";
1572 cout
<< "timecode: " << (timecode1
.negative
? "-" : "") << timecode1
.hours
<< ":" << timecode1
.minutes
<< ":" << timecode1
.seconds
<< ":" << timecode1
.frames
<< "::" << timecode1
.subframes
<< endl
;
1574 for (int i
= 0; i
< 108003; i
++) {
1575 _session
->timecode_to_sample( timecode1
, sample1
, true /* use_offset */, false /* use_subframes */ );
1576 _session
->sample_to_timecode( sample1
, timecode2
, true /* use_offset */, false /* use_subframes */ );
1578 // cout << "timecode: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << " -> ";
1579 // cout << "sample: " << sample1 << endl;
1580 // cout << "sample: " << sample1 << " -> ";
1581 // cout << "timecode: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
1583 if ((i
> 0) && ( ((sample1
- oldsample
) != sample_increment
) && ((sample1
- oldsample
) != (sample_increment
+ 1)) && ((sample1
- oldsample
) != (sample_increment
- 1)))) {
1584 cout
<< "ERROR: sample increment not right: " << (sample1
- oldsample
) << " != " << sample_increment
<< endl
;
1585 cout
<< "timecode1: " << (timecode1
.negative
? "-" : "") << timecode1
.hours
<< ":" << timecode1
.minutes
<< ":" << timecode1
.seconds
<< ":" << timecode1
.frames
<< "::" << timecode1
.subframes
<< " -> ";
1586 cout
<< "sample: " << sample1
<< endl
;
1587 cout
<< "sample: " << sample1
<< " -> ";
1588 cout
<< "timecode2: " << (timecode2
.negative
? "-" : "") << timecode2
.hours
<< ":" << timecode2
.minutes
<< ":" << timecode2
.seconds
<< ":" << timecode2
.frames
<< "::" << timecode2
.subframes
<< endl
;
1592 if (timecode2
.hours
!= timecode1
.hours
|| timecode2
.minutes
!= timecode1
.minutes
|| timecode2
.seconds
!= timecode2
.seconds
|| timecode2
.frames
!= timecode1
.frames
) {
1593 cout
<< "ERROR: timecode2 not equal timecode1" << endl
;
1594 cout
<< "timecode1: " << (timecode1
.negative
? "-" : "") << timecode1
.hours
<< ":" << timecode1
.minutes
<< ":" << timecode1
.seconds
<< ":" << timecode1
.frames
<< "::" << timecode1
.subframes
<< " -> ";
1595 cout
<< "sample: " << sample1
<< endl
;
1596 cout
<< "sample: " << sample1
<< " -> ";
1597 cout
<< "timecode2: " << (timecode2
.negative
? "-" : "") << timecode2
.hours
<< ":" << timecode2
.minutes
<< ":" << timecode2
.seconds
<< ":" << timecode2
.frames
<< "::" << timecode2
.subframes
<< endl
;
1600 oldsample
= sample1
;
1601 _session
->timecode_increment( timecode1
);
1604 cout
<< "sample_increment: " << sample_increment
<< endl
;
1605 cout
<< "sample: " << sample1
<< " -> ";
1606 cout
<< "timecode: " << (timecode2
.negative
? "-" : "") << timecode2
.hours
<< ":" << timecode2
.minutes
<< ":" << timecode2
.seconds
<< ":" << timecode2
.frames
<< "::" << timecode2
.subframes
<< endl
;
1609 #ifdef Timecode_SAMPLE_TEST_3
1610 // Test 3: use_offset = true, use_subframes = false, decrement
1611 cout
<< "use_offset = true, use_subframes = false, decrement" << endl
;
1613 _session
->sample_to_timecode( sample1
, timecode1
, true /* use_offset */, false /* use_subframes */ );
1614 cout
<< "Starting at sample: " << sample1
<< " -> ";
1615 cout
<< "timecode: " << (timecode1
.negative
? "-" : "") << timecode1
.hours
<< ":" << timecode1
.minutes
<< ":" << timecode1
.seconds
<< ":" << timecode1
.frames
<< "::" << timecode1
.subframes
<< endl
;
1617 for (int i
= 0; i
< 108003; i
++) {
1618 _session
->timecode_to_sample( timecode1
, sample1
, true /* use_offset */, false /* use_subframes */ );
1619 _session
->sample_to_timecode( sample1
, timecode2
, true /* use_offset */, false /* use_subframes */ );
1621 // cout << "timecode: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << " -> ";
1622 // cout << "sample: " << sample1 << endl;
1623 // cout << "sample: " << sample1 << " -> ";
1624 // cout << "timecode: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
1626 if ((i
> 0) && ( ((oldsample
- sample1
) != sample_increment
) && ((oldsample
- sample1
) != (sample_increment
+ 1)) && ((oldsample
- sample1
) != (sample_increment
- 1)))) {
1627 cout
<< "ERROR: sample increment not right: " << (oldsample
- sample1
) << " != " << sample_increment
<< endl
;
1628 cout
<< "timecode1: " << (timecode1
.negative
? "-" : "") << timecode1
.hours
<< ":" << timecode1
.minutes
<< ":" << timecode1
.seconds
<< ":" << timecode1
.frames
<< "::" << timecode1
.subframes
<< " -> ";
1629 cout
<< "sample: " << sample1
<< endl
;
1630 cout
<< "sample: " << sample1
<< " -> ";
1631 cout
<< "timecode2: " << (timecode2
.negative
? "-" : "") << timecode2
.hours
<< ":" << timecode2
.minutes
<< ":" << timecode2
.seconds
<< ":" << timecode2
.frames
<< "::" << timecode2
.subframes
<< endl
;
1635 if (timecode2
.hours
!= timecode1
.hours
|| timecode2
.minutes
!= timecode1
.minutes
|| timecode2
.seconds
!= timecode2
.seconds
|| timecode2
.frames
!= timecode1
.frames
) {
1636 cout
<< "ERROR: timecode2 not equal timecode1" << endl
;
1637 cout
<< "timecode1: " << (timecode1
.negative
? "-" : "") << timecode1
.hours
<< ":" << timecode1
.minutes
<< ":" << timecode1
.seconds
<< ":" << timecode1
.frames
<< "::" << timecode1
.subframes
<< " -> ";
1638 cout
<< "sample: " << sample1
<< endl
;
1639 cout
<< "sample: " << sample1
<< " -> ";
1640 cout
<< "timecode2: " << (timecode2
.negative
? "-" : "") << timecode2
.hours
<< ":" << timecode2
.minutes
<< ":" << timecode2
.seconds
<< ":" << timecode2
.frames
<< "::" << timecode2
.subframes
<< endl
;
1643 oldsample
= sample1
;
1644 _session
->timecode_decrement( timecode1
);
1647 cout
<< "sample_decrement: " << sample_increment
<< endl
;
1648 cout
<< "sample: " << sample1
<< " -> ";
1649 cout
<< "timecode: " << (timecode2
.negative
? "-" : "") << timecode2
.hours
<< ":" << timecode2
.minutes
<< ":" << timecode2
.seconds
<< ":" << timecode2
.frames
<< "::" << timecode2
.subframes
<< endl
;
1653 #ifdef Timecode_SAMPLE_TEST_4
1654 // Test 4: use_offset = true, use_subframes = true
1655 cout
<< "use_offset = true, use_subframes = true" << endl
;
1657 for (long sub
= 5; sub
< 80; sub
+= 5) {
1658 timecode1
.hours
= 0;
1659 timecode1
.minutes
= 0;
1660 timecode1
.seconds
= 0;
1661 timecode1
.frames
= 0;
1662 timecode1
.subframes
= 0;
1663 sample1
= oldsample
= (sample_increment
* sub
) / 80;
1665 _session
->sample_to_timecode( sample1
, timecode1
, true /* use_offset */, true /* use_subframes */ );
1667 cout
<< "starting at sample: " << sample1
<< " -> ";
1668 cout
<< "timecode: " << (timecode1
.negative
? "-" : "") << timecode1
.hours
<< ":" << timecode1
.minutes
<< ":" << timecode1
.seconds
<< ":" << timecode1
.frames
<< "::" << timecode1
.subframes
<< endl
;
1670 for (int i
= 0; i
< 108003; i
++) {
1671 _session
->timecode_to_sample( timecode1
, sample1
, true /* use_offset */, true /* use_subframes */ );
1672 _session
->sample_to_timecode( sample1
, timecode2
, true /* use_offset */, true /* use_subframes */ );
1674 if ((i
> 0) && ( ((sample1
- oldsample
) != sample_increment
) && ((sample1
- oldsample
) != (sample_increment
+ 1)) && ((sample1
- oldsample
) != (sample_increment
- 1)))) {
1675 cout
<< "ERROR: sample increment not right: " << (sample1
- oldsample
) << " != " << sample_increment
<< endl
;
1676 cout
<< "timecode1: " << (timecode1
.negative
? "-" : "") << timecode1
.hours
<< ":" << timecode1
.minutes
<< ":" << timecode1
.seconds
<< ":" << timecode1
.frames
<< "::" << timecode1
.subframes
<< " -> ";
1677 cout
<< "sample: " << sample1
<< endl
;
1678 cout
<< "sample: " << sample1
<< " -> ";
1679 cout
<< "timecode2: " << (timecode2
.negative
? "-" : "") << timecode2
.hours
<< ":" << timecode2
.minutes
<< ":" << timecode2
.seconds
<< ":" << timecode2
.frames
<< "::" << timecode2
.subframes
<< endl
;
1683 if (timecode2
.hours
!= timecode1
.hours
|| timecode2
.minutes
!= timecode1
.minutes
|| timecode2
.seconds
!= timecode2
.seconds
|| timecode2
.frames
!= timecode1
.frames
|| timecode2
.subframes
!= timecode1
.subframes
) {
1684 cout
<< "ERROR: timecode2 not equal timecode1" << endl
;
1685 cout
<< "timecode1: " << (timecode1
.negative
? "-" : "") << timecode1
.hours
<< ":" << timecode1
.minutes
<< ":" << timecode1
.seconds
<< ":" << timecode1
.frames
<< "::" << timecode1
.subframes
<< " -> ";
1686 cout
<< "sample: " << sample1
<< endl
;
1687 cout
<< "sample: " << sample1
<< " -> ";
1688 cout
<< "timecode2: " << (timecode2
.negative
? "-" : "") << timecode2
.hours
<< ":" << timecode2
.minutes
<< ":" << timecode2
.seconds
<< ":" << timecode2
.frames
<< "::" << timecode2
.subframes
<< endl
;
1691 oldsample
= sample1
;
1692 _session
->timecode_increment( timecode1
);
1695 cout
<< "sample_increment: " << sample_increment
<< endl
;
1696 cout
<< "sample: " << sample1
<< " -> ";
1697 cout
<< "timecode: " << (timecode2
.negative
? "-" : "") << timecode2
.hours
<< ":" << timecode2
.minutes
<< ":" << timecode2
.seconds
<< ":" << timecode2
.frames
<< "::" << timecode2
.subframes
<< endl
;
1699 for (int i
= 0; i
< 108003; i
++) {
1700 _session
->timecode_to_sample( timecode1
, sample1
, true /* use_offset */, true /* use_subframes */ );
1701 _session
->sample_to_timecode( sample1
, timecode2
, true /* use_offset */, true /* use_subframes */ );
1703 if ((i
> 0) && ( ((oldsample
- sample1
) != sample_increment
) && ((oldsample
- sample1
) != (sample_increment
+ 1)) && ((oldsample
- sample1
) != (sample_increment
- 1)))) {
1704 cout
<< "ERROR: sample increment not right: " << (oldsample
- sample1
) << " != " << sample_increment
<< endl
;
1705 cout
<< "timecode1: " << (timecode1
.negative
? "-" : "") << timecode1
.hours
<< ":" << timecode1
.minutes
<< ":" << timecode1
.seconds
<< ":" << timecode1
.frames
<< "::" << timecode1
.subframes
<< " -> ";
1706 cout
<< "sample: " << sample1
<< endl
;
1707 cout
<< "sample: " << sample1
<< " -> ";
1708 cout
<< "timecode2: " << (timecode2
.negative
? "-" : "") << timecode2
.hours
<< ":" << timecode2
.minutes
<< ":" << timecode2
.seconds
<< ":" << timecode2
.frames
<< "::" << timecode2
.subframes
<< endl
;
1712 if (timecode2
.hours
!= timecode1
.hours
|| timecode2
.minutes
!= timecode1
.minutes
|| timecode2
.seconds
!= timecode2
.seconds
|| timecode2
.frames
!= timecode1
.frames
|| timecode2
.subframes
!= timecode1
.subframes
) {
1713 cout
<< "ERROR: timecode2 not equal timecode1" << endl
;
1714 cout
<< "timecode1: " << (timecode1
.negative
? "-" : "") << timecode1
.hours
<< ":" << timecode1
.minutes
<< ":" << timecode1
.seconds
<< ":" << timecode1
.frames
<< "::" << timecode1
.subframes
<< " -> ";
1715 cout
<< "sample: " << sample1
<< endl
;
1716 cout
<< "sample: " << sample1
<< " -> ";
1717 cout
<< "timecode2: " << (timecode2
.negative
? "-" : "") << timecode2
.hours
<< ":" << timecode2
.minutes
<< ":" << timecode2
.seconds
<< ":" << timecode2
.frames
<< "::" << timecode2
.subframes
<< endl
;
1720 oldsample
= sample1
;
1721 _session
->timecode_decrement( timecode1
);
1724 cout
<< "sample_decrement: " << sample_increment
<< endl
;
1725 cout
<< "sample: " << sample1
<< " -> ";
1726 cout
<< "timecode: " << (timecode2
.negative
? "-" : "") << timecode2
.hours
<< ":" << timecode2
.minutes
<< ":" << timecode2
.seconds
<< ":" << timecode2
.frames
<< "::" << timecode2
.subframes
<< endl
;
1731 #ifdef Timecode_SAMPLE_TEST_5
1732 // Test 5: use_offset = true, use_subframes = false, increment seconds
1733 cout
<< "use_offset = true, use_subframes = false, increment seconds" << endl
;
1735 timecode1
.hours
= 0;
1736 timecode1
.minutes
= 0;
1737 timecode1
.seconds
= 0;
1738 timecode1
.frames
= 0;
1739 timecode1
.subframes
= 0;
1740 sample1
= oldsample
= 0;
1741 sample_increment
= _session
->frame_rate();
1743 _session
->sample_to_timecode( sample1
, timecode1
, true /* use_offset */, false /* use_subframes */ );
1744 cout
<< "Starting at sample: " << sample1
<< " -> ";
1745 cout
<< "timecode: " << (timecode1
.negative
? "-" : "") << timecode1
.hours
<< ":" << timecode1
.minutes
<< ":" << timecode1
.seconds
<< ":" << timecode1
.frames
<< "::" << timecode1
.subframes
<< endl
;
1747 for (int i
= 0; i
< 3600; i
++) {
1748 _session
->timecode_to_sample( timecode1
, sample1
, true /* use_offset */, false /* use_subframes */ );
1749 _session
->sample_to_timecode( sample1
, timecode2
, true /* use_offset */, false /* use_subframes */ );
1751 // cout << "timecode: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << " -> ";
1752 // cout << "sample: " << sample1 << endl;
1753 // cout << "sample: " << sample1 << " -> ";
1754 // cout << "timecode: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
1756 // if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1758 // cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1762 if (timecode2
.hours
!= timecode1
.hours
|| timecode2
.minutes
!= timecode1
.minutes
|| timecode2
.seconds
!= timecode2
.seconds
|| timecode2
.frames
!= timecode1
.frames
) {
1763 cout
<< "ERROR: timecode2 not equal timecode1" << endl
;
1764 cout
<< "timecode: " << (timecode1
.negative
? "-" : "") << timecode1
.hours
<< ":" << timecode1
.minutes
<< ":" << timecode1
.seconds
<< ":" << timecode1
.frames
<< "::" << timecode1
.subframes
<< " -> ";
1765 cout
<< "sample: " << sample1
<< endl
;
1766 cout
<< "sample: " << sample1
<< " -> ";
1767 cout
<< "timecode: " << (timecode2
.negative
? "-" : "") << timecode2
.hours
<< ":" << timecode2
.minutes
<< ":" << timecode2
.seconds
<< ":" << timecode2
.frames
<< "::" << timecode2
.subframes
<< endl
;
1770 oldsample
= sample1
;
1771 _session
->timecode_increment_seconds( timecode1
);
1774 cout
<< "sample_increment: " << sample_increment
<< endl
;
1775 cout
<< "sample: " << sample1
<< " -> ";
1776 cout
<< "timecode: " << (timecode2
.negative
? "-" : "") << timecode2
.hours
<< ":" << timecode2
.minutes
<< ":" << timecode2
.seconds
<< ":" << timecode2
.frames
<< "::" << timecode2
.subframes
<< endl
;
1780 #ifdef Timecode_SAMPLE_TEST_6
1781 // Test 6: use_offset = true, use_subframes = false, increment minutes
1782 cout
<< "use_offset = true, use_subframes = false, increment minutes" << endl
;
1784 timecode1
.hours
= 0;
1785 timecode1
.minutes
= 0;
1786 timecode1
.seconds
= 0;
1787 timecode1
.frames
= 0;
1788 timecode1
.subframes
= 0;
1789 sample1
= oldsample
= 0;
1790 sample_increment
= _session
->frame_rate() * 60;
1792 _session
->sample_to_timecode( sample1
, timecode1
, true /* use_offset */, false /* use_subframes */ );
1793 cout
<< "Starting at sample: " << sample1
<< " -> ";
1794 cout
<< "timecode: " << (timecode1
.negative
? "-" : "") << timecode1
.hours
<< ":" << timecode1
.minutes
<< ":" << timecode1
.seconds
<< ":" << timecode1
.frames
<< "::" << timecode1
.subframes
<< endl
;
1796 for (int i
= 0; i
< 60; i
++) {
1797 _session
->timecode_to_sample( timecode1
, sample1
, true /* use_offset */, false /* use_subframes */ );
1798 _session
->sample_to_timecode( sample1
, timecode2
, true /* use_offset */, false /* use_subframes */ );
1800 // cout << "timecode: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << " -> ";
1801 // cout << "sample: " << sample1 << endl;
1802 // cout << "sample: " << sample1 << " -> ";
1803 // cout << "timecode: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
1805 // if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1807 // cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1811 if (timecode2
.hours
!= timecode1
.hours
|| timecode2
.minutes
!= timecode1
.minutes
|| timecode2
.seconds
!= timecode2
.seconds
|| timecode2
.frames
!= timecode1
.frames
) {
1812 cout
<< "ERROR: timecode2 not equal timecode1" << endl
;
1813 cout
<< "timecode: " << (timecode1
.negative
? "-" : "") << timecode1
.hours
<< ":" << timecode1
.minutes
<< ":" << timecode1
.seconds
<< ":" << timecode1
.frames
<< "::" << timecode1
.subframes
<< " -> ";
1814 cout
<< "sample: " << sample1
<< endl
;
1815 cout
<< "sample: " << sample1
<< " -> ";
1816 cout
<< "timecode: " << (timecode2
.negative
? "-" : "") << timecode2
.hours
<< ":" << timecode2
.minutes
<< ":" << timecode2
.seconds
<< ":" << timecode2
.frames
<< "::" << timecode2
.subframes
<< endl
;
1819 oldsample
= sample1
;
1820 _session
->timecode_increment_minutes( timecode1
);
1823 cout
<< "sample_increment: " << sample_increment
<< endl
;
1824 cout
<< "sample: " << sample1
<< " -> ";
1825 cout
<< "timecode: " << (timecode2
.negative
? "-" : "") << timecode2
.hours
<< ":" << timecode2
.minutes
<< ":" << timecode2
.seconds
<< ":" << timecode2
.frames
<< "::" << timecode2
.subframes
<< endl
;
1828 #ifdef Timecode_SAMPLE_TEST_7
1829 // Test 7: use_offset = true, use_subframes = false, increment hours
1830 cout
<< "use_offset = true, use_subframes = false, increment hours" << endl
;
1832 timecode1
.hours
= 0;
1833 timecode1
.minutes
= 0;
1834 timecode1
.seconds
= 0;
1835 timecode1
.frames
= 0;
1836 timecode1
.subframes
= 0;
1837 sample1
= oldsample
= 0;
1838 sample_increment
= _session
->frame_rate() * 60 * 60;
1840 _session
->sample_to_timecode( sample1
, timecode1
, true /* use_offset */, false /* use_subframes */ );
1841 cout
<< "Starting at sample: " << sample1
<< " -> ";
1842 cout
<< "timecode: " << (timecode1
.negative
? "-" : "") << timecode1
.hours
<< ":" << timecode1
.minutes
<< ":" << timecode1
.seconds
<< ":" << timecode1
.frames
<< "::" << timecode1
.subframes
<< endl
;
1844 for (int i
= 0; i
< 10; i
++) {
1845 _session
->timecode_to_sample( timecode1
, sample1
, true /* use_offset */, false /* use_subframes */ );
1846 _session
->sample_to_timecode( sample1
, timecode2
, true /* use_offset */, false /* use_subframes */ );
1848 // cout << "timecode: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << " -> ";
1849 // cout << "sample: " << sample1 << endl;
1850 // cout << "sample: " << sample1 << " -> ";
1851 // cout << "timecode: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
1853 // if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1855 // cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1859 if (timecode2
.hours
!= timecode1
.hours
|| timecode2
.minutes
!= timecode1
.minutes
|| timecode2
.seconds
!= timecode2
.seconds
|| timecode2
.frames
!= timecode1
.frames
) {
1860 cout
<< "ERROR: timecode2 not equal timecode1" << endl
;
1861 cout
<< "timecode: " << (timecode1
.negative
? "-" : "") << timecode1
.hours
<< ":" << timecode1
.minutes
<< ":" << timecode1
.seconds
<< ":" << timecode1
.frames
<< "::" << timecode1
.subframes
<< " -> ";
1862 cout
<< "sample: " << sample1
<< endl
;
1863 cout
<< "sample: " << sample1
<< " -> ";
1864 cout
<< "timecode: " << (timecode2
.negative
? "-" : "") << timecode2
.hours
<< ":" << timecode2
.minutes
<< ":" << timecode2
.seconds
<< ":" << timecode2
.frames
<< "::" << timecode2
.subframes
<< endl
;
1867 oldsample
= sample1
;
1868 _session
->timecode_increment_hours( timecode1
);
1871 cout
<< "sample_increment: " << sample_increment
<< endl
;
1872 cout
<< "sample: " << sample1
<< " -> ";
1873 cout
<< "timecode: " << (timecode2
.negative
? "-" : "") << timecode2
.hours
<< ":" << timecode2
.minutes
<< ":" << timecode2
.seconds
<< ":" << timecode2
.frames
<< "::" << timecode2
.subframes
<< endl
;
1882 AudioClock::minsec_frame_from_display () const
1884 if (_session
== 0) {
1888 int hrs
= atoi (ms_hours_label
.get_text());
1889 int mins
= atoi (ms_minutes_label
.get_text());
1890 float secs
= atof (ms_seconds_label
.get_text());
1892 nframes_t sr
= _session
->frame_rate();
1894 return (nframes_t
) floor ((hrs
* 60.0f
* 60.0f
* sr
) + (mins
* 60.0f
* sr
) + (secs
* sr
));
1898 AudioClock::bbt_frame_from_display (nframes_t pos
) const
1900 if (_session
== 0) {
1901 error
<< "AudioClock::current_time() called with BBT mode but without session!" << endmsg
;
1906 any
.type
= AnyTime::BBT
;
1908 any
.bbt
.bars
= atoi (bars_label
.get_text());
1909 any
.bbt
.beats
= atoi (beats_label
.get_text());
1910 any
.bbt
.ticks
= atoi (ticks_label
.get_text());
1917 nframes_t ret
= _session
->convert_to_frames_at (pos
, any
);
1924 AudioClock::bbt_frame_duration_from_display (nframes_t pos
) const
1926 if (_session
== 0) {
1927 error
<< "AudioClock::current_time() called with BBT mode but without session!" << endmsg
;
1934 bbt
.bars
= atoi (bars_label
.get_text());
1935 bbt
.beats
= atoi (beats_label
.get_text());
1936 bbt
.ticks
= atoi (ticks_label
.get_text());
1938 return _session
->tempo_map().bbt_duration_at(pos
,bbt
,1);
1942 AudioClock::audio_frame_from_display () const
1944 return (nframes_t
) atoi (audio_frames_label
.get_text());
1948 AudioClock::build_ops_menu ()
1950 using namespace Menu_Helpers
;
1951 ops_menu
= new Menu
;
1952 MenuList
& ops_items
= ops_menu
->items();
1953 ops_menu
->set_name ("ArdourContextMenu");
1955 if (!Profile
->get_sae()) {
1956 ops_items
.push_back (MenuElem (_("Timecode"), sigc::bind (sigc::mem_fun(*this, &AudioClock::set_mode
), Timecode
)));
1958 ops_items
.push_back (MenuElem (_("Bars:Beats"), sigc::bind (sigc::mem_fun(*this, &AudioClock::set_mode
), BBT
)));
1959 ops_items
.push_back (MenuElem (_("Minutes:Seconds"), sigc::bind (sigc::mem_fun(*this, &AudioClock::set_mode
), MinSec
)));
1960 ops_items
.push_back (MenuElem (_("Samples"), sigc::bind (sigc::mem_fun(*this, &AudioClock::set_mode
), Frames
)));
1961 ops_items
.push_back (MenuElem (_("Off"), sigc::bind (sigc::mem_fun(*this, &AudioClock::set_mode
), Off
)));
1963 if (editable
&& !is_duration
&& !_follows_playhead
) {
1964 ops_items
.push_back (SeparatorElem());
1965 ops_items
.push_back (MenuElem (_("Set From Playhead"), sigc::mem_fun(*this, &AudioClock::set_from_playhead
)));
1966 ops_items
.push_back (MenuElem (_("Locate to this time"), sigc::mem_fun(*this, &AudioClock::locate
)));
1971 AudioClock::set_from_playhead ()
1977 set (_session
->transport_frame());
1981 AudioClock::locate ()
1983 if (!_session
|| is_duration
) {
1987 _session
->request_locate (current_time(), false);
1991 AudioClock::set_mode (Mode m
)
1993 /* slightly tricky: this is called from within the ARDOUR_UI
1994 constructor by some of its clock members. at that time
1995 the instance pointer is unset, so we have to be careful.
1996 the main idea is to drop keyboard focus in case we had
1997 started editing the clock and then we switch clock mode.
2000 clock_base
.grab_focus ();
2006 clock_base
.remove ();
2012 clock_base
.add (timecode_packer_hbox
);
2016 clock_base
.add (bbt_packer_hbox
);
2020 clock_base
.add (minsec_packer_hbox
);
2024 clock_base
.add (frames_packer_hbox
);
2028 clock_base
.add (off_hbox
);
2032 set_size_requests ();
2034 set (last_when
, true);
2035 clock_base
.show_all ();
2036 key_entry_state
= 0;
2038 if (!is_transient
) {
2039 ModeChanged (); /* EMIT SIGNAL */
2040 mode_changed (); /* EMIT SIGNAL */
2045 AudioClock::set_size_requests ()
2047 /* note that in some fonts, "88" is narrower than "00" */
2051 Gtkmm2ext::set_size_request_to_display_given_text (hours_label
, "-88", 5, 5);
2052 Gtkmm2ext::set_size_request_to_display_given_text (minutes_label
, "88", 5, 5);
2053 Gtkmm2ext::set_size_request_to_display_given_text (seconds_label
, "88", 5, 5);
2054 Gtkmm2ext::set_size_request_to_display_given_text (frames_label
, "88", 5, 5);
2058 Gtkmm2ext::set_size_request_to_display_given_text (bars_label
, "-888", 5, 5);
2059 Gtkmm2ext::set_size_request_to_display_given_text (beats_label
, "88", 5, 5);
2060 Gtkmm2ext::set_size_request_to_display_given_text (ticks_label
, "8888", 5, 5);
2064 Gtkmm2ext::set_size_request_to_display_given_text (ms_hours_label
, "88", 5, 5);
2065 Gtkmm2ext::set_size_request_to_display_given_text (ms_minutes_label
, "88", 5, 5);
2066 Gtkmm2ext::set_size_request_to_display_given_text (ms_seconds_label
, "88.888", 5, 5);
2070 Gtkmm2ext::set_size_request_to_display_given_text (audio_frames_label
, "8888888888", 5, 5);
2074 Gtkmm2ext::set_size_request_to_display_given_text (off_hbox
, "00000", 5, 5);
2081 AudioClock::set_bbt_reference (nframes64_t pos
)
2083 bbt_reference_time
= pos
;
2087 AudioClock::on_style_changed (const Glib::RefPtr
<Style
>& old_style
)
2089 HBox::on_style_changed (old_style
);
2091 /* propagate style changes to all component widgets that should inherit the main one */
2093 Glib::RefPtr
<RcStyle
> rcstyle
= get_modifier_style();
2095 clock_base
.modify_style (rcstyle
);
2096 audio_frames_label
.modify_style (rcstyle
);
2097 hours_label
.modify_style (rcstyle
);
2098 minutes_label
.modify_style (rcstyle
);
2099 seconds_label
.modify_style (rcstyle
);
2100 frames_label
.modify_style (rcstyle
);
2101 bars_label
.modify_style (rcstyle
);
2102 beats_label
.modify_style (rcstyle
);
2103 ticks_label
.modify_style (rcstyle
);
2104 ms_hours_label
.modify_style (rcstyle
);
2105 ms_minutes_label
.modify_style (rcstyle
);
2106 ms_seconds_label
.modify_style (rcstyle
);
2107 hours_ebox
.modify_style (rcstyle
);
2108 minutes_ebox
.modify_style (rcstyle
);
2109 seconds_ebox
.modify_style (rcstyle
);
2110 frames_ebox
.modify_style (rcstyle
);
2111 audio_frames_ebox
.modify_style (rcstyle
);
2112 bars_ebox
.modify_style (rcstyle
);
2113 beats_ebox
.modify_style (rcstyle
);
2114 ticks_ebox
.modify_style (rcstyle
);
2115 ms_hours_ebox
.modify_style (rcstyle
);
2116 ms_minutes_ebox
.modify_style (rcstyle
);
2117 ms_seconds_ebox
.modify_style (rcstyle
);
2119 colon1
.modify_style (rcstyle
);
2120 colon2
.modify_style (rcstyle
);
2121 colon3
.modify_style (rcstyle
);
2122 colon4
.modify_style (rcstyle
);
2123 colon5
.modify_style (rcstyle
);
2124 b1
.modify_style (rcstyle
);
2125 b2
.modify_style (rcstyle
);
2127 set_size_requests ();