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