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