22 #include <gtkmm/cellrenderercombo.h>
49 using Timecode::BBT_Time;
56 note_length_map.insert (make_pair<int,string> (BBT_Time::ticks_per_beat,
_(
"Whole")));
57 note_length_map.insert (make_pair<int,string> (BBT_Time::ticks_per_beat/2,
_(
"Half")));
58 note_length_map.insert (make_pair<int,string> (BBT_Time::ticks_per_beat/3,
_(
"Triplet")));
59 note_length_map.insert (make_pair<int,string> (BBT_Time::ticks_per_beat/4,
_(
"Quarter")));
60 note_length_map.insert (make_pair<int,string> (BBT_Time::ticks_per_beat/8,
_(
"Eighth")));
61 note_length_map.insert (make_pair<int,string> (BBT_Time::ticks_per_beat/16,
_(
"Sixteenth")));
62 note_length_map.insert (make_pair<int,string> (BBT_Time::ticks_per_beat/32,
_(
"Thirty-second")));
63 note_length_map.insert (make_pair<int,string> (BBT_Time::ticks_per_beat/64,
_(
"Sixty-fourth")));
115 Gtk::TreeViewColumn* lenCol = Gtk::manage (
new Gtk::TreeViewColumn (
_(
"Length")));
116 Gtk::CellRendererCombo* comboCell = Gtk::manage(
new Gtk::CellRendererCombo);
117 lenCol->pack_start(*comboCell);
118 lenCol->add_attribute (comboCell->property_text(),
columns.
length);
121 comboCell->property_text_column() = 1;
122 comboCell->property_has_entry() =
false;
124 view.append_column (*lenCol);
126 view.set_headers_visible (
true);
127 view.set_rules_hint (
true);
128 view.get_selection()->set_mode (SELECTION_MULTIPLE);
131 for (
int i = 0; i < 6; ++i) {
132 CellRendererText* renderer =
dynamic_cast<CellRendererText*
>(
view.get_column_cell_renderer (i));
134 TreeViewColumn* col =
view.get_column (i);
135 col->set_data (
X_(
"colnum"), GUINT_TO_POINTER(i));
137 renderer->property_editable() =
true;
145 scroller.set_policy (POLICY_NEVER, POLICY_AUTOMATIC);
155 gtk_activatable_set_related_action (GTK_ACTIVATABLE (
sound_notes_button.gobj()), act->gobj());
164 vbox.set_spacing (6);
165 vbox.set_border_width (6);
170 set_size_request (-1, 400);
180 TreeModel::Path path;
188 bool was_selected =
false;
191 if (!
view.get_path_at_pos (ev->x, ev->y, path, col, cellx, celly)) {
195 if (
view.get_selection()->count_selected_rows() == 0) {
196 was_selected =
false;
197 }
else if (
view.get_selection()->is_selected (path)) {
200 was_selected =
false;
203 int colnum = GPOINTER_TO_UINT (col->get_data (
X_(
"colnum")));
207 if (Keyboard::modifier_state_equals (ev->state, Keyboard::SecondaryModifier)) {
212 if (ev->direction == GDK_SCROLL_DOWN || ev->direction == GDK_SCROLL_LEFT) {
215 prop = MidiModel::NoteDiffCommand::StartTime;
216 opname =
_(
"edit note start");
221 if (ev->direction == GDK_SCROLL_DOWN || ev->direction == GDK_SCROLL_LEFT) {
224 prop = MidiModel::NoteDiffCommand::Channel;
225 opname =
_(
"edit note channel");
231 if (ev->direction == GDK_SCROLL_DOWN || ev->direction == GDK_SCROLL_LEFT) {
234 prop = MidiModel::NoteDiffCommand::NoteNumber;
235 opname =
_(
"edit note number");
241 if (ev->direction == GDK_SCROLL_DOWN || ev->direction == GDK_SCROLL_LEFT) {
244 prop = MidiModel::NoteDiffCommand::Velocity;
245 opname =
_(
"edit note velocity");
250 if (Keyboard::modifier_state_equals (ev->state, Keyboard::SecondaryModifier)) {
255 if (ev->direction == GDK_SCROLL_DOWN || ev->direction == GDK_SCROLL_LEFT) {
258 prop = MidiModel::NoteDiffCommand::Length;
259 opname =
_(
"edit note length");
272 vector<TreeModel::Path> previous_selection;
278 TreeView::Selection::ListHandle_Path rows =
view.get_selection()->get_selected_rows ();
279 TreeModel::iterator iter;
282 for (TreeView::Selection::ListHandle_Path::iterator i = rows.begin(); i != rows.end(); ++i) {
284 previous_selection.push_back (*i);
286 if ((iter =
model->get_iter (*i))) {
291 case MidiModel::NoteDiffCommand::StartTime:
292 if (note->
time() + fdelta >= 0) {
293 cmd->change (note, prop, note->
time() + fdelta);
298 case MidiModel::NoteDiffCommand::Velocity:
299 cmd->change (note, prop, (uint8_t) (note->
velocity() + idelta));
301 case MidiModel::NoteDiffCommand::Length:
302 if (note->
length().to_double() + fdelta >=
304 cmd->change (note, prop, note->
length() + fdelta);
309 case MidiModel::NoteDiffCommand::Channel:
310 cmd->change (note, prop, (uint8_t) (note->
channel() + idelta));
312 case MidiModel::NoteDiffCommand::NoteNumber:
313 cmd->change (note, prop, (uint8_t) (note->
note() + idelta));
325 TreeModel::iterator iter;
326 iter =
model->get_iter (path);
328 previous_selection.push_back (path);
334 case MidiModel::NoteDiffCommand::StartTime:
335 if (note->
time() + fdelta >= 0) {
336 cmd->change (note, prop, note->
time() + fdelta);
341 case MidiModel::NoteDiffCommand::Velocity:
342 cmd->change (note, prop, (uint8_t) (note->
velocity() + idelta));
344 case MidiModel::NoteDiffCommand::Length:
345 if (note->
length() + fdelta >=
347 cmd->change (note, prop, note->
length() + fdelta);
352 case MidiModel::NoteDiffCommand::Channel:
353 cmd->change (note, prop, (uint8_t) (note->
channel() + idelta));
355 case MidiModel::NoteDiffCommand::NoteNumber:
356 cmd->change (note, prop, (uint8_t) (note->
note() + idelta));
368 for (vector<TreeModel::Path>::iterator i = previous_selection.begin(); i != previous_selection.end(); ++i) {
369 view.get_selection()->select (*i);
380 TreeModel::Path path;
384 switch (ev->keyval) {
399 col =
view.get_column (colnum);
400 view.set_cursor (path, *col,
true);
414 col =
view.get_column (colnum);
415 view.set_cursor (path, *col,
true);
429 col =
view.get_column (colnum);
430 view.set_cursor (path, *col,
true);
448 TreeModel::Path path;
450 TreeModel::iterator iter;
456 switch (ev->keyval) {
461 view.get_cursor (path, col);
462 iter =
model->get_iter (path);
463 cmd = m->new_note_diff_command (
_(
"insert new note"));
471 col =
view.get_column (2);
472 view.set_cursor (path, *col,
true);
507 Glib::RefPtr<TreeSelection> selection =
view.get_selection();
508 TreeView::Selection::ListHandle_Path rows = selection->get_selected_rows ();
514 typedef vector<boost::shared_ptr<NoteType> > Notes;
517 for (TreeView::Selection::ListHandle_Path::iterator i = rows.begin(); i != rows.end(); ++i) {
520 if ((iter =
model->get_iter (*i))) {
522 to_delete.push_back (note);
529 for (Notes::iterator i = to_delete.begin(); i != to_delete.end(); ++i) {
559 Gtk::Entry *e =
dynamic_cast<Gtk::Entry*
> (ed);
579 TreeModel::iterator iter =
model->get_iter (path);
581 if (!iter || text.empty()) {
599 if (sscanf (text.c_str(),
"%d", &ival) == 1 && --ival != note->
channel()) {
600 idelta = ival - note->
channel();
601 prop = MidiModel::NoteDiffCommand::Channel;
602 opname =
_(
"change note channel");
607 if (sscanf (text.c_str(),
"%d", &ival) == 1 && ival != note->
note()) {
608 idelta = ival - note->
note();
609 prop = MidiModel::NoteDiffCommand::NoteNumber;
610 opname =
_(
"change note number");
617 if (sscanf (text.c_str(),
"%d", &ival) == 1 && ival != note->
velocity()) {
619 prop = MidiModel::NoteDiffCommand::Velocity;
620 opname =
_(
"change note velocity");
626 if (sscanf (text.c_str(),
"%lf", &fval) == 1) {
630 if (text.find (
'.') == string::npos && text.find (
',') == string::npos) {
632 fval = fval / BBT_Time::ticks_per_beat;
643 uint64_t len_ticks = note->
length().to_ticks();
654 if (x->second == text) {
660 fval = x->first / BBT_Time::ticks_per_beat;
667 if (text != x->second) {
674 if (x->second == text) {
681 fval = (double) x->first / BBT_Time::ticks_per_beat;
688 fdelta = fval - note->
length().to_double();
689 prop = MidiModel::NoteDiffCommand::Length;
690 opname =
_(
"change note length");
704 TreeView::Selection::ListHandle_Path rows =
view.get_selection()->get_selected_rows ();
706 for (TreeView::Selection::ListHandle_Path::iterator i = rows.begin(); i != rows.end(); ++i) {
707 if ((iter =
model->get_iter (*i))) {
712 case MidiModel::NoteDiffCommand::Velocity:
713 cmd->change (note, prop, (uint8_t) (note->
velocity() + idelta));
715 case MidiModel::NoteDiffCommand::Length:
716 cmd->change (note, prop, note->
length() + fdelta);
718 case MidiModel::NoteDiffCommand::Channel:
719 cmd->change (note, prop, (uint8_t) (note->
channel() + idelta));
721 case MidiModel::NoteDiffCommand::NoteNumber:
722 cmd->change (note, prop, (uint8_t) (note->
note() + idelta));
750 view.set_model (Glib::RefPtr<Gtk::ListStore>(0));
760 for (MidiModel::Notes::iterator i = notes.begin(); i != notes.end(); ++i) {
761 row = *(
model->append());
767 Timecode::BBT_Time bbt;
780 int len_ticks = (*i)->length().to_ticks();
805 TreeModel::Path path;
806 TreeModel::iterator iter;
808 TreeView::Selection::ListHandle_Path rows =
view.get_selection()->get_selected_rows ();
812 for (TreeView::Selection::ListHandle_Path::iterator i = rows.begin(); i != rows.end(); ++i) {
813 if ((iter =
model->get_iter (*i))) {
LIBEVORAL_API std::string midi_note_name(uint8_t noteval)
void apply_command(Session &session, Command *cmd)
void delete_selected_note()
uint32_t get_ticks() const
void bbt_time(framepos_t when, Timecode::BBT_Time &)
Gtk::TreeModelColumn< std::string > start
void edited(const std::string &, const std::string &)
Gtk::TreeModelColumn< uint8_t > channel
Gtk::TreeModelColumn< uint8_t > velocity
LIBGTKMM2EXT_API Glib::RefPtr< Gtk::Action > get_action(const char *group, const char *name)
Gtk::TreeModel::Path edit_path
MidiListModelColumns columns
bool key_release(GdkEventKey *ev)
void add(boost::shared_ptr< NoteType >)
Gtk::TreeModelColumn< boost::shared_ptr< NoteType > > _note
static bool modifier_state_contains(guint state, ModifierMask)
static Beats beats(int32_t beats)
static uint32_t PrimaryModifier
Gtk::TreeModelColumn< uint8_t > note
uint32_t get_beats() const
PBD::ScopedConnection content_connection
MidiListEditor(ARDOUR::Session *, boost::shared_ptr< ARDOUR::MidiRegion >, boost::shared_ptr< ARDOUR::MidiTrack >)
Gtk::CellEditable * editing_editable
static void fill_note_length_map()
framepos_t position() const
Gtk::TreeModelColumn< std::string > note_name
static map< int, std::string > note_length_map
Gtk::TreeModelColumn< std::string > length
static UIConfiguration * config()
void stop_editing(bool cancelled=false)
Gtk::TreeModelColumn< int > ticks
Gtk::ToggleButton sound_notes_button
bool key_press(GdkEventKey *ev)
boost::shared_ptr< ARDOUR::MidiTrack > track
Gtk::ScrolledWindow scroller
virtual void set_session(ARDOUR::Session *)
boost::shared_ptr< MidiSource > midi_source(uint32_t n=0) const
Glib::RefPtr< Gtk::ListStore > model
boost::shared_ptr< ARDOUR::MidiRegion > region
uint32_t max_source_level() const
Glib::RefPtr< Gtk::ListStore > note_length_model
void editing_started(Gtk::CellEditable *, const std::string &path, int)
ARDOUR::Session * _session
Gtk::TreeModelColumn< std::string > name
void add(const NotePtr note)
NoteLengthColumns note_length_columns
Gtk::CellRendererText * editing_renderer
bool scroll_event(GdkEventScroll *)