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