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, char 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 == 'p' && pdelta) {
425 when = (when > offset) ? when - offset : offset - when;
426 } else if (offset && which == 's' && sdelta) {
427 when = (when > offset) ? when - offset : offset - when;
430 if (which == 'p' && pdelta && !last_pdelta) {
431 set_widget_name("TransportClockDisplayDelta");
433 } else if (which == 'p' && !pdelta && last_pdelta) {
434 set_widget_name("TransportClockDisplay");
436 } else if (which == 's' && sdelta && !last_sdelta) {
437 set_widget_name("SecondaryClockDisplayDelta");
439 } else if (which == 's' && !sdelta && last_sdelta) {
440 set_widget_name("SecondaryClockDisplay");
446 set_smpte (when, force);
450 set_bbt (when, force);
454 set_minsec (when, force);
458 set_frames (when, force);
469 AudioClock::smpte_offset_changed ()
476 current = current_duration();
478 current = current_time ();
488 AudioClock::set_frames (nframes_t when, bool force)
491 snprintf (buf, sizeof (buf), "%u", when);
492 audio_frames_label.set_text (buf);
494 if (frames_upper_info_label) {
495 nframes_t rate = session->frame_rate();
497 if (fmod (rate, 1000.0) == 0.000) {
498 sprintf (buf, "%uK", rate/1000);
500 sprintf (buf, "%.3fK", rate/1000.0f);
503 frames_upper_info_label->set_text (buf);
505 float vid_pullup = Config->get_video_pullup();
507 if (vid_pullup == 0.0) {
508 frames_lower_info_label->set_text(_("none"));
510 sprintf (buf, "%-6.4f", vid_pullup);
511 frames_lower_info_label->set_text (buf);
517 AudioClock::set_minsec (nframes_t when, bool force)
526 hrs = (int) floor (left / (session->frame_rate() * 60.0f * 60.0f));
527 left -= (nframes_t) floor (hrs * session->frame_rate() * 60.0f * 60.0f);
528 mins = (int) floor (left / (session->frame_rate() * 60.0f));
529 left -= (nframes_t) floor (mins * session->frame_rate() * 60.0f);
530 secs = left / (float) session->frame_rate();
532 if (force || hrs != ms_last_hrs) {
533 sprintf (buf, "%02d", hrs);
534 ms_hours_label.set_text (buf);
538 if (force || mins != ms_last_mins) {
539 sprintf (buf, "%02d", mins);
540 ms_minutes_label.set_text (buf);
544 if (force || secs != ms_last_secs) {
545 sprintf (buf, "%06.3f", secs);
546 ms_seconds_label.set_text (buf);
552 AudioClock::set_smpte (nframes_t when, bool force)
558 session->smpte_duration (when, smpte);
560 session->smpte_time (when, smpte);
563 if (force || smpte.hours != last_hrs || smpte.negative != last_negative) {
564 if (smpte.negative) {
565 sprintf (buf, "-%02" PRIu32, smpte.hours);
567 sprintf (buf, " %02" PRIu32, smpte.hours);
569 hours_label.set_text (buf);
570 last_hrs = smpte.hours;
571 last_negative = smpte.negative;
574 if (force || smpte.minutes != last_mins) {
575 sprintf (buf, "%02" PRIu32, smpte.minutes);
576 minutes_label.set_text (buf);
577 last_mins = smpte.minutes;
580 if (force || smpte.seconds != last_secs) {
581 sprintf (buf, "%02" PRIu32, smpte.seconds);
582 seconds_label.set_text (buf);
583 last_secs = smpte.seconds;
586 if (force || smpte.frames != last_frames) {
587 sprintf (buf, "%02" PRIu32, smpte.frames);
588 frames_label.set_text (buf);
589 last_frames = smpte.frames;
592 if (smpte_upper_info_label) {
593 double smpte_frames = session->smpte_frames_per_second();
595 if ( fmod(smpte_frames, 1.0) == 0.0) {
596 sprintf (buf, "%u", int (smpte_frames));
598 sprintf (buf, "%.2f", smpte_frames);
601 smpte_upper_info_label->set_text (buf);
603 if ((fabs(smpte_frames - 29.97) < 0.0001) || smpte_frames == 30) {
604 if (session->smpte_drop_frames()) {
607 sprintf (buf, "NDF");
610 // there is no drop frame alternative
614 smpte_lower_info_label->set_text (buf);
619 AudioClock::set_bbt (nframes_t when, bool force)
624 session->tempo_map().bbt_time (when, bbt);
625 sprintf (buf, "%03" PRIu32, bbt.bars);
626 bars_label.set_text (buf);
627 sprintf (buf, "%02" PRIu32, bbt.beats);
628 beats_label.set_text (buf);
629 sprintf (buf, "%04" PRIu32, bbt.ticks);
630 ticks_label.set_text (buf);
632 if (bbt_upper_info_label) {
633 TempoMap::Metric m (session->tempo_map().metric_at (when));
634 sprintf (buf, "%-5.2f", m.tempo().beats_per_minute());
635 bbt_lower_info_label->set_text (buf);
636 sprintf (buf, "%g|%g", m.meter().beats_per_bar(), m.meter().note_divisor());
637 bbt_upper_info_label->set_text (buf);
642 AudioClock::set_session (Session *s)
649 XMLNode* node = session->extra_xml (X_("ClockModes"));
650 AudioClock::Mode amode;
653 if ((prop = node->property (_name)) != 0) {
654 amode = AudioClock::Mode (string_2_enum (prop->value(), amode));
659 set (last_when, true);
668 hours_ebox.grab_focus ();
672 bars_ebox.grab_focus ();
676 ms_hours_ebox.grab_focus ();
680 frames_ebox.grab_focus ();
690 AudioClock::field_key_press_event (GdkEventKey *ev, Field field)
692 /* all key activity is handled on key release */
697 AudioClock::field_key_release_event (GdkEventKey *ev, Field field)
702 bool move_on = false;
706 label = &hours_label;
709 label = &minutes_label;
712 label = &seconds_label;
715 label = &frames_label;
719 label = &audio_frames_label;
723 label = &ms_hours_label;
726 label = &ms_minutes_label;
729 label = &ms_seconds_label;
736 label = &beats_label;
739 label = &ticks_label;
745 switch (ev->keyval) {
789 if (_mode == MinSec && field == MS_Seconds) {
803 clock_base.grab_focus ();
812 if (key_entry_state == 0) {
814 /* initialize with a fresh new string */
816 if (field != AudioFrames) {
817 for (uint32_t xn = 0; xn < field_length[field] - 1; ++xn) {
826 string existing = label->get_text();
827 if (existing.length() >= field_length[field]) {
828 new_text = existing.substr (1, field_length[field] - 1);
830 new_text = existing.substr (0, field_length[field] - 1);
834 new_text += new_char;
835 label->set_text (new_text);
839 if (key_entry_state == field_length[field]) {
845 if (key_entry_state) {
852 // Check SMPTE fields for sanity (may also adjust fields)
853 smpte_sanitize_display();
858 // Bars should never be, unless this clock is for a duration
859 if (atoi(bars_label.get_text()) == 0 && !is_duration) {
860 bars_label.set_text("001");
862 // beats should never be 0, unless this clock is for a duration
863 if (atoi(beats_label.get_text()) == 0 && !is_duration) {
864 beats_label.set_text("01");
871 ValueChanged(); /* EMIT_SIGNAL */
874 /* move on to the next field.
882 minutes_ebox.grab_focus ();
885 seconds_ebox.grab_focus ();
888 frames_ebox.grab_focus ();
891 clock_base.grab_focus ();
896 clock_base.grab_focus ();
902 ms_minutes_ebox.grab_focus ();
905 ms_seconds_ebox.grab_focus ();
908 clock_base.grab_focus ();
914 beats_ebox.grab_focus ();
917 ticks_ebox.grab_focus ();
920 clock_base.grab_focus ();
933 AudioClock::field_focus_in_event (GdkEventFocus *ev, Field field)
937 Keyboard::magic_widget_grab_focus ();
941 hours_ebox.set_flags (Gtk::HAS_FOCUS);
942 hours_ebox.set_state (Gtk::STATE_ACTIVE);
945 minutes_ebox.set_flags (Gtk::HAS_FOCUS);
946 minutes_ebox.set_state (Gtk::STATE_ACTIVE);
949 seconds_ebox.set_flags (Gtk::HAS_FOCUS);
950 seconds_ebox.set_state (Gtk::STATE_ACTIVE);
953 frames_ebox.set_flags (Gtk::HAS_FOCUS);
954 frames_ebox.set_state (Gtk::STATE_ACTIVE);
958 audio_frames_ebox.set_flags (Gtk::HAS_FOCUS);
959 audio_frames_ebox.set_state (Gtk::STATE_ACTIVE);
963 ms_hours_ebox.set_flags (Gtk::HAS_FOCUS);
964 ms_hours_ebox.set_state (Gtk::STATE_ACTIVE);
967 ms_minutes_ebox.set_flags (Gtk::HAS_FOCUS);
968 ms_minutes_ebox.set_state (Gtk::STATE_ACTIVE);
971 ms_seconds_ebox.set_flags (Gtk::HAS_FOCUS);
972 ms_seconds_ebox.set_state (Gtk::STATE_ACTIVE);
975 bars_ebox.set_flags (Gtk::HAS_FOCUS);
976 bars_ebox.set_state (Gtk::STATE_ACTIVE);
979 beats_ebox.set_flags (Gtk::HAS_FOCUS);
980 beats_ebox.set_state (Gtk::STATE_ACTIVE);
983 ticks_ebox.set_flags (Gtk::HAS_FOCUS);
984 ticks_ebox.set_state (Gtk::STATE_ACTIVE);
992 AudioClock::field_focus_out_event (GdkEventFocus *ev, Field field)
997 hours_ebox.unset_flags (Gtk::HAS_FOCUS);
998 hours_ebox.set_state (Gtk::STATE_NORMAL);
1001 minutes_ebox.unset_flags (Gtk::HAS_FOCUS);
1002 minutes_ebox.set_state (Gtk::STATE_NORMAL);
1005 seconds_ebox.unset_flags (Gtk::HAS_FOCUS);
1006 seconds_ebox.set_state (Gtk::STATE_NORMAL);
1009 frames_ebox.unset_flags (Gtk::HAS_FOCUS);
1010 frames_ebox.set_state (Gtk::STATE_NORMAL);
1014 audio_frames_ebox.unset_flags (Gtk::HAS_FOCUS);
1015 audio_frames_ebox.set_state (Gtk::STATE_NORMAL);
1019 ms_hours_ebox.unset_flags (Gtk::HAS_FOCUS);
1020 ms_hours_ebox.set_state (Gtk::STATE_NORMAL);
1023 ms_minutes_ebox.unset_flags (Gtk::HAS_FOCUS);
1024 ms_minutes_ebox.set_state (Gtk::STATE_NORMAL);
1027 ms_seconds_ebox.unset_flags (Gtk::HAS_FOCUS);
1028 ms_seconds_ebox.set_state (Gtk::STATE_NORMAL);
1032 bars_ebox.unset_flags (Gtk::HAS_FOCUS);
1033 bars_ebox.set_state (Gtk::STATE_NORMAL);
1036 beats_ebox.unset_flags (Gtk::HAS_FOCUS);
1037 beats_ebox.set_state (Gtk::STATE_NORMAL);
1040 ticks_ebox.unset_flags (Gtk::HAS_FOCUS);
1041 ticks_ebox.set_state (Gtk::STATE_NORMAL);
1045 Keyboard::magic_widget_drop_focus ();
1051 AudioClock::field_button_release_event (GdkEventButton *ev, Field field)
1054 gdk_pointer_ungrab (GDK_CURRENT_TIME);
1056 if (ev->y > drag_start_y+1 || ev->y < drag_start_y-1 || Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)){
1057 // we actually dragged so return without setting editing focus, or we shift clicked
1063 if (ops_menu == 0) {
1066 ops_menu->popup (1, ev->time);
1070 if (Keyboard::is_context_menu_event (ev)) {
1071 if (ops_menu == 0) {
1074 ops_menu->popup (1, ev->time);
1078 switch (ev->button) {
1082 hours_ebox.grab_focus();
1085 minutes_ebox.grab_focus();
1088 seconds_ebox.grab_focus();
1091 frames_ebox.grab_focus();
1095 audio_frames_ebox.grab_focus();
1099 ms_hours_ebox.grab_focus();
1102 ms_minutes_ebox.grab_focus();
1105 ms_seconds_ebox.grab_focus();
1109 bars_ebox.grab_focus ();
1112 beats_ebox.grab_focus ();
1115 ticks_ebox.grab_focus ();
1128 AudioClock::field_button_press_event (GdkEventButton *ev, Field field)
1130 if (session == 0) return false;
1132 nframes_t frames = 0;
1134 switch (ev->button) {
1136 if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
1138 ValueChanged (); /* EMIT_SIGNAL */
1141 /* make absolutely sure that the pointer is grabbed */
1142 gdk_pointer_grab(ev->window,false ,
1143 GdkEventMask( Gdk::POINTER_MOTION_MASK | Gdk::BUTTON_PRESS_MASK |Gdk::BUTTON_RELEASE_MASK),
1144 NULL,NULL,ev->time);
1147 drag_start_y = ev->y;
1152 if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
1154 ValueChanged (); /* EMIT_SIGNAL */
1159 /* used for context sensitive menu */
1172 AudioClock::field_button_scroll_event (GdkEventScroll *ev, Field field)
1178 nframes_t frames = 0;
1180 switch (ev->direction) {
1183 frames = get_frames (field);
1185 if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
1188 set (current_time() + frames, true);
1189 ValueChanged (); /* EMIT_SIGNAL */
1193 case GDK_SCROLL_DOWN:
1194 frames = get_frames (field);
1196 if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
1200 if ((double)current_time() - (double)frames < 0.0) {
1203 set (current_time() - frames, true);
1206 ValueChanged (); /* EMIT_SIGNAL */
1219 AudioClock::field_motion_notify_event (GdkEventMotion *ev, Field field)
1221 if (session == 0 || !dragging) {
1225 float pixel_frame_scale_factor = 0.2f;
1228 if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
1229 pixel_frame_scale_factor = 0.1f;
1233 if (Keyboard::modifier_state_contains (ev->state,
1234 Keyboard::PrimaryModifier|Keyboard::SecondaryModifier)) {
1236 pixel_frame_scale_factor = 0.025f;
1239 double y_delta = ev->y - drag_y;
1241 drag_accum += y_delta*pixel_frame_scale_factor;
1245 if (trunc(drag_accum) != 0) {
1250 dir = (drag_accum < 0 ? 1:-1);
1251 pos = current_time();
1252 frames = get_frames (field,pos,dir);
1254 if (frames != 0 && frames * drag_accum < current_time()) {
1256 set ((nframes_t) floor (pos - drag_accum * frames), false); // minus because up is negative in computer-land
1264 ValueChanged(); /* EMIT_SIGNAL */
1273 AudioClock::get_frames (Field field,nframes_t pos,int dir)
1276 nframes_t frames = 0;
1280 frames = (nframes_t) floor (3600.0 * session->frame_rate());
1283 frames = (nframes_t) floor (60.0 * session->frame_rate());
1286 frames = session->frame_rate();
1289 frames = (nframes_t) floor (session->frame_rate() / session->smpte_frames_per_second());
1297 frames = (nframes_t) floor (3600.0 * session->frame_rate());
1300 frames = (nframes_t) floor (60.0 * session->frame_rate());
1303 frames = session->frame_rate();
1310 frames = session->tempo_map().bbt_duration_at(pos,bbt,dir);
1316 frames = session->tempo_map().bbt_duration_at(pos,bbt,dir);
1322 frames = session->tempo_map().bbt_duration_at(pos,bbt,dir);
1330 AudioClock::current_time (nframes_t pos) const
1336 ret = smpte_frame_from_display ();
1339 ret = bbt_frame_from_display (pos);
1343 ret = minsec_frame_from_display ();
1347 ret = audio_frame_from_display ();
1358 AudioClock::current_duration (nframes_t pos) const
1364 ret = smpte_frame_from_display ();
1367 ret = bbt_frame_duration_from_display (pos);
1371 ret = minsec_frame_from_display ();
1375 ret = audio_frame_from_display ();
1386 AudioClock::smpte_sanitize_display()
1388 // Check SMPTE fields for sanity, possibly adjusting values
1389 if (atoi(minutes_label.get_text()) > 59) {
1390 minutes_label.set_text("59");
1393 if (atoi(seconds_label.get_text()) > 59) {
1394 seconds_label.set_text("59");
1397 switch ((long)rint(session->smpte_frames_per_second())) {
1399 if (atoi(frames_label.get_text()) > 23) {
1400 frames_label.set_text("23");
1404 if (atoi(frames_label.get_text()) > 24) {
1405 frames_label.set_text("24");
1409 if (atoi(frames_label.get_text()) > 29) {
1410 frames_label.set_text("29");
1417 if (session->smpte_drop_frames()) {
1418 if ((atoi(minutes_label.get_text()) % 10) && (atoi(seconds_label.get_text()) == 0) && (atoi(frames_label.get_text()) < 2)) {
1419 frames_label.set_text("02");
1425 AudioClock::smpte_frame_from_display () const
1434 smpte.hours = atoi (hours_label.get_text());
1435 smpte.minutes = atoi (minutes_label.get_text());
1436 smpte.seconds = atoi (seconds_label.get_text());
1437 smpte.frames = atoi (frames_label.get_text());
1438 smpte.rate = session->smpte_frames_per_second();
1439 smpte.drop= session->smpte_drop_frames();
1441 session->smpte_to_sample( smpte, sample, false /* use_offset */, false /* use_subframes */ );
1445 #define SMPTE_SAMPLE_TEST_1
1446 #define SMPTE_SAMPLE_TEST_2
1447 #define SMPTE_SAMPLE_TEST_3
1448 #define SMPTE_SAMPLE_TEST_4
1449 #define SMPTE_SAMPLE_TEST_5
1450 #define SMPTE_SAMPLE_TEST_6
1451 #define SMPTE_SAMPLE_TEST_7
1453 // Testcode for smpte<->sample conversions (P.S.)
1456 nframes_t oldsample = 0;
1458 nframes_t sample_increment;
1460 sample_increment = (long)rint(session->frame_rate() / session->smpte_frames_per_second);
1462 #ifdef SMPTE_SAMPLE_TEST_1
1463 // Test 1: use_offset = false, use_subframes = false
1464 cout << "use_offset = false, use_subframes = false" << endl;
1465 for (int i = 0; i < 108003; i++) {
1466 session->smpte_to_sample( smpte1, sample1, false /* use_offset */, false /* use_subframes */ );
1467 session->sample_to_smpte( sample1, smpte2, false /* use_offset */, false /* use_subframes */ );
1469 if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
1470 cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1471 cout << "smpte1: " << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1472 cout << "sample: " << sample1 << endl;
1473 cout << "sample: " << sample1 << " -> ";
1474 cout << "smpte2: " << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1478 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1479 cout << "ERROR: smpte2 not equal smpte1" << endl;
1480 cout << "smpte1: " << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1481 cout << "sample: " << sample1 << endl;
1482 cout << "sample: " << sample1 << " -> ";
1483 cout << "smpte2: " << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1486 oldsample = sample1;
1487 session->smpte_increment( smpte1 );
1490 cout << "sample_increment: " << sample_increment << endl;
1491 cout << "sample: " << sample1 << " -> ";
1492 cout << "smpte: " << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1495 #ifdef SMPTE_SAMPLE_TEST_2
1496 // Test 2: use_offset = true, use_subframes = false
1497 cout << "use_offset = true, use_subframes = false" << endl;
1503 smpte1.subframes = 0;
1504 sample1 = oldsample = 0;
1506 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1507 cout << "Starting at sample: " << sample1 << " -> ";
1508 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1510 for (int i = 0; i < 108003; i++) {
1511 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1512 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1514 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1515 // cout << "sample: " << sample1 << endl;
1516 // cout << "sample: " << sample1 << " -> ";
1517 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1519 if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
1520 cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1521 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1522 cout << "sample: " << sample1 << endl;
1523 cout << "sample: " << sample1 << " -> ";
1524 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1528 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1529 cout << "ERROR: smpte2 not equal smpte1" << endl;
1530 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1531 cout << "sample: " << sample1 << endl;
1532 cout << "sample: " << sample1 << " -> ";
1533 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1536 oldsample = sample1;
1537 session->smpte_increment( smpte1 );
1540 cout << "sample_increment: " << sample_increment << endl;
1541 cout << "sample: " << sample1 << " -> ";
1542 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1545 #ifdef SMPTE_SAMPLE_TEST_3
1546 // Test 3: use_offset = true, use_subframes = false, decrement
1547 cout << "use_offset = true, use_subframes = false, decrement" << endl;
1549 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1550 cout << "Starting at sample: " << sample1 << " -> ";
1551 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1553 for (int i = 0; i < 108003; i++) {
1554 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1555 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1557 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1558 // cout << "sample: " << sample1 << endl;
1559 // cout << "sample: " << sample1 << " -> ";
1560 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1562 if ((i > 0) && ( ((oldsample - sample1) != sample_increment) && ((oldsample - sample1) != (sample_increment + 1)) && ((oldsample - sample1) != (sample_increment - 1)))) {
1563 cout << "ERROR: sample increment not right: " << (oldsample - sample1) << " != " << sample_increment << endl;
1564 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1565 cout << "sample: " << sample1 << endl;
1566 cout << "sample: " << sample1 << " -> ";
1567 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1571 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1572 cout << "ERROR: smpte2 not equal smpte1" << endl;
1573 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1574 cout << "sample: " << sample1 << endl;
1575 cout << "sample: " << sample1 << " -> ";
1576 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1579 oldsample = sample1;
1580 session->smpte_decrement( smpte1 );
1583 cout << "sample_decrement: " << sample_increment << endl;
1584 cout << "sample: " << sample1 << " -> ";
1585 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1589 #ifdef SMPTE_SAMPLE_TEST_4
1590 // Test 4: use_offset = true, use_subframes = true
1591 cout << "use_offset = true, use_subframes = true" << endl;
1593 for (long sub = 5; sub < 80; sub += 5) {
1598 smpte1.subframes = 0;
1599 sample1 = oldsample = (sample_increment * sub) / 80;
1601 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, true /* use_subframes */ );
1603 cout << "starting at sample: " << sample1 << " -> ";
1604 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1606 for (int i = 0; i < 108003; i++) {
1607 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, true /* use_subframes */ );
1608 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, true /* use_subframes */ );
1610 if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
1611 cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1612 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1613 cout << "sample: " << sample1 << endl;
1614 cout << "sample: " << sample1 << " -> ";
1615 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1619 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames || smpte2.subframes != smpte1.subframes) {
1620 cout << "ERROR: smpte2 not equal smpte1" << endl;
1621 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1622 cout << "sample: " << sample1 << endl;
1623 cout << "sample: " << sample1 << " -> ";
1624 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1627 oldsample = sample1;
1628 session->smpte_increment( smpte1 );
1631 cout << "sample_increment: " << sample_increment << endl;
1632 cout << "sample: " << sample1 << " -> ";
1633 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1635 for (int i = 0; i < 108003; i++) {
1636 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, true /* use_subframes */ );
1637 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, true /* use_subframes */ );
1639 if ((i > 0) && ( ((oldsample - sample1) != sample_increment) && ((oldsample - sample1) != (sample_increment + 1)) && ((oldsample - sample1) != (sample_increment - 1)))) {
1640 cout << "ERROR: sample increment not right: " << (oldsample - sample1) << " != " << sample_increment << endl;
1641 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1642 cout << "sample: " << sample1 << endl;
1643 cout << "sample: " << sample1 << " -> ";
1644 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1648 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames || smpte2.subframes != smpte1.subframes) {
1649 cout << "ERROR: smpte2 not equal smpte1" << endl;
1650 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1651 cout << "sample: " << sample1 << endl;
1652 cout << "sample: " << sample1 << " -> ";
1653 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1656 oldsample = sample1;
1657 session->smpte_decrement( smpte1 );
1660 cout << "sample_decrement: " << sample_increment << endl;
1661 cout << "sample: " << sample1 << " -> ";
1662 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1667 #ifdef SMPTE_SAMPLE_TEST_5
1668 // Test 5: use_offset = true, use_subframes = false, increment seconds
1669 cout << "use_offset = true, use_subframes = false, increment seconds" << endl;
1675 smpte1.subframes = 0;
1676 sample1 = oldsample = 0;
1677 sample_increment = session->frame_rate();
1679 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1680 cout << "Starting at sample: " << sample1 << " -> ";
1681 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1683 for (int i = 0; i < 3600; i++) {
1684 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1685 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1687 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1688 // cout << "sample: " << sample1 << endl;
1689 // cout << "sample: " << sample1 << " -> ";
1690 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1692 // if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1694 // cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1698 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1699 cout << "ERROR: smpte2 not equal smpte1" << endl;
1700 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1701 cout << "sample: " << sample1 << endl;
1702 cout << "sample: " << sample1 << " -> ";
1703 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1706 oldsample = sample1;
1707 session->smpte_increment_seconds( smpte1 );
1710 cout << "sample_increment: " << sample_increment << endl;
1711 cout << "sample: " << sample1 << " -> ";
1712 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1716 #ifdef SMPTE_SAMPLE_TEST_6
1717 // Test 6: use_offset = true, use_subframes = false, increment minutes
1718 cout << "use_offset = true, use_subframes = false, increment minutes" << endl;
1724 smpte1.subframes = 0;
1725 sample1 = oldsample = 0;
1726 sample_increment = session->frame_rate() * 60;
1728 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1729 cout << "Starting at sample: " << sample1 << " -> ";
1730 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1732 for (int i = 0; i < 60; i++) {
1733 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1734 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1736 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1737 // cout << "sample: " << sample1 << endl;
1738 // cout << "sample: " << sample1 << " -> ";
1739 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1741 // if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1743 // cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1747 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1748 cout << "ERROR: smpte2 not equal smpte1" << endl;
1749 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1750 cout << "sample: " << sample1 << endl;
1751 cout << "sample: " << sample1 << " -> ";
1752 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1755 oldsample = sample1;
1756 session->smpte_increment_minutes( smpte1 );
1759 cout << "sample_increment: " << sample_increment << endl;
1760 cout << "sample: " << sample1 << " -> ";
1761 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1764 #ifdef SMPTE_SAMPLE_TEST_7
1765 // Test 7: use_offset = true, use_subframes = false, increment hours
1766 cout << "use_offset = true, use_subframes = false, increment hours" << endl;
1772 smpte1.subframes = 0;
1773 sample1 = oldsample = 0;
1774 sample_increment = session->frame_rate() * 60 * 60;
1776 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1777 cout << "Starting at sample: " << sample1 << " -> ";
1778 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1780 for (int i = 0; i < 10; i++) {
1781 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1782 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1784 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1785 // cout << "sample: " << sample1 << endl;
1786 // cout << "sample: " << sample1 << " -> ";
1787 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1789 // if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1791 // cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1795 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1796 cout << "ERROR: smpte2 not equal smpte1" << endl;
1797 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1798 cout << "sample: " << sample1 << endl;
1799 cout << "sample: " << sample1 << " -> ";
1800 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1803 oldsample = sample1;
1804 session->smpte_increment_hours( smpte1 );
1807 cout << "sample_increment: " << sample_increment << endl;
1808 cout << "sample: " << sample1 << " -> ";
1809 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1818 AudioClock::minsec_frame_from_display () const
1824 int hrs = atoi (ms_hours_label.get_text());
1825 int mins = atoi (ms_minutes_label.get_text());
1826 float secs = atof (ms_seconds_label.get_text());
1828 nframes_t sr = session->frame_rate();
1830 return (nframes_t) floor ((hrs * 60.0f * 60.0f * sr) + (mins * 60.0f * sr) + (secs * sr));
1834 AudioClock::bbt_frame_from_display (nframes_t pos) const
1837 error << "AudioClock::current_time() called with BBT mode but without session!" << endmsg;
1842 any.type = AnyTime::BBT;
1844 any.bbt.bars = atoi (bars_label.get_text());
1845 any.bbt.beats = atoi (beats_label.get_text());
1846 any.bbt.ticks = atoi (ticks_label.get_text());
1848 nframes_t ret = session->convert_to_frames_at (pos, any);
1855 AudioClock::bbt_frame_duration_from_display (nframes_t pos) const
1858 error << "AudioClock::current_time() called with BBT mode but without session!" << endmsg;
1865 bbt.bars = atoi (bars_label.get_text());
1866 bbt.beats = atoi (beats_label.get_text());
1867 bbt.ticks = atoi (ticks_label.get_text());
1869 return session->tempo_map().bbt_duration_at(pos,bbt,1);
1873 AudioClock::audio_frame_from_display () const
1875 return (nframes_t) atoi (audio_frames_label.get_text());
1879 AudioClock::build_ops_menu ()
1881 using namespace Menu_Helpers;
1882 ops_menu = new Menu;
1883 MenuList& ops_items = ops_menu->items();
1884 ops_menu->set_name ("ArdourContextMenu");
1886 if (!Profile->get_sae()) {
1887 ops_items.push_back (MenuElem (_("Timecode"), bind (mem_fun(*this, &AudioClock::set_mode), SMPTE)));
1889 ops_items.push_back (MenuElem (_("Bars:Beats"), bind (mem_fun(*this, &AudioClock::set_mode), BBT)));
1890 ops_items.push_back (MenuElem (_("Minutes:Seconds"), bind (mem_fun(*this, &AudioClock::set_mode), MinSec)));
1891 ops_items.push_back (MenuElem (_("Samples"), bind (mem_fun(*this, &AudioClock::set_mode), Frames)));
1892 ops_items.push_back (MenuElem (_("Off"), bind (mem_fun(*this, &AudioClock::set_mode), Off)));
1896 AudioClock::set_mode (Mode m)
1898 /* slightly tricky: this is called from within the ARDOUR_UI
1899 constructor by some of its clock members. at that time
1900 the instance pointer is unset, so we have to be careful.
1901 the main idea is to drop keyboard focus in case we had
1902 started editing the clock and then we switch clock mode.
1905 clock_base.grab_focus ();
1911 clock_base.remove ();
1917 clock_base.add (smpte_packer_hbox);
1921 clock_base.add (bbt_packer_hbox);
1925 clock_base.add (minsec_packer_hbox);
1929 clock_base.add (frames_packer_hbox);
1933 clock_base.add (off_hbox);
1937 set_size_requests ();
1939 set (last_when, true);
1940 clock_base.show_all ();
1941 key_entry_state = 0;
1943 if (!is_transient) {
1944 ModeChanged (); /* EMIT SIGNAL */
1949 AudioClock::set_size_requests ()
1951 /* note that in some fonts, "88" is narrower than "00", hence the 2 pixel padding */
1955 Gtkmm2ext::set_size_request_to_display_given_text (hours_label, "-00", 5, 5);
1956 Gtkmm2ext::set_size_request_to_display_given_text (minutes_label, "00", 5, 5);
1957 Gtkmm2ext::set_size_request_to_display_given_text (seconds_label, "00", 5, 5);
1958 Gtkmm2ext::set_size_request_to_display_given_text (frames_label, "00", 5, 5);
1962 Gtkmm2ext::set_size_request_to_display_given_text (bars_label, "-000", 5, 5);
1963 Gtkmm2ext::set_size_request_to_display_given_text (beats_label, "00", 5, 5);
1964 Gtkmm2ext::set_size_request_to_display_given_text (ticks_label, "0000", 5, 5);
1968 Gtkmm2ext::set_size_request_to_display_given_text (ms_hours_label, "00", 5, 5);
1969 Gtkmm2ext::set_size_request_to_display_given_text (ms_minutes_label, "00", 5, 5);
1970 Gtkmm2ext::set_size_request_to_display_given_text (ms_seconds_label, "00.000", 5, 5);
1974 Gtkmm2ext::set_size_request_to_display_given_text (audio_frames_label, "0000000000", 5, 5);
1978 Gtkmm2ext::set_size_request_to_display_given_text (off_hbox, "00000", 5, 5);