Remove duplicate menubarstyle property.
[ardour.git] / gtk2_ardour / audio_clock.cc
1 /*
2     Copyright (C) 1999 Paul Davis 
3
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.
8
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.
13
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.
17
18 */
19
20 #include <cstdio> // for sprintf
21 #include <cmath>
22
23 #include <pbd/convert.h>
24 #include <pbd/enumwriter.h>
25
26 #include <gtkmm2ext/utils.h>
27
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>
33
34 #include "ardour_ui.h"
35 #include "audio_clock.h"
36 #include "utils.h"
37 #include "keyboard.h"
38 #include "i18n.h"
39
40 using namespace ARDOUR;
41 using namespace PBD;
42 using namespace sigc;
43 using namespace Gtk;
44 using namespace std;
45
46 using PBD::atoi;
47 using PBD::atof;
48
49 sigc::signal<void> AudioClock::ModeChanged;
50 vector<AudioClock*> AudioClock::clocks;
51
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 */
64 };
65
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 ("|"),
78           last_when(0)
79 {
80         session = 0;
81         last_when = 0;
82         last_pdelta = 0;
83         last_sdelta = 0;
84         key_entry_state = 0;
85         ops_menu = 0;
86         dragging = false;
87         bbt_reference_time = -1;
88
89         if (with_info) {
90                 frames_upper_info_label = manage (new Label);
91                 frames_lower_info_label = manage (new Label);
92                 smpte_upper_info_label = manage (new Label);
93                 smpte_lower_info_label = manage (new Label);
94                 bbt_upper_info_label = manage (new Label);
95                 bbt_lower_info_label = manage (new Label);
96                 
97                 frames_upper_info_label->set_name ("AudioClockFramesUpperInfo");
98                 frames_lower_info_label->set_name ("AudioClockFramesLowerInfo");
99                 smpte_upper_info_label->set_name ("AudioClockSMPTEUpperInfo");
100                 smpte_lower_info_label->set_name ("AudioClockSMPTELowerInfo");
101                 bbt_upper_info_label->set_name ("AudioClockBBTUpperInfo");
102                 bbt_lower_info_label->set_name ("AudioClockBBTLowerInfo");
103
104                 Gtkmm2ext::set_size_request_to_display_given_text(*smpte_upper_info_label, "23.98",0,0);
105                 Gtkmm2ext::set_size_request_to_display_given_text(*smpte_lower_info_label, "NDF",0,0);
106
107                 Gtkmm2ext::set_size_request_to_display_given_text(*bbt_upper_info_label, "88|88",0,0);
108                 Gtkmm2ext::set_size_request_to_display_given_text(*bbt_lower_info_label, "888.88",0,0);
109
110                 frames_info_box.pack_start (*frames_upper_info_label, true, true);
111                 frames_info_box.pack_start (*frames_lower_info_label, true, true);
112                 smpte_info_box.pack_start (*smpte_upper_info_label, true, true);
113                 smpte_info_box.pack_start (*smpte_lower_info_label, true, true);
114                 bbt_info_box.pack_start (*bbt_upper_info_label, true, true);
115                 bbt_info_box.pack_start (*bbt_lower_info_label, true, true);
116                 
117         } else {
118                 frames_upper_info_label = 0;
119                 frames_lower_info_label = 0;
120                 smpte_upper_info_label = 0;
121                 smpte_lower_info_label = 0;
122                 bbt_upper_info_label = 0;
123                 bbt_lower_info_label = 0;
124         }       
125         
126         audio_frames_ebox.add (audio_frames_label);
127         
128         frames_packer.set_homogeneous (false);
129         frames_packer.set_border_width (2);
130         frames_packer.pack_start (audio_frames_ebox, false, false);
131         
132         if (with_info) {
133                 frames_packer.pack_start (frames_info_box, false, false, 5);
134         }
135         
136         frames_packer_hbox.pack_start (frames_packer, true, false);
137
138         hours_ebox.add (hours_label);
139         minutes_ebox.add (minutes_label);
140         seconds_ebox.add (seconds_label);
141         frames_ebox.add (frames_label);
142         bars_ebox.add (bars_label);
143         beats_ebox.add (beats_label);
144         ticks_ebox.add (ticks_label);
145         ms_hours_ebox.add (ms_hours_label);
146         ms_minutes_ebox.add (ms_minutes_label);
147         ms_seconds_ebox.add (ms_seconds_label);
148
149         smpte_packer.set_homogeneous (false);
150         smpte_packer.set_border_width (2);
151         smpte_packer.pack_start (hours_ebox, false, false);
152         smpte_packer.pack_start (colon1, false, false);
153         smpte_packer.pack_start (minutes_ebox, false, false);
154         smpte_packer.pack_start (colon2, false, false);
155         smpte_packer.pack_start (seconds_ebox, false, false);
156         smpte_packer.pack_start (colon3, false, false);
157         smpte_packer.pack_start (frames_ebox, false, false);
158
159         if (with_info) {
160                 smpte_packer.pack_start (smpte_info_box, false, false, 5);
161         }
162
163         smpte_packer_hbox.pack_start (smpte_packer, true, false);
164
165         bbt_packer.set_homogeneous (false);
166         bbt_packer.set_border_width (2);
167         bbt_packer.pack_start (bars_ebox, false, false);
168         bbt_packer.pack_start (b1, false, false);
169         bbt_packer.pack_start (beats_ebox, false, false);
170         bbt_packer.pack_start (b2, false, false);
171         bbt_packer.pack_start (ticks_ebox, false, false);
172
173         if (with_info) {
174                 bbt_packer.pack_start (bbt_info_box, false, false, 5);
175         }
176
177         bbt_packer_hbox.pack_start (bbt_packer, true, false);
178
179         minsec_packer.set_homogeneous (false);
180         minsec_packer.set_border_width (2);
181         minsec_packer.pack_start (ms_hours_ebox, false, false);
182         minsec_packer.pack_start (colon4, false, false);
183         minsec_packer.pack_start (ms_minutes_ebox, false, false);
184         minsec_packer.pack_start (colon5, false, false);
185         minsec_packer.pack_start (ms_seconds_ebox, false, false);
186
187         minsec_packer_hbox.pack_start (minsec_packer, true, false);
188
189         clock_frame.set_shadow_type (Gtk::SHADOW_IN);
190         clock_frame.set_name ("BaseFrame");
191
192         clock_frame.add (clock_base);
193
194         set_widget_name (widget_name);
195
196         _mode = BBT; /* lie to force mode switch */
197         set_mode (SMPTE);
198
199         pack_start (clock_frame, true, true);
200
201         /* the clock base handles button releases for menu popup regardless of
202            editable status. if the clock is editable, the clock base is where
203            we pass focus to after leaving the last editable "field", which
204            will then shutdown editing till the user starts it up again.
205
206            it does this because the focus out event on the field disables
207            keyboard event handling, and we don't connect anything up to
208            notice focus in on the clock base. hence, keyboard event handling
209            stays disabled.
210         */
211
212         clock_base.add_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK|Gdk::SCROLL_MASK);
213         clock_base.signal_button_release_event().connect (bind (mem_fun (*this, &AudioClock::field_button_release_event), SMPTE_Hours));
214
215         Session::SMPTEOffsetChanged.connect (mem_fun (*this, &AudioClock::smpte_offset_changed));
216
217         if (editable) {
218                 setup_events ();
219         }
220
221         set (last_when, true);
222
223         if (!is_transient) {
224                 clocks.push_back (this);
225         }
226 }
227
228 void
229 AudioClock::set_widget_name (string name)
230 {
231         Widget::set_name (name);
232
233         clock_base.set_name (name);
234
235         audio_frames_label.set_name (name);
236         hours_label.set_name (name);
237         minutes_label.set_name (name);
238         seconds_label.set_name (name);
239         frames_label.set_name (name);
240         bars_label.set_name (name);
241         beats_label.set_name (name);
242         ticks_label.set_name (name);
243         ms_hours_label.set_name (name);
244         ms_minutes_label.set_name (name);
245         ms_seconds_label.set_name (name);
246         hours_ebox.set_name (name);
247         minutes_ebox.set_name (name);
248         seconds_ebox.set_name (name);
249         frames_ebox.set_name (name);
250         audio_frames_ebox.set_name (name);
251         bars_ebox.set_name (name);
252         beats_ebox.set_name (name);
253         ticks_ebox.set_name (name);
254         ms_hours_ebox.set_name (name);
255         ms_minutes_ebox.set_name (name);
256         ms_seconds_ebox.set_name (name);
257         
258         colon1.set_name (name);
259         colon2.set_name (name);
260         colon3.set_name (name);
261         colon4.set_name (name);
262         colon5.set_name (name);
263         b1.set_name (name);
264         b2.set_name (name);
265
266         queue_draw ();
267 }
268
269 void
270 AudioClock::setup_events ()
271 {
272         clock_base.set_flags (Gtk::CAN_FOCUS);
273
274         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);
275         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);
276         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);
277         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);
278         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);
279         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);
280         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);
281         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);
282         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);
283         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);
284         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
286         hours_ebox.set_flags (Gtk::CAN_FOCUS);
287         minutes_ebox.set_flags (Gtk::CAN_FOCUS);
288         seconds_ebox.set_flags (Gtk::CAN_FOCUS);
289         frames_ebox.set_flags (Gtk::CAN_FOCUS);
290         audio_frames_ebox.set_flags (Gtk::CAN_FOCUS);
291         bars_ebox.set_flags (Gtk::CAN_FOCUS);
292         beats_ebox.set_flags (Gtk::CAN_FOCUS);
293         ticks_ebox.set_flags (Gtk::CAN_FOCUS);
294         ms_hours_ebox.set_flags (Gtk::CAN_FOCUS);
295         ms_minutes_ebox.set_flags (Gtk::CAN_FOCUS);
296         ms_seconds_ebox.set_flags (Gtk::CAN_FOCUS);
297
298         hours_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), SMPTE_Hours));
299         minutes_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), SMPTE_Minutes));
300         seconds_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), SMPTE_Seconds));
301         frames_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), SMPTE_Frames));
302         audio_frames_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), AudioFrames));
303         bars_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), Bars));
304         beats_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), Beats));
305         ticks_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), Ticks));
306         ms_hours_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), MS_Hours));
307         ms_minutes_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), MS_Minutes));
308         ms_seconds_ebox.signal_motion_notify_event().connect (bind (mem_fun(*this, &AudioClock::field_motion_notify_event), MS_Seconds));
309
310         hours_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), SMPTE_Hours));
311         minutes_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), SMPTE_Minutes));
312         seconds_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), SMPTE_Seconds));
313         frames_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), SMPTE_Frames));
314         audio_frames_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), AudioFrames));
315         bars_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), Bars));
316         beats_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), Beats));
317         ticks_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), Ticks));
318         ms_hours_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), MS_Hours));
319         ms_minutes_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), MS_Minutes));
320         ms_seconds_ebox.signal_button_press_event().connect (bind (mem_fun(*this, &AudioClock::field_button_press_event), MS_Seconds));
321
322         hours_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), SMPTE_Hours));
323         minutes_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), SMPTE_Minutes));
324         seconds_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), SMPTE_Seconds));
325         frames_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), SMPTE_Frames));
326         audio_frames_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), AudioFrames));
327         bars_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), Bars));
328         beats_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), Beats));
329         ticks_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), Ticks));
330         ms_hours_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), MS_Hours));
331         ms_minutes_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), MS_Minutes));
332         ms_seconds_ebox.signal_button_release_event().connect (bind (mem_fun(*this, &AudioClock::field_button_release_event), MS_Seconds));
333
334         hours_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), SMPTE_Hours));
335         minutes_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), SMPTE_Minutes));
336         seconds_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), SMPTE_Seconds));
337         frames_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), SMPTE_Frames));
338         audio_frames_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), AudioFrames));
339         bars_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), Bars));
340         beats_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), Beats));
341         ticks_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), Ticks));
342         ms_hours_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), MS_Hours));
343         ms_minutes_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), MS_Minutes));
344         ms_seconds_ebox.signal_scroll_event().connect (bind (mem_fun(*this, &AudioClock::field_button_scroll_event), MS_Seconds));
345
346         hours_ebox.signal_key_press_event().connect (bind (mem_fun(*this, &AudioClock::field_key_press_event), SMPTE_Hours));
347         minutes_ebox.signal_key_press_event().connect (bind (mem_fun(*this, &AudioClock::field_key_press_event), SMPTE_Minutes));
348         seconds_ebox.signal_key_press_event().connect (bind (mem_fun(*this, &AudioClock::field_key_press_event), SMPTE_Seconds));
349         frames_ebox.signal_key_press_event().connect (bind (mem_fun(*this, &AudioClock::field_key_press_event), SMPTE_Frames));
350         audio_frames_ebox.signal_key_press_event().connect (bind (mem_fun(*this, &AudioClock::field_key_press_event), AudioFrames));
351         bars_ebox.signal_key_press_event().connect (bind (mem_fun(*this, &AudioClock::field_key_press_event), Bars));
352         beats_ebox.signal_key_press_event().connect (bind (mem_fun(*this, &AudioClock::field_key_press_event), Beats));
353         ticks_ebox.signal_key_press_event().connect (bind (mem_fun(*this, &AudioClock::field_key_press_event), Ticks));
354         ms_hours_ebox.signal_key_press_event().connect (bind (mem_fun(*this, &AudioClock::field_key_press_event), MS_Hours));
355         ms_minutes_ebox.signal_key_press_event().connect (bind (mem_fun(*this, &AudioClock::field_key_press_event), MS_Minutes));
356         ms_seconds_ebox.signal_key_press_event().connect (bind (mem_fun(*this, &AudioClock::field_key_press_event), MS_Seconds));
357
358         hours_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), SMPTE_Hours));
359         minutes_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), SMPTE_Minutes));
360         seconds_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), SMPTE_Seconds));
361         frames_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), SMPTE_Frames));
362         audio_frames_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), AudioFrames));
363         bars_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), Bars));
364         beats_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), Beats));
365         ticks_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), Ticks));
366         ms_hours_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), MS_Hours));
367         ms_minutes_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), MS_Minutes));
368         ms_seconds_ebox.signal_key_release_event().connect (bind (mem_fun(*this, &AudioClock::field_key_release_event), MS_Seconds));
369
370         hours_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), SMPTE_Hours));
371         minutes_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), SMPTE_Minutes));
372         seconds_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), SMPTE_Seconds));
373         frames_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), SMPTE_Frames));
374         audio_frames_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), AudioFrames));
375         bars_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), Bars));
376         beats_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), Beats));
377         ticks_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), Ticks));
378         ms_hours_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), MS_Hours));
379         ms_minutes_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), MS_Minutes));
380         ms_seconds_ebox.signal_focus_in_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_in_event), MS_Seconds));
381
382         hours_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), SMPTE_Hours));
383         minutes_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), SMPTE_Minutes));
384         seconds_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), SMPTE_Seconds));
385         frames_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), SMPTE_Frames));
386         audio_frames_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), AudioFrames));
387         bars_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), Bars));
388         beats_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), Beats));
389         ticks_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), Ticks));
390         ms_hours_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), MS_Hours));
391         ms_minutes_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), MS_Minutes));
392         ms_seconds_ebox.signal_focus_out_event().connect (bind (mem_fun(*this, &AudioClock::field_focus_out_event), MS_Seconds));
393
394         clock_base.signal_focus_in_event().connect (mem_fun (*this, &AudioClock::drop_focus_handler));
395 }
396
397 bool
398 AudioClock::drop_focus_handler (GdkEventFocus* ignored)
399 {
400         Keyboard::magic_widget_drop_focus ();
401         return false;
402 }
403
404 void
405 AudioClock::on_realize ()
406 {
407         HBox::on_realize ();
408
409         /* styles are not available until the widgets are bound to a window */
410
411         set_size_requests ();
412 }
413
414 void
415 AudioClock::set (nframes_t when, bool force, nframes_t offset, char which)
416 {
417
418         if ((!force && !is_visible()) || session == 0) {
419                 return;
420         }
421         
422         if (when == last_when && !offset && !force) {
423                 return;
424         }
425
426         bool pdelta = Config->get_primary_clock_delta_edit_cursor();
427         bool sdelta = Config->get_secondary_clock_delta_edit_cursor();
428
429         if (offset && which == 'p' && pdelta) {
430                 when = (when > offset) ? when - offset : offset - when;
431         } else if (offset && which == 's' && sdelta) {
432                 when = (when > offset) ? when - offset : offset - when;
433         }
434
435         if (which == 'p' && pdelta && !last_pdelta) {
436                 set_widget_name("TransportClockDisplayDelta");
437                 last_pdelta = true;
438         } else if (which == 'p' && !pdelta && last_pdelta) {
439                 set_widget_name("TransportClockDisplay");
440                 last_pdelta = false;
441         } else if (which == 's'  && sdelta && !last_sdelta) {
442                 set_widget_name("SecondaryClockDisplayDelta");
443                 last_sdelta = true;
444         } else if (which == 's' && !sdelta && last_sdelta) {
445                 set_widget_name("SecondaryClockDisplay");
446                 last_sdelta = false;
447         }
448
449         switch (_mode) {
450         case SMPTE:
451                 set_smpte (when, force);
452                 break;
453
454         case BBT:
455                 set_bbt (when, force);
456                 break;
457
458         case MinSec:
459                 set_minsec (when, force);
460                 break;
461
462         case Frames:
463                 set_frames (when, force);
464                 break;
465
466         case Off:
467                 break;
468         }
469
470         last_when = when;
471 }
472
473 void
474 AudioClock::smpte_offset_changed ()
475 {
476         nframes_t current;
477
478         switch (_mode) {
479         case SMPTE:
480                 if (is_duration) {
481                         current = current_duration();
482                 } else {
483                         current = current_time ();
484                 }
485                 set (current, true);
486                 break;
487         default:
488                 break;
489         }
490 }
491
492 void
493 AudioClock::set_frames (nframes_t when, bool force)
494 {
495         char buf[32];
496         snprintf (buf, sizeof (buf), "%u", when);
497         audio_frames_label.set_text (buf);
498         
499         if (frames_upper_info_label) {
500                 nframes_t rate = session->frame_rate();
501                 
502                 if (fmod (rate, 1000.0) == 0.000) {
503                         sprintf (buf, "%uK", rate/1000);
504                 } else {
505                         sprintf (buf, "%.3fK", rate/1000.0f);
506                 }
507                 
508                 if (frames_upper_info_label->get_text() != buf) {
509                         frames_upper_info_label->set_text (buf);
510                 }
511                 
512                 float vid_pullup = Config->get_video_pullup();
513                 
514                 if (vid_pullup == 0.0) {
515                         if (frames_lower_info_label->get_text () != _("none")) {
516                                 frames_lower_info_label->set_text(_("none"));
517                         }
518                 } else {
519                         sprintf (buf, "%-6.4f", vid_pullup);
520                         if (frames_lower_info_label->get_text() != buf) {
521                                 frames_lower_info_label->set_text (buf);
522                         }
523                 }
524         }
525 }       
526
527 void
528 AudioClock::set_minsec (nframes_t when, bool force)
529 {
530         char buf[32];
531         nframes_t left;
532         int hrs;
533         int mins;
534         float secs;
535         
536         left = when;
537         hrs = (int) floor (left / (session->frame_rate() * 60.0f * 60.0f));
538         left -= (nframes_t) floor (hrs * session->frame_rate() * 60.0f * 60.0f);
539         mins = (int) floor (left / (session->frame_rate() * 60.0f));
540         left -= (nframes_t) floor (mins * session->frame_rate() * 60.0f);
541         secs = left / (float) session->frame_rate();
542
543         if (force || hrs != ms_last_hrs) {
544                 sprintf (buf, "%02d", hrs);
545                 ms_hours_label.set_text (buf);
546                 ms_last_hrs = hrs;
547         }
548
549         if (force || mins != ms_last_mins) {
550                 sprintf (buf, "%02d", mins);
551                 ms_minutes_label.set_text (buf);
552                 ms_last_mins = mins;
553         }
554
555         if (force || secs != ms_last_secs) {
556                 sprintf (buf, "%06.3f", secs);
557                 ms_seconds_label.set_text (buf);
558                 ms_last_secs = secs;
559         }
560 }
561
562 void
563 AudioClock::set_smpte (nframes_t when, bool force)
564 {
565         char buf[32];
566         SMPTE::Time smpte;
567         
568         if (is_duration) {
569                 session->smpte_duration (when, smpte);
570         } else {
571                 session->smpte_time (when, smpte);
572         }
573
574         if (force || smpte.hours != last_hrs || smpte.negative != last_negative) {
575                 if (smpte.negative) {
576                         sprintf (buf, "-%02" PRIu32, smpte.hours);
577                 } else {
578                         sprintf (buf, " %02" PRIu32, smpte.hours);
579                 }
580                 hours_label.set_text (buf);
581                 last_hrs = smpte.hours;
582                 last_negative = smpte.negative;
583         }
584
585         if (force || smpte.minutes != last_mins) {
586                 sprintf (buf, "%02" PRIu32, smpte.minutes);
587                 minutes_label.set_text (buf);
588                 last_mins = smpte.minutes;
589         }
590
591         if (force || smpte.seconds != last_secs) {
592                 sprintf (buf, "%02" PRIu32, smpte.seconds);
593                 seconds_label.set_text (buf);
594                 last_secs = smpte.seconds;
595         }
596
597         if (force || smpte.frames != last_frames) {
598                 sprintf (buf, "%02" PRIu32, smpte.frames);
599                 frames_label.set_text (buf);
600                 last_frames = smpte.frames;
601         }
602         
603         if (smpte_upper_info_label) {
604                 double smpte_frames = session->smpte_frames_per_second();
605                 
606                 if ( fmod(smpte_frames, 1.0) == 0.0) {
607                         sprintf (buf, "%u", int (smpte_frames)); 
608                 } else {
609                         sprintf (buf, "%.2f", smpte_frames);
610                 }
611                 
612                 if (smpte_upper_info_label->get_text() != buf) {
613                         smpte_upper_info_label->set_text (buf);
614                 }
615                 
616                 if ((fabs(smpte_frames - 29.97) < 0.0001) || smpte_frames == 30) {
617                         if (session->smpte_drop_frames()) {
618                                 sprintf (buf, "DF");
619                         } else {
620                                 sprintf (buf, "NDF");
621                         }
622                 } else {
623                         // there is no drop frame alternative
624                         buf[0] = '\0';
625                 }
626                 
627                 if (smpte_lower_info_label->get_text() != buf) {
628                         smpte_lower_info_label->set_text (buf);
629                 }
630         }
631 }
632
633 void
634 AudioClock::set_bbt (nframes_t when, bool force)
635 {
636         char buf[16];
637         BBT_Time bbt;
638
639         session->tempo_map().bbt_time (when, bbt);
640
641         /* handle a common case */
642
643         if (is_duration && when == 0) {
644                 bbt.bars = 0;
645                 bbt.beats = 0;
646
647         }
648
649         sprintf (buf, "%03" PRIu32, bbt.bars);
650         if (force || bars_label.get_text () != buf) {
651                 bars_label.set_text (buf);
652         }
653         sprintf (buf, "%02" PRIu32, bbt.beats);
654         if (force || beats_label.get_text () != buf) {
655                 beats_label.set_text (buf);
656         }
657         sprintf (buf, "%04" PRIu32, bbt.ticks);
658         if (force || ticks_label.get_text () != buf) {
659                 ticks_label.set_text (buf);
660         }
661         
662         if (bbt_upper_info_label) {
663                 nframes64_t pos;
664
665                 if (bbt_reference_time < 0) {
666                         pos = when;
667                 } else {
668                         pos = bbt_reference_time;
669                 }
670
671                 TempoMap::Metric m (session->tempo_map().metric_at (pos));
672
673                 sprintf (buf, "%-5.2f", m.tempo().beats_per_minute());
674                 if (bbt_lower_info_label->get_text() != buf) {
675                         bbt_lower_info_label->set_text (buf);
676                 }
677                 sprintf (buf, "%g|%g", m.meter().beats_per_bar(), m.meter().note_divisor());
678                 if (bbt_upper_info_label->get_text() != buf) {
679                         bbt_upper_info_label->set_text (buf);
680                 }
681         }
682 }
683
684 void
685 AudioClock::set_session (Session *s)
686 {
687         session = s;
688
689         if (s) {
690
691                 XMLProperty* prop;
692                 XMLNode* node = session->extra_xml (X_("ClockModes"));
693                 AudioClock::Mode amode;
694                 
695                 if (node) {
696                         if ((prop = node->property (_name)) != 0) {
697                                 amode = AudioClock::Mode (string_2_enum (prop->value(), amode));
698                                 set_mode (amode);
699                         }
700                 }
701
702                 set (last_when, true);
703         }
704 }
705
706 void
707 AudioClock::focus ()
708 {
709         switch (_mode) {
710         case SMPTE:
711                 hours_ebox.grab_focus ();
712                 break;
713
714         case BBT:
715                 bars_ebox.grab_focus ();
716                 break;
717
718         case MinSec:
719                 ms_hours_ebox.grab_focus ();
720                 break;
721
722         case Frames:
723                 frames_ebox.grab_focus ();
724                 break;
725
726         case Off:
727                 break;
728         }
729 }
730
731
732 bool
733 AudioClock::field_key_press_event (GdkEventKey *ev, Field field)
734 {
735         /* all key activity is handled on key release */
736         return true;
737 }
738
739 bool
740 AudioClock::field_key_release_event (GdkEventKey *ev, Field field)
741 {
742         Label *label = 0;
743         string new_text;
744         char new_char = 0;
745         bool move_on = false;
746
747         switch (field) {
748         case SMPTE_Hours:
749                 label = &hours_label;
750                 break;
751         case SMPTE_Minutes:
752                 label = &minutes_label;
753                 break;
754         case SMPTE_Seconds:
755                 label = &seconds_label;
756                 break;
757         case SMPTE_Frames:
758                 label = &frames_label;
759                 break;
760
761         case AudioFrames:
762                 label = &audio_frames_label;
763                 break;
764
765         case MS_Hours:
766                 label = &ms_hours_label;
767                 break;
768         case MS_Minutes:
769                 label = &ms_minutes_label;
770                 break;
771         case MS_Seconds:
772                 label = &ms_seconds_label;
773                 break;
774
775         case Bars:
776                 label = &bars_label;
777                 break;
778         case Beats:
779                 label = &beats_label;
780                 break;
781         case Ticks:
782                 label = &ticks_label;
783                 break;
784         default:
785                 return false;
786         }
787
788         switch (ev->keyval) {
789         case GDK_0:
790         case GDK_KP_0:
791                 new_char = '0';
792                 break;
793         case GDK_1:
794         case GDK_KP_1:
795                 new_char = '1';
796                 break;
797         case GDK_2:
798         case GDK_KP_2:
799                 new_char = '2';
800                 break;
801         case GDK_3:
802         case GDK_KP_3:
803                 new_char = '3';
804                 break;
805         case GDK_4:
806         case GDK_KP_4:
807                 new_char = '4';
808                 break;
809         case GDK_5:
810         case GDK_KP_5:
811                 new_char = '5';
812                 break;
813         case GDK_6:
814         case GDK_KP_6:
815                 new_char = '6';
816                 break;
817         case GDK_7:
818         case GDK_KP_7:
819                 new_char = '7';
820                 break;
821         case GDK_8:
822         case GDK_KP_8:
823                 new_char = '8';
824                 break;
825         case GDK_9:
826         case GDK_KP_9:
827                 new_char = '9';
828                 break;
829
830         case GDK_period:
831         case GDK_KP_Decimal:
832                 if (_mode == MinSec && field == MS_Seconds) {
833                         new_char = '.';
834                 } else {
835                         return false;
836                 }
837                 break;
838
839         case GDK_Tab:
840         case GDK_Return:
841         case GDK_KP_Enter:
842                 move_on = true;
843                 break;
844
845         case GDK_Escape:
846                 key_entry_state = 0;
847                 clock_base.grab_focus ();
848                 ChangeAborted();  /*  EMIT SIGNAL  */
849                 return true;
850
851         default:
852                 return false;
853         }
854
855         if (!move_on) {
856
857                 if (key_entry_state == 0) {
858
859                         /* initialize with a fresh new string */
860
861                         if (field != AudioFrames) {
862                                 for (uint32_t xn = 0; xn < field_length[field] - 1; ++xn) {
863                                         new_text += '0';
864                                 }
865                         } else {
866                                 new_text = "";
867                         }
868
869                 } else {
870
871                         string existing = label->get_text();
872                         if (existing.length() >= field_length[field]) {
873                                 new_text = existing.substr (1, field_length[field] - 1);
874                         } else {
875                                 new_text = existing.substr (0, field_length[field] - 1);
876                         }
877                 }
878
879                 new_text += new_char;
880                 label->set_text (new_text);
881                 key_entry_state++;
882         }
883
884         if (key_entry_state == field_length[field]) {
885                 move_on = true;
886         }
887         
888         if (move_on) {
889
890                 if (key_entry_state) {
891       
892                         switch (field) {
893                         case SMPTE_Hours:
894                         case SMPTE_Minutes:
895                         case SMPTE_Seconds:
896                         case SMPTE_Frames:
897                                 // Check SMPTE fields for sanity (may also adjust fields)
898                                 smpte_sanitize_display();
899                                 break;
900                         case Bars:
901                         case Beats:
902                         case Ticks:
903                                 // Bars should never be, unless this clock is for a duration
904                                 if (atoi(bars_label.get_text()) == 0 && !is_duration) {
905                                         bars_label.set_text("001");
906                                 }
907                                 //  beats should never be 0, unless this clock is for a duration
908                                 if (atoi(beats_label.get_text()) == 0 && !is_duration) {
909                                         beats_label.set_text("01");
910                                 }
911                                 break;
912                         default:
913                                 break;
914                         }
915                         
916                         ValueChanged(); /* EMIT_SIGNAL */
917                 }
918                 
919                 /* move on to the next field.
920                  */
921                 
922                 switch (field) {
923                         
924                         /* SMPTE */
925                         
926                 case SMPTE_Hours:
927                         minutes_ebox.grab_focus ();
928                         break;
929                 case SMPTE_Minutes:
930                         seconds_ebox.grab_focus ();
931                         break;
932                 case SMPTE_Seconds:
933                         frames_ebox.grab_focus ();
934                         break;
935                 case SMPTE_Frames:
936                         clock_base.grab_focus ();
937                         break;
938
939                 /* audio frames */
940                 case AudioFrames:
941                         clock_base.grab_focus ();
942                         break;
943
944                 /* Min:Sec */
945
946                 case MS_Hours:
947                         ms_minutes_ebox.grab_focus ();
948                         break;
949                 case MS_Minutes:
950                         ms_seconds_ebox.grab_focus ();
951                         break;
952                 case MS_Seconds:
953                         clock_base.grab_focus ();
954                         break;
955
956                 /* BBT */
957
958                 case Bars:
959                         beats_ebox.grab_focus ();
960                         break;
961                 case Beats:
962                         ticks_ebox.grab_focus ();
963                         break;
964                 case Ticks:
965                         clock_base.grab_focus ();
966                         break;
967
968                 default:
969                         break;
970                 }
971
972         }
973
974         //if user hit Enter, lose focus
975         switch (ev->keyval) {
976         case GDK_Return:
977         case GDK_KP_Enter:
978                 clock_base.grab_focus ();
979         }
980
981         return true;
982 }
983
984 bool
985 AudioClock::field_focus_in_event (GdkEventFocus *ev, Field field)
986 {
987         key_entry_state = 0;
988
989         Keyboard::magic_widget_grab_focus ();
990
991         switch (field) {
992         case SMPTE_Hours:
993                 hours_ebox.set_flags (Gtk::HAS_FOCUS);
994                 hours_ebox.set_state (Gtk::STATE_ACTIVE);
995                 break;
996         case SMPTE_Minutes:
997                 minutes_ebox.set_flags (Gtk::HAS_FOCUS);
998                 minutes_ebox.set_state (Gtk::STATE_ACTIVE);
999                 break;
1000         case SMPTE_Seconds:
1001                 seconds_ebox.set_flags (Gtk::HAS_FOCUS);
1002                 seconds_ebox.set_state (Gtk::STATE_ACTIVE);
1003                 break;
1004         case SMPTE_Frames:
1005                 frames_ebox.set_flags (Gtk::HAS_FOCUS);
1006                 frames_ebox.set_state (Gtk::STATE_ACTIVE);
1007                 break;
1008
1009         case AudioFrames:
1010                 audio_frames_ebox.set_flags (Gtk::HAS_FOCUS);
1011                 audio_frames_ebox.set_state (Gtk::STATE_ACTIVE);
1012                 break;
1013
1014         case MS_Hours:
1015                 ms_hours_ebox.set_flags (Gtk::HAS_FOCUS);
1016                 ms_hours_ebox.set_state (Gtk::STATE_ACTIVE);
1017                 break;
1018         case MS_Minutes:
1019                 ms_minutes_ebox.set_flags (Gtk::HAS_FOCUS);
1020                 ms_minutes_ebox.set_state (Gtk::STATE_ACTIVE);
1021                 break;
1022         case MS_Seconds:
1023                 ms_seconds_ebox.set_flags (Gtk::HAS_FOCUS);
1024                 ms_seconds_ebox.set_state (Gtk::STATE_ACTIVE);
1025                 break;
1026         case Bars:
1027                 bars_ebox.set_flags (Gtk::HAS_FOCUS);
1028                 bars_ebox.set_state (Gtk::STATE_ACTIVE);
1029                 break;
1030         case Beats:
1031                 beats_ebox.set_flags (Gtk::HAS_FOCUS);
1032                 beats_ebox.set_state (Gtk::STATE_ACTIVE);
1033                 break;
1034         case Ticks:
1035                 ticks_ebox.set_flags (Gtk::HAS_FOCUS);
1036                 ticks_ebox.set_state (Gtk::STATE_ACTIVE);
1037                 break;
1038         }
1039
1040         return false;
1041 }
1042
1043 bool
1044 AudioClock::field_focus_out_event (GdkEventFocus *ev, Field field)
1045 {
1046         switch (field) {
1047
1048         case SMPTE_Hours:
1049                 hours_ebox.unset_flags (Gtk::HAS_FOCUS);
1050                 hours_ebox.set_state (Gtk::STATE_NORMAL);
1051                 break;
1052         case SMPTE_Minutes:
1053                 minutes_ebox.unset_flags (Gtk::HAS_FOCUS);
1054                 minutes_ebox.set_state (Gtk::STATE_NORMAL);
1055                 break;
1056         case SMPTE_Seconds:
1057                 seconds_ebox.unset_flags (Gtk::HAS_FOCUS);
1058                 seconds_ebox.set_state (Gtk::STATE_NORMAL);
1059                 break;
1060         case SMPTE_Frames:
1061                 frames_ebox.unset_flags (Gtk::HAS_FOCUS);
1062                 frames_ebox.set_state (Gtk::STATE_NORMAL);
1063                 break;
1064
1065         case AudioFrames:
1066                 audio_frames_ebox.unset_flags (Gtk::HAS_FOCUS);
1067                 audio_frames_ebox.set_state (Gtk::STATE_NORMAL);
1068                 break;
1069
1070         case MS_Hours:
1071                 ms_hours_ebox.unset_flags (Gtk::HAS_FOCUS);
1072                 ms_hours_ebox.set_state (Gtk::STATE_NORMAL);
1073                 break;
1074         case MS_Minutes:
1075                 ms_minutes_ebox.unset_flags (Gtk::HAS_FOCUS);
1076                 ms_minutes_ebox.set_state (Gtk::STATE_NORMAL);
1077                 break;
1078         case MS_Seconds:
1079                 ms_seconds_ebox.unset_flags (Gtk::HAS_FOCUS);
1080                 ms_seconds_ebox.set_state (Gtk::STATE_NORMAL);
1081                 break;
1082
1083         case Bars:
1084                 bars_ebox.unset_flags (Gtk::HAS_FOCUS);
1085                 bars_ebox.set_state (Gtk::STATE_NORMAL);
1086                 break;
1087         case Beats:
1088                 beats_ebox.unset_flags (Gtk::HAS_FOCUS);
1089                 beats_ebox.set_state (Gtk::STATE_NORMAL);
1090                 break;
1091         case Ticks:
1092                 ticks_ebox.unset_flags (Gtk::HAS_FOCUS);
1093                 ticks_ebox.set_state (Gtk::STATE_NORMAL);
1094                 break;
1095         }
1096
1097         Keyboard::magic_widget_drop_focus ();
1098
1099         return false;
1100 }
1101
1102 bool
1103 AudioClock::field_button_release_event (GdkEventButton *ev, Field field)
1104 {
1105         if (dragging) {
1106                 gdk_pointer_ungrab (GDK_CURRENT_TIME);
1107                 dragging = false;
1108                 if (ev->y > drag_start_y+1 || ev->y < drag_start_y-1 || Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)){
1109                         // we actually dragged so return without setting editing focus, or we shift clicked
1110                         return true;
1111                 }
1112         }
1113
1114         if (!editable) {
1115                 if (ops_menu == 0) {
1116                         build_ops_menu ();
1117                 }
1118                 ops_menu->popup (1, ev->time);
1119                 return true;
1120         }
1121
1122         if (Keyboard::is_context_menu_event (ev)) {
1123                 if (ops_menu == 0) {
1124                         build_ops_menu ();
1125                 }
1126                 ops_menu->popup (1, ev->time);
1127                 return true;
1128         } 
1129
1130         switch (ev->button) {
1131         case 1:
1132                 switch (field) {
1133                 case SMPTE_Hours:
1134                         hours_ebox.grab_focus();
1135                         break;
1136                 case SMPTE_Minutes:
1137                         minutes_ebox.grab_focus();
1138                         break;
1139                 case SMPTE_Seconds:
1140                         seconds_ebox.grab_focus();
1141                         break;
1142                 case SMPTE_Frames:
1143                         frames_ebox.grab_focus();
1144                         break;
1145
1146                 case AudioFrames:
1147                         audio_frames_ebox.grab_focus();
1148                         break;
1149                         
1150                 case MS_Hours:
1151                         ms_hours_ebox.grab_focus();
1152                         break;
1153                 case MS_Minutes:
1154                         ms_minutes_ebox.grab_focus();
1155                         break;
1156                 case MS_Seconds:
1157                         ms_seconds_ebox.grab_focus();
1158                         break;
1159                         
1160                 case Bars:
1161                         bars_ebox.grab_focus ();
1162                         break;
1163                 case Beats:
1164                         beats_ebox.grab_focus ();
1165                         break;
1166                 case Ticks:
1167                         ticks_ebox.grab_focus ();
1168                         break;
1169                 }
1170                 break;
1171                 
1172         default:
1173                 break;
1174         }
1175
1176         return true;
1177 }
1178
1179 bool
1180 AudioClock::field_button_press_event (GdkEventButton *ev, Field field)
1181 {
1182         if (session == 0) return false;
1183
1184         nframes_t frames = 0;
1185
1186         switch (ev->button) {
1187         case 1:
1188                 if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
1189                         set (frames, true);
1190                         ValueChanged (); /* EMIT_SIGNAL */
1191                                         }
1192         
1193                 /* make absolutely sure that the pointer is grabbed */
1194                 gdk_pointer_grab(ev->window,false ,
1195                                  GdkEventMask( Gdk::POINTER_MOTION_MASK | Gdk::BUTTON_PRESS_MASK |Gdk::BUTTON_RELEASE_MASK), 
1196                                  NULL,NULL,ev->time);
1197                 dragging = true;
1198                 drag_accum = 0;
1199                 drag_start_y = ev->y;
1200                 drag_y = ev->y;
1201                 break;
1202
1203         case 2:
1204                 if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
1205                         set (frames, true);
1206                         ValueChanged (); /* EMIT_SIGNAL */
1207                 }
1208                 break;
1209
1210         case 3:
1211                 /* used for context sensitive menu */
1212                 return false;
1213                 break;
1214
1215         default:
1216                 return false;
1217                 break;
1218         }
1219         
1220         return true;
1221 }
1222
1223 bool
1224 AudioClock::field_button_scroll_event (GdkEventScroll *ev, Field field)
1225 {
1226         if (session == 0) {
1227                 return false;
1228         }
1229
1230         nframes_t frames = 0;
1231
1232         switch (ev->direction) {
1233
1234         case GDK_SCROLL_UP:
1235                frames = get_frames (field);
1236                if (frames != 0) {
1237                       if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
1238                              frames *= 10;
1239                       }
1240                       set (current_time() + frames, true);
1241                       ValueChanged (); /* EMIT_SIGNAL */
1242                }
1243                break;
1244
1245         case GDK_SCROLL_DOWN:
1246                frames = get_frames (field);
1247                if (frames != 0) {
1248                       if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
1249                              frames *= 10;
1250                       }
1251                       
1252                       if ((double)current_time() - (double)frames < 0.0) {
1253                              set (0, true);
1254                       } else {
1255                              set (current_time() - frames, true);
1256                       }
1257                       
1258                       ValueChanged (); /* EMIT_SIGNAL */
1259                }
1260                break;
1261
1262         default:
1263                 return false;
1264                 break;
1265         }
1266         
1267         return true;
1268 }
1269
1270 bool
1271 AudioClock::field_motion_notify_event (GdkEventMotion *ev, Field field)
1272 {
1273         if (session == 0 || !dragging) {
1274                 return false;
1275         }
1276         
1277         float pixel_frame_scale_factor = 0.2f;
1278
1279 /*
1280         if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier))  {
1281                 pixel_frame_scale_factor = 0.1f;
1282         }
1283
1284
1285         if (Keyboard::modifier_state_contains (ev->state, 
1286                                                Keyboard::PrimaryModifier|Keyboard::SecondaryModifier)) {
1287
1288                 pixel_frame_scale_factor = 0.025f;
1289         }
1290 */
1291         double y_delta = ev->y - drag_y;
1292
1293         drag_accum +=  y_delta*pixel_frame_scale_factor;
1294
1295         drag_y = ev->y;
1296
1297         if (trunc(drag_accum) != 0) {
1298
1299                 nframes_t frames;
1300                 nframes_t pos ;
1301                 int dir;
1302                 dir = (drag_accum < 0 ? 1:-1);
1303                 pos = current_time();
1304                 frames = get_frames (field,pos,dir);
1305                 
1306                 if (frames  != 0 &&  frames * drag_accum < current_time()) {
1307                 
1308                         set ((nframes_t) floor (pos - drag_accum * frames), false); // minus because up is negative in computer-land
1309                 
1310                 } else {
1311                         set (0 , false);
1312                 
1313                 }
1314
1315                 drag_accum= 0;
1316                 ValueChanged();  /* EMIT_SIGNAL */      
1317                 
1318
1319         }
1320
1321         return true;
1322 }
1323
1324 nframes_t
1325 AudioClock::get_frames (Field field,nframes_t pos,int dir)
1326 {
1327
1328         nframes_t frames = 0;
1329         BBT_Time bbt;
1330         switch (field) {
1331         case SMPTE_Hours:
1332                 frames = (nframes_t) floor (3600.0 * session->frame_rate());
1333                 break;
1334         case SMPTE_Minutes:
1335                 frames = (nframes_t) floor (60.0 * session->frame_rate());
1336                 break;
1337         case SMPTE_Seconds:
1338                 frames = session->frame_rate();
1339                 break;
1340         case SMPTE_Frames:
1341                 frames = (nframes_t) floor (session->frame_rate() / session->smpte_frames_per_second());
1342                 break;
1343
1344         case AudioFrames:
1345                 frames = 1;
1346                 break;
1347
1348         case MS_Hours:
1349                 frames = (nframes_t) floor (3600.0 * session->frame_rate());
1350                 break;
1351         case MS_Minutes:
1352                 frames = (nframes_t) floor (60.0 * session->frame_rate());
1353                 break;
1354         case MS_Seconds:
1355                 frames = session->frame_rate();
1356                 break;
1357
1358         case Bars:
1359                 bbt.bars = 1;
1360                 bbt.beats = 0;
1361                 bbt.ticks = 0;
1362                 frames = session->tempo_map().bbt_duration_at(pos,bbt,dir);
1363                 break;
1364         case Beats:
1365                 bbt.bars = 0;
1366                 bbt.beats = 1;
1367                 bbt.ticks = 0;
1368                 frames = session->tempo_map().bbt_duration_at(pos,bbt,dir);
1369                 break;
1370         case Ticks:
1371                 bbt.bars = 0;
1372                 bbt.beats = 0;
1373                 bbt.ticks = 1;
1374                 frames = session->tempo_map().bbt_duration_at(pos,bbt,dir);
1375                 break;
1376         }
1377
1378         return frames;
1379 }
1380
1381 nframes_t
1382 AudioClock::current_time (nframes_t pos) const
1383 {
1384         nframes_t ret = 0;
1385
1386         switch (_mode) {
1387         case SMPTE:
1388                 ret = smpte_frame_from_display ();
1389                 break;
1390         case BBT:
1391                 ret = bbt_frame_from_display (pos);
1392                 break;
1393
1394         case MinSec:
1395                 ret = minsec_frame_from_display ();
1396                 break;
1397
1398         case Frames:
1399                 ret = audio_frame_from_display ();
1400                 break;
1401
1402         case Off:
1403                 break;
1404         }
1405
1406         return ret;
1407 }
1408
1409 nframes_t
1410 AudioClock::current_duration (nframes_t pos) const
1411 {
1412         nframes_t ret = 0;
1413
1414         switch (_mode) {
1415         case SMPTE:
1416                 ret = smpte_frame_from_display ();
1417                 break;
1418         case BBT:
1419                 ret = bbt_frame_duration_from_display (pos);
1420                 break;
1421
1422         case MinSec:
1423                 ret = minsec_frame_from_display ();
1424                 break;
1425
1426         case Frames:
1427                 ret = audio_frame_from_display ();
1428                 break;
1429
1430         case Off:
1431                 break;
1432         }
1433
1434         return ret;
1435 }
1436
1437 void
1438 AudioClock::smpte_sanitize_display()
1439 {
1440         // Check SMPTE fields for sanity, possibly adjusting values
1441         if (atoi(minutes_label.get_text()) > 59) {
1442                 minutes_label.set_text("59");
1443         }
1444         
1445         if (atoi(seconds_label.get_text()) > 59) {
1446                 seconds_label.set_text("59");
1447         }
1448         
1449         switch ((long)rint(session->smpte_frames_per_second())) {
1450         case 24:
1451                 if (atoi(frames_label.get_text()) > 23) {
1452                         frames_label.set_text("23");
1453                 }
1454                 break;
1455         case 25:
1456                 if (atoi(frames_label.get_text()) > 24) {
1457                         frames_label.set_text("24");
1458                 }
1459                 break;
1460         case 30:
1461                 if (atoi(frames_label.get_text()) > 29) {
1462                         frames_label.set_text("29");
1463                 }
1464                 break;
1465         default:
1466                 break;
1467         }
1468         
1469         if (session->smpte_drop_frames()) {
1470                 if ((atoi(minutes_label.get_text()) % 10) && (atoi(seconds_label.get_text()) == 0) && (atoi(frames_label.get_text()) < 2)) {
1471                         frames_label.set_text("02");
1472                 }
1473         }
1474 }
1475
1476 nframes_t
1477 AudioClock::smpte_frame_from_display () const
1478 {
1479         if (session == 0) {
1480                 return 0;
1481         }
1482         
1483         SMPTE::Time smpte;
1484         nframes_t sample;
1485         
1486         smpte.hours = atoi (hours_label.get_text());
1487         smpte.minutes = atoi (minutes_label.get_text());
1488         smpte.seconds = atoi (seconds_label.get_text());
1489         smpte.frames = atoi (frames_label.get_text());
1490         smpte.rate = session->smpte_frames_per_second();
1491         smpte.drop= session->smpte_drop_frames();
1492
1493         session->smpte_to_sample( smpte, sample, false /* use_offset */, false /* use_subframes */ );
1494         
1495
1496 #if 0
1497 #define SMPTE_SAMPLE_TEST_1
1498 #define SMPTE_SAMPLE_TEST_2
1499 #define SMPTE_SAMPLE_TEST_3
1500 #define SMPTE_SAMPLE_TEST_4
1501 #define SMPTE_SAMPLE_TEST_5
1502 #define SMPTE_SAMPLE_TEST_6
1503 #define SMPTE_SAMPLE_TEST_7
1504
1505         // Testcode for smpte<->sample conversions (P.S.)
1506         SMPTE::Time smpte1;
1507         nframes_t sample1;
1508         nframes_t oldsample = 0;
1509         SMPTE::Time smpte2;
1510         nframes_t sample_increment;
1511
1512         sample_increment = (long)rint(session->frame_rate() / session->smpte_frames_per_second);
1513
1514 #ifdef SMPTE_SAMPLE_TEST_1
1515         // Test 1: use_offset = false, use_subframes = false
1516         cout << "use_offset = false, use_subframes = false" << endl;
1517         for (int i = 0; i < 108003; i++) {
1518                 session->smpte_to_sample( smpte1, sample1, false /* use_offset */, false /* use_subframes */ );
1519                 session->sample_to_smpte( sample1, smpte2, false /* use_offset */, false /* use_subframes */ );
1520
1521                 if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
1522                         cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1523                         cout << "smpte1: " << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1524                         cout << "sample: " << sample1 << endl;
1525                         cout << "sample: " << sample1 << " -> ";
1526                         cout << "smpte2: " << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1527                         break;
1528                 }
1529     
1530                 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1531                         cout << "ERROR: smpte2 not equal smpte1" << endl;
1532                         cout << "smpte1: " << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1533                         cout << "sample: " << sample1 << endl;
1534                         cout << "sample: " << sample1 << " -> ";
1535                         cout << "smpte2: " << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1536                         break;
1537                 }
1538                 oldsample = sample1;
1539                 session->smpte_increment( smpte1 );
1540         }
1541
1542         cout << "sample_increment: " << sample_increment << endl;
1543         cout << "sample: " << sample1 << " -> ";
1544         cout << "smpte: " << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1545 #endif
1546
1547 #ifdef SMPTE_SAMPLE_TEST_2
1548         // Test 2: use_offset = true, use_subframes = false
1549         cout << "use_offset = true, use_subframes = false" << endl;
1550   
1551         smpte1.hours = 0;
1552         smpte1.minutes = 0;
1553         smpte1.seconds = 0;
1554         smpte1.frames = 0;
1555         smpte1.subframes = 0;
1556         sample1 = oldsample = 0;
1557
1558         session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1559         cout << "Starting at sample: " << sample1 << " -> ";
1560         cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1561
1562         for (int i = 0; i < 108003; i++) {
1563                 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1564                 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1565
1566 //     cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1567 //     cout << "sample: " << sample1 << endl;
1568 //     cout << "sample: " << sample1 << " -> ";
1569 //     cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1570     
1571                 if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
1572                         cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << 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;
1577                         break;
1578                 }
1579     
1580                 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1581                         cout << "ERROR: smpte2 not equal smpte1" << endl;
1582                         cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1583                         cout << "sample: " << sample1 << endl;
1584                         cout << "sample: " << sample1 << " -> ";
1585                         cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1586                         break;
1587                 }
1588                 oldsample = sample1;
1589                 session->smpte_increment( smpte1 );
1590         }
1591
1592         cout << "sample_increment: " << sample_increment << endl;
1593         cout << "sample: " << sample1 << " -> ";
1594         cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1595 #endif
1596
1597 #ifdef SMPTE_SAMPLE_TEST_3
1598         // Test 3: use_offset = true, use_subframes = false, decrement
1599         cout << "use_offset = true, use_subframes = false, decrement" << endl;  
1600
1601         session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1602         cout << "Starting at sample: " << sample1 << " -> ";
1603         cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1604
1605         for (int i = 0; i < 108003; i++) {
1606                 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1607                 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1608
1609 //     cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1610 //     cout << "sample: " << sample1 << endl;
1611 //     cout << "sample: " << sample1 << " -> ";
1612 //     cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1613     
1614                 if ((i > 0) && ( ((oldsample - sample1) != sample_increment) && ((oldsample - sample1) != (sample_increment + 1)) && ((oldsample - sample1) != (sample_increment - 1)))) {
1615                         cout << "ERROR: sample increment not right: " << (oldsample - sample1) << " != " << sample_increment << endl;
1616                         cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1617                         cout << "sample: " << sample1 << endl;
1618                         cout << "sample: " << sample1 << " -> ";
1619                         cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1620                         break;
1621                 }
1622     
1623                 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1624                         cout << "ERROR: smpte2 not equal smpte1" << endl;
1625                         cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1626                         cout << "sample: " << sample1 << endl;
1627                         cout << "sample: " << sample1 << " -> ";
1628                         cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1629                         break;
1630                 }
1631                 oldsample = sample1;
1632                 session->smpte_decrement( smpte1 );
1633         }
1634
1635         cout << "sample_decrement: " << sample_increment << endl;
1636         cout << "sample: " << sample1 << " -> ";
1637         cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1638 #endif
1639
1640
1641 #ifdef SMPTE_SAMPLE_TEST_4
1642         // Test 4: use_offset = true, use_subframes = true
1643         cout << "use_offset = true, use_subframes = true" << endl;
1644   
1645         for (long sub = 5; sub < 80; sub += 5) {
1646                 smpte1.hours = 0;
1647                 smpte1.minutes = 0;
1648                 smpte1.seconds = 0;
1649                 smpte1.frames = 0;
1650                 smpte1.subframes = 0;
1651                 sample1 = oldsample = (sample_increment * sub) / 80;
1652     
1653                 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, true /* use_subframes */ );
1654     
1655                 cout << "starting at sample: " << sample1 << " -> ";
1656                 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1657     
1658                 for (int i = 0; i < 108003; i++) {
1659                         session->smpte_to_sample( smpte1, sample1, true /* use_offset */, true /* use_subframes */ );
1660                         session->sample_to_smpte( sample1, smpte2, true /* use_offset */, true /* use_subframes */ );
1661       
1662                         if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
1663                                 cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1664                                 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1665                                 cout << "sample: " << sample1 << endl;
1666                                 cout << "sample: " << sample1 << " -> ";
1667                                 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1668                                 //break;
1669                         }
1670       
1671                         if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames || smpte2.subframes != smpte1.subframes) {
1672                                 cout << "ERROR: smpte2 not equal smpte1" << endl;
1673                                 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1674                                 cout << "sample: " << sample1 << endl;
1675                                 cout << "sample: " << sample1 << " -> ";
1676                                 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1677                                 break;
1678                         }
1679                         oldsample = sample1;
1680                         session->smpte_increment( smpte1 );
1681                 }
1682     
1683                 cout << "sample_increment: " << sample_increment << endl;
1684                 cout << "sample: " << sample1 << " -> ";
1685                 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1686
1687                 for (int i = 0; i < 108003; i++) {
1688                         session->smpte_to_sample( smpte1, sample1, true /* use_offset */, true /* use_subframes */ );
1689                         session->sample_to_smpte( sample1, smpte2, true /* use_offset */, true /* use_subframes */ );
1690       
1691                         if ((i > 0) && ( ((oldsample - sample1) != sample_increment) && ((oldsample - sample1) != (sample_increment + 1)) && ((oldsample - sample1) != (sample_increment - 1)))) {
1692                                 cout << "ERROR: sample increment not right: " << (oldsample - sample1) << " != " << sample_increment << endl;
1693                                 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1694                                 cout << "sample: " << sample1 << endl;
1695                                 cout << "sample: " << sample1 << " -> ";
1696                                 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1697                                 //break;
1698                         }
1699       
1700                         if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames || smpte2.subframes != smpte1.subframes) {
1701                                 cout << "ERROR: smpte2 not equal smpte1" << endl;
1702                                 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1703                                 cout << "sample: " << sample1 << endl;
1704                                 cout << "sample: " << sample1 << " -> ";
1705                                 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1706                                 break;
1707                         }
1708                         oldsample = sample1;
1709                         session->smpte_decrement( smpte1 );
1710                 }
1711     
1712                 cout << "sample_decrement: " << sample_increment << endl;
1713                 cout << "sample: " << sample1 << " -> ";
1714                 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1715         }
1716 #endif
1717
1718
1719 #ifdef SMPTE_SAMPLE_TEST_5
1720         // Test 5: use_offset = true, use_subframes = false, increment seconds
1721         cout << "use_offset = true, use_subframes = false, increment seconds" << endl;
1722   
1723         smpte1.hours = 0;
1724         smpte1.minutes = 0;
1725         smpte1.seconds = 0;
1726         smpte1.frames = 0;
1727         smpte1.subframes = 0;
1728         sample1 = oldsample = 0;
1729         sample_increment = session->frame_rate();
1730
1731         session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1732         cout << "Starting at sample: " << sample1 << " -> ";
1733         cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1734
1735         for (int i = 0; i < 3600; i++) {
1736                 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1737                 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1738
1739 //     cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1740 //     cout << "sample: " << sample1 << endl;
1741 //     cout << "sample: " << sample1 << " -> ";
1742 //     cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1743     
1744 //     if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1745 //     {
1746 //       cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1747 //       break;
1748 //     }
1749     
1750                 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1751                         cout << "ERROR: smpte2 not equal smpte1" << endl;
1752                         cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1753                         cout << "sample: " << sample1 << endl;
1754                         cout << "sample: " << sample1 << " -> ";
1755                         cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1756                         break;
1757                 }
1758                 oldsample = sample1;
1759                 session->smpte_increment_seconds( smpte1 );
1760         }
1761
1762         cout << "sample_increment: " << sample_increment << endl;
1763         cout << "sample: " << sample1 << " -> ";
1764         cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1765 #endif
1766
1767
1768 #ifdef SMPTE_SAMPLE_TEST_6
1769         // Test 6: use_offset = true, use_subframes = false, increment minutes
1770         cout << "use_offset = true, use_subframes = false, increment minutes" << endl;
1771   
1772         smpte1.hours = 0;
1773         smpte1.minutes = 0;
1774         smpte1.seconds = 0;
1775         smpte1.frames = 0;
1776         smpte1.subframes = 0;
1777         sample1 = oldsample = 0;
1778         sample_increment = session->frame_rate() * 60;
1779
1780         session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1781         cout << "Starting at sample: " << sample1 << " -> ";
1782         cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1783
1784         for (int i = 0; i < 60; i++) {
1785                 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1786                 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1787
1788 //     cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1789 //     cout << "sample: " << sample1 << endl;
1790 //     cout << "sample: " << sample1 << " -> ";
1791 //     cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1792     
1793 //     if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1794 //     {
1795 //       cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1796 //       break;
1797 //     }
1798     
1799                 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1800                         cout << "ERROR: smpte2 not equal smpte1" << endl;
1801                         cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1802                         cout << "sample: " << sample1 << endl;
1803                         cout << "sample: " << sample1 << " -> ";
1804                         cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1805                         break;
1806                 }
1807                 oldsample = sample1;
1808                 session->smpte_increment_minutes( smpte1 );
1809         }
1810
1811         cout << "sample_increment: " << sample_increment << endl;
1812         cout << "sample: " << sample1 << " -> ";
1813         cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1814 #endif
1815
1816 #ifdef SMPTE_SAMPLE_TEST_7
1817         // Test 7: use_offset = true, use_subframes = false, increment hours
1818         cout << "use_offset = true, use_subframes = false, increment hours" << endl;
1819   
1820         smpte1.hours = 0;
1821         smpte1.minutes = 0;
1822         smpte1.seconds = 0;
1823         smpte1.frames = 0;
1824         smpte1.subframes = 0;
1825         sample1 = oldsample = 0;
1826         sample_increment = session->frame_rate() * 60 * 60;
1827
1828         session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1829         cout << "Starting at sample: " << sample1 << " -> ";
1830         cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1831
1832         for (int i = 0; i < 10; i++) {
1833                 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1834                 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1835
1836 //     cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1837 //     cout << "sample: " << sample1 << endl;
1838 //     cout << "sample: " << sample1 << " -> ";
1839 //     cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1840     
1841 //     if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1842 //     {
1843 //       cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1844 //       break;
1845 //     }
1846     
1847                 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1848                         cout << "ERROR: smpte2 not equal smpte1" << endl;
1849                         cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1850                         cout << "sample: " << sample1 << endl;
1851                         cout << "sample: " << sample1 << " -> ";
1852                         cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1853                         break;
1854                 }
1855                 oldsample = sample1;
1856                 session->smpte_increment_hours( smpte1 );
1857         }
1858
1859         cout << "sample_increment: " << sample_increment << endl;
1860         cout << "sample: " << sample1 << " -> ";
1861         cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1862 #endif
1863
1864 #endif  
1865
1866         return sample;
1867 }
1868
1869 nframes_t
1870 AudioClock::minsec_frame_from_display () const
1871 {
1872         if (session == 0) {
1873                 return 0;
1874         }
1875
1876         int hrs = atoi (ms_hours_label.get_text());
1877         int mins = atoi (ms_minutes_label.get_text());
1878         float secs = atof (ms_seconds_label.get_text());
1879
1880         nframes_t sr = session->frame_rate();
1881
1882         return (nframes_t) floor ((hrs * 60.0f * 60.0f * sr) + (mins * 60.0f * sr) + (secs * sr));
1883 }
1884
1885 nframes_t
1886 AudioClock::bbt_frame_from_display (nframes_t pos) const
1887 {
1888         if (session == 0) {
1889                 error << "AudioClock::current_time() called with BBT mode but without session!" << endmsg;
1890                 return 0;
1891         }
1892
1893         AnyTime any;
1894         any.type = AnyTime::BBT;
1895
1896         any.bbt.bars = atoi (bars_label.get_text());
1897         any.bbt.beats = atoi (beats_label.get_text());
1898         any.bbt.ticks = atoi (ticks_label.get_text());
1899
1900         nframes_t ret = session->convert_to_frames_at (pos, any);
1901
1902         return ret;
1903 }
1904
1905
1906 nframes_t
1907 AudioClock::bbt_frame_duration_from_display (nframes_t pos) const
1908 {
1909         if (session == 0) {
1910                 error << "AudioClock::current_time() called with BBT mode but without session!" << endmsg;
1911                 return 0;
1912         }
1913
1914         BBT_Time bbt;
1915
1916
1917         bbt.bars = atoi (bars_label.get_text());
1918         bbt.beats = atoi (beats_label.get_text());
1919         bbt.ticks = atoi (ticks_label.get_text());
1920         
1921         return session->tempo_map().bbt_duration_at(pos,bbt,1);
1922 }
1923
1924 nframes_t
1925 AudioClock::audio_frame_from_display () const
1926 {
1927         return (nframes_t) atoi (audio_frames_label.get_text());
1928 }
1929
1930 void
1931 AudioClock::build_ops_menu ()
1932 {
1933         using namespace Menu_Helpers;
1934         ops_menu = new Menu;
1935         MenuList& ops_items = ops_menu->items();
1936         ops_menu->set_name ("ArdourContextMenu");
1937         
1938         if (!Profile->get_sae()) {
1939                 ops_items.push_back (MenuElem (_("Timecode"), bind (mem_fun(*this, &AudioClock::set_mode), SMPTE)));
1940         }
1941         ops_items.push_back (MenuElem (_("Bars:Beats"), bind (mem_fun(*this, &AudioClock::set_mode), BBT)));
1942         ops_items.push_back (MenuElem (_("Minutes:Seconds"), bind (mem_fun(*this, &AudioClock::set_mode), MinSec)));
1943         ops_items.push_back (MenuElem (_("Samples"), bind (mem_fun(*this, &AudioClock::set_mode), Frames)));
1944         ops_items.push_back (MenuElem (_("Off"), bind (mem_fun(*this, &AudioClock::set_mode), Off)));
1945 }
1946
1947 void
1948 AudioClock::set_mode (Mode m)
1949 {
1950         /* slightly tricky: this is called from within the ARDOUR_UI
1951            constructor by some of its clock members. at that time
1952            the instance pointer is unset, so we have to be careful.
1953            the main idea is to drop keyboard focus in case we had
1954            started editing the clock and then we switch clock mode.
1955         */
1956
1957         clock_base.grab_focus ();
1958                 
1959         if (_mode == m) {
1960                 return;
1961         }
1962         
1963         clock_base.remove ();
1964         
1965         _mode = m;
1966
1967         switch (_mode) {
1968         case SMPTE:
1969                 clock_base.add (smpte_packer_hbox);
1970                 break;
1971
1972         case BBT:
1973                 clock_base.add (bbt_packer_hbox);
1974                 break;
1975
1976         case MinSec:
1977                 clock_base.add (minsec_packer_hbox);
1978                 break;
1979
1980         case Frames:
1981                 clock_base.add (frames_packer_hbox);
1982                 break;
1983
1984         case Off:
1985                 clock_base.add (off_hbox);
1986                 break;
1987         }
1988
1989         set_size_requests ();
1990         
1991         set (last_when, true);
1992         clock_base.show_all ();
1993         key_entry_state = 0;
1994
1995         if (!is_transient) {
1996                 ModeChanged (); /* EMIT SIGNAL */
1997                 mode_changed (); /* EMIT SIGNAL */
1998         }
1999 }
2000
2001 void
2002 AudioClock::set_size_requests ()
2003 {
2004         /* note that in some fonts, "88" is narrower than "00", hence the 2 pixel padding */
2005
2006         switch (_mode) {
2007         case SMPTE:
2008                 Gtkmm2ext::set_size_request_to_display_given_text (hours_label, "-00", 5, 5);
2009                 Gtkmm2ext::set_size_request_to_display_given_text (minutes_label, "00", 5, 5);
2010                 Gtkmm2ext::set_size_request_to_display_given_text (seconds_label, "00", 5, 5);
2011                 Gtkmm2ext::set_size_request_to_display_given_text (frames_label, "00", 5, 5);
2012                 break;
2013
2014         case BBT:
2015                 Gtkmm2ext::set_size_request_to_display_given_text (bars_label, "-000", 5, 5);
2016                 Gtkmm2ext::set_size_request_to_display_given_text (beats_label, "00", 5, 5);
2017                 Gtkmm2ext::set_size_request_to_display_given_text (ticks_label, "0000", 5, 5);
2018                 break;
2019
2020         case MinSec:
2021                 Gtkmm2ext::set_size_request_to_display_given_text (ms_hours_label, "00", 5, 5);
2022                 Gtkmm2ext::set_size_request_to_display_given_text (ms_minutes_label, "00", 5, 5);
2023                 Gtkmm2ext::set_size_request_to_display_given_text (ms_seconds_label, "00.000", 5, 5);
2024                 break;
2025
2026         case Frames:
2027                 Gtkmm2ext::set_size_request_to_display_given_text (audio_frames_label, "0000000000", 5, 5);
2028                 break;
2029
2030         case Off:
2031                 Gtkmm2ext::set_size_request_to_display_given_text (off_hbox, "00000", 5, 5);
2032                 break;
2033                 
2034         }
2035 }
2036
2037 void
2038 AudioClock::set_bbt_reference (nframes64_t pos)
2039 {
2040         bbt_reference_time = pos;
2041 }