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