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