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