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