2023-11-25 15:25:29 -07:00
|
|
|
/*
|
|
|
|
|
* Copyright (C) 2006-2014 David Robillard <d@drobilla.net>
|
|
|
|
|
* Copyright (C) 2007 Doug McLain <doug@nostar.net>
|
|
|
|
|
* Copyright (C) 2008-2017 Paul Davis <paul@linuxaudiosystems.com>
|
|
|
|
|
* Copyright (C) 2009-2012 Carl Hetherington <carl@carlh.net>
|
|
|
|
|
* Copyright (C) 2014-2019 Robin Gareus <robin@gareus.org>
|
|
|
|
|
* Copyright (C) 2015 Tim Mayberry <mojofunk@gmail.com>
|
|
|
|
|
* Copyright (C) 2016 Nick Mainsbridge <mainsbridge@gmail.com>
|
|
|
|
|
*
|
|
|
|
|
* 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.,
|
|
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
|
|
|
*/
|
|
|
|
|
|
2025-06-02 19:46:25 -06:00
|
|
|
#include "canvas/debug.h"
|
|
|
|
|
#include "canvas/rect_set.h"
|
2023-11-25 15:25:29 -07:00
|
|
|
|
|
|
|
|
#include "midi_view_background.h"
|
|
|
|
|
#include "ui_config.h"
|
|
|
|
|
|
|
|
|
|
#include "pbd/i18n.h"
|
|
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
|
2025-06-02 18:32:00 -06:00
|
|
|
MidiViewBackground::MidiViewBackground (ArdourCanvas::Item* parent, EditingContext& ec)
|
2025-06-04 14:10:46 -06:00
|
|
|
: note_range_adjustment (0.0f, 0.0f, 0.0f)
|
|
|
|
|
, _editing_context (ec)
|
2023-11-25 15:25:29 -07:00
|
|
|
, _range_dirty (false)
|
|
|
|
|
, _range_sum_cache (-1.0)
|
|
|
|
|
, _lowest_note (UIConfiguration::instance().get_default_lower_midi_note())
|
|
|
|
|
, _highest_note (UIConfiguration::instance().get_default_upper_midi_note())
|
2025-02-25 13:12:50 -07:00
|
|
|
, _data_note_min (127)
|
|
|
|
|
, _data_note_max (0)
|
2025-06-02 18:32:00 -06:00
|
|
|
, _note_lines (new ArdourCanvas::RectSet (parent))
|
2024-01-04 19:07:52 -07:00
|
|
|
, _note_mode (ARDOUR::Sustained)
|
|
|
|
|
, _color_mode (ARDOUR::MeterColors)
|
2024-11-09 09:19:01 -07:00
|
|
|
, _visibility_note_range (ContentsRange)
|
2025-02-25 13:12:50 -07:00
|
|
|
, note_range_set (false)
|
2023-11-25 15:25:29 -07:00
|
|
|
{
|
2025-06-02 18:32:00 -06:00
|
|
|
CANVAS_DEBUG_NAME (_note_lines, "MVB note lines");
|
2023-11-25 15:25:29 -07:00
|
|
|
_note_lines->lower_to_bottom();
|
|
|
|
|
|
2024-01-08 14:35:15 -07:00
|
|
|
// color_handler ();
|
2023-11-25 15:25:29 -07:00
|
|
|
|
|
|
|
|
UIConfiguration::instance().ColorsChanged.connect(sigc::mem_fun(*this, &MidiViewBackground::color_handler));
|
|
|
|
|
UIConfiguration::instance().ParameterChanged.connect(sigc::mem_fun(*this, &MidiViewBackground::parameter_changed));
|
|
|
|
|
|
|
|
|
|
note_range_adjustment.set_page_size(_highest_note - _lowest_note);
|
|
|
|
|
note_range_adjustment.set_value(_lowest_note);
|
2024-02-09 20:59:50 -07:00
|
|
|
note_range_adjustment.set_lower(0);
|
|
|
|
|
note_range_adjustment.set_upper(127);
|
2023-11-25 15:25:29 -07:00
|
|
|
|
2025-06-02 19:46:55 -06:00
|
|
|
note_range_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &MidiViewBackground::note_range_adjustment_changed));
|
2023-11-25 15:25:29 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MidiViewBackground::~MidiViewBackground()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
MidiViewBackground::parameter_changed (std::string const & param)
|
|
|
|
|
{
|
|
|
|
|
if (param == X_("max-note-height")) {
|
|
|
|
|
apply_note_range (_lowest_note, _highest_note, true);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
MidiViewBackground::color_handler ()
|
|
|
|
|
{
|
2025-06-02 19:46:25 -06:00
|
|
|
setup_note_lines ();
|
2023-11-25 15:25:29 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint8_t
|
2025-06-02 19:28:10 -06:00
|
|
|
MidiViewBackground::y_to_note (int y) const
|
2023-11-25 15:25:29 -07:00
|
|
|
{
|
2025-06-09 09:29:52 -06:00
|
|
|
int const n = highest_note() - (floor ((double) y / note_height()));
|
2023-11-25 15:25:29 -07:00
|
|
|
|
|
|
|
|
if (n < 0) {
|
|
|
|
|
return 0;
|
|
|
|
|
} else if (n > 127) {
|
|
|
|
|
return 127;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* min due to rounding and/or off-by-one errors */
|
|
|
|
|
return min ((uint8_t) n, highest_note());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
MidiViewBackground::update_contents_height ()
|
|
|
|
|
{
|
2024-01-08 14:38:16 -07:00
|
|
|
ViewBackground::update_contents_height ();
|
|
|
|
|
|
2025-06-02 19:46:25 -06:00
|
|
|
setup_note_lines ();
|
2023-11-25 15:25:29 -07:00
|
|
|
apply_note_range (lowest_note(), highest_note(), true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2025-06-02 19:47:44 -06:00
|
|
|
MidiViewBackground::get_note_positions (std::vector<int>& numbers, std::vector<int>& pos, std::vector<int>& heights) const
|
|
|
|
|
{
|
|
|
|
|
for (auto const & r : _note_lines->rects()) {
|
|
|
|
|
numbers.push_back (r.index);
|
|
|
|
|
pos.push_back (r.y0);
|
|
|
|
|
heights.push_back (r.height());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
MidiViewBackground::setup_note_lines()
|
2023-11-25 15:25:29 -07:00
|
|
|
{
|
|
|
|
|
if (updates_suspended()) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Gtkmm2ext::Color black = UIConfiguration::instance().color_mod ("piano roll black", "piano roll black");
|
|
|
|
|
Gtkmm2ext::Color white = UIConfiguration::instance().color_mod ("piano roll white", "piano roll white");
|
2025-06-02 19:46:25 -06:00
|
|
|
Gtkmm2ext::Color divider = UIConfiguration::instance().color ("piano roll black outline");
|
2023-11-25 15:25:29 -07:00
|
|
|
Gtkmm2ext::Color color;
|
|
|
|
|
|
2025-06-02 19:46:25 -06:00
|
|
|
ArdourCanvas::RectSet::ResetRAII lr (*_note_lines);
|
2023-11-25 15:25:29 -07:00
|
|
|
|
2025-06-10 12:28:27 -06:00
|
|
|
if (contents_height() < 10 || note_height() < 2) {
|
2023-11-25 15:25:29 -07:00
|
|
|
/* context is too small for note lines, or there are too many */
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* do this is order of highest ... lowest since that matches the
|
|
|
|
|
* coordinate system in which y=0 is at the top
|
|
|
|
|
*/
|
|
|
|
|
|
2025-06-02 19:46:25 -06:00
|
|
|
int h = note_height();
|
2025-06-09 09:29:52 -06:00
|
|
|
double y = 0;
|
2025-06-04 14:11:34 -06:00
|
|
|
|
|
|
|
|
for (int i = highest_note(); i >= lowest_note(); --i) {
|
2025-06-02 19:46:25 -06:00
|
|
|
|
2025-06-03 23:17:53 -06:00
|
|
|
if (i > 127) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-25 15:25:29 -07:00
|
|
|
/* add a thicker line/bar which covers the entire vertical height of this note. */
|
|
|
|
|
|
|
|
|
|
switch (i % 12) {
|
|
|
|
|
case 1:
|
|
|
|
|
case 3:
|
|
|
|
|
case 6:
|
|
|
|
|
case 8:
|
|
|
|
|
case 10:
|
|
|
|
|
color = black;
|
|
|
|
|
break;
|
|
|
|
|
case 4:
|
|
|
|
|
case 11:
|
2025-06-02 19:46:25 -06:00
|
|
|
/* this is the line corresponding to the division between B & C and E & F */
|
|
|
|
|
_note_lines->add_rect (i, ArdourCanvas::Rect (0., y, ArdourCanvas::COORD_MAX, y + 1.), divider);
|
2023-11-25 15:25:29 -07:00
|
|
|
/* fallthrough */
|
|
|
|
|
default:
|
|
|
|
|
color = white;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2025-06-10 12:28:27 -06:00
|
|
|
/* There's no clipping region trivially available for the note
|
|
|
|
|
* lines, so make sure the last line doesn't draw "too tall"
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
if (y + h > contents_height()) {
|
|
|
|
|
h = contents_height() - y;
|
|
|
|
|
}
|
|
|
|
|
|
2025-06-04 14:11:34 -06:00
|
|
|
_note_lines->add_rect (i, ArdourCanvas::Rect (0., y, ArdourCanvas::COORD_MAX, y + h), color);
|
2025-06-09 09:29:52 -06:00
|
|
|
|
|
|
|
|
y += h;
|
2025-06-10 12:28:27 -06:00
|
|
|
|
|
|
|
|
if (y >= contents_height()) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
2023-11-25 15:25:29 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2024-01-16 12:16:46 -07:00
|
|
|
MidiViewBackground::set_note_visibility_range_style (VisibleNoteRange r)
|
2023-11-25 15:25:29 -07:00
|
|
|
{
|
2025-10-03 14:19:11 -06:00
|
|
|
if (r == UserRange) {
|
|
|
|
|
_visibility_note_range = UserRange;
|
|
|
|
|
} else if (r == ContentsRange) {
|
2025-06-16 23:01:03 -06:00
|
|
|
if (apply_note_range (_data_note_min, _data_note_max, true)) {
|
|
|
|
|
_visibility_note_range = ContentsRange;
|
|
|
|
|
}
|
2023-11-25 15:25:29 -07:00
|
|
|
} else {
|
2025-06-16 23:01:03 -06:00
|
|
|
if (apply_note_range (0, 127, true)) {
|
|
|
|
|
_visibility_note_range = FullRange;
|
|
|
|
|
}
|
2023-11-25 15:25:29 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-16 12:16:46 -07:00
|
|
|
void
|
|
|
|
|
MidiViewBackground::maybe_extend_note_range (uint8_t note_num)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
bool changed = false;
|
|
|
|
|
|
|
|
|
|
if (_visibility_note_range == FullRange) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-25 13:12:50 -07:00
|
|
|
if (note_range_set) {
|
|
|
|
|
|
|
|
|
|
if (_lowest_note > _data_note_min) {
|
|
|
|
|
changed = true;
|
|
|
|
|
}
|
2024-01-16 12:16:46 -07:00
|
|
|
|
2025-02-25 13:12:50 -07:00
|
|
|
if (_highest_note < _data_note_max) {
|
|
|
|
|
changed = true;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2024-01-16 12:16:46 -07:00
|
|
|
changed = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (changed) {
|
|
|
|
|
apply_note_range (_data_note_min, _data_note_max, true);
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-01-14 16:49:58 -07:00
|
|
|
|
2025-11-17 11:00:50 -07:00
|
|
|
bool
|
2025-06-10 12:28:27 -06:00
|
|
|
MidiViewBackground::maybe_apply_note_range (uint8_t lowest, uint8_t highest, bool to_children, RangeCanMove can_move)
|
2025-01-14 16:49:58 -07:00
|
|
|
{
|
2025-02-25 13:12:50 -07:00
|
|
|
if (note_range_set && _lowest_note <= lowest && _highest_note >= highest) {
|
2025-01-14 16:49:58 -07:00
|
|
|
/* already large enough */
|
2025-11-17 11:00:50 -07:00
|
|
|
return false;
|
2025-01-14 16:49:58 -07:00
|
|
|
}
|
|
|
|
|
|
2025-11-17 11:00:50 -07:00
|
|
|
return apply_note_range (lowest, highest, to_children, can_move);
|
2025-01-14 16:49:58 -07:00
|
|
|
}
|
|
|
|
|
|
2025-06-16 23:01:03 -06:00
|
|
|
bool
|
2025-06-10 12:28:27 -06:00
|
|
|
MidiViewBackground::apply_note_range (uint8_t lowest, uint8_t highest, bool to_children, RangeCanMove can_move)
|
2023-11-25 15:25:29 -07:00
|
|
|
{
|
2025-06-04 20:41:29 -06:00
|
|
|
if (contents_height() == 0) {
|
2025-06-16 23:01:03 -06:00
|
|
|
return false;
|
2025-06-04 20:41:29 -06:00
|
|
|
}
|
|
|
|
|
|
2024-01-12 12:51:13 -07:00
|
|
|
bool changed = false;
|
|
|
|
|
|
2025-04-28 08:58:25 -06:00
|
|
|
/* Enforce a 1 octave minimum */
|
|
|
|
|
|
|
|
|
|
if (highest - lowest < 12) {
|
|
|
|
|
int8_t mid = lowest + ((highest - lowest) / 2);
|
|
|
|
|
lowest = std::max (mid - 6, 0);
|
|
|
|
|
highest = lowest + 12;
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-12 12:51:13 -07:00
|
|
|
if (_highest_note != highest) {
|
|
|
|
|
_highest_note = highest;
|
|
|
|
|
changed = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_lowest_note != lowest) {
|
|
|
|
|
changed = true;
|
|
|
|
|
_lowest_note = lowest;
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-25 13:12:50 -07:00
|
|
|
if (note_range_set && !changed) {
|
2025-06-16 23:01:03 -06:00
|
|
|
return false;
|
2024-01-12 12:51:13 -07:00
|
|
|
}
|
2023-11-25 15:25:29 -07:00
|
|
|
|
|
|
|
|
float uiscale = UIConfiguration::instance().get_ui_scale();
|
|
|
|
|
|
2025-07-01 17:31:35 -06:00
|
|
|
int range = _highest_note - _lowest_note;
|
|
|
|
|
int apparent_note_height = (int) ceil ((double) contents_height() / range);
|
|
|
|
|
int nh = std::min ((int) (UIConfiguration::instance().get_max_note_height() * uiscale), apparent_note_height);
|
2025-06-04 20:41:03 -06:00
|
|
|
int additional_notes = 0;
|
2023-11-25 15:25:29 -07:00
|
|
|
|
2025-07-07 13:47:36 -06:00
|
|
|
if (nh < 1) {
|
2025-07-01 17:31:35 -06:00
|
|
|
/* range does not fit, so center on the data range */
|
2025-07-07 13:47:36 -06:00
|
|
|
nh = 1;
|
2025-07-01 17:31:35 -06:00
|
|
|
range = _data_note_max - _data_note_min;
|
|
|
|
|
int center = _data_note_min + (range /2);
|
|
|
|
|
highest = center + ((contents_height() / nh) / 2);
|
|
|
|
|
lowest = center - ((contents_height() / nh) / 2);
|
|
|
|
|
}
|
|
|
|
|
|
2025-06-10 12:28:27 -06:00
|
|
|
if (note_range_set) {
|
2025-06-16 23:01:03 -06:00
|
|
|
/* how many notes do we need to add or remove to adequately
|
|
|
|
|
* fill contents_height() with note lines?
|
|
|
|
|
*/
|
2025-06-10 12:28:27 -06:00
|
|
|
additional_notes = (int) ceil ((contents_height() - (nh * range)) / (double) nh);
|
|
|
|
|
}
|
2023-11-25 15:25:29 -07:00
|
|
|
|
2025-06-10 12:28:27 -06:00
|
|
|
/* distribute additional notes to higher and lower ranges, clamp at 0 and 127 */
|
|
|
|
|
if (additional_notes > 0) {
|
|
|
|
|
for (int i = 0; i < additional_notes; i++){
|
|
|
|
|
|
|
|
|
|
if ((can_move & CanMoveTop) || (i % 2 && _highest_note < 127)) {
|
|
|
|
|
_highest_note++;
|
|
|
|
|
} else if ((can_move & CanMoveBottom) && (i % 2)) {
|
|
|
|
|
_lowest_note--;
|
|
|
|
|
} else if ((can_move & CanMoveBottom) && (_lowest_note > 0)) {
|
|
|
|
|
_lowest_note--;
|
|
|
|
|
} else if (can_move & CanMoveTop) {
|
|
|
|
|
_highest_note++;
|
|
|
|
|
}
|
2023-11-25 15:25:29 -07:00
|
|
|
}
|
2025-06-10 12:28:27 -06:00
|
|
|
} else if (additional_notes < 0) {
|
|
|
|
|
for (int i = 0; i < -additional_notes; i++){
|
|
|
|
|
|
|
|
|
|
if ((can_move & CanMoveTop) && (i % 2 && _highest_note < 127)) {
|
|
|
|
|
_highest_note--;
|
2025-06-30 09:39:51 -06:00
|
|
|
} else if ((can_move & CanMoveBottom) && (i % 2)) {
|
2025-06-10 12:28:27 -06:00
|
|
|
_lowest_note++;
|
2025-06-30 09:39:51 -06:00
|
|
|
} else if ((can_move & CanMoveBottom) && (_lowest_note > 0)) {
|
2025-06-10 12:28:27 -06:00
|
|
|
_lowest_note++;
|
2025-06-30 09:39:51 -06:00
|
|
|
} else if ((can_move & CanMoveTop)) {
|
2025-06-10 12:28:27 -06:00
|
|
|
_highest_note--;
|
|
|
|
|
}
|
2023-11-25 15:25:29 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
note_range_adjustment.set_page_size (_highest_note - _lowest_note);
|
|
|
|
|
note_range_adjustment.set_value (_lowest_note);
|
|
|
|
|
|
2025-06-02 19:46:25 -06:00
|
|
|
setup_note_lines();
|
2023-11-25 15:25:29 -07:00
|
|
|
|
|
|
|
|
if (to_children) {
|
|
|
|
|
apply_note_range_to_children ();
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-25 13:12:50 -07:00
|
|
|
note_range_set = true;
|
|
|
|
|
|
2023-11-25 15:25:29 -07:00
|
|
|
NoteRangeChanged(); /* EMIT SIGNAL*/
|
2025-06-16 23:01:03 -06:00
|
|
|
|
|
|
|
|
return true;
|
2023-11-25 15:25:29 -07:00
|
|
|
}
|
|
|
|
|
|
2025-06-10 12:28:27 -06:00
|
|
|
void
|
|
|
|
|
MidiViewBackground::note_range_adjustment_changed()
|
|
|
|
|
{
|
|
|
|
|
double sum = note_range_adjustment.get_value() + note_range_adjustment.get_page_size();
|
|
|
|
|
int lowest = (int) floor(note_range_adjustment.get_value());
|
|
|
|
|
int highest;
|
|
|
|
|
|
|
|
|
|
if (sum == _range_sum_cache) {
|
|
|
|
|
//cerr << "cached" << endl;
|
|
|
|
|
highest = (int) floor(sum);
|
|
|
|
|
} else {
|
|
|
|
|
//cerr << "recalc" << endl;
|
|
|
|
|
highest = lowest + (int) floor(note_range_adjustment.get_page_size());
|
|
|
|
|
_range_sum_cache = sum;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (lowest == _lowest_note && highest == _highest_note) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// cerr << " val=" << v_zoom_adjustment.get_value() << " page=" << v_zoom_adjustment.get_page_size() << " sum=" << v_zoom_adjustment.get_value() + v_zoom_adjustment.get_page_size() << endl;
|
|
|
|
|
|
|
|
|
|
apply_note_range (lowest, highest, true);
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-25 15:25:29 -07:00
|
|
|
bool
|
|
|
|
|
MidiViewBackground::update_data_note_range (uint8_t min, uint8_t max)
|
|
|
|
|
{
|
|
|
|
|
bool dirty = false;
|
2025-07-01 17:31:35 -06:00
|
|
|
|
2025-07-08 17:59:57 -06:00
|
|
|
/* Note: pitches can come and go, so both min and max could be moving
|
|
|
|
|
* up or down on any call.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
if (min != _data_note_min) {
|
2023-11-25 15:25:29 -07:00
|
|
|
_data_note_min = min;
|
|
|
|
|
dirty = true;
|
|
|
|
|
}
|
2025-07-08 17:59:57 -06:00
|
|
|
if (max != _data_note_max) {
|
2023-11-25 15:25:29 -07:00
|
|
|
_data_note_max = max;
|
|
|
|
|
dirty = true;
|
|
|
|
|
}
|
2025-07-08 17:59:57 -06:00
|
|
|
|
2023-11-25 15:25:29 -07:00
|
|
|
return dirty;
|
|
|
|
|
}
|
2024-12-13 21:48:18 -07:00
|
|
|
|
|
|
|
|
void
|
|
|
|
|
MidiViewBackground::set_note_mode (ARDOUR::NoteMode nm)
|
|
|
|
|
{
|
2025-01-15 10:34:40 -07:00
|
|
|
if (_note_mode != nm) {
|
|
|
|
|
_note_mode = nm;
|
|
|
|
|
NoteModeChanged(); /* EMIT SIGNAL */
|
|
|
|
|
}
|
2024-12-13 21:48:18 -07:00
|
|
|
}
|