Compare commits
27 Commits
master
...
mode-clamp
Author | SHA1 | Date |
---|---|---|
Paul Davis | dc8382c0b5 | |
Paul Davis | e8baad9efa | |
Paul Davis | d0cdd0c9db | |
Paul Davis | bf28ecfc4c | |
Paul Davis | 407936277f | |
Paul Davis | bfe52ca668 | |
Paul Davis | a3a8f355ee | |
Paul Davis | 9f4bf02980 | |
Paul Davis | 987c4de725 | |
Paul Davis | ae8c755d51 | |
Paul Davis | 331377212e | |
Paul Davis | eb0c1984de | |
Paul Davis | 2bb880aac0 | |
Paul Davis | 1793c9a61a | |
Paul Davis | 4648785935 | |
Paul Davis | 6cdbd4174d | |
Paul Davis | 9f76d688fd | |
Paul Davis | 1555896d8e | |
Paul Davis | 55a0aadc74 | |
Paul Davis | 22efa2bf17 | |
Paul Davis | 15e4ba5123 | |
Paul Davis | 7f88c71bd3 | |
Paul Davis | fb7dd71c45 | |
Paul Davis | 4801f488c5 | |
Paul Davis | a7907d9e99 | |
Paul Davis | 46242a0079 | |
Paul Davis | b4d6b888bb |
|
@ -856,6 +856,13 @@ MidiRegionView::create_note_at (timepos_t const & t, double y, Temporal::Beats l
|
||||||
Temporal::Beats region_start = t.beats();
|
Temporal::Beats region_start = t.beats();
|
||||||
|
|
||||||
const double note = view->y_to_note(y);
|
const double note = view->y_to_note(y);
|
||||||
|
|
||||||
|
if (mtv->midi_track()->key_enforcment_policy() & NoInsert) {
|
||||||
|
if (!mtv->midi_track()->key().in_key (note)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const uint8_t chan = get_channel_for_add(region_start);
|
const uint8_t chan = get_channel_for_add(region_start);
|
||||||
const uint8_t velocity = get_velocity_for_add (region_start);
|
const uint8_t velocity = get_velocity_for_add (region_start);
|
||||||
|
|
||||||
|
@ -1638,6 +1645,15 @@ MidiRegionView::update_sustained (Note* ev, bool update_ghost_regions)
|
||||||
const timepos_t note_start (note->time());
|
const timepos_t note_start (note->time());
|
||||||
timepos_t note_end (note->end_time());
|
timepos_t note_end (note->end_time());
|
||||||
|
|
||||||
|
MidiTimeAxisView* mtv = dynamic_cast<MidiTimeAxisView*>(&trackview);
|
||||||
|
MusicalKey const & key (mtv->midi_track()->key());
|
||||||
|
if (!(mtv->midi_track()->key_enforcment_policy() & NoDraw) || key.in_key (note->note())) {
|
||||||
|
ev->show ();
|
||||||
|
} else {
|
||||||
|
ev->hide ();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* The note is drawn as a child item of this region view, so its
|
/* The note is drawn as a child item of this region view, so its
|
||||||
* coordinate system is relative to the region view. This means that x0
|
* coordinate system is relative to the region view. This means that x0
|
||||||
* and x1 are pixel offsets relative to beginning of the region (view)
|
* and x1 are pixel offsets relative to beginning of the region (view)
|
||||||
|
@ -2681,6 +2697,9 @@ MidiRegionView::note_dropped(NoteBase *, timecnt_t const & d_qn, int8_t dnote, b
|
||||||
uint8_t highest_note_in_selection = 0;
|
uint8_t highest_note_in_selection = 0;
|
||||||
uint8_t highest_note_difference = 0;
|
uint8_t highest_note_difference = 0;
|
||||||
|
|
||||||
|
MidiTimeAxisView* mtv = dynamic_cast<MidiTimeAxisView*>(&trackview);
|
||||||
|
MusicalKey const & key (mtv->midi_track()->key());
|
||||||
|
|
||||||
if (!copy) {
|
if (!copy) {
|
||||||
// find highest and lowest notes first
|
// find highest and lowest notes first
|
||||||
|
|
||||||
|
@ -2726,7 +2745,11 @@ MidiRegionView::note_dropped(NoteBase *, timecnt_t const & d_qn, int8_t dnote, b
|
||||||
lowest_note_in_selection = std::min(lowest_note_in_selection, new_pitch);
|
lowest_note_in_selection = std::min(lowest_note_in_selection, new_pitch);
|
||||||
highest_note_in_selection = std::max(highest_note_in_selection, new_pitch);
|
highest_note_in_selection = std::max(highest_note_in_selection, new_pitch);
|
||||||
|
|
||||||
note_diff_add_change (*i, MidiModel::NoteDiffCommand::NoteNumber, new_pitch);
|
if (!(mtv->midi_track()->key_enforcment_policy() & NoInsert) || key.in_key (new_pitch)) {
|
||||||
|
note_diff_add_change (*i, MidiModel::NoteDiffCommand::NoteNumber, new_pitch);
|
||||||
|
} else {
|
||||||
|
/* XXX remove it? or what? */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
@ -2769,6 +2792,10 @@ MidiRegionView::note_dropped(NoteBase *, timecnt_t const & d_qn, int8_t dnote, b
|
||||||
lowest_note_in_selection = std::min(lowest_note_in_selection, new_pitch);
|
lowest_note_in_selection = std::min(lowest_note_in_selection, new_pitch);
|
||||||
highest_note_in_selection = std::max(highest_note_in_selection, new_pitch);
|
highest_note_in_selection = std::max(highest_note_in_selection, new_pitch);
|
||||||
|
|
||||||
|
if (!(mtv->midi_track()->key_enforcment_policy() & NoInsert) || key.in_key (new_pitch)) {
|
||||||
|
note_diff_add_change (*i, MidiModel::NoteDiffCommand::NoteNumber, new_pitch);
|
||||||
|
}
|
||||||
|
|
||||||
note_diff_add_note ((*i)->note(), true);
|
note_diff_add_note ((*i)->note(), true);
|
||||||
|
|
||||||
delete *i;
|
delete *i;
|
||||||
|
@ -4219,7 +4246,7 @@ MidiRegionView::get_note_name (boost::shared_ptr<NoteType> n, uint8_t note_value
|
||||||
name.empty() ? ParameterDescriptor::midi_note_name (note_value).c_str() : name.c_str(),
|
name.empty() ? ParameterDescriptor::midi_note_name (note_value).c_str() : name.c_str(),
|
||||||
(int) note_value,
|
(int) note_value,
|
||||||
(int) n->channel() + 1,
|
(int) n->channel() + 1,
|
||||||
(int) n->velocity()); //we display velocity 0-based; velocity 0 is a 'note-off' so the user just sees values 1..127 which 'looks' 1-based
|
(int) n->velocity()); //we display velocity 0-based; velocity 0 is a 'note-off' so the user just sees values 1..127 which 'looks' 1-based
|
||||||
|
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
|
@ -349,19 +349,34 @@ MidiStreamView::draw_note_lines()
|
||||||
* height of this note.
|
* height of this note.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
std::string color_mod_name;
|
||||||
|
std::string color_name;
|
||||||
|
|
||||||
switch (i % 12) {
|
switch (i % 12) {
|
||||||
case 1:
|
case 1:
|
||||||
case 3:
|
case 3:
|
||||||
case 6:
|
case 6:
|
||||||
case 8:
|
case 8:
|
||||||
case 10:
|
case 10:
|
||||||
color = UIConfiguration::instance().color_mod ("piano roll black", "piano roll black");
|
if (boost::dynamic_pointer_cast<MidiTrack>(_trackview.track())->key().in_key (i)) {
|
||||||
|
color_name = X_("piano roll black");
|
||||||
|
} else {
|
||||||
|
color_name = X_("piano roll offkey");
|
||||||
|
}
|
||||||
|
color_mod_name = X_("piano roll black");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
color = UIConfiguration::instance().color_mod ("piano roll white", "piano roll white");
|
if (boost::dynamic_pointer_cast<MidiTrack>(_trackview.track())->key().in_key (i)) {
|
||||||
|
color_name = X_("piano roll white");
|
||||||
|
} else {
|
||||||
|
color_name = X_("piano roll offkey");
|
||||||
|
}
|
||||||
|
color_mod_name = X_("piano roll white");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
color = UIConfiguration::instance().color_mod (color_name, color_mod_name);
|
||||||
|
|
||||||
double h = y - prev_y;
|
double h = y - prev_y;
|
||||||
double mid = y + (h/2.0);
|
double mid = y + (h/2.0);
|
||||||
|
|
||||||
|
|
|
@ -640,6 +640,10 @@ MidiTimeAxisView::append_extra_display_menu_items ()
|
||||||
cmi->set_active (midi_track ()->restore_pgm_on_load ());
|
cmi->set_active (midi_track ()->restore_pgm_on_load ());
|
||||||
cmi->signal_activate().connect (sigc::mem_fun (*this, &MidiTimeAxisView::toggle_restore_pgm_on_load));
|
cmi->signal_activate().connect (sigc::mem_fun (*this, &MidiTimeAxisView::toggle_restore_pgm_on_load));
|
||||||
|
|
||||||
|
items.push_back (MenuElem (_("Scale"), *build_musical_mode_menu ()));
|
||||||
|
items.push_back (MenuElem (_("Tonic (Root)"), *build_musical_root_menu ()));
|
||||||
|
items.push_back (MenuElem (_("Key Enforcement"), *build_key_enforcement_menu()));
|
||||||
|
|
||||||
items.push_back (MenuElem (_("Color Mode"), *build_color_mode_menu ()));
|
items.push_back (MenuElem (_("Color Mode"), *build_color_mode_menu ()));
|
||||||
|
|
||||||
items.push_back (SeparatorElem ());
|
items.push_back (SeparatorElem ());
|
||||||
|
@ -1117,6 +1121,376 @@ MidiTimeAxisView::build_note_mode_menu()
|
||||||
return mode_menu;
|
return mode_menu;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Gtk::Menu*
|
||||||
|
MidiTimeAxisView::build_musical_root_menu ()
|
||||||
|
{
|
||||||
|
using namespace Menu_Helpers;
|
||||||
|
|
||||||
|
Menu* root_menu = manage (new Menu);
|
||||||
|
MenuList& items = root_menu->items();
|
||||||
|
root_menu->set_name ("ArdourContextMenu");
|
||||||
|
|
||||||
|
RadioMenuItem::Group root_group;
|
||||||
|
RadioMenuItem* last_item;
|
||||||
|
|
||||||
|
int r = midi_track()->key().root();
|
||||||
|
|
||||||
|
for (int n = 0; n < 12; ++n) {
|
||||||
|
items.push_back (RadioMenuElem (root_group, ParameterDescriptor::midi_note_name (n, true, false), sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::set_musical_root), n)));
|
||||||
|
last_item = dynamic_cast<RadioMenuItem*>(&items.back());
|
||||||
|
last_item->set_active (r == n);
|
||||||
|
}
|
||||||
|
|
||||||
|
return root_menu;
|
||||||
|
}
|
||||||
|
|
||||||
|
Gtk::Menu*
|
||||||
|
MidiTimeAxisView::build_key_enforcement_menu ()
|
||||||
|
{
|
||||||
|
using namespace Menu_Helpers;
|
||||||
|
|
||||||
|
Menu* menu = manage (new Menu);
|
||||||
|
MenuList& items = menu->items();
|
||||||
|
menu->set_name ("ArdourContextMenu");
|
||||||
|
|
||||||
|
RadioMenuItem::Group group;
|
||||||
|
CheckMenuItem* last_check_item;
|
||||||
|
RadioMenuItem* last_radio_item;
|
||||||
|
|
||||||
|
KeyEnforcementPolicy kep = midi_track()->key_enforcment_policy();
|
||||||
|
|
||||||
|
items.push_back (CheckMenuElem (_("Don't show non-scale ghost notes while drawing/editing")));
|
||||||
|
last_check_item = dynamic_cast<CheckMenuItem*>(&items.back());
|
||||||
|
last_check_item->set_active (kep & NoDraw);
|
||||||
|
last_check_item->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::toggle_key_enforcement_policy), NoDraw, last_check_item));
|
||||||
|
items.push_back (CheckMenuElem (_("Don't allow mouse edits to create non-scale notes")));
|
||||||
|
last_check_item = dynamic_cast<CheckMenuItem*>(&items.back());
|
||||||
|
last_check_item->set_active (kep & NoInsert);
|
||||||
|
last_check_item->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::toggle_key_enforcement_policy), NoInsert, last_check_item));
|
||||||
|
|
||||||
|
items.push_back (RadioMenuElem (group, _("Force note edits of non-scale notes to next lower note")));
|
||||||
|
last_radio_item = dynamic_cast<RadioMenuItem*>(&items.back());
|
||||||
|
last_radio_item->set_active (kep & ForceLower);
|
||||||
|
last_radio_item->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::toggle_key_enforcement_policy), ForceLower, last_radio_item));
|
||||||
|
items.push_back (RadioMenuElem (group, _("Force note edits of non-scale notes to next higher note")));
|
||||||
|
last_radio_item = dynamic_cast<RadioMenuItem*>(&items.back());
|
||||||
|
last_radio_item->set_active (kep & ForceHigher);
|
||||||
|
last_radio_item->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::toggle_key_enforcement_policy), ForceHigher, last_radio_item));
|
||||||
|
items.push_back (RadioMenuElem (group, _("Force note edits of non-scale notes to nearest note")));
|
||||||
|
last_radio_item = dynamic_cast<RadioMenuItem*>(&items.back());
|
||||||
|
last_radio_item->set_active (kep & ForceNearest);
|
||||||
|
last_radio_item->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::toggle_key_enforcement_policy), ForceNearest, last_radio_item));
|
||||||
|
return menu;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MidiTimeAxisView::toggle_key_enforcement_policy (KeyEnforcementPolicy kepb, CheckMenuItem* item)
|
||||||
|
{
|
||||||
|
KeyEnforcementPolicy kep = midi_track()->key_enforcment_policy();
|
||||||
|
|
||||||
|
/* Some of the menu items that trigger this are radio menu items, and
|
||||||
|
this method will be called when they go inactive. We want to ignore
|
||||||
|
these calls.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!item->get_active()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (kep & kepb) {
|
||||||
|
midi_track()->set_key_enforcement_policy (KeyEnforcementPolicy (kep & ~kepb));
|
||||||
|
} else {
|
||||||
|
midi_track()->set_key_enforcement_policy (KeyEnforcementPolicy (kep | kepb));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MidiTimeAxisView::set_musical_root (int r)
|
||||||
|
{
|
||||||
|
midi_track()->set_key (MusicalKey (midi_track()->key().type(), r));
|
||||||
|
}
|
||||||
|
|
||||||
|
Gtk::Menu*
|
||||||
|
MidiTimeAxisView::build_musical_mode_menu()
|
||||||
|
{
|
||||||
|
using namespace Menu_Helpers;
|
||||||
|
|
||||||
|
Menu* mode_menu = manage (new Menu);
|
||||||
|
MenuList& items = mode_menu->items();
|
||||||
|
mode_menu->set_name ("ArdourContextMenu");
|
||||||
|
|
||||||
|
RadioMenuItem::Group mode_group;
|
||||||
|
RadioMenuItem* last_item;
|
||||||
|
|
||||||
|
MusicalMode::Type t = midi_track()->key().type();
|
||||||
|
|
||||||
|
items.push_back (
|
||||||
|
RadioMenuElem (mode_group, _("Chromatic"),
|
||||||
|
sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::set_musical_mode),
|
||||||
|
MusicalMode::Chromatic)));
|
||||||
|
last_item = dynamic_cast<RadioMenuItem*>(&items.back());
|
||||||
|
last_item->set_active (t == MusicalMode::Chromatic);
|
||||||
|
|
||||||
|
items.push_back (
|
||||||
|
RadioMenuElem (mode_group, _("Major (Ionian)"),
|
||||||
|
sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::set_musical_mode),
|
||||||
|
MusicalMode::IonianMajor)));
|
||||||
|
last_item = dynamic_cast<RadioMenuItem*>(&items.back());
|
||||||
|
last_item->set_active (t == MusicalMode::IonianMajor);
|
||||||
|
|
||||||
|
items.push_back (
|
||||||
|
RadioMenuElem (mode_group, _("Minor (Aeolian)"),
|
||||||
|
sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::set_musical_mode),
|
||||||
|
MusicalMode::AeolianMinor)));
|
||||||
|
last_item = dynamic_cast<RadioMenuItem*>(&items.back());
|
||||||
|
last_item->set_active (t == MusicalMode::AeolianMinor);
|
||||||
|
|
||||||
|
items.push_back (
|
||||||
|
RadioMenuElem (mode_group, _("Dorian"),
|
||||||
|
sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::set_musical_mode),
|
||||||
|
MusicalMode::Dorian)));
|
||||||
|
last_item = dynamic_cast<RadioMenuItem*>(&items.back());
|
||||||
|
last_item->set_active (t == MusicalMode::Dorian);
|
||||||
|
|
||||||
|
items.push_back (
|
||||||
|
RadioMenuElem (mode_group, _("HarmonicMinor"),
|
||||||
|
sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::set_musical_mode),
|
||||||
|
MusicalMode::HarmonicMinor)));
|
||||||
|
last_item = dynamic_cast<RadioMenuItem*>(&items.back());
|
||||||
|
last_item->set_active (t == 30);
|
||||||
|
|
||||||
|
items.push_back (
|
||||||
|
RadioMenuElem (mode_group, _("MelodicMinorAscending"),
|
||||||
|
sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::set_musical_mode),
|
||||||
|
MusicalMode::MelodicMinorAscending)));
|
||||||
|
last_item = dynamic_cast<RadioMenuItem*>(&items.back());
|
||||||
|
last_item->set_active (t == MusicalMode::MelodicMinorAscending);
|
||||||
|
|
||||||
|
items.push_back (
|
||||||
|
RadioMenuElem (mode_group, _("MelodicMinorDescending"),
|
||||||
|
sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::set_musical_mode),
|
||||||
|
MusicalMode::MelodicMinorDescending)));
|
||||||
|
last_item = dynamic_cast<RadioMenuItem*>(&items.back());
|
||||||
|
last_item->set_active (t == MusicalMode::MelodicMinorDescending);
|
||||||
|
|
||||||
|
items.push_back (
|
||||||
|
RadioMenuElem (mode_group, _("Phrygian"),
|
||||||
|
sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::set_musical_mode),
|
||||||
|
MusicalMode::Phrygian)));
|
||||||
|
last_item = dynamic_cast<RadioMenuItem*>(&items.back());
|
||||||
|
last_item->set_active (t == MusicalMode::Phrygian);
|
||||||
|
|
||||||
|
items.push_back (
|
||||||
|
RadioMenuElem (mode_group, _("Lydian"),
|
||||||
|
sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::set_musical_mode),
|
||||||
|
MusicalMode::Lydian)));
|
||||||
|
last_item = dynamic_cast<RadioMenuItem*>(&items.back());
|
||||||
|
last_item->set_active (t == MusicalMode::Lydian);
|
||||||
|
|
||||||
|
items.push_back (
|
||||||
|
RadioMenuElem (mode_group, _("Mixolydian"),
|
||||||
|
sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::set_musical_mode),
|
||||||
|
MusicalMode::Mixolydian)));
|
||||||
|
last_item = dynamic_cast<RadioMenuItem*>(&items.back());
|
||||||
|
last_item->set_active (t == MusicalMode::Mixolydian);
|
||||||
|
|
||||||
|
items.push_back (
|
||||||
|
RadioMenuElem (mode_group, _("Locrian"),
|
||||||
|
sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::set_musical_mode),
|
||||||
|
MusicalMode::Locrian)));
|
||||||
|
last_item = dynamic_cast<RadioMenuItem*>(&items.back());
|
||||||
|
last_item->set_active (t == MusicalMode::Locrian);
|
||||||
|
|
||||||
|
items.push_back (
|
||||||
|
RadioMenuElem (mode_group, _("PentatonicMajor"),
|
||||||
|
sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::set_musical_mode),
|
||||||
|
MusicalMode::PentatonicMajor)));
|
||||||
|
last_item = dynamic_cast<RadioMenuItem*>(&items.back());
|
||||||
|
last_item->set_active (t == MusicalMode::PentatonicMajor);
|
||||||
|
|
||||||
|
items.push_back (
|
||||||
|
RadioMenuElem (mode_group, _("PentatonicMinor"),
|
||||||
|
sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::set_musical_mode),
|
||||||
|
MusicalMode::PentatonicMinor)));
|
||||||
|
last_item = dynamic_cast<RadioMenuItem*>(&items.back());
|
||||||
|
last_item->set_active (t == MusicalMode::PentatonicMinor);
|
||||||
|
|
||||||
|
items.push_back (
|
||||||
|
RadioMenuElem (mode_group, _("BluesScale"),
|
||||||
|
sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::set_musical_mode),
|
||||||
|
MusicalMode::BluesScale)));
|
||||||
|
last_item = dynamic_cast<RadioMenuItem*>(&items.back());
|
||||||
|
last_item->set_active (t == MusicalMode::BluesScale);
|
||||||
|
|
||||||
|
items.push_back (
|
||||||
|
RadioMenuElem (mode_group, _("NeapolitanMinor"),
|
||||||
|
sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::set_musical_mode),
|
||||||
|
MusicalMode::NeapolitanMinor)));
|
||||||
|
last_item = dynamic_cast<RadioMenuItem*>(&items.back());
|
||||||
|
last_item->set_active (t == MusicalMode::NeapolitanMinor);
|
||||||
|
|
||||||
|
items.push_back (
|
||||||
|
RadioMenuElem (mode_group, _("NeapolitanMajor"),
|
||||||
|
sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::set_musical_mode),
|
||||||
|
MusicalMode::NeapolitanMajor)));
|
||||||
|
last_item = dynamic_cast<RadioMenuItem*>(&items.back());
|
||||||
|
last_item->set_active (t == MusicalMode::NeapolitanMajor);
|
||||||
|
|
||||||
|
items.push_back (
|
||||||
|
RadioMenuElem (mode_group, _("Oriental"),
|
||||||
|
sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::set_musical_mode),
|
||||||
|
MusicalMode::Oriental)));
|
||||||
|
last_item = dynamic_cast<RadioMenuItem*>(&items.back());
|
||||||
|
last_item->set_active (t == MusicalMode::Oriental);
|
||||||
|
|
||||||
|
items.push_back (
|
||||||
|
RadioMenuElem (mode_group, _("DoubleHarmonic"),
|
||||||
|
sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::set_musical_mode),
|
||||||
|
MusicalMode::DoubleHarmonic)));
|
||||||
|
last_item = dynamic_cast<RadioMenuItem*>(&items.back());
|
||||||
|
last_item->set_active (t == MusicalMode::DoubleHarmonic);
|
||||||
|
|
||||||
|
items.push_back (
|
||||||
|
RadioMenuElem (mode_group, _("Enigmatic"),
|
||||||
|
sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::set_musical_mode),
|
||||||
|
MusicalMode::Enigmatic)));
|
||||||
|
last_item = dynamic_cast<RadioMenuItem*>(&items.back());
|
||||||
|
last_item->set_active (t == MusicalMode::Enigmatic);
|
||||||
|
|
||||||
|
items.push_back (
|
||||||
|
RadioMenuElem (mode_group, _("Hirajoshi"),
|
||||||
|
sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::set_musical_mode),
|
||||||
|
MusicalMode::Hirajoshi)));
|
||||||
|
last_item = dynamic_cast<RadioMenuItem*>(&items.back());
|
||||||
|
last_item->set_active (t == MusicalMode::Hirajoshi);
|
||||||
|
|
||||||
|
items.push_back (
|
||||||
|
RadioMenuElem (mode_group, _("HungarianMinor"),
|
||||||
|
sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::set_musical_mode),
|
||||||
|
MusicalMode::HungarianMinor)));
|
||||||
|
last_item = dynamic_cast<RadioMenuItem*>(&items.back());
|
||||||
|
last_item->set_active (t == MusicalMode::HungarianMinor);
|
||||||
|
|
||||||
|
items.push_back (
|
||||||
|
RadioMenuElem (mode_group, _("HungarianMajor"),
|
||||||
|
sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::set_musical_mode),
|
||||||
|
MusicalMode::HungarianMajor)));
|
||||||
|
last_item = dynamic_cast<RadioMenuItem*>(&items.back());
|
||||||
|
last_item->set_active (t == MusicalMode::HungarianMajor);
|
||||||
|
|
||||||
|
items.push_back (
|
||||||
|
RadioMenuElem (mode_group, _("Kumoi"),
|
||||||
|
sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::set_musical_mode),
|
||||||
|
MusicalMode::Kumoi)));
|
||||||
|
last_item = dynamic_cast<RadioMenuItem*>(&items.back());
|
||||||
|
last_item->set_active (t == MusicalMode::Kumoi);
|
||||||
|
|
||||||
|
items.push_back (
|
||||||
|
RadioMenuElem (mode_group, _("Iwato"),
|
||||||
|
sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::set_musical_mode),
|
||||||
|
MusicalMode::Iwato)));
|
||||||
|
last_item = dynamic_cast<RadioMenuItem*>(&items.back());
|
||||||
|
last_item->set_active (t == MusicalMode::Iwato);
|
||||||
|
|
||||||
|
items.push_back (
|
||||||
|
RadioMenuElem (mode_group, _("Hindu"),
|
||||||
|
sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::set_musical_mode),
|
||||||
|
MusicalMode::Hindu)));
|
||||||
|
last_item = dynamic_cast<RadioMenuItem*>(&items.back());
|
||||||
|
last_item->set_active (t == MusicalMode::Hindu);
|
||||||
|
|
||||||
|
items.push_back (
|
||||||
|
RadioMenuElem (mode_group, _("Spanish8Tone"),
|
||||||
|
sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::set_musical_mode),
|
||||||
|
MusicalMode::Spanish8Tone)));
|
||||||
|
last_item = dynamic_cast<RadioMenuItem*>(&items.back());
|
||||||
|
last_item->set_active (t == MusicalMode::Spanish8Tone);
|
||||||
|
|
||||||
|
items.push_back (
|
||||||
|
RadioMenuElem (mode_group, _("Pelog"),
|
||||||
|
sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::set_musical_mode),
|
||||||
|
MusicalMode::Pelog)));
|
||||||
|
last_item = dynamic_cast<RadioMenuItem*>(&items.back());
|
||||||
|
last_item->set_active (t == MusicalMode::Pelog);
|
||||||
|
|
||||||
|
items.push_back (
|
||||||
|
RadioMenuElem (mode_group, _("HungarianGypsy"),
|
||||||
|
sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::set_musical_mode),
|
||||||
|
MusicalMode::HungarianGypsy)));
|
||||||
|
last_item = dynamic_cast<RadioMenuItem*>(&items.back());
|
||||||
|
last_item->set_active (t == MusicalMode::HungarianGypsy);
|
||||||
|
|
||||||
|
items.push_back (
|
||||||
|
RadioMenuElem (mode_group, _("Overtone"),
|
||||||
|
sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::set_musical_mode),
|
||||||
|
MusicalMode::Overtone)));
|
||||||
|
last_item = dynamic_cast<RadioMenuItem*>(&items.back());
|
||||||
|
last_item->set_active (t == MusicalMode::Overtone);
|
||||||
|
|
||||||
|
items.push_back (
|
||||||
|
RadioMenuElem (mode_group, _("LeadingWholeTone"),
|
||||||
|
sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::set_musical_mode),
|
||||||
|
MusicalMode::LeadingWholeTone)));
|
||||||
|
last_item = dynamic_cast<RadioMenuItem*>(&items.back());
|
||||||
|
last_item->set_active (t == MusicalMode::LeadingWholeTone);
|
||||||
|
|
||||||
|
items.push_back (
|
||||||
|
RadioMenuElem (mode_group, _("Arabian"),
|
||||||
|
sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::set_musical_mode),
|
||||||
|
MusicalMode::Arabian)));
|
||||||
|
last_item = dynamic_cast<RadioMenuItem*>(&items.back());
|
||||||
|
last_item->set_active (t == MusicalMode::Arabian);
|
||||||
|
|
||||||
|
items.push_back (
|
||||||
|
RadioMenuElem (mode_group, _("Balinese"),
|
||||||
|
sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::set_musical_mode),
|
||||||
|
MusicalMode::Balinese)));
|
||||||
|
last_item = dynamic_cast<RadioMenuItem*>(&items.back());
|
||||||
|
last_item->set_active (t == MusicalMode::Balinese);
|
||||||
|
|
||||||
|
items.push_back (
|
||||||
|
RadioMenuElem (mode_group, _("Gypsy"),
|
||||||
|
sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::set_musical_mode),
|
||||||
|
MusicalMode::Gypsy)));
|
||||||
|
last_item = dynamic_cast<RadioMenuItem*>(&items.back());
|
||||||
|
last_item->set_active (t == MusicalMode::Gypsy);
|
||||||
|
|
||||||
|
items.push_back (
|
||||||
|
RadioMenuElem (mode_group, _("Mohammedan"),
|
||||||
|
sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::set_musical_mode),
|
||||||
|
MusicalMode::Mohammedan)));
|
||||||
|
last_item = dynamic_cast<RadioMenuItem*>(&items.back());
|
||||||
|
last_item->set_active (t == MusicalMode::Mohammedan);
|
||||||
|
|
||||||
|
items.push_back (
|
||||||
|
RadioMenuElem (mode_group, _("Javanese"),
|
||||||
|
sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::set_musical_mode),
|
||||||
|
MusicalMode::Javanese)));
|
||||||
|
last_item = dynamic_cast<RadioMenuItem*>(&items.back());
|
||||||
|
last_item->set_active (t == MusicalMode::Javanese);
|
||||||
|
|
||||||
|
items.push_back (
|
||||||
|
RadioMenuElem (mode_group, _("Persian"),
|
||||||
|
sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::set_musical_mode),
|
||||||
|
MusicalMode::Persian)));
|
||||||
|
last_item = dynamic_cast<RadioMenuItem*>(&items.back());
|
||||||
|
last_item->set_active (t == MusicalMode::Persian);
|
||||||
|
|
||||||
|
items.push_back (
|
||||||
|
RadioMenuElem (mode_group, _("Algerian"),
|
||||||
|
sigc::bind (sigc::mem_fun (*this, &MidiTimeAxisView::set_musical_mode),
|
||||||
|
MusicalMode::Algerian)));
|
||||||
|
last_item = dynamic_cast<RadioMenuItem*>(&items.back());
|
||||||
|
last_item->set_active (t == MusicalMode::Algerian);
|
||||||
|
|
||||||
|
return mode_menu;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MidiTimeAxisView::set_musical_mode (MusicalMode::Type mode_type)
|
||||||
|
{
|
||||||
|
midi_track()->set_key (MusicalKey (mode_type, midi_track()->key().root()));
|
||||||
|
}
|
||||||
|
|
||||||
Gtk::Menu*
|
Gtk::Menu*
|
||||||
MidiTimeAxisView::build_color_mode_menu()
|
MidiTimeAxisView::build_color_mode_menu()
|
||||||
{
|
{
|
||||||
|
@ -1781,3 +2155,13 @@ MidiTimeAxisView::get_regions_with_selected_data (RegionSelection& rs)
|
||||||
{
|
{
|
||||||
midi_view()->get_regions_with_selected_data (rs);
|
midi_view()->get_regions_with_selected_data (rs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MidiTimeAxisView::route_property_changed (const PBD::PropertyChange& pc)
|
||||||
|
{
|
||||||
|
RouteTimeAxisView::route_property_changed (pc);
|
||||||
|
|
||||||
|
if (pc.contains (Properties::musical_mode) || pc.contains (Properties::musical_root)) {
|
||||||
|
_view->redisplay_track ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -117,6 +117,7 @@ protected:
|
||||||
void start_step_editing ();
|
void start_step_editing ();
|
||||||
void stop_step_editing ();
|
void stop_step_editing ();
|
||||||
void processors_changed (ARDOUR::RouteProcessorChange);
|
void processors_changed (ARDOUR::RouteProcessorChange);
|
||||||
|
void route_property_changed (const PBD::PropertyChange&);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
sigc::signal<void, std::string, std::string> _midi_patch_settings_changed;
|
sigc::signal<void, std::string, std::string> _midi_patch_settings_changed;
|
||||||
|
@ -133,7 +134,13 @@ private:
|
||||||
void build_automation_action_menu (bool);
|
void build_automation_action_menu (bool);
|
||||||
Gtk::Menu* build_note_mode_menu();
|
Gtk::Menu* build_note_mode_menu();
|
||||||
Gtk::Menu* build_color_mode_menu();
|
Gtk::Menu* build_color_mode_menu();
|
||||||
|
Gtk::Menu* build_musical_mode_menu ();
|
||||||
|
Gtk::Menu* build_musical_root_menu ();
|
||||||
|
Gtk::Menu* build_key_enforcement_menu ();
|
||||||
|
|
||||||
|
void toggle_key_enforcement_policy (ARDOUR::KeyEnforcementPolicy, Gtk::CheckMenuItem*);
|
||||||
|
void set_musical_mode (MusicalMode::Type);
|
||||||
|
void set_musical_root (int note);
|
||||||
void set_note_mode (ARDOUR::NoteMode mode, bool apply_to_selection = false);
|
void set_note_mode (ARDOUR::NoteMode mode, bool apply_to_selection = false);
|
||||||
void set_color_mode (ARDOUR::ColorMode, bool force = false, bool redisplay = true, bool apply_to_selection = false);
|
void set_color_mode (ARDOUR::ColorMode, bool force = false, bool redisplay = true, bool apply_to_selection = false);
|
||||||
void set_note_range (MidiStreamView::VisibleNoteRange range, bool apply_to_selection = false);
|
void set_note_range (MidiStreamView::VisibleNoteRange range, bool apply_to_selection = false);
|
||||||
|
@ -199,4 +206,5 @@ private:
|
||||||
StepEditor* _step_editor;
|
StepEditor* _step_editor;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif /* __ardour_midi_time_axis_h__ */
|
#endif /* __ardour_midi_time_axis_h__ */
|
||||||
|
|
|
@ -294,6 +294,7 @@
|
||||||
<ColorAlias name="piano roll black" alias="theme:contrasting selection"/>
|
<ColorAlias name="piano roll black" alias="theme:contrasting selection"/>
|
||||||
<ColorAlias name="piano roll black outline" alias="neutral:foreground2"/>
|
<ColorAlias name="piano roll black outline" alias="neutral:foreground2"/>
|
||||||
<ColorAlias name="piano roll white" alias="neutral:foreground2"/>
|
<ColorAlias name="piano roll white" alias="neutral:foreground2"/>
|
||||||
|
<ColorAlias name="piano roll offkey" alias="alert:ruddy"/>
|
||||||
<ColorAlias name="pinrouting custom: led active" alias="alert:ruddy"/>
|
<ColorAlias name="pinrouting custom: led active" alias="alert:ruddy"/>
|
||||||
<ColorAlias name="pinrouting sidechain: led active" alias="alert:green"/>
|
<ColorAlias name="pinrouting sidechain: led active" alias="alert:green"/>
|
||||||
<ColorAlias name="play head" alias="theme:contrasting"/>
|
<ColorAlias name="play head" alias="theme:contrasting"/>
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Paul Davis <paul@linuxaudiosystems.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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ardour_key_h__
|
||||||
|
#define __ardour_key_h__
|
||||||
|
|
||||||
|
#include "ardour/mode.h"
|
||||||
|
|
||||||
|
class MusicalKey : public MusicalMode
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MusicalKey (Type t, int root) : MusicalMode (t), _root (root) {}
|
||||||
|
~MusicalKey ();
|
||||||
|
|
||||||
|
int root () const { return _root; }
|
||||||
|
void set_root (int);
|
||||||
|
|
||||||
|
bool in_key (int note) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
int _root;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* __ardour_key_h__ */
|
|
@ -24,11 +24,17 @@
|
||||||
|
|
||||||
#include "ardour/midi_channel_filter.h"
|
#include "ardour/midi_channel_filter.h"
|
||||||
#include "ardour/midi_ring_buffer.h"
|
#include "ardour/midi_ring_buffer.h"
|
||||||
|
#include "ardour/key.h"
|
||||||
#include "ardour/track.h"
|
#include "ardour/track.h"
|
||||||
|
|
||||||
namespace ARDOUR
|
namespace ARDOUR
|
||||||
{
|
{
|
||||||
|
|
||||||
|
namespace Properties {
|
||||||
|
LIBARDOUR_API extern PBD::PropertyDescriptor<MusicalKey::Type> musical_mode;
|
||||||
|
LIBARDOUR_API extern PBD::PropertyDescriptor<int> musical_root;
|
||||||
|
}
|
||||||
|
|
||||||
class InterThreadInfo;
|
class InterThreadInfo;
|
||||||
class MidiPlaylist;
|
class MidiPlaylist;
|
||||||
class RouteGroup;
|
class RouteGroup;
|
||||||
|
@ -43,6 +49,8 @@ public:
|
||||||
|
|
||||||
int init ();
|
int init ();
|
||||||
|
|
||||||
|
static void make_property_quarks ();
|
||||||
|
|
||||||
void realtime_locate (bool);
|
void realtime_locate (bool);
|
||||||
void non_realtime_locate (samplepos_t);
|
void non_realtime_locate (samplepos_t);
|
||||||
|
|
||||||
|
@ -144,6 +152,12 @@ public:
|
||||||
void realtime_handle_transport_stopped ();
|
void realtime_handle_transport_stopped ();
|
||||||
void region_edited (boost::shared_ptr<Region>);
|
void region_edited (boost::shared_ptr<Region>);
|
||||||
|
|
||||||
|
MusicalKey const & key() const { return _key; }
|
||||||
|
void set_key (MusicalKey const & key);
|
||||||
|
|
||||||
|
KeyEnforcementPolicy key_enforcment_policy () const;
|
||||||
|
void set_key_enforcement_policy (KeyEnforcementPolicy);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
XMLNode& state (bool save_template);
|
XMLNode& state (bool save_template);
|
||||||
|
@ -166,6 +180,9 @@ private:
|
||||||
MidiChannelFilter _playback_filter;
|
MidiChannelFilter _playback_filter;
|
||||||
MidiChannelFilter _capture_filter;
|
MidiChannelFilter _capture_filter;
|
||||||
|
|
||||||
|
MusicalKey _key;
|
||||||
|
KeyEnforcementPolicy _key_enforcement_policy;
|
||||||
|
|
||||||
void set_state_part_two ();
|
void set_state_part_two ();
|
||||||
void set_state_part_three ();
|
void set_state_part_three ();
|
||||||
|
|
||||||
|
|
|
@ -68,9 +68,11 @@ class MusicalMode
|
||||||
~MusicalMode ();
|
~MusicalMode ();
|
||||||
|
|
||||||
std::vector<float> steps;
|
std::vector<float> steps;
|
||||||
|
Type type() const { return _type; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void fill (MusicalMode&, Type);
|
static void fill (MusicalMode&, Type);
|
||||||
|
Type _type;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* __ardour_mode_h__ */
|
#endif /* __ardour_mode_h__ */
|
||||||
|
|
|
@ -50,7 +50,7 @@ struct LIBARDOUR_API ParameterDescriptor : public Evoral::ParameterDescriptor
|
||||||
HZ, ///< Frequency in Hertz
|
HZ, ///< Frequency in Hertz
|
||||||
};
|
};
|
||||||
|
|
||||||
static std::string midi_note_name (uint8_t, bool translate=true);
|
static std::string midi_note_name (uint8_t, bool translate = true, bool with_octave = true);
|
||||||
|
|
||||||
/** Dual of midi_note_name, convert a note name into its midi note number. */
|
/** Dual of midi_note_name, convert a note name into its midi note number. */
|
||||||
typedef std::map<std::string, uint8_t> NameNumMap;
|
typedef std::map<std::string, uint8_t> NameNumMap;
|
||||||
|
|
|
@ -811,6 +811,15 @@ enum LocateTransportDisposition {
|
||||||
RollIfAppropriate
|
RollIfAppropriate
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum KeyEnforcementPolicy {
|
||||||
|
NoDraw = 0x1, /* do not show visually as candidate for new notes */
|
||||||
|
NoInsert = 0x2,
|
||||||
|
NoPlay = 0x4,
|
||||||
|
ForceLower = 0x8,
|
||||||
|
ForceHigher = 0x10,
|
||||||
|
ForceNearest = 0x20
|
||||||
|
};
|
||||||
|
|
||||||
typedef std::vector<CaptureInfo*> CaptureInfos;
|
typedef std::vector<CaptureInfo*> CaptureInfos;
|
||||||
|
|
||||||
} // namespace ARDOUR
|
} // namespace ARDOUR
|
||||||
|
|
|
@ -158,6 +158,7 @@ setup_enum_writer ()
|
||||||
Trigger::State _TriggerState;
|
Trigger::State _TriggerState;
|
||||||
Trigger::LaunchStyle _TriggerLaunchStyle;
|
Trigger::LaunchStyle _TriggerLaunchStyle;
|
||||||
Trigger::FollowAction _TriggerFollowAction;
|
Trigger::FollowAction _TriggerFollowAction;
|
||||||
|
KeyEnforcementPolicy _KeyEnforcementPolicy;
|
||||||
|
|
||||||
#define REGISTER(e) enum_writer.register_distinct (typeid(e).name(), i, s); i.clear(); s.clear()
|
#define REGISTER(e) enum_writer.register_distinct (typeid(e).name(), i, s); i.clear(); s.clear()
|
||||||
#define REGISTER_BITS(e) enum_writer.register_bits (typeid(e).name(), i, s); i.clear(); s.clear()
|
#define REGISTER_BITS(e) enum_writer.register_bits (typeid(e).name(), i, s); i.clear(); s.clear()
|
||||||
|
@ -868,6 +869,13 @@ setup_enum_writer ()
|
||||||
REGISTER_CLASS_ENUM (Trigger, Repeat);
|
REGISTER_CLASS_ENUM (Trigger, Repeat);
|
||||||
REGISTER (_TriggerLaunchStyle);
|
REGISTER (_TriggerLaunchStyle);
|
||||||
|
|
||||||
|
REGISTER_ENUM (NoDraw);
|
||||||
|
REGISTER_ENUM (NoInsert);
|
||||||
|
REGISTER_ENUM (NoPlay);
|
||||||
|
REGISTER_ENUM (ForceLower);
|
||||||
|
REGISTER_ENUM (ForceHigher);
|
||||||
|
REGISTER_ENUM (ForceNearest);
|
||||||
|
REGISTER_BITS (_KeyEnforcementPolicy);
|
||||||
}
|
}
|
||||||
|
|
||||||
} /* namespace ARDOUR */
|
} /* namespace ARDOUR */
|
||||||
|
|
|
@ -108,6 +108,7 @@
|
||||||
#include "ardour/filesystem_paths.h"
|
#include "ardour/filesystem_paths.h"
|
||||||
#include "ardour/midi_patch_manager.h"
|
#include "ardour/midi_patch_manager.h"
|
||||||
#include "ardour/midi_region.h"
|
#include "ardour/midi_region.h"
|
||||||
|
#include "ardour/midi_track.h"
|
||||||
#include "ardour/midi_ui.h"
|
#include "ardour/midi_ui.h"
|
||||||
#include "ardour/midiport_manager.h"
|
#include "ardour/midiport_manager.h"
|
||||||
#include "ardour/mix.h"
|
#include "ardour/mix.h"
|
||||||
|
@ -563,6 +564,7 @@ ARDOUR::init (bool try_optimization, const char* localedir, bool with_gui)
|
||||||
PresentationInfo::make_property_quarks ();
|
PresentationInfo::make_property_quarks ();
|
||||||
TransportMaster::make_property_quarks ();
|
TransportMaster::make_property_quarks ();
|
||||||
Trigger::make_property_quarks ();
|
Trigger::make_property_quarks ();
|
||||||
|
MidiTrack::make_property_quarks ();
|
||||||
|
|
||||||
/* this is a useful ready to use PropertyChange that many
|
/* this is a useful ready to use PropertyChange that many
|
||||||
things need to check. This avoids having to compose
|
things need to check. This avoids having to compose
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2021 Paul Davis <paul@linuxaudiosystems.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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ardour/key.h"
|
||||||
|
|
||||||
|
MusicalKey::~MusicalKey ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MusicalKey::set_root (int r)
|
||||||
|
{
|
||||||
|
/* force root into lowest octave. Yes, 12 tone for now */
|
||||||
|
_root = (r % 12);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
MusicalKey::in_key (int note) const
|
||||||
|
{
|
||||||
|
/* currently 12 tone based */
|
||||||
|
|
||||||
|
note = note % 12;
|
||||||
|
|
||||||
|
/* we should speed this us. Probably a bitset */
|
||||||
|
|
||||||
|
if (note == _root) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (std::vector<float>::const_iterator i = steps.begin(); i != steps.end(); ++i) {
|
||||||
|
int ii = (int) ((*i) * 2.0);
|
||||||
|
|
||||||
|
if (note == _root + ii) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
|
@ -72,12 +72,27 @@ class InterThreadInfo;
|
||||||
class MidiSource;
|
class MidiSource;
|
||||||
class Region;
|
class Region;
|
||||||
class SMFSource;
|
class SMFSource;
|
||||||
|
|
||||||
|
|
||||||
|
namespace Properties {
|
||||||
|
PBD::PropertyDescriptor<MusicalMode::Type> musical_mode;
|
||||||
|
PBD::PropertyDescriptor<int> musical_root;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace ARDOUR;
|
using namespace ARDOUR;
|
||||||
using namespace PBD;
|
using namespace PBD;
|
||||||
|
|
||||||
|
void
|
||||||
|
MidiTrack::make_property_quarks ()
|
||||||
|
{
|
||||||
|
Properties::musical_mode.property_id = g_quark_from_static_string (X_("musical-mode"));
|
||||||
|
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for musical-mode = %1\n", Properties::musical_mode.property_id));
|
||||||
|
Properties::musical_root.property_id = g_quark_from_static_string (X_("musical-root"));
|
||||||
|
DEBUG_TRACE (DEBUG::Properties, string_compose ("quark for musical-root = %1\n", Properties::musical_root.property_id));
|
||||||
|
}
|
||||||
|
|
||||||
MidiTrack::MidiTrack (Session& sess, string name, TrackMode mode)
|
MidiTrack::MidiTrack (Session& sess, string name, TrackMode mode)
|
||||||
: Track (sess, name, PresentationInfo::MidiTrack, mode, DataType::MIDI)
|
: Track (sess, name, PresentationInfo::MidiTrack, mode, DataType::MIDI)
|
||||||
, _immediate_events(6096) // FIXME: size?
|
, _immediate_events(6096) // FIXME: size?
|
||||||
|
@ -87,6 +102,8 @@ MidiTrack::MidiTrack (Session& sess, string name, TrackMode mode)
|
||||||
, _step_editing (false)
|
, _step_editing (false)
|
||||||
, _input_active (true)
|
, _input_active (true)
|
||||||
, _restore_pgm_on_load (true)
|
, _restore_pgm_on_load (true)
|
||||||
|
, _key (MusicalKey (MusicalMode::IonianMajor, 0))
|
||||||
|
, _key_enforcement_policy (KeyEnforcementPolicy (0))
|
||||||
{
|
{
|
||||||
_session.SessionLoaded.connect_same_thread (*this, boost::bind (&MidiTrack::restore_controls, this));
|
_session.SessionLoaded.connect_same_thread (*this, boost::bind (&MidiTrack::restore_controls, this));
|
||||||
|
|
||||||
|
@ -120,6 +137,31 @@ MidiTrack::init ()
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MidiTrack::set_key_enforcement_policy (KeyEnforcementPolicy kep)
|
||||||
|
{
|
||||||
|
_key_enforcement_policy = kep;
|
||||||
|
}
|
||||||
|
|
||||||
|
KeyEnforcementPolicy
|
||||||
|
MidiTrack::key_enforcment_policy () const
|
||||||
|
{
|
||||||
|
return _key_enforcement_policy;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MidiTrack::set_key (MusicalKey const & k)
|
||||||
|
{
|
||||||
|
_key = k;
|
||||||
|
|
||||||
|
PropertyChange pc;
|
||||||
|
|
||||||
|
pc.add (Properties::musical_mode);
|
||||||
|
pc.add (Properties::musical_root);
|
||||||
|
|
||||||
|
PropertyChanged (pc); /* EMIT SIGNAL */
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MidiTrack::data_recorded (boost::weak_ptr<MidiSource> src)
|
MidiTrack::data_recorded (boost::weak_ptr<MidiSource> src)
|
||||||
{
|
{
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include "ardour/mode.h"
|
#include "ardour/mode.h"
|
||||||
|
|
||||||
MusicalMode::MusicalMode (MusicalMode::Type t)
|
MusicalMode::MusicalMode (MusicalMode::Type t)
|
||||||
|
: _type (t)
|
||||||
{
|
{
|
||||||
fill (*this, t);
|
fill (*this, t);
|
||||||
}
|
}
|
||||||
|
|
|
@ -252,7 +252,7 @@ ParameterDescriptor::update_steps()
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string
|
std::string
|
||||||
ParameterDescriptor::midi_note_name (const uint8_t b, bool translate)
|
ParameterDescriptor::midi_note_name (const uint8_t b, bool translate, bool with_octave)
|
||||||
{
|
{
|
||||||
char buf[16];
|
char buf[16];
|
||||||
if (b > 127) {
|
if (b > 127) {
|
||||||
|
@ -279,9 +279,14 @@ ParameterDescriptor::midi_note_name (const uint8_t b, bool translate)
|
||||||
S_("Note|B")
|
S_("Note|B")
|
||||||
};
|
};
|
||||||
|
|
||||||
/* MIDI note 0 is in octave -1 (in scientific pitch notation) */
|
|
||||||
const int octave = b / 12 - 1;
|
|
||||||
const size_t p = b % 12;
|
const size_t p = b % 12;
|
||||||
|
|
||||||
|
/* MIDI note 0 is in octave -1 (in scientific pitch notation) */
|
||||||
|
if (!with_octave) {
|
||||||
|
return translate ? notes[p] : en_notes[p];
|
||||||
|
}
|
||||||
|
|
||||||
|
const int octave = b / 12 - 1;
|
||||||
snprintf (buf, sizeof (buf), "%s%d", translate ? notes[p] : en_notes[p], octave);
|
snprintf (buf, sizeof (buf), "%s%d", translate ? notes[p] : en_notes[p], octave);
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
|
@ -115,6 +115,7 @@ libardour_sources = [
|
||||||
'interpolation.cc',
|
'interpolation.cc',
|
||||||
'io.cc',
|
'io.cc',
|
||||||
'io_processor.cc',
|
'io_processor.cc',
|
||||||
|
'key.cc',
|
||||||
'kmeterdsp.cc',
|
'kmeterdsp.cc',
|
||||||
'ladspa_plugin.cc',
|
'ladspa_plugin.cc',
|
||||||
'latent.cc',
|
'latent.cc',
|
||||||
|
@ -206,7 +207,7 @@ libardour_sources = [
|
||||||
'route_group_member.cc',
|
'route_group_member.cc',
|
||||||
'rb_effect.cc',
|
'rb_effect.cc',
|
||||||
'rt_tasklist.cc',
|
'rt_tasklist.cc',
|
||||||
'scene_change.cc',
|
'scene_change.cc',
|
||||||
'search_paths.cc',
|
'search_paths.cc',
|
||||||
'selection.cc',
|
'selection.cc',
|
||||||
'send.cc',
|
'send.cc',
|
||||||
|
|
Loading…
Reference in New Issue