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