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.
This commit is contained in:
parent
e1064701a5
commit
16a100703b
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user