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;
46 const uint32_t AudioClock::field_length[(int) AudioClock::AudioFrames+1] = {
48 2, /* SMPTE_Minutes */
49 2, /* SMPTE_Seconds */
60 AudioClock::AudioClock (const string& name, bool allow_edit, bool duration, bool with_tempo_and_meter)
61 : is_duration (duration),
62 editable (allow_edit),
77 audio_frames_ebox.add (audio_frames_label);
78 frames_packer_hbox.set_border_width (2);
79 frames_packer_hbox.pack_start (audio_frames_ebox, false, false);
81 hours_ebox.add (hours_label);
82 minutes_ebox.add (minutes_label);
83 seconds_ebox.add (seconds_label);
84 frames_ebox.add (frames_label);
85 bars_ebox.add (bars_label);
86 beats_ebox.add (beats_label);
87 ticks_ebox.add (ticks_label);
88 ms_hours_ebox.add (ms_hours_label);
89 ms_minutes_ebox.add (ms_minutes_label);
90 ms_seconds_ebox.add (ms_seconds_label);
92 smpte_packer.set_homogeneous (false);
93 smpte_packer.set_border_width (2);
94 smpte_packer.pack_start (hours_ebox, false, false);
95 smpte_packer.pack_start (colon1, false, false);
96 smpte_packer.pack_start (minutes_ebox, false, false);
97 smpte_packer.pack_start (colon2, false, false);
98 smpte_packer.pack_start (seconds_ebox, false, false);
99 smpte_packer.pack_start (colon3, false, false);
100 smpte_packer.pack_start (frames_ebox, false, false);
102 smpte_packer_hbox.pack_start (smpte_packer, true, false);
104 bbt_packer.set_homogeneous (false);
105 bbt_packer.set_border_width (2);
106 bbt_packer.pack_start (bars_ebox, false, false);
107 bbt_packer.pack_start (b1, false, false);
108 bbt_packer.pack_start (beats_ebox, false, false);
109 bbt_packer.pack_start (b2, false, false);
110 bbt_packer.pack_start (ticks_ebox, false, false);
112 if (with_tempo_and_meter) {
113 meter_label = manage (new Label);
114 tempo_label = manage (new Label);
116 meter_label->set_name ("BBTMeterLabel");
117 tempo_label->set_name ("BBTTempoLabel");
119 tempo_meter_box.pack_start (*meter_label, true, true);
120 tempo_meter_box.pack_start (*tempo_label, true, true);
122 bbt_packer.pack_start (tempo_meter_box, false, false, 5);
128 bbt_packer_hbox.pack_start (bbt_packer, true, false);
130 minsec_packer.set_homogeneous (false);
131 minsec_packer.set_border_width (2);
132 minsec_packer.pack_start (ms_hours_ebox, false, false);
133 minsec_packer.pack_start (colon4, false, false);
134 minsec_packer.pack_start (ms_minutes_ebox, false, false);
135 minsec_packer.pack_start (colon5, false, false);
136 minsec_packer.pack_start (ms_seconds_ebox, false, false);
138 minsec_packer_hbox.pack_start (minsec_packer, true, false);
141 clock_base.set_name (name);
143 audio_frames_label.set_name (name);
144 hours_label.set_name (name);
145 minutes_label.set_name (name);
146 seconds_label.set_name (name);
147 frames_label.set_name (name);
148 bars_label.set_name (name);
149 beats_label.set_name (name);
150 ticks_label.set_name (name);
151 ms_hours_label.set_name (name);
152 ms_minutes_label.set_name (name);
153 ms_seconds_label.set_name (name);
154 hours_ebox.set_name (name);
155 minutes_ebox.set_name (name);
156 seconds_ebox.set_name (name);
157 frames_ebox.set_name (name);
158 audio_frames_ebox.set_name (name);
159 bars_ebox.set_name (name);
160 beats_ebox.set_name (name);
161 ticks_ebox.set_name (name);
162 ms_hours_ebox.set_name (name);
163 ms_minutes_ebox.set_name (name);
164 ms_seconds_ebox.set_name (name);
166 colon1.set_name (name);
167 colon2.set_name (name);
168 colon3.set_name (name);
169 colon4.set_name (name);
170 colon5.set_name (name);
174 clock_frame.set_shadow_type (Gtk::SHADOW_IN);
175 clock_frame.set_name ("BaseFrame");
177 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));
202 set (last_when, true);
206 AudioClock::setup_events ()
208 clock_base.set_flags (Gtk::CAN_FOCUS);
210 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);
211 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);
212 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);
213 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);
214 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);
215 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);
216 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);
217 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);
218 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);
219 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);
220 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);
222 hours_ebox.set_flags (Gtk::CAN_FOCUS);
223 minutes_ebox.set_flags (Gtk::CAN_FOCUS);
224 seconds_ebox.set_flags (Gtk::CAN_FOCUS);
225 frames_ebox.set_flags (Gtk::CAN_FOCUS);
226 audio_frames_ebox.set_flags (Gtk::CAN_FOCUS);
227 bars_ebox.set_flags (Gtk::CAN_FOCUS);
228 beats_ebox.set_flags (Gtk::CAN_FOCUS);
229 ticks_ebox.set_flags (Gtk::CAN_FOCUS);
230 ms_hours_ebox.set_flags (Gtk::CAN_FOCUS);
231 ms_minutes_ebox.set_flags (Gtk::CAN_FOCUS);
232 ms_seconds_ebox.set_flags (Gtk::CAN_FOCUS);
234 hours_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), SMPTE_Hours));
235 minutes_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), SMPTE_Minutes));
236 seconds_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), SMPTE_Seconds));
237 frames_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), SMPTE_Frames));
238 audio_frames_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), AudioFrames));
239 bars_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), Bars));
240 beats_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), Beats));
241 ticks_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), Ticks));
242 ms_hours_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), MS_Hours));
243 ms_minutes_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), MS_Minutes));
244 ms_seconds_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), MS_Seconds));
246 hours_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), SMPTE_Hours));
247 minutes_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), SMPTE_Minutes));
248 seconds_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), SMPTE_Seconds));
249 frames_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), SMPTE_Frames));
250 audio_frames_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), AudioFrames));
251 bars_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), Bars));
252 beats_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), Beats));
253 ticks_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), Ticks));
254 ms_hours_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), MS_Hours));
255 ms_minutes_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), MS_Minutes));
256 ms_seconds_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), MS_Seconds));
258 hours_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), SMPTE_Hours));
259 minutes_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), SMPTE_Minutes));
260 seconds_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), SMPTE_Seconds));
261 frames_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), SMPTE_Frames));
262 audio_frames_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), AudioFrames));
263 bars_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), Bars));
264 beats_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), Beats));
265 ticks_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), Ticks));
266 ms_hours_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), MS_Hours));
267 ms_minutes_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), MS_Minutes));
268 ms_seconds_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), MS_Seconds));
270 hours_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), SMPTE_Hours));
271 minutes_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), SMPTE_Minutes));
272 seconds_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), SMPTE_Seconds));
273 frames_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), SMPTE_Frames));
274 audio_frames_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), AudioFrames));
275 bars_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), Bars));
276 beats_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), Beats));
277 ticks_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), Ticks));
278 ms_hours_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), MS_Hours));
279 ms_minutes_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), MS_Minutes));
280 ms_seconds_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), MS_Seconds));
282 hours_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), SMPTE_Hours));
283 minutes_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), SMPTE_Minutes));
284 seconds_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), SMPTE_Seconds));
285 frames_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), SMPTE_Frames));
286 audio_frames_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), AudioFrames));
287 bars_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), Bars));
288 beats_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), Beats));
289 ticks_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), Ticks));
290 ms_hours_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), MS_Hours));
291 ms_minutes_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), MS_Minutes));
292 ms_seconds_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), MS_Seconds));
294 hours_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), SMPTE_Hours));
295 minutes_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), SMPTE_Minutes));
296 seconds_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), SMPTE_Seconds));
297 frames_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), SMPTE_Frames));
298 audio_frames_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), AudioFrames));
299 bars_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), Bars));
300 beats_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), Beats));
301 ticks_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), Ticks));
302 ms_hours_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), MS_Hours));
303 ms_minutes_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), MS_Minutes));
304 ms_seconds_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), MS_Seconds));
306 hours_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), SMPTE_Hours));
307 minutes_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), SMPTE_Minutes));
308 seconds_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), SMPTE_Seconds));
309 frames_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), SMPTE_Frames));
310 audio_frames_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), AudioFrames));
311 bars_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), Bars));
312 beats_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), Beats));
313 ticks_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), Ticks));
314 ms_hours_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), MS_Hours));
315 ms_minutes_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), MS_Minutes));
316 ms_seconds_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), MS_Seconds));
320 AudioClock::on_realize ()
324 /* styles are not available until the widgets are bound to a window */
328 Gtkmm2ext::set_size_request_to_display_given_text (hours_label, "-88", 0, 2);
329 Gtkmm2ext::set_size_request_to_display_given_text (minutes_label, "88", 0, 2);
330 Gtkmm2ext::set_size_request_to_display_given_text (seconds_label, "88", 0, 2);
331 Gtkmm2ext::set_size_request_to_display_given_text (frames_label, "88", 0, 2);
335 Gtkmm2ext::set_size_request_to_display_given_text (bars_label, "-888", 0, 2);
336 Gtkmm2ext::set_size_request_to_display_given_text (beats_label, "88", 0, 2);
337 Gtkmm2ext::set_size_request_to_display_given_text (ticks_label, "8888", 0, 2);
341 Gtkmm2ext::set_size_request_to_display_given_text (ms_hours_label, "99", 0, 2);
342 Gtkmm2ext::set_size_request_to_display_given_text (ms_minutes_label, "99", 0, 2);
343 Gtkmm2ext::set_size_request_to_display_given_text (ms_seconds_label, "99", 0, 2);
347 Gtkmm2ext::set_size_request_to_display_given_text (audio_frames_label, "4294967296", 0, 2);
357 AudioClock::set (jack_nframes_t when, bool force)
360 if ((!force && !is_visible()) || session == 0) {
364 if (when == last_when && !force) {
370 set_smpte (when, force);
374 set_bbt (when, force);
378 set_minsec (when, force);
382 set_frames (when, force);
393 AudioClock::set_frames (jack_nframes_t when, bool force)
396 snprintf (buf, sizeof (buf), "%u", when);
397 audio_frames_label.set_text (buf);
401 AudioClock::set_minsec (jack_nframes_t when, bool force)
410 hrs = (int) floor (left / (session->frame_rate() * 60.0f * 60.0f));
411 left -= (jack_nframes_t) floor (hrs * session->frame_rate() * 60.0f * 60.0f);
412 mins = (int) floor (left / (session->frame_rate() * 60.0f));
413 left -= (jack_nframes_t) floor (mins * session->frame_rate() * 60.0f);
414 secs = left / (float) session->frame_rate();
416 if (force || hrs != ms_last_hrs) {
417 sprintf (buf, "%d", hrs);
418 ms_hours_label.set_text (buf);
422 if (force || mins != ms_last_mins) {
423 sprintf (buf, "%d", mins);
424 ms_minutes_label.set_text (buf);
428 if (force || secs != ms_last_secs) {
429 sprintf (buf, "%06.3f", secs);
430 ms_seconds_label.set_text (buf);
436 AudioClock::set_smpte (jack_nframes_t when, bool force)
442 session->smpte_duration (when, smpte);
444 session->smpte_time (when, smpte);
447 if (force || smpte.hours != last_hrs || smpte.negative != last_negative) {
448 if (smpte.negative) {
449 sprintf (buf, "-%02ld", smpte.hours);
451 sprintf (buf, " %02ld", smpte.hours);
453 hours_label.set_text (buf);
454 last_hrs = smpte.hours;
455 last_negative = smpte.negative;
458 if (force || smpte.minutes != last_mins) {
459 sprintf (buf, "%02ld", smpte.minutes);
460 minutes_label.set_text (buf);
461 last_mins = smpte.minutes;
464 if (force || smpte.seconds != last_secs) {
465 sprintf (buf, "%02ld", smpte.seconds);
466 seconds_label.set_text (buf);
467 last_secs = smpte.seconds;
470 if (force || smpte.frames != last_frames) {
471 sprintf (buf, "%02ld", smpte.frames);
472 frames_label.set_text (buf);
473 last_frames = smpte.frames;
478 AudioClock::set_bbt (jack_nframes_t when, bool force)
483 session->tempo_map().bbt_time (when, bbt);
484 sprintf (buf, "%03" PRIu32, bbt.bars);
485 bars_label.set_text (buf);
486 sprintf (buf, "%02" PRIu32, bbt.beats);
487 beats_label.set_text (buf);
488 sprintf (buf, "%04" PRIu32, bbt.ticks);
489 ticks_label.set_text (buf);
492 TempoMap::Metric m (session->tempo_map().metric_at (when));
493 sprintf (buf, "%-5.2f", m.tempo().beats_per_minute());
494 tempo_label->set_text (buf);
495 sprintf (buf, "%g|%g", m.meter().beats_per_bar(), m.meter().note_divisor());
496 meter_label->set_text (buf);
501 AudioClock::set_session (Session *s)
506 set (last_when, true);
511 AudioClock::field_key_release_event (GdkEventKey *ev, Field field)
516 bool move_on = false;
520 label = &hours_label;
523 label = &minutes_label;
526 label = &seconds_label;
529 label = &frames_label;
533 label = &audio_frames_label;
537 label = &ms_hours_label;
540 label = &ms_minutes_label;
543 label = &ms_seconds_label;
550 label = &beats_label;
553 label = &ticks_label;
559 switch (ev->keyval) {
603 if (_mode == MinSec && field == MS_Seconds) {
617 clock_base.grab_focus ();
626 if (key_entry_state == 0) {
628 /* initialize with a fresh new string */
630 if (field != AudioFrames) {
631 for (uint32_t xn = 0; xn < field_length[field] - 1; ++xn) {
640 string existing = label->get_text();
641 if (existing.length() >= field_length[field]) {
642 new_text = existing.substr (1, field_length[field] - 1);
644 new_text = existing.substr (0, field_length[field] - 1);
648 new_text += new_char;
649 label->set_text (new_text);
653 if (key_entry_state == field_length[field]) {
659 if (key_entry_state) {
666 // Check SMPTE fields for sanity (may also adjust fields)
667 smpte_sanitize_display();
673 ValueChanged(); /* EMIT_SIGNAL */
676 /* move on to the next field.
684 minutes_ebox.grab_focus ();
687 seconds_ebox.grab_focus ();
690 frames_ebox.grab_focus ();
693 clock_base.grab_focus ();
698 clock_base.grab_focus ();
704 ms_minutes_ebox.grab_focus ();
707 ms_seconds_ebox.grab_focus ();
710 clock_base.grab_focus ();
716 beats_ebox.grab_focus ();
719 ticks_ebox.grab_focus ();
722 clock_base.grab_focus ();
735 AudioClock::field_focus_in_event (GdkEventFocus *ev, Field field)
741 hours_ebox.set_flags (Gtk::HAS_FOCUS);
742 hours_ebox.set_state (Gtk::STATE_ACTIVE);
745 minutes_ebox.set_flags (Gtk::HAS_FOCUS);
746 minutes_ebox.set_state (Gtk::STATE_ACTIVE);
749 seconds_ebox.set_flags (Gtk::HAS_FOCUS);
750 seconds_ebox.set_state (Gtk::STATE_ACTIVE);
753 frames_ebox.set_flags (Gtk::HAS_FOCUS);
754 frames_ebox.set_state (Gtk::STATE_ACTIVE);
758 audio_frames_ebox.set_flags (Gtk::HAS_FOCUS);
759 audio_frames_ebox.set_state (Gtk::STATE_ACTIVE);
763 ms_hours_ebox.set_flags (Gtk::HAS_FOCUS);
764 ms_hours_ebox.set_state (Gtk::STATE_ACTIVE);
767 ms_minutes_ebox.set_flags (Gtk::HAS_FOCUS);
768 ms_minutes_ebox.set_state (Gtk::STATE_ACTIVE);
771 ms_seconds_ebox.set_flags (Gtk::HAS_FOCUS);
772 ms_seconds_ebox.set_state (Gtk::STATE_ACTIVE);
775 bars_ebox.set_flags (Gtk::HAS_FOCUS);
776 bars_ebox.set_state (Gtk::STATE_ACTIVE);
779 beats_ebox.set_flags (Gtk::HAS_FOCUS);
780 beats_ebox.set_state (Gtk::STATE_ACTIVE);
783 ticks_ebox.set_flags (Gtk::HAS_FOCUS);
784 ticks_ebox.set_state (Gtk::STATE_ACTIVE);
792 AudioClock::field_focus_out_event (GdkEventFocus *ev, Field field)
797 hours_ebox.unset_flags (Gtk::HAS_FOCUS);
798 hours_ebox.set_state (Gtk::STATE_NORMAL);
801 minutes_ebox.unset_flags (Gtk::HAS_FOCUS);
802 minutes_ebox.set_state (Gtk::STATE_NORMAL);
805 seconds_ebox.unset_flags (Gtk::HAS_FOCUS);
806 seconds_ebox.set_state (Gtk::STATE_NORMAL);
809 frames_ebox.unset_flags (Gtk::HAS_FOCUS);
810 frames_ebox.set_state (Gtk::STATE_NORMAL);
814 audio_frames_ebox.unset_flags (Gtk::HAS_FOCUS);
815 audio_frames_ebox.set_state (Gtk::STATE_NORMAL);
819 ms_hours_ebox.unset_flags (Gtk::HAS_FOCUS);
820 ms_hours_ebox.set_state (Gtk::STATE_NORMAL);
823 ms_minutes_ebox.unset_flags (Gtk::HAS_FOCUS);
824 ms_minutes_ebox.set_state (Gtk::STATE_NORMAL);
827 ms_seconds_ebox.unset_flags (Gtk::HAS_FOCUS);
828 ms_seconds_ebox.set_state (Gtk::STATE_NORMAL);
832 bars_ebox.unset_flags (Gtk::HAS_FOCUS);
833 bars_ebox.set_state (Gtk::STATE_NORMAL);
836 beats_ebox.unset_flags (Gtk::HAS_FOCUS);
837 beats_ebox.set_state (Gtk::STATE_NORMAL);
840 ticks_ebox.unset_flags (Gtk::HAS_FOCUS);
841 ticks_ebox.set_state (Gtk::STATE_NORMAL);
849 AudioClock::field_button_release_event (GdkEventButton *ev, Field field)
854 gdk_pointer_ungrab(GDK_CURRENT_TIME);
856 if (ev->y > drag_start_y+1 || ev->y < drag_start_y-1 || Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)){
857 // we actually dragged so return without setting editing focus, or we shift clicked
867 ops_menu->popup (1, ev->time);
871 if (Keyboard::is_context_menu_event (ev)) {
875 ops_menu->popup (1, ev->time);
879 switch (ev->button) {
883 hours_ebox.grab_focus();
886 minutes_ebox.grab_focus();
889 seconds_ebox.grab_focus();
892 frames_ebox.grab_focus();
896 audio_frames_ebox.grab_focus();
900 ms_hours_ebox.grab_focus();
903 ms_minutes_ebox.grab_focus();
906 ms_seconds_ebox.grab_focus();
910 bars_ebox.grab_focus ();
913 beats_ebox.grab_focus ();
916 ticks_ebox.grab_focus ();
929 AudioClock::field_button_press_event (GdkEventButton *ev, Field field)
931 if (session == 0) return FALSE;
933 jack_nframes_t frames = 0;
935 switch (ev->button) {
937 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
939 ValueChanged (); /* EMIT_SIGNAL */
942 /* make absolutely sure that the pointer is grabbed */
943 gdk_pointer_grab(ev->window,FALSE ,
944 GdkEventMask( Gdk::POINTER_MOTION_MASK | Gdk::BUTTON_PRESS_MASK |Gdk::BUTTON_RELEASE_MASK),
948 drag_start_y = ev->y;
953 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
955 ValueChanged (); /* EMIT_SIGNAL */
960 /* used for context sensitive menu */
965 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
966 frames = get_frames (field);
968 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
971 set (current_time() + frames, true);
972 ValueChanged (); /* EMIT_SIGNAL */
978 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
979 frames = get_frames (field);
981 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
985 if ((double)current_time() - (double)frames < 0.0) {
989 set (current_time() - frames, true);
992 ValueChanged (); /* EMIT_SIGNAL */
1006 AudioClock::field_button_scroll_event (GdkEventScroll *ev, Field field)
1008 if (session == 0) return FALSE;
1010 jack_nframes_t frames = 0;
1012 switch (ev->direction) {
1015 frames = get_frames (field);
1017 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
1020 set (current_time() + frames, true);
1021 ValueChanged (); /* EMIT_SIGNAL */
1025 case GDK_SCROLL_DOWN:
1026 frames = get_frames (field);
1028 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
1032 if ((double)current_time() - (double)frames < 0.0) {
1035 set (current_time() - frames, true);
1038 ValueChanged (); /* EMIT_SIGNAL */
1051 AudioClock::field_motion_notify_event (GdkEventMotion *ev, Field field)
1053 if (session == 0 || !dragging) {
1057 float pixel_frame_scale_factor = 0.2f;
1060 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
1061 pixel_frame_scale_factor = 0.1f;
1065 if (Keyboard::modifier_state_contains (ev->state,
1066 Keyboard::Control|Keyboard::Alt)) {
1068 pixel_frame_scale_factor = 0.025f;
1071 double y_delta = ev->y - drag_y;
1073 drag_accum += y_delta*pixel_frame_scale_factor;
1077 if (trunc(drag_accum) != 0) {
1079 jack_nframes_t frames;
1080 jack_nframes_t pos ;
1082 dir = (drag_accum < 0 ? 1:-1);
1083 pos = current_time();
1084 frames = get_frames (field,pos,dir);
1086 if (frames != 0 && frames * drag_accum < current_time()) {
1088 set ((jack_nframes_t) floor (pos - drag_accum * frames), false); // minus because up is negative in computer-land
1096 ValueChanged(); /* EMIT_SIGNAL */
1105 AudioClock::get_frames (Field field,jack_nframes_t pos,int dir)
1108 jack_nframes_t frames = 0;
1112 frames = (jack_nframes_t) floor (3600.0 * session->frame_rate());
1115 frames = (jack_nframes_t) floor (60.0 * session->frame_rate());
1118 frames = session->frame_rate();
1121 frames = (jack_nframes_t) floor (session->frame_rate() / session->smpte_frames_per_second);
1129 frames = (jack_nframes_t) floor (3600.0 * session->frame_rate());
1132 frames = (jack_nframes_t) floor (60.0 * session->frame_rate());
1135 frames = session->frame_rate();
1142 frames = session->tempo_map().bbt_duration_at(pos,bbt,dir);
1148 frames = session->tempo_map().bbt_duration_at(pos,bbt,dir);
1154 frames = session->tempo_map().bbt_duration_at(pos,bbt,dir);
1162 AudioClock::current_time (jack_nframes_t pos) const
1164 jack_nframes_t ret = 0;
1168 ret = smpte_frame_from_display ();
1171 ret = bbt_frame_from_display (pos);
1175 ret = minsec_frame_from_display ();
1179 ret = audio_frame_from_display ();
1190 AudioClock::current_duration (jack_nframes_t pos) const
1192 jack_nframes_t ret = 0;
1196 ret = smpte_frame_from_display ();
1199 ret = bbt_frame_duration_from_display (pos);
1203 ret = minsec_frame_from_display ();
1207 ret = audio_frame_from_display ();
1218 AudioClock::smpte_sanitize_display()
1220 // Check SMPTE fields for sanity, possibly adjusting values
1221 if (atoi(minutes_label.get_text()) > 59) {
1222 minutes_label.set_text("59");
1225 if (atoi(seconds_label.get_text()) > 59) {
1226 seconds_label.set_text("59");
1229 switch ((long)rint(session->smpte_frames_per_second)) {
1231 if (atoi(frames_label.get_text()) > 23) {
1232 frames_label.set_text("23");
1236 if (atoi(frames_label.get_text()) > 24) {
1237 frames_label.set_text("24");
1241 if (atoi(frames_label.get_text()) > 29) {
1242 frames_label.set_text("29");
1249 if (session->smpte_drop_frames) {
1250 if ((atoi(minutes_label.get_text()) % 10) && (atoi(seconds_label.get_text()) == 0) && (atoi(frames_label.get_text()) < 2)) {
1251 frames_label.set_text("02");
1257 AudioClock::smpte_frame_from_display () const
1264 jack_nframes_t sample;
1266 smpte.hours = atoi (hours_label.get_text());
1267 smpte.minutes = atoi (minutes_label.get_text());
1268 smpte.seconds = atoi (seconds_label.get_text());
1269 smpte.frames = atoi (frames_label.get_text());
1271 session->smpte_to_sample( smpte, sample, false /* use_offset */, false /* use_subframes */ );
1275 #define SMPTE_SAMPLE_TEST_1
1276 #define SMPTE_SAMPLE_TEST_2
1277 #define SMPTE_SAMPLE_TEST_3
1278 #define SMPTE_SAMPLE_TEST_4
1279 #define SMPTE_SAMPLE_TEST_5
1280 #define SMPTE_SAMPLE_TEST_6
1281 #define SMPTE_SAMPLE_TEST_7
1283 // Testcode for smpte<->sample conversions (P.S.)
1285 jack_nframes_t sample1;
1286 jack_nframes_t oldsample = 0;
1288 jack_nframes_t sample_increment;
1290 sample_increment = (long)rint(session->frame_rate() / session->smpte_frames_per_second);
1292 #ifdef SMPTE_SAMPLE_TEST_1
1293 // Test 1: use_offset = false, use_subframes = false
1294 cout << "use_offset = false, use_subframes = false" << endl;
1295 for (int i = 0; i < 108003; i++) {
1296 session->smpte_to_sample( smpte1, sample1, false /* use_offset */, false /* use_subframes */ );
1297 session->sample_to_smpte( sample1, smpte2, false /* use_offset */, false /* use_subframes */ );
1299 if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
1300 cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1301 cout << "smpte1: " << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1302 cout << "sample: " << sample1 << endl;
1303 cout << "sample: " << sample1 << " -> ";
1304 cout << "smpte2: " << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1308 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1309 cout << "ERROR: smpte2 not equal smpte1" << endl;
1310 cout << "smpte1: " << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1311 cout << "sample: " << sample1 << endl;
1312 cout << "sample: " << sample1 << " -> ";
1313 cout << "smpte2: " << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1316 oldsample = sample1;
1317 session->smpte_increment( smpte1 );
1320 cout << "sample_increment: " << sample_increment << endl;
1321 cout << "sample: " << sample1 << " -> ";
1322 cout << "smpte: " << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1325 #ifdef SMPTE_SAMPLE_TEST_2
1326 // Test 2: use_offset = true, use_subframes = false
1327 cout << "use_offset = true, use_subframes = false" << endl;
1333 smpte1.subframes = 0;
1334 sample1 = oldsample = 0;
1336 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1337 cout << "Starting at sample: " << sample1 << " -> ";
1338 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1340 for (int i = 0; i < 108003; i++) {
1341 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1342 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1344 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1345 // cout << "sample: " << sample1 << endl;
1346 // cout << "sample: " << sample1 << " -> ";
1347 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1349 if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
1350 cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1351 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1352 cout << "sample: " << sample1 << endl;
1353 cout << "sample: " << sample1 << " -> ";
1354 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1358 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1359 cout << "ERROR: smpte2 not equal smpte1" << endl;
1360 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1361 cout << "sample: " << sample1 << endl;
1362 cout << "sample: " << sample1 << " -> ";
1363 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1366 oldsample = sample1;
1367 session->smpte_increment( smpte1 );
1370 cout << "sample_increment: " << sample_increment << endl;
1371 cout << "sample: " << sample1 << " -> ";
1372 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1375 #ifdef SMPTE_SAMPLE_TEST_3
1376 // Test 3: use_offset = true, use_subframes = false, decrement
1377 cout << "use_offset = true, use_subframes = false, decrement" << endl;
1379 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1380 cout << "Starting at sample: " << sample1 << " -> ";
1381 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1383 for (int i = 0; i < 108003; i++) {
1384 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1385 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1387 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1388 // cout << "sample: " << sample1 << endl;
1389 // cout << "sample: " << sample1 << " -> ";
1390 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1392 if ((i > 0) && ( ((oldsample - sample1) != sample_increment) && ((oldsample - sample1) != (sample_increment + 1)) && ((oldsample - sample1) != (sample_increment - 1)))) {
1393 cout << "ERROR: sample increment not right: " << (oldsample - sample1) << " != " << sample_increment << endl;
1394 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1395 cout << "sample: " << sample1 << endl;
1396 cout << "sample: " << sample1 << " -> ";
1397 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1401 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1402 cout << "ERROR: smpte2 not equal smpte1" << endl;
1403 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1404 cout << "sample: " << sample1 << endl;
1405 cout << "sample: " << sample1 << " -> ";
1406 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1409 oldsample = sample1;
1410 session->smpte_decrement( smpte1 );
1413 cout << "sample_decrement: " << sample_increment << endl;
1414 cout << "sample: " << sample1 << " -> ";
1415 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1419 #ifdef SMPTE_SAMPLE_TEST_4
1420 // Test 4: use_offset = true, use_subframes = true
1421 cout << "use_offset = true, use_subframes = true" << endl;
1423 for (long sub = 5; sub < 80; sub += 5) {
1428 smpte1.subframes = 0;
1429 sample1 = oldsample = (sample_increment * sub) / 80;
1431 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, true /* use_subframes */ );
1433 cout << "starting at sample: " << sample1 << " -> ";
1434 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1436 for (int i = 0; i < 108003; i++) {
1437 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, true /* use_subframes */ );
1438 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, true /* use_subframes */ );
1440 if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
1441 cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1442 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1443 cout << "sample: " << sample1 << endl;
1444 cout << "sample: " << sample1 << " -> ";
1445 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1449 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames || smpte2.subframes != smpte1.subframes) {
1450 cout << "ERROR: smpte2 not equal smpte1" << endl;
1451 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1452 cout << "sample: " << sample1 << endl;
1453 cout << "sample: " << sample1 << " -> ";
1454 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1457 oldsample = sample1;
1458 session->smpte_increment( smpte1 );
1461 cout << "sample_increment: " << sample_increment << endl;
1462 cout << "sample: " << sample1 << " -> ";
1463 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1465 for (int i = 0; i < 108003; i++) {
1466 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, true /* use_subframes */ );
1467 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, true /* use_subframes */ );
1469 if ((i > 0) && ( ((oldsample - sample1) != sample_increment) && ((oldsample - sample1) != (sample_increment + 1)) && ((oldsample - sample1) != (sample_increment - 1)))) {
1470 cout << "ERROR: sample increment not right: " << (oldsample - sample1) << " != " << sample_increment << endl;
1471 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1472 cout << "sample: " << sample1 << endl;
1473 cout << "sample: " << sample1 << " -> ";
1474 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1478 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames || smpte2.subframes != smpte1.subframes) {
1479 cout << "ERROR: smpte2 not equal smpte1" << endl;
1480 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1481 cout << "sample: " << sample1 << endl;
1482 cout << "sample: " << sample1 << " -> ";
1483 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1486 oldsample = sample1;
1487 session->smpte_decrement( smpte1 );
1490 cout << "sample_decrement: " << sample_increment << endl;
1491 cout << "sample: " << sample1 << " -> ";
1492 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1497 #ifdef SMPTE_SAMPLE_TEST_5
1498 // Test 5: use_offset = true, use_subframes = false, increment seconds
1499 cout << "use_offset = true, use_subframes = false, increment seconds" << endl;
1505 smpte1.subframes = 0;
1506 sample1 = oldsample = 0;
1507 sample_increment = session->frame_rate();
1509 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1510 cout << "Starting at sample: " << sample1 << " -> ";
1511 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1513 for (int i = 0; i < 3600; i++) {
1514 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1515 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1517 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1518 // cout << "sample: " << sample1 << endl;
1519 // cout << "sample: " << sample1 << " -> ";
1520 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1522 // if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1524 // cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1528 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1529 cout << "ERROR: smpte2 not equal smpte1" << endl;
1530 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1531 cout << "sample: " << sample1 << endl;
1532 cout << "sample: " << sample1 << " -> ";
1533 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1536 oldsample = sample1;
1537 session->smpte_increment_seconds( smpte1 );
1540 cout << "sample_increment: " << sample_increment << endl;
1541 cout << "sample: " << sample1 << " -> ";
1542 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1546 #ifdef SMPTE_SAMPLE_TEST_6
1547 // Test 6: use_offset = true, use_subframes = false, increment minutes
1548 cout << "use_offset = true, use_subframes = false, increment minutes" << endl;
1554 smpte1.subframes = 0;
1555 sample1 = oldsample = 0;
1556 sample_increment = session->frame_rate() * 60;
1558 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1559 cout << "Starting at sample: " << sample1 << " -> ";
1560 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1562 for (int i = 0; i < 60; i++) {
1563 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1564 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1566 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1567 // cout << "sample: " << sample1 << endl;
1568 // cout << "sample: " << sample1 << " -> ";
1569 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1571 // if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1573 // cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1577 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1578 cout << "ERROR: smpte2 not equal smpte1" << endl;
1579 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1580 cout << "sample: " << sample1 << endl;
1581 cout << "sample: " << sample1 << " -> ";
1582 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1585 oldsample = sample1;
1586 session->smpte_increment_minutes( smpte1 );
1589 cout << "sample_increment: " << sample_increment << endl;
1590 cout << "sample: " << sample1 << " -> ";
1591 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1594 #ifdef SMPTE_SAMPLE_TEST_7
1595 // Test 7: use_offset = true, use_subframes = false, increment hours
1596 cout << "use_offset = true, use_subframes = false, increment hours" << endl;
1602 smpte1.subframes = 0;
1603 sample1 = oldsample = 0;
1604 sample_increment = session->frame_rate() * 60 * 60;
1606 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1607 cout << "Starting at sample: " << sample1 << " -> ";
1608 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1610 for (int i = 0; i < 10; i++) {
1611 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1612 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1614 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1615 // cout << "sample: " << sample1 << endl;
1616 // cout << "sample: " << sample1 << " -> ";
1617 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1619 // if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1621 // cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1625 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1626 cout << "ERROR: smpte2 not equal smpte1" << endl;
1627 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1628 cout << "sample: " << sample1 << endl;
1629 cout << "sample: " << sample1 << " -> ";
1630 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1633 oldsample = sample1;
1634 session->smpte_increment_hours( smpte1 );
1637 cout << "sample_increment: " << sample_increment << endl;
1638 cout << "sample: " << sample1 << " -> ";
1639 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1648 AudioClock::minsec_frame_from_display () const
1654 int hrs = atoi (ms_hours_label.get_text());
1655 int mins = atoi (ms_minutes_label.get_text());
1656 float secs = atof (ms_seconds_label.get_text());
1658 jack_nframes_t sr = session->frame_rate();
1660 return (jack_nframes_t) floor ((hrs * 60.0f * 60.0f * sr) + (mins * 60.0f * sr) + (secs * sr));
1664 AudioClock::bbt_frame_from_display (jack_nframes_t pos) const
1667 error << "AudioClock::current_time() called with BBT mode but without session!" << endmsg;
1672 any.type = AnyTime::BBT;
1674 any.bbt.bars = atoi (bars_label.get_text());
1675 any.bbt.beats = atoi (beats_label.get_text());
1676 any.bbt.ticks = atoi (ticks_label.get_text());
1678 jack_nframes_t ret = session->convert_to_frames_at (pos, any);
1685 AudioClock::bbt_frame_duration_from_display (jack_nframes_t pos) const
1688 error << "AudioClock::current_time() called with BBT mode but without session!" << endmsg;
1695 bbt.bars = atoi (bars_label.get_text());
1696 bbt.beats = atoi (beats_label.get_text());
1697 bbt.ticks = atoi (ticks_label.get_text());
1699 return session->tempo_map().bbt_duration_at(pos,bbt,1);
1703 AudioClock::audio_frame_from_display () const
1705 return (jack_nframes_t) atoi (audio_frames_label.get_text());
1709 AudioClock::build_ops_menu ()
1711 using namespace Menu_Helpers;
1712 ops_menu = new Menu;
1713 MenuList& ops_items = ops_menu->items();
1714 ops_menu->set_name ("ArdourContextMenu");
1716 Menu *mode_menu = manage (new Menu);
1717 MenuList& mode_items = mode_menu->items();
1718 mode_menu->set_name ("ArdourContextMenu");
1720 mode_items.push_back (MenuElem (_("SMPTE"), bind (mem_fun(*this, &AudioClock::set_mode), SMPTE)));
1721 mode_items.push_back (MenuElem (_("Bars:Beats"), bind (mem_fun(*this, &AudioClock::set_mode), BBT)));
1722 mode_items.push_back (MenuElem (_("Minutes:Seconds"), bind (mem_fun(*this, &AudioClock::set_mode), MinSec)));
1723 mode_items.push_back (MenuElem (_("Audio Frames"), bind (mem_fun(*this, &AudioClock::set_mode), Frames)));
1724 mode_items.push_back (MenuElem (_("Off"), bind (mem_fun(*this, &AudioClock::set_mode), Off)));
1726 ops_items.push_back (MenuElem (_("Mode"), *mode_menu));
1730 AudioClock::set_mode (Mode m)
1732 /* slightly tricky: this is called from within the ARDOUR_UI
1733 constructor by some of its clock members. at that time
1734 the instance pointer is unset, so we have to be careful.
1735 the main idea is to drop keyboard focus in case we had
1736 started editing the clock and then we switch clock mode.
1739 clock_base.grab_focus ();
1749 clock_base.remove ();
1759 clock_base.add (smpte_packer_hbox);
1760 Gtkmm2ext::set_size_request_to_display_given_text (hours_label, "-88", 0, 2);
1761 Gtkmm2ext::set_size_request_to_display_given_text (minutes_label, "88", 0, 2);
1762 Gtkmm2ext::set_size_request_to_display_given_text (seconds_label, "88", 0, 2);
1763 Gtkmm2ext::set_size_request_to_display_given_text (frames_label, "88", 0, 2);
1767 clock_base.add (bbt_packer_hbox);
1768 Gtkmm2ext::set_size_request_to_display_given_text (bars_label, "-888", 0, 2);
1769 Gtkmm2ext::set_size_request_to_display_given_text (beats_label, "88", 0, 2);
1770 Gtkmm2ext::set_size_request_to_display_given_text (ticks_label, "8888", 0, 2);
1774 clock_base.add (minsec_packer_hbox);
1775 Gtkmm2ext::set_size_request_to_display_given_text (ms_hours_label, "99", 0, 2);
1776 Gtkmm2ext::set_size_request_to_display_given_text (ms_minutes_label, "99", 0, 2);
1777 Gtkmm2ext::set_size_request_to_display_given_text (ms_seconds_label, "99", 0, 2);
1781 clock_base.add (frames_packer_hbox);
1782 Gtkmm2ext::set_size_request_to_display_given_text (audio_frames_label, "4294967296", 0, 2);
1788 set (last_when, true);
1789 clock_base.show_all ();
1790 key_entry_state = 0;