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