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