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