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