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
),
84 _canonical_time_is_displayed (true),
93 bbt_reference_time
= -1;
96 frames_upper_info_label
= manage (new Label
);
97 frames_lower_info_label
= manage (new Label
);
98 timecode_upper_info_label
= manage (new Label
);
99 timecode_lower_info_label
= manage (new Label
);
100 bbt_upper_info_label
= manage (new Label
);
101 bbt_lower_info_label
= manage (new Label
);
103 frames_upper_info_label
->set_name ("AudioClockFramesUpperInfo");
104 frames_lower_info_label
->set_name ("AudioClockFramesLowerInfo");
105 timecode_upper_info_label
->set_name ("AudioClockTimecodeUpperInfo");
106 timecode_lower_info_label
->set_name ("AudioClockTimecodeLowerInfo");
107 bbt_upper_info_label
->set_name ("AudioClockBBTUpperInfo");
108 bbt_lower_info_label
->set_name ("AudioClockBBTLowerInfo");
110 Gtkmm2ext::set_size_request_to_display_given_text(*timecode_upper_info_label
, "23.98",0,0);
111 Gtkmm2ext::set_size_request_to_display_given_text(*timecode_lower_info_label
, "NDF",0,0);
113 Gtkmm2ext::set_size_request_to_display_given_text(*bbt_upper_info_label
, "88|88",0,0);
114 Gtkmm2ext::set_size_request_to_display_given_text(*bbt_lower_info_label
, "888.88",0,0);
116 frames_info_box
.pack_start (*frames_upper_info_label
, true, true);
117 frames_info_box
.pack_start (*frames_lower_info_label
, true, true);
118 timecode_info_box
.pack_start (*timecode_upper_info_label
, true, true);
119 timecode_info_box
.pack_start (*timecode_lower_info_label
, true, true);
120 bbt_info_box
.pack_start (*bbt_upper_info_label
, true, true);
121 bbt_info_box
.pack_start (*bbt_lower_info_label
, true, true);
124 frames_upper_info_label
= 0;
125 frames_lower_info_label
= 0;
126 timecode_upper_info_label
= 0;
127 timecode_lower_info_label
= 0;
128 bbt_upper_info_label
= 0;
129 bbt_lower_info_label
= 0;
132 audio_frames_ebox
.add (audio_frames_label
);
134 frames_packer
.set_homogeneous (false);
135 frames_packer
.set_border_width (2);
136 frames_packer
.pack_start (audio_frames_ebox
, false, false);
139 frames_packer
.pack_start (frames_info_box
, false, false, 5);
142 frames_packer_hbox
.pack_start (frames_packer
, true, false);
144 hours_ebox
.add (hours_label
);
145 minutes_ebox
.add (minutes_label
);
146 seconds_ebox
.add (seconds_label
);
147 frames_ebox
.add (frames_label
);
148 bars_ebox
.add (bars_label
);
149 beats_ebox
.add (beats_label
);
150 ticks_ebox
.add (ticks_label
);
151 ms_hours_ebox
.add (ms_hours_label
);
152 ms_minutes_ebox
.add (ms_minutes_label
);
153 ms_seconds_ebox
.add (ms_seconds_label
);
155 timecode_packer
.set_homogeneous (false);
156 timecode_packer
.set_border_width (2);
157 timecode_packer
.pack_start (hours_ebox
, false, false);
158 timecode_packer
.pack_start (colon1
, false, false);
159 timecode_packer
.pack_start (minutes_ebox
, false, false);
160 timecode_packer
.pack_start (colon2
, false, false);
161 timecode_packer
.pack_start (seconds_ebox
, false, false);
162 timecode_packer
.pack_start (colon3
, false, false);
163 timecode_packer
.pack_start (frames_ebox
, false, false);
166 timecode_packer
.pack_start (timecode_info_box
, false, false, 5);
169 timecode_packer_hbox
.pack_start (timecode_packer
, true, false);
171 bbt_packer
.set_homogeneous (false);
172 bbt_packer
.set_border_width (2);
173 bbt_packer
.pack_start (bars_ebox
, false, false);
174 bbt_packer
.pack_start (b1
, false, false);
175 bbt_packer
.pack_start (beats_ebox
, false, false);
176 bbt_packer
.pack_start (b2
, false, false);
177 bbt_packer
.pack_start (ticks_ebox
, false, false);
180 bbt_packer
.pack_start (bbt_info_box
, false, false, 5);
183 bbt_packer_hbox
.pack_start (bbt_packer
, true, false);
185 minsec_packer
.set_homogeneous (false);
186 minsec_packer
.set_border_width (2);
187 minsec_packer
.pack_start (ms_hours_ebox
, false, false);
188 minsec_packer
.pack_start (colon4
, false, false);
189 minsec_packer
.pack_start (ms_minutes_ebox
, false, false);
190 minsec_packer
.pack_start (colon5
, false, false);
191 minsec_packer
.pack_start (ms_seconds_ebox
, false, false);
193 minsec_packer_hbox
.pack_start (minsec_packer
, true, false);
195 clock_frame
.set_shadow_type (Gtk::SHADOW_IN
);
196 clock_frame
.set_name ("BaseFrame");
198 clock_frame
.add (clock_base
);
200 set_widget_name (widget_name
);
202 _mode
= BBT
; /* lie to force mode switch */
205 pack_start (clock_frame
, true, true);
207 /* the clock base handles button releases for menu popup regardless of
208 editable status. if the clock is editable, the clock base is where
209 we pass focus to after leaving the last editable "field", which
210 will then shutdown editing till the user starts it up again.
212 it does this because the focus out event on the field disables
213 keyboard event handling, and we don't connect anything up to
214 notice focus in on the clock base. hence, keyboard event handling
218 clock_base
.add_events (Gdk::BUTTON_PRESS_MASK
|Gdk::BUTTON_RELEASE_MASK
|Gdk::SCROLL_MASK
);
219 clock_base
.signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &AudioClock::field_button_release_event
), Timecode_Hours
));
225 set (last_when
, true);
228 clocks
.push_back (this);
233 AudioClock::set_widget_name (string name
)
235 Widget::set_name (name
);
237 clock_base
.set_name (name
);
239 audio_frames_label
.set_name (name
);
240 hours_label
.set_name (name
);
241 minutes_label
.set_name (name
);
242 seconds_label
.set_name (name
);
243 frames_label
.set_name (name
);
244 bars_label
.set_name (name
);
245 beats_label
.set_name (name
);
246 ticks_label
.set_name (name
);
247 ms_hours_label
.set_name (name
);
248 ms_minutes_label
.set_name (name
);
249 ms_seconds_label
.set_name (name
);
250 hours_ebox
.set_name (name
);
251 minutes_ebox
.set_name (name
);
252 seconds_ebox
.set_name (name
);
253 frames_ebox
.set_name (name
);
254 audio_frames_ebox
.set_name (name
);
255 bars_ebox
.set_name (name
);
256 beats_ebox
.set_name (name
);
257 ticks_ebox
.set_name (name
);
258 ms_hours_ebox
.set_name (name
);
259 ms_minutes_ebox
.set_name (name
);
260 ms_seconds_ebox
.set_name (name
);
262 colon1
.set_name (name
);
263 colon2
.set_name (name
);
264 colon3
.set_name (name
);
265 colon4
.set_name (name
);
266 colon5
.set_name (name
);
274 AudioClock::setup_events ()
276 clock_base
.set_flags (Gtk::CAN_FOCUS
);
278 hours_ebox
.add_events (Gdk::BUTTON_PRESS_MASK
|Gdk::BUTTON_RELEASE_MASK
|Gdk::KEY_PRESS_MASK
|Gdk::KEY_RELEASE_MASK
|Gdk::FOCUS_CHANGE_MASK
|Gdk::POINTER_MOTION_MASK
|Gdk::SCROLL_MASK
);
279 minutes_ebox
.add_events (Gdk::BUTTON_PRESS_MASK
|Gdk::BUTTON_RELEASE_MASK
|Gdk::KEY_PRESS_MASK
|Gdk::KEY_RELEASE_MASK
|Gdk::FOCUS_CHANGE_MASK
|Gdk::POINTER_MOTION_MASK
|Gdk::SCROLL_MASK
);
280 seconds_ebox
.add_events (Gdk::BUTTON_PRESS_MASK
|Gdk::BUTTON_RELEASE_MASK
|Gdk::KEY_PRESS_MASK
|Gdk::KEY_RELEASE_MASK
|Gdk::FOCUS_CHANGE_MASK
|Gdk::POINTER_MOTION_MASK
|Gdk::SCROLL_MASK
);
281 frames_ebox
.add_events (Gdk::BUTTON_PRESS_MASK
|Gdk::BUTTON_RELEASE_MASK
|Gdk::KEY_PRESS_MASK
|Gdk::KEY_RELEASE_MASK
|Gdk::FOCUS_CHANGE_MASK
|Gdk::POINTER_MOTION_MASK
|Gdk::SCROLL_MASK
);
282 bars_ebox
.add_events (Gdk::BUTTON_PRESS_MASK
|Gdk::BUTTON_RELEASE_MASK
|Gdk::KEY_PRESS_MASK
|Gdk::KEY_RELEASE_MASK
|Gdk::FOCUS_CHANGE_MASK
|Gdk::POINTER_MOTION_MASK
|Gdk::SCROLL_MASK
);
283 beats_ebox
.add_events (Gdk::BUTTON_PRESS_MASK
|Gdk::BUTTON_RELEASE_MASK
|Gdk::KEY_PRESS_MASK
|Gdk::KEY_RELEASE_MASK
|Gdk::FOCUS_CHANGE_MASK
|Gdk::POINTER_MOTION_MASK
|Gdk::SCROLL_MASK
);
284 ticks_ebox
.add_events (Gdk::BUTTON_PRESS_MASK
|Gdk::BUTTON_RELEASE_MASK
|Gdk::KEY_PRESS_MASK
|Gdk::KEY_RELEASE_MASK
|Gdk::FOCUS_CHANGE_MASK
|Gdk::POINTER_MOTION_MASK
|Gdk::SCROLL_MASK
);
285 ms_hours_ebox
.add_events (Gdk::BUTTON_PRESS_MASK
|Gdk::BUTTON_RELEASE_MASK
|Gdk::KEY_PRESS_MASK
|Gdk::KEY_RELEASE_MASK
|Gdk::FOCUS_CHANGE_MASK
|Gdk::POINTER_MOTION_MASK
|Gdk::SCROLL_MASK
);
286 ms_minutes_ebox
.add_events (Gdk::BUTTON_PRESS_MASK
|Gdk::BUTTON_RELEASE_MASK
|Gdk::KEY_PRESS_MASK
|Gdk::KEY_RELEASE_MASK
|Gdk::FOCUS_CHANGE_MASK
|Gdk::POINTER_MOTION_MASK
|Gdk::SCROLL_MASK
);
287 ms_seconds_ebox
.add_events (Gdk::BUTTON_PRESS_MASK
|Gdk::BUTTON_RELEASE_MASK
|Gdk::KEY_PRESS_MASK
|Gdk::KEY_RELEASE_MASK
|Gdk::FOCUS_CHANGE_MASK
|Gdk::POINTER_MOTION_MASK
|Gdk::SCROLL_MASK
);
288 audio_frames_ebox
.add_events (Gdk::BUTTON_PRESS_MASK
|Gdk::BUTTON_RELEASE_MASK
|Gdk::KEY_PRESS_MASK
|Gdk::KEY_RELEASE_MASK
|Gdk::FOCUS_CHANGE_MASK
|Gdk::POINTER_MOTION_MASK
|Gdk::SCROLL_MASK
);
290 hours_ebox
.set_flags (Gtk::CAN_FOCUS
);
291 minutes_ebox
.set_flags (Gtk::CAN_FOCUS
);
292 seconds_ebox
.set_flags (Gtk::CAN_FOCUS
);
293 frames_ebox
.set_flags (Gtk::CAN_FOCUS
);
294 audio_frames_ebox
.set_flags (Gtk::CAN_FOCUS
);
295 bars_ebox
.set_flags (Gtk::CAN_FOCUS
);
296 beats_ebox
.set_flags (Gtk::CAN_FOCUS
);
297 ticks_ebox
.set_flags (Gtk::CAN_FOCUS
);
298 ms_hours_ebox
.set_flags (Gtk::CAN_FOCUS
);
299 ms_minutes_ebox
.set_flags (Gtk::CAN_FOCUS
);
300 ms_seconds_ebox
.set_flags (Gtk::CAN_FOCUS
);
302 hours_ebox
.signal_motion_notify_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_motion_notify_event
), Timecode_Hours
));
303 minutes_ebox
.signal_motion_notify_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_motion_notify_event
), Timecode_Minutes
));
304 seconds_ebox
.signal_motion_notify_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_motion_notify_event
), Timecode_Seconds
));
305 frames_ebox
.signal_motion_notify_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_motion_notify_event
), Timecode_Frames
));
306 audio_frames_ebox
.signal_motion_notify_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_motion_notify_event
), AudioFrames
));
307 bars_ebox
.signal_motion_notify_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_motion_notify_event
), Bars
));
308 beats_ebox
.signal_motion_notify_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_motion_notify_event
), Beats
));
309 ticks_ebox
.signal_motion_notify_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_motion_notify_event
), Ticks
));
310 ms_hours_ebox
.signal_motion_notify_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_motion_notify_event
), MS_Hours
));
311 ms_minutes_ebox
.signal_motion_notify_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_motion_notify_event
), MS_Minutes
));
312 ms_seconds_ebox
.signal_motion_notify_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_motion_notify_event
), MS_Seconds
));
314 hours_ebox
.signal_button_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_press_event
), Timecode_Hours
));
315 minutes_ebox
.signal_button_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_press_event
), Timecode_Minutes
));
316 seconds_ebox
.signal_button_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_press_event
), Timecode_Seconds
));
317 frames_ebox
.signal_button_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_press_event
), Timecode_Frames
));
318 audio_frames_ebox
.signal_button_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_press_event
), AudioFrames
));
319 bars_ebox
.signal_button_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_press_event
), Bars
));
320 beats_ebox
.signal_button_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_press_event
), Beats
));
321 ticks_ebox
.signal_button_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_press_event
), Ticks
));
322 ms_hours_ebox
.signal_button_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_press_event
), MS_Hours
));
323 ms_minutes_ebox
.signal_button_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_press_event
), MS_Minutes
));
324 ms_seconds_ebox
.signal_button_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_press_event
), MS_Seconds
));
326 hours_ebox
.signal_button_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_release_event
), Timecode_Hours
));
327 minutes_ebox
.signal_button_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_release_event
), Timecode_Minutes
));
328 seconds_ebox
.signal_button_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_release_event
), Timecode_Seconds
));
329 frames_ebox
.signal_button_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_release_event
), Timecode_Frames
));
330 audio_frames_ebox
.signal_button_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_release_event
), AudioFrames
));
331 bars_ebox
.signal_button_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_release_event
), Bars
));
332 beats_ebox
.signal_button_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_release_event
), Beats
));
333 ticks_ebox
.signal_button_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_release_event
), Ticks
));
334 ms_hours_ebox
.signal_button_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_release_event
), MS_Hours
));
335 ms_minutes_ebox
.signal_button_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_release_event
), MS_Minutes
));
336 ms_seconds_ebox
.signal_button_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_release_event
), MS_Seconds
));
338 hours_ebox
.signal_scroll_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_scroll_event
), Timecode_Hours
));
339 minutes_ebox
.signal_scroll_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_scroll_event
), Timecode_Minutes
));
340 seconds_ebox
.signal_scroll_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_scroll_event
), Timecode_Seconds
));
341 frames_ebox
.signal_scroll_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_scroll_event
), Timecode_Frames
));
342 audio_frames_ebox
.signal_scroll_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_scroll_event
), AudioFrames
));
343 bars_ebox
.signal_scroll_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_scroll_event
), Bars
));
344 beats_ebox
.signal_scroll_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_scroll_event
), Beats
));
345 ticks_ebox
.signal_scroll_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_scroll_event
), Ticks
));
346 ms_hours_ebox
.signal_scroll_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_scroll_event
), MS_Hours
));
347 ms_minutes_ebox
.signal_scroll_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_scroll_event
), MS_Minutes
));
348 ms_seconds_ebox
.signal_scroll_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_button_scroll_event
), MS_Seconds
));
350 hours_ebox
.signal_key_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_press_event
), Timecode_Hours
));
351 minutes_ebox
.signal_key_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_press_event
), Timecode_Minutes
));
352 seconds_ebox
.signal_key_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_press_event
), Timecode_Seconds
));
353 frames_ebox
.signal_key_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_press_event
), Timecode_Frames
));
354 audio_frames_ebox
.signal_key_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_press_event
), AudioFrames
));
355 bars_ebox
.signal_key_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_press_event
), Bars
));
356 beats_ebox
.signal_key_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_press_event
), Beats
));
357 ticks_ebox
.signal_key_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_press_event
), Ticks
));
358 ms_hours_ebox
.signal_key_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_press_event
), MS_Hours
));
359 ms_minutes_ebox
.signal_key_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_press_event
), MS_Minutes
));
360 ms_seconds_ebox
.signal_key_press_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_press_event
), MS_Seconds
));
362 hours_ebox
.signal_key_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_release_event
), Timecode_Hours
));
363 minutes_ebox
.signal_key_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_release_event
), Timecode_Minutes
));
364 seconds_ebox
.signal_key_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_release_event
), Timecode_Seconds
));
365 frames_ebox
.signal_key_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_release_event
), Timecode_Frames
));
366 audio_frames_ebox
.signal_key_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_release_event
), AudioFrames
));
367 bars_ebox
.signal_key_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_release_event
), Bars
));
368 beats_ebox
.signal_key_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_release_event
), Beats
));
369 ticks_ebox
.signal_key_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_release_event
), Ticks
));
370 ms_hours_ebox
.signal_key_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_release_event
), MS_Hours
));
371 ms_minutes_ebox
.signal_key_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_release_event
), MS_Minutes
));
372 ms_seconds_ebox
.signal_key_release_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_key_release_event
), MS_Seconds
));
374 hours_ebox
.signal_focus_in_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_in_event
), Timecode_Hours
));
375 minutes_ebox
.signal_focus_in_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_in_event
), Timecode_Minutes
));
376 seconds_ebox
.signal_focus_in_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_in_event
), Timecode_Seconds
));
377 frames_ebox
.signal_focus_in_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_in_event
), Timecode_Frames
));
378 audio_frames_ebox
.signal_focus_in_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_in_event
), AudioFrames
));
379 bars_ebox
.signal_focus_in_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_in_event
), Bars
));
380 beats_ebox
.signal_focus_in_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_in_event
), Beats
));
381 ticks_ebox
.signal_focus_in_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_in_event
), Ticks
));
382 ms_hours_ebox
.signal_focus_in_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_in_event
), MS_Hours
));
383 ms_minutes_ebox
.signal_focus_in_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_in_event
), MS_Minutes
));
384 ms_seconds_ebox
.signal_focus_in_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_in_event
), MS_Seconds
));
386 hours_ebox
.signal_focus_out_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_out_event
), Timecode_Hours
));
387 minutes_ebox
.signal_focus_out_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_out_event
), Timecode_Minutes
));
388 seconds_ebox
.signal_focus_out_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_out_event
), Timecode_Seconds
));
389 frames_ebox
.signal_focus_out_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_out_event
), Timecode_Frames
));
390 audio_frames_ebox
.signal_focus_out_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_out_event
), AudioFrames
));
391 bars_ebox
.signal_focus_out_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_out_event
), Bars
));
392 beats_ebox
.signal_focus_out_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_out_event
), Beats
));
393 ticks_ebox
.signal_focus_out_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_out_event
), Ticks
));
394 ms_hours_ebox
.signal_focus_out_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_out_event
), MS_Hours
));
395 ms_minutes_ebox
.signal_focus_out_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_out_event
), MS_Minutes
));
396 ms_seconds_ebox
.signal_focus_out_event().connect (sigc::bind (sigc::mem_fun(*this, &AudioClock::field_focus_out_event
), MS_Seconds
));
398 clock_base
.signal_focus_in_event().connect (sigc::mem_fun (*this, &AudioClock::drop_focus_handler
));
402 AudioClock::drop_focus_handler (GdkEventFocus
*)
404 Keyboard::magic_widget_drop_focus ();
409 AudioClock::on_realize ()
413 /* styles are not available until the widgets are bound to a window */
415 set_size_requests ();
419 AudioClock::set (framepos_t when
, bool force
, framecnt_t offset
, char which
)
421 if ((!force
&& !is_visible()) || _session
== 0) {
425 bool const pdelta
= Config
->get_primary_clock_delta_edit_cursor ();
426 bool const sdelta
= Config
->get_secondary_clock_delta_edit_cursor ();
428 if (offset
&& which
== 'p' && pdelta
) {
429 when
= (when
> offset
) ? when
- offset
: offset
- when
;
430 } else if (offset
&& which
== 's' && sdelta
) {
431 when
= (when
> offset
) ? when
- offset
: offset
- when
;
434 if (when
== last_when
&& !force
) {
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
);
475 /* we're setting the time from a frames value, so keep it as the canonical value */
476 _canonical_time
= when
;
477 _canonical_time_is_displayed
= false;
481 AudioClock::session_configuration_changed (std::string p
)
483 if (p
!= "timecode-offset" && p
!= "timecode-offset-negative") {
492 current
= current_duration ();
494 current
= current_time ();
504 AudioClock::set_frames (framepos_t when
, bool /*force*/)
507 snprintf (buf
, sizeof (buf
), "%" PRId64
, when
);
508 audio_frames_label
.set_text (buf
);
510 if (frames_upper_info_label
) {
511 framecnt_t rate
= _session
->frame_rate();
513 if (fmod (rate
, 1000.0) == 0.000) {
514 sprintf (buf
, "%" PRId64
"K", rate
/1000);
516 sprintf (buf
, "%.3fK", rate
/1000.0f
);
519 if (frames_upper_info_label
->get_text() != buf
) {
520 frames_upper_info_label
->set_text (buf
);
523 float vid_pullup
= _session
->config
.get_video_pullup();
525 if (vid_pullup
== 0.0) {
526 if (frames_lower_info_label
->get_text () != _("none")) {
527 frames_lower_info_label
->set_text(_("none"));
530 sprintf (buf
, "%-6.4f", vid_pullup
);
531 if (frames_lower_info_label
->get_text() != buf
) {
532 frames_lower_info_label
->set_text (buf
);
539 AudioClock::set_minsec (framepos_t when
, bool force
)
548 hrs
= (int) floor (left
/ (_session
->frame_rate() * 60.0f
* 60.0f
));
549 left
-= (framecnt_t
) floor (hrs
* _session
->frame_rate() * 60.0f
* 60.0f
);
550 mins
= (int) floor (left
/ (_session
->frame_rate() * 60.0f
));
551 left
-= (framecnt_t
) floor (mins
* _session
->frame_rate() * 60.0f
);
552 secs
= left
/ (float) _session
->frame_rate();
554 if (force
|| hrs
!= ms_last_hrs
) {
555 sprintf (buf
, "%02d", hrs
);
556 ms_hours_label
.set_text (buf
);
560 if (force
|| mins
!= ms_last_mins
) {
561 sprintf (buf
, "%02d", mins
);
562 ms_minutes_label
.set_text (buf
);
566 if (force
|| secs
!= ms_last_secs
) {
567 sprintf (buf
, "%06.3f", secs
);
568 ms_seconds_label
.set_text (buf
);
574 AudioClock::set_timecode (framepos_t when
, bool force
)
577 Timecode::Time timecode
;
580 _session
->timecode_duration (when
, timecode
);
582 _session
->timecode_time (when
, timecode
);
585 if (force
|| timecode
.hours
!= last_hrs
|| timecode
.negative
!= last_negative
) {
586 if (timecode
.negative
) {
587 sprintf (buf
, "-%02" PRIu32
, timecode
.hours
);
589 sprintf (buf
, " %02" PRIu32
, timecode
.hours
);
591 hours_label
.set_text (buf
);
592 last_hrs
= timecode
.hours
;
593 last_negative
= timecode
.negative
;
596 if (force
|| timecode
.minutes
!= last_mins
) {
597 sprintf (buf
, "%02" PRIu32
, timecode
.minutes
);
598 minutes_label
.set_text (buf
);
599 last_mins
= timecode
.minutes
;
602 if (force
|| timecode
.seconds
!= last_secs
) {
603 sprintf (buf
, "%02" PRIu32
, timecode
.seconds
);
604 seconds_label
.set_text (buf
);
605 last_secs
= timecode
.seconds
;
608 if (force
|| timecode
.frames
!= last_frames
) {
609 sprintf (buf
, "%02" PRIu32
, timecode
.frames
);
610 frames_label
.set_text (buf
);
611 last_frames
= timecode
.frames
;
614 if (timecode_upper_info_label
) {
615 double timecode_frames
= _session
->timecode_frames_per_second();
617 if ( fmod(timecode_frames
, 1.0) == 0.0) {
618 sprintf (buf
, "%u", int (timecode_frames
));
620 sprintf (buf
, "%.2f", timecode_frames
);
623 if (timecode_upper_info_label
->get_text() != buf
) {
624 timecode_upper_info_label
->set_text (buf
);
627 if ((fabs(timecode_frames
- 29.97) < 0.0001) || timecode_frames
== 30) {
628 if (_session
->timecode_drop_frames()) {
631 sprintf (buf
, "NDF");
634 // there is no drop frame alternative
638 if (timecode_lower_info_label
->get_text() != buf
) {
639 timecode_lower_info_label
->set_text (buf
);
645 AudioClock::set_bbt (framepos_t when
, bool force
)
648 Timecode::BBT_Time bbt
;
650 /* handle a common case */
657 _session
->tempo_map().bbt_time (when
, bbt
);
662 _session
->tempo_map().bbt_time (when
, bbt
);
665 sprintf (buf
, "%03" PRIu32
, bbt
.bars
);
666 if (force
|| bars_label
.get_text () != buf
) {
667 bars_label
.set_text (buf
);
669 sprintf (buf
, "%02" PRIu32
, bbt
.beats
);
670 if (force
|| beats_label
.get_text () != buf
) {
671 beats_label
.set_text (buf
);
673 sprintf (buf
, "%04" PRIu32
, bbt
.ticks
);
674 if (force
|| ticks_label
.get_text () != buf
) {
675 ticks_label
.set_text (buf
);
678 if (bbt_upper_info_label
) {
681 if (bbt_reference_time
< 0) {
684 pos
= bbt_reference_time
;
687 TempoMetric
m (_session
->tempo_map().metric_at (pos
));
689 sprintf (buf
, "%-5.2f", m
.tempo().beats_per_minute());
690 if (bbt_lower_info_label
->get_text() != buf
) {
691 bbt_lower_info_label
->set_text (buf
);
693 sprintf (buf
, "%g|%g", m
.meter().beats_per_bar(), m
.meter().note_divisor());
694 if (bbt_upper_info_label
->get_text() != buf
) {
695 bbt_upper_info_label
->set_text (buf
);
701 AudioClock::set_session (Session
*s
)
703 SessionHandlePtr::set_session (s
);
707 _session
->config
.ParameterChanged
.connect (_session_connections
, invalidator (*this), boost::bind (&AudioClock::session_configuration_changed
, this, _1
), gui_context());
710 XMLNode
* node
= _session
->extra_xml (X_("ClockModes"));
711 AudioClock::Mode amode
;
714 if ((prop
= node
->property (_name
)) != 0) {
715 amode
= AudioClock::Mode (string_2_enum (prop
->value(), amode
));
720 set (last_when
, true);
729 hours_ebox
.grab_focus ();
733 bars_ebox
.grab_focus ();
737 ms_hours_ebox
.grab_focus ();
741 frames_ebox
.grab_focus ();
751 AudioClock::field_key_press_event (GdkEventKey */
*ev*/
, Field
/*field*/)
753 /* all key activity is handled on key release */
758 AudioClock::field_key_release_event (GdkEventKey
*ev
, Field field
)
763 bool move_on
= false;
767 label
= &hours_label
;
769 case Timecode_Minutes
:
770 label
= &minutes_label
;
772 case Timecode_Seconds
:
773 label
= &seconds_label
;
775 case Timecode_Frames
:
776 label
= &frames_label
;
780 label
= &audio_frames_label
;
784 label
= &ms_hours_label
;
787 label
= &ms_minutes_label
;
790 label
= &ms_seconds_label
;
797 label
= &beats_label
;
800 label
= &ticks_label
;
806 switch (ev
->keyval
) {
850 if (_mode
== MinSec
&& field
== MS_Seconds
) {
865 clock_base
.grab_focus ();
866 ChangeAborted(); /* EMIT SIGNAL */
875 if (key_entry_state
== 0) {
877 /* initialize with a fresh new string */
879 if (field
!= AudioFrames
) {
880 for (uint32_t xn
= 0; xn
< field_length
[field
] - 1; ++xn
) {
889 string existing
= label
->get_text();
890 if (existing
.length() >= field_length
[field
]) {
891 new_text
= existing
.substr (1, field_length
[field
] - 1);
893 new_text
= existing
.substr (0, field_length
[field
] - 1);
897 new_text
+= new_char
;
898 label
->set_text (new_text
);
899 _canonical_time_is_displayed
= true;
903 if (key_entry_state
== field_length
[field
]) {
909 if (key_entry_state
) {
913 case Timecode_Minutes
:
914 case Timecode_Seconds
:
915 case Timecode_Frames
:
916 // Check Timecode fields for sanity (may also adjust fields)
917 timecode_sanitize_display();
922 // Bars should never be, unless this clock is for a duration
923 if (atoi(bars_label
.get_text()) == 0 && !is_duration
) {
924 bars_label
.set_text("001");
925 _canonical_time_is_displayed
= true;
927 // beats should never be 0, unless this clock is for a duration
928 if (atoi(beats_label
.get_text()) == 0 && !is_duration
) {
929 beats_label
.set_text("01");
930 _canonical_time_is_displayed
= true;
937 ValueChanged(); /* EMIT_SIGNAL */
940 /* move on to the next field.
948 minutes_ebox
.grab_focus ();
950 case Timecode_Minutes
:
951 seconds_ebox
.grab_focus ();
953 case Timecode_Seconds
:
954 frames_ebox
.grab_focus ();
956 case Timecode_Frames
:
957 clock_base
.grab_focus ();
962 clock_base
.grab_focus ();
968 ms_minutes_ebox
.grab_focus ();
971 ms_seconds_ebox
.grab_focus ();
974 clock_base
.grab_focus ();
980 beats_ebox
.grab_focus ();
983 ticks_ebox
.grab_focus ();
986 clock_base
.grab_focus ();
995 //if user hit Enter, lose focus
996 switch (ev
->keyval
) {
999 clock_base
.grab_focus ();
1006 AudioClock::field_focus_in_event (GdkEventFocus */
*ev*/
, Field field
)
1008 key_entry_state
= 0;
1010 Keyboard::magic_widget_grab_focus ();
1013 case Timecode_Hours
:
1014 hours_ebox
.set_flags (Gtk::HAS_FOCUS
);
1015 hours_ebox
.set_state (Gtk::STATE_ACTIVE
);
1017 case Timecode_Minutes
:
1018 minutes_ebox
.set_flags (Gtk::HAS_FOCUS
);
1019 minutes_ebox
.set_state (Gtk::STATE_ACTIVE
);
1021 case Timecode_Seconds
:
1022 seconds_ebox
.set_flags (Gtk::HAS_FOCUS
);
1023 seconds_ebox
.set_state (Gtk::STATE_ACTIVE
);
1025 case Timecode_Frames
:
1026 frames_ebox
.set_flags (Gtk::HAS_FOCUS
);
1027 frames_ebox
.set_state (Gtk::STATE_ACTIVE
);
1031 audio_frames_ebox
.set_flags (Gtk::HAS_FOCUS
);
1032 audio_frames_ebox
.set_state (Gtk::STATE_ACTIVE
);
1036 ms_hours_ebox
.set_flags (Gtk::HAS_FOCUS
);
1037 ms_hours_ebox
.set_state (Gtk::STATE_ACTIVE
);
1040 ms_minutes_ebox
.set_flags (Gtk::HAS_FOCUS
);
1041 ms_minutes_ebox
.set_state (Gtk::STATE_ACTIVE
);
1044 ms_seconds_ebox
.set_flags (Gtk::HAS_FOCUS
);
1045 ms_seconds_ebox
.set_state (Gtk::STATE_ACTIVE
);
1048 bars_ebox
.set_flags (Gtk::HAS_FOCUS
);
1049 bars_ebox
.set_state (Gtk::STATE_ACTIVE
);
1052 beats_ebox
.set_flags (Gtk::HAS_FOCUS
);
1053 beats_ebox
.set_state (Gtk::STATE_ACTIVE
);
1056 ticks_ebox
.set_flags (Gtk::HAS_FOCUS
);
1057 ticks_ebox
.set_state (Gtk::STATE_ACTIVE
);
1065 AudioClock::field_focus_out_event (GdkEventFocus */
*ev*/
, Field field
)
1069 case Timecode_Hours
:
1070 hours_ebox
.unset_flags (Gtk::HAS_FOCUS
);
1071 hours_ebox
.set_state (Gtk::STATE_NORMAL
);
1073 case Timecode_Minutes
:
1074 minutes_ebox
.unset_flags (Gtk::HAS_FOCUS
);
1075 minutes_ebox
.set_state (Gtk::STATE_NORMAL
);
1077 case Timecode_Seconds
:
1078 seconds_ebox
.unset_flags (Gtk::HAS_FOCUS
);
1079 seconds_ebox
.set_state (Gtk::STATE_NORMAL
);
1081 case Timecode_Frames
:
1082 frames_ebox
.unset_flags (Gtk::HAS_FOCUS
);
1083 frames_ebox
.set_state (Gtk::STATE_NORMAL
);
1087 audio_frames_ebox
.unset_flags (Gtk::HAS_FOCUS
);
1088 audio_frames_ebox
.set_state (Gtk::STATE_NORMAL
);
1092 ms_hours_ebox
.unset_flags (Gtk::HAS_FOCUS
);
1093 ms_hours_ebox
.set_state (Gtk::STATE_NORMAL
);
1096 ms_minutes_ebox
.unset_flags (Gtk::HAS_FOCUS
);
1097 ms_minutes_ebox
.set_state (Gtk::STATE_NORMAL
);
1100 ms_seconds_ebox
.unset_flags (Gtk::HAS_FOCUS
);
1101 ms_seconds_ebox
.set_state (Gtk::STATE_NORMAL
);
1105 bars_ebox
.unset_flags (Gtk::HAS_FOCUS
);
1106 bars_ebox
.set_state (Gtk::STATE_NORMAL
);
1109 beats_ebox
.unset_flags (Gtk::HAS_FOCUS
);
1110 beats_ebox
.set_state (Gtk::STATE_NORMAL
);
1113 ticks_ebox
.unset_flags (Gtk::HAS_FOCUS
);
1114 ticks_ebox
.set_state (Gtk::STATE_NORMAL
);
1118 Keyboard::magic_widget_drop_focus ();
1124 AudioClock::field_button_release_event (GdkEventButton
*ev
, Field field
)
1127 cerr
<< "button event on clock but we are dragging\n";
1128 gdk_pointer_ungrab (GDK_CURRENT_TIME
);
1130 if (ev
->y
> drag_start_y
+1 || ev
->y
< drag_start_y
-1 || Keyboard::modifier_state_equals (ev
->state
, Keyboard::TertiaryModifier
)){
1131 // we actually dragged so return without setting editing focus, or we shift clicked
1137 if (ops_menu
== 0) {
1140 ops_menu
->popup (1, ev
->time
);
1144 if (Keyboard::is_context_menu_event (ev
)) {
1145 if (ops_menu
== 0) {
1148 ops_menu
->popup (1, ev
->time
);
1152 switch (ev
->button
) {
1155 case Timecode_Hours
:
1156 hours_ebox
.grab_focus();
1158 case Timecode_Minutes
:
1159 minutes_ebox
.grab_focus();
1161 case Timecode_Seconds
:
1162 seconds_ebox
.grab_focus();
1164 case Timecode_Frames
:
1165 frames_ebox
.grab_focus();
1169 audio_frames_ebox
.grab_focus();
1173 ms_hours_ebox
.grab_focus();
1176 ms_minutes_ebox
.grab_focus();
1179 ms_seconds_ebox
.grab_focus();
1183 bars_ebox
.grab_focus ();
1186 beats_ebox
.grab_focus ();
1189 ticks_ebox
.grab_focus ();
1202 AudioClock::field_button_press_event (GdkEventButton
*ev
, Field
/*field*/)
1204 if (_session
== 0) {
1208 framepos_t frames
= 0;
1210 switch (ev
->button
) {
1212 if (Keyboard::modifier_state_equals (ev
->state
, Keyboard::TertiaryModifier
)) {
1214 ValueChanged (); /* EMIT_SIGNAL */
1217 /* make absolutely sure that the pointer is grabbed */
1218 gdk_pointer_grab(ev
->window
,false ,
1219 GdkEventMask( Gdk::POINTER_MOTION_MASK
| Gdk::BUTTON_PRESS_MASK
|Gdk::BUTTON_RELEASE_MASK
),
1220 NULL
,NULL
,ev
->time
);
1223 drag_start_y
= ev
->y
;
1228 if (Keyboard::modifier_state_equals (ev
->state
, Keyboard::TertiaryModifier
)) {
1230 ValueChanged (); /* EMIT_SIGNAL */
1235 /* used for context sensitive menu */
1248 AudioClock::field_button_scroll_event (GdkEventScroll
*ev
, Field field
)
1250 if (_session
== 0) {
1254 framepos_t frames
= 0;
1256 switch (ev
->direction
) {
1259 frames
= get_frames (field
);
1261 if (Keyboard::modifier_state_equals (ev
->state
, Keyboard::PrimaryModifier
)) {
1264 set (current_time() + frames
, true);
1265 ValueChanged (); /* EMIT_SIGNAL */
1269 case GDK_SCROLL_DOWN
:
1270 frames
= get_frames (field
);
1272 if (Keyboard::modifier_state_equals (ev
->state
, Keyboard::PrimaryModifier
)) {
1276 if ((double)current_time() - (double)frames
< 0.0) {
1279 set (current_time() - frames
, true);
1282 ValueChanged (); /* EMIT_SIGNAL */
1295 AudioClock::field_motion_notify_event (GdkEventMotion
*ev
, Field field
)
1297 if (_session
== 0 || !dragging
) {
1301 float pixel_frame_scale_factor
= 0.2f
;
1304 if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
1305 pixel_frame_scale_factor = 0.1f;
1309 if (Keyboard::modifier_state_contains (ev->state,
1310 Keyboard::PrimaryModifier|Keyboard::SecondaryModifier)) {
1312 pixel_frame_scale_factor = 0.025f;
1315 double y_delta
= ev
->y
- drag_y
;
1317 drag_accum
+= y_delta
*pixel_frame_scale_factor
;
1321 if (trunc(drag_accum
) != 0) {
1326 dir
= (drag_accum
< 0 ? 1:-1);
1327 pos
= current_time();
1328 frames
= get_frames (field
,pos
,dir
);
1330 if (frames
!= 0 && frames
* drag_accum
< current_time()) {
1332 set ((framepos_t
) floor (pos
- drag_accum
* frames
), false); // minus because up is negative in computer-land
1340 ValueChanged(); /* EMIT_SIGNAL */
1349 AudioClock::get_frames (Field field
, framepos_t pos
, int dir
)
1351 framecnt_t frames
= 0;
1352 Timecode::BBT_Time bbt
;
1354 case Timecode_Hours
:
1355 frames
= (framecnt_t
) floor (3600.0 * _session
->frame_rate());
1357 case Timecode_Minutes
:
1358 frames
= (framecnt_t
) floor (60.0 * _session
->frame_rate());
1360 case Timecode_Seconds
:
1361 frames
= _session
->frame_rate();
1363 case Timecode_Frames
:
1364 frames
= (framecnt_t
) floor (_session
->frame_rate() / _session
->timecode_frames_per_second());
1372 frames
= (framecnt_t
) floor (3600.0 * _session
->frame_rate());
1375 frames
= (framecnt_t
) floor (60.0 * _session
->frame_rate());
1378 frames
= _session
->frame_rate();
1385 frames
= _session
->tempo_map().bbt_duration_at(pos
,bbt
,dir
);
1391 frames
= _session
->tempo_map().bbt_duration_at(pos
,bbt
,dir
);
1397 frames
= _session
->tempo_map().bbt_duration_at(pos
,bbt
,dir
);
1405 AudioClock::current_time (framepos_t pos
) const
1407 if (!_canonical_time_is_displayed
) {
1408 return _canonical_time
;
1415 ret
= timecode_frame_from_display ();
1418 ret
= bbt_frame_from_display (pos
);
1422 ret
= minsec_frame_from_display ();
1426 ret
= audio_frame_from_display ();
1437 AudioClock::current_duration (framepos_t pos
) const
1443 ret
= timecode_frame_from_display ();
1446 ret
= bbt_frame_duration_from_display (pos
);
1450 ret
= minsec_frame_from_display ();
1454 ret
= audio_frame_from_display ();
1465 AudioClock::timecode_sanitize_display()
1467 // Check Timecode fields for sanity, possibly adjusting values
1468 if (atoi(minutes_label
.get_text()) > 59) {
1469 minutes_label
.set_text("59");
1470 _canonical_time_is_displayed
= true;
1473 if (atoi(seconds_label
.get_text()) > 59) {
1474 seconds_label
.set_text("59");
1475 _canonical_time_is_displayed
= true;
1478 switch ((long)rint(_session
->timecode_frames_per_second())) {
1480 if (atoi(frames_label
.get_text()) > 23) {
1481 frames_label
.set_text("23");
1482 _canonical_time_is_displayed
= true;
1486 if (atoi(frames_label
.get_text()) > 24) {
1487 frames_label
.set_text("24");
1488 _canonical_time_is_displayed
= true;
1492 if (atoi(frames_label
.get_text()) > 29) {
1493 frames_label
.set_text("29");
1494 _canonical_time_is_displayed
= true;
1501 if (_session
->timecode_drop_frames()) {
1502 if ((atoi(minutes_label
.get_text()) % 10) && (atoi(seconds_label
.get_text()) == 0) && (atoi(frames_label
.get_text()) < 2)) {
1503 frames_label
.set_text("02");
1504 _canonical_time_is_displayed
= true;
1510 AudioClock::timecode_frame_from_display () const
1512 if (_session
== 0) {
1516 Timecode::Time timecode
;
1519 timecode
.hours
= atoi (hours_label
.get_text());
1520 timecode
.minutes
= atoi (minutes_label
.get_text());
1521 timecode
.seconds
= atoi (seconds_label
.get_text());
1522 timecode
.frames
= atoi (frames_label
.get_text());
1523 timecode
.rate
= _session
->timecode_frames_per_second();
1524 timecode
.drop
= _session
->timecode_drop_frames();
1526 _session
->timecode_to_sample( timecode
, sample
, false /* use_offset */, false /* use_subframes */ );
1530 #define Timecode_SAMPLE_TEST_1
1531 #define Timecode_SAMPLE_TEST_2
1532 #define Timecode_SAMPLE_TEST_3
1533 #define Timecode_SAMPLE_TEST_4
1534 #define Timecode_SAMPLE_TEST_5
1535 #define Timecode_SAMPLE_TEST_6
1536 #define Timecode_SAMPLE_TEST_7
1538 // Testcode for timecode<->sample conversions (P.S.)
1539 Timecode::Time timecode1
;
1541 framepos_t oldsample
= 0;
1542 Timecode::Time timecode2
;
1543 framecnt_t sample_increment
;
1545 sample_increment
= (framecnt_t
)rint(_session
->frame_rate() / _session
->timecode_frames_per_second
);
1547 #ifdef Timecode_SAMPLE_TEST_1
1548 // Test 1: use_offset = false, use_subframes = false
1549 cout
<< "use_offset = false, use_subframes = false" << endl
;
1550 for (int i
= 0; i
< 108003; i
++) {
1551 _session
->timecode_to_sample( timecode1
, sample1
, false /* use_offset */, false /* use_subframes */ );
1552 _session
->sample_to_timecode( sample1
, timecode2
, false /* use_offset */, false /* use_subframes */ );
1554 if ((i
> 0) && ( ((sample1
- oldsample
) != sample_increment
) && ((sample1
- oldsample
) != (sample_increment
+ 1)) && ((sample1
- oldsample
) != (sample_increment
- 1)))) {
1555 cout
<< "ERROR: sample increment not right: " << (sample1
- oldsample
) << " != " << sample_increment
<< endl
;
1556 cout
<< "timecode1: " << timecode1
.hours
<< ":" << timecode1
.minutes
<< ":" << timecode1
.seconds
<< ":" << timecode1
.frames
<< "::" << timecode1
.subframes
<< " -> ";
1557 cout
<< "sample: " << sample1
<< endl
;
1558 cout
<< "sample: " << sample1
<< " -> ";
1559 cout
<< "timecode2: " << timecode2
.hours
<< ":" << timecode2
.minutes
<< ":" << timecode2
.seconds
<< ":" << timecode2
.frames
<< "::" << timecode2
.subframes
<< endl
;
1563 if (timecode2
.hours
!= timecode1
.hours
|| timecode2
.minutes
!= timecode1
.minutes
|| timecode2
.seconds
!= timecode2
.seconds
|| timecode2
.frames
!= timecode1
.frames
) {
1564 cout
<< "ERROR: timecode2 not equal timecode1" << endl
;
1565 cout
<< "timecode1: " << timecode1
.hours
<< ":" << timecode1
.minutes
<< ":" << timecode1
.seconds
<< ":" << timecode1
.frames
<< "::" << timecode1
.subframes
<< " -> ";
1566 cout
<< "sample: " << sample1
<< endl
;
1567 cout
<< "sample: " << sample1
<< " -> ";
1568 cout
<< "timecode2: " << timecode2
.hours
<< ":" << timecode2
.minutes
<< ":" << timecode2
.seconds
<< ":" << timecode2
.frames
<< "::" << timecode2
.subframes
<< endl
;
1571 oldsample
= sample1
;
1572 _session
->timecode_increment( timecode1
);
1575 cout
<< "sample_increment: " << sample_increment
<< endl
;
1576 cout
<< "sample: " << sample1
<< " -> ";
1577 cout
<< "timecode: " << timecode2
.hours
<< ":" << timecode2
.minutes
<< ":" << timecode2
.seconds
<< ":" << timecode2
.frames
<< "::" << timecode2
.subframes
<< endl
;
1580 #ifdef Timecode_SAMPLE_TEST_2
1581 // Test 2: use_offset = true, use_subframes = false
1582 cout
<< "use_offset = true, use_subframes = false" << endl
;
1584 timecode1
.hours
= 0;
1585 timecode1
.minutes
= 0;
1586 timecode1
.seconds
= 0;
1587 timecode1
.frames
= 0;
1588 timecode1
.subframes
= 0;
1589 sample1
= oldsample
= 0;
1591 _session
->sample_to_timecode( sample1
, timecode1
, true /* use_offset */, false /* use_subframes */ );
1592 cout
<< "Starting at sample: " << sample1
<< " -> ";
1593 cout
<< "timecode: " << (timecode1
.negative
? "-" : "") << timecode1
.hours
<< ":" << timecode1
.minutes
<< ":" << timecode1
.seconds
<< ":" << timecode1
.frames
<< "::" << timecode1
.subframes
<< endl
;
1595 for (int i
= 0; i
< 108003; i
++) {
1596 _session
->timecode_to_sample( timecode1
, sample1
, true /* use_offset */, false /* use_subframes */ );
1597 _session
->sample_to_timecode( sample1
, timecode2
, true /* use_offset */, false /* use_subframes */ );
1599 // cout << "timecode: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << " -> ";
1600 // cout << "sample: " << sample1 << endl;
1601 // cout << "sample: " << sample1 << " -> ";
1602 // cout << "timecode: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
1604 if ((i
> 0) && ( ((sample1
- oldsample
) != sample_increment
) && ((sample1
- oldsample
) != (sample_increment
+ 1)) && ((sample1
- oldsample
) != (sample_increment
- 1)))) {
1605 cout
<< "ERROR: sample increment not right: " << (sample1
- oldsample
) << " != " << sample_increment
<< endl
;
1606 cout
<< "timecode1: " << (timecode1
.negative
? "-" : "") << timecode1
.hours
<< ":" << timecode1
.minutes
<< ":" << timecode1
.seconds
<< ":" << timecode1
.frames
<< "::" << timecode1
.subframes
<< " -> ";
1607 cout
<< "sample: " << sample1
<< endl
;
1608 cout
<< "sample: " << sample1
<< " -> ";
1609 cout
<< "timecode2: " << (timecode2
.negative
? "-" : "") << timecode2
.hours
<< ":" << timecode2
.minutes
<< ":" << timecode2
.seconds
<< ":" << timecode2
.frames
<< "::" << timecode2
.subframes
<< endl
;
1613 if (timecode2
.hours
!= timecode1
.hours
|| timecode2
.minutes
!= timecode1
.minutes
|| timecode2
.seconds
!= timecode2
.seconds
|| timecode2
.frames
!= timecode1
.frames
) {
1614 cout
<< "ERROR: timecode2 not equal timecode1" << endl
;
1615 cout
<< "timecode1: " << (timecode1
.negative
? "-" : "") << timecode1
.hours
<< ":" << timecode1
.minutes
<< ":" << timecode1
.seconds
<< ":" << timecode1
.frames
<< "::" << timecode1
.subframes
<< " -> ";
1616 cout
<< "sample: " << sample1
<< endl
;
1617 cout
<< "sample: " << sample1
<< " -> ";
1618 cout
<< "timecode2: " << (timecode2
.negative
? "-" : "") << timecode2
.hours
<< ":" << timecode2
.minutes
<< ":" << timecode2
.seconds
<< ":" << timecode2
.frames
<< "::" << timecode2
.subframes
<< endl
;
1621 oldsample
= sample1
;
1622 _session
->timecode_increment( timecode1
);
1625 cout
<< "sample_increment: " << sample_increment
<< endl
;
1626 cout
<< "sample: " << sample1
<< " -> ";
1627 cout
<< "timecode: " << (timecode2
.negative
? "-" : "") << timecode2
.hours
<< ":" << timecode2
.minutes
<< ":" << timecode2
.seconds
<< ":" << timecode2
.frames
<< "::" << timecode2
.subframes
<< endl
;
1630 #ifdef Timecode_SAMPLE_TEST_3
1631 // Test 3: use_offset = true, use_subframes = false, decrement
1632 cout
<< "use_offset = true, use_subframes = false, decrement" << endl
;
1634 _session
->sample_to_timecode( sample1
, timecode1
, true /* use_offset */, false /* use_subframes */ );
1635 cout
<< "Starting at sample: " << sample1
<< " -> ";
1636 cout
<< "timecode: " << (timecode1
.negative
? "-" : "") << timecode1
.hours
<< ":" << timecode1
.minutes
<< ":" << timecode1
.seconds
<< ":" << timecode1
.frames
<< "::" << timecode1
.subframes
<< endl
;
1638 for (int i
= 0; i
< 108003; i
++) {
1639 _session
->timecode_to_sample( timecode1
, sample1
, true /* use_offset */, false /* use_subframes */ );
1640 _session
->sample_to_timecode( sample1
, timecode2
, true /* use_offset */, false /* use_subframes */ );
1642 // cout << "timecode: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << " -> ";
1643 // cout << "sample: " << sample1 << endl;
1644 // cout << "sample: " << sample1 << " -> ";
1645 // cout << "timecode: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
1647 if ((i
> 0) && ( ((oldsample
- sample1
) != sample_increment
) && ((oldsample
- sample1
) != (sample_increment
+ 1)) && ((oldsample
- sample1
) != (sample_increment
- 1)))) {
1648 cout
<< "ERROR: sample increment not right: " << (oldsample
- sample1
) << " != " << sample_increment
<< endl
;
1649 cout
<< "timecode1: " << (timecode1
.negative
? "-" : "") << timecode1
.hours
<< ":" << timecode1
.minutes
<< ":" << timecode1
.seconds
<< ":" << timecode1
.frames
<< "::" << timecode1
.subframes
<< " -> ";
1650 cout
<< "sample: " << sample1
<< endl
;
1651 cout
<< "sample: " << sample1
<< " -> ";
1652 cout
<< "timecode2: " << (timecode2
.negative
? "-" : "") << timecode2
.hours
<< ":" << timecode2
.minutes
<< ":" << timecode2
.seconds
<< ":" << timecode2
.frames
<< "::" << timecode2
.subframes
<< endl
;
1656 if (timecode2
.hours
!= timecode1
.hours
|| timecode2
.minutes
!= timecode1
.minutes
|| timecode2
.seconds
!= timecode2
.seconds
|| timecode2
.frames
!= timecode1
.frames
) {
1657 cout
<< "ERROR: timecode2 not equal timecode1" << endl
;
1658 cout
<< "timecode1: " << (timecode1
.negative
? "-" : "") << timecode1
.hours
<< ":" << timecode1
.minutes
<< ":" << timecode1
.seconds
<< ":" << timecode1
.frames
<< "::" << timecode1
.subframes
<< " -> ";
1659 cout
<< "sample: " << sample1
<< endl
;
1660 cout
<< "sample: " << sample1
<< " -> ";
1661 cout
<< "timecode2: " << (timecode2
.negative
? "-" : "") << timecode2
.hours
<< ":" << timecode2
.minutes
<< ":" << timecode2
.seconds
<< ":" << timecode2
.frames
<< "::" << timecode2
.subframes
<< endl
;
1664 oldsample
= sample1
;
1665 _session
->timecode_decrement( timecode1
);
1668 cout
<< "sample_decrement: " << sample_increment
<< endl
;
1669 cout
<< "sample: " << sample1
<< " -> ";
1670 cout
<< "timecode: " << (timecode2
.negative
? "-" : "") << timecode2
.hours
<< ":" << timecode2
.minutes
<< ":" << timecode2
.seconds
<< ":" << timecode2
.frames
<< "::" << timecode2
.subframes
<< endl
;
1674 #ifdef Timecode_SAMPLE_TEST_4
1675 // Test 4: use_offset = true, use_subframes = true
1676 cout
<< "use_offset = true, use_subframes = true" << endl
;
1678 for (long sub
= 5; sub
< 80; sub
+= 5) {
1679 timecode1
.hours
= 0;
1680 timecode1
.minutes
= 0;
1681 timecode1
.seconds
= 0;
1682 timecode1
.frames
= 0;
1683 timecode1
.subframes
= 0;
1684 sample1
= oldsample
= (sample_increment
* sub
) / 80;
1686 _session
->sample_to_timecode( sample1
, timecode1
, true /* use_offset */, true /* use_subframes */ );
1688 cout
<< "starting at sample: " << sample1
<< " -> ";
1689 cout
<< "timecode: " << (timecode1
.negative
? "-" : "") << timecode1
.hours
<< ":" << timecode1
.minutes
<< ":" << timecode1
.seconds
<< ":" << timecode1
.frames
<< "::" << timecode1
.subframes
<< endl
;
1691 for (int i
= 0; i
< 108003; i
++) {
1692 _session
->timecode_to_sample( timecode1
, sample1
, true /* use_offset */, true /* use_subframes */ );
1693 _session
->sample_to_timecode( sample1
, timecode2
, true /* use_offset */, true /* use_subframes */ );
1695 if ((i
> 0) && ( ((sample1
- oldsample
) != sample_increment
) && ((sample1
- oldsample
) != (sample_increment
+ 1)) && ((sample1
- oldsample
) != (sample_increment
- 1)))) {
1696 cout
<< "ERROR: sample increment not right: " << (sample1
- oldsample
) << " != " << sample_increment
<< endl
;
1697 cout
<< "timecode1: " << (timecode1
.negative
? "-" : "") << timecode1
.hours
<< ":" << timecode1
.minutes
<< ":" << timecode1
.seconds
<< ":" << timecode1
.frames
<< "::" << timecode1
.subframes
<< " -> ";
1698 cout
<< "sample: " << sample1
<< endl
;
1699 cout
<< "sample: " << sample1
<< " -> ";
1700 cout
<< "timecode2: " << (timecode2
.negative
? "-" : "") << timecode2
.hours
<< ":" << timecode2
.minutes
<< ":" << timecode2
.seconds
<< ":" << timecode2
.frames
<< "::" << timecode2
.subframes
<< endl
;
1704 if (timecode2
.hours
!= timecode1
.hours
|| timecode2
.minutes
!= timecode1
.minutes
|| timecode2
.seconds
!= timecode2
.seconds
|| timecode2
.frames
!= timecode1
.frames
|| timecode2
.subframes
!= timecode1
.subframes
) {
1705 cout
<< "ERROR: timecode2 not equal timecode1" << endl
;
1706 cout
<< "timecode1: " << (timecode1
.negative
? "-" : "") << timecode1
.hours
<< ":" << timecode1
.minutes
<< ":" << timecode1
.seconds
<< ":" << timecode1
.frames
<< "::" << timecode1
.subframes
<< " -> ";
1707 cout
<< "sample: " << sample1
<< endl
;
1708 cout
<< "sample: " << sample1
<< " -> ";
1709 cout
<< "timecode2: " << (timecode2
.negative
? "-" : "") << timecode2
.hours
<< ":" << timecode2
.minutes
<< ":" << timecode2
.seconds
<< ":" << timecode2
.frames
<< "::" << timecode2
.subframes
<< endl
;
1712 oldsample
= sample1
;
1713 _session
->timecode_increment( timecode1
);
1716 cout
<< "sample_increment: " << sample_increment
<< endl
;
1717 cout
<< "sample: " << sample1
<< " -> ";
1718 cout
<< "timecode: " << (timecode2
.negative
? "-" : "") << timecode2
.hours
<< ":" << timecode2
.minutes
<< ":" << timecode2
.seconds
<< ":" << timecode2
.frames
<< "::" << timecode2
.subframes
<< endl
;
1720 for (int i
= 0; i
< 108003; i
++) {
1721 _session
->timecode_to_sample( timecode1
, sample1
, true /* use_offset */, true /* use_subframes */ );
1722 _session
->sample_to_timecode( sample1
, timecode2
, true /* use_offset */, true /* use_subframes */ );
1724 if ((i
> 0) && ( ((oldsample
- sample1
) != sample_increment
) && ((oldsample
- sample1
) != (sample_increment
+ 1)) && ((oldsample
- sample1
) != (sample_increment
- 1)))) {
1725 cout
<< "ERROR: sample increment not right: " << (oldsample
- sample1
) << " != " << sample_increment
<< endl
;
1726 cout
<< "timecode1: " << (timecode1
.negative
? "-" : "") << timecode1
.hours
<< ":" << timecode1
.minutes
<< ":" << timecode1
.seconds
<< ":" << timecode1
.frames
<< "::" << timecode1
.subframes
<< " -> ";
1727 cout
<< "sample: " << sample1
<< endl
;
1728 cout
<< "sample: " << sample1
<< " -> ";
1729 cout
<< "timecode2: " << (timecode2
.negative
? "-" : "") << timecode2
.hours
<< ":" << timecode2
.minutes
<< ":" << timecode2
.seconds
<< ":" << timecode2
.frames
<< "::" << timecode2
.subframes
<< endl
;
1733 if (timecode2
.hours
!= timecode1
.hours
|| timecode2
.minutes
!= timecode1
.minutes
|| timecode2
.seconds
!= timecode2
.seconds
|| timecode2
.frames
!= timecode1
.frames
|| timecode2
.subframes
!= timecode1
.subframes
) {
1734 cout
<< "ERROR: timecode2 not equal timecode1" << endl
;
1735 cout
<< "timecode1: " << (timecode1
.negative
? "-" : "") << timecode1
.hours
<< ":" << timecode1
.minutes
<< ":" << timecode1
.seconds
<< ":" << timecode1
.frames
<< "::" << timecode1
.subframes
<< " -> ";
1736 cout
<< "sample: " << sample1
<< endl
;
1737 cout
<< "sample: " << sample1
<< " -> ";
1738 cout
<< "timecode2: " << (timecode2
.negative
? "-" : "") << timecode2
.hours
<< ":" << timecode2
.minutes
<< ":" << timecode2
.seconds
<< ":" << timecode2
.frames
<< "::" << timecode2
.subframes
<< endl
;
1741 oldsample
= sample1
;
1742 _session
->timecode_decrement( timecode1
);
1745 cout
<< "sample_decrement: " << sample_increment
<< endl
;
1746 cout
<< "sample: " << sample1
<< " -> ";
1747 cout
<< "timecode: " << (timecode2
.negative
? "-" : "") << timecode2
.hours
<< ":" << timecode2
.minutes
<< ":" << timecode2
.seconds
<< ":" << timecode2
.frames
<< "::" << timecode2
.subframes
<< endl
;
1752 #ifdef Timecode_SAMPLE_TEST_5
1753 // Test 5: use_offset = true, use_subframes = false, increment seconds
1754 cout
<< "use_offset = true, use_subframes = false, increment seconds" << endl
;
1756 timecode1
.hours
= 0;
1757 timecode1
.minutes
= 0;
1758 timecode1
.seconds
= 0;
1759 timecode1
.frames
= 0;
1760 timecode1
.subframes
= 0;
1761 sample1
= oldsample
= 0;
1762 sample_increment
= _session
->frame_rate();
1764 _session
->sample_to_timecode( sample1
, timecode1
, true /* use_offset */, false /* use_subframes */ );
1765 cout
<< "Starting at sample: " << sample1
<< " -> ";
1766 cout
<< "timecode: " << (timecode1
.negative
? "-" : "") << timecode1
.hours
<< ":" << timecode1
.minutes
<< ":" << timecode1
.seconds
<< ":" << timecode1
.frames
<< "::" << timecode1
.subframes
<< endl
;
1768 for (int i
= 0; i
< 3600; i
++) {
1769 _session
->timecode_to_sample( timecode1
, sample1
, true /* use_offset */, false /* use_subframes */ );
1770 _session
->sample_to_timecode( sample1
, timecode2
, true /* use_offset */, false /* use_subframes */ );
1772 // cout << "timecode: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << " -> ";
1773 // cout << "sample: " << sample1 << endl;
1774 // cout << "sample: " << sample1 << " -> ";
1775 // cout << "timecode: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
1777 // if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1779 // cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1783 if (timecode2
.hours
!= timecode1
.hours
|| timecode2
.minutes
!= timecode1
.minutes
|| timecode2
.seconds
!= timecode2
.seconds
|| timecode2
.frames
!= timecode1
.frames
) {
1784 cout
<< "ERROR: timecode2 not equal timecode1" << endl
;
1785 cout
<< "timecode: " << (timecode1
.negative
? "-" : "") << timecode1
.hours
<< ":" << timecode1
.minutes
<< ":" << timecode1
.seconds
<< ":" << timecode1
.frames
<< "::" << timecode1
.subframes
<< " -> ";
1786 cout
<< "sample: " << sample1
<< endl
;
1787 cout
<< "sample: " << sample1
<< " -> ";
1788 cout
<< "timecode: " << (timecode2
.negative
? "-" : "") << timecode2
.hours
<< ":" << timecode2
.minutes
<< ":" << timecode2
.seconds
<< ":" << timecode2
.frames
<< "::" << timecode2
.subframes
<< endl
;
1791 oldsample
= sample1
;
1792 _session
->timecode_increment_seconds( timecode1
);
1795 cout
<< "sample_increment: " << sample_increment
<< endl
;
1796 cout
<< "sample: " << sample1
<< " -> ";
1797 cout
<< "timecode: " << (timecode2
.negative
? "-" : "") << timecode2
.hours
<< ":" << timecode2
.minutes
<< ":" << timecode2
.seconds
<< ":" << timecode2
.frames
<< "::" << timecode2
.subframes
<< endl
;
1801 #ifdef Timecode_SAMPLE_TEST_6
1802 // Test 6: use_offset = true, use_subframes = false, increment minutes
1803 cout
<< "use_offset = true, use_subframes = false, increment minutes" << endl
;
1805 timecode1
.hours
= 0;
1806 timecode1
.minutes
= 0;
1807 timecode1
.seconds
= 0;
1808 timecode1
.frames
= 0;
1809 timecode1
.subframes
= 0;
1810 sample1
= oldsample
= 0;
1811 sample_increment
= _session
->frame_rate() * 60;
1813 _session
->sample_to_timecode( sample1
, timecode1
, true /* use_offset */, false /* use_subframes */ );
1814 cout
<< "Starting at sample: " << sample1
<< " -> ";
1815 cout
<< "timecode: " << (timecode1
.negative
? "-" : "") << timecode1
.hours
<< ":" << timecode1
.minutes
<< ":" << timecode1
.seconds
<< ":" << timecode1
.frames
<< "::" << timecode1
.subframes
<< endl
;
1817 for (int i
= 0; i
< 60; i
++) {
1818 _session
->timecode_to_sample( timecode1
, sample1
, true /* use_offset */, false /* use_subframes */ );
1819 _session
->sample_to_timecode( sample1
, timecode2
, true /* use_offset */, false /* use_subframes */ );
1821 // cout << "timecode: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << " -> ";
1822 // cout << "sample: " << sample1 << endl;
1823 // cout << "sample: " << sample1 << " -> ";
1824 // cout << "timecode: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
1826 // if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1828 // cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1832 if (timecode2
.hours
!= timecode1
.hours
|| timecode2
.minutes
!= timecode1
.minutes
|| timecode2
.seconds
!= timecode2
.seconds
|| timecode2
.frames
!= timecode1
.frames
) {
1833 cout
<< "ERROR: timecode2 not equal timecode1" << endl
;
1834 cout
<< "timecode: " << (timecode1
.negative
? "-" : "") << timecode1
.hours
<< ":" << timecode1
.minutes
<< ":" << timecode1
.seconds
<< ":" << timecode1
.frames
<< "::" << timecode1
.subframes
<< " -> ";
1835 cout
<< "sample: " << sample1
<< endl
;
1836 cout
<< "sample: " << sample1
<< " -> ";
1837 cout
<< "timecode: " << (timecode2
.negative
? "-" : "") << timecode2
.hours
<< ":" << timecode2
.minutes
<< ":" << timecode2
.seconds
<< ":" << timecode2
.frames
<< "::" << timecode2
.subframes
<< endl
;
1840 oldsample
= sample1
;
1841 _session
->timecode_increment_minutes( timecode1
);
1844 cout
<< "sample_increment: " << sample_increment
<< endl
;
1845 cout
<< "sample: " << sample1
<< " -> ";
1846 cout
<< "timecode: " << (timecode2
.negative
? "-" : "") << timecode2
.hours
<< ":" << timecode2
.minutes
<< ":" << timecode2
.seconds
<< ":" << timecode2
.frames
<< "::" << timecode2
.subframes
<< endl
;
1849 #ifdef Timecode_SAMPLE_TEST_7
1850 // Test 7: use_offset = true, use_subframes = false, increment hours
1851 cout
<< "use_offset = true, use_subframes = false, increment hours" << endl
;
1853 timecode1
.hours
= 0;
1854 timecode1
.minutes
= 0;
1855 timecode1
.seconds
= 0;
1856 timecode1
.frames
= 0;
1857 timecode1
.subframes
= 0;
1858 sample1
= oldsample
= 0;
1859 sample_increment
= _session
->frame_rate() * 60 * 60;
1861 _session
->sample_to_timecode( sample1
, timecode1
, true /* use_offset */, false /* use_subframes */ );
1862 cout
<< "Starting at sample: " << sample1
<< " -> ";
1863 cout
<< "timecode: " << (timecode1
.negative
? "-" : "") << timecode1
.hours
<< ":" << timecode1
.minutes
<< ":" << timecode1
.seconds
<< ":" << timecode1
.frames
<< "::" << timecode1
.subframes
<< endl
;
1865 for (int i
= 0; i
< 10; i
++) {
1866 _session
->timecode_to_sample( timecode1
, sample1
, true /* use_offset */, false /* use_subframes */ );
1867 _session
->sample_to_timecode( sample1
, timecode2
, true /* use_offset */, false /* use_subframes */ );
1869 // cout << "timecode: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << " -> ";
1870 // cout << "sample: " << sample1 << endl;
1871 // cout << "sample: " << sample1 << " -> ";
1872 // cout << "timecode: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
1874 // if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1876 // cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1880 if (timecode2
.hours
!= timecode1
.hours
|| timecode2
.minutes
!= timecode1
.minutes
|| timecode2
.seconds
!= timecode2
.seconds
|| timecode2
.frames
!= timecode1
.frames
) {
1881 cout
<< "ERROR: timecode2 not equal timecode1" << endl
;
1882 cout
<< "timecode: " << (timecode1
.negative
? "-" : "") << timecode1
.hours
<< ":" << timecode1
.minutes
<< ":" << timecode1
.seconds
<< ":" << timecode1
.frames
<< "::" << timecode1
.subframes
<< " -> ";
1883 cout
<< "sample: " << sample1
<< endl
;
1884 cout
<< "sample: " << sample1
<< " -> ";
1885 cout
<< "timecode: " << (timecode2
.negative
? "-" : "") << timecode2
.hours
<< ":" << timecode2
.minutes
<< ":" << timecode2
.seconds
<< ":" << timecode2
.frames
<< "::" << timecode2
.subframes
<< endl
;
1888 oldsample
= sample1
;
1889 _session
->timecode_increment_hours( timecode1
);
1892 cout
<< "sample_increment: " << sample_increment
<< endl
;
1893 cout
<< "sample: " << sample1
<< " -> ";
1894 cout
<< "timecode: " << (timecode2
.negative
? "-" : "") << timecode2
.hours
<< ":" << timecode2
.minutes
<< ":" << timecode2
.seconds
<< ":" << timecode2
.frames
<< "::" << timecode2
.subframes
<< endl
;
1903 AudioClock::minsec_frame_from_display () const
1905 if (_session
== 0) {
1909 int hrs
= atoi (ms_hours_label
.get_text());
1910 int mins
= atoi (ms_minutes_label
.get_text());
1911 float secs
= atof (ms_seconds_label
.get_text());
1913 framecnt_t sr
= _session
->frame_rate();
1915 return (framepos_t
) floor ((hrs
* 60.0f
* 60.0f
* sr
) + (mins
* 60.0f
* sr
) + (secs
* sr
));
1919 AudioClock::bbt_frame_from_display (framepos_t pos
) const
1921 if (_session
== 0) {
1922 error
<< "AudioClock::current_time() called with BBT mode but without session!" << endmsg
;
1927 any
.type
= AnyTime::BBT
;
1929 any
.bbt
.bars
= atoi (bars_label
.get_text());
1930 any
.bbt
.beats
= atoi (beats_label
.get_text());
1931 any
.bbt
.ticks
= atoi (ticks_label
.get_text());
1936 return _session
->any_duration_to_frames (pos
, any
);
1938 return _session
->convert_to_frames (any
);
1944 AudioClock::bbt_frame_duration_from_display (framepos_t pos
) const
1946 if (_session
== 0) {
1947 error
<< "AudioClock::current_time() called with BBT mode but without session!" << endmsg
;
1951 Timecode::BBT_Time bbt
;
1954 bbt
.bars
= atoi (bars_label
.get_text());
1955 bbt
.beats
= atoi (beats_label
.get_text());
1956 bbt
.ticks
= atoi (ticks_label
.get_text());
1958 return _session
->tempo_map().bbt_duration_at(pos
,bbt
,1);
1962 AudioClock::audio_frame_from_display () const
1964 return (framepos_t
) atoi (audio_frames_label
.get_text());
1968 AudioClock::build_ops_menu ()
1970 using namespace Menu_Helpers
;
1971 ops_menu
= new Menu
;
1972 MenuList
& ops_items
= ops_menu
->items();
1973 ops_menu
->set_name ("ArdourContextMenu");
1975 if (!Profile
->get_sae()) {
1976 ops_items
.push_back (MenuElem (_("Timecode"), sigc::bind (sigc::mem_fun(*this, &AudioClock::set_mode
), Timecode
)));
1978 ops_items
.push_back (MenuElem (_("Bars:Beats"), sigc::bind (sigc::mem_fun(*this, &AudioClock::set_mode
), BBT
)));
1979 ops_items
.push_back (MenuElem (_("Minutes:Seconds"), sigc::bind (sigc::mem_fun(*this, &AudioClock::set_mode
), MinSec
)));
1980 ops_items
.push_back (MenuElem (_("Samples"), sigc::bind (sigc::mem_fun(*this, &AudioClock::set_mode
), Frames
)));
1981 ops_items
.push_back (MenuElem (_("Off"), sigc::bind (sigc::mem_fun(*this, &AudioClock::set_mode
), Off
)));
1983 if (editable
&& !is_duration
&& !_follows_playhead
) {
1984 ops_items
.push_back (SeparatorElem());
1985 ops_items
.push_back (MenuElem (_("Set From Playhead"), sigc::mem_fun(*this, &AudioClock::set_from_playhead
)));
1986 ops_items
.push_back (MenuElem (_("Locate to This Time"), sigc::mem_fun(*this, &AudioClock::locate
)));
1991 AudioClock::set_from_playhead ()
1997 set (_session
->transport_frame());
2002 AudioClock::locate ()
2004 if (!_session
|| is_duration
) {
2008 _session
->request_locate (current_time(), _session
->transport_rolling ());
2012 AudioClock::set_mode (Mode m
)
2014 /* slightly tricky: this is called from within the ARDOUR_UI
2015 constructor by some of its clock members. at that time
2016 the instance pointer is unset, so we have to be careful.
2017 the main idea is to drop keyboard focus in case we had
2018 started editing the clock and then we switch clock mode.
2021 clock_base
.grab_focus ();
2027 clock_base
.remove ();
2033 clock_base
.add (timecode_packer_hbox
);
2037 clock_base
.add (bbt_packer_hbox
);
2041 clock_base
.add (minsec_packer_hbox
);
2045 clock_base
.add (frames_packer_hbox
);
2049 clock_base
.add (off_hbox
);
2053 set_size_requests ();
2055 set (last_when
, true);
2056 clock_base
.show_all ();
2057 key_entry_state
= 0;
2059 if (!is_transient
) {
2060 ModeChanged (); /* EMIT SIGNAL (the static one)*/
2063 mode_changed (); /* EMIT SIGNAL (the member one) */
2067 AudioClock::set_size_requests ()
2069 /* note that in some fonts, "88" is narrower than "00" */
2073 Gtkmm2ext::set_size_request_to_display_given_text (hours_label
, "-88", 5, 5);
2074 Gtkmm2ext::set_size_request_to_display_given_text (minutes_label
, "88", 5, 5);
2075 Gtkmm2ext::set_size_request_to_display_given_text (seconds_label
, "88", 5, 5);
2076 Gtkmm2ext::set_size_request_to_display_given_text (frames_label
, "88", 5, 5);
2080 Gtkmm2ext::set_size_request_to_display_given_text (bars_label
, "-888", 5, 5);
2081 Gtkmm2ext::set_size_request_to_display_given_text (beats_label
, "88", 5, 5);
2082 Gtkmm2ext::set_size_request_to_display_given_text (ticks_label
, "8888", 5, 5);
2086 Gtkmm2ext::set_size_request_to_display_given_text (ms_hours_label
, "88", 5, 5);
2087 Gtkmm2ext::set_size_request_to_display_given_text (ms_minutes_label
, "88", 5, 5);
2088 Gtkmm2ext::set_size_request_to_display_given_text (ms_seconds_label
, "88.888", 5, 5);
2092 Gtkmm2ext::set_size_request_to_display_given_text (audio_frames_label
, "8888888888", 5, 5);
2096 Gtkmm2ext::set_size_request_to_display_given_text (off_hbox
, "00000", 5, 5);
2103 AudioClock::set_bbt_reference (framepos_t pos
)
2105 bbt_reference_time
= pos
;
2109 AudioClock::on_style_changed (const Glib::RefPtr
<Gtk::Style
>& old_style
)
2111 HBox::on_style_changed (old_style
);
2113 /* propagate style changes to all component widgets that should inherit the main one */
2115 Glib::RefPtr
<RcStyle
> rcstyle
= get_modifier_style();
2117 clock_base
.modify_style (rcstyle
);
2118 audio_frames_label
.modify_style (rcstyle
);
2119 hours_label
.modify_style (rcstyle
);
2120 minutes_label
.modify_style (rcstyle
);
2121 seconds_label
.modify_style (rcstyle
);
2122 frames_label
.modify_style (rcstyle
);
2123 bars_label
.modify_style (rcstyle
);
2124 beats_label
.modify_style (rcstyle
);
2125 ticks_label
.modify_style (rcstyle
);
2126 ms_hours_label
.modify_style (rcstyle
);
2127 ms_minutes_label
.modify_style (rcstyle
);
2128 ms_seconds_label
.modify_style (rcstyle
);
2129 hours_ebox
.modify_style (rcstyle
);
2130 minutes_ebox
.modify_style (rcstyle
);
2131 seconds_ebox
.modify_style (rcstyle
);
2132 frames_ebox
.modify_style (rcstyle
);
2133 audio_frames_ebox
.modify_style (rcstyle
);
2134 bars_ebox
.modify_style (rcstyle
);
2135 beats_ebox
.modify_style (rcstyle
);
2136 ticks_ebox
.modify_style (rcstyle
);
2137 ms_hours_ebox
.modify_style (rcstyle
);
2138 ms_minutes_ebox
.modify_style (rcstyle
);
2139 ms_seconds_ebox
.modify_style (rcstyle
);
2141 colon1
.modify_style (rcstyle
);
2142 colon2
.modify_style (rcstyle
);
2143 colon3
.modify_style (rcstyle
);
2144 colon4
.modify_style (rcstyle
);
2145 colon5
.modify_style (rcstyle
);
2146 b1
.modify_style (rcstyle
);
2147 b2
.modify_style (rcstyle
);
2149 set_size_requests ();
2153 AudioClock::set_is_duration (bool yn
)
2155 if (yn
== is_duration
) {
2160 set (last_when
, true, 0, 's');