summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Gareus <robin@gareus.org>2017-09-09 18:17:42 +0200
committerRobin Gareus <robin@gareus.org>2017-09-09 18:23:34 +0200
commit9e2251a61959a006c6ac272514d61c26ebb2ecaf (patch)
tree7e4fd769dfd961c11cb4b3127715e0e178df79b9
parentba2114644d2d0f578f5aaeccbc9ce5c88ee1a17f (diff)
Prepare PatchChangeWidget for Midi-Busses (use instrument-plugin)
-rw-r--r--gtk2_ardour/patch_change_widget.cc211
-rw-r--r--gtk2_ardour/patch_change_widget.h4
2 files changed, 145 insertions, 70 deletions
diff --git a/gtk2_ardour/patch_change_widget.cc b/gtk2_ardour/patch_change_widget.cc
index 0d167eb576..5d8f77b13c 100644
--- a/gtk2_ardour/patch_change_widget.cc
+++ b/gtk2_ardour/patch_change_widget.cc
@@ -29,6 +29,7 @@
#include "ardour/instrument_info.h"
#include "ardour/midi_track.h"
+#include "ardour/plugin_insert.h"
#include "gtkmm2ext/menu_elems.h"
#include "widgets/tooltips.h"
@@ -49,6 +50,7 @@ PatchChangeWidget::PatchChangeWidget (boost::shared_ptr<ARDOUR::Route> r)
, _program_table (/*rows*/ 16, /*cols*/ 8, true)
, _channel (-1)
, _ignore_spin_btn_signals (false)
+ , _no_notifications (false)
, _info (r->instrument_info ())
, _audition_enable (_("Audition on Change"), ArdourWidgets::ArdourButton::led_default_elements)
, _audition_start_spin (*manage (new Adjustment (48, 0, 127, 1, 16)))
@@ -76,23 +78,25 @@ PatchChangeWidget::PatchChangeWidget (boost::shared_ptr<ARDOUR::Route> r)
_program_table.set_spacings (1);
pack_start (_program_table, true, true);
- if (boost::dynamic_pointer_cast<MidiTrack> (_route)) {
- box = manage (new HBox ());
- box->set_spacing (4);
- box->pack_start (_audition_enable, false, false);
- box->pack_start (*manage (new Label (_("Start Note:"))), false, false);
- box->pack_start (_audition_start_spin, false, false);
- box->pack_start (*manage (new Label (_("End Note:"))), false, false);
- box->pack_start (_audition_end_spin, false, false);
- box->pack_start (*manage (new Label (_("Velocity:"))), false, false);
- box->pack_start (_audition_velocity, false, false);
-
- Box* box2 = manage (new HBox ());
- box2->pack_start (*box, true, false);
- box2->set_border_width (2);
- pack_start (*box2, false, false);
+ if (!boost::dynamic_pointer_cast<MidiTrack> (_route)) {
+ pack_start ( *manage (new Label (_("Note: Patch Selection is volatile (only Midi-Tracks retain bank/patch selection)."))), false, false);
}
+ box = manage (new HBox ());
+ box->set_spacing (4);
+ box->pack_start (_audition_enable, false, false);
+ box->pack_start (*manage (new Label (_("Start Note:"))), false, false);
+ box->pack_start (_audition_start_spin, false, false);
+ box->pack_start (*manage (new Label (_("End Note:"))), false, false);
+ box->pack_start (_audition_end_spin, false, false);
+ box->pack_start (*manage (new Label (_("Velocity:"))), false, false);
+ box->pack_start (_audition_velocity, false, false);
+
+ Box* box2 = manage (new HBox ());
+ box2->pack_start (*box, true, false);
+ box2->set_border_width (2);
+ pack_start (*box2, false, false);
+
for (uint8_t pgm = 0; pgm < 128; ++pgm) {
_program_btn[pgm].set_text_ellipsize (Pango::ELLIPSIZE_END);
_program_btn[pgm].set_layout_ellipsize_width (PANGO_SCALE * 112 * UIConfiguration::instance ().get_ui_scale ());
@@ -110,13 +114,11 @@ PatchChangeWidget::PatchChangeWidget (boost::shared_ptr<ARDOUR::Route> r)
_channel_select.AddMenuElem (MenuElemNoMnemonic (buf, sigc::bind (sigc::mem_fun (*this, &PatchChangeWidget::select_channel), chn)));
}
- if (boost::dynamic_pointer_cast<MidiTrack> (_route)) {
- piano_keyboard_set_monophonic (_piano, TRUE);
- g_signal_connect (G_OBJECT (_piano), "note-on", G_CALLBACK (PatchChangeWidget::_note_on_event_handler), this);
- g_signal_connect (G_OBJECT (_piano), "note-off", G_CALLBACK (PatchChangeWidget::_note_off_event_handler), this);
- _pianomm->set_flags(Gtk::CAN_FOCUS);
- pack_start (*_pianomm, false, false);
- }
+ piano_keyboard_set_monophonic (_piano, TRUE);
+ g_signal_connect (G_OBJECT (_piano), "note-on", G_CALLBACK (PatchChangeWidget::_note_on_event_handler), this);
+ g_signal_connect (G_OBJECT (_piano), "note-off", G_CALLBACK (PatchChangeWidget::_note_off_event_handler), this);
+ _pianomm->set_flags(Gtk::CAN_FOCUS);
+ pack_start (*_pianomm, false, false);
_audition_start_spin.set_sensitive (false);
_audition_end_spin.set_sensitive (false);
@@ -130,6 +132,12 @@ PatchChangeWidget::PatchChangeWidget (boost::shared_ptr<ARDOUR::Route> r)
_info.Changed.connect (_info_changed_connection, invalidator (*this),
boost::bind (&PatchChangeWidget::instrument_info_changed, this), gui_context());
+ if (!boost::dynamic_pointer_cast<MidiTrack> (_route)) {
+ _route->processors_changed.connect (_route_connection, invalidator (*this),
+ boost::bind (&PatchChangeWidget::processors_changed, this), gui_context());
+ processors_changed ();
+ }
+
set_spacing (4);
show_all ();
}
@@ -179,19 +187,30 @@ PatchChangeWidget::select_channel (uint8_t chn)
_channel_select.set_text (string_compose ("%1", (int)(chn + 1)));
_channel = chn;
+ _no_notifications = false;
_ac_connections.drop_connections ();
- boost::shared_ptr<AutomationControl> bank_msb = _route->automation_control(Evoral::Parameter (MidiCCAutomation, chn, MIDI_CTL_MSB_BANK), true);
- boost::shared_ptr<AutomationControl> bank_lsb = _route->automation_control(Evoral::Parameter (MidiCCAutomation, chn, MIDI_CTL_LSB_BANK), true);
- boost::shared_ptr<AutomationControl> program = _route->automation_control(Evoral::Parameter (MidiPgmChangeAutomation, chn), true);
-
- bank_msb->Changed.connect (_ac_connections, invalidator (*this),
- boost::bind (&PatchChangeWidget::bank_changed, this), gui_context ());
- bank_lsb->Changed.connect (_ac_connections, invalidator (*this),
- boost::bind (&PatchChangeWidget::bank_changed, this), gui_context ());
- program->Changed.connect (_ac_connections, invalidator (*this),
- boost::bind (&PatchChangeWidget::program_changed, this), gui_context ());
+ if (boost::dynamic_pointer_cast<MidiTrack> (_route)) {
+ boost::shared_ptr<AutomationControl> bank_msb = _route->automation_control(Evoral::Parameter (MidiCCAutomation, chn, MIDI_CTL_MSB_BANK), true);
+ boost::shared_ptr<AutomationControl> bank_lsb = _route->automation_control(Evoral::Parameter (MidiCCAutomation, chn, MIDI_CTL_LSB_BANK), true);
+ boost::shared_ptr<AutomationControl> program = _route->automation_control(Evoral::Parameter (MidiPgmChangeAutomation, chn), true);
+
+ bank_msb->Changed.connect (_ac_connections, invalidator (*this),
+ boost::bind (&PatchChangeWidget::bank_changed, this), gui_context ());
+ bank_lsb->Changed.connect (_ac_connections, invalidator (*this),
+ boost::bind (&PatchChangeWidget::bank_changed, this), gui_context ());
+ program->Changed.connect (_ac_connections, invalidator (*this),
+ boost::bind (&PatchChangeWidget::program_changed, this), gui_context ());
+ } else if (boost::shared_ptr<PluginInsert> pi = boost::dynamic_pointer_cast<PluginInsert> (_route->the_instrument())) {
+ if (pi->plugin()->knows_bank_patch ()) {
+ pi->plugin ()->BankPatchChange.connect (_ac_connections, invalidator (*this),
+ boost::bind (&PatchChangeWidget::bankpatch_changed, this, _1), gui_context ());
+ } else {
+ _no_notifications = true;
+ // TODO add note: instrument does not report changes.
+ }
+ }
refill_banks ();
}
@@ -285,11 +304,24 @@ PatchChangeWidget::select_bank (uint32_t bank)
{
cancel_audition ();
- boost::shared_ptr<AutomationControl> bank_msb = _route->automation_control(Evoral::Parameter (MidiCCAutomation, _channel, MIDI_CTL_MSB_BANK), true);
- boost::shared_ptr<AutomationControl> bank_lsb = _route->automation_control(Evoral::Parameter (MidiCCAutomation, _channel, MIDI_CTL_LSB_BANK), true);
+ if (boost::dynamic_pointer_cast<MidiTrack> (_route)) {
+ boost::shared_ptr<AutomationControl> bank_msb = _route->automation_control(Evoral::Parameter (MidiCCAutomation, _channel, MIDI_CTL_MSB_BANK), true);
+ boost::shared_ptr<AutomationControl> bank_lsb = _route->automation_control(Evoral::Parameter (MidiCCAutomation, _channel, MIDI_CTL_LSB_BANK), true);
+
+ bank_msb->set_value (bank >> 7, PBD::Controllable::NoGroup);
+ bank_lsb->set_value (bank & 127, PBD::Controllable::NoGroup);
+ } else if (boost::shared_ptr<PluginInsert> pi = boost::dynamic_pointer_cast<PluginInsert> (_route->the_instrument())) {
+ uint8_t event[3];
+ event[0] = (MIDI_CMD_CONTROL | _channel);
+ event[1] = 0x00;
+ event[2] = bank >> 7;
+ pi->write_immediate_event (3, event);
+
+ event[1] = 0x20;
+ event[2] = bank & 127;
+ pi->write_immediate_event (3, event);
+ }
- bank_msb->set_value (bank >> 7, PBD::Controllable::NoGroup);
- bank_lsb->set_value (bank & 127, PBD::Controllable::NoGroup);
select_program (program (_channel));
}
@@ -297,9 +329,23 @@ void
PatchChangeWidget::select_program (uint8_t pgm)
{
cancel_audition ();
+ if (_no_notifications) {
+ program_changed ();
+ }
+
+ if (pgm > 127) {
+ return;
+ }
- boost::shared_ptr<AutomationControl> program = _route->automation_control(Evoral::Parameter (MidiPgmChangeAutomation, _channel), true);
- program->set_value (pgm, PBD::Controllable::NoGroup);
+ if (boost::dynamic_pointer_cast<MidiTrack> (_route)) {
+ boost::shared_ptr<AutomationControl> program = _route->automation_control(Evoral::Parameter (MidiPgmChangeAutomation, _channel), true);
+ program->set_value (pgm, PBD::Controllable::NoGroup);
+ } else if (boost::shared_ptr<PluginInsert> pi = boost::dynamic_pointer_cast<PluginInsert> (_route->the_instrument())) {
+ uint8_t event[2];
+ event[0] = (MIDI_CMD_PGM_CHANGE | _channel);
+ event[1] = pgm;
+ pi->write_immediate_event (2, event);
+ }
audition ();
}
@@ -313,6 +359,14 @@ PatchChangeWidget::bank_changed ()
}
void
+PatchChangeWidget::bankpatch_changed (uint8_t chn)
+{
+ if (chn == _channel) {
+ refill_banks ();
+ }
+}
+
+void
PatchChangeWidget::program_changed ()
{
uint8_t p = program (_channel);
@@ -327,6 +381,17 @@ PatchChangeWidget::instrument_info_changed ()
refill_banks ();
}
+void
+PatchChangeWidget::processors_changed ()
+{
+ assert (!boost::dynamic_pointer_cast<MidiTrack> (_route));
+ if (_route->the_instrument ()) {
+ set_sensitive (true);
+ } else {
+ set_sensitive (false);
+ }
+}
+
/* ***** play notes *****/
void
@@ -364,22 +429,15 @@ PatchChangeWidget::cancel_audition ()
_note_queue_connection.disconnect();
if (_audition_note_on) {
- boost::shared_ptr<MidiTrack> mt = boost::dynamic_pointer_cast<MidiTrack> (_route);
- uint8_t event[3];
-
- event[0] = (MIDI_CMD_NOTE_OFF | _channel);
- event[1] = _audition_note_num;
- event[2] = 0;
- mt->write_immediate_event (3, event);
+ note_off_event_handler (_audition_note_num);
piano_keyboard_set_note_off (_piano, _audition_note_num);
}
- _audition_note_on = false;
}
void
PatchChangeWidget::audition ()
{
- if (!boost::dynamic_pointer_cast<MidiTrack> (_route)) {
+ if (!boost::dynamic_pointer_cast<MidiTrack> (_route) && !boost::dynamic_pointer_cast<PluginInsert> (_route)) {
return;
}
if (_channel > 16) {
@@ -403,23 +461,12 @@ PatchChangeWidget::audition ()
bool
PatchChangeWidget::audition_next ()
{
- boost::shared_ptr<MidiTrack> mt = boost::dynamic_pointer_cast<MidiTrack> (_route);
- uint8_t event[3];
-
if (_audition_note_on) {
- event[0] = (MIDI_CMD_NOTE_OFF | _channel);
- event[1] = _audition_note_num;
- event[2] = 0;
- mt->write_immediate_event (3, event);
- _audition_note_on = false;
+ note_off_event_handler (_audition_note_num);
piano_keyboard_set_note_off (_piano, _audition_note_num);
return ++_audition_note_num <= _audition_end_spin.get_value_as_int() && _audition_enable.get_active ();
} else {
- event[0] = (MIDI_CMD_NOTE_ON | _channel);
- event[1] = _audition_note_num;
- event[2] = _audition_velocity.get_value_as_int ();
- mt->write_immediate_event (3, event);
- _audition_note_on = true;
+ note_on_event_handler (_audition_note_num);
piano_keyboard_set_note_on (_piano, _audition_note_num);
return true;
}
@@ -442,26 +489,34 @@ PatchChangeWidget::note_on_event_handler (int note)
{
cancel_audition ();
_pianomm->grab_focus ();
- boost::shared_ptr<MidiTrack> mt = boost::dynamic_pointer_cast<MidiTrack> (_route);
uint8_t event[3];
event[0] = (MIDI_CMD_NOTE_ON | _channel);
event[1] = note;
event[2] = _audition_velocity.get_value_as_int ();
- mt->write_immediate_event (3, event);
_audition_note_on = true;
_audition_note_num = note;
+
+ if (boost::shared_ptr<MidiTrack> mt = boost::dynamic_pointer_cast<MidiTrack> (_route)) {
+ mt->write_immediate_event (3, event);
+ } else if (boost::shared_ptr<PluginInsert> pi = boost::dynamic_pointer_cast<PluginInsert> (_route->the_instrument())) {
+ pi->write_immediate_event (3, event);
+ }
}
void
PatchChangeWidget::note_off_event_handler (int note)
{
- boost::shared_ptr<MidiTrack> mt = boost::dynamic_pointer_cast<MidiTrack> (_route);
uint8_t event[3];
event[0] = (MIDI_CMD_NOTE_OFF | _channel);
event[1] = note;
event[2] = 0;
- mt->write_immediate_event (3, event);
_audition_note_on = false;
+
+ if (boost::shared_ptr<MidiTrack> mt = boost::dynamic_pointer_cast<MidiTrack> (_route)) {
+ mt->write_immediate_event (3, event);
+ } else if (boost::shared_ptr<PluginInsert> pi = boost::dynamic_pointer_cast<PluginInsert> (_route->the_instrument())) {
+ pi->write_immediate_event (3, event);
+ }
}
/* ***** query info *****/
@@ -469,17 +524,33 @@ PatchChangeWidget::note_off_event_handler (int note)
int
PatchChangeWidget::bank (uint8_t chn) const
{
- boost::shared_ptr<AutomationControl> bank_msb = _route->automation_control(Evoral::Parameter (MidiCCAutomation, chn, MIDI_CTL_MSB_BANK), true);
- boost::shared_ptr<AutomationControl> bank_lsb = _route->automation_control(Evoral::Parameter (MidiCCAutomation, chn, MIDI_CTL_LSB_BANK), true);
-
- return ((int)bank_msb->get_value () << 7) + (int)bank_lsb->get_value();
+ if (boost::shared_ptr<MidiTrack> mt = boost::dynamic_pointer_cast<MidiTrack> (_route)) {
+ boost::shared_ptr<AutomationControl> bank_msb = _route->automation_control(Evoral::Parameter (MidiCCAutomation, chn, MIDI_CTL_MSB_BANK), true);
+ boost::shared_ptr<AutomationControl> bank_lsb = _route->automation_control(Evoral::Parameter (MidiCCAutomation, chn, MIDI_CTL_LSB_BANK), true);
+
+ return ((int)bank_msb->get_value () << 7) + (int)bank_lsb->get_value();
+ } else if (boost::shared_ptr<PluginInsert> pi = boost::dynamic_pointer_cast<PluginInsert> (_route->the_instrument())) {
+ uint32_t bankpatch = pi->plugin()->bank_patch (chn);
+ if (bankpatch != UINT32_MAX) {
+ return bankpatch >> 7;
+ }
+ }
+ return 0;
}
uint8_t
PatchChangeWidget::program (uint8_t chn) const
{
- boost::shared_ptr<AutomationControl> program = _route->automation_control(Evoral::Parameter (MidiPgmChangeAutomation, chn), true);
- return program->get_value();
+ if (boost::shared_ptr<MidiTrack> mt = boost::dynamic_pointer_cast<MidiTrack> (_route)) {
+ boost::shared_ptr<AutomationControl> program = _route->automation_control(Evoral::Parameter (MidiPgmChangeAutomation, chn), true);
+ return program->get_value();
+ } else if (boost::shared_ptr<PluginInsert> pi = boost::dynamic_pointer_cast<PluginInsert> (_route->the_instrument())) {
+ uint32_t bankpatch = pi->plugin()->bank_patch (chn);
+ if (bankpatch != UINT32_MAX) {
+ return bankpatch & 127;
+ }
+ }
+ return 255;
}
/* ***************************************************************************/
diff --git a/gtk2_ardour/patch_change_widget.h b/gtk2_ardour/patch_change_widget.h
index 81e73bda44..dcd5eaa171 100644
--- a/gtk2_ardour/patch_change_widget.h
+++ b/gtk2_ardour/patch_change_widget.h
@@ -24,6 +24,7 @@
#include <gtkmm/table.h>
#include "pbd/signals.h"
+#include "midi++/midnam_patch.h"
#include "ardour/route.h"
@@ -60,6 +61,7 @@ private:
uint8_t _channel;
bool _ignore_spin_btn_signals;
+ bool _no_notifications;
void select_channel (uint8_t);
void select_bank (uint32_t);
@@ -68,11 +70,13 @@ private:
void bank_changed ();
void program_changed ();
+ void bankpatch_changed (uint8_t);
void refill_banks ();
void refill_program_list ();
void instrument_info_changed ();
+ void processors_changed ();
PBD::ScopedConnection _info_changed_connection;
PBD::ScopedConnection _route_connection;