implement deleting of sysex events
authorHans Baier <hansfbaier@googlemail.com>
Thu, 11 Oct 2012 03:22:17 +0000 (03:22 +0000)
committerHans Baier <hansfbaier@googlemail.com>
Thu, 11 Oct 2012 03:22:17 +0000 (03:22 +0000)
git-svn-id: svn://localhost/ardour2/branches/3.0@13238 d708f5d6-7413-0410-9779-e7cbd77b26cf

gtk2_ardour/canvas-flag.h
gtk2_ardour/canvas-sysex.cc
gtk2_ardour/canvas-sysex.h
gtk2_ardour/midi_region_view.cc
gtk2_ardour/midi_region_view.h
libs/ardour/ardour/midi_model.h
libs/ardour/midi_model.cc
libs/evoral/evoral/Sequence.hpp
libs/evoral/src/Sequence.cpp

index 4ad41ec8833191b4b912d0e5acb4d22b9d510c64..f82e6a9504bfba625aa84dec6cb8739d1bb55497 100644 (file)
@@ -19,27 +19,27 @@ class CanvasFlag : public Group
 {
 public:
        CanvasFlag (MidiRegionView& region,
-                   Group&          parent,
-                   double          height,
-                   guint           outline_color_rgba = 0xc0c0c0ff,
-                   guint           fill_color_rgba = 0x07070707,
-                   double          x = 0.0,
-                   double          y = 0.0);
+                   Group&          parent,
+                   double         height,
+                   guint           outline_color_rgba = 0xc0c0c0ff,
+                   guint           fill_color_rgba = 0x07070707,
+                   double         x = 0.0,
+                   double         y = 0.0);
 
        virtual ~CanvasFlag();
 
        virtual void set_text(const std::string& a_text);
        virtual void set_height (double);
 
-        int width () const { return name_pixbuf_width + 10.0; }
-    
+       int width () const { return name_pixbuf_width + 10.0; }
+
 protected:
        ArdourCanvas::Pixbuf* _name_pixbuf;
        double           _height;
        guint            _outline_color_rgba;
        guint            _fill_color_rgba;
        MidiRegionView&  _region;
-        int name_pixbuf_width;
+       int name_pixbuf_width;
 
 private:
        void delete_allocated_objects();
index 667b493d5c4f0411ce92db00bcd529cb63c33ad2..f8948d596e8877aa2ba91e226badc0baaa987178 100644 (file)
@@ -21,6 +21,7 @@
 
 #include "ardour_ui.h"
 
+#include "midi_region_view.h"
 #include "canvas-sysex.h"
 
 using namespace Gnome::Canvas;
@@ -32,7 +33,8 @@ CanvasSysEx::CanvasSysEx(
                string&         text,
                double          height,
                double          x,
-               double          y)
+               double          y,
+               const ARDOUR::MidiModel::SysExPtr sysex)
        : CanvasFlag(
                        region,
                        parent,
@@ -40,7 +42,8 @@ CanvasSysEx::CanvasSysEx(
                        ARDOUR_UI::config()->canvasvar_MidiSysExOutline.get(),
                        ARDOUR_UI::config()->canvasvar_MidiSysExFill.get(),
                        x,
-                       y)
+                       y),
+       _sysex(sysex)
 {
        set_text(text);
 }
@@ -67,6 +70,29 @@ CanvasSysEx::on_event(GdkEvent* ev)
                }
                break;
 
+       case GDK_KEY_PRESS:
+               switch (ev->key.keyval) {
+
+               case GDK_Delete:
+               case GDK_BackSpace:
+                       _region.delete_sysex (this);
+                       break;
+               default:
+                       break;
+               }
+               break;
+
+       case GDK_ENTER_NOTIFY:
+               grab_focus();
+               return true;
+               break;
+
+       case GDK_LEAVE_NOTIFY:
+       /* focus will transfer back via the enter-notify
+        * event sent to the midi region view.
+        */
+       break;
+
        default:
                break;
        }
index 718f81fd6a23f87fbfa2657f97de08133ed65bce..6cee8df97b9e9c17b45f90f08bf5443926480680 100644 (file)
@@ -23,6 +23,7 @@
 #include <string>
 
 #include "canvas-flag.h"
+#include "ardour/midi_model.h"
 
 class MidiRegionView;
 
@@ -38,11 +39,17 @@ public:
                        std::string&    text,
                        double          height,
                        double          x,
-                       double          y);
+                       double          y,
+                       ARDOUR::MidiModel::SysExPtr sysex);
 
        virtual ~CanvasSysEx();
 
+       const ARDOUR::MidiModel::SysExPtr sysex() const { return _sysex; }
+
        virtual bool on_event(GdkEvent* ev);
+
+private:
+       const ARDOUR::MidiModel::SysExPtr _sysex;
 };
 
 } // namespace Canvas
index 0ede957a45c7a2d773f6df865d7878c62b2634c3..ce29e6dcba5d5592ac05da6f0ca88b4043c099b2 100644 (file)
@@ -48,6 +48,7 @@
 #include "canvas-hit.h"
 #include "canvas-note.h"
 #include "canvas_patch_change.h"
+#include "canvas-sysex.h"
 #include "debug.h"
 #include "editor.h"
 #include "editor_drag.h"
@@ -1296,7 +1297,7 @@ MidiRegionView::display_sysexes()
                double height = midi_stream_view()->contents_height();
 
                boost::shared_ptr<CanvasSysEx> sysex = boost::shared_ptr<CanvasSysEx>(
-                       new CanvasSysEx(*this, *_note_group, text, height, x, 1.0));
+                       new CanvasSysEx(*this, *_note_group, text, height, x, 1.0, (*i)));
 
                // Show unless message is beyond the region bounds
                if (time - _region->start() >= _region->length() || time < _region->start()) {
@@ -3752,6 +3753,18 @@ MidiRegionView::edit_patch_change (ArdourCanvas::CanvasPatchChange* pc)
        change_patch_change (pc->patch(), d.patch ());
 }
 
+void
+MidiRegionView::delete_sysex (CanvasSysEx* sysex)
+{
+       cerr << "about to delete sysex " << sysex->sysex() << endl;
+
+       MidiModel::SysExDiffCommand* c = _model->new_sysex_diff_command (_("delete sysex"));
+       c->remove (sysex->sysex());
+       _model->apply_command (*trackview.session(), c);
+
+       _sys_exes.clear ();
+       display_sysexes();
+}
 
 void
 MidiRegionView::show_verbose_cursor (boost::shared_ptr<NoteType> n) const
index 7674ea245f78d544ebc3c3141f7eedca478d5c77..f3dd827b1978a4437ed6fb03a58f4d0502fb7818 100644 (file)
@@ -145,6 +145,8 @@ public:
        void delete_patch_change (ArdourCanvas::CanvasPatchChange *);
        void edit_patch_change (ArdourCanvas::CanvasPatchChange *);
 
+       void delete_sysex (ArdourCanvas::CanvasSysEx*);
+
        /** Alter a given patch to be its predecessor in the MIDNAM file.
         */
        void previous_patch (ArdourCanvas::CanvasPatchChange &);
index 38bd3ab982f26d1df57c90728e8a625472f11d6f..0d11f940b9ddf6d219ddab6abe10ced11ff293a8 100644 (file)
@@ -152,6 +152,7 @@ public:
                int set_state (const XMLNode&, int version);
                XMLNode & get_state ();
 
+               void remove (SysExPtr sysex);
                void operator() ();
                void undo ();
 
@@ -168,6 +169,8 @@ public:
                typedef std::list<Change> ChangeList;
                ChangeList _changes;
 
+               std::list<SysExPtr> _removed;
+
                XMLNode & marshal_change (const Change &);
                Change unmarshal_change (XMLNode *);
        };
index e86b229c71585077d209eb6bdea7d80ee8ca47d0..4c6f6633d5e2a7ec90cd2dc3f3822f198f2d43ac 100644 (file)
@@ -786,6 +786,10 @@ MidiModel::SysExDiffCommand::operator() ()
        {
                MidiModel::WriteLock lock (_model->edit_lock ());
 
+               for (list<SysExPtr>::iterator i = _removed.begin(); i != _removed.end(); ++i) {
+                       _model->remove_sysex_unlocked (*i);
+               }
+
                for (ChangeList::iterator i = _changes.begin(); i != _changes.end(); ++i) {
                        switch (i->property) {
                        case Time:
@@ -803,6 +807,10 @@ MidiModel::SysExDiffCommand::undo ()
        {
                MidiModel::WriteLock lock (_model->edit_lock ());
 
+               for (list<SysExPtr>::iterator i = _removed.begin(); i != _removed.end(); ++i) {
+                       _model->add_sysex_unlocked (*i);
+               }
+
                for (ChangeList::iterator i = _changes.begin(); i != _changes.end(); ++i) {
                        switch (i->property) {
                        case Time:
@@ -816,6 +824,12 @@ MidiModel::SysExDiffCommand::undo ()
        _model->ContentsChanged(); /* EMIT SIGNAL */
 }
 
+void
+MidiModel::SysExDiffCommand::remove (SysExPtr sysex)
+{
+       _removed.push_back(sysex);
+}
+
 XMLNode&
 MidiModel::SysExDiffCommand::marshal_change (const Change& change)
 {
index cb851cf2f60434f1a249702357eac6466d5da304..815d02f980ebb716d4adf4b80b35504e852d1b62 100644 (file)
@@ -181,7 +181,16 @@ public:
 
        void set_notes (const Sequence<Time>::Notes& n);
 
-       typedef std::vector< boost::shared_ptr< Event<Time> > > SysExes;
+       typedef boost::shared_ptr< Event<Time> > SysExPtr;
+       typedef boost::shared_ptr<const Event<Time> > constSysExPtr;
+
+       struct EarlierSysExComparator {
+               inline bool operator() (constSysExPtr a, constSysExPtr b) const {
+                       return a->time() < b->time();
+               }
+       };
+
+       typedef std::multiset<SysExPtr, EarlierSysExComparator> SysExes;
        inline       SysExes& sysexes()       { return _sysexes; }
        inline const SysExes& sysexes() const { return _sysexes; }
 
@@ -262,6 +271,7 @@ public:
 
        typename Notes::const_iterator note_lower_bound (Time t) const;
        typename PatchChanges::const_iterator patch_change_lower_bound (Time t) const;
+       typename SysExes::const_iterator sysex_lower_bound (Time t) const;
 
        bool control_to_midi_event(boost::shared_ptr< Event<Time> >& ev,
                                   const ControlIterator&            iter) const;
@@ -279,6 +289,9 @@ public:
        void add_patch_change_unlocked (const PatchChangePtr);
        void remove_patch_change_unlocked (const constPatchChangePtr);
 
+       void add_sysex_unlocked (const SysExPtr);
+       void remove_sysex_unlocked (const SysExPtr);
+
        uint8_t lowest_note()  const { return _lowest_note; }
        uint8_t highest_note() const { return _highest_note; }
 
index 7a8a08cfdfd26994d94064b9e200ba158136fa56..1b5683320cbcacd96051953d155dd6cb841a6c37 100644 (file)
@@ -494,7 +494,7 @@ Sequence<Time>::Sequence(const Sequence<Time>& other)
 
        for (typename SysExes::const_iterator i = other._sysexes.begin(); i != other._sysexes.end(); ++i) {
                boost::shared_ptr<Event<Time> > n (new Event<Time> (**i, true));
-               _sysexes.push_back (n);
+               _sysexes.insert (n);
        }
 
        for (typename PatchChanges::const_iterator i = other._patch_changes.begin(); i != other._patch_changes.end(); ++i) {
@@ -788,6 +788,24 @@ Sequence<Time>::remove_patch_change_unlocked (const constPatchChangePtr p)
        }
 }
 
+template<typename Time>
+void
+Sequence<Time>::remove_sysex_unlocked (const SysExPtr sysex)
+{
+       typename Sequence<Time>::SysExes::iterator i = sysex_lower_bound (sysex->time ());
+       while (i != _sysexes.end() && (*i)->time() == sysex->time()) {
+
+               typename Sequence<Time>::SysExes::iterator tmp = i;
+               ++tmp;
+
+               if (*i == sysex) {
+                       _sysexes.erase (i);
+               }
+
+               i = tmp;
+       }
+}
+
 /** Append \a ev to model.  NOT realtime safe.
  *
  * The timestamp of event is expected to be relative to
@@ -984,7 +1002,7 @@ Sequence<Time>::append_sysex_unlocked(const MIDIEvent<Time>& ev, event_id_t /* e
 
        boost::shared_ptr<MIDIEvent<Time> > event(new MIDIEvent<Time>(ev, true));
        /* XXX sysex events should use IDs */
-       _sysexes.push_back(event);
+       _sysexes.insert(event);
 }
 
 template<typename Time>
@@ -1011,6 +1029,17 @@ Sequence<Time>::add_patch_change_unlocked (PatchChangePtr p)
        _patch_changes.insert (p);
 }
 
+template<typename Time>
+void
+Sequence<Time>::add_sysex_unlocked (SysExPtr s)
+{
+       if (s->id () < 0) {
+               s->set_id (Evoral::next_event_id ());
+       }
+
+       _sysexes.insert (s);
+}
+
 template<typename Time>
 bool
 Sequence<Time>::contains (const NotePtr& note) const
@@ -1105,6 +1134,17 @@ Sequence<Time>::patch_change_lower_bound (Time t) const
        return i;
 }
 
+/** Return the earliest sysex with time >= t */
+template<typename Time>
+typename Sequence<Time>::SysExes::const_iterator
+Sequence<Time>::sysex_lower_bound (Time t) const
+{
+       SysExPtr search (new Event<Time> (0, t));
+       typename Sequence<Time>::SysExes::const_iterator i = _sysexes.lower_bound (search);
+       assert (i == _sysexes.end() || (*i)->time() >= t);
+       return i;
+}
+
 template<typename Time>
 void
 Sequence<Time>::get_notes (Notes& n, NoteOperator op, uint8_t val, int chan_mask) const