several related changes to get visible channel control working in MidiView/Pianoroll

This commit is contained in:
Paul Davis
2025-03-04 11:30:42 -07:00
parent e34fd3cc3b
commit 06050bb578
4 changed files with 78 additions and 34 deletions

View File

@@ -746,6 +746,10 @@ MidiView::channel_edit ()
}
apply_note_diff ();
if (_visible_channel >= 0 && _visible_channel != new_channel) {
set_visible_channel (new_channel, false);
}
}
void
@@ -1283,24 +1287,10 @@ MidiView::view_changed()
size_end_rect ();
}
void
MidiView::visible_channel_changed ()
bool
MidiView::note_editable (std::shared_ptr<const NoteType> note) const
{
if (!display_is_enabled()) {
return;
}
if (!_model) {
return;
}
for (auto & [note, gui] : _events) {
if (gui->item()->visible()) {
color_note (gui, note->channel());
gui->set_ignore_events (note->channel() != _visible_channel);
}
}
return (_visible_channel < 0) || (note->channel() == _visible_channel);
}
void
@@ -1789,8 +1779,8 @@ MidiView::update_sustained (Note* ev)
ev->set_outline_all ();
}
color_note (ev, note->channel());
ev->set_ignore_events (!note_editable (note));
}
void
@@ -1799,8 +1789,8 @@ MidiView::color_note (NoteBase* ev, int channel)
// Update color in case velocity has changed
uint32_t base_color = ev->base_color();
if (channel != _visible_channel) {
base_color = Gtkmm2ext::change_alpha (base_color, 0.2);
if (!note_editable (ev->note())) {
base_color = Gtkmm2ext::change_alpha (base_color, 0.15);
}
ev->set_fill_color (base_color);
@@ -1940,6 +1930,9 @@ MidiView::update_hit (Hit* ev)
const uint32_t base_col = ev->base_color();
ev->set_fill_color(base_col);
ev->set_outline_color(ev->calculate_outline(base_col, ev->selected()));
color_note (ev, _visible_channel);
ev->set_ignore_events (!note_editable (note));
}
/** Add a MIDI note to the view (with length).
@@ -2327,10 +2320,11 @@ MidiView::clear_selection_internal ()
{
DEBUG_TRACE(DEBUG::Selection, "MRV::clear_selection_internal\n");
for (auto & sel : _selection) {
sel->set_selected (false);
sel->hide_velocity();
ghost_sync_selection (sel);
for (auto & note : _selection) {
note->set_selected (false);
color_note (note, _visible_channel);
note->hide_velocity();
ghost_sync_selection (note);
}
_selection.clear();
}
@@ -2627,15 +2621,15 @@ MidiView::update_drag_selection(timepos_t const & start, timepos_t const & end,
// adjusting things that are in the area that appears/disappeared.
// We probably need a tree to be able to find events in O(log(n)) time.
for (Events::iterator i = _events.begin(); i != _events.end(); ++i) {
if (i->second->x0() < x1 && i->second->x1() > x0 && i->second->y0() < y1 && i->second->y1() > y0) {
for (auto & [ note, gui ] : _events) {
if (gui->x0() < x1 && gui->x1() > x0 && gui->y0() < y1 && gui->y1() > y0) {
// Rectangles intersect
if (!i->second->selected()) {
add_to_selection (i->second);
if (!gui->selected() && note_editable (note)) {
add_to_selection (gui);
}
} else if (i->second->selected() && !extend) {
} else if (gui->selected() && !extend) {
// Rectangles do not intersect
remove_from_selection (i->second);
remove_from_selection (gui);
}
}
@@ -3518,6 +3512,8 @@ MidiView::change_note_channel (NoteBase* event, int8_t chn, bool relative)
}
note_diff_add_change (event, MidiModel::NoteDiffCommand::Channel, new_channel);
}
void
@@ -5240,10 +5236,30 @@ MidiView::set_visibility_note_range (MidiViewBackground::VisibleNoteRange nvr, b
}
void
MidiView::set_visible_channel (int chn)
MidiView::set_visible_channel (int chn, bool clear_selection)
{
_visible_channel = chn;
visible_channel_changed ();
VisibleChannelChanged(); /* EMIT SIGNAL */
if (!display_is_enabled()) {
return;
}
if (!_model) {
return;
}
for (auto & [note, gui] : _events) {
if (gui->item()->visible()) {
color_note (gui, note->channel());
gui->set_ignore_events (!note_editable (note));
}
}
if (clear_selection) {
clear_selection_internal ();
}
}
void

View File

@@ -377,7 +377,8 @@ class MidiView : public virtual sigc::trackable, public LineMerger
virtual bool midi_canvas_group_event(GdkEvent* ev);
int visible_channel() const { return _visible_channel; }
void set_visible_channel (int);
void set_visible_channel (int, bool clear_selection = true);
PBD::Signal<void()> VisibleChannelChanged;
protected:
void init (std::shared_ptr<ARDOUR::MidiTrack>);
@@ -389,6 +390,7 @@ class MidiView : public virtual sigc::trackable, public LineMerger
virtual void reset_width_dependent_items (double pixel_width);
void redisplay (bool view_only);
bool note_editable (std::shared_ptr<const NoteType>) const;
protected:
friend class EditingContext;
@@ -688,7 +690,6 @@ class MidiView : public virtual sigc::trackable, public LineMerger
virtual void add_control_points_to_selection (Temporal::timepos_t const &, Temporal::timepos_t const &, double y0, double y1) {}
void color_note (NoteBase*, int channel);
void visible_channel_changed ();
};

View File

@@ -17,6 +17,7 @@
*/
#include "pbd/stateful_diff_command.h"
#include "pbd/unwind.h"
#include "ardour/midi_region.h"
#include "ardour/midi_track.h"
@@ -74,6 +75,7 @@ Pianoroll::Pianoroll (std::string const & name)
, bar_adjustment (4, 1, 32, 1, 4)
, bar_spinner (bar_adjustment)
, length_label (X_("Record (Bars):"))
, ignore_channel_changes (false)
{
mouse_mode = Editing::MouseContent;
autoscroll_vertical_allowed = false;
@@ -434,6 +436,8 @@ Pianoroll::build_upper_toolbar ()
void
Pianoroll::set_visible_channel (int n)
{
PBD::Unwinder<bool> uw (ignore_channel_changes, true);
_visible_channel = n;
visible_channel_selector.set_active (string_compose ("%1", _visible_channel + 1));
@@ -539,6 +543,7 @@ Pianoroll::build_canvas ()
view = new PianorollMidiView (nullptr, *data_group, *no_scroll_group, *this, *bg, 0xff0000ff);
view->AutomationStateChange.connect (sigc::mem_fun (*this, &Pianoroll::automation_state_changed));
view->VisibleChannelChanged.connect (view_connections, invalidator (*this), std::bind (&Pianoroll::visible_channel_changed, this), gui_context());
bg->set_view (view);
prh->set_view (view);
@@ -574,6 +579,24 @@ Pianoroll::build_canvas ()
bindings_changed ();
}
void
Pianoroll::visible_channel_changed ()
{
if (ignore_channel_changes) {
/* We're changing it */
return;
}
/* Something else changed it */
if (!view) {
return; /* Ought to be impossible */
}
_visible_channel = view->visible_channel();
visible_channel_selector.set_active (string_compose ("%1", view->visible_channel() + 1));
}
void
Pianoroll::bindings_changed ()
{

View File

@@ -252,6 +252,7 @@ class Pianoroll : public CueEditor
sigc::connection _update_connection;
PBD::ScopedConnectionList object_connections;
PBD::ScopedConnectionList view_connections;
void maybe_update ();
void trigger_prop_change (PBD::PropertyChange const &);
@@ -304,4 +305,7 @@ class Pianoroll : public CueEditor
void add_multi_controller_item (Gtk::Menu_Helpers::MenuList& ctl_items, uint16_t channels, int ctl, const std::string& name, ArdourWidgets::MetaButton*);
void reset_user_cc_choice (std::string, Evoral::Parameter param, ArdourWidgets::MetaButton*);
bool ignore_channel_changes;
void visible_channel_changed ();
};