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