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