summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gtk2_ardour/canvas-flag.h18
-rw-r--r--gtk2_ardour/canvas-sysex.cc30
-rw-r--r--gtk2_ardour/canvas-sysex.h9
-rw-r--r--gtk2_ardour/midi_region_view.cc15
-rw-r--r--gtk2_ardour/midi_region_view.h2
-rw-r--r--libs/ardour/ardour/midi_model.h3
-rw-r--r--libs/ardour/midi_model.cc14
-rw-r--r--libs/evoral/evoral/Sequence.hpp15
-rw-r--r--libs/evoral/src/Sequence.cpp44
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