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