summaryrefslogtreecommitdiff
path: root/gtk2_ardour
diff options
context:
space:
mode:
authorRobin Gareus <robin@gareus.org>2017-09-08 19:42:24 +0200
committerRobin Gareus <robin@gareus.org>2017-09-08 23:35:00 +0200
commitaa11cb96b3c9b35d40a5fbefc41aa75ccf957f80 (patch)
tree52b7613d3b58416a3d905274523fe6d03bb4351e /gtk2_ardour
parentc3e8cdb418008d05a927b442eb9291a1cd6f7111 (diff)
Experimental GenericPluginUI MIDI patch select.
Diffstat (limited to 'gtk2_ardour')
-rw-r--r--gtk2_ardour/generic_pluginui.cc155
-rw-r--r--gtk2_ardour/plugin_ui.h8
2 files changed, 162 insertions, 1 deletions
diff --git a/gtk2_ardour/generic_pluginui.cc b/gtk2_ardour/generic_pluginui.cc
index ffb4a2cc92..dbb4d7f756 100644
--- a/gtk2_ardour/generic_pluginui.cc
+++ b/gtk2_ardour/generic_pluginui.cc
@@ -34,11 +34,19 @@
#include "pbd/xml++.h"
#include "pbd/failed_constructor.h"
+#include "evoral/midi_events.h"
+#include "evoral/PatchChange.hpp"
+
+#include "midi++/midnam_patch.h"
+
+#include "ardour/midi_patch_manager.h"
+#include "ardour/midi_track.h"
#include "ardour/plugin.h"
#include "ardour/plugin_insert.h"
#include "ardour/session.h"
#include "ardour/value_as_string.h"
+#include "gtkmm2ext/menu_elems.h"
#include "gtkmm2ext/utils.h"
#include "gtkmm2ext/doi.h"
@@ -152,6 +160,13 @@ GenericPluginUI::GenericPluginUI (boost::shared_ptr<PluginInsert> pi, bool scrol
prefheight = 0;
build ();
+ if (insert->plugin()->has_midnam() && insert->plugin()->knows_bank_patch()) {
+ /* right now PC are sent via MIDI Track controls only */
+ if (dynamic_cast<MidiTrack*> (insert->owner())) {
+ build_midi_table ();
+ }
+ }
+
if (is_scrollable) {
scroller.set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
scroller.set_name ("PluginEditor");
@@ -400,10 +415,11 @@ GenericPluginUI::automatic_layout (const std::vector<ControlUI*>& control_uis)
button_table->set_homogeneous (false);
button_table->set_row_spacings (2);
button_table->set_col_spacings (2);
+ button_table->set_border_width (5);
+
output_table->set_homogeneous (true);
output_table->set_row_spacings (2);
output_table->set_col_spacings (2);
- button_table->set_border_width (5);
output_table->set_border_width (5);
@@ -596,6 +612,143 @@ GenericPluginUI::custom_layout (const std::vector<ControlUI*>& control_uis)
}
}
+void
+GenericPluginUI::build_midi_table ()
+{
+ Gtk::Table* pgm_table = manage (new Gtk::Table (8, 2));
+
+ pgm_table->set_homogeneous (true);
+ pgm_table->set_row_spacings (2);
+ pgm_table->set_col_spacings (2);
+ pgm_table->set_border_width (5);
+
+ Frame* frame = manage (new Frame);
+ frame->set_name ("BaseFrame");
+ frame->set_label (_("MIDI Progams (sent to track)"));
+ //frame->set_label (_("MIDI Progams (volatile)"));
+ frame->add (*pgm_table);
+ hpacker.pack_start (*frame, true, true);
+
+ for (uint8_t chn = 0; chn < 16; ++chn) {
+ int col = chn / 8;
+ int row = chn % 8;
+ ArdourDropdown* cui = manage (new ArdourWidgets::ArdourDropdown ());
+ // TODO set size_request
+ cui->set_text_ellipsize (Pango::ELLIPSIZE_END);
+ cui->set_layout_ellipsize_width (PANGO_SCALE * 112 * UIConfiguration::instance ().get_ui_scale ());
+ midi_pgmsel.push_back (cui);
+ pgm_table->attach (*cui, col, col + 1, row, row+1, FILL|EXPAND, FILL);
+ }
+
+ midi_refill_patches ();
+
+ insert->plugin()->BankPatchChange.connect (
+ midi_connections, invalidator (*this),
+ boost::bind (&GenericPluginUI::midi_bank_patch_change, this, _1),
+ gui_context());
+
+ /* Note: possible race with MidiTimeAxisView::update_patch_selector()
+ * which uses this signal to update/re-register the midnam (also in gui context).
+ * MTAV does register before us, so the midnam should already be updated when
+ * we're notified.
+ */
+ insert->plugin()->UpdateMidnam.connect (
+ midi_connections, invalidator (*this),
+ boost::bind (&GenericPluginUI::midi_refill_patches, this),
+ gui_context());
+}
+
+void
+GenericPluginUI::midi_refill_patches ()
+{
+ assert (midi_pgmsel.size() == 16);
+
+ pgm_names.clear ();
+
+ const std::string model = insert->plugin ()->midnam_model ();
+ std::string mode;
+ const std::list<std::string> device_modes = MIDI::Name::MidiPatchManager::instance().custom_device_mode_names_by_model (model);
+ if (device_modes.size() > 0) {
+ mode = device_modes.front();
+ }
+
+ for (uint8_t chn = 0; chn < 16; ++chn) {
+ midi_pgmsel[chn]->clear_items ();
+ boost::shared_ptr<MIDI::Name::ChannelNameSet> cns =
+ MIDI::Name::MidiPatchManager::instance().find_channel_name_set (model, mode, chn);
+
+ if (cns) {
+ using namespace Menu_Helpers;
+ using namespace Gtkmm2ext;
+
+ for (MIDI::Name::ChannelNameSet::PatchBanks::const_iterator i = cns->patch_banks().begin(); i != cns->patch_banks().end(); ++i) {
+ const MIDI::Name::PatchNameList& patches = (*i)->patch_name_list ();
+ for (MIDI::Name::PatchNameList::const_iterator j = patches.begin(); j != patches.end(); ++j) {
+ const std::string pgm = (*j)->name ();
+ MIDI::Name::PatchPrimaryKey const& key = (*j)->patch_primary_key ();
+ assert ((*i)->number () == key.bank());
+ const uint32_t bp = (key.bank() << 7) | key.program();
+ midi_pgmsel[chn]->AddMenuElem (MenuElemNoMnemonic (pgm, sigc::bind (sigc::mem_fun (*this, &GenericPluginUI::midi_bank_patch_select), chn, bp)));
+ pgm_names[bp] = pgm;
+ }
+ }
+ }
+
+ midi_bank_patch_change (chn);
+ }
+}
+
+void
+GenericPluginUI::midi_bank_patch_change (uint8_t chn)
+{
+ assert (chn < 16 && midi_pgmsel.size() == 16);
+ uint32_t bankpgm = insert->plugin()->bank_patch (chn);
+ if (bankpgm == UINT32_MAX) {
+ midi_pgmsel[chn]->set_text (_("--Unset--"));
+ } else {
+ int bank = bankpgm >> 7;
+ int pgm = bankpgm & 127;
+ if (pgm_names.find (bankpgm) != pgm_names.end ()) {
+ midi_pgmsel[chn]->set_text (pgm_names[bankpgm]);
+ } else {
+ midi_pgmsel[chn]->set_text (string_compose ("Bank %1,%2 Pgm %3",
+ (bank >> 7) + 1, (bank & 127) + 1, pgm +1));
+ }
+ }
+}
+
+void
+GenericPluginUI::midi_bank_patch_select (uint8_t chn, uint32_t bankpgm)
+{
+ int bank = bankpgm >> 7;
+ int pgm = bankpgm & 127;
+ if (1) {
+ /* send to track */
+ MidiTrack* mt = dynamic_cast<MidiTrack*> (insert->owner());
+ if (!mt) {
+ return;
+ }
+
+ boost::shared_ptr<AutomationControl> bank_msb = mt->automation_control(Evoral::Parameter (MidiCCAutomation, chn, MIDI_CTL_MSB_BANK), true);
+ boost::shared_ptr<AutomationControl> bank_lsb = mt->automation_control(Evoral::Parameter (MidiCCAutomation, chn, MIDI_CTL_LSB_BANK), true);
+ boost::shared_ptr<AutomationControl> program = mt->automation_control(Evoral::Parameter (MidiPgmChangeAutomation, chn), true);
+
+ bank_msb->set_value (bank >> 7, PBD::Controllable::NoGroup);
+ bank_lsb->set_value (bank & 127, PBD::Controllable::NoGroup);
+ program->set_value (pgm, PBD::Controllable::NoGroup);
+
+ } else {
+#if 0 // TODO inject directly to plugin..
+ const int cnt = insert->get_count();
+ for (int i=0; i < cnt; i++ ) {
+ boost::shared_ptr<LV2Plugin> lv2i = boost::dynamic_pointer_cast<LV2Plugin> (insert->plugin(i));
+ //lv2i->write_from_ui(port_index, format, buffer_size, (const uint8_t*)buffer);
+
+ }
+#endif
+ }
+}
+
GenericPluginUI::ControlUI::ControlUI (const Evoral::Parameter& p)
: param(p)
, automate_button (X_("")) // force creation of a label
diff --git a/gtk2_ardour/plugin_ui.h b/gtk2_ardour/plugin_ui.h
index ed1c722605..d685e86bdc 100644
--- a/gtk2_ardour/plugin_ui.h
+++ b/gtk2_ardour/plugin_ui.h
@@ -303,6 +303,14 @@ private:
void scroller_size_request (Gtk::Requisition*);
Gtk::ScrolledWindow scroller;
+
+ void build_midi_table ();
+ void midi_refill_patches ();
+ void midi_bank_patch_change (uint8_t chn);
+ void midi_bank_patch_select (uint8_t chn, uint32_t bankpgm);
+ std::vector<ArdourWidgets::ArdourDropdown*> midi_pgmsel;
+ PBD::ScopedConnectionList midi_connections;
+ std::map<uint32_t, std::string> pgm_names;
};
class PluginUIWindow : public ArdourWindow