summaryrefslogtreecommitdiff
path: root/libs/surfaces/generic_midi
diff options
context:
space:
mode:
authorBen Loftis <ben@harrisonconsoles.com>2015-12-02 18:31:43 -0600
committerBen Loftis <ben@harrisonconsoles.com>2015-12-02 19:18:22 -0600
commit16a100703b28d2c5937804ff2e33bd44c2267b05 (patch)
tree834596aea36bd59424446ff573db01aeddea4de7 /libs/surfaces/generic_midi
parente1064701a5c3c8ccd941f6260f36e673ef00c9e2 (diff)
GenericMidi: Partially working IO selectors.
2 remaining problems: * IO selectors are not updated if you change the connection outside the dialog. * occasional crash on the next startup, after a connection is made from the menu.
Diffstat (limited to 'libs/surfaces/generic_midi')
-rw-r--r--libs/surfaces/generic_midi/generic_midi_control_protocol.h7
-rw-r--r--libs/surfaces/generic_midi/gmcp_gui.cc186
2 files changed, 190 insertions, 3 deletions
diff --git a/libs/surfaces/generic_midi/generic_midi_control_protocol.h b/libs/surfaces/generic_midi/generic_midi_control_protocol.h
index f09c8e4883..9d51efc97d 100644
--- a/libs/surfaces/generic_midi/generic_midi_control_protocol.h
+++ b/libs/surfaces/generic_midi/generic_midi_control_protocol.h
@@ -24,6 +24,7 @@
#include <glibmm/threads.h>
#include "ardour/types.h"
+#include "ardour/port.h"
#include "control_protocol/control_protocol.h"
@@ -53,8 +54,9 @@ class GenericMidiControlProtocol : public ARDOUR::ControlProtocol {
int set_active (bool yn);
static bool probe() { return true; }
- MIDI::Port* input_port () const { return _input_port; }
- MIDI::Port* output_port () const { return _output_port; }
+ ARDOUR::Port* input_port () const { return ((ARDOUR::Port*) _input_port); }
+ ARDOUR::Port* output_port () const { return ((ARDOUR::Port*) _output_port); }
+
void set_feedback_interval (ARDOUR::microseconds_t);
int set_feedback (bool yn);
@@ -100,6 +102,7 @@ class GenericMidiControlProtocol : public ARDOUR::ControlProtocol {
return _threshold;
}
+ PBD::Signal0<void> ConnectionChange;
private:
MIDI::Port* _input_port;
MIDI::Port* _output_port;
diff --git a/libs/surfaces/generic_midi/gmcp_gui.cc b/libs/surfaces/generic_midi/gmcp_gui.cc
index 710b61be8e..427ed1d327 100644
--- a/libs/surfaces/generic_midi/gmcp_gui.cc
+++ b/libs/surfaces/generic_midi/gmcp_gui.cc
@@ -27,8 +27,16 @@
#include <gtkmm/adjustment.h>
#include <gtkmm/spinbutton.h>
#include <gtkmm/table.h>
+#include <gtkmm/liststore.h>
+
+#include "pbd/unwind.h"
+
+#include "ardour/audioengine.h"
+#include "ardour/port.h"
+#include "ardour/midi_port.h"
#include "gtkmm2ext/gtk_ui.h"
+#include "gtkmm2ext/gui_thread.h"
#include "gtkmm2ext/utils.h"
#include "generic_midi_control_protocol.h"
@@ -50,10 +58,32 @@ private:
Gtk::Adjustment threshold_adjustment;
Gtk::SpinButton threshold_spinner;
+ Gtk::ComboBox input_combo;
+ Gtk::ComboBox output_combo;
+
void binding_changed ();
void bank_changed ();
void motorised_changed ();
void threshold_changed ();
+
+ void update_port_combos ();
+ PBD::ScopedConnection connection_change_connection;
+ void connection_handler ();
+
+ struct MidiPortColumns : public Gtk::TreeModel::ColumnRecord {
+ MidiPortColumns() {
+ add (short_name);
+ add (full_name);
+ }
+ Gtk::TreeModelColumn<std::string> short_name;
+ Gtk::TreeModelColumn<std::string> full_name;
+ };
+
+ MidiPortColumns midi_port_columns;
+ bool ignore_active_change;
+
+ Glib::RefPtr<Gtk::ListStore> build_midi_port_list (std::vector<std::string> const & ports, bool for_input);
+ void active_port_changed (Gtk::ComboBox*,bool for_input);
};
using namespace PBD;
@@ -129,7 +159,29 @@ GMCPGUI::GMCPGUI (GenericMidiControlProtocol& p)
int n = 0;
- Label* label = manage (new Label (_("MIDI Bindings:")));
+ // MIDI input and output selectors
+ input_combo.pack_start (midi_port_columns.short_name);
+ output_combo.pack_start (midi_port_columns.short_name);
+
+ input_combo.signal_changed().connect (sigc::bind (sigc::mem_fun (*this, &GMCPGUI::active_port_changed), &input_combo, true));
+ output_combo.signal_changed().connect (sigc::bind (sigc::mem_fun (*this, &GMCPGUI::active_port_changed), &output_combo, false));
+
+ Label* label = manage (new Gtk::Label);
+ label->set_markup (string_compose ("<span weight=\"bold\">%1</span>", _("Incoming MIDI on:")));
+ label->set_alignment (1.0, 0.5);
+ table->attach (*label, 0, 1, n, n+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
+ table->attach (input_combo, 1, 2, n, n+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 0);
+ n++;
+
+ label = manage (new Gtk::Label);
+ label->set_markup (string_compose ("<span weight=\"bold\">%1</span>", _("Outgoing MIDI on:")));
+ label->set_alignment (1.0, 0.5);
+ table->attach (*label, 0, 1, n, n+1, AttachOptions(FILL|EXPAND), AttachOptions(0));
+ table->attach (output_combo, 1, 2, n, n+1, AttachOptions(FILL|EXPAND), AttachOptions(0), 0, 0);
+ n++;
+
+ //MIDI binding file selector...
+ label = manage (new Label (_("MIDI Bindings:")));
label->set_alignment (0, 0.5);
table->attach (*label, 0, 1, n, n + 1);
table->attach (map_combo, 1, 2, n, n + 1);
@@ -173,6 +225,14 @@ GMCPGUI::GMCPGUI (GenericMidiControlProtocol& p)
pack_start (*table, false, false);
binding_changed ();
+
+ /* update the port connection combos */
+
+ update_port_combos ();
+
+ /* catch future changes to connection state */
+
+ cp.ConnectionChange.connect (connection_change_connection, invalidator (*this), boost::bind (&GMCPGUI::connection_handler, this), gui_context());
}
GMCPGUI::~GMCPGUI ()
@@ -216,3 +276,127 @@ GMCPGUI::threshold_changed ()
{
cp.set_threshold (threshold_adjustment.get_value());
}
+
+void
+GMCPGUI::connection_handler ()
+{
+ /* ignore all changes to combobox active strings here, because we're
+ updating them to match a new ("external") reality - we were called
+ because port connections have changed.
+ */
+
+ PBD::Unwinder<bool> ici (ignore_active_change, true);
+
+ update_port_combos ();
+}
+
+void
+GMCPGUI::update_port_combos ()
+{
+ vector<string> midi_inputs;
+ vector<string> midi_outputs;
+
+ ARDOUR::AudioEngine::instance()->get_ports ("", ARDOUR::DataType::MIDI, ARDOUR::PortFlags (ARDOUR::IsOutput|ARDOUR::IsTerminal), midi_inputs);
+ ARDOUR::AudioEngine::instance()->get_ports ("", ARDOUR::DataType::MIDI, ARDOUR::PortFlags (ARDOUR::IsInput|ARDOUR::IsTerminal), midi_outputs);
+
+ Glib::RefPtr<Gtk::ListStore> input = build_midi_port_list (midi_inputs, true);
+ Glib::RefPtr<Gtk::ListStore> output = build_midi_port_list (midi_outputs, false);
+ bool input_found = false;
+ bool output_found = false;
+ int n;
+
+ input_combo.set_model (input);
+ output_combo.set_model (output);
+
+ Gtk::TreeModel::Children children = input->children();
+ Gtk::TreeModel::Children::iterator i;
+ i = children.begin();
+ ++i; /* skip "Disconnected" */
+
+
+ for (n = 1; i != children.end(); ++i, ++n) {
+ string port_name = (*i)[midi_port_columns.full_name];
+ if (cp.input_port()->connected_to (port_name)) {
+ input_combo.set_active (n);
+ input_found = true;
+ break;
+ }
+ }
+
+ if (!input_found) {
+ input_combo.set_active (0); /* disconnected */
+ }
+
+ children = output->children();
+ i = children.begin();
+ ++i; /* skip "Disconnected" */
+
+ for (n = 1; i != children.end(); ++i, ++n) {
+ string port_name = (*i)[midi_port_columns.full_name];
+ if (cp.output_port()->connected_to (port_name)) {
+ output_combo.set_active (n);
+ output_found = true;
+ break;
+ }
+ }
+
+ if (!output_found) {
+ output_combo.set_active (0); /* disconnected */
+ }
+}
+
+Glib::RefPtr<Gtk::ListStore>
+GMCPGUI::build_midi_port_list (vector<string> const & ports, bool for_input)
+{
+ Glib::RefPtr<Gtk::ListStore> store = ListStore::create (midi_port_columns);
+ TreeModel::Row row;
+
+ row = *store->append ();
+ row[midi_port_columns.full_name] = string();
+ row[midi_port_columns.short_name] = _("Disconnected");
+
+ for (vector<string>::const_iterator p = ports.begin(); p != ports.end(); ++p) {
+ row = *store->append ();
+ row[midi_port_columns.full_name] = *p;
+ std::string pn = ARDOUR::AudioEngine::instance()->get_pretty_name_by_name (*p);
+ if (pn.empty ()) {
+ pn = (*p).substr ((*p).find (':') + 1);
+ }
+ row[midi_port_columns.short_name] = pn;
+ }
+
+ return store;
+}
+
+void
+GMCPGUI::active_port_changed (Gtk::ComboBox* combo, bool for_input)
+{
+ if (ignore_active_change) {
+ return;
+ }
+
+ TreeModel::iterator active = combo->get_active ();
+ string new_port = (*active)[midi_port_columns.full_name];
+
+ if (new_port.empty()) {
+ if (for_input) {
+ cp.input_port()->disconnect_all ();
+ } else {
+ cp.output_port()->disconnect_all ();
+ }
+
+ return;
+ }
+
+ if (for_input) {
+ if (!cp.input_port()->connected_to (new_port)) {
+ cp.input_port()->disconnect_all ();
+ cp.input_port()->connect (new_port);
+ }
+ } else {
+ if (!cp.output_port()->connected_to (new_port)) {
+ cp.output_port()->disconnect_all ();
+ cp.output_port()->connect (new_port);
+ }
+ }
+}