plugin manager: filter-by-type really is filter-by-category, so fix the naming and...
[ardour2.git] / gtk2_ardour / audio_clock.cc
blob518bd1c156f67fe8fa75025aabc7effc4b4ee77b
1 /*
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
21 #include <cmath>
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"
36 #include "utils.h"
37 #include "keyboard.h"
38 #include "i18n.h"
40 using namespace ARDOUR;
41 using namespace PBD;
42 using namespace sigc;
43 using namespace Gtk;
44 using namespace std;
46 using PBD::atoi;
47 using PBD::atof;
49 sigc::signal<void> AudioClock::ModeChanged;
50 vector<AudioClock*> AudioClock::clocks;
52 const uint32_t AudioClock::field_length[(int) AudioClock::AudioFrames+1] = {
53 2, /* SMPTE_Hours */
54 2, /* SMPTE_Minutes */
55 2, /* SMPTE_Seconds */
56 2, /* SMPTE_Frames */
57 2, /* MS_Hours */
58 2, /* MS_Minutes */
59 5, /* MS_Seconds */
60 3, /* Bars */
61 2, /* Beats */
62 4, /* Tick */
63 10 /* Audio Frame */
66 AudioClock::AudioClock (std::string clock_name, bool transient, std::string widget_name, bool allow_edit, bool duration, bool with_info)
67 : _name (clock_name),
68 is_transient (transient),
69 is_duration (duration),
70 editable (allow_edit),
71 colon1 (":"),
72 colon2 (":"),
73 colon3 (":"),
74 colon4 (":"),
75 colon5 (":"),
76 b1 ("|"),
77 b2 ("|")
79 session = 0;
80 last_when = 0;
81 last_pdelta = 0;
82 last_sdelta = 0;
83 key_entry_state = 0;
84 ops_menu = 0;
85 dragging = false;
86 bbt_reference_time = -1;
88 if (with_info) {
89 frames_upper_info_label = manage (new Label);
90 frames_lower_info_label = manage (new Label);
91 smpte_upper_info_label = manage (new Label);
92 smpte_lower_info_label = manage (new Label);
93 bbt_upper_info_label = manage (new Label);
94 bbt_lower_info_label = manage (new Label);
96 frames_upper_info_label->set_name ("AudioClockFramesUpperInfo");
97 frames_lower_info_label->set_name ("AudioClockFramesLowerInfo");
98 smpte_upper_info_label->set_name ("AudioClockSMPTEUpperInfo");
99 smpte_lower_info_label->set_name ("AudioClockSMPTELowerInfo");
100 bbt_upper_info_label->set_name ("AudioClockBBTUpperInfo");
101 bbt_lower_info_label->set_name ("AudioClockBBTLowerInfo");
103 Gtkmm2ext::set_size_request_to_display_given_text(*smpte_upper_info_label, "23.98",0,0);
104 Gtkmm2ext::set_size_request_to_display_given_text(*smpte_lower_info_label, "NDF",0,0);
106 Gtkmm2ext::set_size_request_to_display_given_text(*bbt_upper_info_label, "88|88",0,0);
107 Gtkmm2ext::set_size_request_to_display_given_text(*bbt_lower_info_label, "888.88",0,0);
109 frames_info_box.pack_start (*frames_upper_info_label, true, true);
110 frames_info_box.pack_start (*frames_lower_info_label, true, true);
111 smpte_info_box.pack_start (*smpte_upper_info_label, true, true);
112 smpte_info_box.pack_start (*smpte_lower_info_label, true, true);
113 bbt_info_box.pack_start (*bbt_upper_info_label, true, true);
114 bbt_info_box.pack_start (*bbt_lower_info_label, true, true);
116 } else {
117 frames_upper_info_label = 0;
118 frames_lower_info_label = 0;
119 smpte_upper_info_label = 0;
120 smpte_lower_info_label = 0;
121 bbt_upper_info_label = 0;
122 bbt_lower_info_label = 0;
125 audio_frames_ebox.add (audio_frames_label);
127 frames_packer.set_homogeneous (false);
128 frames_packer.set_border_width (2);
129 frames_packer.pack_start (audio_frames_ebox, false, false);
131 if (with_info) {
132 frames_packer.pack_start (frames_info_box, false, false, 5);
135 frames_packer_hbox.pack_start (frames_packer, true, false);
137 hours_ebox.add (hours_label);
138 minutes_ebox.add (minutes_label);
139 seconds_ebox.add (seconds_label);
140 frames_ebox.add (frames_label);
141 bars_ebox.add (bars_label);
142 beats_ebox.add (beats_label);
143 ticks_ebox.add (ticks_label);
144 ms_hours_ebox.add (ms_hours_label);
145 ms_minutes_ebox.add (ms_minutes_label);
146 ms_seconds_ebox.add (ms_seconds_label);
148 smpte_packer.set_homogeneous (false);
149 smpte_packer.set_border_width (2);
150 smpte_packer.pack_start (hours_ebox, false, false);
151 smpte_packer.pack_start (colon1, false, false);
152 smpte_packer.pack_start (minutes_ebox, false, false);
153 smpte_packer.pack_start (colon2, false, false);
154 smpte_packer.pack_start (seconds_ebox, false, false);
155 smpte_packer.pack_start (colon3, false, false);
156 smpte_packer.pack_start (frames_ebox, false, false);
158 if (with_info) {
159 smpte_packer.pack_start (smpte_info_box, false, false, 5);
162 smpte_packer_hbox.pack_start (smpte_packer, true, false);
164 bbt_packer.set_homogeneous (false);
165 bbt_packer.set_border_width (2);
166 bbt_packer.pack_start (bars_ebox, false, false);
167 bbt_packer.pack_start (b1, false, false);
168 bbt_packer.pack_start (beats_ebox, false, false);
169 bbt_packer.pack_start (b2, false, false);
170 bbt_packer.pack_start (ticks_ebox, false, false);
172 if (with_info) {
173 bbt_packer.pack_start (bbt_info_box, false, false, 5);
176 bbt_packer_hbox.pack_start (bbt_packer, true, false);
178 minsec_packer.set_homogeneous (false);
179 minsec_packer.set_border_width (2);
180 minsec_packer.pack_start (ms_hours_ebox, false, false);
181 minsec_packer.pack_start (colon4, false, false);
182 minsec_packer.pack_start (ms_minutes_ebox, false, false);
183 minsec_packer.pack_start (colon5, false, false);
184 minsec_packer.pack_start (ms_seconds_ebox, false, false);
186 minsec_packer_hbox.pack_start (minsec_packer, true, false);
188 clock_frame.set_shadow_type (Gtk::SHADOW_IN);
189 clock_frame.set_name ("BaseFrame");
191 clock_frame.add (clock_base);
193 set_widget_name (widget_name);
195 _mode = BBT; /* lie to force mode switch */
196 set_mode (SMPTE);
198 pack_start (clock_frame, true, true);
200 /* the clock base handles button releases for menu popup regardless of
201 editable status. if the clock is editable, the clock base is where
202 we pass focus to after leaving the last editable "field", which
203 will then shutdown editing till the user starts it up again.
205 it does this because the focus out event on the field disables
206 keyboard event handling, and we don't connect anything up to
207 notice focus in on the clock base. hence, keyboard event handling
208 stays disabled.
211 clock_base.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::SCROLL_MASK);
212 clock_base.signal_button_release_event().connect (bind (mem_fun (*this, &AudioClock::field_button_release_event), SMPTE_Hours));
214 Session::SMPTEOffsetChanged.connect (mem_fun (*this, &AudioClock::smpte_offset_changed));
216 if (editable) {
217 setup_events ();
220 set (last_when, true);
222 if (!is_transient) {
223 clocks.push_back (this);
227 void
228 AudioClock::set_widget_name (string name)
230 Widget::set_name (name);
232 clock_base.set_name (name);
234 audio_frames_label.set_name (name);
235 hours_label.set_name (name);
236 minutes_label.set_name (name);
237 seconds_label.set_name (name);
238 frames_label.set_name (name);
239 bars_label.set_name (name);
240 beats_label.set_name (name);
241 ticks_label.set_name (name);
242 ms_hours_label.set_name (name);
243 ms_minutes_label.set_name (name);
244 ms_seconds_label.set_name (name);
245 hours_ebox.set_name (name);
246 minutes_ebox.set_name (name);
247 seconds_ebox.set_name (name);
248 frames_ebox.set_name (name);
249 audio_frames_ebox.set_name (name);
250 bars_ebox.set_name (name);
251 beats_ebox.set_name (name);
252 ticks_ebox.set_name (name);
253 ms_hours_ebox.set_name (name);
254 ms_minutes_ebox.set_name (name);
255 ms_seconds_ebox.set_name (name);
257 colon1.set_name (name);
258 colon2.set_name (name);
259 colon3.set_name (name);
260 colon4.set_name (name);
261 colon5.set_name (name);
262 b1.set_name (name);
263 b2.set_name (name);
265 queue_draw ();
268 void
269 AudioClock::setup_events ()
271 clock_base.set_flags (Gtk::CAN_FOCUS);
273 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);
274 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);
275 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);
276 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);
277 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);
278 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);
279 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);
280 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);
281 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);
282 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);
283 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);
285 hours_ebox.set_flags (Gtk::CAN_FOCUS);
286 minutes_ebox.set_flags (Gtk::CAN_FOCUS);
287 seconds_ebox.set_flags (Gtk::CAN_FOCUS);
288 frames_ebox.set_flags (Gtk::CAN_FOCUS);
289 audio_frames_ebox.set_flags (Gtk::CAN_FOCUS);
290 bars_ebox.set_flags (Gtk::CAN_FOCUS);
291 beats_ebox.set_flags (Gtk::CAN_FOCUS);
292 ticks_ebox.set_flags (Gtk::CAN_FOCUS);
293 ms_hours_ebox.set_flags (Gtk::CAN_FOCUS);
294 ms_minutes_ebox.set_flags (Gtk::CAN_FOCUS);
295 ms_seconds_ebox.set_flags (Gtk::CAN_FOCUS);
297 hours_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), SMPTE_Hours));
298 minutes_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), SMPTE_Minutes));
299 seconds_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), SMPTE_Seconds));
300 frames_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), SMPTE_Frames));
301 audio_frames_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), AudioFrames));
302 bars_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), Bars));
303 beats_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), Beats));
304 ticks_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), Ticks));
305 ms_hours_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), MS_Hours));
306 ms_minutes_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), MS_Minutes));
307 ms_seconds_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), MS_Seconds));
309 hours_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), SMPTE_Hours));
310 minutes_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), SMPTE_Minutes));
311 seconds_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), SMPTE_Seconds));
312 frames_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), SMPTE_Frames));
313 audio_frames_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), AudioFrames));
314 bars_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), Bars));
315 beats_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), Beats));
316 ticks_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), Ticks));
317 ms_hours_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), MS_Hours));
318 ms_minutes_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), MS_Minutes));
319 ms_seconds_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), MS_Seconds));
321 hours_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), SMPTE_Hours));
322 minutes_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), SMPTE_Minutes));
323 seconds_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), SMPTE_Seconds));
324 frames_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), SMPTE_Frames));
325 audio_frames_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), AudioFrames));
326 bars_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), Bars));
327 beats_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), Beats));
328 ticks_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), Ticks));
329 ms_hours_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), MS_Hours));
330 ms_minutes_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), MS_Minutes));
331 ms_seconds_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), MS_Seconds));
333 hours_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), SMPTE_Hours));
334 minutes_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), SMPTE_Minutes));
335 seconds_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), SMPTE_Seconds));
336 frames_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), SMPTE_Frames));
337 audio_frames_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), AudioFrames));
338 bars_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), Bars));
339 beats_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), Beats));
340 ticks_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), Ticks));
341 ms_hours_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), MS_Hours));
342 ms_minutes_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), MS_Minutes));
343 ms_seconds_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), MS_Seconds));
345 hours_ebox.signal_key_press_event().connect (bind (mem_fun(*this, &AudioClock::field_key_press_event), SMPTE_Hours));
346 minutes_ebox.signal_key_press_event().connect (bind (mem_fun(*this, &AudioClock::field_key_press_event), SMPTE_Minutes));
347 seconds_ebox.signal_key_press_event().connect (bind (mem_fun(*this, &AudioClock::field_key_press_event), SMPTE_Seconds));
348 frames_ebox.signal_key_press_event().connect (bind (mem_fun(*this, &AudioClock::field_key_press_event), SMPTE_Frames));
349 audio_frames_ebox.signal_key_press_event().connect (bind (mem_fun(*this, &AudioClock::field_key_press_event), AudioFrames));
350 bars_ebox.signal_key_press_event().connect (bind (mem_fun(*this, &AudioClock::field_key_press_event), Bars));
351 beats_ebox.signal_key_press_event().connect (bind (mem_fun(*this, &AudioClock::field_key_press_event), Beats));
352 ticks_ebox.signal_key_press_event().connect (bind (mem_fun(*this, &AudioClock::field_key_press_event), Ticks));
353 ms_hours_ebox.signal_key_press_event().connect (bind (mem_fun(*this, &AudioClock::field_key_press_event), MS_Hours));
354 ms_minutes_ebox.signal_key_press_event().connect (bind (mem_fun(*this, &AudioClock::field_key_press_event), MS_Minutes));
355 ms_seconds_ebox.signal_key_press_event().connect (bind (mem_fun(*this, &AudioClock::field_key_press_event), MS_Seconds));
357 hours_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), SMPTE_Hours));
358 minutes_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), SMPTE_Minutes));
359 seconds_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), SMPTE_Seconds));
360 frames_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), SMPTE_Frames));
361 audio_frames_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), AudioFrames));
362 bars_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), Bars));
363 beats_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), Beats));
364 ticks_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), Ticks));
365 ms_hours_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), MS_Hours));
366 ms_minutes_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), MS_Minutes));
367 ms_seconds_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), MS_Seconds));
369 hours_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), SMPTE_Hours));
370 minutes_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), SMPTE_Minutes));
371 seconds_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), SMPTE_Seconds));
372 frames_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), SMPTE_Frames));
373 audio_frames_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), AudioFrames));
374 bars_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), Bars));
375 beats_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), Beats));
376 ticks_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), Ticks));
377 ms_hours_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), MS_Hours));
378 ms_minutes_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), MS_Minutes));
379 ms_seconds_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), MS_Seconds));
381 hours_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), SMPTE_Hours));
382 minutes_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), SMPTE_Minutes));
383 seconds_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), SMPTE_Seconds));
384 frames_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), SMPTE_Frames));
385 audio_frames_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), AudioFrames));
386 bars_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), Bars));
387 beats_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), Beats));
388 ticks_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), Ticks));
389 ms_hours_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), MS_Hours));
390 ms_minutes_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), MS_Minutes));
391 ms_seconds_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), MS_Seconds));
393 clock_base.signal_focus_in_event().connect (mem_fun (*this, &AudioClock::drop_focus_handler));
396 bool
397 AudioClock::drop_focus_handler (GdkEventFocus* ignored)
399 Keyboard::magic_widget_drop_focus ();
400 return false;
403 void
404 AudioClock::on_realize ()
406 HBox::on_realize ();
408 /* styles are not available until the widgets are bound to a window */
410 set_size_requests ();
413 void
414 AudioClock::set (nframes_t when, bool force, nframes_t offset, int which)
417 if ((!force && !is_visible()) || session == 0) {
418 return;
421 if (when == last_when && !offset && !force) {
422 return;
425 bool pdelta = Config->get_primary_clock_delta_edit_cursor();
426 bool sdelta = Config->get_secondary_clock_delta_edit_cursor();
428 if (offset && which == 1 && pdelta) {
429 when = (when > offset) ? when - offset : offset - when;
430 } else if (offset && which == 2 && sdelta) {
431 when = (when > offset) ? when - offset : offset - when;
434 if (which == 1 && pdelta && !last_pdelta) {
435 set_widget_name("TransportClockDisplayDelta");
436 last_pdelta = true;
437 } else if (which == 1 && !pdelta && last_pdelta) {
438 set_widget_name("TransportClockDisplay");
439 last_pdelta = false;
440 } else if (which == 2 && sdelta && !last_sdelta) {
441 set_widget_name("SecondaryClockDisplayDelta");
442 last_sdelta = true;
443 } else if (which == 2 && !sdelta && last_sdelta) {
444 set_widget_name("SecondaryClockDisplay");
445 last_sdelta = false;
448 switch (_mode) {
449 case SMPTE:
450 set_smpte (when, force);
451 break;
453 case BBT:
454 set_bbt (when, force);
455 break;
457 case MinSec:
458 set_minsec (when, force);
459 break;
461 case Frames:
462 set_frames (when, force);
463 break;
465 case Off:
466 break;
469 last_when = when;
472 void
473 AudioClock::smpte_offset_changed ()
475 nframes_t current;
477 switch (_mode) {
478 case SMPTE:
479 if (is_duration) {
480 current = current_duration();
481 } else {
482 current = current_time ();
484 set (current, true);
485 break;
486 default:
487 break;
491 void
492 AudioClock::set_frames (nframes_t when, bool force)
494 char buf[32];
495 snprintf (buf, sizeof (buf), "%u", when);
496 audio_frames_label.set_text (buf);
498 if (frames_upper_info_label) {
499 nframes_t rate = session->frame_rate();
501 if (fmod (rate, 1000.0) == 0.000) {
502 sprintf (buf, "%uK", rate/1000);
503 } else {
504 sprintf (buf, "%.3fK", rate/1000.0f);
507 if (frames_upper_info_label->get_text() != buf) {
508 frames_upper_info_label->set_text (buf);
511 float vid_pullup = Config->get_video_pullup();
513 if (vid_pullup == 0.0) {
514 if (frames_lower_info_label->get_text () != _("none")) {
515 frames_lower_info_label->set_text(_("none"));
517 } else {
518 sprintf (buf, "%-6.4f", vid_pullup);
519 if (frames_lower_info_label->get_text() != buf) {
520 frames_lower_info_label->set_text (buf);
526 void
527 AudioClock::set_minsec (nframes_t when, bool force)
529 char buf[32];
530 nframes_t left;
531 int hrs;
532 int mins;
533 float secs;
535 left = when;
536 hrs = (int) floor (left / (session->frame_rate() * 60.0f * 60.0f));
537 left -= (nframes_t) floor (hrs * session->frame_rate() * 60.0f * 60.0f);
538 mins = (int) floor (left / (session->frame_rate() * 60.0f));
539 left -= (nframes_t) floor (mins * session->frame_rate() * 60.0f);
540 secs = left / (float) session->frame_rate();
542 if (force || hrs != ms_last_hrs) {
543 sprintf (buf, "%02d", hrs);
544 ms_hours_label.set_text (buf);
545 ms_last_hrs = hrs;
548 if (force || mins != ms_last_mins) {
549 sprintf (buf, "%02d", mins);
550 ms_minutes_label.set_text (buf);
551 ms_last_mins = mins;
554 if (force || secs != ms_last_secs) {
555 sprintf (buf, "%06.3f", secs);
556 ms_seconds_label.set_text (buf);
557 ms_last_secs = secs;
561 void
562 AudioClock::set_smpte (nframes_t when, bool force)
564 char buf[32];
565 SMPTE::Time smpte;
567 if (is_duration) {
568 session->smpte_duration (when, smpte);
569 } else {
570 session->smpte_time (when, smpte);
573 if (force || smpte.hours != last_hrs || smpte.negative != last_negative) {
574 if (smpte.negative) {
575 sprintf (buf, "-%02" PRIu32, smpte.hours);
576 } else {
577 sprintf (buf, " %02" PRIu32, smpte.hours);
579 hours_label.set_text (buf);
580 last_hrs = smpte.hours;
581 last_negative = smpte.negative;
584 if (force || smpte.minutes != last_mins) {
585 sprintf (buf, "%02" PRIu32, smpte.minutes);
586 minutes_label.set_text (buf);
587 last_mins = smpte.minutes;
590 if (force || smpte.seconds != last_secs) {
591 sprintf (buf, "%02" PRIu32, smpte.seconds);
592 seconds_label.set_text (buf);
593 last_secs = smpte.seconds;
596 if (force || smpte.frames != last_frames) {
597 sprintf (buf, "%02" PRIu32, smpte.frames);
598 frames_label.set_text (buf);
599 last_frames = smpte.frames;
602 if (smpte_upper_info_label) {
603 double smpte_frames = session->smpte_frames_per_second();
605 if ( fmod(smpte_frames, 1.0) == 0.0) {
606 sprintf (buf, "%u", int (smpte_frames));
607 } else {
608 sprintf (buf, "%.2f", smpte_frames);
611 if (smpte_upper_info_label->get_text() != buf) {
612 smpte_upper_info_label->set_text (buf);
615 if ((fabs(smpte_frames - 29.97) < 0.0001) || smpte_frames == 30) {
616 if (session->smpte_drop_frames()) {
617 sprintf (buf, "DF");
618 } else {
619 sprintf (buf, "NDF");
621 } else {
622 // there is no drop frame alternative
623 buf[0] = '\0';
626 if (smpte_lower_info_label->get_text() != buf) {
627 smpte_lower_info_label->set_text (buf);
632 void
633 AudioClock::set_bbt (nframes_t when, bool force)
635 char buf[16];
636 BBT_Time bbt;
638 /* handle a common case */
639 if (is_duration) {
640 if (when == 0) {
641 bbt.bars = 0;
642 bbt.beats = 0;
643 bbt.ticks = 0;
644 } else {
645 session->tempo_map().bbt_time (when, bbt);
646 bbt.bars--;
647 bbt.beats--;
649 } else {
650 session->tempo_map().bbt_time (when, bbt);
653 sprintf (buf, "%03" PRIu32, bbt.bars);
654 if (force || bars_label.get_text () != buf) {
655 bars_label.set_text (buf);
657 sprintf (buf, "%02" PRIu32, bbt.beats);
658 if (force || beats_label.get_text () != buf) {
659 beats_label.set_text (buf);
661 sprintf (buf, "%04" PRIu32, bbt.ticks);
662 if (force || ticks_label.get_text () != buf) {
663 ticks_label.set_text (buf);
666 if (bbt_upper_info_label) {
667 nframes64_t pos;
669 if (bbt_reference_time < 0) {
670 pos = when;
671 } else {
672 pos = bbt_reference_time;
675 TempoMap::Metric m (session->tempo_map().metric_at (pos));
677 sprintf (buf, "%-5.2f", m.tempo().beats_per_minute());
678 if (bbt_lower_info_label->get_text() != buf) {
679 bbt_lower_info_label->set_text (buf);
681 sprintf (buf, "%g|%g", m.meter().beats_per_bar(), m.meter().note_divisor());
682 if (bbt_upper_info_label->get_text() != buf) {
683 bbt_upper_info_label->set_text (buf);
688 void
689 AudioClock::set_session (Session *s)
691 session = s;
693 if (s) {
695 XMLProperty* prop;
696 XMLNode* node = session->extra_xml (X_("ClockModes"));
697 AudioClock::Mode amode;
699 if (node) {
700 if ((prop = node->property (_name)) != 0) {
701 amode = AudioClock::Mode (string_2_enum (prop->value(), amode));
702 set_mode (amode);
706 set (last_when, true);
710 void
711 AudioClock::focus ()
713 switch (_mode) {
714 case SMPTE:
715 hours_ebox.grab_focus ();
716 break;
718 case BBT:
719 bars_ebox.grab_focus ();
720 break;
722 case MinSec:
723 ms_hours_ebox.grab_focus ();
724 break;
726 case Frames:
727 frames_ebox.grab_focus ();
728 break;
730 case Off:
731 break;
736 bool
737 AudioClock::field_key_press_event (GdkEventKey *ev, Field field)
739 /* all key activity is handled on key release */
740 return true;
743 bool
744 AudioClock::field_key_release_event (GdkEventKey *ev, Field field)
746 Label *label = 0;
747 string new_text;
748 char new_char = 0;
749 bool move_on = false;
751 switch (field) {
752 case SMPTE_Hours:
753 label = &hours_label;
754 break;
755 case SMPTE_Minutes:
756 label = &minutes_label;
757 break;
758 case SMPTE_Seconds:
759 label = &seconds_label;
760 break;
761 case SMPTE_Frames:
762 label = &frames_label;
763 break;
765 case AudioFrames:
766 label = &audio_frames_label;
767 break;
769 case MS_Hours:
770 label = &ms_hours_label;
771 break;
772 case MS_Minutes:
773 label = &ms_minutes_label;
774 break;
775 case MS_Seconds:
776 label = &ms_seconds_label;
777 break;
779 case Bars:
780 label = &bars_label;
781 break;
782 case Beats:
783 label = &beats_label;
784 break;
785 case Ticks:
786 label = &ticks_label;
787 break;
788 default:
789 return false;
792 switch (ev->keyval) {
793 case GDK_0:
794 case GDK_KP_0:
795 new_char = '0';
796 break;
797 case GDK_1:
798 case GDK_KP_1:
799 new_char = '1';
800 break;
801 case GDK_2:
802 case GDK_KP_2:
803 new_char = '2';
804 break;
805 case GDK_3:
806 case GDK_KP_3:
807 new_char = '3';
808 break;
809 case GDK_4:
810 case GDK_KP_4:
811 new_char = '4';
812 break;
813 case GDK_5:
814 case GDK_KP_5:
815 new_char = '5';
816 break;
817 case GDK_6:
818 case GDK_KP_6:
819 new_char = '6';
820 break;
821 case GDK_7:
822 case GDK_KP_7:
823 new_char = '7';
824 break;
825 case GDK_8:
826 case GDK_KP_8:
827 new_char = '8';
828 break;
829 case GDK_9:
830 case GDK_KP_9:
831 new_char = '9';
832 break;
834 case GDK_period:
835 case GDK_KP_Decimal:
836 if (_mode == MinSec && field == MS_Seconds) {
837 new_char = '.';
838 } else {
839 return false;
841 break;
843 case GDK_Tab:
844 case GDK_Return:
845 case GDK_KP_Enter:
846 move_on = true;
847 break;
849 case GDK_Escape:
850 key_entry_state = 0;
851 clock_base.grab_focus ();
852 ChangeAborted(); /* EMIT SIGNAL */
853 return true;
855 default:
856 return false;
859 if (!move_on) {
861 if (key_entry_state == 0) {
863 /* initialize with a fresh new string */
865 if (field != AudioFrames) {
866 for (uint32_t xn = 0; xn < field_length[field] - 1; ++xn) {
867 new_text += '0';
869 } else {
870 new_text = "";
873 } else {
875 string existing = label->get_text();
876 if (existing.length() >= field_length[field]) {
877 new_text = existing.substr (1, field_length[field] - 1);
878 } else {
879 new_text = existing.substr (0, field_length[field] - 1);
883 new_text += new_char;
884 label->set_text (new_text);
885 key_entry_state++;
888 if (key_entry_state == field_length[field]) {
889 move_on = true;
892 if (move_on) {
894 if (key_entry_state) {
896 switch (field) {
897 case SMPTE_Hours:
898 case SMPTE_Minutes:
899 case SMPTE_Seconds:
900 case SMPTE_Frames:
901 // Check SMPTE fields for sanity (may also adjust fields)
902 smpte_sanitize_display();
903 break;
904 case Bars:
905 case Beats:
906 case Ticks:
907 // Bars should never be, unless this clock is for a duration
908 if (atoi(bars_label.get_text()) == 0 && !is_duration) {
909 bars_label.set_text("001");
911 // beats should never be 0, unless this clock is for a duration
912 if (atoi(beats_label.get_text()) == 0 && !is_duration) {
913 beats_label.set_text("01");
915 break;
916 default:
917 break;
920 ValueChanged(); /* EMIT_SIGNAL */
923 /* move on to the next field.
926 switch (field) {
928 /* SMPTE */
930 case SMPTE_Hours:
931 minutes_ebox.grab_focus ();
932 break;
933 case SMPTE_Minutes:
934 seconds_ebox.grab_focus ();
935 break;
936 case SMPTE_Seconds:
937 frames_ebox.grab_focus ();
938 break;
939 case SMPTE_Frames:
940 clock_base.grab_focus ();
941 break;
943 /* audio frames */
944 case AudioFrames:
945 clock_base.grab_focus ();
946 break;
948 /* Min:Sec */
950 case MS_Hours:
951 ms_minutes_ebox.grab_focus ();
952 break;
953 case MS_Minutes:
954 ms_seconds_ebox.grab_focus ();
955 break;
956 case MS_Seconds:
957 clock_base.grab_focus ();
958 break;
960 /* BBT */
962 case Bars:
963 beats_ebox.grab_focus ();
964 break;
965 case Beats:
966 ticks_ebox.grab_focus ();
967 break;
968 case Ticks:
969 clock_base.grab_focus ();
970 break;
972 default:
973 break;
978 //if user hit Enter, lose focus
979 switch (ev->keyval) {
980 case GDK_Return:
981 case GDK_KP_Enter:
982 clock_base.grab_focus ();
985 return true;
988 bool
989 AudioClock::field_focus_in_event (GdkEventFocus *ev, Field field)
991 key_entry_state = 0;
993 Keyboard::magic_widget_grab_focus ();
995 switch (field) {
996 case SMPTE_Hours:
997 hours_ebox.set_flags (Gtk::HAS_FOCUS);
998 hours_ebox.set_state (Gtk::STATE_ACTIVE);
999 break;
1000 case SMPTE_Minutes:
1001 minutes_ebox.set_flags (Gtk::HAS_FOCUS);
1002 minutes_ebox.set_state (Gtk::STATE_ACTIVE);
1003 break;
1004 case SMPTE_Seconds:
1005 seconds_ebox.set_flags (Gtk::HAS_FOCUS);
1006 seconds_ebox.set_state (Gtk::STATE_ACTIVE);
1007 break;
1008 case SMPTE_Frames:
1009 frames_ebox.set_flags (Gtk::HAS_FOCUS);
1010 frames_ebox.set_state (Gtk::STATE_ACTIVE);
1011 break;
1013 case AudioFrames:
1014 audio_frames_ebox.set_flags (Gtk::HAS_FOCUS);
1015 audio_frames_ebox.set_state (Gtk::STATE_ACTIVE);
1016 break;
1018 case MS_Hours:
1019 ms_hours_ebox.set_flags (Gtk::HAS_FOCUS);
1020 ms_hours_ebox.set_state (Gtk::STATE_ACTIVE);
1021 break;
1022 case MS_Minutes:
1023 ms_minutes_ebox.set_flags (Gtk::HAS_FOCUS);
1024 ms_minutes_ebox.set_state (Gtk::STATE_ACTIVE);
1025 break;
1026 case MS_Seconds:
1027 ms_seconds_ebox.set_flags (Gtk::HAS_FOCUS);
1028 ms_seconds_ebox.set_state (Gtk::STATE_ACTIVE);
1029 break;
1030 case Bars:
1031 bars_ebox.set_flags (Gtk::HAS_FOCUS);
1032 bars_ebox.set_state (Gtk::STATE_ACTIVE);
1033 break;
1034 case Beats:
1035 beats_ebox.set_flags (Gtk::HAS_FOCUS);
1036 beats_ebox.set_state (Gtk::STATE_ACTIVE);
1037 break;
1038 case Ticks:
1039 ticks_ebox.set_flags (Gtk::HAS_FOCUS);
1040 ticks_ebox.set_state (Gtk::STATE_ACTIVE);
1041 break;
1044 return false;
1047 bool
1048 AudioClock::field_focus_out_event (GdkEventFocus *ev, Field field)
1050 switch (field) {
1052 case SMPTE_Hours:
1053 hours_ebox.unset_flags (Gtk::HAS_FOCUS);
1054 hours_ebox.set_state (Gtk::STATE_NORMAL);
1055 break;
1056 case SMPTE_Minutes:
1057 minutes_ebox.unset_flags (Gtk::HAS_FOCUS);
1058 minutes_ebox.set_state (Gtk::STATE_NORMAL);
1059 break;
1060 case SMPTE_Seconds:
1061 seconds_ebox.unset_flags (Gtk::HAS_FOCUS);
1062 seconds_ebox.set_state (Gtk::STATE_NORMAL);
1063 break;
1064 case SMPTE_Frames:
1065 frames_ebox.unset_flags (Gtk::HAS_FOCUS);
1066 frames_ebox.set_state (Gtk::STATE_NORMAL);
1067 break;
1069 case AudioFrames:
1070 audio_frames_ebox.unset_flags (Gtk::HAS_FOCUS);
1071 audio_frames_ebox.set_state (Gtk::STATE_NORMAL);
1072 break;
1074 case MS_Hours:
1075 ms_hours_ebox.unset_flags (Gtk::HAS_FOCUS);
1076 ms_hours_ebox.set_state (Gtk::STATE_NORMAL);
1077 break;
1078 case MS_Minutes:
1079 ms_minutes_ebox.unset_flags (Gtk::HAS_FOCUS);
1080 ms_minutes_ebox.set_state (Gtk::STATE_NORMAL);
1081 break;
1082 case MS_Seconds:
1083 ms_seconds_ebox.unset_flags (Gtk::HAS_FOCUS);
1084 ms_seconds_ebox.set_state (Gtk::STATE_NORMAL);
1085 break;
1087 case Bars:
1088 bars_ebox.unset_flags (Gtk::HAS_FOCUS);
1089 bars_ebox.set_state (Gtk::STATE_NORMAL);
1090 break;
1091 case Beats:
1092 beats_ebox.unset_flags (Gtk::HAS_FOCUS);
1093 beats_ebox.set_state (Gtk::STATE_NORMAL);
1094 break;
1095 case Ticks:
1096 ticks_ebox.unset_flags (Gtk::HAS_FOCUS);
1097 ticks_ebox.set_state (Gtk::STATE_NORMAL);
1098 break;
1101 Keyboard::magic_widget_drop_focus ();
1103 return false;
1106 bool
1107 AudioClock::field_button_release_event (GdkEventButton *ev, Field field)
1109 if (dragging) {
1110 gdk_pointer_ungrab (GDK_CURRENT_TIME);
1111 dragging = false;
1112 if (ev->y > drag_start_y+1 || ev->y < drag_start_y-1 || Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)){
1113 // we actually dragged so return without setting editing focus, or we shift clicked
1114 return true;
1118 if (!editable) {
1119 if (ops_menu == 0) {
1120 build_ops_menu ();
1122 ops_menu->popup (1, ev->time);
1123 return true;
1126 if (Keyboard::is_context_menu_event (ev)) {
1127 if (ops_menu == 0) {
1128 build_ops_menu ();
1130 ops_menu->popup (1, ev->time);
1131 return true;
1134 switch (ev->button) {
1135 case 1:
1136 switch (field) {
1137 case SMPTE_Hours:
1138 hours_ebox.grab_focus();
1139 break;
1140 case SMPTE_Minutes:
1141 minutes_ebox.grab_focus();
1142 break;
1143 case SMPTE_Seconds:
1144 seconds_ebox.grab_focus();
1145 break;
1146 case SMPTE_Frames:
1147 frames_ebox.grab_focus();
1148 break;
1150 case AudioFrames:
1151 audio_frames_ebox.grab_focus();
1152 break;
1154 case MS_Hours:
1155 ms_hours_ebox.grab_focus();
1156 break;
1157 case MS_Minutes:
1158 ms_minutes_ebox.grab_focus();
1159 break;
1160 case MS_Seconds:
1161 ms_seconds_ebox.grab_focus();
1162 break;
1164 case Bars:
1165 bars_ebox.grab_focus ();
1166 break;
1167 case Beats:
1168 beats_ebox.grab_focus ();
1169 break;
1170 case Ticks:
1171 ticks_ebox.grab_focus ();
1172 break;
1174 break;
1176 default:
1177 break;
1180 return true;
1183 bool
1184 AudioClock::field_button_press_event (GdkEventButton *ev, Field field)
1186 if (session == 0) return false;
1188 nframes_t frames = 0;
1190 switch (ev->button) {
1191 case 1:
1192 if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
1193 set (frames, true);
1194 ValueChanged (); /* EMIT_SIGNAL */
1197 /* make absolutely sure that the pointer is grabbed */
1198 gdk_pointer_grab(ev->window,false ,
1199 GdkEventMask( Gdk::POINTER_MOTION_MASK | Gdk::BUTTON_PRESS_MASK |Gdk::BUTTON_RELEASE_MASK),
1200 NULL,NULL,ev->time);
1201 dragging = true;
1202 drag_accum = 0;
1203 drag_start_y = ev->y;
1204 drag_y = ev->y;
1205 break;
1207 case 2:
1208 if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
1209 set (frames, true);
1210 ValueChanged (); /* EMIT_SIGNAL */
1212 break;
1214 case 3:
1215 /* used for context sensitive menu */
1216 return false;
1217 break;
1219 default:
1220 return false;
1221 break;
1224 return true;
1227 bool
1228 AudioClock::field_button_scroll_event (GdkEventScroll *ev, Field field)
1230 if (session == 0) {
1231 return false;
1234 nframes_t frames = 0;
1236 switch (ev->direction) {
1238 case GDK_SCROLL_UP:
1239 frames = get_frames (field);
1240 if (frames != 0) {
1241 if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
1242 frames *= 10;
1244 set (current_time() + frames, true);
1245 ValueChanged (); /* EMIT_SIGNAL */
1247 break;
1249 case GDK_SCROLL_DOWN:
1250 frames = get_frames (field);
1251 if (frames != 0) {
1252 if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
1253 frames *= 10;
1256 if ((double)current_time() - (double)frames < 0.0) {
1257 set (0, true);
1258 } else {
1259 set (current_time() - frames, true);
1262 ValueChanged (); /* EMIT_SIGNAL */
1264 break;
1266 default:
1267 return false;
1268 break;
1271 return true;
1274 bool
1275 AudioClock::field_motion_notify_event (GdkEventMotion *ev, Field field)
1277 if (session == 0 || !dragging) {
1278 return false;
1281 float pixel_frame_scale_factor = 0.2f;
1284 if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
1285 pixel_frame_scale_factor = 0.1f;
1289 if (Keyboard::modifier_state_contains (ev->state,
1290 Keyboard::PrimaryModifier|Keyboard::SecondaryModifier)) {
1292 pixel_frame_scale_factor = 0.025f;
1295 double y_delta = ev->y - drag_y;
1297 drag_accum += y_delta*pixel_frame_scale_factor;
1299 drag_y = ev->y;
1301 if (trunc(drag_accum) != 0) {
1303 nframes_t frames;
1304 nframes_t pos ;
1305 int dir;
1306 dir = (drag_accum < 0 ? 1:-1);
1307 pos = current_time();
1308 frames = get_frames (field,pos,dir);
1310 if (frames != 0 && frames * drag_accum < current_time()) {
1312 set ((nframes_t) floor (pos - drag_accum * frames), false); // minus because up is negative in computer-land
1314 } else {
1315 set (0 , false);
1319 drag_accum= 0;
1320 ValueChanged(); /* EMIT_SIGNAL */
1325 return true;
1328 nframes_t
1329 AudioClock::get_frames (Field field,nframes_t pos,int dir)
1332 nframes_t frames = 0;
1333 BBT_Time bbt;
1334 switch (field) {
1335 case SMPTE_Hours:
1336 frames = (nframes_t) floor (3600.0 * session->frame_rate());
1337 break;
1338 case SMPTE_Minutes:
1339 frames = (nframes_t) floor (60.0 * session->frame_rate());
1340 break;
1341 case SMPTE_Seconds:
1342 frames = session->frame_rate();
1343 break;
1344 case SMPTE_Frames:
1345 frames = (nframes_t) floor (session->frame_rate() / session->smpte_frames_per_second());
1346 break;
1348 case AudioFrames:
1349 frames = 1;
1350 break;
1352 case MS_Hours:
1353 frames = (nframes_t) floor (3600.0 * session->frame_rate());
1354 break;
1355 case MS_Minutes:
1356 frames = (nframes_t) floor (60.0 * session->frame_rate());
1357 break;
1358 case MS_Seconds:
1359 frames = session->frame_rate();
1360 break;
1362 case Bars:
1363 bbt.bars = 1;
1364 bbt.beats = 0;
1365 bbt.ticks = 0;
1366 frames = session->tempo_map().bbt_duration_at(pos,bbt,dir);
1367 break;
1368 case Beats:
1369 bbt.bars = 0;
1370 bbt.beats = 1;
1371 bbt.ticks = 0;
1372 frames = session->tempo_map().bbt_duration_at(pos,bbt,dir);
1373 break;
1374 case Ticks:
1375 bbt.bars = 0;
1376 bbt.beats = 0;
1377 bbt.ticks = 1;
1378 frames = session->tempo_map().bbt_duration_at(pos,bbt,dir);
1379 break;
1382 return frames;
1385 nframes_t
1386 AudioClock::current_time (nframes_t pos) const
1388 nframes_t ret = 0;
1390 switch (_mode) {
1391 case SMPTE:
1392 ret = smpte_frame_from_display ();
1393 break;
1394 case BBT:
1395 ret = bbt_frame_from_display (pos);
1396 break;
1398 case MinSec:
1399 ret = minsec_frame_from_display ();
1400 break;
1402 case Frames:
1403 ret = audio_frame_from_display ();
1404 break;
1406 case Off:
1407 break;
1410 return ret;
1413 nframes_t
1414 AudioClock::current_duration (nframes_t pos) const
1416 nframes_t ret = 0;
1418 switch (_mode) {
1419 case SMPTE:
1420 ret = smpte_frame_from_display ();
1421 break;
1422 case BBT:
1423 ret = bbt_frame_duration_from_display (pos);
1424 break;
1426 case MinSec:
1427 ret = minsec_frame_from_display ();
1428 break;
1430 case Frames:
1431 ret = audio_frame_from_display ();
1432 break;
1434 case Off:
1435 break;
1438 return ret;
1441 void
1442 AudioClock::smpte_sanitize_display()
1444 // Check SMPTE fields for sanity, possibly adjusting values
1445 if (atoi(minutes_label.get_text()) > 59) {
1446 minutes_label.set_text("59");
1449 if (atoi(seconds_label.get_text()) > 59) {
1450 seconds_label.set_text("59");
1453 switch ((long)rint(session->smpte_frames_per_second())) {
1454 case 24:
1455 if (atoi(frames_label.get_text()) > 23) {
1456 frames_label.set_text("23");
1458 break;
1459 case 25:
1460 if (atoi(frames_label.get_text()) > 24) {
1461 frames_label.set_text("24");
1463 break;
1464 case 30:
1465 if (atoi(frames_label.get_text()) > 29) {
1466 frames_label.set_text("29");
1468 break;
1469 default:
1470 break;
1473 if (session->smpte_drop_frames()) {
1474 if ((atoi(minutes_label.get_text()) % 10) && (atoi(seconds_label.get_text()) == 0) && (atoi(frames_label.get_text()) < 2)) {
1475 frames_label.set_text("02");
1480 nframes_t
1481 AudioClock::smpte_frame_from_display () const
1483 if (session == 0) {
1484 return 0;
1487 SMPTE::Time smpte;
1488 nframes_t sample;
1490 smpte.hours = atoi (hours_label.get_text());
1491 smpte.minutes = atoi (minutes_label.get_text());
1492 smpte.seconds = atoi (seconds_label.get_text());
1493 smpte.frames = atoi (frames_label.get_text());
1494 smpte.rate = session->smpte_frames_per_second();
1495 smpte.drop= session->smpte_drop_frames();
1497 session->smpte_to_sample( smpte, sample, false /* use_offset */, false /* use_subframes */ );
1500 #if 0
1501 #define SMPTE_SAMPLE_TEST_1
1502 #define SMPTE_SAMPLE_TEST_2
1503 #define SMPTE_SAMPLE_TEST_3
1504 #define SMPTE_SAMPLE_TEST_4
1505 #define SMPTE_SAMPLE_TEST_5
1506 #define SMPTE_SAMPLE_TEST_6
1507 #define SMPTE_SAMPLE_TEST_7
1509 // Testcode for smpte<->sample conversions (P.S.)
1510 SMPTE::Time smpte1;
1511 nframes_t sample1;
1512 nframes_t oldsample = 0;
1513 SMPTE::Time smpte2;
1514 nframes_t sample_increment;
1516 sample_increment = (long)rint(session->frame_rate() / session->smpte_frames_per_second);
1518 #ifdef SMPTE_SAMPLE_TEST_1
1519 // Test 1: use_offset = false, use_subframes = false
1520 cout << "use_offset = false, use_subframes = false" << endl;
1521 for (int i = 0; i < 108003; i++) {
1522 session->smpte_to_sample( smpte1, sample1, false /* use_offset */, false /* use_subframes */ );
1523 session->sample_to_smpte( sample1, smpte2, false /* use_offset */, false /* use_subframes */ );
1525 if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
1526 cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1527 cout << "smpte1: " << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1528 cout << "sample: " << sample1 << endl;
1529 cout << "sample: " << sample1 << " -> ";
1530 cout << "smpte2: " << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1531 break;
1534 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1535 cout << "ERROR: smpte2 not equal smpte1" << endl;
1536 cout << "smpte1: " << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1537 cout << "sample: " << sample1 << endl;
1538 cout << "sample: " << sample1 << " -> ";
1539 cout << "smpte2: " << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1540 break;
1542 oldsample = sample1;
1543 session->smpte_increment( smpte1 );
1546 cout << "sample_increment: " << sample_increment << endl;
1547 cout << "sample: " << sample1 << " -> ";
1548 cout << "smpte: " << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1549 #endif
1551 #ifdef SMPTE_SAMPLE_TEST_2
1552 // Test 2: use_offset = true, use_subframes = false
1553 cout << "use_offset = true, use_subframes = false" << endl;
1555 smpte1.hours = 0;
1556 smpte1.minutes = 0;
1557 smpte1.seconds = 0;
1558 smpte1.frames = 0;
1559 smpte1.subframes = 0;
1560 sample1 = oldsample = 0;
1562 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1563 cout << "Starting at sample: " << sample1 << " -> ";
1564 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1566 for (int i = 0; i < 108003; i++) {
1567 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1568 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1570 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1571 // cout << "sample: " << sample1 << endl;
1572 // cout << "sample: " << sample1 << " -> ";
1573 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1575 if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
1576 cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1577 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1578 cout << "sample: " << sample1 << endl;
1579 cout << "sample: " << sample1 << " -> ";
1580 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1581 break;
1584 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1585 cout << "ERROR: smpte2 not equal smpte1" << endl;
1586 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1587 cout << "sample: " << sample1 << endl;
1588 cout << "sample: " << sample1 << " -> ";
1589 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1590 break;
1592 oldsample = sample1;
1593 session->smpte_increment( smpte1 );
1596 cout << "sample_increment: " << sample_increment << endl;
1597 cout << "sample: " << sample1 << " -> ";
1598 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1599 #endif
1601 #ifdef SMPTE_SAMPLE_TEST_3
1602 // Test 3: use_offset = true, use_subframes = false, decrement
1603 cout << "use_offset = true, use_subframes = false, decrement" << endl;
1605 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1606 cout << "Starting at sample: " << sample1 << " -> ";
1607 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1609 for (int i = 0; i < 108003; i++) {
1610 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1611 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1613 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1614 // cout << "sample: " << sample1 << endl;
1615 // cout << "sample: " << sample1 << " -> ";
1616 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1618 if ((i > 0) && ( ((oldsample - sample1) != sample_increment) && ((oldsample - sample1) != (sample_increment + 1)) && ((oldsample - sample1) != (sample_increment - 1)))) {
1619 cout << "ERROR: sample increment not right: " << (oldsample - sample1) << " != " << sample_increment << endl;
1620 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1621 cout << "sample: " << sample1 << endl;
1622 cout << "sample: " << sample1 << " -> ";
1623 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1624 break;
1627 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1628 cout << "ERROR: smpte2 not equal smpte1" << endl;
1629 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1630 cout << "sample: " << sample1 << endl;
1631 cout << "sample: " << sample1 << " -> ";
1632 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1633 break;
1635 oldsample = sample1;
1636 session->smpte_decrement( smpte1 );
1639 cout << "sample_decrement: " << sample_increment << endl;
1640 cout << "sample: " << sample1 << " -> ";
1641 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1642 #endif
1645 #ifdef SMPTE_SAMPLE_TEST_4
1646 // Test 4: use_offset = true, use_subframes = true
1647 cout << "use_offset = true, use_subframes = true" << endl;
1649 for (long sub = 5; sub < 80; sub += 5) {
1650 smpte1.hours = 0;
1651 smpte1.minutes = 0;
1652 smpte1.seconds = 0;
1653 smpte1.frames = 0;
1654 smpte1.subframes = 0;
1655 sample1 = oldsample = (sample_increment * sub) / 80;
1657 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, true /* use_subframes */ );
1659 cout << "starting at sample: " << sample1 << " -> ";
1660 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1662 for (int i = 0; i < 108003; i++) {
1663 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, true /* use_subframes */ );
1664 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, true /* use_subframes */ );
1666 if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
1667 cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1668 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1669 cout << "sample: " << sample1 << endl;
1670 cout << "sample: " << sample1 << " -> ";
1671 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1672 //break;
1675 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames || smpte2.subframes != smpte1.subframes) {
1676 cout << "ERROR: smpte2 not equal smpte1" << endl;
1677 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1678 cout << "sample: " << sample1 << endl;
1679 cout << "sample: " << sample1 << " -> ";
1680 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1681 break;
1683 oldsample = sample1;
1684 session->smpte_increment( smpte1 );
1687 cout << "sample_increment: " << sample_increment << endl;
1688 cout << "sample: " << sample1 << " -> ";
1689 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1691 for (int i = 0; i < 108003; i++) {
1692 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, true /* use_subframes */ );
1693 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, true /* use_subframes */ );
1695 if ((i > 0) && ( ((oldsample - sample1) != sample_increment) && ((oldsample - sample1) != (sample_increment + 1)) && ((oldsample - sample1) != (sample_increment - 1)))) {
1696 cout << "ERROR: sample increment not right: " << (oldsample - sample1) << " != " << sample_increment << endl;
1697 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1698 cout << "sample: " << sample1 << endl;
1699 cout << "sample: " << sample1 << " -> ";
1700 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1701 //break;
1704 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames || smpte2.subframes != smpte1.subframes) {
1705 cout << "ERROR: smpte2 not equal smpte1" << endl;
1706 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1707 cout << "sample: " << sample1 << endl;
1708 cout << "sample: " << sample1 << " -> ";
1709 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1710 break;
1712 oldsample = sample1;
1713 session->smpte_decrement( smpte1 );
1716 cout << "sample_decrement: " << sample_increment << endl;
1717 cout << "sample: " << sample1 << " -> ";
1718 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1720 #endif
1723 #ifdef SMPTE_SAMPLE_TEST_5
1724 // Test 5: use_offset = true, use_subframes = false, increment seconds
1725 cout << "use_offset = true, use_subframes = false, increment seconds" << endl;
1727 smpte1.hours = 0;
1728 smpte1.minutes = 0;
1729 smpte1.seconds = 0;
1730 smpte1.frames = 0;
1731 smpte1.subframes = 0;
1732 sample1 = oldsample = 0;
1733 sample_increment = session->frame_rate();
1735 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1736 cout << "Starting at sample: " << sample1 << " -> ";
1737 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1739 for (int i = 0; i < 3600; i++) {
1740 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1741 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1743 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1744 // cout << "sample: " << sample1 << endl;
1745 // cout << "sample: " << sample1 << " -> ";
1746 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1748 // if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1749 // {
1750 // cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1751 // break;
1752 // }
1754 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1755 cout << "ERROR: smpte2 not equal smpte1" << endl;
1756 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1757 cout << "sample: " << sample1 << endl;
1758 cout << "sample: " << sample1 << " -> ";
1759 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1760 break;
1762 oldsample = sample1;
1763 session->smpte_increment_seconds( smpte1 );
1766 cout << "sample_increment: " << sample_increment << endl;
1767 cout << "sample: " << sample1 << " -> ";
1768 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1769 #endif
1772 #ifdef SMPTE_SAMPLE_TEST_6
1773 // Test 6: use_offset = true, use_subframes = false, increment minutes
1774 cout << "use_offset = true, use_subframes = false, increment minutes" << endl;
1776 smpte1.hours = 0;
1777 smpte1.minutes = 0;
1778 smpte1.seconds = 0;
1779 smpte1.frames = 0;
1780 smpte1.subframes = 0;
1781 sample1 = oldsample = 0;
1782 sample_increment = session->frame_rate() * 60;
1784 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1785 cout << "Starting at sample: " << sample1 << " -> ";
1786 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1788 for (int i = 0; i < 60; i++) {
1789 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1790 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1792 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1793 // cout << "sample: " << sample1 << endl;
1794 // cout << "sample: " << sample1 << " -> ";
1795 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1797 // if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1798 // {
1799 // cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1800 // break;
1801 // }
1803 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1804 cout << "ERROR: smpte2 not equal smpte1" << endl;
1805 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1806 cout << "sample: " << sample1 << endl;
1807 cout << "sample: " << sample1 << " -> ";
1808 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1809 break;
1811 oldsample = sample1;
1812 session->smpte_increment_minutes( smpte1 );
1815 cout << "sample_increment: " << sample_increment << endl;
1816 cout << "sample: " << sample1 << " -> ";
1817 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1818 #endif
1820 #ifdef SMPTE_SAMPLE_TEST_7
1821 // Test 7: use_offset = true, use_subframes = false, increment hours
1822 cout << "use_offset = true, use_subframes = false, increment hours" << endl;
1824 smpte1.hours = 0;
1825 smpte1.minutes = 0;
1826 smpte1.seconds = 0;
1827 smpte1.frames = 0;
1828 smpte1.subframes = 0;
1829 sample1 = oldsample = 0;
1830 sample_increment = session->frame_rate() * 60 * 60;
1832 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1833 cout << "Starting at sample: " << sample1 << " -> ";
1834 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1836 for (int i = 0; i < 10; i++) {
1837 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1838 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1840 // cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1841 // cout << "sample: " << sample1 << endl;
1842 // cout << "sample: " << sample1 << " -> ";
1843 // cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1845 // if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1846 // {
1847 // cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1848 // break;
1849 // }
1851 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1852 cout << "ERROR: smpte2 not equal smpte1" << endl;
1853 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1854 cout << "sample: " << sample1 << endl;
1855 cout << "sample: " << sample1 << " -> ";
1856 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1857 break;
1859 oldsample = sample1;
1860 session->smpte_increment_hours( smpte1 );
1863 cout << "sample_increment: " << sample_increment << endl;
1864 cout << "sample: " << sample1 << " -> ";
1865 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1866 #endif
1868 #endif
1870 return sample;
1873 nframes_t
1874 AudioClock::minsec_frame_from_display () const
1876 if (session == 0) {
1877 return 0;
1880 int hrs = atoi (ms_hours_label.get_text());
1881 int mins = atoi (ms_minutes_label.get_text());
1882 float secs = atof (ms_seconds_label.get_text());
1884 nframes_t sr = session->frame_rate();
1886 return (nframes_t) floor ((hrs * 60.0f * 60.0f * sr) + (mins * 60.0f * sr) + (secs * sr));
1889 nframes_t
1890 AudioClock::bbt_frame_from_display (nframes_t pos) const
1892 if (session == 0) {
1893 error << "AudioClock::current_time() called with BBT mode but without session!" << endmsg;
1894 return 0;
1897 AnyTime any;
1898 any.type = AnyTime::BBT;
1900 any.bbt.bars = atoi (bars_label.get_text());
1901 any.bbt.beats = atoi (beats_label.get_text());
1902 any.bbt.ticks = atoi (ticks_label.get_text());
1904 if (is_duration) {
1905 any.bbt.bars++;
1906 any.bbt.beats++;
1909 nframes_t ret = session->convert_to_frames_at (pos, any);
1911 return ret;
1915 nframes_t
1916 AudioClock::bbt_frame_duration_from_display (nframes_t pos) const
1918 if (session == 0) {
1919 error << "AudioClock::current_time() called with BBT mode but without session!" << endmsg;
1920 return 0;
1923 BBT_Time bbt;
1926 bbt.bars = atoi (bars_label.get_text());
1927 bbt.beats = atoi (beats_label.get_text());
1928 bbt.ticks = atoi (ticks_label.get_text());
1930 return session->tempo_map().bbt_duration_at(pos,bbt,1);
1933 nframes_t
1934 AudioClock::audio_frame_from_display () const
1936 return (nframes_t) atoi (audio_frames_label.get_text());
1939 void
1940 AudioClock::build_ops_menu ()
1942 using namespace Menu_Helpers;
1943 ops_menu = new Menu;
1944 MenuList& ops_items = ops_menu->items();
1945 ops_menu->set_name ("ArdourContextMenu");
1947 if (!Profile->get_sae()) {
1948 ops_items.push_back (MenuElem (_("Timecode"), bind (mem_fun(*this, &AudioClock::set_mode), SMPTE)));
1950 ops_items.push_back (MenuElem (_("Bars:Beats"), bind (mem_fun(*this, &AudioClock::set_mode), BBT)));
1951 ops_items.push_back (MenuElem (_("Minutes:Seconds"), bind (mem_fun(*this, &AudioClock::set_mode), MinSec)));
1952 ops_items.push_back (MenuElem (_("Samples"), bind (mem_fun(*this, &AudioClock::set_mode), Frames)));
1953 ops_items.push_back (MenuElem (_("Off"), bind (mem_fun(*this, &AudioClock::set_mode), Off)));
1956 void
1957 AudioClock::set_mode (Mode m)
1959 /* slightly tricky: this is called from within the ARDOUR_UI
1960 constructor by some of its clock members. at that time
1961 the instance pointer is unset, so we have to be careful.
1962 the main idea is to drop keyboard focus in case we had
1963 started editing the clock and then we switch clock mode.
1966 clock_base.grab_focus ();
1968 if (_mode == m) {
1969 return;
1972 clock_base.remove ();
1974 _mode = m;
1976 switch (_mode) {
1977 case SMPTE:
1978 clock_base.add (smpte_packer_hbox);
1979 break;
1981 case BBT:
1982 clock_base.add (bbt_packer_hbox);
1983 break;
1985 case MinSec:
1986 clock_base.add (minsec_packer_hbox);
1987 break;
1989 case Frames:
1990 clock_base.add (frames_packer_hbox);
1991 break;
1993 case Off:
1994 clock_base.add (off_hbox);
1995 break;
1998 set_size_requests ();
2000 set (last_when, true);
2001 clock_base.show_all ();
2002 key_entry_state = 0;
2004 if (!is_transient) {
2005 ModeChanged (); /* EMIT SIGNAL */
2009 void
2010 AudioClock::set_size_requests ()
2012 /* note that in some fonts, "88" is narrower than "00", hence the 2 pixel padding */
2014 switch (_mode) {
2015 case SMPTE:
2016 Gtkmm2ext::set_size_request_to_display_given_text (hours_label, "-00", 5, 5);
2017 Gtkmm2ext::set_size_request_to_display_given_text (minutes_label, "00", 5, 5);
2018 Gtkmm2ext::set_size_request_to_display_given_text (seconds_label, "00", 5, 5);
2019 Gtkmm2ext::set_size_request_to_display_given_text (frames_label, "00", 5, 5);
2020 break;
2022 case BBT:
2023 Gtkmm2ext::set_size_request_to_display_given_text (bars_label, "-000", 5, 5);
2024 Gtkmm2ext::set_size_request_to_display_given_text (beats_label, "00", 5, 5);
2025 Gtkmm2ext::set_size_request_to_display_given_text (ticks_label, "0000", 5, 5);
2026 break;
2028 case MinSec:
2029 Gtkmm2ext::set_size_request_to_display_given_text (ms_hours_label, "00", 5, 5);
2030 Gtkmm2ext::set_size_request_to_display_given_text (ms_minutes_label, "00", 5, 5);
2031 Gtkmm2ext::set_size_request_to_display_given_text (ms_seconds_label, "00.000", 5, 5);
2032 break;
2034 case Frames:
2035 Gtkmm2ext::set_size_request_to_display_given_text (audio_frames_label, "0000000000", 5, 5);
2036 break;
2038 case Off:
2039 Gtkmm2ext::set_size_request_to_display_given_text (off_hbox, "00000", 5, 5);
2040 break;
2045 void
2046 AudioClock::set_bbt_reference (nframes64_t pos)
2048 bbt_reference_time = pos;