From 31a6e0b2541f7e0f84fc3293930eff021f31d84b Mon Sep 17 00:00:00 2001 From: David Robillard Date: Mon, 16 Feb 2009 05:54:12 +0000 Subject: [PATCH] Fix time / positioning of PC flags (beat time). Fix needless string copying in flag stuff. Clean up. git-svn-id: svn://localhost/ardour2/branches/3.0@4601 d708f5d6-7413-0410-9779-e7cbd77b26cf --- gtk2_ardour/canvas-flag.cc | 3 +- gtk2_ardour/canvas-flag.h | 47 +++---- gtk2_ardour/canvas-program-change.cc | 2 +- gtk2_ardour/canvas-program-change.h | 2 +- gtk2_ardour/midi_region_view.cc | 182 ++++++++++++++------------- gtk2_ardour/midi_region_view.h | 37 +++--- 6 files changed, 134 insertions(+), 139 deletions(-) diff --git a/gtk2_ardour/canvas-flag.cc b/gtk2_ardour/canvas-flag.cc index 199f4d4054..41a2fbe8e4 100644 --- a/gtk2_ardour/canvas-flag.cc +++ b/gtk2_ardour/canvas-flag.cc @@ -5,7 +5,6 @@ using namespace Gnome::Canvas; using namespace std; - void CanvasFlag::delete_allocated_objects() { @@ -20,7 +19,7 @@ CanvasFlag::delete_allocated_objects() } void -CanvasFlag::set_text(string& a_text) +CanvasFlag::set_text(const string& a_text) { delete_allocated_objects(); diff --git a/gtk2_ardour/canvas-flag.h b/gtk2_ardour/canvas-flag.h index c48f78b358..ad8c506d65 100644 --- a/gtk2_ardour/canvas-flag.h +++ b/gtk2_ardour/canvas-flag.h @@ -1,6 +1,7 @@ #ifndef CANVASFLAG_H_ #define CANVASFLAG_H_ +#include #include #include @@ -19,41 +20,41 @@ class CanvasFlag : public Group, public InteractiveItem { 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, x, y) - , _text(0) - , _height(height) - , _outline_color_rgba(outline_color_rgba) - , _fill_color_rgba(fill_color_rgba) - , _region(region) - , _line(0) - , _rect(0) + 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, x, y) + , _text(0) + , _height(height) + , _outline_color_rgba(outline_color_rgba) + , _fill_color_rgba(fill_color_rgba) + , _region(region) + , _line(0) + , _rect(0) {} virtual ~CanvasFlag(); virtual bool on_event(GdkEvent* ev); - void set_text(string& a_text); + void set_text(const std::string& a_text); protected: - InteractiveText* _text; - double _height; - guint _outline_color_rgba; - guint _fill_color_rgba; - MidiRegionView& _region; + InteractiveText* _text; + double _height; + guint _outline_color_rgba; + guint _fill_color_rgba; + MidiRegionView& _region; private: void delete_allocated_objects(); - SimpleLine* _line; - InteractiveRect* _rect; + SimpleLine* _line; + InteractiveRect* _rect; }; diff --git a/gtk2_ardour/canvas-program-change.cc b/gtk2_ardour/canvas-program-change.cc index badadd22a7..94e367b345 100644 --- a/gtk2_ardour/canvas-program-change.cc +++ b/gtk2_ardour/canvas-program-change.cc @@ -14,7 +14,7 @@ using namespace std; CanvasProgramChange::CanvasProgramChange( MidiRegionView& region, Group& parent, - string& text, + const string& text, double height, double x, double y, diff --git a/gtk2_ardour/canvas-program-change.h b/gtk2_ardour/canvas-program-change.h index b4014a56a6..ef69089f93 100644 --- a/gtk2_ardour/canvas-program-change.h +++ b/gtk2_ardour/canvas-program-change.h @@ -20,7 +20,7 @@ public: CanvasProgramChange( MidiRegionView& region, Group& parent, - string& text, + const string& text, double height, double x, double y, diff --git a/gtk2_ardour/midi_region_view.cc b/gtk2_ardour/midi_region_view.cc index 67e1c4948a..d7d5afbb0d 100644 --- a/gtk2_ardour/midi_region_view.cc +++ b/gtk2_ardour/midi_region_view.cc @@ -609,8 +609,7 @@ MidiRegionView::display_program_change_flags() MIDI::Name::MidiPatchManager::instance().find_patch( _model_name, _custom_device_mode, channel, patch_key); - ControlEvent program_change(beats_to_frames(event_time), - uint8_t(program_number), channel); + PCEvent program_change(event_time, uint8_t(program_number), channel); if (patch != 0) { add_pgm_change(program_change, patch->name()); @@ -753,7 +752,7 @@ MidiRegionView::add_ghost (TimeAxisView& tv) if (mtv && mtv->midi_view()) { /* if ghost is inserted into midi track, use a dedicated midi ghost canvas group - to allow having midi notes on top of note lines and waveforms under it. + to allow having midi notes on top of note lines and waveforms. */ ghost = new MidiGhostRegion (*mtv->midi_view(), trackview, unit_position); } else { @@ -921,10 +920,7 @@ MidiRegionView::add_note(const boost::shared_ptr note) if (_active_notes[note->note()]) { CanvasNote* const old_rect = _active_notes[note->note()]; boost::shared_ptr old_note = old_rect->note(); - cerr << "MidiModel: WARNING: Note has length 0: chan " << old_note->channel() - << "note " << (int)old_note->note() << " @ " << old_note->time() << endl; - /* FIXME: How large to make it? Make it a diamond? */ - old_rect->property_x2() = old_rect->property_x1() + 2.0; + old_rect->property_x2() = x; old_rect->property_outline_what() = (guint32) 0xF; } _active_notes[note->note()] = ev_rect; @@ -971,16 +967,12 @@ MidiRegionView::add_note(const boost::shared_ptr note) } void -MidiRegionView::add_pgm_change(ControlEvent& program, string displaytext) +MidiRegionView::add_pgm_change(PCEvent& program, const string& displaytext) { assert(program.time >= 0); - // dont display program changes beyond the region bounds - if (program.time - _region->start() >= _region->length() || program.time < _region->start()) - return; - ArdourCanvas::Group* const group = (ArdourCanvas::Group*)get_canvas_group(); - const double x = trackview.editor().frame_to_pixel((nframes64_t)program.time - _region->start()); + const double x = trackview.editor().frame_to_pixel(beats_to_frames(program.time)); double height = midi_stream_view()->contents_height(); @@ -993,6 +985,13 @@ MidiRegionView::add_pgm_change(ControlEvent& program, string displaytext) _custom_device_mode, program.time, program.channel, program.value)); + // Show unless program change is beyond the region bounds + if (program.time - _region->start() >= _region->length() || program.time < _region->start()) { + pgm_change->hide(); + } else { + pgm_change->show(); + } + _pgm_changes.push_back(pgm_change); } @@ -1001,7 +1000,7 @@ MidiRegionView::get_patch_key_at(double time, uint8_t channel, MIDI::Name::Patch { cerr << "getting patch key at " << time << " for channel " << channel << endl; Evoral::Parameter bank_select_msb(MidiCCAutomation, channel, MIDI_CTL_MSB_BANK); - boost::shared_ptr msb_control = _model->control(bank_select_msb); + boost::shared_ptr msb_control = _model->control(bank_select_msb); float msb = -1.0; if (msb_control != 0) { msb = int(msb_control->get_float(true, time)); @@ -1009,7 +1008,7 @@ MidiRegionView::get_patch_key_at(double time, uint8_t channel, MIDI::Name::Patch } Evoral::Parameter bank_select_lsb(MidiCCAutomation, channel, MIDI_CTL_LSB_BANK); - boost::shared_ptr lsb_control = _model->control(bank_select_lsb); + boost::shared_ptr lsb_control = _model->control(bank_select_lsb); float lsb = -1.0; if (lsb_control != 0) { lsb = lsb_control->get_float(true, time); @@ -1017,7 +1016,7 @@ MidiRegionView::get_patch_key_at(double time, uint8_t channel, MIDI::Name::Patch } Evoral::Parameter program_change(MidiPgmChangeAutomation, channel, 0); - boost::shared_ptr program_control = _model->control(program_change); + boost::shared_ptr program_control = _model->control(program_change); float program_number = -1.0; if (program_control != 0) { program_number = program_control->get_float(true, time); @@ -1032,24 +1031,24 @@ MidiRegionView::get_patch_key_at(double time, uint8_t channel, MIDI::Name::Patch void -MidiRegionView::alter_program_change(ControlEvent& old_program, const MIDI::Name::PatchPrimaryKey& new_patch) +MidiRegionView::alter_program_change(PCEvent& old_program, const MIDI::Name::PatchPrimaryKey& new_patch) { // TODO: Get the real event here and alter them at the original times Evoral::Parameter bank_select_msb(MidiCCAutomation, old_program.channel, MIDI_CTL_MSB_BANK); - boost::shared_ptr msb_control = _model->control(bank_select_msb); + boost::shared_ptr msb_control = _model->control(bank_select_msb); if (msb_control != 0) { msb_control->set_float(float(new_patch.msb), true, old_program.time); } // TODO: Get the real event here and alter them at the original times Evoral::Parameter bank_select_lsb(MidiCCAutomation, old_program.channel, MIDI_CTL_LSB_BANK); - boost::shared_ptr lsb_control = _model->control(bank_select_lsb); + boost::shared_ptr lsb_control = _model->control(bank_select_lsb); if (lsb_control != 0) { lsb_control->set_float(float(new_patch.lsb), true, old_program.time); } Evoral::Parameter program_change(MidiPgmChangeAutomation, old_program.channel, 0); - boost::shared_ptr program_control = _model->control(program_change); + boost::shared_ptr program_control = _model->control(program_change); assert(program_control != 0); program_control->set_float(float(new_patch.program_number), true, old_program.time); @@ -1060,7 +1059,7 @@ MidiRegionView::alter_program_change(ControlEvent& old_program, const MIDI::Name void MidiRegionView::program_selected(CanvasProgramChange& program, const MIDI::Name::PatchPrimaryKey& new_patch) { - ControlEvent program_change_event(program.event_time(), program.program(), program.channel()); + PCEvent program_change_event(program.event_time(), program.program(), program.channel()); alter_program_change(program_change_event, new_patch); } @@ -1077,7 +1076,7 @@ MidiRegionView::previous_program(CanvasProgramChange& program) program.channel(), key); - ControlEvent program_change_event(program.event_time(), program.program(), program.channel()); + PCEvent program_change_event(program.event_time(), program.program(), program.channel()); if (patch) { alter_program_change(program_change_event, patch->patch_primary_key()); } @@ -1095,7 +1094,8 @@ MidiRegionView::next_program(CanvasProgramChange& program) _custom_device_mode, program.channel(), key); - ControlEvent program_change_event(program.event_time(), program.program(), program.channel()); + + PCEvent program_change_event(program.event_time(), program.program(), program.channel()); if (patch) { alter_program_change(program_change_event, patch->patch_primary_key()); } @@ -1246,81 +1246,83 @@ void MidiRegionView::note_dropped(CanvasNoteEvent* ev, double dt, uint8_t dnote) { // TODO: This would be faster/nicer with a MoveCommand that doesn't need to copy... - if (_selection.find(ev) != _selection.end()) { - uint8_t lowest_note_in_selection = midi_stream_view()->lowest_note(); - uint8_t highest_note_in_selection = midi_stream_view()->highest_note(); - uint8_t highest_note_difference = 0; + if (_selection.find(ev) == _selection.end()) { + return; + } - // find highest and lowest notes first - for (Selection::iterator i = _selection.begin(); i != _selection.end(); ++i) { - uint8_t pitch = (*i)->note()->note(); - lowest_note_in_selection = std::min(lowest_note_in_selection, pitch); - highest_note_in_selection = std::max(highest_note_in_selection, pitch); + uint8_t lowest_note_in_selection = midi_stream_view()->lowest_note(); + uint8_t highest_note_in_selection = midi_stream_view()->highest_note(); + uint8_t highest_note_difference = 0; + + // find highest and lowest notes first + for (Selection::iterator i = _selection.begin(); i != _selection.end(); ++i) { + uint8_t pitch = (*i)->note()->note(); + lowest_note_in_selection = std::min(lowest_note_in_selection, pitch); + highest_note_in_selection = std::max(highest_note_in_selection, pitch); + } + + /* + cerr << "dnote: " << (int) dnote << endl; + cerr << "lowest note (streamview): " << int(midi_stream_view()->lowest_note()) + << " highest note (streamview): " << int(midi_stream_view()->highest_note()) << endl; + cerr << "lowest note (selection): " << int(lowest_note_in_selection) << " highest note(selection): " + << int(highest_note_in_selection) << endl; + cerr << "selection size: " << _selection.size() << endl; + cerr << "Highest note in selection: " << (int) highest_note_in_selection << endl; + */ + + // Make sure the note pitch does not exceed the MIDI standard range + if (dnote <= 127 && (highest_note_in_selection + dnote > 127)) { + highest_note_difference = highest_note_in_selection - 127; + } + + start_delta_command(_("move notes")); + + for (Selection::iterator i = _selection.begin(); i != _selection.end() ; ) { + Selection::iterator next = i; + ++next; + + const boost::shared_ptr copy(new NoteType(*(*i)->note().get())); + + // we need to snap here again in nframes64_t in order to be sample accurate + double start_frames = snap_to_frame(beats_to_frames((*i)->note()->time()) + dt); + + // keep notes inside region if dragged beyond left region bound + if (start_frames < _region->start()) { + start_frames = _region->start(); } - /* - cerr << "dnote: " << (int) dnote << endl; - cerr << "lowest note (streamview): " << int(midi_stream_view()->lowest_note()) - << " highest note (streamview): " << int(midi_stream_view()->highest_note()) << endl; - cerr << "lowest note (selection): " << int(lowest_note_in_selection) << " highest note(selection): " - << int(highest_note_in_selection) << endl; - cerr << "selection size: " << _selection.size() << endl; - cerr << "Highest note in selection: " << (int) highest_note_in_selection << endl; - */ + copy->set_time(frames_to_beats(start_frames)); + + uint8_t original_pitch = (*i)->note()->note(); + uint8_t new_pitch = original_pitch + dnote - highest_note_difference; - // Make sure the note pitch does not exceed the MIDI standard range - if (dnote <= 127 && (highest_note_in_selection + dnote > 127)) { - highest_note_difference = highest_note_in_selection - 127; - } + // keep notes in standard midi range + clamp_to_0_127(new_pitch); - start_delta_command(_("move notes")); - - for (Selection::iterator i = _selection.begin(); i != _selection.end() ; ) { - Selection::iterator next = i; - ++next; - - const boost::shared_ptr copy(new NoteType(*(*i)->note().get())); - - // we need to snap here again in nframes64_t in order to be sample accurate - double start_frames = snap_to_frame(beats_to_frames((*i)->note()->time()) + dt); - - // keep notes inside region if dragged beyond left region bound - if (start_frames < _region->start()) { - start_frames = _region->start(); - } - - copy->set_time(frames_to_beats(start_frames)); - - uint8_t original_pitch = (*i)->note()->note(); - uint8_t new_pitch = original_pitch + dnote - highest_note_difference; - - // keep notes in standard midi range - clamp_to_0_127(new_pitch); - - // keep original pitch if note is dragged outside valid midi range - if ((original_pitch != 0 && new_pitch == 0) - || (original_pitch != 127 && new_pitch == 127)) { - new_pitch = original_pitch; - } - - lowest_note_in_selection = std::min(lowest_note_in_selection, new_pitch); - highest_note_in_selection = std::max(highest_note_in_selection, new_pitch); - - copy->set_note(new_pitch); - - command_remove_note(*i); - command_add_note(copy, (*i)->selected()); - - i = next; + // keep original pitch if note is dragged outside valid midi range + if ((original_pitch != 0 && new_pitch == 0) + || (original_pitch != 127 && new_pitch == 127)) { + new_pitch = original_pitch; } - apply_command(); + lowest_note_in_selection = std::min(lowest_note_in_selection, new_pitch); + highest_note_in_selection = std::max(highest_note_in_selection, new_pitch); + + copy->set_note(new_pitch); - // care about notes being moved beyond the upper/lower bounds on the canvas - if (lowest_note_in_selection < midi_stream_view()->lowest_note() || - highest_note_in_selection > midi_stream_view()->highest_note()) { - midi_stream_view()->set_note_range(MidiStreamView::ContentsRange); - } + command_remove_note(*i); + command_add_note(copy, (*i)->selected()); + + i = next; + } + + apply_command(); + + // care about notes being moved beyond the upper/lower bounds on the canvas + if (lowest_note_in_selection < midi_stream_view()->lowest_note() || + highest_note_in_selection > midi_stream_view()->highest_note()) { + midi_stream_view()->set_note_range(MidiStreamView::ContentsRange); } } diff --git a/gtk2_ardour/midi_region_view.h b/gtk2_ardour/midi_region_view.h index d6a7695997..453a0fd42f 100644 --- a/gtk2_ardour/midi_region_view.h +++ b/gtk2_ardour/midi_region_view.h @@ -19,6 +19,7 @@ #ifndef __gtk_ardour_midi_region_view_h__ #define __gtk_ardour_midi_region_view_h__ +#include #include #include @@ -96,28 +97,20 @@ class MidiRegionView : public RegionView void add_note(const boost::shared_ptr note); void resolve_note(uint8_t note_num, double end_time); - struct ControlEvent - { - nframes_t time; - uint8_t value; - uint8_t channel; - - ControlEvent(nframes_t a_time, uint8_t a_value, uint8_t a_channel) + struct PCEvent { + PCEvent(double a_time, uint8_t a_value, uint8_t a_channel) : time(a_time), value(a_value), channel(a_channel) {} - - ControlEvent& operator=(const ControlEvent& other) { - time = other.time; - value = other.value; - channel = other.channel; - return *this; - } + + double time; + uint8_t value; + uint8_t channel; }; /** Add a new program change flag to the canvas. - * @param program the MidiRegionView::ControlEvent to add + * @param program the MidiRegionView::PCEvent to add * @param the text to display in the flag */ - void add_pgm_change(ControlEvent& program, string displaytext); + void add_pgm_change(PCEvent& program, const std::string& displaytext); /** Look up the given time and channel in the 'automation' and set keys accordingly. * @param time the time of the program change event @@ -128,10 +121,10 @@ class MidiRegionView : public RegionView void get_patch_key_at(double time, uint8_t channel, MIDI::Name::PatchPrimaryKey& key); /** Change the 'automation' data of old_program to new values which correspond to new_patch. - * @param old_program identifies the program change event which is to be altered - * @param new_patch defines the new lsb, msb and program number which are to be set in the automation list data + * @param old_program the program change event which is to be altered + * @param new_patch the new lsb, msb and program number which are to be set */ - void alter_program_change(ControlEvent& old_program, const MIDI::Name::PatchPrimaryKey& new_patch); + void alter_program_change(PCEvent& old_program, const MIDI::Name::PatchPrimaryKey& new_patch); /** Alter a given program to the new given one. * (Called on context menu select on CanvasProgramChange) @@ -160,7 +153,7 @@ class MidiRegionView : public RegionView void display_model(boost::shared_ptr model); - void start_delta_command(string name = "midi edit"); + void start_delta_command(std::string name = "midi edit"); void command_add_note(const boost::shared_ptr note, bool selected); void command_remove_note(ArdourCanvas::CanvasNoteEvent* ev); @@ -308,10 +301,10 @@ class MidiRegionView : public RegionView uint8_t _current_range_max; /// MIDNAM information of the current track: Model name of MIDNAM file - string _model_name; + std::string _model_name; /// MIDNAM information of the current track: CustomDeviceMode - string _custom_device_mode; + std::string _custom_device_mode; typedef std::vector Events; typedef std::vector< boost::shared_ptr > PgmChanges;