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));
198 Session::SMPTEOffsetChanged.connect (mem_fun (*this, &AudioClock::smpte_offset_changed));
204 set (last_when, true);
208 AudioClock::setup_events ()
210 clock_base.set_flags (Gtk::CAN_FOCUS);
212 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);
213 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);
214 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);
215 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);
216 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);
217 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);
218 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);
219 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);
220 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);
221 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);
222 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);
224 hours_ebox.set_flags (Gtk::CAN_FOCUS);
225 minutes_ebox.set_flags (Gtk::CAN_FOCUS);
226 seconds_ebox.set_flags (Gtk::CAN_FOCUS);
227 frames_ebox.set_flags (Gtk::CAN_FOCUS);
228 audio_frames_ebox.set_flags (Gtk::CAN_FOCUS);
229 bars_ebox.set_flags (Gtk::CAN_FOCUS);
230 beats_ebox.set_flags (Gtk::CAN_FOCUS);
231 ticks_ebox.set_flags (Gtk::CAN_FOCUS);
232 ms_hours_ebox.set_flags (Gtk::CAN_FOCUS);
233 ms_minutes_ebox.set_flags (Gtk::CAN_FOCUS);
234 ms_seconds_ebox.set_flags (Gtk::CAN_FOCUS);
236 hours_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), SMPTE_Hours));
237 minutes_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), SMPTE_Minutes));
238 seconds_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), SMPTE_Seconds));
239 frames_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), SMPTE_Frames));
240 audio_frames_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), AudioFrames));
241 bars_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), Bars));
242 beats_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), Beats));
243 ticks_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), Ticks));
244 ms_hours_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), MS_Hours));
245 ms_minutes_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), MS_Minutes));
246 ms_seconds_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), MS_Seconds));
248 hours_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), SMPTE_Hours));
249 minutes_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), SMPTE_Minutes));
250 seconds_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), SMPTE_Seconds));
251 frames_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), SMPTE_Frames));
252 audio_frames_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), AudioFrames));
253 bars_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), Bars));
254 beats_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), Beats));
255 ticks_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), Ticks));
256 ms_hours_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), MS_Hours));
257 ms_minutes_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), MS_Minutes));
258 ms_seconds_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), MS_Seconds));
260 hours_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), SMPTE_Hours));
261 minutes_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), SMPTE_Minutes));
262 seconds_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), SMPTE_Seconds));
263 frames_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), SMPTE_Frames));
264 audio_frames_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), AudioFrames));
265 bars_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), Bars));
266 beats_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), Beats));
267 ticks_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), Ticks));
268 ms_hours_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), MS_Hours));
269 ms_minutes_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), MS_Minutes));
270 ms_seconds_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), MS_Seconds));
272 hours_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), SMPTE_Hours));
273 minutes_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), SMPTE_Minutes));
274 seconds_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), SMPTE_Seconds));
275 frames_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), SMPTE_Frames));
276 audio_frames_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), AudioFrames));
277 bars_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), Bars));
278 beats_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), Beats));
279 ticks_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), Ticks));
280 ms_hours_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), MS_Hours));
281 ms_minutes_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), MS_Minutes));
282 ms_seconds_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), MS_Seconds));
284 hours_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), SMPTE_Hours));
285 minutes_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), SMPTE_Minutes));
286 seconds_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), SMPTE_Seconds));
287 frames_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), SMPTE_Frames));
288 audio_frames_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), AudioFrames));
289 bars_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), Bars));
290 beats_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), Beats));
291 ticks_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), Ticks));
292 ms_hours_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), MS_Hours));
293 ms_minutes_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), MS_Minutes));
294 ms_seconds_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), MS_Seconds));
296 hours_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), SMPTE_Hours));
297 minutes_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), SMPTE_Minutes));
298 seconds_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), SMPTE_Seconds));
299 frames_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), SMPTE_Frames));
300 audio_frames_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), AudioFrames));
301 bars_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), Bars));
302 beats_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), Beats));
303 ticks_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), Ticks));
304 ms_hours_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), MS_Hours));
305 ms_minutes_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), MS_Minutes));
306 ms_seconds_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), MS_Seconds));
308 hours_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), SMPTE_Hours));
309 minutes_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), SMPTE_Minutes));
310 seconds_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), SMPTE_Seconds));
311 frames_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), SMPTE_Frames));
312 audio_frames_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), AudioFrames));
313 bars_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), Bars));
314 beats_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), Beats));
315 ticks_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), Ticks));
316 ms_hours_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), MS_Hours));
317 ms_minutes_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), MS_Minutes));
318 ms_seconds_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), MS_Seconds));
322 AudioClock::on_realize ()
326 /* styles are not available until the widgets are bound to a window */
330 Gtkmm2ext::set_size_request_to_display_given_text (hours_label, "-88", 0, 2);
331 Gtkmm2ext::set_size_request_to_display_given_text (minutes_label, "88", 0, 2);
332 Gtkmm2ext::set_size_request_to_display_given_text (seconds_label, "88", 0, 2);
333 Gtkmm2ext::set_size_request_to_display_given_text (frames_label, "88", 0, 2);
337 Gtkmm2ext::set_size_request_to_display_given_text (bars_label, "-888", 0, 2);
338 Gtkmm2ext::set_size_request_to_display_given_text (beats_label, "88", 0, 2);
339 Gtkmm2ext::set_size_request_to_display_given_text (ticks_label, "8888", 0, 2);
343 Gtkmm2ext::set_size_request_to_display_given_text (ms_hours_label, "99", 0, 2);
344 Gtkmm2ext::set_size_request_to_display_given_text (ms_minutes_label, "99", 0, 2);
345 Gtkmm2ext::set_size_request_to_display_given_text (ms_seconds_label, "99", 0, 2);
349 Gtkmm2ext::set_size_request_to_display_given_text (audio_frames_label, "4294967296", 0, 2);
359 AudioClock::set (jack_nframes_t when, bool force)
362 if ((!force && !is_visible()) || session == 0) {
366 if (when == last_when && !force) {
372 set_smpte (when, force);
376 set_bbt (when, force);
380 set_minsec (when, force);
384 set_frames (when, force);
395 AudioClock::smpte_offset_changed ()
397 jack_nframes_t current;
402 current = current_duration();
404 current = current_time ();
414 AudioClock::set_frames (jack_nframes_t when, bool force)
417 snprintf (buf, sizeof (buf), "%u", when);
418 audio_frames_label.set_text (buf);
422 AudioClock::set_minsec (jack_nframes_t when, bool force)
431 hrs = (int) floor (left / (session->frame_rate() * 60.0f * 60.0f));
432 left -= (jack_nframes_t) floor (hrs * session->frame_rate() * 60.0f * 60.0f);
433 mins = (int) floor (left / (session->frame_rate() * 60.0f));
434 left -= (jack_nframes_t) floor (mins * session->frame_rate() * 60.0f);
435 secs = left / (float) session->frame_rate();
437 if (force || hrs != ms_last_hrs) {
438 sprintf (buf, "%d", hrs);
439 ms_hours_label.set_text (buf);
443 if (force || mins != ms_last_mins) {
444 sprintf (buf, "%d", mins);
445 ms_minutes_label.set_text (buf);
449 if (force || secs != ms_last_secs) {
450 sprintf (buf, "%06.3f", secs);
451 ms_seconds_label.set_text (buf);
457 AudioClock::set_smpte (jack_nframes_t when, bool force)
463 session->smpte_duration (when, smpte);
465 session->smpte_time (when, smpte);
468 if (force || smpte.hours != last_hrs || smpte.negative != last_negative) {
469 if (smpte.negative) {
470 sprintf (buf, "-%02" PRIu32, smpte.hours);
472 sprintf (buf, " %02" PRIu32, smpte.hours);
474 hours_label.set_text (buf);
475 last_hrs = smpte.hours;
476 last_negative = smpte.negative;
479 if (force || smpte.minutes != last_mins) {
480 sprintf (buf, "%02" PRIu32, smpte.minutes);
481 minutes_label.set_text (buf);
482 last_mins = smpte.minutes;
485 if (force || smpte.seconds != last_secs) {
486 sprintf (buf, "%02" PRIu32, smpte.seconds);
487 seconds_label.set_text (buf);
488 last_secs = smpte.seconds;
491 if (force || smpte.frames != last_frames) {
492 sprintf (buf, "%02" PRIu32, smpte.frames);
493 frames_label.set_text (buf);
494 last_frames = smpte.frames;
499 AudioClock::set_bbt (jack_nframes_t when, bool force)
504 session->tempo_map().bbt_time (when, bbt);
505 sprintf (buf, "%03" PRIu32, bbt.bars);
506 bars_label.set_text (buf);
507 sprintf (buf, "%02" PRIu32, bbt.beats);
508 beats_label.set_text (buf);
509 sprintf (buf, "%04" PRIu32, bbt.ticks);
510 ticks_label.set_text (buf);
513 TempoMap::Metric m (session->tempo_map().metric_at (when));
514 sprintf (buf, "%-5.2f", m.tempo().beats_per_minute());
515 tempo_label->set_text (buf);
516 sprintf (buf, "%g|%g", m.meter().beats_per_bar(), m.meter().note_divisor());
517 meter_label->set_text (buf);
522 AudioClock::set_session (Session *s)
527 set (last_when, true);
532 AudioClock::field_key_release_event (GdkEventKey *ev, Field field)
537 bool move_on = false;
541 label = &hours_label;
544 label = &minutes_label;
547 label = &seconds_label;
550 label = &frames_label;
554 label = &audio_frames_label;
558 label = &ms_hours_label;
561 label = &ms_minutes_label;
564 label = &ms_seconds_label;
571 label = &beats_label;
574 label = &ticks_label;
580 switch (ev->keyval) {
624 if (_mode == MinSec && field == MS_Seconds) {
638 clock_base.grab_focus ();
647 if (key_entry_state == 0) {
649 /* initialize with a fresh new string */
651 if (field != AudioFrames) {
652 for (uint32_t xn = 0; xn < field_length[field] - 1; ++xn) {
661 string existing = label->get_text();
662 if (existing.length() >= field_length[field]) {
663 new_text = existing.substr (1, field_length[field] - 1);
665 new_text = existing.substr (0, field_length[field] - 1);
669 new_text += new_char;
670 label->set_text (new_text);
674 if (key_entry_state == field_length[field]) {
680 if (key_entry_state) {
687 // Check SMPTE fields for sanity (may also adjust fields)
688 smpte_sanitize_display();
694 ValueChanged(); /* EMIT_SIGNAL */
697 /* move on to the next field.
705 minutes_ebox.grab_focus ();
708 seconds_ebox.grab_focus ();
711 frames_ebox.grab_focus ();
714 clock_base.grab_focus ();
719 clock_base.grab_focus ();
725 ms_minutes_ebox.grab_focus ();
728 ms_seconds_ebox.grab_focus ();
731 clock_base.grab_focus ();
737 beats_ebox.grab_focus ();
740 ticks_ebox.grab_focus ();
743 clock_base.grab_focus ();
756 AudioClock::field_focus_in_event (GdkEventFocus *ev, Field field)
762 hours_ebox.set_flags (Gtk::HAS_FOCUS);
763 hours_ebox.set_state (Gtk::STATE_ACTIVE);
766 minutes_ebox.set_flags (Gtk::HAS_FOCUS);
767 minutes_ebox.set_state (Gtk::STATE_ACTIVE);
770 seconds_ebox.set_flags (Gtk::HAS_FOCUS);
771 seconds_ebox.set_state (Gtk::STATE_ACTIVE);
774 frames_ebox.set_flags (Gtk::HAS_FOCUS);
775 frames_ebox.set_state (Gtk::STATE_ACTIVE);
779 audio_frames_ebox.set_flags (Gtk::HAS_FOCUS);
780 audio_frames_ebox.set_state (Gtk::STATE_ACTIVE);
784 ms_hours_ebox.set_flags (Gtk::HAS_FOCUS);
785 ms_hours_ebox.set_state (Gtk::STATE_ACTIVE);
788 ms_minutes_ebox.set_flags (Gtk::HAS_FOCUS);
789 ms_minutes_ebox.set_state (Gtk::STATE_ACTIVE);
792 ms_seconds_ebox.set_flags (Gtk::HAS_FOCUS);
793 ms_seconds_ebox.set_state (Gtk::STATE_ACTIVE);
796 bars_ebox.set_flags (Gtk::HAS_FOCUS);
797 bars_ebox.set_state (Gtk::STATE_ACTIVE);
800 beats_ebox.set_flags (Gtk::HAS_FOCUS);
801 beats_ebox.set_state (Gtk::STATE_ACTIVE);
804 ticks_ebox.set_flags (Gtk::HAS_FOCUS);
805 ticks_ebox.set_state (Gtk::STATE_ACTIVE);
813 AudioClock::field_focus_out_event (GdkEventFocus *ev, Field field)
818 hours_ebox.unset_flags (Gtk::HAS_FOCUS);
819 hours_ebox.set_state (Gtk::STATE_NORMAL);
822 minutes_ebox.unset_flags (Gtk::HAS_FOCUS);
823 minutes_ebox.set_state (Gtk::STATE_NORMAL);
826 seconds_ebox.unset_flags (Gtk::HAS_FOCUS);
827 seconds_ebox.set_state (Gtk::STATE_NORMAL);
830 frames_ebox.unset_flags (Gtk::HAS_FOCUS);
831 frames_ebox.set_state (Gtk::STATE_NORMAL);
835 audio_frames_ebox.unset_flags (Gtk::HAS_FOCUS);
836 audio_frames_ebox.set_state (Gtk::STATE_NORMAL);
840 ms_hours_ebox.unset_flags (Gtk::HAS_FOCUS);
841 ms_hours_ebox.set_state (Gtk::STATE_NORMAL);
844 ms_minutes_ebox.unset_flags (Gtk::HAS_FOCUS);
845 ms_minutes_ebox.set_state (Gtk::STATE_NORMAL);
848 ms_seconds_ebox.unset_flags (Gtk::HAS_FOCUS);
849 ms_seconds_ebox.set_state (Gtk::STATE_NORMAL);
853 bars_ebox.unset_flags (Gtk::HAS_FOCUS);
854 bars_ebox.set_state (Gtk::STATE_NORMAL);
857 beats_ebox.unset_flags (Gtk::HAS_FOCUS);
858 beats_ebox.set_state (Gtk::STATE_NORMAL);
861 ticks_ebox.unset_flags (Gtk::HAS_FOCUS);
862 ticks_ebox.set_state (Gtk::STATE_NORMAL);
870 AudioClock::field_button_release_event (GdkEventButton *ev, Field field)
875 gdk_pointer_ungrab(GDK_CURRENT_TIME);
877 if (ev->y > drag_start_y+1 || ev->y < drag_start_y-1 || Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)){
878 // we actually dragged so return without setting editing focus, or we shift clicked
888 ops_menu->popup (1, ev->time);
892 if (Keyboard::is_context_menu_event (ev)) {
896 ops_menu->popup (1, ev->time);
900 switch (ev->button) {
904 hours_ebox.grab_focus();
907 minutes_ebox.grab_focus();
910 seconds_ebox.grab_focus();
913 frames_ebox.grab_focus();
917 audio_frames_ebox.grab_focus();
921 ms_hours_ebox.grab_focus();
924 ms_minutes_ebox.grab_focus();
927 ms_seconds_ebox.grab_focus();
931 bars_ebox.grab_focus ();
934 beats_ebox.grab_focus ();
937 ticks_ebox.grab_focus ();
950 AudioClock::field_button_press_event (GdkEventButton *ev, Field field)
952 if (session == 0) return FALSE;
954 jack_nframes_t frames = 0;
956 switch (ev->button) {
958 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
960 ValueChanged (); /* EMIT_SIGNAL */
963 /* make absolutely sure that the pointer is grabbed */
964 gdk_pointer_grab(ev->window,FALSE ,
965 GdkEventMask( Gdk::POINTER_MOTION_MASK | Gdk::BUTTON_PRESS_MASK |Gdk::BUTTON_RELEASE_MASK),
969 drag_start_y = ev->y;
974 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
976 ValueChanged (); /* EMIT_SIGNAL */
981 /* used for context sensitive menu */
986 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
987 frames = get_frames (field);
989 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
992 set (current_time() + frames, true);
993 ValueChanged (); /* EMIT_SIGNAL */
999 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Shift)) {
1000 frames = get_frames (field);
1002 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
1006 if ((double)current_time() - (double)frames < 0.0) {
1010 set (current_time() - frames, true);
1013 ValueChanged (); /* EMIT_SIGNAL */
1027 AudioClock::field_button_scroll_event (GdkEventScroll *ev, Field field)
1029 if (session == 0) return FALSE;
1031 jack_nframes_t frames = 0;
1033 switch (ev->direction) {
1036 frames = get_frames (field);
1038 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
1041 set (current_time() + frames, true);
1042 ValueChanged (); /* EMIT_SIGNAL */
1046 case GDK_SCROLL_DOWN:
1047 frames = get_frames (field);
1049 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
1053 if ((double)current_time() - (double)frames < 0.0) {
1056 set (current_time() - frames, true);
1059 ValueChanged (); /* EMIT_SIGNAL */
1072 AudioClock::field_motion_notify_event (GdkEventMotion *ev, Field field)
1074 if (session == 0 || !dragging) {
1078 float pixel_frame_scale_factor = 0.2f;
1081 if (Keyboard::modifier_state_equals (ev->state, Keyboard::Control)) {
1082 pixel_frame_scale_factor = 0.1f;
1086 if (Keyboard::modifier_state_contains (ev->state,
1087 Keyboard::Control|Keyboard::Alt)) {
1089 pixel_frame_scale_factor = 0.025f;
1092 double y_delta = ev->y - drag_y;
1094 drag_accum += y_delta*pixel_frame_scale_factor;
1098 if (trunc(drag_accum) != 0) {
1100 jack_nframes_t frames;
1101 jack_nframes_t pos ;
1103 dir = (drag_accum < 0 ? 1:-1);
1104 pos = current_time();
1105 frames = get_frames (field,pos,dir);
1107 if (frames != 0 && frames * drag_accum < current_time()) {
1109 set ((jack_nframes_t) floor (pos - drag_accum * frames), false); // minus because up is negative in computer-land
1117 ValueChanged(); /* EMIT_SIGNAL */
1126 AudioClock::get_frames (Field field,jack_nframes_t pos,int dir)
1129 jack_nframes_t frames = 0;
1133 frames = (jack_nframes_t) floor (3600.0 * session->frame_rate());
1136 frames = (jack_nframes_t) floor (60.0 * session->frame_rate());
1139 frames = session->frame_rate();
1142 frames = (jack_nframes_t) floor (session->frame_rate() / session->smpte_frames_per_second);
1150 frames = (jack_nframes_t) floor (3600.0 * session->frame_rate());
1153 frames = (jack_nframes_t) floor (60.0 * session->frame_rate());
1156 frames = session->frame_rate();
1163 frames = session->tempo_map().bbt_duration_at(pos,bbt,dir);
1169 frames = session->tempo_map().bbt_duration_at(pos,bbt,dir);
1175 frames = session->tempo_map().bbt_duration_at(pos,bbt,dir);
1183 AudioClock::current_time (jack_nframes_t pos) const
1185 jack_nframes_t ret = 0;
1189 ret = smpte_frame_from_display ();
1192 ret = bbt_frame_from_display (pos);
1196 ret = minsec_frame_from_display ();
1200 ret = audio_frame_from_display ();
1211 AudioClock::current_duration (jack_nframes_t pos) const
1213 jack_nframes_t ret = 0;
1217 ret = smpte_frame_from_display ();
1220 ret = bbt_frame_duration_from_display (pos);
1224 ret = minsec_frame_from_display ();
1228 ret = audio_frame_from_display ();
1239 AudioClock::smpte_sanitize_display()
1241 // Check SMPTE fields for sanity, possibly adjusting values
1242 if (atoi(minutes_label.get_text()) > 59) {
1243 minutes_label.set_text("59");
1246 if (atoi(seconds_label.get_text()) > 59) {
1247 seconds_label.set_text("59");
1250 switch ((long)rint(session->smpte_frames_per_second)) {
1252 if (atoi(frames_label.get_text()) > 23) {
1253 frames_label.set_text("23");
1257 if (atoi(frames_label.get_text()) > 24) {
1258 frames_label.set_text("24");
1262 if (atoi(frames_label.get_text()) > 29) {
1263 frames_label.set_text("29");
1270 if (session->smpte_drop_frames) {
1271 if ((atoi(minutes_label.get_text()) % 10) && (atoi(seconds_label.get_text()) == 0) && (atoi(frames_label.get_text()) < 2)) {
1272 frames_label.set_text("02");
1278 AudioClock::smpte_frame_from_display () const
1285 jack_nframes_t sample;
1287 smpte.hours = atoi (hours_label.get_text());
1288 smpte.minutes = atoi (minutes_label.get_text());
1289 smpte.seconds = atoi (seconds_label.get_text());
1290 smpte.frames = atoi (frames_label.get_text());
1292 session->smpte_to_sample( smpte, sample, false /* use_offset */, false /* use_subframes */ );
1296 #define SMPTE_SAMPLE_TEST_1
1297 #define SMPTE_SAMPLE_TEST_2
1298 #define SMPTE_SAMPLE_TEST_3
1299 #define SMPTE_SAMPLE_TEST_4
1300 #define SMPTE_SAMPLE_TEST_5
1301 #define SMPTE_SAMPLE_TEST_6
1302 #define SMPTE_SAMPLE_TEST_7
1304 // Testcode for smpte<->sample conversions (P.S.)
1306 jack_nframes_t sample1;
1307 jack_nframes_t oldsample = 0;
1309 jack_nframes_t sample_increment;
1311 sample_increment = (long)rint(session->frame_rate() / session->smpte_frames_per_second);
1313 #ifdef SMPTE_SAMPLE_TEST_1
1314 // Test 1: use_offset = false, use_subframes = false
1315 cout << "use_offset = false, use_subframes = false" << endl;
1316 for (int i = 0; i < 108003; i++) {
1317 session->smpte_to_sample( smpte1, sample1, false /* use_offset */, false /* use_subframes */ );
1318 session->sample_to_smpte( sample1, smpte2, false /* use_offset */, false /* use_subframes */ );
1320 if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
1321 cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1322 cout << "smpte1: " << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1323 cout << "sample: " << sample1 << endl;
1324 cout << "sample: " << sample1 << " -> ";
1325 cout << "smpte2: " << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1329 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1330 cout << "ERROR: smpte2 not equal smpte1" << endl;
1331 cout << "smpte1: " << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1332 cout << "sample: " << sample1 << endl;
1333 cout << "sample: " << sample1 << " -> ";
1334 cout << "smpte2: " << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1337 oldsample = sample1;
1338 session->smpte_increment( smpte1 );
1341 cout << "sample_increment: " << sample_increment << endl;
1342 cout << "sample: " << sample1 << " -> ";
1343 cout << "smpte: " << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1346 #ifdef SMPTE_SAMPLE_TEST_2
1347 // Test 2: use_offset = true, use_subframes = false
1348 cout << "use_offset = true, use_subframes = false" << endl;
1354 smpte1.subframes = 0;
1355 sample1 = oldsample = 0;
1357 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1358 cout << "Starting at sample: " << sample1 << " -> ";
1359 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1361 for (int i = 0; i < 108003; i++) {
1362 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1363 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1365 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1366 // cout << "sample: " << sample1 << endl;
1367 // cout << "sample: " << sample1 << " -> ";
1368 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1370 if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
1371 cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1372 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1373 cout << "sample: " << sample1 << endl;
1374 cout << "sample: " << sample1 << " -> ";
1375 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1379 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1380 cout << "ERROR: smpte2 not equal smpte1" << endl;
1381 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1382 cout << "sample: " << sample1 << endl;
1383 cout << "sample: " << sample1 << " -> ";
1384 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1387 oldsample = sample1;
1388 session->smpte_increment( smpte1 );
1391 cout << "sample_increment: " << sample_increment << endl;
1392 cout << "sample: " << sample1 << " -> ";
1393 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1396 #ifdef SMPTE_SAMPLE_TEST_3
1397 // Test 3: use_offset = true, use_subframes = false, decrement
1398 cout << "use_offset = true, use_subframes = false, decrement" << endl;
1400 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1401 cout << "Starting at sample: " << sample1 << " -> ";
1402 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1404 for (int i = 0; i < 108003; i++) {
1405 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1406 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1408 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1409 // cout << "sample: " << sample1 << endl;
1410 // cout << "sample: " << sample1 << " -> ";
1411 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1413 if ((i > 0) && ( ((oldsample - sample1) != sample_increment) && ((oldsample - sample1) != (sample_increment + 1)) && ((oldsample - sample1) != (sample_increment - 1)))) {
1414 cout << "ERROR: sample increment not right: " << (oldsample - sample1) << " != " << sample_increment << endl;
1415 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1416 cout << "sample: " << sample1 << endl;
1417 cout << "sample: " << sample1 << " -> ";
1418 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1422 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1423 cout << "ERROR: smpte2 not equal smpte1" << endl;
1424 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1425 cout << "sample: " << sample1 << endl;
1426 cout << "sample: " << sample1 << " -> ";
1427 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1430 oldsample = sample1;
1431 session->smpte_decrement( smpte1 );
1434 cout << "sample_decrement: " << sample_increment << endl;
1435 cout << "sample: " << sample1 << " -> ";
1436 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1440 #ifdef SMPTE_SAMPLE_TEST_4
1441 // Test 4: use_offset = true, use_subframes = true
1442 cout << "use_offset = true, use_subframes = true" << endl;
1444 for (long sub = 5; sub < 80; sub += 5) {
1449 smpte1.subframes = 0;
1450 sample1 = oldsample = (sample_increment * sub) / 80;
1452 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, true /* use_subframes */ );
1454 cout << "starting at sample: " << sample1 << " -> ";
1455 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1457 for (int i = 0; i < 108003; i++) {
1458 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, true /* use_subframes */ );
1459 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, true /* use_subframes */ );
1461 if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
1462 cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1463 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1464 cout << "sample: " << sample1 << endl;
1465 cout << "sample: " << sample1 << " -> ";
1466 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1470 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames || smpte2.subframes != smpte1.subframes) {
1471 cout << "ERROR: smpte2 not equal smpte1" << endl;
1472 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1473 cout << "sample: " << sample1 << endl;
1474 cout << "sample: " << sample1 << " -> ";
1475 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1478 oldsample = sample1;
1479 session->smpte_increment( smpte1 );
1482 cout << "sample_increment: " << sample_increment << endl;
1483 cout << "sample: " << sample1 << " -> ";
1484 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1486 for (int i = 0; i < 108003; i++) {
1487 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, true /* use_subframes */ );
1488 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, true /* use_subframes */ );
1490 if ((i > 0) && ( ((oldsample - sample1) != sample_increment) && ((oldsample - sample1) != (sample_increment + 1)) && ((oldsample - sample1) != (sample_increment - 1)))) {
1491 cout << "ERROR: sample increment not right: " << (oldsample - sample1) << " != " << sample_increment << endl;
1492 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1493 cout << "sample: " << sample1 << endl;
1494 cout << "sample: " << sample1 << " -> ";
1495 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1499 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames || smpte2.subframes != smpte1.subframes) {
1500 cout << "ERROR: smpte2 not equal smpte1" << endl;
1501 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1502 cout << "sample: " << sample1 << endl;
1503 cout << "sample: " << sample1 << " -> ";
1504 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1507 oldsample = sample1;
1508 session->smpte_decrement( smpte1 );
1511 cout << "sample_decrement: " << sample_increment << endl;
1512 cout << "sample: " << sample1 << " -> ";
1513 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1518 #ifdef SMPTE_SAMPLE_TEST_5
1519 // Test 5: use_offset = true, use_subframes = false, increment seconds
1520 cout << "use_offset = true, use_subframes = false, increment seconds" << endl;
1526 smpte1.subframes = 0;
1527 sample1 = oldsample = 0;
1528 sample_increment = session->frame_rate();
1530 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1531 cout << "Starting at sample: " << sample1 << " -> ";
1532 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1534 for (int i = 0; i < 3600; i++) {
1535 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1536 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1538 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1539 // cout << "sample: " << sample1 << endl;
1540 // cout << "sample: " << sample1 << " -> ";
1541 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1543 // if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1545 // cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1549 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1550 cout << "ERROR: smpte2 not equal smpte1" << endl;
1551 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1552 cout << "sample: " << sample1 << endl;
1553 cout << "sample: " << sample1 << " -> ";
1554 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1557 oldsample = sample1;
1558 session->smpte_increment_seconds( smpte1 );
1561 cout << "sample_increment: " << sample_increment << endl;
1562 cout << "sample: " << sample1 << " -> ";
1563 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1567 #ifdef SMPTE_SAMPLE_TEST_6
1568 // Test 6: use_offset = true, use_subframes = false, increment minutes
1569 cout << "use_offset = true, use_subframes = false, increment minutes" << endl;
1575 smpte1.subframes = 0;
1576 sample1 = oldsample = 0;
1577 sample_increment = session->frame_rate() * 60;
1579 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1580 cout << "Starting at sample: " << sample1 << " -> ";
1581 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1583 for (int i = 0; i < 60; i++) {
1584 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1585 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1587 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1588 // cout << "sample: " << sample1 << endl;
1589 // cout << "sample: " << sample1 << " -> ";
1590 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1592 // if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1594 // cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1598 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1599 cout << "ERROR: smpte2 not equal smpte1" << endl;
1600 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1601 cout << "sample: " << sample1 << endl;
1602 cout << "sample: " << sample1 << " -> ";
1603 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1606 oldsample = sample1;
1607 session->smpte_increment_minutes( smpte1 );
1610 cout << "sample_increment: " << sample_increment << endl;
1611 cout << "sample: " << sample1 << " -> ";
1612 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1615 #ifdef SMPTE_SAMPLE_TEST_7
1616 // Test 7: use_offset = true, use_subframes = false, increment hours
1617 cout << "use_offset = true, use_subframes = false, increment hours" << endl;
1623 smpte1.subframes = 0;
1624 sample1 = oldsample = 0;
1625 sample_increment = session->frame_rate() * 60 * 60;
1627 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1628 cout << "Starting at sample: " << sample1 << " -> ";
1629 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1631 for (int i = 0; i < 10; i++) {
1632 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1633 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1635 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1636 // cout << "sample: " << sample1 << endl;
1637 // cout << "sample: " << sample1 << " -> ";
1638 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1640 // if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1642 // cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1646 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1647 cout << "ERROR: smpte2 not equal smpte1" << endl;
1648 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1649 cout << "sample: " << sample1 << endl;
1650 cout << "sample: " << sample1 << " -> ";
1651 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1654 oldsample = sample1;
1655 session->smpte_increment_hours( smpte1 );
1658 cout << "sample_increment: " << sample_increment << endl;
1659 cout << "sample: " << sample1 << " -> ";
1660 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1669 AudioClock::minsec_frame_from_display () const
1675 int hrs = atoi (ms_hours_label.get_text());
1676 int mins = atoi (ms_minutes_label.get_text());
1677 float secs = atof (ms_seconds_label.get_text());
1679 jack_nframes_t sr = session->frame_rate();
1681 return (jack_nframes_t) floor ((hrs * 60.0f * 60.0f * sr) + (mins * 60.0f * sr) + (secs * sr));
1685 AudioClock::bbt_frame_from_display (jack_nframes_t pos) const
1688 error << "AudioClock::current_time() called with BBT mode but without session!" << endmsg;
1693 any.type = AnyTime::BBT;
1695 any.bbt.bars = atoi (bars_label.get_text());
1696 any.bbt.beats = atoi (beats_label.get_text());
1697 any.bbt.ticks = atoi (ticks_label.get_text());
1699 jack_nframes_t ret = session->convert_to_frames_at (pos, any);
1706 AudioClock::bbt_frame_duration_from_display (jack_nframes_t pos) const
1709 error << "AudioClock::current_time() called with BBT mode but without session!" << endmsg;
1716 bbt.bars = atoi (bars_label.get_text());
1717 bbt.beats = atoi (beats_label.get_text());
1718 bbt.ticks = atoi (ticks_label.get_text());
1720 return session->tempo_map().bbt_duration_at(pos,bbt,1);
1724 AudioClock::audio_frame_from_display () const
1726 return (jack_nframes_t) atoi (audio_frames_label.get_text());
1730 AudioClock::build_ops_menu ()
1732 using namespace Menu_Helpers;
1733 ops_menu = new Menu;
1734 MenuList& ops_items = ops_menu->items();
1735 ops_menu->set_name ("ArdourContextMenu");
1737 Menu *mode_menu = manage (new Menu);
1738 MenuList& mode_items = mode_menu->items();
1739 mode_menu->set_name ("ArdourContextMenu");
1741 mode_items.push_back (MenuElem (_("SMPTE"), bind (mem_fun(*this, &AudioClock::set_mode), SMPTE)));
1742 mode_items.push_back (MenuElem (_("Bars:Beats"), bind (mem_fun(*this, &AudioClock::set_mode), BBT)));
1743 mode_items.push_back (MenuElem (_("Minutes:Seconds"), bind (mem_fun(*this, &AudioClock::set_mode), MinSec)));
1744 mode_items.push_back (MenuElem (_("Audio Frames"), bind (mem_fun(*this, &AudioClock::set_mode), Frames)));
1745 mode_items.push_back (MenuElem (_("Off"), bind (mem_fun(*this, &AudioClock::set_mode), Off)));
1747 ops_items.push_back (MenuElem (_("Mode"), *mode_menu));
1751 AudioClock::set_mode (Mode m)
1753 /* slightly tricky: this is called from within the ARDOUR_UI
1754 constructor by some of its clock members. at that time
1755 the instance pointer is unset, so we have to be careful.
1756 the main idea is to drop keyboard focus in case we had
1757 started editing the clock and then we switch clock mode.
1760 clock_base.grab_focus ();
1770 clock_base.remove ();
1780 clock_base.add (smpte_packer_hbox);
1781 Gtkmm2ext::set_size_request_to_display_given_text (hours_label, "-88", 0, 2);
1782 Gtkmm2ext::set_size_request_to_display_given_text (minutes_label, "88", 0, 2);
1783 Gtkmm2ext::set_size_request_to_display_given_text (seconds_label, "88", 0, 2);
1784 Gtkmm2ext::set_size_request_to_display_given_text (frames_label, "88", 0, 2);
1788 clock_base.add (bbt_packer_hbox);
1789 Gtkmm2ext::set_size_request_to_display_given_text (bars_label, "-888", 0, 2);
1790 Gtkmm2ext::set_size_request_to_display_given_text (beats_label, "88", 0, 2);
1791 Gtkmm2ext::set_size_request_to_display_given_text (ticks_label, "8888", 0, 2);
1795 clock_base.add (minsec_packer_hbox);
1796 Gtkmm2ext::set_size_request_to_display_given_text (ms_hours_label, "99", 0, 2);
1797 Gtkmm2ext::set_size_request_to_display_given_text (ms_minutes_label, "99", 0, 2);
1798 Gtkmm2ext::set_size_request_to_display_given_text (ms_seconds_label, "99", 0, 2);
1802 clock_base.add (frames_packer_hbox);
1803 Gtkmm2ext::set_size_request_to_display_given_text (audio_frames_label, "4294967296", 0, 2);
1809 set (last_when, true);
1810 clock_base.show_all ();
1811 key_entry_state = 0;