implement relative clock editing (terminated by + or - keys, which adjust the clock...
authorPaul Davis <paul@linuxaudiosystems.com>
Fri, 18 Nov 2011 05:04:18 +0000 (05:04 +0000)
committerPaul Davis <paul@linuxaudiosystems.com>
Fri, 18 Nov 2011 05:04:18 +0000 (05:04 +0000)
git-svn-id: svn://localhost/ardour2/branches/3.0@10670 d708f5d6-7413-0410-9779-e7cbd77b26cf

gtk2_ardour/audio_clock.cc
gtk2_ardour/audio_clock.h

index f3bde6187f755884743e46e11b67ca5bcc351341..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))
        , last_sdelta (0)
        , dragging (false)
        , drag_field (Field (0))
-       , _canonical_time_is_displayed (true)
-       , _canonical_time (0)
 
 {
        set_flags (CAN_FOCUS);
 
 {
        set_flags (CAN_FOCUS);
@@ -407,8 +405,36 @@ AudioClock::end_edit (bool modify)
                        edit_string = pre_edit_string;
                        input_string.clear ();
                        _layout->set_text (edit_string);
                        edit_string = pre_edit_string;
                        input_string.clear ();
                        _layout->set_text (edit_string);
+                       show_edit_status (1);
+                       /* edit attributes remain in use */
                } else {
                } else {
+
                        editing = false;
                        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 */
                }
                        _layout->set_attributes (normal_attributes);
                        ValueChanged(); /* EMIT_SIGNAL */
                }
@@ -422,17 +448,20 @@ AudioClock::end_edit (bool modify)
        queue_draw ();
 
        if (!editing) {
        queue_draw ();
 
        if (!editing) {
+               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 ();
-               }
+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 ();
        }
 }
 
        }
 }
 
@@ -451,12 +480,99 @@ AudioClock::parse_as_frames_distance (const std::string& str)
 framecnt_t 
 AudioClock::parse_as_minsec_distance (const std::string& str)
 {
 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);
+               
+       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)
 {
        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);
+               
+       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;
 }
 
        return 0;
 }
 
@@ -467,8 +583,14 @@ AudioClock::parse_as_bbt_distance (const std::string& str)
 }
 
 framecnt_t 
 }
 
 framecnt_t 
-AudioClock::parse_as_distance (const std::string& str)
+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);
        switch (_mode) {
        case Timecode:
                return parse_as_timecode_distance (str);
@@ -493,6 +615,9 @@ AudioClock::end_edit_relative (bool add)
 
        editing = false;
 
 
        editing = false;
 
+       editing = false;
+       _layout->set_attributes (normal_attributes);
+
        if (frames != 0) {
                if (add) {
                        set (current_time() + frames, true);
        if (frames != 0) {
                if (add) {
                        set (current_time() + frames, true);
@@ -505,18 +630,12 @@ AudioClock::end_edit_relative (bool add)
                                set (0, true);
                        }
                }
                                set (0, true);
                        }
                }
+               ValueChanged (); /* EMIT SIGNAL */
        }
 
        }
 
-       /* 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 ();
-       }
+       input_string.clear ();
+       queue_draw ();
+       drop_focus ();
 }
 
 void
 }
 
 void
@@ -602,10 +721,6 @@ AudioClock::set (framepos_t when, bool force, framecnt_t offset, char which)
        }
 
        last_when = when;
        }
 
        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
 }
 
 void
@@ -912,11 +1027,13 @@ AudioClock::on_key_release_event (GdkEventKey *ev)
        case GDK_minus:
        case GDK_KP_Subtract:
                end_edit_relative (false);
        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);
                break;
 
        case GDK_plus:
        case GDK_KP_Add:
                end_edit_relative (true);
+               return true;
                break;
 
        case GDK_Tab:
                break;
 
        case GDK_Tab:
@@ -1287,30 +1404,7 @@ AudioClock::get_frame_step (Field field, framepos_t pos, int dir)
 framepos_t
 AudioClock::current_time (framepos_t pos) const
 {
 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
 }
 
 framepos_t
@@ -1320,18 +1414,18 @@ AudioClock::current_duration (framepos_t pos) const
 
        switch (_mode) {
        case Timecode:
 
        switch (_mode) {
        case Timecode:
-               ret = timecode_frame_from_display ();
+               ret = last_when;
                break;
        case BBT:
                break;
        case BBT:
-               ret = bbt_frame_duration_from_display (pos);
+               ret = frame_duration_from_bbt_string (pos, _layout->get_text());
                break;
 
        case MinSec:
                break;
 
        case MinSec:
-               ret = minsec_frame_from_display ();
+               ret = last_when;
                break;
 
        case Frames:
                break;
 
        case Frames:
-               ret = audio_frame_from_display ();
+               ret = last_when;
                break;
        }
 
                break;
        }
 
@@ -1384,7 +1478,7 @@ AudioClock::timecode_validate_edit (const string& str)
 }
 
 framepos_t
 }
 
 framepos_t
-AudioClock::timecode_frame_from_display () const
+AudioClock::frames_from_timecode_string (const string& str) const
 {
        if (_session == 0) {
                return 0;
 {
        if (_session == 0) {
                return 0;
@@ -1393,7 +1487,7 @@ AudioClock::timecode_frame_from_display () const
        Timecode::Time TC;
        framepos_t sample;
 
        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();
 
        TC.rate = _session->timecode_frames_per_second();
        TC.drop= _session->timecode_drop_frames();
@@ -1406,7 +1500,7 @@ AudioClock::timecode_frame_from_display () const
 }
 
 framepos_t
 }
 
 framepos_t
-AudioClock::minsec_frame_from_display () const
+AudioClock::frames_from_minsec_string (const string& str) const
 {
        if (_session == 0) {
                return 0;
 {
        if (_session == 0) {
                return 0;
@@ -1415,12 +1509,12 @@ AudioClock::minsec_frame_from_display () const
        int hrs, mins, secs, millisecs;
        framecnt_t sr = _session->frame_rate();
 
        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
        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;
 {
        if (_session == 0) {
                error << "AudioClock::current_time() called with BBT mode but without session!" << endmsg;
@@ -1430,7 +1524,7 @@ AudioClock::bbt_frame_from_display (framepos_t pos) const
        AnyTime any;
        any.type = AnyTime::BBT;
 
        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++;
 
        if (is_duration) {
                any.bbt.bars++;
@@ -1443,7 +1537,7 @@ AudioClock::bbt_frame_from_display (framepos_t pos) const
 
 
 framepos_t
 
 
 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;
 {
        if (_session == 0) {
                error << "AudioClock::current_time() called with BBT mode but without session!" << endmsg;
@@ -1452,16 +1546,16 @@ AudioClock::bbt_frame_duration_from_display (framepos_t pos) const
 
        Timecode::BBT_Time bbt;
 
 
        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
 
        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;
 {
        framepos_t f;
-       sscanf (_layout->get_text().c_str(), "%" PRId64, &f);
+       sscanf (str.c_str(), "%" PRId64, &f);
        return f;
 }
 
        return f;
 }
 
@@ -1582,16 +1676,11 @@ AudioClock::set_off (bool yn)
 
        _off = 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
 }
 
 void
index 061e790735272d9efaa797763d4edd2b0e60b8d2..3f3c5dc84657f7a9d217f052130fc56931979173 100644 (file)
@@ -152,13 +152,6 @@ class AudioClock : public CairoWidget, public ARDOUR::SessionHandlePtr
        double drag_accum;
        Field  drag_field;
 
        double drag_accum;
        Field  drag_field;
 
-       /** true if the time of this clock is the one displayed in its widgets.
-        *  if false, the time in the widgets is an approximation of _canonical_time,
-        *  and _canonical_time should be returned as the `current' time of the clock.
-        */
-       bool _canonical_time_is_displayed;
-       framepos_t _canonical_time;
-
        void on_realize ();
        bool on_key_press_event (GdkEventKey *);
        bool on_key_release_event (GdkEventKey *);
        void on_realize ();
        bool on_key_press_event (GdkEventKey *);
        bool on_key_release_event (GdkEventKey *);
@@ -181,11 +174,11 @@ class AudioClock : public CairoWidget, public ARDOUR::SessionHandlePtr
        bool timecode_validate_edit (const std::string&);
        bool bbt_validate_edit (const std::string&);
 
        bool timecode_validate_edit (const std::string&);
        bool bbt_validate_edit (const std::string&);
 
-       framepos_t timecode_frame_from_display () const;
-       framepos_t bbt_frame_from_display (framepos_t) const;
-       framepos_t bbt_frame_duration_from_display (framepos_t) const;
-       framepos_t minsec_frame_from_display () const;
-       framepos_t audio_frame_from_display () const;
+       framepos_t frames_from_timecode_string (const std::string&) const;
+       framepos_t frames_from_bbt_string (framepos_t, const std::string&) const;
+       framepos_t frame_duration_from_bbt_string (framepos_t, const std::string&) const;
+       framepos_t frames_from_minsec_string (const std::string&) const;
+       framepos_t frames_from_audioframes_string (const std::string&) const;
 
        void build_ops_menu ();
 
 
        void build_ops_menu ();
 
@@ -208,8 +201,8 @@ class AudioClock : public CairoWidget, public ARDOUR::SessionHandlePtr
        void set_colors ();
        void show_edit_status (int length);
 
        void set_colors ();
        void show_edit_status (int length);
 
-       void timecode_tester ();
-
+       void drop_focus ();
+       
        double bg_r, bg_g, bg_b, bg_a;
 };
 
        double bg_r, bg_g, bg_b, bg_a;
 };