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.
21 #include <cstdio> // for sprintf
24 #include <pbd/convert.h>
26 #include <gtkmm2ext/utils.h>
28 #include <ardour/ardour.h>
29 #include <ardour/session.h>
30 #include <ardour/tempo.h>
31 #include <sigc++/bind.h>
33 #include "ardour_ui.h"
34 #include "audio_clock.h"
39 using namespace ARDOUR;
47 const uint32_t AudioClock::field_length[(int) AudioClock::AudioFrames+1] = {
49 2, /* SMPTE_Minutes */
50 2, /* SMPTE_Seconds */
61 AudioClock::AudioClock (std::string name, bool allow_edit, bool duration, bool with_info)
62 : is_duration (duration),
63 editable (allow_edit),
79 frames_upper_info_label = manage (new Label);
80 frames_lower_info_label = manage (new Label);
81 smpte_upper_info_label = manage (new Label);
82 smpte_lower_info_label = manage (new Label);
83 bbt_upper_info_label = manage (new Label);
84 bbt_lower_info_label = manage (new Label);
86 frames_upper_info_label->set_name ("AudioClockFramesUpperInfo");
87 frames_lower_info_label->set_name ("AudioClockFramesLowerInfo");
88 smpte_upper_info_label->set_name ("AudioClockSMPTEUpperInfo");
89 smpte_lower_info_label->set_name ("AudioClockSMPTELowerInfo");
90 bbt_upper_info_label->set_name ("AudioClockBBTUpperInfo");
91 bbt_lower_info_label->set_name ("AudioClockBBTLowerInfo");
93 frames_info_box.pack_start (*frames_upper_info_label, true, true);
94 frames_info_box.pack_start (*frames_lower_info_label, true, true);
95 smpte_info_box.pack_start (*smpte_upper_info_label, true, true);
96 smpte_info_box.pack_start (*smpte_lower_info_label, true, true);
97 bbt_info_box.pack_start (*bbt_upper_info_label, true, true);
98 bbt_info_box.pack_start (*bbt_lower_info_label, true, true);
101 frames_upper_info_label = 0;
102 frames_lower_info_label = 0;
103 smpte_upper_info_label = 0;
104 smpte_lower_info_label = 0;
105 bbt_upper_info_label = 0;
106 bbt_lower_info_label = 0;
109 audio_frames_ebox.add (audio_frames_label);
111 frames_packer.set_homogeneous (false);
112 frames_packer.set_border_width (2);
113 frames_packer.pack_start (audio_frames_ebox, false, false);
116 frames_packer.pack_start (frames_info_box, false, false, 5);
119 frames_packer_hbox.pack_start (frames_packer, true, false);
121 hours_ebox.add (hours_label);
122 minutes_ebox.add (minutes_label);
123 seconds_ebox.add (seconds_label);
124 frames_ebox.add (frames_label);
125 bars_ebox.add (bars_label);
126 beats_ebox.add (beats_label);
127 ticks_ebox.add (ticks_label);
128 ms_hours_ebox.add (ms_hours_label);
129 ms_minutes_ebox.add (ms_minutes_label);
130 ms_seconds_ebox.add (ms_seconds_label);
132 smpte_packer.set_homogeneous (false);
133 smpte_packer.set_border_width (2);
134 smpte_packer.pack_start (hours_ebox, false, false);
135 smpte_packer.pack_start (colon1, false, false);
136 smpte_packer.pack_start (minutes_ebox, false, false);
137 smpte_packer.pack_start (colon2, false, false);
138 smpte_packer.pack_start (seconds_ebox, false, false);
139 smpte_packer.pack_start (colon3, false, false);
140 smpte_packer.pack_start (frames_ebox, false, false);
143 smpte_packer.pack_start (smpte_info_box, false, false, 5);
146 smpte_packer_hbox.pack_start (smpte_packer, true, false);
148 bbt_packer.set_homogeneous (false);
149 bbt_packer.set_border_width (2);
150 bbt_packer.pack_start (bars_ebox, false, false);
151 bbt_packer.pack_start (b1, false, false);
152 bbt_packer.pack_start (beats_ebox, false, false);
153 bbt_packer.pack_start (b2, false, false);
154 bbt_packer.pack_start (ticks_ebox, false, false);
157 bbt_packer.pack_start (bbt_info_box, false, false, 5);
160 bbt_packer_hbox.pack_start (bbt_packer, true, false);
162 minsec_packer.set_homogeneous (false);
163 minsec_packer.set_border_width (2);
164 minsec_packer.pack_start (ms_hours_ebox, false, false);
165 minsec_packer.pack_start (colon4, false, false);
166 minsec_packer.pack_start (ms_minutes_ebox, false, false);
167 minsec_packer.pack_start (colon5, false, false);
168 minsec_packer.pack_start (ms_seconds_ebox, false, false);
170 minsec_packer_hbox.pack_start (minsec_packer, true, false);
172 clock_frame.set_shadow_type (Gtk::SHADOW_IN);
173 clock_frame.set_name ("BaseFrame");
175 clock_frame.add (clock_base);
179 _mode = BBT; /* lie to force mode switch */
182 pack_start (clock_frame, true, true);
184 /* the clock base handles button releases for menu popup regardless of
185 editable status. if the clock is editable, the clock base is where
186 we pass focus to after leaving the last editable "field", which
187 will then shutdown editing till the user starts it up again.
189 it does this because the focus out event on the field disables
190 keyboard event handling, and we don't connect anything up to
191 notice focus in on the clock base. hence, keyboard event handling
195 clock_base.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::SCROLL_MASK);
196 clock_base.signal_button_release_event().connect (bind (mem_fun (*this, &AudioClock::field_button_release_event), SMPTE_Hours));
198 Session::SMPTEOffsetChanged.connect (mem_fun (*this, &AudioClock::smpte_offset_changed));
204 set (last_when, true);
208 AudioClock::set_name (string name)
210 Widget::set_name (name);
212 clock_base.set_name (name);
214 audio_frames_label.set_name (name);
215 hours_label.set_name (name);
216 minutes_label.set_name (name);
217 seconds_label.set_name (name);
218 frames_label.set_name (name);
219 bars_label.set_name (name);
220 beats_label.set_name (name);
221 ticks_label.set_name (name);
222 ms_hours_label.set_name (name);
223 ms_minutes_label.set_name (name);
224 ms_seconds_label.set_name (name);
225 hours_ebox.set_name (name);
226 minutes_ebox.set_name (name);
227 seconds_ebox.set_name (name);
228 frames_ebox.set_name (name);
229 audio_frames_ebox.set_name (name);
230 bars_ebox.set_name (name);
231 beats_ebox.set_name (name);
232 ticks_ebox.set_name (name);
233 ms_hours_ebox.set_name (name);
234 ms_minutes_ebox.set_name (name);
235 ms_seconds_ebox.set_name (name);
237 colon1.set_name (name);
238 colon2.set_name (name);
239 colon3.set_name (name);
240 colon4.set_name (name);
241 colon5.set_name (name);
249 AudioClock::setup_events ()
251 clock_base.set_flags (Gtk::CAN_FOCUS);
253 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);
254 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);
255 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);
256 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);
257 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);
258 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);
259 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);
260 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);
261 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);
262 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);
263 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);
265 hours_ebox.set_flags (Gtk::CAN_FOCUS);
266 minutes_ebox.set_flags (Gtk::CAN_FOCUS);
267 seconds_ebox.set_flags (Gtk::CAN_FOCUS);
268 frames_ebox.set_flags (Gtk::CAN_FOCUS);
269 audio_frames_ebox.set_flags (Gtk::CAN_FOCUS);
270 bars_ebox.set_flags (Gtk::CAN_FOCUS);
271 beats_ebox.set_flags (Gtk::CAN_FOCUS);
272 ticks_ebox.set_flags (Gtk::CAN_FOCUS);
273 ms_hours_ebox.set_flags (Gtk::CAN_FOCUS);
274 ms_minutes_ebox.set_flags (Gtk::CAN_FOCUS);
275 ms_seconds_ebox.set_flags (Gtk::CAN_FOCUS);
277 hours_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), SMPTE_Hours));
278 minutes_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), SMPTE_Minutes));
279 seconds_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), SMPTE_Seconds));
280 frames_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), SMPTE_Frames));
281 audio_frames_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), AudioFrames));
282 bars_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), Bars));
283 beats_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), Beats));
284 ticks_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), Ticks));
285 ms_hours_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), MS_Hours));
286 ms_minutes_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), MS_Minutes));
287 ms_seconds_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), MS_Seconds));
289 hours_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), SMPTE_Hours));
290 minutes_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), SMPTE_Minutes));
291 seconds_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), SMPTE_Seconds));
292 frames_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), SMPTE_Frames));
293 audio_frames_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), AudioFrames));
294 bars_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), Bars));
295 beats_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), Beats));
296 ticks_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), Ticks));
297 ms_hours_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), MS_Hours));
298 ms_minutes_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), MS_Minutes));
299 ms_seconds_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), MS_Seconds));
301 hours_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), SMPTE_Hours));
302 minutes_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), SMPTE_Minutes));
303 seconds_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), SMPTE_Seconds));
304 frames_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), SMPTE_Frames));
305 audio_frames_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), AudioFrames));
306 bars_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), Bars));
307 beats_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), Beats));
308 ticks_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), Ticks));
309 ms_hours_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), MS_Hours));
310 ms_minutes_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), MS_Minutes));
311 ms_seconds_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), MS_Seconds));
313 hours_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), SMPTE_Hours));
314 minutes_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), SMPTE_Minutes));
315 seconds_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), SMPTE_Seconds));
316 frames_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), SMPTE_Frames));
317 audio_frames_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), AudioFrames));
318 bars_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), Bars));
319 beats_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), Beats));
320 ticks_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), Ticks));
321 ms_hours_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), MS_Hours));
322 ms_minutes_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), MS_Minutes));
323 ms_seconds_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), MS_Seconds));
325 hours_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), SMPTE_Hours));
326 minutes_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), SMPTE_Minutes));
327 seconds_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), SMPTE_Seconds));
328 frames_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), SMPTE_Frames));
329 audio_frames_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), AudioFrames));
330 bars_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), Bars));
331 beats_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), Beats));
332 ticks_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), Ticks));
333 ms_hours_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), MS_Hours));
334 ms_minutes_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), MS_Minutes));
335 ms_seconds_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), MS_Seconds));
337 hours_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), SMPTE_Hours));
338 minutes_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), SMPTE_Minutes));
339 seconds_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), SMPTE_Seconds));
340 frames_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), SMPTE_Frames));
341 audio_frames_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), AudioFrames));
342 bars_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), Bars));
343 beats_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), Beats));
344 ticks_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), Ticks));
345 ms_hours_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), MS_Hours));
346 ms_minutes_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), MS_Minutes));
347 ms_seconds_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), MS_Seconds));
349 hours_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), SMPTE_Hours));
350 minutes_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), SMPTE_Minutes));
351 seconds_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), SMPTE_Seconds));
352 frames_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), SMPTE_Frames));
353 audio_frames_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), AudioFrames));
354 bars_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), Bars));
355 beats_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), Beats));
356 ticks_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), Ticks));
357 ms_hours_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), MS_Hours));
358 ms_minutes_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), MS_Minutes));
359 ms_seconds_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), MS_Seconds));
363 AudioClock::on_realize ()
367 /* styles are not available until the widgets are bound to a window */
369 set_size_requests ();
373 AudioClock::set (nframes_t when, bool force)
376 if ((!force && !is_visible()) || session == 0) {
380 if (when == last_when && !force) {
386 set_smpte (when, force);
390 set_bbt (when, force);
394 set_minsec (when, force);
398 set_frames (when, force);
409 AudioClock::smpte_offset_changed ()
416 current = current_duration();
418 current = current_time ();
428 AudioClock::set_frames (nframes_t when, bool force)
431 snprintf (buf, sizeof (buf), "%u", when);
432 audio_frames_label.set_text (buf);
434 if (frames_upper_info_label) {
435 nframes_t rate = session->frame_rate();
437 if (fmod (rate, 1000.0) == 0.000) {
438 sprintf (buf, "%uK", rate/1000);
440 sprintf (buf, "%.3fK", rate/1000.0f);
443 frames_upper_info_label->set_text (buf);
445 float vid_pullup = Config->get_video_pullup();
447 if (vid_pullup == 0.0) {
448 frames_lower_info_label->set_text(_("none"));
450 sprintf (buf, "%-6.4f", vid_pullup);
451 frames_lower_info_label->set_text (buf);
457 AudioClock::set_minsec (nframes_t when, bool force)
466 hrs = (int) floor (left / (session->frame_rate() * 60.0f * 60.0f));
467 left -= (nframes_t) floor (hrs * session->frame_rate() * 60.0f * 60.0f);
468 mins = (int) floor (left / (session->frame_rate() * 60.0f));
469 left -= (nframes_t) floor (mins * session->frame_rate() * 60.0f);
470 secs = left / (float) session->frame_rate();
472 if (force || hrs != ms_last_hrs) {
473 sprintf (buf, "%02d", hrs);
474 ms_hours_label.set_text (buf);
478 if (force || mins != ms_last_mins) {
479 sprintf (buf, "%02d", mins);
480 ms_minutes_label.set_text (buf);
484 if (force || secs != ms_last_secs) {
485 sprintf (buf, "%06.3f", secs);
486 ms_seconds_label.set_text (buf);
492 AudioClock::set_smpte (nframes_t when, bool force)
498 session->smpte_duration (when, smpte);
500 session->smpte_time (when, smpte);
503 if (force || smpte.hours != last_hrs || smpte.negative != last_negative) {
504 if (smpte.negative) {
505 sprintf (buf, "-%02" PRIu32, smpte.hours);
507 sprintf (buf, " %02" PRIu32, smpte.hours);
509 hours_label.set_text (buf);
510 last_hrs = smpte.hours;
511 last_negative = smpte.negative;
514 if (force || smpte.minutes != last_mins) {
515 sprintf (buf, "%02" PRIu32, smpte.minutes);
516 minutes_label.set_text (buf);
517 last_mins = smpte.minutes;
520 if (force || smpte.seconds != last_secs) {
521 sprintf (buf, "%02" PRIu32, smpte.seconds);
522 seconds_label.set_text (buf);
523 last_secs = smpte.seconds;
526 if (force || smpte.frames != last_frames) {
527 sprintf (buf, "%02" PRIu32, smpte.frames);
528 frames_label.set_text (buf);
529 last_frames = smpte.frames;
532 if (smpte_upper_info_label) {
533 float smpte_frames = Config->get_smpte_frames_per_second();
535 if ( fmod(smpte_frames, 1.0) == 0.0) {
536 sprintf (buf, "%u", int (smpte_frames));
538 sprintf (buf, "%.2f", smpte_frames);
541 smpte_upper_info_label->set_text (buf);
543 if (Config->get_smpte_drop_frames()) {
546 sprintf (buf, "NDF");
549 smpte_lower_info_label->set_text (buf);
554 AudioClock::set_bbt (nframes_t when, bool force)
559 session->tempo_map().bbt_time (when, bbt);
560 sprintf (buf, "%03" PRIu32, bbt.bars);
561 bars_label.set_text (buf);
562 sprintf (buf, "%02" PRIu32, bbt.beats);
563 beats_label.set_text (buf);
564 sprintf (buf, "%04" PRIu32, bbt.ticks);
565 ticks_label.set_text (buf);
567 if (bbt_upper_info_label) {
568 TempoMap::Metric m (session->tempo_map().metric_at (when));
569 sprintf (buf, "%-5.2f", m.tempo().beats_per_minute());
570 bbt_lower_info_label->set_text (buf);
571 sprintf (buf, "%g|%g", m.meter().beats_per_bar(), m.meter().note_divisor());
572 bbt_upper_info_label->set_text (buf);
577 AudioClock::set_session (Session *s)
582 set (last_when, true);
587 AudioClock::field_key_release_event (GdkEventKey *ev, Field field)
592 bool move_on = false;
596 label = &hours_label;
599 label = &minutes_label;
602 label = &seconds_label;
605 label = &frames_label;
609 label = &audio_frames_label;
613 label = &ms_hours_label;
616 label = &ms_minutes_label;
619 label = &ms_seconds_label;
626 label = &beats_label;
629 label = &ticks_label;
635 switch (ev->keyval) {
679 if (_mode == MinSec && field == MS_Seconds) {
693 clock_base.grab_focus ();
702 if (key_entry_state == 0) {
704 /* initialize with a fresh new string */
706 if (field != AudioFrames) {
707 for (uint32_t xn = 0; xn < field_length[field] - 1; ++xn) {
716 string existing = label->get_text();
717 if (existing.length() >= field_length[field]) {
718 new_text = existing.substr (1, field_length[field] - 1);
720 new_text = existing.substr (0, field_length[field] - 1);
724 new_text += new_char;
725 label->set_text (new_text);
729 if (key_entry_state == field_length[field]) {
735 if (key_entry_state) {
742 // Check SMPTE fields for sanity (may also adjust fields)
743 smpte_sanitize_display();
749 ValueChanged(); /* EMIT_SIGNAL */
752 /* move on to the next field.
760 minutes_ebox.grab_focus ();
763 seconds_ebox.grab_focus ();
766 frames_ebox.grab_focus ();
769 clock_base.grab_focus ();
774 clock_base.grab_focus ();
780 ms_minutes_ebox.grab_focus ();
783 ms_seconds_ebox.grab_focus ();
786 clock_base.grab_focus ();
792 beats_ebox.grab_focus ();
795 ticks_ebox.grab_focus ();
798 clock_base.grab_focus ();
811 AudioClock::field_focus_in_event (GdkEventFocus *ev, Field field)
817 hours_ebox.set_flags (Gtk::HAS_FOCUS);
818 hours_ebox.set_state (Gtk::STATE_ACTIVE);
821 minutes_ebox.set_flags (Gtk::HAS_FOCUS);
822 minutes_ebox.set_state (Gtk::STATE_ACTIVE);
825 seconds_ebox.set_flags (Gtk::HAS_FOCUS);
826 seconds_ebox.set_state (Gtk::STATE_ACTIVE);
829 frames_ebox.set_flags (Gtk::HAS_FOCUS);
830 frames_ebox.set_state (Gtk::STATE_ACTIVE);
834 audio_frames_ebox.set_flags (Gtk::HAS_FOCUS);
835 audio_frames_ebox.set_state (Gtk::STATE_ACTIVE);
839 ms_hours_ebox.set_flags (Gtk::HAS_FOCUS);
840 ms_hours_ebox.set_state (Gtk::STATE_ACTIVE);
843 ms_minutes_ebox.set_flags (Gtk::HAS_FOCUS);
844 ms_minutes_ebox.set_state (Gtk::STATE_ACTIVE);
847 ms_seconds_ebox.set_flags (Gtk::HAS_FOCUS);
848 ms_seconds_ebox.set_state (Gtk::STATE_ACTIVE);
851 bars_ebox.set_flags (Gtk::HAS_FOCUS);
852 bars_ebox.set_state (Gtk::STATE_ACTIVE);
855 beats_ebox.set_flags (Gtk::HAS_FOCUS);
856 beats_ebox.set_state (Gtk::STATE_ACTIVE);
859 ticks_ebox.set_flags (Gtk::HAS_FOCUS);
860 ticks_ebox.set_state (Gtk::STATE_ACTIVE);
868 AudioClock::field_focus_out_event (GdkEventFocus *ev, Field field)
873 hours_ebox.unset_flags (Gtk::HAS_FOCUS);
874 hours_ebox.set_state (Gtk::STATE_NORMAL);
877 minutes_ebox.unset_flags (Gtk::HAS_FOCUS);
878 minutes_ebox.set_state (Gtk::STATE_NORMAL);
881 seconds_ebox.unset_flags (Gtk::HAS_FOCUS);
882 seconds_ebox.set_state (Gtk::STATE_NORMAL);
885 frames_ebox.unset_flags (Gtk::HAS_FOCUS);
886 frames_ebox.set_state (Gtk::STATE_NORMAL);
890 audio_frames_ebox.unset_flags (Gtk::HAS_FOCUS);
891 audio_frames_ebox.set_state (Gtk::STATE_NORMAL);
895 ms_hours_ebox.unset_flags (Gtk::HAS_FOCUS);
896 ms_hours_ebox.set_state (Gtk::STATE_NORMAL);
899 ms_minutes_ebox.unset_flags (Gtk::HAS_FOCUS);
900 ms_minutes_ebox.set_state (Gtk::STATE_NORMAL);
903 ms_seconds_ebox.unset_flags (Gtk::HAS_FOCUS);
904 ms_seconds_ebox.set_state (Gtk::STATE_NORMAL);
908 bars_ebox.unset_flags (Gtk::HAS_FOCUS);
909 bars_ebox.set_state (Gtk::STATE_NORMAL);
912 beats_ebox.unset_flags (Gtk::HAS_FOCUS);
913 beats_ebox.set_state (Gtk::STATE_NORMAL);
916 ticks_ebox.unset_flags (Gtk::HAS_FOCUS);
917 ticks_ebox.set_state (Gtk::STATE_NORMAL);
925 AudioClock::field_button_release_event (GdkEventButton *ev, Field field)
930 gdk_pointer_ungrab(GDK_CURRENT_TIME);
932 if (ev->y > drag_start_y+1 || ev->y < drag_start_y-1 || Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)){
933 // we actually dragged so return without setting editing focus, or we shift clicked
943 ops_menu->popup (1, ev->time);
947 if (Keyboard::is_context_menu_event (ev)) {
951 ops_menu->popup (1, ev->time);
955 switch (ev->button) {
959 hours_ebox.grab_focus();
962 minutes_ebox.grab_focus();
965 seconds_ebox.grab_focus();
968 frames_ebox.grab_focus();
972 audio_frames_ebox.grab_focus();
976 ms_hours_ebox.grab_focus();
979 ms_minutes_ebox.grab_focus();
982 ms_seconds_ebox.grab_focus();
986 bars_ebox.grab_focus ();
989 beats_ebox.grab_focus ();
992 ticks_ebox.grab_focus ();
1005 AudioClock::field_button_press_event (GdkEventButton *ev, Field field)
1007 if (session == 0) return FALSE;
1009 nframes_t frames = 0;
1011 switch (ev->button) {
1013 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
1015 ValueChanged (); /* EMIT_SIGNAL */
1018 /* make absolutely sure that the pointer is grabbed */
1019 gdk_pointer_grab(ev->window,FALSE ,
1020 GdkEventMask( Gdk::POINTER_MOTION_MASK | Gdk::BUTTON_PRESS_MASK |Gdk::BUTTON_RELEASE_MASK),
1021 NULL,NULL,ev->time);
1024 drag_start_y = ev->y;
1029 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
1031 ValueChanged (); /* EMIT_SIGNAL */
1036 /* used for context sensitive menu */
1041 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
1042 frames = get_frames (field);
1044 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
1047 set (current_time() + frames, true);
1048 ValueChanged (); /* EMIT_SIGNAL */
1054 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
1055 frames = get_frames (field);
1057 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
1061 if ((double)current_time() - (double)frames < 0.0) {
1065 set (current_time() - frames, true);
1068 ValueChanged (); /* EMIT_SIGNAL */
1082 AudioClock::field_button_scroll_event (GdkEventScroll *ev, Field field)
1084 if (session == 0) return FALSE;
1086 nframes_t frames = 0;
1088 switch (ev->direction) {
1091 frames = get_frames (field);
1093 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
1096 set (current_time() + frames, true);
1097 ValueChanged (); /* EMIT_SIGNAL */
1101 case GDK_SCROLL_DOWN:
1102 frames = get_frames (field);
1104 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
1108 if ((double)current_time() - (double)frames < 0.0) {
1111 set (current_time() - frames, true);
1114 ValueChanged (); /* EMIT_SIGNAL */
1127 AudioClock::field_motion_notify_event (GdkEventMotion *ev, Field field)
1129 if (session == 0 || !dragging) {
1133 float pixel_frame_scale_factor = 0.2f;
1136 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
1137 pixel_frame_scale_factor = 0.1f;
1141 if (Keyboard::modifier_state_contains (ev->state,
1142 Keyboard::Control|Keyboard::Alt)) {
1144 pixel_frame_scale_factor = 0.025f;
1147 double y_delta = ev->y - drag_y;
1149 drag_accum += y_delta*pixel_frame_scale_factor;
1153 if (trunc(drag_accum) != 0) {
1158 dir = (drag_accum < 0 ? 1:-1);
1159 pos = current_time();
1160 frames = get_frames (field,pos,dir);
1162 if (frames != 0 && frames * drag_accum < current_time()) {
1164 set ((nframes_t) floor (pos - drag_accum * frames), false); // minus because up is negative in computer-land
1172 ValueChanged(); /* EMIT_SIGNAL */
1181 AudioClock::get_frames (Field field,nframes_t pos,int dir)
1184 nframes_t frames = 0;
1188 frames = (nframes_t) floor (3600.0 * session->frame_rate());
1191 frames = (nframes_t) floor (60.0 * session->frame_rate());
1194 frames = session->frame_rate();
1197 frames = (nframes_t) floor (session->frame_rate() / Config->get_smpte_frames_per_second());
1205 frames = (nframes_t) floor (3600.0 * session->frame_rate());
1208 frames = (nframes_t) floor (60.0 * session->frame_rate());
1211 frames = session->frame_rate();
1218 frames = session->tempo_map().bbt_duration_at(pos,bbt,dir);
1224 frames = session->tempo_map().bbt_duration_at(pos,bbt,dir);
1230 frames = session->tempo_map().bbt_duration_at(pos,bbt,dir);
1238 AudioClock::current_time (nframes_t pos) const
1244 ret = smpte_frame_from_display ();
1247 ret = bbt_frame_from_display (pos);
1251 ret = minsec_frame_from_display ();
1255 ret = audio_frame_from_display ();
1266 AudioClock::current_duration (nframes_t pos) const
1272 ret = smpte_frame_from_display ();
1275 ret = bbt_frame_duration_from_display (pos);
1279 ret = minsec_frame_from_display ();
1283 ret = audio_frame_from_display ();
1294 AudioClock::smpte_sanitize_display()
1296 // Check SMPTE fields for sanity, possibly adjusting values
1297 if (atoi(minutes_label.get_text()) > 59) {
1298 minutes_label.set_text("59");
1301 if (atoi(seconds_label.get_text()) > 59) {
1302 seconds_label.set_text("59");
1305 switch ((long)rint(Config->get_smpte_frames_per_second())) {
1307 if (atoi(frames_label.get_text()) > 23) {
1308 frames_label.set_text("23");
1312 if (atoi(frames_label.get_text()) > 24) {
1313 frames_label.set_text("24");
1317 if (atoi(frames_label.get_text()) > 29) {
1318 frames_label.set_text("29");
1325 if (Config->get_smpte_drop_frames()) {
1326 if ((atoi(minutes_label.get_text()) % 10) && (atoi(seconds_label.get_text()) == 0) && (atoi(frames_label.get_text()) < 2)) {
1327 frames_label.set_text("02");
1333 AudioClock::smpte_frame_from_display () const
1342 smpte.hours = atoi (hours_label.get_text());
1343 smpte.minutes = atoi (minutes_label.get_text());
1344 smpte.seconds = atoi (seconds_label.get_text());
1345 smpte.frames = atoi (frames_label.get_text());
1347 session->smpte_to_sample( smpte, sample, false /* use_offset */, false /* use_subframes */ );
1351 #define SMPTE_SAMPLE_TEST_1
1352 #define SMPTE_SAMPLE_TEST_2
1353 #define SMPTE_SAMPLE_TEST_3
1354 #define SMPTE_SAMPLE_TEST_4
1355 #define SMPTE_SAMPLE_TEST_5
1356 #define SMPTE_SAMPLE_TEST_6
1357 #define SMPTE_SAMPLE_TEST_7
1359 // Testcode for smpte<->sample conversions (P.S.)
1362 nframes_t oldsample = 0;
1364 nframes_t sample_increment;
1366 sample_increment = (long)rint(session->frame_rate() / session->smpte_frames_per_second);
1368 #ifdef SMPTE_SAMPLE_TEST_1
1369 // Test 1: use_offset = false, use_subframes = false
1370 cout << "use_offset = false, use_subframes = false" << endl;
1371 for (int i = 0; i < 108003; i++) {
1372 session->smpte_to_sample( smpte1, sample1, false /* use_offset */, false /* use_subframes */ );
1373 session->sample_to_smpte( sample1, smpte2, false /* use_offset */, false /* use_subframes */ );
1375 if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
1376 cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1377 cout << "smpte1: " << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1378 cout << "sample: " << sample1 << endl;
1379 cout << "sample: " << sample1 << " -> ";
1380 cout << "smpte2: " << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1384 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1385 cout << "ERROR: smpte2 not equal smpte1" << endl;
1386 cout << "smpte1: " << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1387 cout << "sample: " << sample1 << endl;
1388 cout << "sample: " << sample1 << " -> ";
1389 cout << "smpte2: " << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1392 oldsample = sample1;
1393 session->smpte_increment( smpte1 );
1396 cout << "sample_increment: " << sample_increment << endl;
1397 cout << "sample: " << sample1 << " -> ";
1398 cout << "smpte: " << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1401 #ifdef SMPTE_SAMPLE_TEST_2
1402 // Test 2: use_offset = true, use_subframes = false
1403 cout << "use_offset = true, use_subframes = false" << endl;
1409 smpte1.subframes = 0;
1410 sample1 = oldsample = 0;
1412 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1413 cout << "Starting at sample: " << sample1 << " -> ";
1414 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1416 for (int i = 0; i < 108003; i++) {
1417 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1418 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1420 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1421 // cout << "sample: " << sample1 << endl;
1422 // cout << "sample: " << sample1 << " -> ";
1423 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1425 if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
1426 cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1427 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1428 cout << "sample: " << sample1 << endl;
1429 cout << "sample: " << sample1 << " -> ";
1430 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1434 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1435 cout << "ERROR: smpte2 not equal smpte1" << endl;
1436 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1437 cout << "sample: " << sample1 << endl;
1438 cout << "sample: " << sample1 << " -> ";
1439 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1442 oldsample = sample1;
1443 session->smpte_increment( smpte1 );
1446 cout << "sample_increment: " << sample_increment << endl;
1447 cout << "sample: " << sample1 << " -> ";
1448 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1451 #ifdef SMPTE_SAMPLE_TEST_3
1452 // Test 3: use_offset = true, use_subframes = false, decrement
1453 cout << "use_offset = true, use_subframes = false, decrement" << endl;
1455 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1456 cout << "Starting at sample: " << sample1 << " -> ";
1457 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1459 for (int i = 0; i < 108003; i++) {
1460 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1461 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1463 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1464 // cout << "sample: " << sample1 << endl;
1465 // cout << "sample: " << sample1 << " -> ";
1466 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1468 if ((i > 0) && ( ((oldsample - sample1) != sample_increment) && ((oldsample - sample1) != (sample_increment + 1)) && ((oldsample - sample1) != (sample_increment - 1)))) {
1469 cout << "ERROR: sample increment not right: " << (oldsample - sample1) << " != " << sample_increment << endl;
1470 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1471 cout << "sample: " << sample1 << endl;
1472 cout << "sample: " << sample1 << " -> ";
1473 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1477 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1478 cout << "ERROR: smpte2 not equal smpte1" << endl;
1479 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1480 cout << "sample: " << sample1 << endl;
1481 cout << "sample: " << sample1 << " -> ";
1482 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1485 oldsample = sample1;
1486 session->smpte_decrement( smpte1 );
1489 cout << "sample_decrement: " << sample_increment << endl;
1490 cout << "sample: " << sample1 << " -> ";
1491 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1495 #ifdef SMPTE_SAMPLE_TEST_4
1496 // Test 4: use_offset = true, use_subframes = true
1497 cout << "use_offset = true, use_subframes = true" << endl;
1499 for (long sub = 5; sub < 80; sub += 5) {
1504 smpte1.subframes = 0;
1505 sample1 = oldsample = (sample_increment * sub) / 80;
1507 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, true /* use_subframes */ );
1509 cout << "starting at sample: " << sample1 << " -> ";
1510 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1512 for (int i = 0; i < 108003; i++) {
1513 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, true /* use_subframes */ );
1514 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, true /* use_subframes */ );
1516 if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
1517 cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1518 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1519 cout << "sample: " << sample1 << endl;
1520 cout << "sample: " << sample1 << " -> ";
1521 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1525 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames || smpte2.subframes != smpte1.subframes) {
1526 cout << "ERROR: smpte2 not equal smpte1" << endl;
1527 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1528 cout << "sample: " << sample1 << endl;
1529 cout << "sample: " << sample1 << " -> ";
1530 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1533 oldsample = sample1;
1534 session->smpte_increment( smpte1 );
1537 cout << "sample_increment: " << sample_increment << endl;
1538 cout << "sample: " << sample1 << " -> ";
1539 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1541 for (int i = 0; i < 108003; i++) {
1542 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, true /* use_subframes */ );
1543 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, true /* use_subframes */ );
1545 if ((i > 0) && ( ((oldsample - sample1) != sample_increment) && ((oldsample - sample1) != (sample_increment + 1)) && ((oldsample - sample1) != (sample_increment - 1)))) {
1546 cout << "ERROR: sample increment not right: " << (oldsample - sample1) << " != " << sample_increment << endl;
1547 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1548 cout << "sample: " << sample1 << endl;
1549 cout << "sample: " << sample1 << " -> ";
1550 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1554 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames || smpte2.subframes != smpte1.subframes) {
1555 cout << "ERROR: smpte2 not equal smpte1" << endl;
1556 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1557 cout << "sample: " << sample1 << endl;
1558 cout << "sample: " << sample1 << " -> ";
1559 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1562 oldsample = sample1;
1563 session->smpte_decrement( smpte1 );
1566 cout << "sample_decrement: " << sample_increment << endl;
1567 cout << "sample: " << sample1 << " -> ";
1568 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1573 #ifdef SMPTE_SAMPLE_TEST_5
1574 // Test 5: use_offset = true, use_subframes = false, increment seconds
1575 cout << "use_offset = true, use_subframes = false, increment seconds" << endl;
1581 smpte1.subframes = 0;
1582 sample1 = oldsample = 0;
1583 sample_increment = session->frame_rate();
1585 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1586 cout << "Starting at sample: " << sample1 << " -> ";
1587 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1589 for (int i = 0; i < 3600; i++) {
1590 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1591 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1593 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1594 // cout << "sample: " << sample1 << endl;
1595 // cout << "sample: " << sample1 << " -> ";
1596 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1598 // if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1600 // cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1604 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1605 cout << "ERROR: smpte2 not equal smpte1" << endl;
1606 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1607 cout << "sample: " << sample1 << endl;
1608 cout << "sample: " << sample1 << " -> ";
1609 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1612 oldsample = sample1;
1613 session->smpte_increment_seconds( smpte1 );
1616 cout << "sample_increment: " << sample_increment << endl;
1617 cout << "sample: " << sample1 << " -> ";
1618 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1622 #ifdef SMPTE_SAMPLE_TEST_6
1623 // Test 6: use_offset = true, use_subframes = false, increment minutes
1624 cout << "use_offset = true, use_subframes = false, increment minutes" << endl;
1630 smpte1.subframes = 0;
1631 sample1 = oldsample = 0;
1632 sample_increment = session->frame_rate() * 60;
1634 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1635 cout << "Starting at sample: " << sample1 << " -> ";
1636 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1638 for (int i = 0; i < 60; i++) {
1639 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1640 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1642 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1643 // cout << "sample: " << sample1 << endl;
1644 // cout << "sample: " << sample1 << " -> ";
1645 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1647 // if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1649 // cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1653 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1654 cout << "ERROR: smpte2 not equal smpte1" << endl;
1655 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1656 cout << "sample: " << sample1 << endl;
1657 cout << "sample: " << sample1 << " -> ";
1658 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1661 oldsample = sample1;
1662 session->smpte_increment_minutes( smpte1 );
1665 cout << "sample_increment: " << sample_increment << endl;
1666 cout << "sample: " << sample1 << " -> ";
1667 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1670 #ifdef SMPTE_SAMPLE_TEST_7
1671 // Test 7: use_offset = true, use_subframes = false, increment hours
1672 cout << "use_offset = true, use_subframes = false, increment hours" << endl;
1678 smpte1.subframes = 0;
1679 sample1 = oldsample = 0;
1680 sample_increment = session->frame_rate() * 60 * 60;
1682 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1683 cout << "Starting at sample: " << sample1 << " -> ";
1684 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1686 for (int i = 0; i < 10; i++) {
1687 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1688 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1690 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1691 // cout << "sample: " << sample1 << endl;
1692 // cout << "sample: " << sample1 << " -> ";
1693 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1695 // if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1697 // cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1701 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1702 cout << "ERROR: smpte2 not equal smpte1" << endl;
1703 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1704 cout << "sample: " << sample1 << endl;
1705 cout << "sample: " << sample1 << " -> ";
1706 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1709 oldsample = sample1;
1710 session->smpte_increment_hours( smpte1 );
1713 cout << "sample_increment: " << sample_increment << endl;
1714 cout << "sample: " << sample1 << " -> ";
1715 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1724 AudioClock::minsec_frame_from_display () const
1730 int hrs = atoi (ms_hours_label.get_text());
1731 int mins = atoi (ms_minutes_label.get_text());
1732 float secs = atof (ms_seconds_label.get_text());
1734 nframes_t sr = session->frame_rate();
1736 return (nframes_t) floor ((hrs * 60.0f * 60.0f * sr) + (mins * 60.0f * sr) + (secs * sr));
1740 AudioClock::bbt_frame_from_display (nframes_t pos) const
1743 error << "AudioClock::current_time() called with BBT mode but without session!" << endmsg;
1748 any.type = AnyTime::BBT;
1750 any.bbt.bars = atoi (bars_label.get_text());
1751 any.bbt.beats = atoi (beats_label.get_text());
1752 any.bbt.ticks = atoi (ticks_label.get_text());
1754 nframes_t ret = session->convert_to_frames_at (pos, any);
1761 AudioClock::bbt_frame_duration_from_display (nframes_t pos) const
1764 error << "AudioClock::current_time() called with BBT mode but without session!" << endmsg;
1771 bbt.bars = atoi (bars_label.get_text());
1772 bbt.beats = atoi (beats_label.get_text());
1773 bbt.ticks = atoi (ticks_label.get_text());
1775 return session->tempo_map().bbt_duration_at(pos,bbt,1);
1779 AudioClock::audio_frame_from_display () const
1781 return (nframes_t) atoi (audio_frames_label.get_text());
1785 AudioClock::build_ops_menu ()
1787 using namespace Menu_Helpers;
1788 ops_menu = new Menu;
1789 MenuList& ops_items = ops_menu->items();
1790 ops_menu->set_name ("ArdourContextMenu");
1792 Menu *mode_menu = manage (new Menu);
1793 MenuList& mode_items = mode_menu->items();
1794 mode_menu->set_name ("ArdourContextMenu");
1796 mode_items.push_back (MenuElem (_("Timecode"), bind (mem_fun(*this, &AudioClock::set_mode), SMPTE)));
1797 mode_items.push_back (MenuElem (_("Bars:Beats"), bind (mem_fun(*this, &AudioClock::set_mode), BBT)));
1798 mode_items.push_back (MenuElem (_("Minutes:Seconds"), bind (mem_fun(*this, &AudioClock::set_mode), MinSec)));
1799 mode_items.push_back (MenuElem (_("Audio Frames"), bind (mem_fun(*this, &AudioClock::set_mode), Frames)));
1800 mode_items.push_back (MenuElem (_("Off"), bind (mem_fun(*this, &AudioClock::set_mode), Off)));
1802 ops_items.push_back (MenuElem (_("Mode"), *mode_menu));
1806 AudioClock::set_mode (Mode m)
1808 /* slightly tricky: this is called from within the ARDOUR_UI
1809 constructor by some of its clock members. at that time
1810 the instance pointer is unset, so we have to be careful.
1811 the main idea is to drop keyboard focus in case we had
1812 started editing the clock and then we switch clock mode.
1815 clock_base.grab_focus ();
1825 clock_base.remove ();
1835 clock_base.add (smpte_packer_hbox);
1839 clock_base.add (bbt_packer_hbox);
1843 clock_base.add (minsec_packer_hbox);
1847 clock_base.add (frames_packer_hbox);
1854 set_size_requests ();
1856 set (last_when, true);
1857 clock_base.show_all ();
1858 key_entry_state = 0;
1862 AudioClock::set_size_requests ()
1864 /* note that in some fonts, "88" is narrower than "00", hence the 2 pixel padding */
1868 Gtkmm2ext::set_size_request_to_display_given_text (hours_label, "-00", 5, 5);
1869 Gtkmm2ext::set_size_request_to_display_given_text (minutes_label, "00", 5, 5);
1870 Gtkmm2ext::set_size_request_to_display_given_text (seconds_label, "00", 5, 5);
1871 Gtkmm2ext::set_size_request_to_display_given_text (frames_label, "00", 5, 5);
1875 Gtkmm2ext::set_size_request_to_display_given_text (bars_label, "-000", 5, 5);
1876 Gtkmm2ext::set_size_request_to_display_given_text (beats_label, "00", 5, 5);
1877 Gtkmm2ext::set_size_request_to_display_given_text (ticks_label, "0000", 5, 5);
1881 Gtkmm2ext::set_size_request_to_display_given_text (ms_hours_label, "00", 5, 5);
1882 Gtkmm2ext::set_size_request_to_display_given_text (ms_minutes_label, "00", 5, 5);
1883 Gtkmm2ext::set_size_request_to_display_given_text (ms_seconds_label, "00.000", 5, 5);
1887 Gtkmm2ext::set_size_request_to_display_given_text (audio_frames_label, "0000000000", 5, 5);