diff options
-rw-r--r-- | gtk2_ardour/SConscript | 1 | ||||
-rw-r--r-- | gtk2_ardour/canvas-hit.h | 4 | ||||
-rw-r--r-- | gtk2_ardour/canvas-midi-event.cc | 24 | ||||
-rw-r--r-- | gtk2_ardour/canvas-midi-event.h | 4 | ||||
-rw-r--r-- | gtk2_ardour/canvas-note.cc | 4 | ||||
-rw-r--r-- | gtk2_ardour/canvas-note.h | 2 | ||||
-rw-r--r-- | gtk2_ardour/canvas-program-change.cc | 58 | ||||
-rw-r--r-- | gtk2_ardour/canvas-program-change.h | 43 | ||||
-rw-r--r-- | gtk2_ardour/canvas_vars.h | 2 | ||||
-rw-r--r-- | gtk2_ardour/ghostregion.cc | 2 | ||||
-rw-r--r-- | gtk2_ardour/ghostregion.h | 6 | ||||
-rw-r--r-- | gtk2_ardour/midi_region_view.cc | 32 | ||||
-rw-r--r-- | gtk2_ardour/midi_region_view.h | 21 | ||||
-rw-r--r-- | libs/ardour/midi_model.cc | 17 |
14 files changed, 180 insertions, 40 deletions
diff --git a/gtk2_ardour/SConscript b/gtk2_ardour/SConscript index 5b4fa141f9..aceb587998 100644 --- a/gtk2_ardour/SConscript +++ b/gtk2_ardour/SConscript @@ -131,6 +131,7 @@ automation_streamview.cc automation_time_axis.cc axis_view.cc bundle_manager.cc +canvas-program-change.cc canvas-midi-event.cc canvas-note.cc canvas-simpleline.c diff --git a/gtk2_ardour/canvas-hit.h b/gtk2_ardour/canvas-hit.h index e9be381ef2..ffa1764003 100644 --- a/gtk2_ardour/canvas-hit.h +++ b/gtk2_ardour/canvas-hit.h @@ -27,7 +27,7 @@ namespace Gnome { namespace Canvas { -class CanvasHit : public Diamond, public CanvasMidiEvent { +class CanvasHit : public Diamond, public CanvasNoteEvent { public: CanvasHit( MidiRegionView& region, @@ -47,7 +47,7 @@ public: void set_outline_color(uint32_t c) { property_outline_color_rgba() = c; } void set_fill_color(uint32_t c) { property_fill_color_rgba() = c; } - bool on_event(GdkEvent* ev) { return CanvasMidiEvent::on_event(ev); } + bool on_event(GdkEvent* ev) { return CanvasNoteEvent::on_event(ev); } }; } // namespace Gnome diff --git a/gtk2_ardour/canvas-midi-event.cc b/gtk2_ardour/canvas-midi-event.cc index f87ae135cb..20804260b2 100644 --- a/gtk2_ardour/canvas-midi-event.cc +++ b/gtk2_ardour/canvas-midi-event.cc @@ -31,7 +31,7 @@ namespace Gnome { namespace Canvas { -CanvasMidiEvent::CanvasMidiEvent(MidiRegionView& region, Item* item, +CanvasNoteEvent::CanvasMidiEvent(MidiRegionView& region, Item* item, const boost::shared_ptr<ARDOUR::Note> note) : _region(region) , _item(item) @@ -44,21 +44,21 @@ CanvasMidiEvent::CanvasMidiEvent(MidiRegionView& region, Item* item, _text = new Text(*(item->property_parent())); } -CanvasMidiEvent::~CanvasMidiEvent() +CanvasNoteEvent::~CanvasNoteEvent() { if(_text) delete _text; if(_channel_selector_widget) delete _channel_selector_widget; } void -CanvasMidiEvent::move_event(double dx, double dy) +CanvasNoteEvent::move_event(double dx, double dy) { _item->move(dx, dy); _text->move(dx, dy); } void -CanvasMidiEvent::show_velocity(void) +CanvasNoteEvent::show_velocity(void) { _text->property_x() = (x1() + x2()) /2; _text->property_y() = (y1() + y2()) /2; @@ -73,13 +73,13 @@ CanvasMidiEvent::show_velocity(void) } void -CanvasMidiEvent::hide_velocity(void) +CanvasNoteEvent::hide_velocity(void) { _text->hide(); } void -CanvasMidiEvent::on_channel_selection_change(uint16_t selection) +CanvasNoteEvent::on_channel_selection_change(uint16_t selection) { // make note change its color if its channel is not marked active if( (selection & (1 << _note->channel())) == 0 ) { @@ -95,7 +95,7 @@ CanvasMidiEvent::on_channel_selection_change(uint16_t selection) } void -CanvasMidiEvent::on_channel_change(uint8_t channel) +CanvasNoteEvent::on_channel_change(uint8_t channel) { _region.note_selected(this, true); hide_channel_selector(); @@ -103,14 +103,14 @@ CanvasMidiEvent::on_channel_change(uint8_t channel) } void -CanvasMidiEvent::show_channel_selector(void) +CanvasNoteEvent::show_channel_selector(void) { if(_channel_selector_widget == 0) { cerr << "Note has channel: " << int(_note->channel()) << endl; SingleMidiChannelSelector* _channel_selector = new SingleMidiChannelSelector(_note->channel()); _channel_selector->show_all(); _channel_selector->channel_selected.connect( - sigc::mem_fun(this, &CanvasMidiEvent::on_channel_change)); + sigc::mem_fun(this, &CanvasNoteEvent::on_channel_change)); _channel_selector_widget = new Widget(*(_item->property_parent()), @@ -129,7 +129,7 @@ CanvasMidiEvent::show_channel_selector(void) } void -CanvasMidiEvent::hide_channel_selector(void) +CanvasNoteEvent::hide_channel_selector(void) { if(_channel_selector_widget) { _channel_selector_widget->hide(); @@ -139,7 +139,7 @@ CanvasMidiEvent::hide_channel_selector(void) } void -CanvasMidiEvent::selected(bool yn) +CanvasNoteEvent::selected(bool yn) { if (!_note) { return; @@ -159,7 +159,7 @@ CanvasMidiEvent::selected(bool yn) bool -CanvasMidiEvent::on_event(GdkEvent* ev) +CanvasNoteEvent::on_event(GdkEvent* ev) { MidiStreamView *streamview = _region.midi_stream_view(); static uint8_t drag_delta_note = 0; diff --git a/gtk2_ardour/canvas-midi-event.h b/gtk2_ardour/canvas-midi-event.h index acb49b8984..bb076eea23 100644 --- a/gtk2_ardour/canvas-midi-event.h +++ b/gtk2_ardour/canvas-midi-event.h @@ -44,14 +44,14 @@ namespace Canvas { * * A newer, better canvas should remove the need for all the ugly here. */ -class CanvasMidiEvent : public sigc::trackable { +class CanvasNoteEvent : public sigc::trackable { public: CanvasMidiEvent( MidiRegionView& region, Item* item, const boost::shared_ptr<ARDOUR::Note> note = boost::shared_ptr<ARDOUR::Note>()); - virtual ~CanvasMidiEvent(); + virtual ~CanvasNoteEvent(); bool on_event(GdkEvent* ev); diff --git a/gtk2_ardour/canvas-note.cc b/gtk2_ardour/canvas-note.cc index bc15c3468d..30b1e3807b 100644 --- a/gtk2_ardour/canvas-note.cc +++ b/gtk2_ardour/canvas-note.cc @@ -80,11 +80,11 @@ CanvasNote::on_event(GdkEvent* ev) return true; default: - return CanvasMidiEvent::on_event(ev); + return CanvasNoteEvent::on_event(ev); } default: - return CanvasMidiEvent::on_event(ev); + return CanvasNoteEvent::on_event(ev); } } diff --git a/gtk2_ardour/canvas-note.h b/gtk2_ardour/canvas-note.h index 0a1aed8021..f404794b78 100644 --- a/gtk2_ardour/canvas-note.h +++ b/gtk2_ardour/canvas-note.h @@ -29,7 +29,7 @@ namespace Gnome { namespace Canvas { -class CanvasNote : public SimpleRect, public CanvasMidiEvent { +class CanvasNote : public SimpleRect, public CanvasNoteEvent { public: CanvasNote( MidiRegionView& region, diff --git a/gtk2_ardour/canvas-program-change.cc b/gtk2_ardour/canvas-program-change.cc new file mode 100644 index 0000000000..5883dd5b86 --- /dev/null +++ b/gtk2_ardour/canvas-program-change.cc @@ -0,0 +1,58 @@ +#include "canvas-program-change.h" +#include <iostream> + +using namespace ArdourCanvas; +using namespace std; + +CanvasProgramChange::CanvasProgramChange( + MidiRegionView& region, + Group& parent, + boost::shared_ptr<MIDI::Event> event, + double height, + double x, + double y) + : Group(parent, x, y), + _region(region), + _event(event), + _text(0), + _line(0), + _rect(0), + _widget(0) +{ + _text = new Text(*this); + ostringstream pgm(ios::ate); + pgm << int(event->pgm_number()); + _text->property_text() = pgm.str(); + _text->property_justification() = Gtk::JUSTIFY_CENTER; + _text->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_MidiProgramChangeOutline.get(); + double flagwidth = _text->property_text_width() + 10.0; + double flagheight = _text->property_text_height() + 3.0; + _text->property_x() = flagwidth / 2.0; + _text->property_y() = flagheight / 2.0; + _text->show(); + _line = new SimpleLine(*this, 0.0, 0.0, 0.0, height); + _line->property_color_rgba() = ARDOUR_UI::config()->canvasvar_MidiProgramChangeOutline.get(); + _rect = new SimpleRect(*this, 0.0, 0.0, flagwidth, flagheight); + _rect->property_outline_color_rgba() = ARDOUR_UI::config()->canvasvar_MidiProgramChangeOutline.get(); + _rect->property_fill_color_rgba() = ARDOUR_UI::config()->canvasvar_MidiProgramChangeFill.get(); + _text->lower_to_bottom(); + _text->raise(2); + assert(_widget == 0); + assert(_text != 0); + assert(_line != 0); + assert(_rect != 0); +} + +CanvasProgramChange::~CanvasProgramChange() +{ + if(_line) + delete _line; + if(_rect) + delete _rect; + if(_text) + delete _text; + if(_widget) + delete _widget; +} + + diff --git a/gtk2_ardour/canvas-program-change.h b/gtk2_ardour/canvas-program-change.h new file mode 100644 index 0000000000..cf99ca0715 --- /dev/null +++ b/gtk2_ardour/canvas-program-change.h @@ -0,0 +1,43 @@ +#ifndef CANVASPROGRAMCHANGE_H_ +#define CANVASPROGRAMCHANGE_H_ + +#include <libgnomecanvasmm/group.h> +#include "simplerect.h" +#include "simpleline.h" +#include "midi_region_view.h" +#include <libgnomecanvasmm/text.h> +#include <libgnomecanvasmm/widget.h> +#include <ardour/midi_model.h> + +namespace Gnome +{ +namespace Canvas +{ + +class CanvasProgramChange : public Group +{ +public: + CanvasProgramChange( + MidiRegionView& region, + Group& parent, + boost::shared_ptr<MIDI::Event> event, + double height, + double x = 0.0, + double y = 0.0 + ); + + virtual ~CanvasProgramChange(); + +private: + MidiRegionView& _region; + boost::shared_ptr<MIDI::Event> _event; + Text* _text; + SimpleLine* _line; + SimpleRect* _rect; + Widget* _widget; +}; + +} // namespace Canvas +} // namespace Gnome + +#endif /*CANVASPROGRAMCHANGE_H_*/ diff --git a/gtk2_ardour/canvas_vars.h b/gtk2_ardour/canvas_vars.h index 5a29309e67..44a710703b 100644 --- a/gtk2_ardour/canvas_vars.h +++ b/gtk2_ardour/canvas_vars.h @@ -65,6 +65,8 @@ CANVAS_VARIABLE(canvasvar_MidiNoteOutlineMid, "midi note outline mid") CANVAS_VARIABLE(canvasvar_MidiNoteOutlineMin, "midi note outline min") CANVAS_VARIABLE(canvasvar_MidiNoteOutlineInactiveChannel, "midi note outline inactive channel") CANVAS_VARIABLE(canvasvar_MidiNoteSelectedOutline, "midi note selected outline") +CANVAS_VARIABLE(canvasvar_MidiProgramChangeFill, "midi program change fill") +CANVAS_VARIABLE(canvasvar_MidiProgramChangeOutline, "midi program change outline") CANVAS_VARIABLE(canvasvar_MidiSelectRectFill, "midi select rect fill") CANVAS_VARIABLE(canvasvar_MidiSelectRectOutline, "midi select rect outline") CANVAS_VARIABLE(canvasvar_MidiTrackBase, "midi track base") diff --git a/gtk2_ardour/ghostregion.cc b/gtk2_ardour/ghostregion.cc index 6384baffa0..4e06ece82f 100644 --- a/gtk2_ardour/ghostregion.cc +++ b/gtk2_ardour/ghostregion.cc @@ -174,7 +174,7 @@ MidiGhostRegion::~MidiGhostRegion() //clear_events(); } -MidiGhostRegion::Event::Event(ArdourCanvas::CanvasMidiEvent* e) +MidiGhostRegion::Event::Event(ArdourCanvas::CanvasNoteEvent* e) : event(e) { } diff --git a/gtk2_ardour/ghostregion.h b/gtk2_ardour/ghostregion.h index 72658f2d53..885edfde59 100644 --- a/gtk2_ardour/ghostregion.h +++ b/gtk2_ardour/ghostregion.h @@ -28,7 +28,7 @@ namespace Gnome { namespace Canvas { - class CanvasMidiEvent; + class CanvasNoteEvent; class CanvasNote; class CanvasHit; class Diamond; @@ -76,11 +76,11 @@ class MidiGhostRegion : public GhostRegion { public: class Event : public sigc::trackable { public: - Event(ArdourCanvas::CanvasMidiEvent*); + Event(ArdourCanvas::CanvasNoteEvent*); virtual ~Event() {} virtual void x_changed() = 0; - ArdourCanvas::CanvasMidiEvent* event; + ArdourCanvas::CanvasNoteEvent* event; }; class Note : public Event { diff --git a/gtk2_ardour/midi_region_view.cc b/gtk2_ardour/midi_region_view.cc index 858f59af69..0d8d7984a2 100644 --- a/gtk2_ardour/midi_region_view.cc +++ b/gtk2_ardour/midi_region_view.cc @@ -41,6 +41,7 @@ #include "simpleline.h" #include "canvas-hit.h" #include "canvas-note.h" +#include "canvas-program-change.h" #include "public_editor.h" #include "ghostregion.h" #include "midi_time_axis.h" @@ -474,6 +475,16 @@ MidiRegionView::redisplay_model() add_note(_model->note_at(i)); } + MidiModel::PgmChanges& pgm_changes = _model->pgm_changes(); + /* + for (MidiModel::PgmChanges::const_iterator i = pgm_changes.begin(); + i != pgm_changes.end(); + ++i) { + add_pgm_change() + } + */ + for_each(pgm_changes.begin(), pgm_changes.end(), sigc::mem_fun(this, &MidiRegionView::add_pgm_change)); + end_write(); /*for (Automatable::Controls::const_iterator i = _model->controls().begin(); @@ -793,6 +804,27 @@ MidiRegionView::add_note(const boost::shared_ptr<Note> note) } void +MidiRegionView::add_pgm_change(boost::shared_ptr<MIDI::Event> event) +{ + assert(event->time() >= 0); + + // dont display notes beyond the region bounds + if( + event->time() - _region->start() >= _region->length() || + event->time() < _region->start() + ) { + return; + } + + ArdourCanvas::Group* const group = (ArdourCanvas::Group*)get_canvas_group(); + const double x = trackview.editor.frame_to_pixel((nframes_t)event->time() - _region->start()); + + double height = midi_stream_view()->contents_height(); + new CanvasProgramChange(*this, *group, event, height, x, 1.0); + //TODO : keep track of pgm changes +} + +void MidiRegionView::delete_selection() { assert(_delta_command); diff --git a/gtk2_ardour/midi_region_view.h b/gtk2_ardour/midi_region_view.h index bc5639476f..f380704d33 100644 --- a/gtk2_ardour/midi_region_view.h +++ b/gtk2_ardour/midi_region_view.h @@ -37,6 +37,7 @@ #include "canvas.h" #include "canvas-note.h" #include "canvas-midi-event.h" +#include "canvas-program-change.h" namespace ARDOUR { class MidiRegion; @@ -80,6 +81,8 @@ class MidiRegionView : public RegionView void add_note(const boost::shared_ptr<ARDOUR::Note> note); void resolve_note(uint8_t note_num, double end_time); + + void add_pgm_change(boost::shared_ptr<MIDI::Event> event); void begin_write(); void end_write(); @@ -101,7 +104,7 @@ class MidiRegionView : public RegionView _delta_command->add(note); } - void command_remove_note(ArdourCanvas::CanvasMidiEvent* ev) { + void command_remove_note(ArdourCanvas::CanvasNoteEvent* ev) { if (_delta_command && ev->note()) { _selection.erase(ev); _delta_command->remove(ev->note()); @@ -123,15 +126,15 @@ class MidiRegionView : public RegionView midi_view()->midi_track()->diskstream()->playlist_modified(); } - void note_entered(ArdourCanvas::CanvasMidiEvent* ev); - void unique_select(ArdourCanvas::CanvasMidiEvent* ev); - void note_selected(ArdourCanvas::CanvasMidiEvent* ev, bool add); - void note_deselected(ArdourCanvas::CanvasMidiEvent* ev, bool add); + void note_entered(ArdourCanvas::CanvasNoteEvent* ev); + void unique_select(ArdourCanvas::CanvasNoteEvent* ev); + void note_selected(ArdourCanvas::CanvasNoteEvent* ev, bool add); + void note_deselected(ArdourCanvas::CanvasNoteEvent* ev, bool add); void delete_selection(); size_t selection_size() { return _selection.size(); } void move_selection(double dx, double dy); - void note_dropped(ArdourCanvas::CanvasMidiEvent* ev, double dt, uint8_t dnote); + void note_dropped(ArdourCanvas::CanvasNoteEvent* ev, double dt, uint8_t dnote); /** * This function is needed to subtract the region start in pixels @@ -243,14 +246,14 @@ class MidiRegionView : public RegionView uint16_t last_channel_selection; void midi_channel_selection_changed(uint16_t selection); - void clear_selection_except(ArdourCanvas::CanvasMidiEvent* ev); + void clear_selection_except(ArdourCanvas::CanvasNoteEvent* ev); void clear_selection() { clear_selection_except(NULL); } void update_drag_selection(double last_x, double x, double last_y, double y); double _default_note_length; boost::shared_ptr<ARDOUR::MidiModel> _model; - std::vector<ArdourCanvas::CanvasMidiEvent*> _events; + std::vector<ArdourCanvas::CanvasNoteEvent*> _events; ArdourCanvas::CanvasNote** _active_notes; ArdourCanvas::Group* _note_group; ARDOUR::MidiModel::DeltaCommand* _delta_command; @@ -259,7 +262,7 @@ class MidiRegionView : public RegionView int _pressed_button; /// currently selected CanvasMidiEvents - typedef std::set<ArdourCanvas::CanvasMidiEvent*> Selection; + typedef std::set<ArdourCanvas::CanvasNoteEvent*> Selection; Selection _selection; /** diff --git a/libs/ardour/midi_model.cc b/libs/ardour/midi_model.cc index 4c811604ee..d2e24bafb7 100644 --- a/libs/ardour/midi_model.cc +++ b/libs/ardour/midi_model.cc @@ -87,6 +87,7 @@ MidiModel::const_iterator::const_iterator(const MidiModel& model, double t) } } + /* TODO: Disabled for stablility reasons MidiControlIterator earliest_control(boost::shared_ptr<AutomationList>(), DBL_MAX, 0.0); _control_iters.reserve(model.controls().size()); @@ -98,8 +99,8 @@ MidiModel::const_iterator::const_iterator(const MidiModel& model, double t) double x, y; bool ret = i->second->list()->rt_safe_earliest_event_unlocked(t, DBL_MAX, x, y); if (!ret) { - /*cerr << "MIDI Iterator: CC " << i->first.id() << " (size " << i->second->list()->size() - << ") has no events past " << t << endl;*/ + //cerr << "MIDI Iterator: CC " << i->first.id() << " (size " << i->second->list()->size() + // << ") has no events past " << t << endl; continue; } @@ -118,6 +119,8 @@ MidiModel::const_iterator::const_iterator(const MidiModel& model, double t) --_control_iter; } } + */ + if (_note_iter != model.notes().end()) { _event = MIDI::Event((*_note_iter)->on_event(), false); @@ -126,10 +129,12 @@ MidiModel::const_iterator::const_iterator(const MidiModel& model, double t) ++_note_iter; } + /** TODO: Disabled for stability reasons if (earliest_control.automation_list && earliest_control.x < _event.time()) model.control_to_midi_event(_event, earliest_control); else _control_iter = _control_iters.end(); + */ _pgm_change_iter = model.pgm_changes().end(); // find first program change which begins after t @@ -556,12 +561,13 @@ MidiModel::append_cc_unlocked(uint8_t chan, double time, uint8_t number, uint8_t assert(chan < 16); assert(_writing); + /** TODO: disabled for now until debugged.... _edited = true; Parameter param(MidiCCAutomation, number, chan); - boost::shared_ptr<AutomationControl> control = Automatable::control(param, true); control->list()->fast_simple_add(time, (double)value); + */ } void @@ -577,11 +583,6 @@ MidiModel::append_pgm_change_unlocked(uint8_t chan, double time, uint8_t number) event_ptr->set_channel(chan); event_ptr->set_pgm_number(number); _pgm_changes.push_back(event_ptr); - cerr << "MidiModel::append_pgm_change_unlocked: appended pgm change" << endl; - for(PgmChanges::iterator i = _pgm_changes.begin(); i != _pgm_changes.end(); ++i) { - cerr << "_pgm_changes contents: channel " << int((*i)->channel()) << dec << " time: " << int((*i)->time()) << hex << " program number: " << int(int((*i)->pgm_number())) <<endl; - } - //<< int(_pgm_changes.) << " time: " << time << " program number: " << int(number) <<endl; } void |