2 Copyright (C) 1999 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include <cstdio> // for sprintf
23 #include <pbd/convert.h>
24 #include <pbd/enumwriter.h>
26 #include <gtkmm2ext/utils.h>
28 #include <ardour/ardour.h>
29 #include <ardour/session.h>
30 #include <ardour/tempo.h>
31 #include <ardour/profile.h>
32 #include <sigc++/bind.h>
34 #include "ardour_ui.h"
35 #include "audio_clock.h"
40 using namespace ARDOUR;
49 sigc::signal<void> AudioClock::ModeChanged;
50 vector<AudioClock*> AudioClock::clocks;
52 const uint32_t AudioClock::field_length[(int) AudioClock::AudioFrames+1] = {
54 2, /* SMPTE_Minutes */
55 2, /* SMPTE_Seconds */
66 AudioClock::AudioClock (std::string clock_name, bool transient, std::string widget_name, bool allow_edit, bool duration, bool with_info)
68 is_transient (transient),
69 is_duration (duration),
70 editable (allow_edit),
88 frames_upper_info_label = manage (new Label);
89 frames_lower_info_label = manage (new Label);
90 smpte_upper_info_label = manage (new Label);
91 smpte_lower_info_label = manage (new Label);
92 bbt_upper_info_label = manage (new Label);
93 bbt_lower_info_label = manage (new Label);
95 frames_upper_info_label->set_name ("AudioClockFramesUpperInfo");
96 frames_lower_info_label->set_name ("AudioClockFramesLowerInfo");
97 smpte_upper_info_label->set_name ("AudioClockSMPTEUpperInfo");
98 smpte_lower_info_label->set_name ("AudioClockSMPTELowerInfo");
99 bbt_upper_info_label->set_name ("AudioClockBBTUpperInfo");
100 bbt_lower_info_label->set_name ("AudioClockBBTLowerInfo");
102 Gtkmm2ext::set_size_request_to_display_given_text(*smpte_upper_info_label, "23.98",0,0);
103 Gtkmm2ext::set_size_request_to_display_given_text(*smpte_lower_info_label, "NDF",0,0);
105 frames_info_box.pack_start (*frames_upper_info_label, true, true);
106 frames_info_box.pack_start (*frames_lower_info_label, true, true);
107 smpte_info_box.pack_start (*smpte_upper_info_label, true, true);
108 smpte_info_box.pack_start (*smpte_lower_info_label, true, true);
109 bbt_info_box.pack_start (*bbt_upper_info_label, true, true);
110 bbt_info_box.pack_start (*bbt_lower_info_label, true, true);
113 frames_upper_info_label = 0;
114 frames_lower_info_label = 0;
115 smpte_upper_info_label = 0;
116 smpte_lower_info_label = 0;
117 bbt_upper_info_label = 0;
118 bbt_lower_info_label = 0;
121 audio_frames_ebox.add (audio_frames_label);
123 frames_packer.set_homogeneous (false);
124 frames_packer.set_border_width (2);
125 frames_packer.pack_start (audio_frames_ebox, false, false);
128 frames_packer.pack_start (frames_info_box, false, false, 5);
131 frames_packer_hbox.pack_start (frames_packer, true, false);
133 hours_ebox.add (hours_label);
134 minutes_ebox.add (minutes_label);
135 seconds_ebox.add (seconds_label);
136 frames_ebox.add (frames_label);
137 bars_ebox.add (bars_label);
138 beats_ebox.add (beats_label);
139 ticks_ebox.add (ticks_label);
140 ms_hours_ebox.add (ms_hours_label);
141 ms_minutes_ebox.add (ms_minutes_label);
142 ms_seconds_ebox.add (ms_seconds_label);
144 smpte_packer.set_homogeneous (false);
145 smpte_packer.set_border_width (2);
146 smpte_packer.pack_start (hours_ebox, false, false);
147 smpte_packer.pack_start (colon1, false, false);
148 smpte_packer.pack_start (minutes_ebox, false, false);
149 smpte_packer.pack_start (colon2, false, false);
150 smpte_packer.pack_start (seconds_ebox, false, false);
151 smpte_packer.pack_start (colon3, false, false);
152 smpte_packer.pack_start (frames_ebox, false, false);
155 smpte_packer.pack_start (smpte_info_box, false, false, 5);
158 smpte_packer_hbox.pack_start (smpte_packer, true, false);
160 bbt_packer.set_homogeneous (false);
161 bbt_packer.set_border_width (2);
162 bbt_packer.pack_start (bars_ebox, false, false);
163 bbt_packer.pack_start (b1, false, false);
164 bbt_packer.pack_start (beats_ebox, false, false);
165 bbt_packer.pack_start (b2, false, false);
166 bbt_packer.pack_start (ticks_ebox, false, false);
169 bbt_packer.pack_start (bbt_info_box, false, false, 5);
172 bbt_packer_hbox.pack_start (bbt_packer, true, false);
174 minsec_packer.set_homogeneous (false);
175 minsec_packer.set_border_width (2);
176 minsec_packer.pack_start (ms_hours_ebox, false, false);
177 minsec_packer.pack_start (colon4, false, false);
178 minsec_packer.pack_start (ms_minutes_ebox, false, false);
179 minsec_packer.pack_start (colon5, false, false);
180 minsec_packer.pack_start (ms_seconds_ebox, false, false);
182 minsec_packer_hbox.pack_start (minsec_packer, true, false);
184 clock_frame.set_shadow_type (Gtk::SHADOW_IN);
185 clock_frame.set_name ("BaseFrame");
187 clock_frame.add (clock_base);
189 set_widget_name (widget_name);
191 _mode = BBT; /* lie to force mode switch */
194 pack_start (clock_frame, true, true);
196 /* the clock base handles button releases for menu popup regardless of
197 editable status. if the clock is editable, the clock base is where
198 we pass focus to after leaving the last editable "field", which
199 will then shutdown editing till the user starts it up again.
201 it does this because the focus out event on the field disables
202 keyboard event handling, and we don't connect anything up to
203 notice focus in on the clock base. hence, keyboard event handling
207 clock_base.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::SCROLL_MASK);
208 clock_base.signal_button_release_event().connect (bind (mem_fun (*this, &AudioClock::field_button_release_event), SMPTE_Hours));
210 Session::SMPTEOffsetChanged.connect (mem_fun (*this, &AudioClock::smpte_offset_changed));
216 set (last_when, true);
219 clocks.push_back (this);
224 AudioClock::set_widget_name (string name)
226 Widget::set_name (name);
228 clock_base.set_name (name);
230 audio_frames_label.set_name (name);
231 hours_label.set_name (name);
232 minutes_label.set_name (name);
233 seconds_label.set_name (name);
234 frames_label.set_name (name);
235 bars_label.set_name (name);
236 beats_label.set_name (name);
237 ticks_label.set_name (name);
238 ms_hours_label.set_name (name);
239 ms_minutes_label.set_name (name);
240 ms_seconds_label.set_name (name);
241 hours_ebox.set_name (name);
242 minutes_ebox.set_name (name);
243 seconds_ebox.set_name (name);
244 frames_ebox.set_name (name);
245 audio_frames_ebox.set_name (name);
246 bars_ebox.set_name (name);
247 beats_ebox.set_name (name);
248 ticks_ebox.set_name (name);
249 ms_hours_ebox.set_name (name);
250 ms_minutes_ebox.set_name (name);
251 ms_seconds_ebox.set_name (name);
253 colon1.set_name (name);
254 colon2.set_name (name);
255 colon3.set_name (name);
256 colon4.set_name (name);
257 colon5.set_name (name);
265 AudioClock::setup_events ()
267 clock_base.set_flags (Gtk::CAN_FOCUS);
269 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);
270 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);
271 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);
272 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);
273 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);
274 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);
275 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);
276 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);
277 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);
278 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);
279 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);
281 hours_ebox.set_flags (Gtk::CAN_FOCUS);
282 minutes_ebox.set_flags (Gtk::CAN_FOCUS);
283 seconds_ebox.set_flags (Gtk::CAN_FOCUS);
284 frames_ebox.set_flags (Gtk::CAN_FOCUS);
285 audio_frames_ebox.set_flags (Gtk::CAN_FOCUS);
286 bars_ebox.set_flags (Gtk::CAN_FOCUS);
287 beats_ebox.set_flags (Gtk::CAN_FOCUS);
288 ticks_ebox.set_flags (Gtk::CAN_FOCUS);
289 ms_hours_ebox.set_flags (Gtk::CAN_FOCUS);
290 ms_minutes_ebox.set_flags (Gtk::CAN_FOCUS);
291 ms_seconds_ebox.set_flags (Gtk::CAN_FOCUS);
293 hours_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), SMPTE_Hours));
294 minutes_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), SMPTE_Minutes));
295 seconds_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), SMPTE_Seconds));
296 frames_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), SMPTE_Frames));
297 audio_frames_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), AudioFrames));
298 bars_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), Bars));
299 beats_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), Beats));
300 ticks_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), Ticks));
301 ms_hours_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), MS_Hours));
302 ms_minutes_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), MS_Minutes));
303 ms_seconds_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), MS_Seconds));
305 hours_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), SMPTE_Hours));
306 minutes_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), SMPTE_Minutes));
307 seconds_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), SMPTE_Seconds));
308 frames_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), SMPTE_Frames));
309 audio_frames_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), AudioFrames));
310 bars_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), Bars));
311 beats_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), Beats));
312 ticks_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), Ticks));
313 ms_hours_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), MS_Hours));
314 ms_minutes_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), MS_Minutes));
315 ms_seconds_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), MS_Seconds));
317 hours_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), SMPTE_Hours));
318 minutes_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), SMPTE_Minutes));
319 seconds_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), SMPTE_Seconds));
320 frames_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), SMPTE_Frames));
321 audio_frames_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), AudioFrames));
322 bars_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), Bars));
323 beats_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), Beats));
324 ticks_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), Ticks));
325 ms_hours_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), MS_Hours));
326 ms_minutes_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), MS_Minutes));
327 ms_seconds_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), MS_Seconds));
329 hours_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), SMPTE_Hours));
330 minutes_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), SMPTE_Minutes));
331 seconds_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), SMPTE_Seconds));
332 frames_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), SMPTE_Frames));
333 audio_frames_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), AudioFrames));
334 bars_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), Bars));
335 beats_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), Beats));
336 ticks_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), Ticks));
337 ms_hours_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), MS_Hours));
338 ms_minutes_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), MS_Minutes));
339 ms_seconds_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), MS_Seconds));
341 hours_ebox.signal_key_press_event().connect (bind (mem_fun(*this, &AudioClock::field_key_press_event), SMPTE_Hours));
342 minutes_ebox.signal_key_press_event().connect (bind (mem_fun(*this, &AudioClock::field_key_press_event), SMPTE_Minutes));
343 seconds_ebox.signal_key_press_event().connect (bind (mem_fun(*this, &AudioClock::field_key_press_event), SMPTE_Seconds));
344 frames_ebox.signal_key_press_event().connect (bind (mem_fun(*this, &AudioClock::field_key_press_event), SMPTE_Frames));
345 audio_frames_ebox.signal_key_press_event().connect (bind (mem_fun(*this, &AudioClock::field_key_press_event), AudioFrames));
346 bars_ebox.signal_key_press_event().connect (bind (mem_fun(*this, &AudioClock::field_key_press_event), Bars));
347 beats_ebox.signal_key_press_event().connect (bind (mem_fun(*this, &AudioClock::field_key_press_event), Beats));
348 ticks_ebox.signal_key_press_event().connect (bind (mem_fun(*this, &AudioClock::field_key_press_event), Ticks));
349 ms_hours_ebox.signal_key_press_event().connect (bind (mem_fun(*this, &AudioClock::field_key_press_event), MS_Hours));
350 ms_minutes_ebox.signal_key_press_event().connect (bind (mem_fun(*this, &AudioClock::field_key_press_event), MS_Minutes));
351 ms_seconds_ebox.signal_key_press_event().connect (bind (mem_fun(*this, &AudioClock::field_key_press_event), MS_Seconds));
353 hours_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), SMPTE_Hours));
354 minutes_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), SMPTE_Minutes));
355 seconds_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), SMPTE_Seconds));
356 frames_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), SMPTE_Frames));
357 audio_frames_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), AudioFrames));
358 bars_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), Bars));
359 beats_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), Beats));
360 ticks_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), Ticks));
361 ms_hours_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), MS_Hours));
362 ms_minutes_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), MS_Minutes));
363 ms_seconds_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), MS_Seconds));
365 hours_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), SMPTE_Hours));
366 minutes_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), SMPTE_Minutes));
367 seconds_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), SMPTE_Seconds));
368 frames_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), SMPTE_Frames));
369 audio_frames_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), AudioFrames));
370 bars_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), Bars));
371 beats_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), Beats));
372 ticks_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), Ticks));
373 ms_hours_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), MS_Hours));
374 ms_minutes_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), MS_Minutes));
375 ms_seconds_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), MS_Seconds));
377 hours_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), SMPTE_Hours));
378 minutes_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), SMPTE_Minutes));
379 seconds_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), SMPTE_Seconds));
380 frames_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), SMPTE_Frames));
381 audio_frames_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), AudioFrames));
382 bars_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), Bars));
383 beats_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), Beats));
384 ticks_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), Ticks));
385 ms_hours_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), MS_Hours));
386 ms_minutes_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), MS_Minutes));
387 ms_seconds_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), MS_Seconds));
389 clock_base.signal_focus_in_event().connect (mem_fun (*this, &AudioClock::drop_focus_handler));
393 AudioClock::drop_focus_handler (GdkEventFocus* ignored)
395 Keyboard::magic_widget_drop_focus ();
400 AudioClock::on_realize ()
404 /* styles are not available until the widgets are bound to a window */
406 set_size_requests ();
410 AudioClock::set (nframes_t when, bool force, nframes_t offset, int which)
413 if ((!force && !is_visible()) || session == 0) {
417 if (when == last_when && !offset && !force) {
421 bool pdelta = Config->get_primary_clock_delta_edit_cursor();
422 bool sdelta = Config->get_secondary_clock_delta_edit_cursor();
424 if (offset && which == 1 && pdelta) {
425 when = (when > offset) ? when - offset : offset - when;
426 } else if (offset && which == 2 && sdelta) {
427 when = (when > offset) ? when - offset : offset - when;
430 if (which == 1 && pdelta && !last_pdelta) {
431 cout << "set_widget_name() called" << endl;
432 set_widget_name("TransportClockDisplayDelta");
434 } else if (which == 1 && !pdelta && last_pdelta) {
435 set_widget_name("TransportClockDisplay");
437 } else if (which == 2 && sdelta && !last_sdelta) {
438 set_widget_name("SecondaryClockDisplayDelta");
440 } else if (which == 2 && !sdelta && last_sdelta) {
441 set_widget_name("SecondaryClockDisplay");
447 set_smpte (when, force);
451 set_bbt (when, force);
455 set_minsec (when, force);
459 set_frames (when, force);
470 AudioClock::smpte_offset_changed ()
477 current = current_duration();
479 current = current_time ();
489 AudioClock::set_frames (nframes_t when, bool force)
492 snprintf (buf, sizeof (buf), "%u", when);
493 audio_frames_label.set_text (buf);
495 if (frames_upper_info_label) {
496 nframes_t rate = session->frame_rate();
498 if (fmod (rate, 1000.0) == 0.000) {
499 sprintf (buf, "%uK", rate/1000);
501 sprintf (buf, "%.3fK", rate/1000.0f);
504 frames_upper_info_label->set_text (buf);
506 float vid_pullup = Config->get_video_pullup();
508 if (vid_pullup == 0.0) {
509 frames_lower_info_label->set_text(_("none"));
511 sprintf (buf, "%-6.4f", vid_pullup);
512 frames_lower_info_label->set_text (buf);
518 AudioClock::set_minsec (nframes_t when, bool force)
527 hrs = (int) floor (left / (session->frame_rate() * 60.0f * 60.0f));
528 left -= (nframes_t) floor (hrs * session->frame_rate() * 60.0f * 60.0f);
529 mins = (int) floor (left / (session->frame_rate() * 60.0f));
530 left -= (nframes_t) floor (mins * session->frame_rate() * 60.0f);
531 secs = left / (float) session->frame_rate();
533 if (force || hrs != ms_last_hrs) {
534 sprintf (buf, "%02d", hrs);
535 ms_hours_label.set_text (buf);
539 if (force || mins != ms_last_mins) {
540 sprintf (buf, "%02d", mins);
541 ms_minutes_label.set_text (buf);
545 if (force || secs != ms_last_secs) {
546 sprintf (buf, "%06.3f", secs);
547 ms_seconds_label.set_text (buf);
553 AudioClock::set_smpte (nframes_t when, bool force)
559 session->smpte_duration (when, smpte);
561 session->smpte_time (when, smpte);
564 if (force || smpte.hours != last_hrs || smpte.negative != last_negative) {
565 if (smpte.negative) {
566 sprintf (buf, "-%02" PRIu32, smpte.hours);
568 sprintf (buf, " %02" PRIu32, smpte.hours);
570 hours_label.set_text (buf);
571 last_hrs = smpte.hours;
572 last_negative = smpte.negative;
575 if (force || smpte.minutes != last_mins) {
576 sprintf (buf, "%02" PRIu32, smpte.minutes);
577 minutes_label.set_text (buf);
578 last_mins = smpte.minutes;
581 if (force || smpte.seconds != last_secs) {
582 sprintf (buf, "%02" PRIu32, smpte.seconds);
583 seconds_label.set_text (buf);
584 last_secs = smpte.seconds;
587 if (force || smpte.frames != last_frames) {
588 sprintf (buf, "%02" PRIu32, smpte.frames);
589 frames_label.set_text (buf);
590 last_frames = smpte.frames;
593 if (smpte_upper_info_label) {
594 double smpte_frames = session->smpte_frames_per_second();
596 if ( fmod(smpte_frames, 1.0) == 0.0) {
597 sprintf (buf, "%u", int (smpte_frames));
599 sprintf (buf, "%.2f", smpte_frames);
602 smpte_upper_info_label->set_text (buf);
604 if ((fabs(smpte_frames - 29.97) < 0.0001) || smpte_frames == 30) {
605 if (session->smpte_drop_frames()) {
608 sprintf (buf, "NDF");
611 // there is no drop frame alternative
615 smpte_lower_info_label->set_text (buf);
620 AudioClock::set_bbt (nframes_t when, bool force)
625 session->tempo_map().bbt_time (when, bbt);
626 sprintf (buf, "%03" PRIu32, bbt.bars);
627 bars_label.set_text (buf);
628 sprintf (buf, "%02" PRIu32, bbt.beats);
629 beats_label.set_text (buf);
630 sprintf (buf, "%04" PRIu32, bbt.ticks);
631 ticks_label.set_text (buf);
633 if (bbt_upper_info_label) {
634 TempoMap::Metric m (session->tempo_map().metric_at (when));
635 sprintf (buf, "%-5.2f", m.tempo().beats_per_minute());
636 bbt_lower_info_label->set_text (buf);
637 sprintf (buf, "%g|%g", m.meter().beats_per_bar(), m.meter().note_divisor());
638 bbt_upper_info_label->set_text (buf);
643 AudioClock::set_session (Session *s)
650 XMLNode* node = session->extra_xml (X_("ClockModes"));
651 AudioClock::Mode amode;
654 if ((prop = node->property (_name)) != 0) {
655 amode = AudioClock::Mode (string_2_enum (prop->value(), amode));
660 set (last_when, true);
669 hours_ebox.grab_focus ();
673 bars_ebox.grab_focus ();
677 ms_hours_ebox.grab_focus ();
681 frames_ebox.grab_focus ();
691 AudioClock::field_key_press_event (GdkEventKey *ev, Field field)
693 /* all key activity is handled on key release */
698 AudioClock::field_key_release_event (GdkEventKey *ev, Field field)
703 bool move_on = false;
707 label = &hours_label;
710 label = &minutes_label;
713 label = &seconds_label;
716 label = &frames_label;
720 label = &audio_frames_label;
724 label = &ms_hours_label;
727 label = &ms_minutes_label;
730 label = &ms_seconds_label;
737 label = &beats_label;
740 label = &ticks_label;
746 switch (ev->keyval) {
790 if (_mode == MinSec && field == MS_Seconds) {
804 clock_base.grab_focus ();
813 if (key_entry_state == 0) {
815 /* initialize with a fresh new string */
817 if (field != AudioFrames) {
818 for (uint32_t xn = 0; xn < field_length[field] - 1; ++xn) {
827 string existing = label->get_text();
828 if (existing.length() >= field_length[field]) {
829 new_text = existing.substr (1, field_length[field] - 1);
831 new_text = existing.substr (0, field_length[field] - 1);
835 new_text += new_char;
836 label->set_text (new_text);
840 if (key_entry_state == field_length[field]) {
846 if (key_entry_state) {
853 // Check SMPTE fields for sanity (may also adjust fields)
854 smpte_sanitize_display();
859 // Bars should never be, unless this clock is for a duration
860 if (atoi(bars_label.get_text()) == 0 && !is_duration) {
861 bars_label.set_text("001");
863 // beats should never be 0, unless this clock is for a duration
864 if (atoi(beats_label.get_text()) == 0 && !is_duration) {
865 beats_label.set_text("01");
872 ValueChanged(); /* EMIT_SIGNAL */
875 /* move on to the next field.
883 minutes_ebox.grab_focus ();
886 seconds_ebox.grab_focus ();
889 frames_ebox.grab_focus ();
892 clock_base.grab_focus ();
897 clock_base.grab_focus ();
903 ms_minutes_ebox.grab_focus ();
906 ms_seconds_ebox.grab_focus ();
909 clock_base.grab_focus ();
915 beats_ebox.grab_focus ();
918 ticks_ebox.grab_focus ();
921 clock_base.grab_focus ();
934 AudioClock::field_focus_in_event (GdkEventFocus *ev, Field field)
938 Keyboard::magic_widget_grab_focus ();
942 hours_ebox.set_flags (Gtk::HAS_FOCUS);
943 hours_ebox.set_state (Gtk::STATE_ACTIVE);
946 minutes_ebox.set_flags (Gtk::HAS_FOCUS);
947 minutes_ebox.set_state (Gtk::STATE_ACTIVE);
950 seconds_ebox.set_flags (Gtk::HAS_FOCUS);
951 seconds_ebox.set_state (Gtk::STATE_ACTIVE);
954 frames_ebox.set_flags (Gtk::HAS_FOCUS);
955 frames_ebox.set_state (Gtk::STATE_ACTIVE);
959 audio_frames_ebox.set_flags (Gtk::HAS_FOCUS);
960 audio_frames_ebox.set_state (Gtk::STATE_ACTIVE);
964 ms_hours_ebox.set_flags (Gtk::HAS_FOCUS);
965 ms_hours_ebox.set_state (Gtk::STATE_ACTIVE);
968 ms_minutes_ebox.set_flags (Gtk::HAS_FOCUS);
969 ms_minutes_ebox.set_state (Gtk::STATE_ACTIVE);
972 ms_seconds_ebox.set_flags (Gtk::HAS_FOCUS);
973 ms_seconds_ebox.set_state (Gtk::STATE_ACTIVE);
976 bars_ebox.set_flags (Gtk::HAS_FOCUS);
977 bars_ebox.set_state (Gtk::STATE_ACTIVE);
980 beats_ebox.set_flags (Gtk::HAS_FOCUS);
981 beats_ebox.set_state (Gtk::STATE_ACTIVE);
984 ticks_ebox.set_flags (Gtk::HAS_FOCUS);
985 ticks_ebox.set_state (Gtk::STATE_ACTIVE);
993 AudioClock::field_focus_out_event (GdkEventFocus *ev, Field field)
998 hours_ebox.unset_flags (Gtk::HAS_FOCUS);
999 hours_ebox.set_state (Gtk::STATE_NORMAL);
1002 minutes_ebox.unset_flags (Gtk::HAS_FOCUS);
1003 minutes_ebox.set_state (Gtk::STATE_NORMAL);
1006 seconds_ebox.unset_flags (Gtk::HAS_FOCUS);
1007 seconds_ebox.set_state (Gtk::STATE_NORMAL);
1010 frames_ebox.unset_flags (Gtk::HAS_FOCUS);
1011 frames_ebox.set_state (Gtk::STATE_NORMAL);
1015 audio_frames_ebox.unset_flags (Gtk::HAS_FOCUS);
1016 audio_frames_ebox.set_state (Gtk::STATE_NORMAL);
1020 ms_hours_ebox.unset_flags (Gtk::HAS_FOCUS);
1021 ms_hours_ebox.set_state (Gtk::STATE_NORMAL);
1024 ms_minutes_ebox.unset_flags (Gtk::HAS_FOCUS);
1025 ms_minutes_ebox.set_state (Gtk::STATE_NORMAL);
1028 ms_seconds_ebox.unset_flags (Gtk::HAS_FOCUS);
1029 ms_seconds_ebox.set_state (Gtk::STATE_NORMAL);
1033 bars_ebox.unset_flags (Gtk::HAS_FOCUS);
1034 bars_ebox.set_state (Gtk::STATE_NORMAL);
1037 beats_ebox.unset_flags (Gtk::HAS_FOCUS);
1038 beats_ebox.set_state (Gtk::STATE_NORMAL);
1041 ticks_ebox.unset_flags (Gtk::HAS_FOCUS);
1042 ticks_ebox.set_state (Gtk::STATE_NORMAL);
1046 Keyboard::magic_widget_drop_focus ();
1052 AudioClock::field_button_release_event (GdkEventButton *ev, Field field)
1055 gdk_pointer_ungrab (GDK_CURRENT_TIME);
1057 if (ev->y > drag_start_y+1 || ev->y < drag_start_y-1 || Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)){
1058 // we actually dragged so return without setting editing focus, or we shift clicked
1064 if (ops_menu == 0) {
1067 ops_menu->popup (1, ev->time);
1071 if (Keyboard::is_context_menu_event (ev)) {
1072 if (ops_menu == 0) {
1075 ops_menu->popup (1, ev->time);
1079 switch (ev->button) {
1083 hours_ebox.grab_focus();
1086 minutes_ebox.grab_focus();
1089 seconds_ebox.grab_focus();
1092 frames_ebox.grab_focus();
1096 audio_frames_ebox.grab_focus();
1100 ms_hours_ebox.grab_focus();
1103 ms_minutes_ebox.grab_focus();
1106 ms_seconds_ebox.grab_focus();
1110 bars_ebox.grab_focus ();
1113 beats_ebox.grab_focus ();
1116 ticks_ebox.grab_focus ();
1129 AudioClock::field_button_press_event (GdkEventButton *ev, Field field)
1131 if (session == 0) return false;
1133 nframes_t frames = 0;
1135 switch (ev->button) {
1137 if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
1139 ValueChanged (); /* EMIT_SIGNAL */
1142 /* make absolutely sure that the pointer is grabbed */
1143 gdk_pointer_grab(ev->window,false ,
1144 GdkEventMask( Gdk::POINTER_MOTION_MASK | Gdk::BUTTON_PRESS_MASK |Gdk::BUTTON_RELEASE_MASK),
1145 NULL,NULL,ev->time);
1148 drag_start_y = ev->y;
1153 if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
1155 ValueChanged (); /* EMIT_SIGNAL */
1160 /* used for context sensitive menu */
1173 AudioClock::field_button_scroll_event (GdkEventScroll *ev, Field field)
1179 nframes_t frames = 0;
1181 switch (ev->direction) {
1184 frames = get_frames (field);
1186 if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
1189 set (current_time() + frames, true);
1190 ValueChanged (); /* EMIT_SIGNAL */
1194 case GDK_SCROLL_DOWN:
1195 frames = get_frames (field);
1197 if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
1201 if ((double)current_time() - (double)frames < 0.0) {
1204 set (current_time() - frames, true);
1207 ValueChanged (); /* EMIT_SIGNAL */
1220 AudioClock::field_motion_notify_event (GdkEventMotion *ev, Field field)
1222 if (session == 0 || !dragging) {
1226 float pixel_frame_scale_factor = 0.2f;
1229 if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
1230 pixel_frame_scale_factor = 0.1f;
1234 if (Keyboard::modifier_state_contains (ev->state,
1235 Keyboard::PrimaryModifier|Keyboard::SecondaryModifier)) {
1237 pixel_frame_scale_factor = 0.025f;
1240 double y_delta = ev->y - drag_y;
1242 drag_accum += y_delta*pixel_frame_scale_factor;
1246 if (trunc(drag_accum) != 0) {
1251 dir = (drag_accum < 0 ? 1:-1);
1252 pos = current_time();
1253 frames = get_frames (field,pos,dir);
1255 if (frames != 0 && frames * drag_accum < current_time()) {
1257 set ((nframes_t) floor (pos - drag_accum * frames), false); // minus because up is negative in computer-land
1265 ValueChanged(); /* EMIT_SIGNAL */
1274 AudioClock::get_frames (Field field,nframes_t pos,int dir)
1277 nframes_t frames = 0;
1281 frames = (nframes_t) floor (3600.0 * session->frame_rate());
1284 frames = (nframes_t) floor (60.0 * session->frame_rate());
1287 frames = session->frame_rate();
1290 frames = (nframes_t) floor (session->frame_rate() / session->smpte_frames_per_second());
1298 frames = (nframes_t) floor (3600.0 * session->frame_rate());
1301 frames = (nframes_t) floor (60.0 * session->frame_rate());
1304 frames = session->frame_rate();
1311 frames = session->tempo_map().bbt_duration_at(pos,bbt,dir);
1317 frames = session->tempo_map().bbt_duration_at(pos,bbt,dir);
1323 frames = session->tempo_map().bbt_duration_at(pos,bbt,dir);
1331 AudioClock::current_time (nframes_t pos) const
1337 ret = smpte_frame_from_display ();
1340 ret = bbt_frame_from_display (pos);
1344 ret = minsec_frame_from_display ();
1348 ret = audio_frame_from_display ();
1359 AudioClock::current_duration (nframes_t pos) const
1365 ret = smpte_frame_from_display ();
1368 ret = bbt_frame_duration_from_display (pos);
1372 ret = minsec_frame_from_display ();
1376 ret = audio_frame_from_display ();
1387 AudioClock::smpte_sanitize_display()
1389 // Check SMPTE fields for sanity, possibly adjusting values
1390 if (atoi(minutes_label.get_text()) > 59) {
1391 minutes_label.set_text("59");
1394 if (atoi(seconds_label.get_text()) > 59) {
1395 seconds_label.set_text("59");
1398 switch ((long)rint(session->smpte_frames_per_second())) {
1400 if (atoi(frames_label.get_text()) > 23) {
1401 frames_label.set_text("23");
1405 if (atoi(frames_label.get_text()) > 24) {
1406 frames_label.set_text("24");
1410 if (atoi(frames_label.get_text()) > 29) {
1411 frames_label.set_text("29");
1418 if (session->smpte_drop_frames()) {
1419 if ((atoi(minutes_label.get_text()) % 10) && (atoi(seconds_label.get_text()) == 0) && (atoi(frames_label.get_text()) < 2)) {
1420 frames_label.set_text("02");
1426 AudioClock::smpte_frame_from_display () const
1435 smpte.hours = atoi (hours_label.get_text());
1436 smpte.minutes = atoi (minutes_label.get_text());
1437 smpte.seconds = atoi (seconds_label.get_text());
1438 smpte.frames = atoi (frames_label.get_text());
1439 smpte.rate = session->smpte_frames_per_second();
1440 smpte.drop= session->smpte_drop_frames();
1442 session->smpte_to_sample( smpte, sample, false /* use_offset */, false /* use_subframes */ );
1446 #define SMPTE_SAMPLE_TEST_1
1447 #define SMPTE_SAMPLE_TEST_2
1448 #define SMPTE_SAMPLE_TEST_3
1449 #define SMPTE_SAMPLE_TEST_4
1450 #define SMPTE_SAMPLE_TEST_5
1451 #define SMPTE_SAMPLE_TEST_6
1452 #define SMPTE_SAMPLE_TEST_7
1454 // Testcode for smpte<->sample conversions (P.S.)
1457 nframes_t oldsample = 0;
1459 nframes_t sample_increment;
1461 sample_increment = (long)rint(session->frame_rate() / session->smpte_frames_per_second);
1463 #ifdef SMPTE_SAMPLE_TEST_1
1464 // Test 1: use_offset = false, use_subframes = false
1465 cout << "use_offset = false, use_subframes = false" << endl;
1466 for (int i = 0; i < 108003; i++) {
1467 session->smpte_to_sample( smpte1, sample1, false /* use_offset */, false /* use_subframes */ );
1468 session->sample_to_smpte( sample1, smpte2, false /* use_offset */, false /* use_subframes */ );
1470 if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
1471 cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1472 cout << "smpte1: " << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1473 cout << "sample: " << sample1 << endl;
1474 cout << "sample: " << sample1 << " -> ";
1475 cout << "smpte2: " << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1479 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1480 cout << "ERROR: smpte2 not equal smpte1" << endl;
1481 cout << "smpte1: " << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1482 cout << "sample: " << sample1 << endl;
1483 cout << "sample: " << sample1 << " -> ";
1484 cout << "smpte2: " << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1487 oldsample = sample1;
1488 session->smpte_increment( smpte1 );
1491 cout << "sample_increment: " << sample_increment << endl;
1492 cout << "sample: " << sample1 << " -> ";
1493 cout << "smpte: " << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1496 #ifdef SMPTE_SAMPLE_TEST_2
1497 // Test 2: use_offset = true, use_subframes = false
1498 cout << "use_offset = true, use_subframes = false" << endl;
1504 smpte1.subframes = 0;
1505 sample1 = oldsample = 0;
1507 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1508 cout << "Starting at sample: " << sample1 << " -> ";
1509 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1511 for (int i = 0; i < 108003; i++) {
1512 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1513 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1515 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1516 // cout << "sample: " << sample1 << endl;
1517 // cout << "sample: " << sample1 << " -> ";
1518 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1520 if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
1521 cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1522 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1523 cout << "sample: " << sample1 << endl;
1524 cout << "sample: " << sample1 << " -> ";
1525 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1529 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1530 cout << "ERROR: smpte2 not equal smpte1" << endl;
1531 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1532 cout << "sample: " << sample1 << endl;
1533 cout << "sample: " << sample1 << " -> ";
1534 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1537 oldsample = sample1;
1538 session->smpte_increment( smpte1 );
1541 cout << "sample_increment: " << sample_increment << endl;
1542 cout << "sample: " << sample1 << " -> ";
1543 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1546 #ifdef SMPTE_SAMPLE_TEST_3
1547 // Test 3: use_offset = true, use_subframes = false, decrement
1548 cout << "use_offset = true, use_subframes = false, decrement" << endl;
1550 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1551 cout << "Starting at sample: " << sample1 << " -> ";
1552 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1554 for (int i = 0; i < 108003; i++) {
1555 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1556 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1558 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1559 // cout << "sample: " << sample1 << endl;
1560 // cout << "sample: " << sample1 << " -> ";
1561 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1563 if ((i > 0) && ( ((oldsample - sample1) != sample_increment) && ((oldsample - sample1) != (sample_increment + 1)) && ((oldsample - sample1) != (sample_increment - 1)))) {
1564 cout << "ERROR: sample increment not right: " << (oldsample - sample1) << " != " << sample_increment << endl;
1565 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1566 cout << "sample: " << sample1 << endl;
1567 cout << "sample: " << sample1 << " -> ";
1568 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1572 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1573 cout << "ERROR: smpte2 not equal smpte1" << endl;
1574 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1575 cout << "sample: " << sample1 << endl;
1576 cout << "sample: " << sample1 << " -> ";
1577 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1580 oldsample = sample1;
1581 session->smpte_decrement( smpte1 );
1584 cout << "sample_decrement: " << sample_increment << endl;
1585 cout << "sample: " << sample1 << " -> ";
1586 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1590 #ifdef SMPTE_SAMPLE_TEST_4
1591 // Test 4: use_offset = true, use_subframes = true
1592 cout << "use_offset = true, use_subframes = true" << endl;
1594 for (long sub = 5; sub < 80; sub += 5) {
1599 smpte1.subframes = 0;
1600 sample1 = oldsample = (sample_increment * sub) / 80;
1602 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, true /* use_subframes */ );
1604 cout << "starting at sample: " << sample1 << " -> ";
1605 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1607 for (int i = 0; i < 108003; i++) {
1608 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, true /* use_subframes */ );
1609 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, true /* use_subframes */ );
1611 if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
1612 cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1613 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1614 cout << "sample: " << sample1 << endl;
1615 cout << "sample: " << sample1 << " -> ";
1616 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1620 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames || smpte2.subframes != smpte1.subframes) {
1621 cout << "ERROR: smpte2 not equal smpte1" << endl;
1622 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1623 cout << "sample: " << sample1 << endl;
1624 cout << "sample: " << sample1 << " -> ";
1625 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1628 oldsample = sample1;
1629 session->smpte_increment( smpte1 );
1632 cout << "sample_increment: " << sample_increment << endl;
1633 cout << "sample: " << sample1 << " -> ";
1634 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1636 for (int i = 0; i < 108003; i++) {
1637 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, true /* use_subframes */ );
1638 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, true /* use_subframes */ );
1640 if ((i > 0) && ( ((oldsample - sample1) != sample_increment) && ((oldsample - sample1) != (sample_increment + 1)) && ((oldsample - sample1) != (sample_increment - 1)))) {
1641 cout << "ERROR: sample increment not right: " << (oldsample - sample1) << " != " << sample_increment << endl;
1642 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1643 cout << "sample: " << sample1 << endl;
1644 cout << "sample: " << sample1 << " -> ";
1645 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1649 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames || smpte2.subframes != smpte1.subframes) {
1650 cout << "ERROR: smpte2 not equal smpte1" << endl;
1651 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1652 cout << "sample: " << sample1 << endl;
1653 cout << "sample: " << sample1 << " -> ";
1654 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1657 oldsample = sample1;
1658 session->smpte_decrement( smpte1 );
1661 cout << "sample_decrement: " << sample_increment << endl;
1662 cout << "sample: " << sample1 << " -> ";
1663 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1668 #ifdef SMPTE_SAMPLE_TEST_5
1669 // Test 5: use_offset = true, use_subframes = false, increment seconds
1670 cout << "use_offset = true, use_subframes = false, increment seconds" << endl;
1676 smpte1.subframes = 0;
1677 sample1 = oldsample = 0;
1678 sample_increment = session->frame_rate();
1680 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1681 cout << "Starting at sample: " << sample1 << " -> ";
1682 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1684 for (int i = 0; i < 3600; i++) {
1685 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1686 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1688 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1689 // cout << "sample: " << sample1 << endl;
1690 // cout << "sample: " << sample1 << " -> ";
1691 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1693 // if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1695 // cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1699 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1700 cout << "ERROR: smpte2 not equal smpte1" << endl;
1701 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1702 cout << "sample: " << sample1 << endl;
1703 cout << "sample: " << sample1 << " -> ";
1704 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1707 oldsample = sample1;
1708 session->smpte_increment_seconds( smpte1 );
1711 cout << "sample_increment: " << sample_increment << endl;
1712 cout << "sample: " << sample1 << " -> ";
1713 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1717 #ifdef SMPTE_SAMPLE_TEST_6
1718 // Test 6: use_offset = true, use_subframes = false, increment minutes
1719 cout << "use_offset = true, use_subframes = false, increment minutes" << endl;
1725 smpte1.subframes = 0;
1726 sample1 = oldsample = 0;
1727 sample_increment = session->frame_rate() * 60;
1729 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1730 cout << "Starting at sample: " << sample1 << " -> ";
1731 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1733 for (int i = 0; i < 60; i++) {
1734 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1735 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1737 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1738 // cout << "sample: " << sample1 << endl;
1739 // cout << "sample: " << sample1 << " -> ";
1740 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1742 // if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1744 // cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1748 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1749 cout << "ERROR: smpte2 not equal smpte1" << endl;
1750 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1751 cout << "sample: " << sample1 << endl;
1752 cout << "sample: " << sample1 << " -> ";
1753 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1756 oldsample = sample1;
1757 session->smpte_increment_minutes( smpte1 );
1760 cout << "sample_increment: " << sample_increment << endl;
1761 cout << "sample: " << sample1 << " -> ";
1762 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1765 #ifdef SMPTE_SAMPLE_TEST_7
1766 // Test 7: use_offset = true, use_subframes = false, increment hours
1767 cout << "use_offset = true, use_subframes = false, increment hours" << endl;
1773 smpte1.subframes = 0;
1774 sample1 = oldsample = 0;
1775 sample_increment = session->frame_rate() * 60 * 60;
1777 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1778 cout << "Starting at sample: " << sample1 << " -> ";
1779 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1781 for (int i = 0; i < 10; i++) {
1782 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1783 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1785 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1786 // cout << "sample: " << sample1 << endl;
1787 // cout << "sample: " << sample1 << " -> ";
1788 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1790 // if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1792 // cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1796 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1797 cout << "ERROR: smpte2 not equal smpte1" << endl;
1798 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1799 cout << "sample: " << sample1 << endl;
1800 cout << "sample: " << sample1 << " -> ";
1801 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1804 oldsample = sample1;
1805 session->smpte_increment_hours( smpte1 );
1808 cout << "sample_increment: " << sample_increment << endl;
1809 cout << "sample: " << sample1 << " -> ";
1810 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1819 AudioClock::minsec_frame_from_display () const
1825 int hrs = atoi (ms_hours_label.get_text());
1826 int mins = atoi (ms_minutes_label.get_text());
1827 float secs = atof (ms_seconds_label.get_text());
1829 nframes_t sr = session->frame_rate();
1831 return (nframes_t) floor ((hrs * 60.0f * 60.0f * sr) + (mins * 60.0f * sr) + (secs * sr));
1835 AudioClock::bbt_frame_from_display (nframes_t pos) const
1838 error << "AudioClock::current_time() called with BBT mode but without session!" << endmsg;
1843 any.type = AnyTime::BBT;
1845 any.bbt.bars = atoi (bars_label.get_text());
1846 any.bbt.beats = atoi (beats_label.get_text());
1847 any.bbt.ticks = atoi (ticks_label.get_text());
1849 nframes_t ret = session->convert_to_frames_at (pos, any);
1856 AudioClock::bbt_frame_duration_from_display (nframes_t pos) const
1859 error << "AudioClock::current_time() called with BBT mode but without session!" << endmsg;
1866 bbt.bars = atoi (bars_label.get_text());
1867 bbt.beats = atoi (beats_label.get_text());
1868 bbt.ticks = atoi (ticks_label.get_text());
1870 return session->tempo_map().bbt_duration_at(pos,bbt,1);
1874 AudioClock::audio_frame_from_display () const
1876 return (nframes_t) atoi (audio_frames_label.get_text());
1880 AudioClock::build_ops_menu ()
1882 using namespace Menu_Helpers;
1883 ops_menu = new Menu;
1884 MenuList& ops_items = ops_menu->items();
1885 ops_menu->set_name ("ArdourContextMenu");
1887 if (!Profile->get_sae()) {
1888 ops_items.push_back (MenuElem (_("Timecode"), bind (mem_fun(*this, &AudioClock::set_mode), SMPTE)));
1890 ops_items.push_back (MenuElem (_("Bars:Beats"), bind (mem_fun(*this, &AudioClock::set_mode), BBT)));
1891 ops_items.push_back (MenuElem (_("Minutes:Seconds"), bind (mem_fun(*this, &AudioClock::set_mode), MinSec)));
1892 ops_items.push_back (MenuElem (_("Samples"), bind (mem_fun(*this, &AudioClock::set_mode), Frames)));
1893 ops_items.push_back (MenuElem (_("Off"), bind (mem_fun(*this, &AudioClock::set_mode), Off)));
1897 AudioClock::set_mode (Mode m)
1899 /* slightly tricky: this is called from within the ARDOUR_UI
1900 constructor by some of its clock members. at that time
1901 the instance pointer is unset, so we have to be careful.
1902 the main idea is to drop keyboard focus in case we had
1903 started editing the clock and then we switch clock mode.
1906 clock_base.grab_focus ();
1912 clock_base.remove ();
1918 clock_base.add (smpte_packer_hbox);
1922 clock_base.add (bbt_packer_hbox);
1926 clock_base.add (minsec_packer_hbox);
1930 clock_base.add (frames_packer_hbox);
1934 clock_base.add (off_hbox);
1938 set_size_requests ();
1940 set (last_when, true);
1941 clock_base.show_all ();
1942 key_entry_state = 0;
1944 if (!is_transient) {
1945 ModeChanged (); /* EMIT SIGNAL */
1950 AudioClock::set_size_requests ()
1952 /* note that in some fonts, "88" is narrower than "00", hence the 2 pixel padding */
1956 Gtkmm2ext::set_size_request_to_display_given_text (hours_label, "-00", 5, 5);
1957 Gtkmm2ext::set_size_request_to_display_given_text (minutes_label, "00", 5, 5);
1958 Gtkmm2ext::set_size_request_to_display_given_text (seconds_label, "00", 5, 5);
1959 Gtkmm2ext::set_size_request_to_display_given_text (frames_label, "00", 5, 5);
1963 Gtkmm2ext::set_size_request_to_display_given_text (bars_label, "-000", 5, 5);
1964 Gtkmm2ext::set_size_request_to_display_given_text (beats_label, "00", 5, 5);
1965 Gtkmm2ext::set_size_request_to_display_given_text (ticks_label, "0000", 5, 5);
1969 Gtkmm2ext::set_size_request_to_display_given_text (ms_hours_label, "00", 5, 5);
1970 Gtkmm2ext::set_size_request_to_display_given_text (ms_minutes_label, "00", 5, 5);
1971 Gtkmm2ext::set_size_request_to_display_given_text (ms_seconds_label, "00.000", 5, 5);
1975 Gtkmm2ext::set_size_request_to_display_given_text (audio_frames_label, "0000000000", 5, 5);
1979 Gtkmm2ext::set_size_request_to_display_given_text (off_hbox, "00000", 5, 5);