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