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