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