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