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