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