implement relative clock editing (terminated by + or - keys, which adjust the clock...
[ardour.git] / gtk2_ardour / audio_clock.cc
index f2347d749cbf23b182da75cbe17d6004affb0441..e1e468e54426a7c3923dd5492a0262d3b579c3d6 100644 (file)
@@ -75,8 +75,6 @@ AudioClock::AudioClock (const string& clock_name, bool transient, const string&
        , last_sdelta (0)
        , dragging (false)
        , drag_field (Field (0))
-       , _canonical_time_is_displayed (true)
-       , _canonical_time (0)
 
 {
        set_flags (CAN_FOCUS);
@@ -374,6 +372,7 @@ AudioClock::start_edit ()
        editing = true;
 
        show_edit_status (1);
+       queue_draw ();
 
        Keyboard::magic_widget_grab_focus ();
        grab_focus ();
@@ -406,32 +405,237 @@ AudioClock::end_edit (bool modify)
                        edit_string = pre_edit_string;
                        input_string.clear ();
                        _layout->set_text (edit_string);
+                       show_edit_status (1);
+                       /* edit attributes remain in use */
                } else {
+
                        editing = false;
+                       framepos_t pos;
+
+                       switch (_mode) {
+                       case Timecode:
+                               pos = frames_from_timecode_string (edit_string);
+                               break;
+                               
+                       case BBT:
+                               if (is_duration) {
+                                       pos = frame_duration_from_bbt_string (0, edit_string);
+                               } else {
+                                       pos = frames_from_bbt_string (0, edit_string);
+                               }
+                               break;
+                               
+                       case MinSec:
+                               pos = frames_from_minsec_string (edit_string);
+                               break;
+                               
+                       case Frames:
+                               pos = frames_from_audioframes_string (edit_string);
+                               break;
+                       }
+
+                       set (pos, true);
                        _layout->set_attributes (normal_attributes);
                        ValueChanged(); /* EMIT_SIGNAL */
                }
 
        } else {
                editing = false;
+               _layout->set_attributes (normal_attributes);
                _layout->set_text (pre_edit_string);
        }
 
        queue_draw ();
 
        if (!editing) {
+               drop_focus ();
+       }
+}
 
-               /* move focus back to the default widget in the top level window */
-               
-               Keyboard::magic_widget_drop_focus ();
+void
+AudioClock::drop_focus ()
+{
+       /* move focus back to the default widget in the top level window */
+       
+       Keyboard::magic_widget_drop_focus ();
+       Widget* top = get_toplevel();
+       if (top->is_toplevel ()) {
+               Window* win = dynamic_cast<Window*> (top);
+               win->grab_focus ();
+       }
+}
+
+framecnt_t 
+AudioClock::parse_as_frames_distance (const std::string& str)
+{
+       framecnt_t f;
+
+       if (sscanf (str.c_str(), "%" PRId64, &f) == 1) {
+               return f;
+       }
+
+       return 0;
+}
+
+framecnt_t 
+AudioClock::parse_as_minsec_distance (const std::string& str)
+{
+       framecnt_t sr = _session->frame_rate();
+       int msecs;
+       int secs;
+       int mins;
+       int hrs;
+
+       switch (str.length()) {
+       case 0:
+               return 0;
+       case 1:
+       case 2:
+       case 3:
+       case 4:
+               sscanf (str.c_str(), "%" PRId32, &msecs);
+               return msecs * (sr / 1000);
                
-               Widget* top = get_toplevel();
+       case 5:
+               sscanf (str.c_str(), "%1" PRId32 "%" PRId32, &secs, &msecs);
+               return (secs * sr) + (msecs * (sr/1000));
+
+       case 6:
+               sscanf (str.c_str(), "%2" PRId32 "%" PRId32, &secs, &msecs);
+               return (secs * sr) + (msecs * (sr/1000));
+
+       case 7:
+               sscanf (str.c_str(), "%1" PRId32 "%2" PRId32 "%" PRId32, &mins, &secs, &msecs);
+               return (mins * 60 * sr) + (secs * sr) + (msecs * (sr/1000));
+
+       case 8:
+               sscanf (str.c_str(), "%2" PRId32 "%2" PRId32 "%" PRId32, &mins, &secs, &msecs);
+               return (mins * 60 * sr) + (secs * sr) + (msecs * (sr/1000));
+
+       case 9:
+               sscanf (str.c_str(), "%1" PRId32 "%2" PRId32 "%2" PRId32 "%" PRId32, &hrs, &mins, &secs, &msecs);
+               return (hrs * 3600 * sr) + (mins * 60 * sr) + (secs * sr) + (msecs * (sr/1000));
+
+       case 10:
+               sscanf (str.c_str(), "%1" PRId32 "%2" PRId32 "%2" PRId32 "%" PRId32, &hrs, &mins, &secs, &msecs);
+               return (hrs * 3600 * sr) + (mins * 60 * sr) + (secs * sr) + (msecs * (sr/1000));
+       
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+framecnt_t 
+AudioClock::parse_as_timecode_distance (const std::string& str)
+{
+       double fps = _session->timecode_frames_per_second();
+       framecnt_t sr = _session->frame_rate();
+       int frames;
+       int secs;
+       int mins;
+       int hrs;
+       
+       switch (str.length()) {
+       case 0:
+               return 0;
+       case 1:
+       case 2:
+               sscanf (str.c_str(), "%" PRId32, &frames);
+               return lrint ((frames/(float)fps) * sr);
+
+       case 3:
+               sscanf (str.c_str(), "%1" PRId32 "%" PRId32, &secs, &frames);
+               return (secs * sr) + lrint ((frames/(float)fps) * sr);
+
+       case 4:
+               sscanf (str.c_str(), "%2" PRId32 "%" PRId32, &secs, &frames);
+               return (secs * sr) + lrint ((frames/(float)fps) * sr);
                
-               if (top->is_toplevel ()) {
-                       Window* win = dynamic_cast<Window*> (top);
-                       win->grab_focus ();
+       case 5:
+               sscanf (str.c_str(), "%1" PRId32 "%2" PRId32 "%" PRId32, &mins, &secs, &frames);
+               return (mins * 60 * sr) + (secs * sr) + lrint ((frames/(float)fps) * sr);
+
+       case 6:
+               sscanf (str.c_str(), "%2" PRId32 "%2" PRId32 "%" PRId32, &mins, &secs, &frames);
+               return (mins * 60 * sr) + (secs * sr) + lrint ((frames/(float)fps) * sr);
+
+       case 7:
+               sscanf (str.c_str(), "%1" PRId32 "%2" PRId32 "%2" PRId32 "%" PRId32, &hrs, &mins, &secs, &frames);
+               return (hrs * 3600 * sr) + (mins * 60 * sr) + (secs * sr) + lrint ((frames/(float)fps) * sr);
+
+       case 8:
+               sscanf (str.c_str(), "%2" PRId32 "%2" PRId32 "%2" PRId32 "%" PRId32, &hrs, &mins, &secs, &frames);
+               return (hrs * 3600 * sr) + (mins * 60 * sr) + (secs * sr) + lrint ((frames/(float)fps) * sr);
+       
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+framecnt_t 
+AudioClock::parse_as_bbt_distance (const std::string& str)
+{
+       return 0;
+}
+
+framecnt_t 
+AudioClock::parse_as_distance (const std::string& instr)
+{
+       string str = instr;
+
+       /* the input string is in reverse order */
+
+       std::reverse (str.begin(), str.end());
+
+       switch (_mode) {
+       case Timecode:
+               return parse_as_timecode_distance (str);
+               break;
+       case Frames:
+               return parse_as_frames_distance (str);
+               break;
+       case BBT:
+               return parse_as_bbt_distance (str);
+               break;
+       case MinSec:
+               return parse_as_minsec_distance (str);
+               break;
+       }
+       return 0;
+}
+
+void
+AudioClock::end_edit_relative (bool add)
+{
+       framecnt_t frames = parse_as_distance (input_string);
+
+       editing = false;
+
+       editing = false;
+       _layout->set_attributes (normal_attributes);
+
+       if (frames != 0) {
+               if (add) {
+                       set (current_time() + frames, true);
+               } else {
+                       framepos_t c = current_time();
+
+                       if (c > frames) {
+                               set (c - frames, true);
+                       } else {
+                               set (0, true);
+                       }
                }
+               ValueChanged (); /* EMIT SIGNAL */
        }
+
+       input_string.clear ();
+       queue_draw ();
+       drop_focus ();
 }
 
 void
@@ -517,10 +721,6 @@ AudioClock::set (framepos_t when, bool force, framecnt_t offset, char which)
        }
 
        last_when = when;
-
-       /* we're setting the time from a frames value, so keep it as the canonical value */
-       _canonical_time = when;
-       _canonical_time_is_displayed = false;
 }
 
 void
@@ -824,6 +1024,18 @@ AudioClock::on_key_release_event (GdkEventKey *ev)
                new_char = '9';
                break;
 
+       case GDK_minus:
+       case GDK_KP_Subtract:
+               end_edit_relative (false);
+               return true;
+               break;
+
+       case GDK_plus:
+       case GDK_KP_Add:
+               end_edit_relative (true);
+               return true;
+               break;
+
        case GDK_Tab:
        case GDK_Return:
        case GDK_KP_Enter:
@@ -1012,6 +1224,16 @@ AudioClock::on_button_release_event (GdkEventButton *ev)
        return false;
 }
 
+bool
+AudioClock::on_focus_out_event (GdkEventFocus* ev)
+{
+       bool ret = CairoWidget::on_focus_out_event (ev);
+
+       end_edit (false);
+
+       return ret;
+}
+
 bool
 AudioClock::on_scroll_event (GdkEventScroll *ev)
 {
@@ -1182,30 +1404,7 @@ AudioClock::get_frame_step (Field field, framepos_t pos, int dir)
 framepos_t
 AudioClock::current_time (framepos_t pos) const
 {
-       // if (!_canonical_time_is_displayed) {
-       // return _canonical_time;
-        //}
-
-       framepos_t ret = 0;
-
-       switch (_mode) {
-       case Timecode:
-               ret = timecode_frame_from_display ();
-               break;
-       case BBT:
-               ret = bbt_frame_from_display (pos);
-               break;
-
-       case MinSec:
-               ret = minsec_frame_from_display ();
-               break;
-
-       case Frames:
-               ret = audio_frame_from_display ();
-               break;
-       }
-
-       return ret;
+       return last_when;
 }
 
 framepos_t
@@ -1215,18 +1414,18 @@ AudioClock::current_duration (framepos_t pos) const
 
        switch (_mode) {
        case Timecode:
-               ret = timecode_frame_from_display ();
+               ret = last_when;
                break;
        case BBT:
-               ret = bbt_frame_duration_from_display (pos);
+               ret = frame_duration_from_bbt_string (pos, _layout->get_text());
                break;
 
        case MinSec:
-               ret = minsec_frame_from_display ();
+               ret = last_when;
                break;
 
        case Frames:
-               ret = audio_frame_from_display ();
+               ret = last_when;
                break;
        }
 
@@ -1279,7 +1478,7 @@ AudioClock::timecode_validate_edit (const string& str)
 }
 
 framepos_t
-AudioClock::timecode_frame_from_display () const
+AudioClock::frames_from_timecode_string (const string& str) const
 {
        if (_session == 0) {
                return 0;
@@ -1288,7 +1487,7 @@ AudioClock::timecode_frame_from_display () const
        Timecode::Time TC;
        framepos_t sample;
 
-       sscanf (_layout->get_text().c_str(), "%d:%d:%d:%d", &TC.hours, &TC.minutes, &TC.seconds, &TC.frames);
+       sscanf (str.c_str(), "%d:%d:%d:%d", &TC.hours, &TC.minutes, &TC.seconds, &TC.frames);
 
        TC.rate = _session->timecode_frames_per_second();
        TC.drop= _session->timecode_drop_frames();
@@ -1301,7 +1500,7 @@ AudioClock::timecode_frame_from_display () const
 }
 
 framepos_t
-AudioClock::minsec_frame_from_display () const
+AudioClock::frames_from_minsec_string (const string& str) const
 {
        if (_session == 0) {
                return 0;
@@ -1310,12 +1509,12 @@ AudioClock::minsec_frame_from_display () const
        int hrs, mins, secs, millisecs;
        framecnt_t sr = _session->frame_rate();
 
-       sscanf (_layout->get_text().c_str(), "%d:%d:%d:%d", &hrs, &mins, &secs, &millisecs);
+       sscanf (str.c_str(), "%d:%d:%d:%d", &hrs, &mins, &secs, &millisecs);
        return (framepos_t) floor ((hrs * 60.0f * 60.0f * sr) + (mins * 60.0f * sr) + (secs * sr) + (millisecs * sr / 1000.0));
 }
 
 framepos_t
-AudioClock::bbt_frame_from_display (framepos_t pos) const
+AudioClock::frames_from_bbt_string (framepos_t pos, const string& str) const
 {
        if (_session == 0) {
                error << "AudioClock::current_time() called with BBT mode but without session!" << endmsg;
@@ -1325,7 +1524,7 @@ AudioClock::bbt_frame_from_display (framepos_t pos) const
        AnyTime any;
        any.type = AnyTime::BBT;
 
-       sscanf (_layout->get_text().c_str(), "%" PRId32 "|%" PRId32 "|%" PRId32, &any.bbt.bars, &any.bbt.beats, &any.bbt.ticks);
+       sscanf (str.c_str(), "%" PRId32 "|%" PRId32 "|%" PRId32, &any.bbt.bars, &any.bbt.beats, &any.bbt.ticks);
 
        if (is_duration) {
                any.bbt.bars++;
@@ -1338,7 +1537,7 @@ AudioClock::bbt_frame_from_display (framepos_t pos) const
 
 
 framepos_t
-AudioClock::bbt_frame_duration_from_display (framepos_t pos) const
+AudioClock::frame_duration_from_bbt_string (framepos_t pos, const string& str) const
 {
        if (_session == 0) {
                error << "AudioClock::current_time() called with BBT mode but without session!" << endmsg;
@@ -1347,16 +1546,16 @@ AudioClock::bbt_frame_duration_from_display (framepos_t pos) const
 
        Timecode::BBT_Time bbt;
 
-       sscanf (_layout->get_text().c_str(), "%" PRIu32 "|%" PRIu32 "|%" PRIu32, &bbt.bars, &bbt.beats, &bbt.ticks);
+       sscanf (str.c_str(), "%" PRIu32 "|%" PRIu32 "|%" PRIu32, &bbt.bars, &bbt.beats, &bbt.ticks);
 
        return _session->tempo_map().bbt_duration_at(pos,bbt,1);
 }
 
 framepos_t
-AudioClock::audio_frame_from_display () const
+AudioClock::frames_from_audioframes_string (const string& str) const
 {
        framepos_t f;
-       sscanf (_layout->get_text().c_str(), "%" PRId64, &f);
+       sscanf (str.c_str(), "%" PRId64, &f);
        return f;
 }
 
@@ -1477,16 +1676,11 @@ AudioClock::set_off (bool yn)
 
        _off = yn;
 
-       if (_off) {
-               _canonical_time = current_time ();
-               _canonical_time_is_displayed = false;
-       } else {
-               _canonical_time_is_displayed = true;
-       }
-
-       /* force a possible redraw */
+       /* force a redraw. last_when will be preserved, but the clock text will
+        * change 
+        */
        
-       set (_canonical_time, true);
+       set (last_when, true);
 }
 
 void
@@ -1501,376 +1695,3 @@ AudioClock::set_draw_background (bool yn)
        _need_bg = yn;
 }
 
-void
-AudioClock::timecode_tester ()
-{
-#if 0
-#define Timecode_SAMPLE_TEST_1
-#define Timecode_SAMPLE_TEST_2
-#define Timecode_SAMPLE_TEST_3
-#define Timecode_SAMPLE_TEST_4
-#define Timecode_SAMPLE_TEST_5
-#define Timecode_SAMPLE_TEST_6
-#define Timecode_SAMPLE_TEST_7
-
-       // Testcode for timecode<->sample conversions (P.S.)
-       Timecode::Time timecode1;
-       framepos_t sample1;
-       framepos_t oldsample = 0;
-       Timecode::Time timecode2;
-       framecnt_t sample_increment;
-
-       sample_increment = (framecnt_t)rint(_session->frame_rate() / _session->timecode_frames_per_second);
-
-#ifdef Timecode_SAMPLE_TEST_1
-       // Test 1: use_offset = false, use_subframes = false
-       cout << "use_offset = false, use_subframes = false" << endl;
-       for (int i = 0; i < 108003; i++) {
-               _session->timecode_to_sample( timecode1, sample1, false /* use_offset */, false /* use_subframes */ );
-               _session->sample_to_timecode( sample1, timecode2, false /* use_offset */, false /* use_subframes */ );
-
-               if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
-                       cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
-                       cout << "timecode1: " << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << " -> ";
-                       cout << "sample: " << sample1 << endl;
-                       cout << "sample: " << sample1 << " -> ";
-                       cout << "timecode2: " << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
-                       break;
-               }
-
-               if (timecode2.hours != timecode1.hours || timecode2.minutes != timecode1.minutes || timecode2.seconds != timecode2.seconds || timecode2.frames != timecode1.frames) {
-                       cout << "ERROR: timecode2 not equal timecode1" << endl;
-                       cout << "timecode1: " << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << " -> ";
-                       cout << "sample: " << sample1 << endl;
-                       cout << "sample: " << sample1 << " -> ";
-                       cout << "timecode2: " << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
-                       break;
-               }
-               oldsample = sample1;
-               _session->timecode_increment( timecode1 );
-       }
-
-       cout << "sample_increment: " << sample_increment << endl;
-       cout << "sample: " << sample1 << " -> ";
-       cout << "timecode: " << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
-#endif
-
-#ifdef Timecode_SAMPLE_TEST_2
-       // Test 2: use_offset = true, use_subframes = false
-       cout << "use_offset = true, use_subframes = false" << endl;
-
-       timecode1.hours = 0;
-       timecode1.minutes = 0;
-       timecode1.seconds = 0;
-       timecode1.frames = 0;
-       timecode1.subframes = 0;
-       sample1 = oldsample = 0;
-
-       _session->sample_to_timecode( sample1, timecode1, true /* use_offset */, false /* use_subframes */ );
-       cout << "Starting at sample: " << sample1 << " -> ";
-       cout << "timecode: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << endl;
-
-       for (int i = 0; i < 108003; i++) {
-               _session->timecode_to_sample( timecode1, sample1, true /* use_offset */, false /* use_subframes */ );
-               _session->sample_to_timecode( sample1, timecode2, true /* use_offset */, false /* use_subframes */ );
-
-//     cout << "timecode: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << " -> ";
-//     cout << "sample: " << sample1 << endl;
-//     cout << "sample: " << sample1 << " -> ";
-//     cout << "timecode: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
-
-               if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
-                       cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
-                       cout << "timecode1: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << " -> ";
-                       cout << "sample: " << sample1 << endl;
-                       cout << "sample: " << sample1 << " -> ";
-                       cout << "timecode2: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
-                       break;
-               }
-
-               if (timecode2.hours != timecode1.hours || timecode2.minutes != timecode1.minutes || timecode2.seconds != timecode2.seconds || timecode2.frames != timecode1.frames) {
-                       cout << "ERROR: timecode2 not equal timecode1" << endl;
-                       cout << "timecode1: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << " -> ";
-                       cout << "sample: " << sample1 << endl;
-                       cout << "sample: " << sample1 << " -> ";
-                       cout << "timecode2: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
-                       break;
-               }
-               oldsample = sample1;
-               _session->timecode_increment( timecode1 );
-       }
-
-       cout << "sample_increment: " << sample_increment << endl;
-       cout << "sample: " << sample1 << " -> ";
-       cout << "timecode: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
-#endif
-
-#ifdef Timecode_SAMPLE_TEST_3
-       // Test 3: use_offset = true, use_subframes = false, decrement
-       cout << "use_offset = true, use_subframes = false, decrement" << endl;
-
-       _session->sample_to_timecode( sample1, timecode1, true /* use_offset */, false /* use_subframes */ );
-       cout << "Starting at sample: " << sample1 << " -> ";
-       cout << "timecode: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << endl;
-
-       for (int i = 0; i < 108003; i++) {
-               _session->timecode_to_sample( timecode1, sample1, true /* use_offset */, false /* use_subframes */ );
-               _session->sample_to_timecode( sample1, timecode2, true /* use_offset */, false /* use_subframes */ );
-
-//     cout << "timecode: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << " -> ";
-//     cout << "sample: " << sample1 << endl;
-//     cout << "sample: " << sample1 << " -> ";
-//     cout << "timecode: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
-
-               if ((i > 0) && ( ((oldsample - sample1) != sample_increment) && ((oldsample - sample1) != (sample_increment + 1)) && ((oldsample - sample1) != (sample_increment - 1)))) {
-                       cout << "ERROR: sample increment not right: " << (oldsample - sample1) << " != " << sample_increment << endl;
-                       cout << "timecode1: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << " -> ";
-                       cout << "sample: " << sample1 << endl;
-                       cout << "sample: " << sample1 << " -> ";
-                       cout << "timecode2: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
-                       break;
-               }
-
-               if (timecode2.hours != timecode1.hours || timecode2.minutes != timecode1.minutes || timecode2.seconds != timecode2.seconds || timecode2.frames != timecode1.frames) {
-                       cout << "ERROR: timecode2 not equal timecode1" << endl;
-                       cout << "timecode1: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << " -> ";
-                       cout << "sample: " << sample1 << endl;
-                       cout << "sample: " << sample1 << " -> ";
-                       cout << "timecode2: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
-                       break;
-               }
-               oldsample = sample1;
-               _session->timecode_decrement( timecode1 );
-       }
-
-       cout << "sample_decrement: " << sample_increment << endl;
-       cout << "sample: " << sample1 << " -> ";
-       cout << "timecode: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
-#endif
-
-
-#ifdef Timecode_SAMPLE_TEST_4
-       // Test 4: use_offset = true, use_subframes = true
-       cout << "use_offset = true, use_subframes = true" << endl;
-
-       for (long sub = 5; sub < 80; sub += 5) {
-               timecode1.hours = 0;
-               timecode1.minutes = 0;
-               timecode1.seconds = 0;
-               timecode1.frames = 0;
-               timecode1.subframes = 0;
-               sample1 = oldsample = (sample_increment * sub) / 80;
-
-               _session->sample_to_timecode( sample1, timecode1, true /* use_offset */, true /* use_subframes */ );
-
-               cout << "starting at sample: " << sample1 << " -> ";
-               cout << "timecode: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << endl;
-
-               for (int i = 0; i < 108003; i++) {
-                       _session->timecode_to_sample( timecode1, sample1, true /* use_offset */, true /* use_subframes */ );
-                       _session->sample_to_timecode( sample1, timecode2, true /* use_offset */, true /* use_subframes */ );
-
-                       if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1)))) {
-                               cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
-                               cout << "timecode1: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << " -> ";
-                               cout << "sample: " << sample1 << endl;
-                               cout << "sample: " << sample1 << " -> ";
-                               cout << "timecode2: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
-                               //break;
-                       }
-
-                       if (timecode2.hours != timecode1.hours || timecode2.minutes != timecode1.minutes || timecode2.seconds != timecode2.seconds || timecode2.frames != timecode1.frames || timecode2.subframes != timecode1.subframes) {
-                               cout << "ERROR: timecode2 not equal timecode1" << endl;
-                               cout << "timecode1: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << " -> ";
-                               cout << "sample: " << sample1 << endl;
-                               cout << "sample: " << sample1 << " -> ";
-                               cout << "timecode2: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
-                               break;
-                       }
-                       oldsample = sample1;
-                       _session->timecode_increment( timecode1 );
-               }
-
-               cout << "sample_increment: " << sample_increment << endl;
-               cout << "sample: " << sample1 << " -> ";
-               cout << "timecode: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
-
-               for (int i = 0; i < 108003; i++) {
-                       _session->timecode_to_sample( timecode1, sample1, true /* use_offset */, true /* use_subframes */ );
-                       _session->sample_to_timecode( sample1, timecode2, true /* use_offset */, true /* use_subframes */ );
-
-                       if ((i > 0) && ( ((oldsample - sample1) != sample_increment) && ((oldsample - sample1) != (sample_increment + 1)) && ((oldsample - sample1) != (sample_increment - 1)))) {
-                               cout << "ERROR: sample increment not right: " << (oldsample - sample1) << " != " << sample_increment << endl;
-                               cout << "timecode1: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << " -> ";
-                               cout << "sample: " << sample1 << endl;
-                               cout << "sample: " << sample1 << " -> ";
-                               cout << "timecode2: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
-                               //break;
-                       }
-
-                       if (timecode2.hours != timecode1.hours || timecode2.minutes != timecode1.minutes || timecode2.seconds != timecode2.seconds || timecode2.frames != timecode1.frames || timecode2.subframes != timecode1.subframes) {
-                               cout << "ERROR: timecode2 not equal timecode1" << endl;
-                               cout << "timecode1: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << " -> ";
-                               cout << "sample: " << sample1 << endl;
-                               cout << "sample: " << sample1 << " -> ";
-                               cout << "timecode2: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
-                               break;
-                       }
-                       oldsample = sample1;
-                       _session->timecode_decrement( timecode1 );
-               }
-
-               cout << "sample_decrement: " << sample_increment << endl;
-               cout << "sample: " << sample1 << " -> ";
-               cout << "timecode: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
-       }
-#endif
-
-
-#ifdef Timecode_SAMPLE_TEST_5
-       // Test 5: use_offset = true, use_subframes = false, increment seconds
-       cout << "use_offset = true, use_subframes = false, increment seconds" << endl;
-
-       timecode1.hours = 0;
-       timecode1.minutes = 0;
-       timecode1.seconds = 0;
-       timecode1.frames = 0;
-       timecode1.subframes = 0;
-       sample1 = oldsample = 0;
-       sample_increment = _session->frame_rate();
-
-       _session->sample_to_timecode( sample1, timecode1, true /* use_offset */, false /* use_subframes */ );
-       cout << "Starting at sample: " << sample1 << " -> ";
-       cout << "timecode: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << endl;
-
-       for (int i = 0; i < 3600; i++) {
-               _session->timecode_to_sample( timecode1, sample1, true /* use_offset */, false /* use_subframes */ );
-               _session->sample_to_timecode( sample1, timecode2, true /* use_offset */, false /* use_subframes */ );
-
-//     cout << "timecode: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << " -> ";
-//     cout << "sample: " << sample1 << endl;
-//     cout << "sample: " << sample1 << " -> ";
-//     cout << "timecode: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
-
-//     if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
-//     {
-//       cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
-//       break;
-//     }
-
-               if (timecode2.hours != timecode1.hours || timecode2.minutes != timecode1.minutes || timecode2.seconds != timecode2.seconds || timecode2.frames != timecode1.frames) {
-                       cout << "ERROR: timecode2 not equal timecode1" << endl;
-                       cout << "timecode: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << " -> ";
-                       cout << "sample: " << sample1 << endl;
-                       cout << "sample: " << sample1 << " -> ";
-                       cout << "timecode: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
-                       break;
-               }
-               oldsample = sample1;
-               _session->timecode_increment_seconds( timecode1 );
-       }
-
-       cout << "sample_increment: " << sample_increment << endl;
-       cout << "sample: " << sample1 << " -> ";
-       cout << "timecode: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
-#endif
-
-
-#ifdef Timecode_SAMPLE_TEST_6
-       // Test 6: use_offset = true, use_subframes = false, increment minutes
-       cout << "use_offset = true, use_subframes = false, increment minutes" << endl;
-
-       timecode1.hours = 0;
-       timecode1.minutes = 0;
-       timecode1.seconds = 0;
-       timecode1.frames = 0;
-       timecode1.subframes = 0;
-       sample1 = oldsample = 0;
-       sample_increment = _session->frame_rate() * 60;
-
-       _session->sample_to_timecode( sample1, timecode1, true /* use_offset */, false /* use_subframes */ );
-       cout << "Starting at sample: " << sample1 << " -> ";
-       cout << "timecode: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << endl;
-
-       for (int i = 0; i < 60; i++) {
-               _session->timecode_to_sample( timecode1, sample1, true /* use_offset */, false /* use_subframes */ );
-               _session->sample_to_timecode( sample1, timecode2, true /* use_offset */, false /* use_subframes */ );
-
-//     cout << "timecode: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << " -> ";
-//     cout << "sample: " << sample1 << endl;
-//     cout << "sample: " << sample1 << " -> ";
-//     cout << "timecode: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
-
-//     if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
-//     {
-//       cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
-//       break;
-//     }
-
-               if (timecode2.hours != timecode1.hours || timecode2.minutes != timecode1.minutes || timecode2.seconds != timecode2.seconds || timecode2.frames != timecode1.frames) {
-                       cout << "ERROR: timecode2 not equal timecode1" << endl;
-                       cout << "timecode: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << " -> ";
-                       cout << "sample: " << sample1 << endl;
-                       cout << "sample: " << sample1 << " -> ";
-                       cout << "timecode: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
-                       break;
-               }
-               oldsample = sample1;
-               _session->timecode_increment_minutes( timecode1 );
-       }
-
-       cout << "sample_increment: " << sample_increment << endl;
-       cout << "sample: " << sample1 << " -> ";
-       cout << "timecode: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
-#endif
-
-#ifdef Timecode_SAMPLE_TEST_7
-       // Test 7: use_offset = true, use_subframes = false, increment hours
-       cout << "use_offset = true, use_subframes = false, increment hours" << endl;
-
-       timecode1.hours = 0;
-       timecode1.minutes = 0;
-       timecode1.seconds = 0;
-       timecode1.frames = 0;
-       timecode1.subframes = 0;
-       sample1 = oldsample = 0;
-       sample_increment = _session->frame_rate() * 60 * 60;
-
-       _session->sample_to_timecode( sample1, timecode1, true /* use_offset */, false /* use_subframes */ );
-       cout << "Starting at sample: " << sample1 << " -> ";
-       cout << "timecode: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << endl;
-
-       for (int i = 0; i < 10; i++) {
-               _session->timecode_to_sample( timecode1, sample1, true /* use_offset */, false /* use_subframes */ );
-               _session->sample_to_timecode( sample1, timecode2, true /* use_offset */, false /* use_subframes */ );
-
-//     cout << "timecode: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << " -> ";
-//     cout << "sample: " << sample1 << endl;
-//     cout << "sample: " << sample1 << " -> ";
-//     cout << "timecode: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
-
-//     if ((i > 0) && ( ((sample1 - oldsample) != sample_increment) && ((sample1 - oldsample) != (sample_increment + 1)) && ((sample1 - oldsample) != (sample_increment - 1))))
-//     {
-//       cout << "ERROR: sample increment not right: " << (sample1 - oldsample) << " != " << sample_increment << endl;
-//       break;
-//     }
-
-               if (timecode2.hours != timecode1.hours || timecode2.minutes != timecode1.minutes || timecode2.seconds != timecode2.seconds || timecode2.frames != timecode1.frames) {
-                       cout << "ERROR: timecode2 not equal timecode1" << endl;
-                       cout << "timecode: " << (timecode1.negative ? "-" : "") << timecode1.hours << ":" << timecode1.minutes << ":" << timecode1.seconds << ":" << timecode1.frames << "::" << timecode1.subframes << " -> ";
-                       cout << "sample: " << sample1 << endl;
-                       cout << "sample: " << sample1 << " -> ";
-                       cout << "timecode: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
-                       break;
-               }
-               oldsample = sample1;
-               _session->timecode_increment_hours( timecode1 );
-       }
-
-       cout << "sample_increment: " << sample_increment << endl;
-       cout << "sample: " << sample1 << " -> ";
-       cout << "timecode: " << (timecode2.negative ? "-" : "") << timecode2.hours << ":" << timecode2.minutes << ":" << timecode2.seconds << ":" << timecode2.frames << "::" << timecode2.subframes << endl;
-#endif
-
-#endif
-}