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