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