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