ardour
edit_note_dialog.cc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2010 Paul Davis
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; either version 2 of the License, or
7  (at your option) any later version.
8 
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with this program; if not, write to the Free Software
16  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 
18 */
19 
20 #include <gtkmm/stock.h>
21 #include <gtkmm/table.h>
22 
23 #include "gtkmm2ext/utils.h"
24 
25 #include "edit_note_dialog.h"
26 #include "midi_region_view.h"
27 #include "note_base.h"
28 
29 #include "i18n.h"
30 
31 using namespace std;
32 using namespace Gtk;
33 using namespace Gtkmm2ext;
34 
42  : ArdourDialog (_("Note"))
43  , _region_view (rv)
44  , _events (n)
45  , _channel_all (_("Set selected notes to this channel"))
46  , _pitch_all (_("Set selected notes to this pitch"))
47  , _velocity_all (_("Set selected notes to this velocity"))
48  , _time_clock (X_("notetime"), true, "", true, false)
49  , _time_all (_("Set selected notes to this time"))
50  , _length_clock (X_("notelength"), true, "", true, false, true)
51  , _length_all (_("Set selected notes to this length"))
52 {
53  Table* table = manage (new Table (4, 2));
54  table->set_spacings (6);
55 
56  int r = 0;
57 
58  Label* l = manage (left_aligned_label (_("Channel")));
59  table->attach (*l, 0, 1, r, r + 1);
60  table->attach (_channel, 1, 2, r, r + 1);
61  table->attach (_channel_all, 2, 3, r, r + 1);
62  ++r;
63 
64  _channel.set_range (1, 16);
65  _channel.set_increments (1, 2);
66  _channel.set_value ((*_events.begin())->note()->channel () + 1);
67 
68  l = manage (left_aligned_label (_("Pitch")));
69  table->attach (*l, 0, 1, r, r + 1);
70  table->attach (_pitch, 1, 2, r, r + 1);
71  table->attach (_pitch_all, 2, 3, r, r + 1);
72  ++r;
73 
74  _pitch.set_range (0, 127);
75  _pitch.set_increments (1, 10);
76  _pitch.set_value ((*_events.begin())->note()->note());
77 
78  l = manage (left_aligned_label (_("Velocity")));
79  table->attach (*l, 0, 1, r, r + 1);
80  table->attach (_velocity, 1, 2, r, r + 1);
81  table->attach (_velocity_all, 2, 3, r, r + 1);
82  ++r;
83 
84  _velocity.set_range (0, 127);
85  _velocity.set_increments (1, 10);
86  _velocity.set_value ((*_events.begin())->note()->velocity ());
87 
88  l = manage (left_aligned_label (_("Time")));
89  table->attach (*l, 0, 1, r, r + 1);
90  table->attach (_time_clock, 1, 2, r, r + 1);
91  table->attach (_time_all, 2, 3, r, r + 1);
92  ++r;
93 
96  _time_clock.set (_region_view->source_relative_time_converter().to ((*_events.begin())->note()->time ()), true);
97 
98  l = manage (left_aligned_label (_("Length")));
99  table->attach (*l, 0, 1, r, r + 1);
100  table->attach (_length_clock, 1, 2, r, r + 1);
101  table->attach (_length_all, 2, 3, r, r + 1);
102  ++r;
103 
106  _length_clock.set (_region_view->region_relative_time_converter().to ((*_events.begin())->note()->length ()), true);
107 
108  /* Set up `set all notes...' buttons' sensitivity */
109 
110  _channel_all.set_sensitive (false);
111  _pitch_all.set_sensitive (false);
112  _velocity_all.set_sensitive (false);
113  _time_all.set_sensitive (false);
114  _length_all.set_sensitive (false);
115 
116  int test_channel = (*_events.begin())->note()->channel ();
117  int test_pitch = (*_events.begin())->note()->note ();
118  int test_velocity = (*_events.begin())->note()->velocity ();
119  Evoral::Beats test_time = (*_events.begin())->note()->time ();
120  Evoral::Beats test_length = (*_events.begin())->note()->length ();
121 
122  for (set<NoteBase*>::iterator i = _events.begin(); i != _events.end(); ++i) {
123  if ((*i)->note()->channel() != test_channel) {
124  _channel_all.set_sensitive (true);
125  }
126 
127  if ((*i)->note()->note() != test_pitch) {
128  _pitch_all.set_sensitive (true);
129  }
130 
131  if ((*i)->note()->velocity() != test_velocity) {
132  _velocity_all.set_sensitive (true);
133  }
134 
135  if ((*i)->note()->time () != test_time) {
136  _time_all.set_sensitive (true);
137  }
138 
139  if ((*i)->note()->length () != test_length) {
140  _length_all.set_sensitive (true);
141  }
142  }
143 
144  get_vbox()->pack_start (*table);
145 
146  add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
147  add_button (Gtk::Stock::APPLY, Gtk::RESPONSE_ACCEPT);
148  set_default_response (Gtk::RESPONSE_ACCEPT);
149 }
150 
151 void
153 {
154  if (r != RESPONSE_ACCEPT) {
155  return;
156  }
157 
158  /* These calls mean that if a value is entered using the keyboard
159  it will be returned by the get_value_as_int()s below.
160  */
161  _channel.update ();
162  _pitch.update ();
163  _velocity.update ();
164 
165  _region_view->start_note_diff_command (_("edit note"));
166 
167  bool had_change = false;
168 
169  if (!_channel_all.get_sensitive() || _channel_all.get_active ()) {
170  for (set<NoteBase*>::iterator i = _events.begin(); i != _events.end(); ++i) {
171  if (_channel.get_value_as_int() - 1 != (*i)->note()->channel()) {
172  _region_view->change_note_channel (*i, _channel.get_value_as_int () - 1);
173  had_change = true;
174  }
175  }
176  }
177 
178  if (!_pitch_all.get_sensitive() || _pitch_all.get_active ()) {
179  for (set<NoteBase*>::iterator i = _events.begin(); i != _events.end(); ++i) {
180  if (_pitch.get_value_as_int() != (*i)->note()->note()) {
181  _region_view->change_note_note (*i, _pitch.get_value_as_int ());
182  had_change = true;
183  }
184  }
185  }
186 
187  if (!_velocity_all.get_sensitive() || _velocity_all.get_active ()) {
188  for (set<NoteBase*>::iterator i = _events.begin(); i != _events.end(); ++i) {
189  if (_velocity.get_value_as_int() != (*i)->note()->velocity()) {
190  _region_view->change_note_velocity (*i, _velocity.get_value_as_int ());
191  had_change = true;
192  }
193  }
194  }
195 
197 
198  if (!_time_all.get_sensitive() || _time_all.get_active ()) {
199  for (set<NoteBase*>::iterator i = _events.begin(); i != _events.end(); ++i) {
200  if (t != (*i)->note()->time()) {
202  had_change = true;
203  }
204  }
205  }
206 
208 
209  if (!_length_all.get_sensitive() || _length_all.get_active ()) {
210  for (set<NoteBase*>::iterator i = _events.begin(); i != _events.end(); ++i) {
211  if (d != (*i)->note()->length()) {
213  had_change = true;
214  }
215  }
216  }
217 
218  if (!had_change) {
220  }
221 
223 
224  for (set<NoteBase*>::iterator i = _events.begin(); i != _events.end(); ++i) {
225  (*i)->set_selected ((*i)->selected()); // change color
226  }
227 }
framepos_t current_time(framepos_t position=0) const
std::set< NoteBase * > _events
TimeAxisView & get_time_axis_view() const
void set(framepos_t, bool force=false, ARDOUR::framecnt_t offset=0)
Definition: audio_clock.cc:956
void set_session(ARDOUR::Session *s)
Definition: ardour_ui.h:130
void change_note_channel(NoteBase *, int8_t, bool relative=false)
Gtk::CheckButton _time_all
Gtk::CheckButton _velocity_all
Definition: Beats.hpp:239
void change_note_velocity(NoteBase *ev, int8_t vel, bool relative=false)
#define _(Text)
Definition: i18n.h:11
#define X_(Text)
Definition: i18n.h:13
MidiRegionView * _region_view
void change_note_time(NoteBase *ev, ARDOUR::MidiModel::TimeType, bool relative=false)
Gtk::SpinButton _pitch
EditNoteDialog(MidiRegionView *rv, std::set< NoteBase * > n)
ARDOUR::Session * session() const
Definition: axis_view.h:52
ARDOUR::BeatsFramesConverter const & source_relative_time_converter() const
ARDOUR::BeatsFramesConverter const & region_relative_time_converter() const
LIBGTKMM2EXT_API Gtk::Label * left_aligned_label(std::string const &)
Evoral::Beats from(framepos_t frames) const
Gtk::CheckButton _length_all
Gtk::CheckButton _pitch_all
void set_mode(Mode)
AudioClock _time_clock
void change_note_length(NoteBase *, ARDOUR::MidiModel::TimeType)
void change_note_note(NoteBase *ev, int8_t note, bool relative=false)
Gtk::SpinButton _channel
framepos_t current_duration(framepos_t position=0) const
Gtk::CheckButton _channel_all
void apply_diff(bool as_subcommand=false)
Gtk::SpinButton _velocity
AudioClock _length_clock
framepos_t to(Evoral::Beats beats) const
void start_note_diff_command(std::string name="midi edit")