diff options
-rw-r--r-- | gtk2_ardour/canvas-flag.h | 18 | ||||
-rw-r--r-- | gtk2_ardour/canvas-sysex.cc | 30 | ||||
-rw-r--r-- | gtk2_ardour/canvas-sysex.h | 9 | ||||
-rw-r--r-- | gtk2_ardour/midi_region_view.cc | 15 | ||||
-rw-r--r-- | gtk2_ardour/midi_region_view.h | 2 | ||||
-rw-r--r-- | libs/ardour/ardour/midi_model.h | 3 | ||||
-rw-r--r-- | libs/ardour/midi_model.cc | 14 | ||||
-rw-r--r-- | libs/evoral/evoral/Sequence.hpp | 15 | ||||
-rw-r--r-- | libs/evoral/src/Sequence.cpp | 44 |
9 files changed, 134 insertions, 16 deletions
diff --git a/gtk2_ardour/canvas-flag.h b/gtk2_ardour/canvas-flag.h index 4ad41ec883..f82e6a9504 100644 --- a/gtk2_ardour/canvas-flag.h +++ b/gtk2_ardour/canvas-flag.h @@ -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(); diff --git a/gtk2_ardour/canvas-sysex.cc b/gtk2_ardour/canvas-sysex.cc index 667b493d5c..f8948d596e 100644 --- a/gtk2_ardour/canvas-sysex.cc +++ b/gtk2_ardour/canvas-sysex.cc @@ -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; } diff --git a/gtk2_ardour/canvas-sysex.h b/gtk2_ardour/canvas-sysex.h index 718f81fd6a..6cee8df97b 100644 --- a/gtk2_ardour/canvas-sysex.h +++ b/gtk2_ardour/canvas-sysex.h @@ -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 diff --git a/gtk2_ardour/midi_region_view.cc b/gtk2_ardour/midi_region_view.cc index 0ede957a45..ce29e6dcba 100644 --- a/gtk2_ardour/midi_region_view.cc +++ b/gtk2_ardour/midi_region_view.cc @@ -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 diff --git a/gtk2_ardour/midi_region_view.h b/gtk2_ardour/midi_region_view.h index 7674ea245f..f3dd827b19 100644 --- a/gtk2_ardour/midi_region_view.h +++ b/gtk2_ardour/midi_region_view.h @@ -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 &); diff --git a/libs/ardour/ardour/midi_model.h b/libs/ardour/ardour/midi_model.h index 38bd3ab982..0d11f940b9 100644 --- a/libs/ardour/ardour/midi_model.h +++ b/libs/ardour/ardour/midi_model.h @@ -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 *); }; diff --git a/libs/ardour/midi_model.cc b/libs/ardour/midi_model.cc index e86b229c71..4c6f6633d5 100644 --- a/libs/ardour/midi_model.cc +++ b/libs/ardour/midi_model.cc @@ -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) { diff --git a/libs/evoral/evoral/Sequence.hpp b/libs/evoral/evoral/Sequence.hpp index cb851cf2f6..815d02f980 100644 --- a/libs/evoral/evoral/Sequence.hpp +++ b/libs/evoral/evoral/Sequence.hpp @@ -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; } diff --git a/libs/evoral/src/Sequence.cpp b/libs/evoral/src/Sequence.cpp index 7a8a08cfdf..1b5683320c 100644 --- a/libs/evoral/src/Sequence.cpp +++ b/libs/evoral/src/Sequence.cpp @@ -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> @@ -1012,6 +1030,17 @@ Sequence<Time>::add_patch_change_unlocked (PatchChangePtr 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 |