From 439d13535ee7ae73b1e7d6b0cc99022739234a28 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Sat, 14 Aug 2010 02:00:50 +0000 Subject: Add note edit dialog. Fixes #3346. git-svn-id: svn://localhost/ardour2/branches/3.0@7625 d708f5d6-7413-0410-9779-e7cbd77b26cf --- gtk2_ardour/edit_note_dialog.cc | 156 ++++++++++++++++++++++++++++++++++++++++ gtk2_ardour/edit_note_dialog.h | 48 +++++++++++++ gtk2_ardour/editor.h | 1 + gtk2_ardour/editor_mouse.cc | 18 +++++ gtk2_ardour/midi_region_view.cc | 12 ++++ gtk2_ardour/midi_region_view.h | 12 ++-- gtk2_ardour/region_view.h | 4 ++ gtk2_ardour/wscript | 1 + 8 files changed, 246 insertions(+), 6 deletions(-) create mode 100644 gtk2_ardour/edit_note_dialog.cc create mode 100644 gtk2_ardour/edit_note_dialog.h (limited to 'gtk2_ardour') diff --git a/gtk2_ardour/edit_note_dialog.cc b/gtk2_ardour/edit_note_dialog.cc new file mode 100644 index 0000000000..fe45093057 --- /dev/null +++ b/gtk2_ardour/edit_note_dialog.cc @@ -0,0 +1,156 @@ +/* + Copyright (C) 2010 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include +#include +#include "ardour/midi_model.h" +#include "edit_note_dialog.h" +#include "canvas-note-event.h" +#include "midi_region_view.h" + +using namespace Gtk; + +/** + * EditNoteDialog constructor. + * + * @param n Note to edit. + */ + +EditNoteDialog::EditNoteDialog (MidiRegionView* rv, Gnome::Canvas::CanvasNoteEvent* ev) + : ArdourDialog (_("Note")) + , _region_view (rv) + , _event (ev) + , _time_clock (X_("notetime"), true, X_("NoteTimeClock"), true, false) + , _length_clock (X_("notelength"), true, X_("NoteLengthClock"), true, false, true) +{ + Table* table = manage (new Table (4, 2)); + table->set_spacings (6); + + int r = 0; + + Label* l = manage (new Label (_("Channel"))); + l->set_alignment (0, 0.5); + table->attach (*l, 0, 1, r, r + 1); + table->attach (_channel, 1, 2, r, r + 1); + ++r; + + _channel.set_range (1, 16); + _channel.set_increments (1, 2); + _channel.set_value (ev->note()->channel () + 1); + + l = manage (new Label (_("Pitch"))); + l->set_alignment (0, 0.5); + table->attach (*l, 0, 1, r, r + 1); + table->attach (_pitch, 1, 2, r, r + 1); + ++r; + + _pitch.set_range (0, 127); + _pitch.set_increments (1, 10); + _pitch.set_value (ev->note()->note ()); + + l = manage (new Label (_("Velocity"))); + l->set_alignment (0, 0.5); + table->attach (*l, 0, 1, r, r + 1); + table->attach (_velocity, 1, 2, r, r + 1); + ++r; + + _velocity.set_range (0, 127); + _velocity.set_increments (1, 10); + _velocity.set_value (ev->note()->velocity ()); + + l = manage (new Label (_("Time"))); + l->set_alignment (0, 0.5); + table->attach (*l, 0, 1, r, r + 1); + table->attach (_time_clock, 1, 2, r, r + 1); + ++r; + + _time_clock.set_session (_region_view->get_trackview().session ()); + _time_clock.set_mode (AudioClock::BBT); + _time_clock.set (_region_view->time_converter().to (ev->note()->time ()), true); + + l = manage (new Label (_("Length"))); + l->set_alignment (0, 0.5); + table->attach (*l, 0, 1, r, r + 1); + table->attach (_length_clock, 1, 2, r, r + 1); + ++r; + + _length_clock.set_session (_region_view->get_trackview().session ()); + _length_clock.set_mode (AudioClock::BBT); + _length_clock.set (_region_view->time_converter().to (ev->note()->length ()), true); + + get_vbox()->pack_start (*table); + + add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL); + add_button (Gtk::Stock::APPLY, Gtk::RESPONSE_ACCEPT); + set_default_response (Gtk::RESPONSE_ACCEPT); + + show_all (); +} + +int +EditNoteDialog::run () +{ + int const r = Dialog::run (); + if (r != RESPONSE_ACCEPT) { + return r; + } + + _region_view->start_diff_command (_("edit note")); + + bool had_change = false; + + if (_channel.get_value_as_int() - 1 != _event->note()->channel()) { + _region_view->change_note_channel (_event, _channel.get_value_as_int () - 1); + had_change = true; + } + + if (_pitch.get_value_as_int() != _event->note()->note()) { + _region_view->change_note_note (_event, _pitch.get_value_as_int (), false); + had_change = true; + } + + if (_velocity.get_value_as_int() != _event->note()->velocity()) { + _region_view->change_note_velocity (_event, _velocity.get_value_as_int (), false); + had_change = true; + } + + double const t = _region_view->time_converter().from (_time_clock.current_time ()); + + if (t != _event->note()->time()) { + _region_view->change_note_time (_event, t); + had_change = true; + } + + double const d = _region_view->time_converter().from (_length_clock.current_duration ()); + + if (d != _event->note()->length()) { + _region_view->change_note_length (_event, d); + had_change = true; + } + + if (!had_change) { + _region_view->abort_command (); + } + + _region_view->apply_diff (); + + _event->set_selected (_event->selected()); // change color + + return r; +} diff --git a/gtk2_ardour/edit_note_dialog.h b/gtk2_ardour/edit_note_dialog.h new file mode 100644 index 0000000000..8dfd434440 --- /dev/null +++ b/gtk2_ardour/edit_note_dialog.h @@ -0,0 +1,48 @@ +/* + Copyright (C) 2010 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include +#include "ardour/midi_model.h" +#include "ardour_dialog.h" +#include "audio_clock.h" + +class MidiRegionView; + +namespace Gnome { + namespace Canvas { + class CanvasNoteEvent; + } +} + +class EditNoteDialog : public ArdourDialog +{ +public: + EditNoteDialog (MidiRegionView *, Gnome::Canvas::CanvasNoteEvent *); + + int run (); + +private: + MidiRegionView* _region_view; + Gnome::Canvas::CanvasNoteEvent* _event; + Gtk::SpinButton _channel; + Gtk::SpinButton _pitch; + Gtk::SpinButton _velocity; + AudioClock _time_clock; + AudioClock _length_clock; +}; diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h index 9158e40d26..45ef788d40 100644 --- a/gtk2_ardour/editor.h +++ b/gtk2_ardour/editor.h @@ -1461,6 +1461,7 @@ public: void edit_tempo_marker (ArdourCanvas::Item*); void edit_meter_marker (ArdourCanvas::Item*); void edit_control_point (ArdourCanvas::Item*); + void edit_note (ArdourCanvas::Item *); void marker_menu_edit (); void marker_menu_remove (); diff --git a/gtk2_ardour/editor_mouse.cc b/gtk2_ardour/editor_mouse.cc index 18ed2c9226..4713258b19 100644 --- a/gtk2_ardour/editor_mouse.cc +++ b/gtk2_ardour/editor_mouse.cc @@ -54,6 +54,7 @@ #include "control_point_dialog.h" #include "editor_drag.h" #include "automation_region_view.h" +#include "edit_note_dialog.h" #include "ardour/types.h" #include "ardour/profile.h" @@ -1150,6 +1151,10 @@ Editor::button_release_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemT edit_control_point (item); break; + case NoteItem: + edit_note (item); + break; + default: break; } @@ -1989,6 +1994,19 @@ Editor::edit_control_point (ArdourCanvas::Item* item) p->line().modify_point_y (*p, d.get_y_fraction ()); } +void +Editor::edit_note (ArdourCanvas::Item* item) +{ + ArdourCanvas::CanvasNoteEvent* e = dynamic_cast (item); + assert (e); + + EditNoteDialog d (&e->region_view(), e); + d.set_position (Gtk::WIN_POS_MOUSE); + ensure_float (d); + + d.run (); +} + void Editor::visible_order_range (int* low, int* high) const diff --git a/gtk2_ardour/midi_region_view.cc b/gtk2_ardour/midi_region_view.cc index b761941df1..a520a22d50 100644 --- a/gtk2_ardour/midi_region_view.cc +++ b/gtk2_ardour/midi_region_view.cc @@ -2260,6 +2260,12 @@ MidiRegionView::commit_resizing (ArdourCanvas::CanvasNote* primary, bool at_fron apply_diff(); } +void +MidiRegionView::change_note_channel (CanvasNoteEvent* event, int8_t channel) +{ + diff_add_change (event, MidiModel::DiffCommand::Channel, (uint8_t) channel); +} + void MidiRegionView::change_note_velocity(CanvasNoteEvent* event, int8_t velocity, bool relative) { @@ -2386,6 +2392,12 @@ MidiRegionView::change_note_time (CanvasNoteEvent* event, Evoral::MusicalTime de diff_add_change (event, MidiModel::DiffCommand::StartTime, new_time); } +void +MidiRegionView::change_note_length (CanvasNoteEvent* event, Evoral::MusicalTime t) +{ + diff_add_change (event, MidiModel::DiffCommand::Length, t); +} + void MidiRegionView::change_velocities (bool up, bool fine, bool allow_smush) { diff --git a/gtk2_ardour/midi_region_view.h b/gtk2_ardour/midi_region_view.h index ccab1d06bc..75ee5f13d8 100644 --- a/gtk2_ardour/midi_region_view.h +++ b/gtk2_ardour/midi_region_view.h @@ -64,6 +64,7 @@ class AutomationTimeAxisView; class AutomationRegionView; class MidiCutBuffer; class MidiListEditor; +class EditNoteDialog; class MidiRegionView : public RegionView { @@ -224,12 +225,6 @@ class MidiRegionView : public RegionView void update_resizing (ArdourCanvas::CanvasNote *, bool, double, bool); void commit_resizing (ArdourCanvas::CanvasNote *, bool, double, bool); - /** Adjust the velocity on a note, and the selection if applicable. - * @param velocity the relative or absolute velocity - * @param relative whether velocity is relative or absolute - */ - void change_velocity(ArdourCanvas::CanvasNoteEvent* ev, int8_t velocity, bool relative=false); - /** Change the channel of the selection. * @param channel - the channel number of the new channel, zero-based */ @@ -306,6 +301,9 @@ class MidiRegionView : public RegionView void reset_width_dependent_items (double pixel_width); private: + + friend class EditNoteDialog; + /** Play the NoteOn event of the given note immediately * and schedule the playback of the corresponding NoteOff event. */ @@ -325,9 +323,11 @@ class MidiRegionView : public RegionView void midi_channel_mode_changed(ARDOUR::ChannelMode mode, uint16_t mask); void midi_patch_settings_changed(std::string model, std::string custom_device_mode); + void change_note_channel (ArdourCanvas::CanvasNoteEvent *, int8_t); void change_note_velocity(ArdourCanvas::CanvasNoteEvent* ev, int8_t vel, bool relative=false); void change_note_note(ArdourCanvas::CanvasNoteEvent* ev, int8_t note, bool relative=false); void change_note_time(ArdourCanvas::CanvasNoteEvent* ev, ARDOUR::MidiModel::TimeType, bool relative=false); + void change_note_length (ArdourCanvas::CanvasNoteEvent *, ARDOUR::MidiModel::TimeType); void trim_note(ArdourCanvas::CanvasNoteEvent* ev, ARDOUR::MidiModel::TimeType start_delta, ARDOUR::MidiModel::TimeType end_delta); diff --git a/gtk2_ardour/region_view.h b/gtk2_ardour/region_view.h index 5421d7d613..79cbae30ac 100644 --- a/gtk2_ardour/region_view.h +++ b/gtk2_ardour/region_view.h @@ -91,6 +91,10 @@ class RegionView : public TimeAxisViewItem static PBD::Signal1 RegionViewGoingAway; + ARDOUR::BeatsFramesConverter const & time_converter () { + return _time_converter; + } + protected: /** Allows derived types to specify their visibility requirements diff --git a/gtk2_ardour/wscript b/gtk2_ardour/wscript index 307ebe371e..858d086c48 100644 --- a/gtk2_ardour/wscript +++ b/gtk2_ardour/wscript @@ -66,6 +66,7 @@ gtk2_ardour_sources = [ 'crossfade_view.cc', 'curvetest.cc', 'diamond.cc', + 'edit_note_dialog.cc', 'editing.cc', 'editor.cc', 'editor_actions.cc', -- cgit v1.2.3