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