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