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