diff --git a/gtk2_ardour/canvas-midi-event.cc b/gtk2_ardour/canvas-midi-event.cc index 6c5c0598f3..73c2b29925 100644 --- a/gtk2_ardour/canvas-midi-event.cc +++ b/gtk2_ardour/canvas-midi-event.cc @@ -74,7 +74,7 @@ CanvasMidiEvent::on_event(GdkEvent* ev) case GDK_MOTION_NOTIFY: event_x = ev->motion.x; event_y = ev->motion.y; - cerr << "MOTION @ " << event_x << ", " << event_y << endl; + //cerr << "MOTION @ " << event_x << ", " << event_y << endl; _item->property_parent().get_value()->w2i(event_x, event_y); switch (_state) { diff --git a/gtk2_ardour/midi_region_view.cc b/gtk2_ardour/midi_region_view.cc index 3110cdd600..755e896f6c 100644 --- a/gtk2_ardour/midi_region_view.cc +++ b/gtk2_ardour/midi_region_view.cc @@ -74,10 +74,9 @@ MidiRegionView::MidiRegionView (ArdourCanvas::Group *parent, RouteTimeAxisView & void MidiRegionView::init (Gdk::Color& basic_color, bool wfd) { - // FIXME: Some redundancy here with RegionView::init. Need to figure out - // where order is important and where it isn't... + if (wfd) + _model = midi_region()->midi_source(0)->model(); - // FIXME RegionView::init(basic_color, /*wfd*/false); compute_colors (basic_color); @@ -94,13 +93,10 @@ MidiRegionView::init (Gdk::Color& basic_color, bool wfd) set_colors (); - if (wfd) { - midi_region()->midi_source(0)->load_model(); - display_events(); - } + if (wfd) + redisplay_model(); - midi_region()->midi_source(0)->model()->ContentsChanged.connect(sigc::mem_fun( - this, &MidiRegionView::redisplay_model)); + _model->ContentsChanged.connect(sigc::mem_fun(this, &MidiRegionView::redisplay_model)); group->signal_event().connect (mem_fun (this, &MidiRegionView::canvas_event), false); } @@ -109,10 +105,13 @@ bool MidiRegionView::canvas_event(GdkEvent* ev) { enum State { None, Pressed, Dragging }; + static int press_button = 0; static State _state; static double last_x, last_y; double event_x, event_y; + + static ArdourCanvas::SimpleRect* select_rect = NULL; if (trackview.editor.current_mouse_mode() != MouseNote) return false; @@ -120,29 +119,40 @@ MidiRegionView::canvas_event(GdkEvent* ev) switch (ev->type) { case GDK_BUTTON_PRESS: //group->grab(GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK, ev->button.time); - // This should happen on release... - if (ev->button.button == 1) - create_note_at(ev->button.x, ev->button.y); - _state = Pressed; + press_button = ev->button.button; + cerr << "PRESSED: " << press_button << endl; return true; case GDK_MOTION_NOTIFY: - cerr << "MOTION, _state = " << _state << endl; event_x = ev->motion.x; event_y = ev->motion.y; group->w2i(event_x, event_y); switch (_state) { - case Pressed: - cerr << "SELECT DRAG START\n"; - group->grab(GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK, - Gdk::Cursor(Gdk::FLEUR), ev->motion.time); + case Pressed: // Drag start + cerr << "PRESSED MOTION: " << press_button << endl; + if (press_button == 1) { // Select rect start + group->grab(GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK, + Gdk::Cursor(Gdk::FLEUR), ev->motion.time); + _state = Dragging; + last_x = event_x; + last_y = event_y; + + select_rect = new ArdourCanvas::SimpleRect(*group); + select_rect->property_x1() = event_x; + select_rect->property_y1() = event_y; + select_rect->property_x2() = event_x; + select_rect->property_y2() = event_y; + select_rect->property_outline_color_rgba() = 0xFF000099; + select_rect->property_fill_color_rgba() = 0xFFDDDD33; + + return true; + } _state = Dragging; - last_x = event_x; - last_y = event_y; - return true; - case Dragging: + break; + + case Dragging: // Select rect motion if (ev->motion.is_hint) { int t_x; int t_y; @@ -152,30 +162,33 @@ MidiRegionView::canvas_event(GdkEvent* ev) event_y = t_y; } - cerr << "SELECT DRAG" << endl; - //move(event_x - last_x, event_y - last_y); + if (select_rect) { + select_rect->property_x2() = event_x; + select_rect->property_y2() = event_y; + } last_x = event_x; last_y = event_y; return true; default: + _state = None; break; } break; case GDK_BUTTON_RELEASE: - cerr << "RELEASE\n"; group->ungrab(ev->button.time); switch (_state) { - case Pressed: - cerr << "CLICK\n"; - //create_note_at(ev->button.x, ev->button.y); + case Pressed: // Clicked + if (ev->button.button == 1) + create_note_at(ev->button.x, ev->button.y); _state = None; return true; - case Dragging: - cerr << "SELECT RECT DONE\n"; + case Dragging: // Select rect done _state = None; + delete select_rect; + select_rect = NULL; return true; default: break; @@ -214,14 +227,12 @@ MidiRegionView::create_note_at(double x, double y) const Tempo& t = trackview.session().tempo_map().tempo_at(stamp); double dur = m.frames_per_bar(t, trackview.session().frame_rate()) / m.beats_per_bar(); - MidiModel* model = midi_region()->midi_source(0)->model(); - // Add a 1 beat long note (for now) const MidiModel::Note new_note(stamp, dur, (uint8_t)note, 0x40); - model->begin_command(); - model->add_note(new_note); - model->finish_command(); + _model->begin_command(); + _model->add_note(new_note); + _model->finish_command(); view->update_bounds(new_note.note()); @@ -229,14 +240,6 @@ MidiRegionView::create_note_at(double x, double y) } -void -MidiRegionView::redisplay_model() -{ - clear_events(); - display_events(); -} - - void MidiRegionView::clear_events() { @@ -248,16 +251,29 @@ MidiRegionView::clear_events() void -MidiRegionView::display_events() +MidiRegionView::display_model(boost::shared_ptr model) +{ + _model = model; + redisplay_model(); +} + + +void +MidiRegionView::redisplay_model() { clear_events(); - begin_write(); + if (_model) { + begin_write(); - for (size_t i=0; i < midi_region()->midi_source(0)->model()->n_notes(); ++i) - add_note(midi_region()->midi_source(0)->model()->note_at(i)); + for (size_t i=0; i < _model->n_notes(); ++i) + add_note(_model->note_at(i)); - end_write(); + end_write(); + } else { + assert(false); + warning << "MidiRegionView::redisplay_model called without a model" << endmsg; + } } @@ -283,7 +299,7 @@ MidiRegionView::region_resized (Change what_changed) if (what_changed & ARDOUR::PositionChanged) { - display_events(); + redisplay_model(); } else if (what_changed & Change (StartChanged)) { @@ -302,7 +318,7 @@ MidiRegionView::reset_width_dependent_items (double pixel_width) RegionView::reset_width_dependent_items(pixel_width); assert(_pixel_width == pixel_width); - display_events(); + redisplay_model(); } void @@ -310,7 +326,7 @@ MidiRegionView::set_y_position_and_height (double y, double h) { RegionView::set_y_position_and_height(y, h - 1); - display_events(); + redisplay_model(); if (name_text) { name_text->raise_to_top(); diff --git a/gtk2_ardour/midi_region_view.h b/gtk2_ardour/midi_region_view.h index bfac56209d..9207ca6b21 100644 --- a/gtk2_ardour/midi_region_view.h +++ b/gtk2_ardour/midi_region_view.h @@ -37,6 +37,7 @@ namespace ARDOUR { class MidiRegion; + class MidiModel; }; class MidiTimeAxisView; @@ -54,7 +55,7 @@ class MidiRegionView : public RegionView ~MidiRegionView (); - virtual void init (Gdk::Color& base_color, bool wait_for_data = false); + virtual void init (Gdk::Color& basic_color, bool wfd); boost::shared_ptr midi_region() const; @@ -73,6 +74,8 @@ class MidiRegionView : public RegionView void create_note_at(double x, double y); + void display_model(boost::shared_ptr model); + protected: /* this constructor allows derived types @@ -97,14 +100,14 @@ class MidiRegionView : public RegionView private: void redisplay_model(); - void display_events(); void clear_events(); bool canvas_event(GdkEvent* ev); bool note_canvas_event(GdkEvent* ev); - std::vector _events; - ArdourCanvas::CanvasNote** _active_notes; + boost::shared_ptr _model; + std::vector _events; + ArdourCanvas::CanvasNote** _active_notes; }; #endif /* __gtk_ardour_midi_region_view_h__ */ diff --git a/gtk2_ardour/midi_streamview.cc b/gtk2_ardour/midi_streamview.cc index 7d3c05a876..51a0543d18 100644 --- a/gtk2_ardour/midi_streamview.cc +++ b/gtk2_ardour/midi_streamview.cc @@ -93,15 +93,12 @@ MidiStreamView::add_region_view_internal (boost::shared_ptr r, bool wait /* great. we already have a MidiRegionView for this Region. use it again. */ (*i)->set_valid (true); - display_region(dynamic_cast(*i), false); + display_region(dynamic_cast(*i)); return NULL; } } - // can't we all just get along? - assert(_trackview.midi_track()->mode() != Destructive); - region_view = new MidiRegionView (canvas_group, _trackview, region, _samples_per_unit, region_color); @@ -114,7 +111,7 @@ MidiStreamView::add_region_view_internal (boost::shared_ptr r, bool wait //region_view->set_waveform_visible(_trackview.editor.show_waveforms()); /* display events and find note range */ - display_region(region_view, false); + display_region(region_view); /* always display at least 1 octave range */ _highest_note = max(_highest_note, static_cast(_lowest_note + 11)); @@ -128,27 +125,22 @@ MidiStreamView::add_region_view_internal (boost::shared_ptr r, bool wait } void -MidiStreamView::display_region(MidiRegionView* region_view, bool redisplay_events) +MidiStreamView::display_region(MidiRegionView* region_view) { if ( ! region_view) return; - if (redisplay_events) - region_view->begin_write(); - boost::shared_ptr source(region_view->midi_region()->midi_source(0)); + source->load_model(); + // Find our note range for (size_t i=0; i < source->model()->n_notes(); ++i) { const MidiModel::Note& note = source->model()->note_at(i); - update_bounds(note.note()); - - if (redisplay_events) - region_view->add_note(note); } - if (redisplay_events) - region_view->end_write(); + // Display region contents + region_view->display_model(source->model()); } // FIXME: code duplication with AudioStreamView diff --git a/gtk2_ardour/midi_streamview.h b/gtk2_ardour/midi_streamview.h index b8ae33cf46..baaf33d67d 100644 --- a/gtk2_ardour/midi_streamview.h +++ b/gtk2_ardour/midi_streamview.h @@ -79,7 +79,7 @@ class MidiStreamView : public StreamView void update_rec_regions (boost::shared_ptr data, jack_nframes_t start, jack_nframes_t dur); RegionView* add_region_view_internal (boost::shared_ptr, bool wait_for_waves); - void display_region(MidiRegionView* region_view, bool redisplay_events); + void display_region(MidiRegionView* region_view); void color_handler (); diff --git a/libs/ardour/ardour/midi_source.h b/libs/ardour/ardour/midi_source.h index 9917a0cb42..ba4fe99604 100644 --- a/libs/ardour/ardour/midi_source.h +++ b/libs/ardour/ardour/midi_source.h @@ -77,7 +77,7 @@ class MidiSource : public Source void set_note_mode(NoteMode mode) { if (_model) _model->set_note_mode(mode); } virtual bool model_loaded() const { return _model_loaded; } - MidiModel* model() { return _model; } + boost::shared_ptr model() { return _model; } protected: virtual nframes_t read_unlocked (MidiRingBuffer& dst, nframes_t start, nframes_t cnt, nframes_t stamp_offset) const = 0; @@ -88,8 +88,8 @@ class MidiSource : public Source mutable uint32_t _read_data_count; ///< modified in read() mutable uint32_t _write_data_count; ///< modified in write() - MidiModel* _model; - bool _model_loaded; + boost::shared_ptr _model; + bool _model_loaded; private: bool file_changed (string path); diff --git a/libs/ardour/midi_source.cc b/libs/ardour/midi_source.cc index 238bf4f481..09e574c2ed 100644 --- a/libs/ardour/midi_source.cc +++ b/libs/ardour/midi_source.cc @@ -66,7 +66,6 @@ MidiSource::MidiSource (Session& s, const XMLNode& node) MidiSource::~MidiSource () { - delete _model; } XMLNode& diff --git a/libs/ardour/smf_source.cc b/libs/ardour/smf_source.cc index eac782853f..d9a46ec782 100644 --- a/libs/ardour/smf_source.cc +++ b/libs/ardour/smf_source.cc @@ -805,7 +805,7 @@ SMFSource::load_model(bool lock, bool force_reload) } if (! _model) { - _model = new MidiModel(_session); + _model = boost::shared_ptr(new MidiModel(_session)); } else { cerr << "SMFSource: Reloading model." << endl; _model->clear(); @@ -855,7 +855,6 @@ SMFSource::load_model(bool lock, bool force_reload) void SMFSource::destroy_model() { - delete _model; - _model = NULL; + _model.reset(); }