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