most of the 2.X->3.0 commit (up to rev 4299) except for gtk2_ardour/editor_canvas...
[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         /* handle a common case */
640         if (is_duration) {
641                 if (when == 0) {
642                         bbt.bars = 0;
643                         bbt.beats = 0;
644                         bbt.ticks = 0;  
645                 } else {
646                         session->tempo_map().bbt_time (when, bbt);
647                         bbt.bars--;
648                         bbt.beats--;
649                 }
650         } else {
651                 session->tempo_map().bbt_time (when, bbt);
652         }
653
654         sprintf (buf, "%03" PRIu32, bbt.bars);
655         if (force || bars_label.get_text () != buf) {
656                 bars_label.set_text (buf);
657         }
658         sprintf (buf, "%02" PRIu32, bbt.beats);
659         if (force || beats_label.get_text () != buf) {
660                 beats_label.set_text (buf);
661         }
662         sprintf (buf, "%04" PRIu32, bbt.ticks);
663         if (force || ticks_label.get_text () != buf) {
664                 ticks_label.set_text (buf);
665         }
666         
667         if (bbt_upper_info_label) {
668                 nframes64_t pos;
669
670                 if (bbt_reference_time < 0) {
671                         pos = when;
672                 } else {
673                         pos = bbt_reference_time;
674                 }
675
676                 TempoMap::Metric m (session->tempo_map().metric_at (pos));
677
678                 sprintf (buf, "%-5.2f", m.tempo().beats_per_minute());
679                 if (bbt_lower_info_label->get_text() != buf) {
680                         bbt_lower_info_label->set_text (buf);
681                 }
682                 sprintf (buf, "%g|%g", m.meter().beats_per_bar(), m.meter().note_divisor());
683                 if (bbt_upper_info_label->get_text() != buf) {
684                         bbt_upper_info_label->set_text (buf);
685                 }
686         }
687 }
688
689 void
690 AudioClock::set_session (Session *s)
691 {
692         session = s;
693
694         if (s) {
695
696                 XMLProperty* prop;
697                 XMLNode* node = session->extra_xml (X_("ClockModes"));
698                 AudioClock::Mode amode;
699                 
700                 if (node) {
701                         if ((prop = node->property (_name)) != 0) {
702                                 amode = AudioClock::Mode (string_2_enum (prop->value(), amode));
703                                 set_mode (amode);
704                         }
705                 }
706
707                 set (last_when, true);
708         }
709 }
710
711 void
712 AudioClock::focus ()
713 {
714         switch (_mode) {
715         case SMPTE:
716                 hours_ebox.grab_focus ();
717                 break;
718
719         case BBT:
720                 bars_ebox.grab_focus ();
721                 break;
722
723         case MinSec:
724                 ms_hours_ebox.grab_focus ();
725                 break;
726
727         case Frames:
728                 frames_ebox.grab_focus ();
729                 break;
730
731         case Off:
732                 break;
733         }
734 }
735
736
737 bool
738 AudioClock::field_key_press_event (GdkEventKey *ev, Field field)
739 {
740         /* all key activity is handled on key release */
741         return true;
742 }
743
744 bool
745 AudioClock::field_key_release_event (GdkEventKey *ev, Field field)
746 {
747         Label *label = 0;
748         string new_text;
749         char new_char = 0;
750         bool move_on = false;
751
752         switch (field) {
753         case SMPTE_Hours:
754                 label = &hours_label;
755                 break;
756         case SMPTE_Minutes:
757                 label = &minutes_label;
758                 break;
759         case SMPTE_Seconds:
760                 label = &seconds_label;
761                 break;
762         case SMPTE_Frames:
763                 label = &frames_label;
764                 break;
765
766         case AudioFrames:
767                 label = &audio_frames_label;
768                 break;
769
770         case MS_Hours:
771                 label = &ms_hours_label;
772                 break;
773         case MS_Minutes:
774                 label = &ms_minutes_label;
775                 break;
776         case MS_Seconds:
777                 label = &ms_seconds_label;
778                 break;
779
780         case Bars:
781                 label = &bars_label;
782                 break;
783         case Beats:
784                 label = &beats_label;
785                 break;
786         case Ticks:
787                 label = &ticks_label;
788                 break;
789         default:
790                 return false;
791         }
792
793         switch (ev->keyval) {
794         case GDK_0:
795         case GDK_KP_0:
796                 new_char = '0';
797                 break;
798         case GDK_1:
799         case GDK_KP_1:
800                 new_char = '1';
801                 break;
802         case GDK_2:
803         case GDK_KP_2:
804                 new_char = '2';
805                 break;
806         case GDK_3:
807         case GDK_KP_3:
808                 new_char = '3';
809                 break;
810         case GDK_4:
811         case GDK_KP_4:
812                 new_char = '4';
813                 break;
814         case GDK_5:
815         case GDK_KP_5:
816                 new_char = '5';
817                 break;
818         case GDK_6:
819         case GDK_KP_6:
820                 new_char = '6';
821                 break;
822         case GDK_7:
823         case GDK_KP_7:
824                 new_char = '7';
825                 break;
826         case GDK_8:
827         case GDK_KP_8:
828                 new_char = '8';
829                 break;
830         case GDK_9:
831         case GDK_KP_9:
832                 new_char = '9';
833                 break;
834
835         case GDK_period:
836         case GDK_KP_Decimal:
837                 if (_mode == MinSec && field == MS_Seconds) {
838                         new_char = '.';
839                 } else {
840                         return false;
841                 }
842                 break;
843
844         case GDK_Tab:
845         case GDK_Return:
846         case GDK_KP_Enter:
847                 move_on = true;
848                 break;
849
850         case GDK_Escape:
851                 key_entry_state = 0;
852                 clock_base.grab_focus ();
853                 ChangeAborted();  /*  EMIT SIGNAL  */
854                 return true;
855
856         default:
857                 return false;
858         }
859
860         if (!move_on) {
861
862                 if (key_entry_state == 0) {
863
864                         /* initialize with a fresh new string */
865
866                         if (field != AudioFrames) {
867                                 for (uint32_t xn = 0; xn < field_length[field] - 1; ++xn) {
868                                         new_text += '0';
869                                 }
870                         } else {
871                                 new_text = "";
872                         }
873
874                 } else {
875
876                         string existing = label->get_text();
877                         if (existing.length() >= field_length[field]) {
878                                 new_text = existing.substr (1, field_length[field] - 1);
879                         } else {
880                                 new_text = existing.substr (0, field_length[field] - 1);
881                         }
882                 }
883
884                 new_text += new_char;
885                 label->set_text (new_text);
886                 key_entry_state++;
887         }
888
889         if (key_entry_state == field_length[field]) {
890                 move_on = true;
891         }
892         
893         if (move_on) {
894
895                 if (key_entry_state) {
896       
897                         switch (field) {
898                         case SMPTE_Hours:
899                         case SMPTE_Minutes:
900                         case SMPTE_Seconds:
901                         case SMPTE_Frames:
902                                 // Check SMPTE fields for sanity (may also adjust fields)
903                                 smpte_sanitize_display();
904                                 break;
905                         case Bars:
906                         case Beats:
907                         case Ticks:
908                                 // Bars should never be, unless this clock is for a duration
909                                 if (atoi(bars_label.get_text()) == 0 && !is_duration) {
910                                         bars_label.set_text("001");
911                                 }
912                                 //  beats should never be 0, unless this clock is for a duration
913                                 if (atoi(beats_label.get_text()) == 0 && !is_duration) {
914                                         beats_label.set_text("01");
915                                 }
916                                 break;
917                         default:
918                                 break;
919                         }
920                         
921                         ValueChanged(); /* EMIT_SIGNAL */
922                 }
923                 
924                 /* move on to the next field.
925                  */
926                 
927                 switch (field) {
928                         
929                         /* SMPTE */
930                         
931                 case SMPTE_Hours:
932                         minutes_ebox.grab_focus ();
933                         break;
934                 case SMPTE_Minutes:
935                         seconds_ebox.grab_focus ();
936                         break;
937                 case SMPTE_Seconds:
938                         frames_ebox.grab_focus ();
939                         break;
940                 case SMPTE_Frames:
941                         clock_base.grab_focus ();
942                         break;
943
944                 /* audio frames */
945                 case AudioFrames:
946                         clock_base.grab_focus ();
947                         break;
948
949                 /* Min:Sec */
950
951                 case MS_Hours:
952                         ms_minutes_ebox.grab_focus ();
953                         break;
954                 case MS_Minutes:
955                         ms_seconds_ebox.grab_focus ();
956                         break;
957                 case MS_Seconds:
958                         clock_base.grab_focus ();
959                         break;
960
961                 /* BBT */
962
963                 case Bars:
964                         beats_ebox.grab_focus ();
965                         break;
966                 case Beats:
967                         ticks_ebox.grab_focus ();
968                         break;
969                 case Ticks:
970                         clock_base.grab_focus ();
971                         break;
972
973                 default:
974                         break;
975                 }
976
977         }
978
979         //if user hit Enter, lose focus
980         switch (ev->keyval) {
981         case GDK_Return:
982         case GDK_KP_Enter:
983                 clock_base.grab_focus ();
984         }
985
986         return true;
987 }
988
989 bool
990 AudioClock::field_focus_in_event (GdkEventFocus *ev, Field field)
991 {
992         key_entry_state = 0;
993
994         Keyboard::magic_widget_grab_focus ();
995
996         switch (field) {
997         case SMPTE_Hours:
998                 hours_ebox.set_flags (Gtk::HAS_FOCUS);
999                 hours_ebox.set_state (Gtk::STATE_ACTIVE);
1000                 break;
1001         case SMPTE_Minutes:
1002                 minutes_ebox.set_flags (Gtk::HAS_FOCUS);
1003                 minutes_ebox.set_state (Gtk::STATE_ACTIVE);
1004                 break;
1005         case SMPTE_Seconds:
1006                 seconds_ebox.set_flags (Gtk::HAS_FOCUS);
1007                 seconds_ebox.set_state (Gtk::STATE_ACTIVE);
1008                 break;
1009         case SMPTE_Frames:
1010                 frames_ebox.set_flags (Gtk::HAS_FOCUS);
1011                 frames_ebox.set_state (Gtk::STATE_ACTIVE);
1012                 break;
1013
1014         case AudioFrames:
1015                 audio_frames_ebox.set_flags (Gtk::HAS_FOCUS);
1016                 audio_frames_ebox.set_state (Gtk::STATE_ACTIVE);
1017                 break;
1018
1019         case MS_Hours:
1020                 ms_hours_ebox.set_flags (Gtk::HAS_FOCUS);
1021                 ms_hours_ebox.set_state (Gtk::STATE_ACTIVE);
1022                 break;
1023         case MS_Minutes:
1024                 ms_minutes_ebox.set_flags (Gtk::HAS_FOCUS);
1025                 ms_minutes_ebox.set_state (Gtk::STATE_ACTIVE);
1026                 break;
1027         case MS_Seconds:
1028                 ms_seconds_ebox.set_flags (Gtk::HAS_FOCUS);
1029                 ms_seconds_ebox.set_state (Gtk::STATE_ACTIVE);
1030                 break;
1031         case Bars:
1032                 bars_ebox.set_flags (Gtk::HAS_FOCUS);
1033                 bars_ebox.set_state (Gtk::STATE_ACTIVE);
1034                 break;
1035         case Beats:
1036                 beats_ebox.set_flags (Gtk::HAS_FOCUS);
1037                 beats_ebox.set_state (Gtk::STATE_ACTIVE);
1038                 break;
1039         case Ticks:
1040                 ticks_ebox.set_flags (Gtk::HAS_FOCUS);
1041                 ticks_ebox.set_state (Gtk::STATE_ACTIVE);
1042                 break;
1043         }
1044
1045         return false;
1046 }
1047
1048 bool
1049 AudioClock::field_focus_out_event (GdkEventFocus *ev, Field field)
1050 {
1051         switch (field) {
1052
1053         case SMPTE_Hours:
1054                 hours_ebox.unset_flags (Gtk::HAS_FOCUS);
1055                 hours_ebox.set_state (Gtk::STATE_NORMAL);
1056                 break;
1057         case SMPTE_Minutes:
1058                 minutes_ebox.unset_flags (Gtk::HAS_FOCUS);
1059                 minutes_ebox.set_state (Gtk::STATE_NORMAL);
1060                 break;
1061         case SMPTE_Seconds:
1062                 seconds_ebox.unset_flags (Gtk::HAS_FOCUS);
1063                 seconds_ebox.set_state (Gtk::STATE_NORMAL);
1064                 break;
1065         case SMPTE_Frames:
1066                 frames_ebox.unset_flags (Gtk::HAS_FOCUS);
1067                 frames_ebox.set_state (Gtk::STATE_NORMAL);
1068                 break;
1069
1070         case AudioFrames:
1071                 audio_frames_ebox.unset_flags (Gtk::HAS_FOCUS);
1072                 audio_frames_ebox.set_state (Gtk::STATE_NORMAL);
1073                 break;
1074
1075         case MS_Hours:
1076                 ms_hours_ebox.unset_flags (Gtk::HAS_FOCUS);
1077                 ms_hours_ebox.set_state (Gtk::STATE_NORMAL);
1078                 break;
1079         case MS_Minutes:
1080                 ms_minutes_ebox.unset_flags (Gtk::HAS_FOCUS);
1081                 ms_minutes_ebox.set_state (Gtk::STATE_NORMAL);
1082                 break;
1083         case MS_Seconds:
1084                 ms_seconds_ebox.unset_flags (Gtk::HAS_FOCUS);
1085                 ms_seconds_ebox.set_state (Gtk::STATE_NORMAL);
1086                 break;
1087
1088         case Bars:
1089                 bars_ebox.unset_flags (Gtk::HAS_FOCUS);
1090                 bars_ebox.set_state (Gtk::STATE_NORMAL);
1091                 break;
1092         case Beats:
1093                 beats_ebox.unset_flags (Gtk::HAS_FOCUS);
1094                 beats_ebox.set_state (Gtk::STATE_NORMAL);
1095                 break;
1096         case Ticks:
1097                 ticks_ebox.unset_flags (Gtk::HAS_FOCUS);
1098                 ticks_ebox.set_state (Gtk::STATE_NORMAL);
1099                 break;
1100         }
1101
1102         Keyboard::magic_widget_drop_focus ();
1103
1104         return false;
1105 }
1106
1107 bool
1108 AudioClock::field_button_release_event (GdkEventButton *ev, Field field)
1109 {
1110         if (dragging) {
1111                 gdk_pointer_ungrab (GDK_CURRENT_TIME);
1112                 dragging = false;
1113                 if (ev->y > drag_start_y+1 || ev->y < drag_start_y-1 || Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)){
1114                         // we actually dragged so return without setting editing focus, or we shift clicked
1115                         return true;
1116                 }
1117         }
1118
1119         if (!editable) {
1120                 if (ops_menu == 0) {
1121                         build_ops_menu ();
1122                 }
1123                 ops_menu->popup (1, ev->time);
1124                 return true;
1125         }
1126
1127         if (Keyboard::is_context_menu_event (ev)) {
1128                 if (ops_menu == 0) {
1129                         build_ops_menu ();
1130                 }
1131                 ops_menu->popup (1, ev->time);
1132                 return true;
1133         } 
1134
1135         switch (ev->button) {
1136         case 1:
1137                 switch (field) {
1138                 case SMPTE_Hours:
1139                         hours_ebox.grab_focus();
1140                         break;
1141                 case SMPTE_Minutes:
1142                         minutes_ebox.grab_focus();
1143                         break;
1144                 case SMPTE_Seconds:
1145                         seconds_ebox.grab_focus();
1146                         break;
1147                 case SMPTE_Frames:
1148                         frames_ebox.grab_focus();
1149                         break;
1150
1151                 case AudioFrames:
1152                         audio_frames_ebox.grab_focus();
1153                         break;
1154                         
1155                 case MS_Hours:
1156                         ms_hours_ebox.grab_focus();
1157                         break;
1158                 case MS_Minutes:
1159                         ms_minutes_ebox.grab_focus();
1160                         break;
1161                 case MS_Seconds:
1162                         ms_seconds_ebox.grab_focus();
1163                         break;
1164                         
1165                 case Bars:
1166                         bars_ebox.grab_focus ();
1167                         break;
1168                 case Beats:
1169                         beats_ebox.grab_focus ();
1170                         break;
1171                 case Ticks:
1172                         ticks_ebox.grab_focus ();
1173                         break;
1174                 }
1175                 break;
1176                 
1177         default:
1178                 break;
1179         }
1180
1181         return true;
1182 }
1183
1184 bool
1185 AudioClock::field_button_press_event (GdkEventButton *ev, Field field)
1186 {
1187         if (session == 0) return false;
1188
1189         nframes_t frames = 0;
1190
1191         switch (ev->button) {
1192         case 1:
1193                 if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
1194                         set (frames, true);
1195                         ValueChanged (); /* EMIT_SIGNAL */
1196                                         }
1197         
1198                 /* make absolutely sure that the pointer is grabbed */
1199                 gdk_pointer_grab(ev->window,false ,
1200                                  GdkEventMask( Gdk::POINTER_MOTION_MASK | Gdk::BUTTON_PRESS_MASK |Gdk::BUTTON_RELEASE_MASK), 
1201                                  NULL,NULL,ev->time);
1202                 dragging = true;
1203                 drag_accum = 0;
1204                 drag_start_y = ev->y;
1205                 drag_y = ev->y;
1206                 break;
1207
1208         case 2:
1209                 if (Keyboard::modifier_state_equals (ev->state, Keyboard::TertiaryModifier)) {
1210                         set (frames, true);
1211                         ValueChanged (); /* EMIT_SIGNAL */
1212                 }
1213                 break;
1214
1215         case 3:
1216                 /* used for context sensitive menu */
1217                 return false;
1218                 break;
1219
1220         default:
1221                 return false;
1222                 break;
1223         }
1224         
1225         return true;
1226 }
1227
1228 bool
1229 AudioClock::field_button_scroll_event (GdkEventScroll *ev, Field field)
1230 {
1231         if (session == 0) {
1232                 return false;
1233         }
1234
1235         nframes_t frames = 0;
1236
1237         switch (ev->direction) {
1238
1239         case GDK_SCROLL_UP:
1240                frames = get_frames (field);
1241                if (frames != 0) {
1242                       if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
1243                              frames *= 10;
1244                       }
1245                       set (current_time() + frames, true);
1246                       ValueChanged (); /* EMIT_SIGNAL */
1247                }
1248                break;
1249
1250         case GDK_SCROLL_DOWN:
1251                frames = get_frames (field);
1252                if (frames != 0) {
1253                       if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
1254                              frames *= 10;
1255                       }
1256                       
1257                       if ((double)current_time() - (double)frames < 0.0) {
1258                              set (0, true);
1259                       } else {
1260                              set (current_time() - frames, true);
1261                       }
1262                       
1263                       ValueChanged (); /* EMIT_SIGNAL */
1264                }
1265                break;
1266
1267         default:
1268                 return false;
1269                 break;
1270         }
1271         
1272         return true;
1273 }
1274
1275 bool
1276 AudioClock::field_motion_notify_event (GdkEventMotion *ev, Field field)
1277 {
1278         if (session == 0 || !dragging) {
1279                 return false;
1280         }
1281         
1282         float pixel_frame_scale_factor = 0.2f;
1283
1284 /*
1285         if (Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier))  {
1286                 pixel_frame_scale_factor = 0.1f;
1287         }
1288
1289
1290         if (Keyboard::modifier_state_contains (ev->state, 
1291                                                Keyboard::PrimaryModifier|Keyboard::SecondaryModifier)) {
1292
1293                 pixel_frame_scale_factor = 0.025f;
1294         }
1295 */
1296         double y_delta = ev->y - drag_y;
1297
1298         drag_accum +=  y_delta*pixel_frame_scale_factor;
1299
1300         drag_y = ev->y;
1301
1302         if (trunc(drag_accum) != 0) {
1303
1304                 nframes_t frames;
1305                 nframes_t pos ;
1306                 int dir;
1307                 dir = (drag_accum < 0 ? 1:-1);
1308                 pos = current_time();
1309                 frames = get_frames (field,pos,dir);
1310                 
1311                 if (frames  != 0 &&  frames * drag_accum < current_time()) {
1312                 
1313                         set ((nframes_t) floor (pos - drag_accum * frames), false); // minus because up is negative in computer-land
1314                 
1315                 } else {
1316                         set (0 , false);
1317                 
1318                 }
1319
1320                 drag_accum= 0;
1321                 ValueChanged();  /* EMIT_SIGNAL */      
1322                 
1323
1324         }
1325
1326         return true;
1327 }
1328
1329 nframes_t
1330 AudioClock::get_frames (Field field,nframes_t pos,int dir)
1331 {
1332
1333         nframes_t frames = 0;
1334         BBT_Time bbt;
1335         switch (field) {
1336         case SMPTE_Hours:
1337                 frames = (nframes_t) floor (3600.0 * session->frame_rate());
1338                 break;
1339         case SMPTE_Minutes:
1340                 frames = (nframes_t) floor (60.0 * session->frame_rate());
1341                 break;
1342         case SMPTE_Seconds:
1343                 frames = session->frame_rate();
1344                 break;
1345         case SMPTE_Frames:
1346                 frames = (nframes_t) floor (session->frame_rate() / session->smpte_frames_per_second());
1347                 break;
1348
1349         case AudioFrames:
1350                 frames = 1;
1351                 break;
1352
1353         case MS_Hours:
1354                 frames = (nframes_t) floor (3600.0 * session->frame_rate());
1355                 break;
1356         case MS_Minutes:
1357                 frames = (nframes_t) floor (60.0 * session->frame_rate());
1358                 break;
1359         case MS_Seconds:
1360                 frames = session->frame_rate();
1361                 break;
1362
1363         case Bars:
1364                 bbt.bars = 1;
1365                 bbt.beats = 0;
1366                 bbt.ticks = 0;
1367                 frames = session->tempo_map().bbt_duration_at(pos,bbt,dir);
1368                 break;
1369         case Beats:
1370                 bbt.bars = 0;
1371                 bbt.beats = 1;
1372                 bbt.ticks = 0;
1373                 frames = session->tempo_map().bbt_duration_at(pos,bbt,dir);
1374                 break;
1375         case Ticks:
1376                 bbt.bars = 0;
1377                 bbt.beats = 0;
1378                 bbt.ticks = 1;
1379                 frames = session->tempo_map().bbt_duration_at(pos,bbt,dir);
1380                 break;
1381         }
1382
1383         return frames;
1384 }
1385
1386 nframes_t
1387 AudioClock::current_time (nframes_t pos) const
1388 {
1389         nframes_t ret = 0;
1390
1391         switch (_mode) {
1392         case SMPTE:
1393                 ret = smpte_frame_from_display ();
1394                 break;
1395         case BBT:
1396                 ret = bbt_frame_from_display (pos);
1397                 break;
1398
1399         case MinSec:
1400                 ret = minsec_frame_from_display ();
1401                 break;
1402
1403         case Frames:
1404                 ret = audio_frame_from_display ();
1405                 break;
1406
1407         case Off:
1408                 break;
1409         }
1410
1411         return ret;
1412 }
1413
1414 nframes_t
1415 AudioClock::current_duration (nframes_t pos) const
1416 {
1417         nframes_t ret = 0;
1418
1419         switch (_mode) {
1420         case SMPTE:
1421                 ret = smpte_frame_from_display ();
1422                 break;
1423         case BBT:
1424                 ret = bbt_frame_duration_from_display (pos);
1425                 break;
1426
1427         case MinSec:
1428                 ret = minsec_frame_from_display ();
1429                 break;
1430
1431         case Frames:
1432                 ret = audio_frame_from_display ();
1433                 break;
1434
1435         case Off:
1436                 break;
1437         }
1438
1439         return ret;
1440 }
1441
1442 void
1443 AudioClock::smpte_sanitize_display()
1444 {
1445         // Check SMPTE fields for sanity, possibly adjusting values
1446         if (atoi(minutes_label.get_text()) > 59) {
1447                 minutes_label.set_text("59");
1448         }
1449         
1450         if (atoi(seconds_label.get_text()) > 59) {
1451                 seconds_label.set_text("59");
1452         }
1453         
1454         switch ((long)rint(session->smpte_frames_per_second())) {
1455         case 24:
1456                 if (atoi(frames_label.get_text()) > 23) {
1457                         frames_label.set_text("23");
1458                 }
1459                 break;
1460         case 25:
1461                 if (atoi(frames_label.get_text()) > 24) {
1462                         frames_label.set_text("24");
1463                 }
1464                 break;
1465         case 30:
1466                 if (atoi(frames_label.get_text()) > 29) {
1467                         frames_label.set_text("29");
1468                 }
1469                 break;
1470         default:
1471                 break;
1472         }
1473         
1474         if (session->smpte_drop_frames()) {
1475                 if ((atoi(minutes_label.get_text()) % 10) && (atoi(seconds_label.get_text()) == 0) && (atoi(frames_label.get_text()) < 2)) {
1476                         frames_label.set_text("02");
1477                 }
1478         }
1479 }
1480
1481 nframes_t
1482 AudioClock::smpte_frame_from_display () const
1483 {
1484         if (session == 0) {
1485                 return 0;
1486         }
1487         
1488         SMPTE::Time smpte;
1489         nframes_t sample;
1490         
1491         smpte.hours = atoi (hours_label.get_text());
1492         smpte.minutes = atoi (minutes_label.get_text());
1493         smpte.seconds = atoi (seconds_label.get_text());
1494         smpte.frames = atoi (frames_label.get_text());
1495         smpte.rate = session->smpte_frames_per_second();
1496         smpte.drop= session->smpte_drop_frames();
1497
1498         session->smpte_to_sample( smpte, sample, false /* use_offset */, false /* use_subframes */ );
1499         
1500
1501 #if 0
1502 #define SMPTE_SAMPLE_TEST_1
1503 #define SMPTE_SAMPLE_TEST_2
1504 #define SMPTE_SAMPLE_TEST_3
1505 #define SMPTE_SAMPLE_TEST_4
1506 #define SMPTE_SAMPLE_TEST_5
1507 #define SMPTE_SAMPLE_TEST_6
1508 #define SMPTE_SAMPLE_TEST_7
1509
1510         // Testcode for smpte<->sample conversions (P.S.)
1511         SMPTE::Time smpte1;
1512         nframes_t sample1;
1513         nframes_t oldsample = 0;
1514         SMPTE::Time smpte2;
1515         nframes_t sample_increment;
1516
1517         sample_increment = (long)rint(session->frame_rate() / session->smpte_frames_per_second);
1518
1519 #ifdef SMPTE_SAMPLE_TEST_1
1520         // Test 1: use_offset = false, use_subframes = false
1521         cout << "use_offset = false, use_subframes = false" << endl;
1522         for (int i = 0; i < 108003; i++) {
1523                 session->smpte_to_sample( smpte1, sample1, false /* use_offset */, false /* use_subframes */ );
1524                 session->sample_to_smpte( sample1, smpte2, false /* use_offset */, false /* use_subframes */ );
1525
1526                 if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
1527                         cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1528                         cout << "smpte1: " << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1529                         cout << "sample: " << sample1 << endl;
1530                         cout << "sample: " << sample1 << " -> ";
1531                         cout << "smpte2: " << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1532                         break;
1533                 }
1534     
1535                 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1536                         cout << "ERROR: smpte2 not equal smpte1" << endl;
1537                         cout << "smpte1: " << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1538                         cout << "sample: " << sample1 << endl;
1539                         cout << "sample: " << sample1 << " -> ";
1540                         cout << "smpte2: " << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1541                         break;
1542                 }
1543                 oldsample = sample1;
1544                 session->smpte_increment( smpte1 );
1545         }
1546
1547         cout << "sample_increment: " << sample_increment << endl;
1548         cout << "sample: " << sample1 << " -> ";
1549         cout << "smpte: " << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1550 #endif
1551
1552 #ifdef SMPTE_SAMPLE_TEST_2
1553         // Test 2: use_offset = true, use_subframes = false
1554         cout << "use_offset = true, use_subframes = false" << endl;
1555   
1556         smpte1.hours = 0;
1557         smpte1.minutes = 0;
1558         smpte1.seconds = 0;
1559         smpte1.frames = 0;
1560         smpte1.subframes = 0;
1561         sample1 = oldsample = 0;
1562
1563         session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1564         cout << "Starting at sample: " << sample1 << " -> ";
1565         cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1566
1567         for (int i = 0; i < 108003; i++) {
1568                 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1569                 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1570
1571 //     cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1572 //     cout << "sample: " << sample1 << endl;
1573 //     cout << "sample: " << sample1 << " -> ";
1574 //     cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1575     
1576                 if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
1577                         cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1578                         cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1579                         cout << "sample: " << sample1 << endl;
1580                         cout << "sample: " << sample1 << " -> ";
1581                         cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1582                         break;
1583                 }
1584     
1585                 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1586                         cout << "ERROR: smpte2 not equal smpte1" << endl;
1587                         cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1588                         cout << "sample: " << sample1 << endl;
1589                         cout << "sample: " << sample1 << " -> ";
1590                         cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1591                         break;
1592                 }
1593                 oldsample = sample1;
1594                 session->smpte_increment( smpte1 );
1595         }
1596
1597         cout << "sample_increment: " << sample_increment << endl;
1598         cout << "sample: " << sample1 << " -> ";
1599         cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1600 #endif
1601
1602 #ifdef SMPTE_SAMPLE_TEST_3
1603         // Test 3: use_offset = true, use_subframes = false, decrement
1604         cout << "use_offset = true, use_subframes = false, decrement" << endl;  
1605
1606         session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1607         cout << "Starting at sample: " << sample1 << " -> ";
1608         cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1609
1610         for (int i = 0; i < 108003; i++) {
1611                 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1612                 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1613
1614 //     cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1615 //     cout << "sample: " << sample1 << endl;
1616 //     cout << "sample: " << sample1 << " -> ";
1617 //     cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1618     
1619                 if ((i > 0) && ( ((oldsample - sample1) != sample_increment) && ((oldsample - sample1) != (sample_increment + 1)) && ((oldsample - sample1) != (sample_increment - 1)))) {
1620                         cout << "ERROR: sample increment not right: " << (oldsample - sample1) << " != " << sample_increment << endl;
1621                         cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1622                         cout << "sample: " << sample1 << endl;
1623                         cout << "sample: " << sample1 << " -> ";
1624                         cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1625                         break;
1626                 }
1627     
1628                 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1629                         cout << "ERROR: smpte2 not equal smpte1" << endl;
1630                         cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1631                         cout << "sample: " << sample1 << endl;
1632                         cout << "sample: " << sample1 << " -> ";
1633                         cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1634                         break;
1635                 }
1636                 oldsample = sample1;
1637                 session->smpte_decrement( smpte1 );
1638         }
1639
1640         cout << "sample_decrement: " << sample_increment << endl;
1641         cout << "sample: " << sample1 << " -> ";
1642         cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1643 #endif
1644
1645
1646 #ifdef SMPTE_SAMPLE_TEST_4
1647         // Test 4: use_offset = true, use_subframes = true
1648         cout << "use_offset = true, use_subframes = true" << endl;
1649   
1650         for (long sub = 5; sub < 80; sub += 5) {
1651                 smpte1.hours = 0;
1652                 smpte1.minutes = 0;
1653                 smpte1.seconds = 0;
1654                 smpte1.frames = 0;
1655                 smpte1.subframes = 0;
1656                 sample1 = oldsample = (sample_increment * sub) / 80;
1657     
1658                 session->sample_to_smpte( sample1, smpte1, true /* use_offset */, true /* use_subframes */ );
1659     
1660                 cout << "starting at sample: " << sample1 << " -> ";
1661                 cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1662     
1663                 for (int i = 0; i < 108003; i++) {
1664                         session->smpte_to_sample( smpte1, sample1, true /* use_offset */, true /* use_subframes */ );
1665                         session->sample_to_smpte( sample1, smpte2, true /* use_offset */, true /* use_subframes */ );
1666       
1667                         if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
1668                                 cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1669                                 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1670                                 cout << "sample: " << sample1 << endl;
1671                                 cout << "sample: " << sample1 << " -> ";
1672                                 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1673                                 //break;
1674                         }
1675       
1676                         if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames || smpte2.subframes != smpte1.subframes) {
1677                                 cout << "ERROR: smpte2 not equal smpte1" << endl;
1678                                 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1679                                 cout << "sample: " << sample1 << endl;
1680                                 cout << "sample: " << sample1 << " -> ";
1681                                 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1682                                 break;
1683                         }
1684                         oldsample = sample1;
1685                         session->smpte_increment( smpte1 );
1686                 }
1687     
1688                 cout << "sample_increment: " << sample_increment << endl;
1689                 cout << "sample: " << sample1 << " -> ";
1690                 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1691
1692                 for (int i = 0; i < 108003; i++) {
1693                         session->smpte_to_sample( smpte1, sample1, true /* use_offset */, true /* use_subframes */ );
1694                         session->sample_to_smpte( sample1, smpte2, true /* use_offset */, true /* use_subframes */ );
1695       
1696                         if ((i > 0) && ( ((oldsample - sample1) != sample_increment) && ((oldsample - sample1) != (sample_increment + 1)) && ((oldsample - sample1) != (sample_increment - 1)))) {
1697                                 cout << "ERROR: sample increment not right: " << (oldsample - sample1) << " != " << sample_increment << endl;
1698                                 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1699                                 cout << "sample: " << sample1 << endl;
1700                                 cout << "sample: " << sample1 << " -> ";
1701                                 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1702                                 //break;
1703                         }
1704       
1705                         if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames || smpte2.subframes != smpte1.subframes) {
1706                                 cout << "ERROR: smpte2 not equal smpte1" << endl;
1707                                 cout << "smpte1: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1708                                 cout << "sample: " << sample1 << endl;
1709                                 cout << "sample: " << sample1 << " -> ";
1710                                 cout << "smpte2: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1711                                 break;
1712                         }
1713                         oldsample = sample1;
1714                         session->smpte_decrement( smpte1 );
1715                 }
1716     
1717                 cout << "sample_decrement: " << sample_increment << endl;
1718                 cout << "sample: " << sample1 << " -> ";
1719                 cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1720         }
1721 #endif
1722
1723
1724 #ifdef SMPTE_SAMPLE_TEST_5
1725         // Test 5: use_offset = true, use_subframes = false, increment seconds
1726         cout << "use_offset = true, use_subframes = false, increment seconds" << endl;
1727   
1728         smpte1.hours = 0;
1729         smpte1.minutes = 0;
1730         smpte1.seconds = 0;
1731         smpte1.frames = 0;
1732         smpte1.subframes = 0;
1733         sample1 = oldsample = 0;
1734         sample_increment = session->frame_rate();
1735
1736         session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1737         cout << "Starting at sample: " << sample1 << " -> ";
1738         cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1739
1740         for (int i = 0; i < 3600; i++) {
1741                 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1742                 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1743
1744 //     cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1745 //     cout << "sample: " << sample1 << endl;
1746 //     cout << "sample: " << sample1 << " -> ";
1747 //     cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1748     
1749 //     if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1750 //     {
1751 //       cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1752 //       break;
1753 //     }
1754     
1755                 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1756                         cout << "ERROR: smpte2 not equal smpte1" << endl;
1757                         cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1758                         cout << "sample: " << sample1 << endl;
1759                         cout << "sample: " << sample1 << " -> ";
1760                         cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1761                         break;
1762                 }
1763                 oldsample = sample1;
1764                 session->smpte_increment_seconds( smpte1 );
1765         }
1766
1767         cout << "sample_increment: " << sample_increment << endl;
1768         cout << "sample: " << sample1 << " -> ";
1769         cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1770 #endif
1771
1772
1773 #ifdef SMPTE_SAMPLE_TEST_6
1774         // Test 6: use_offset = true, use_subframes = false, increment minutes
1775         cout << "use_offset = true, use_subframes = false, increment minutes" << endl;
1776   
1777         smpte1.hours = 0;
1778         smpte1.minutes = 0;
1779         smpte1.seconds = 0;
1780         smpte1.frames = 0;
1781         smpte1.subframes = 0;
1782         sample1 = oldsample = 0;
1783         sample_increment = session->frame_rate() * 60;
1784
1785         session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1786         cout << "Starting at sample: " << sample1 << " -> ";
1787         cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1788
1789         for (int i = 0; i < 60; i++) {
1790                 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1791                 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1792
1793 //     cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1794 //     cout << "sample: " << sample1 << endl;
1795 //     cout << "sample: " << sample1 << " -> ";
1796 //     cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1797     
1798 //     if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1799 //     {
1800 //       cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1801 //       break;
1802 //     }
1803     
1804                 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1805                         cout << "ERROR: smpte2 not equal smpte1" << endl;
1806                         cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1807                         cout << "sample: " << sample1 << endl;
1808                         cout << "sample: " << sample1 << " -> ";
1809                         cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1810                         break;
1811                 }
1812                 oldsample = sample1;
1813                 session->smpte_increment_minutes( smpte1 );
1814         }
1815
1816         cout << "sample_increment: " << sample_increment << endl;
1817         cout << "sample: " << sample1 << " -> ";
1818         cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1819 #endif
1820
1821 #ifdef SMPTE_SAMPLE_TEST_7
1822         // Test 7: use_offset = true, use_subframes = false, increment hours
1823         cout << "use_offset = true, use_subframes = false, increment hours" << endl;
1824   
1825         smpte1.hours = 0;
1826         smpte1.minutes = 0;
1827         smpte1.seconds = 0;
1828         smpte1.frames = 0;
1829         smpte1.subframes = 0;
1830         sample1 = oldsample = 0;
1831         sample_increment = session->frame_rate() * 60 * 60;
1832
1833         session->sample_to_smpte( sample1, smpte1, true /* use_offset */, false /* use_subframes */ );
1834         cout << "Starting at sample: " << sample1 << " -> ";
1835         cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << endl;
1836
1837         for (int i = 0; i < 10; i++) {
1838                 session->smpte_to_sample( smpte1, sample1, true /* use_offset */, false /* use_subframes */ );
1839                 session->sample_to_smpte( sample1, smpte2, true /* use_offset */, false /* use_subframes */ );
1840
1841 //     cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1842 //     cout << "sample: " << sample1 << endl;
1843 //     cout << "sample: " << sample1 << " -> ";
1844 //     cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1845     
1846 //     if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
1847 //     {
1848 //       cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
1849 //       break;
1850 //     }
1851     
1852                 if (smpte2.hours != smpte1.hours || smpte2.minutes != smpte1.minutes || smpte2.seconds != smpte2.seconds || smpte2.frames != smpte1.frames) {
1853                         cout << "ERROR: smpte2 not equal smpte1" << endl;
1854                         cout << "smpte: " << (smpte1.negative ? "-" : "") << smpte1.hours << ":" << smpte1.minutes << ":" << smpte1.seconds << ":" << smpte1.frames << "::" << smpte1.subframes << " -> ";
1855                         cout << "sample: " << sample1 << endl;
1856                         cout << "sample: " << sample1 << " -> ";
1857                         cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1858                         break;
1859                 }
1860                 oldsample = sample1;
1861                 session->smpte_increment_hours( smpte1 );
1862         }
1863
1864         cout << "sample_increment: " << sample_increment << endl;
1865         cout << "sample: " << sample1 << " -> ";
1866         cout << "smpte: " << (smpte2.negative ? "-" : "") << smpte2.hours << ":" << smpte2.minutes << ":" << smpte2.seconds << ":" << smpte2.frames << "::" << smpte2.subframes << endl;
1867 #endif
1868
1869 #endif  
1870
1871         return sample;
1872 }
1873
1874 nframes_t
1875 AudioClock::minsec_frame_from_display () const
1876 {
1877         if (session == 0) {
1878                 return 0;
1879         }
1880
1881         int hrs = atoi (ms_hours_label.get_text());
1882         int mins = atoi (ms_minutes_label.get_text());
1883         float secs = atof (ms_seconds_label.get_text());
1884
1885         nframes_t sr = session->frame_rate();
1886
1887         return (nframes_t) floor ((hrs * 60.0f * 60.0f * sr) + (mins * 60.0f * sr) + (secs * sr));
1888 }
1889
1890 nframes_t
1891 AudioClock::bbt_frame_from_display (nframes_t pos) const
1892 {
1893         if (session == 0) {
1894                 error << "AudioClock::current_time() called with BBT mode but without session!" << endmsg;
1895                 return 0;
1896         }
1897
1898         AnyTime any;
1899         any.type = AnyTime::BBT;
1900
1901         any.bbt.bars = atoi (bars_label.get_text());
1902         any.bbt.beats = atoi (beats_label.get_text());
1903         any.bbt.ticks = atoi (ticks_label.get_text());
1904
1905        if (is_duration) {
1906                any.bbt.bars++;
1907                any.bbt.beats++;
1908        }
1909
1910         nframes_t ret = session->convert_to_frames_at (pos, any);
1911
1912         return ret;
1913 }
1914
1915
1916 nframes_t
1917 AudioClock::bbt_frame_duration_from_display (nframes_t pos) const
1918 {
1919         if (session == 0) {
1920                 error << "AudioClock::current_time() called with BBT mode but without session!" << endmsg;
1921                 return 0;
1922         }
1923
1924         BBT_Time bbt;
1925
1926
1927         bbt.bars = atoi (bars_label.get_text());
1928         bbt.beats = atoi (beats_label.get_text());
1929         bbt.ticks = atoi (ticks_label.get_text());
1930         
1931         return session->tempo_map().bbt_duration_at(pos,bbt,1);
1932 }
1933
1934 nframes_t
1935 AudioClock::audio_frame_from_display () const
1936 {
1937         return (nframes_t) atoi (audio_frames_label.get_text());
1938 }
1939
1940 void
1941 AudioClock::build_ops_menu ()
1942 {
1943         using namespace Menu_Helpers;
1944         ops_menu = new Menu;
1945         MenuList& ops_items = ops_menu->items();
1946         ops_menu->set_name ("ArdourContextMenu");
1947         
1948         if (!Profile->get_sae()) {
1949                 ops_items.push_back (MenuElem (_("Timecode"), bind (mem_fun(*this, &AudioClock::set_mode), SMPTE)));
1950         }
1951         ops_items.push_back (MenuElem (_("Bars:Beats"), bind (mem_fun(*this, &AudioClock::set_mode), BBT)));
1952         ops_items.push_back (MenuElem (_("Minutes:Seconds"), bind (mem_fun(*this, &AudioClock::set_mode), MinSec)));
1953         ops_items.push_back (MenuElem (_("Samples"), bind (mem_fun(*this, &AudioClock::set_mode), Frames)));
1954         ops_items.push_back (MenuElem (_("Off"), bind (mem_fun(*this, &AudioClock::set_mode), Off)));
1955 }
1956
1957 void
1958 AudioClock::set_mode (Mode m)
1959 {
1960         /* slightly tricky: this is called from within the ARDOUR_UI
1961            constructor by some of its clock members. at that time
1962            the instance pointer is unset, so we have to be careful.
1963            the main idea is to drop keyboard focus in case we had
1964            started editing the clock and then we switch clock mode.
1965         */
1966
1967         clock_base.grab_focus ();
1968                 
1969         if (_mode == m) {
1970                 return;
1971         }
1972         
1973         clock_base.remove ();
1974         
1975         _mode = m;
1976
1977         switch (_mode) {
1978         case SMPTE:
1979                 clock_base.add (smpte_packer_hbox);
1980                 break;
1981
1982         case BBT:
1983                 clock_base.add (bbt_packer_hbox);
1984                 break;
1985
1986         case MinSec:
1987                 clock_base.add (minsec_packer_hbox);
1988                 break;
1989
1990         case Frames:
1991                 clock_base.add (frames_packer_hbox);
1992                 break;
1993
1994         case Off:
1995                 clock_base.add (off_hbox);
1996                 break;
1997         }
1998
1999         set_size_requests ();
2000         
2001         set (last_when, true);
2002         clock_base.show_all ();
2003         key_entry_state = 0;
2004
2005         if (!is_transient) {
2006                 ModeChanged (); /* EMIT SIGNAL */
2007                 mode_changed (); /* EMIT SIGNAL */
2008         }
2009 }
2010
2011 void
2012 AudioClock::set_size_requests ()
2013 {
2014         /* note that in some fonts, "88" is narrower than "00", hence the 2 pixel padding */
2015
2016         switch (_mode) {
2017         case SMPTE:
2018                 Gtkmm2ext::set_size_request_to_display_given_text (hours_label, "-00", 5, 5);
2019                 Gtkmm2ext::set_size_request_to_display_given_text (minutes_label, "00", 5, 5);
2020                 Gtkmm2ext::set_size_request_to_display_given_text (seconds_label, "00", 5, 5);
2021                 Gtkmm2ext::set_size_request_to_display_given_text (frames_label, "00", 5, 5);
2022                 break;
2023
2024         case BBT:
2025                 Gtkmm2ext::set_size_request_to_display_given_text (bars_label, "-000", 5, 5);
2026                 Gtkmm2ext::set_size_request_to_display_given_text (beats_label, "00", 5, 5);
2027                 Gtkmm2ext::set_size_request_to_display_given_text (ticks_label, "0000", 5, 5);
2028                 break;
2029
2030         case MinSec:
2031                 Gtkmm2ext::set_size_request_to_display_given_text (ms_hours_label, "00", 5, 5);
2032                 Gtkmm2ext::set_size_request_to_display_given_text (ms_minutes_label, "00", 5, 5);
2033                 Gtkmm2ext::set_size_request_to_display_given_text (ms_seconds_label, "00.000", 5, 5);
2034                 break;
2035
2036         case Frames:
2037                 Gtkmm2ext::set_size_request_to_display_given_text (audio_frames_label, "0000000000", 5, 5);
2038                 break;
2039
2040         case Off:
2041                 Gtkmm2ext::set_size_request_to_display_given_text (off_hbox, "00000", 5, 5);
2042                 break;
2043                 
2044         }
2045 }
2046
2047 void
2048 AudioClock::set_bbt_reference (nframes64_t pos)
2049 {
2050         bbt_reference_time = pos;
2051 }