add GUI for midi-device settings (and properly indent the code)

This commit is contained in:
Robin Gareus 2014-06-13 12:01:55 +02:00
parent da912f7ed4
commit 2e88935bbf
2 changed files with 1460 additions and 1281 deletions

View File

@ -59,7 +59,7 @@ using namespace Gtkmm2ext;
using namespace PBD;
using namespace Glib;
static const unsigned int midi_tab = -1; /* not currently in use */
static const unsigned int midi_tab = 2;
static const unsigned int latency_tab = 1; /* zero-based, page zero is the main setup page */
static const char* results_markup = X_("<span foreground=\"red\" style=\"italic\" size=\"larger\">%1</span>");
@ -78,19 +78,18 @@ EngineControl::EngineControl ()
, ports_adjustment (128, 8, 1024, 1, 16)
, ports_spinner (ports_adjustment)
, control_app_button (_("Device Control Panel"))
, midi_devices_button (_("Midi Device Setup"))
, lm_measure_label (_("Measure"))
, lm_use_button (_("Use results"))
, lm_back_button (_("Back to settings ... (ignore results)"))
, lm_button_audio (_("Calibrate Audio"))
, lm_button_midi (_("Calibrate Midi"))
, lm_table (12, 3)
, have_lm_results (false)
, lm_running (false)
, midi_refresh_button (_("Refresh list"))
, midi_back_button (_("Back to settings"))
, ignore_changes (0)
, _desired_sample_rate (0)
, started_at_least_once (false)
, _measure_midi(false)
{
using namespace Notebook_Helpers;
vector<string> strings;
@ -100,8 +99,7 @@ EngineControl::EngineControl ()
set_name (X_("AudioMIDISetup"));
/* the backend combo is the one thing that is ALWAYS visible
*/
/* the backend combo is the one thing that is ALWAYS visible */
vector<const ARDOUR::AudioBackendInfo*> backends = ARDOUR::AudioEngine::instance()->available_backends();
@ -131,8 +129,6 @@ EngineControl::EngineControl ()
basic_hbox.pack_start (basic_packer, false, false);
/* latency tab */
/* latency measurement tab */
lm_title.set_markup (string_compose ("<span size=\"large\" weight=\"bold\">%1</span>", _("Latency Measurement Tool")));
@ -185,7 +181,7 @@ EngineControl::EngineControl ()
lm_measure_button.add (lm_measure_label);
lm_measure_button.signal_clicked().connect (sigc::mem_fun (*this, &EngineControl::latency_button_clicked));
lm_use_button.signal_clicked().connect (sigc::mem_fun (*this, &EngineControl::use_latency_button_clicked));
lm_back_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (notebook, &Gtk::Notebook::set_current_page), 0));
lm_back_button_signal = lm_back_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (notebook, &Gtk::Notebook::set_current_page), 0));
lm_use_button.set_sensitive (false);
@ -233,11 +229,13 @@ EngineControl::EngineControl ()
lm_vbox.set_border_width (12);
lm_vbox.pack_start (lm_table, false, false);
midi_back_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (notebook, &Gtk::Notebook::set_current_page), 0));
/* pack it all up */
notebook.pages().push_back (TabElem (basic_vbox, _("Audio")));
// notebook.pages().push_back (TabElem (midi_vbox, _("MIDI")));
notebook.pages().push_back (TabElem (lm_vbox, _("Latency")));
notebook.pages().push_back (TabElem (midi_vbox, _("MIDI")));
notebook.set_border_width (12);
notebook.set_show_tabs (false);
@ -257,6 +255,10 @@ EngineControl::EngineControl ()
input_channels.signal_output().connect (sigc::bind (sigc::ptr_fun (&EngineControl::print_channel_count), &input_channels));
output_channels.signal_output().connect (sigc::bind (sigc::ptr_fun (&EngineControl::print_channel_count), &output_channels));
midi_devices_button.signal_clicked.connect (mem_fun (*this, &EngineControl::configure_midi_devices));
midi_devices_button.set_sensitive (false);
midi_devices_button.set_name ("generic button");
control_app_button.signal_clicked().connect (mem_fun (*this, &EngineControl::control_app_button_clicked));
manage_control_app_sensitivity ();
@ -307,7 +309,8 @@ EngineControl::EngineControl ()
push_state_to_backend (true);
hide ();
break;
case RESPONSE_DELETE_EVENT: {
case RESPONSE_DELETE_EVENT:
{
GdkEventButton ev;
ev.type = GDK_BUTTON_PRESS;
ev.button = 1;
@ -341,9 +344,6 @@ EngineControl::EngineControl ()
lm_button_audio.signal_clicked.connect (sigc::mem_fun (*this, &EngineControl::calibrate_audio_latency));
lm_button_audio.set_name ("generic button");
lm_button_midi.signal_clicked.connect (sigc::mem_fun (*this, &EngineControl::calibrate_midi_latency));
lm_button_midi.set_name ("generic button");
if (_have_control) {
build_full_control_notebook ();
} else {
@ -458,7 +458,7 @@ EngineControl::EngineControl ()
label = manage (left_aligned_label (_("MIDI System")));
basic_packer.attach (*label, 0, 1, row, row + 1, xopt, (AttachOptions) 0);
basic_packer.attach (midi_option_combo, 1, 2, row, row + 1, SHRINK, (AttachOptions) 0);
basic_packer.attach (lm_button_midi, 3, 4, row, row+1, xopt, xopt);
basic_packer.attach (midi_devices_button, 3, 4, row, row+1, xopt, xopt);
row++;
}
@ -569,10 +569,8 @@ EngineControl::EngineControl ()
}
midi_vbox.pack_start (midi_device_table, true, true);
midi_vbox.pack_start (midi_refresh_button, false, false);
midi_vbox.pack_start (midi_back_button, false, false);
midi_vbox.show_all ();
midi_refresh_button.signal_clicked().connect (sigc::mem_fun (*this, &EngineControl::refresh_midi_display));
}
void
@ -580,56 +578,91 @@ EngineControl::EngineControl ()
{
}
void
EngineControl::midi_latency_adjustment_changed (Gtk::Adjustment *a, MidiDeviceSettings device, bool for_input) {
if (for_input) {
device->input_latency = a->get_value();
} else {
device->output_latency = a->get_value();
}
}
bool
EngineControl::midi_device_enabled_toggled (GdkEventButton* ev, ArdourButton *b, MidiDeviceSettings device) {
if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS) {
return true;
}
b->set_active (!b->get_active());
device->enabled = b->get_active();
refresh_midi_display();
return true;
}
void
EngineControl::refresh_midi_display ()
{
boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
assert (backend);
vector<string> midi_inputs;
vector<string> midi_outputs;
int row = 0;
AttachOptions xopt = AttachOptions (FILL|EXPAND);
Gtk::Label* l;
Gtkmm2ext::container_clear (midi_device_table);
backend->get_physical_inputs (ARDOUR::DataType::MIDI, midi_inputs);
backend->get_physical_outputs (ARDOUR::DataType::MIDI, midi_outputs);
midi_device_table.set_spacings (6);
midi_device_table.set_homogeneous (true);
midi_device_table.resize (midi_inputs.size() + midi_outputs.size() + 3, 1);
l = manage (new Label);
l->set_markup (string_compose ("<span size=\"large\" weight=\"bold\">%1</span>", _("MIDI Inputs")));
midi_device_table.attach (*l, 0, 1, row, row + 1, xopt, AttachOptions (0));
l->set_alignment (0, 0.5);
l->set_markup (string_compose ("<span size=\"large\" weight=\"bold\">%1</span>", _("MIDI Devices")));
midi_device_table.attach (*l, 0, 4, row, row + 1, xopt, AttachOptions (0));
l->set_alignment (0.5, 0.5);
row++;
l->show ();
for (vector<string>::iterator p = midi_inputs.begin(); p != midi_inputs.end(); ++p) {
l = manage (new Label ((*p).substr ((*p).find_last_of (':') + 1)));
l->set_alignment (0, 0.5);
midi_device_table.attach (*l, 0, 1, row, row + 1, xopt, AttachOptions (0));
l->show ();
l = manage (new Label (_("Device"))); l->show (); l->set_alignment (0.5, 0.5);
midi_device_table.attach (*l, 0, 1, row, row + 2, xopt, AttachOptions (0));
l = manage (new Label (_("Hardware Latencies"))); l->show (); l->set_alignment (0.5, 0.5);
midi_device_table.attach (*l, 1, 3, row, row + 1, xopt, AttachOptions (0));
row++;
}
row++; // extra row of spacing
l = manage (new Label);
l->set_markup (string_compose ("<span size=\"large\" weight=\"bold\">%1</span>", _("MIDI Outputs")));
midi_device_table.attach (*l, 0, 1, row, row + 1, xopt, AttachOptions (0));
l->set_alignment (0, 0.5);
l = manage (new Label (_("Input"))); l->show (); l->set_alignment (0.5, 0.5);
midi_device_table.attach (*l, 1, 2, row, row + 1, xopt, AttachOptions (0));
l = manage (new Label (_("Output"))); l->show (); l->set_alignment (0.5, 0.5);
midi_device_table.attach (*l, 2, 3, row, row + 1, xopt, AttachOptions (0));
row++;
l->show ();
for (vector<string>::iterator p = midi_outputs.begin(); p != midi_outputs.end(); ++p) {
l = manage (new Label ((*p).substr ((*p).find_last_of (':') + 1)));
l->set_alignment (0, 0.5);
midi_device_table.attach (*l, 0, 1, row, row + 1, xopt, AttachOptions (0));
l->show ();
for (vector<MidiDeviceSettings>::const_iterator p = _midi_devices.begin(); p != _midi_devices.end(); ++p) {
ArdourButton *m;
Gtk::Button* b;
Gtk::Adjustment *a;
Gtk::SpinButton *s;
bool enabled = (*p)->enabled;
m = manage (new ArdourButton ((*p)->name, ArdourButton::led_default_elements));
m->set_name ("midi device");
m->add_events (Gdk::BUTTON_RELEASE_MASK);
m->set_active (enabled);
m->signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &EngineControl::midi_device_enabled_toggled), m, *p));
midi_device_table.attach (*m, 0, 1, row, row + 1, xopt, AttachOptions (0)); m->show ();
a = manage (new Gtk::Adjustment (0, 0, 99999, 1));
s = manage (new Gtk::SpinButton (*a));
a->set_value ((*p)->input_latency);
s->signal_value_changed().connect (sigc::bind (sigc::mem_fun (*this, &EngineControl::midi_latency_adjustment_changed), a, *p, true));
s->set_sensitive (_can_set_midi_latencies && enabled);
midi_device_table.attach (*s, 1, 2, row, row + 1, xopt, AttachOptions (0)); s->show ();
a = manage (new Gtk::Adjustment (0, 0, 99999, 1));
s = manage (new Gtk::SpinButton (*a));
a->set_value ((*p)->output_latency);
s->signal_value_changed().connect (sigc::bind (sigc::mem_fun (*this, &EngineControl::midi_latency_adjustment_changed), a, *p, false));
s->set_sensitive (_can_set_midi_latencies && enabled);
midi_device_table.attach (*s, 2, 3, row, row + 1, xopt, AttachOptions (0)); s->show ();
b = manage (new Button (_("Calibrate")));
b->signal_clicked().connect (sigc::bind (sigc::mem_fun (*this, &EngineControl::calibrate_midi_latency), *p));
b->set_sensitive (_can_set_midi_latencies && enabled);
midi_device_table.attach (*b, 3, 4, row, row + 1, xopt, AttachOptions (0)); b->show ();
row++;
}
}
@ -654,6 +687,7 @@ EngineControl::EngineControl ()
build_notebook ();
setup_midi_tab_for_backend ();
_midi_devices.clear();
if (backend->requires_driver_selection()) {
vector<string> drivers = backend->enumerate_drivers();
@ -691,6 +725,9 @@ EngineControl::EngineControl ()
midi_option_combo.set_sensitive (false);
}
}
midi_option_changed();
started_at_least_once = false;
if (!ignore_changes) {
@ -944,6 +981,41 @@ EngineControl::EngineControl ()
void
EngineControl::midi_option_changed ()
{
boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
assert (backend);
backend->set_midi_option (get_midi_option());
vector<ARDOUR::AudioBackend::DeviceStatus> midi_devices = backend->enumerate_midi_devices();
//_midi_devices.clear(); // TODO merge with state-saved settings..
_can_set_midi_latencies = backend->can_set_systemic_midi_latencies();
std::vector<MidiDeviceSettings> new_devices;
for (vector<ARDOUR::AudioBackend::DeviceStatus>::const_iterator i = midi_devices.begin(); i != midi_devices.end(); ++i) {
MidiDeviceSettings mds = find_midi_device (i->name);
if (i->available && !mds) {
uint32_t input_latency = 0;
uint32_t output_latency = 0;
if (_can_set_midi_latencies) {
input_latency = backend->systemic_midi_input_latency (i->name);
output_latency = backend->systemic_midi_output_latency (i->name);
}
bool enabled = backend->midi_device_enabled (i->name);
MidiDeviceSettings ptr (new MidiDeviceSetting (i->name, enabled, input_latency, output_latency));
new_devices.push_back (ptr);
} else if (i->available) {
new_devices.push_back (mds);
}
}
_midi_devices = new_devices;
if (_midi_devices.empty()) {
midi_devices_button.set_sensitive (false);
} else {
midi_devices_button.set_sensitive (true);
}
if (!ignore_changes) {
save_state ();
}
@ -958,7 +1030,8 @@ EngineControl::EngineControl ()
}
EngineControl::State*
EngineControl::get_matching_state (const string& backend,
EngineControl::get_matching_state (
const string& backend,
const string& driver,
const string& device)
{
@ -1026,6 +1099,7 @@ EngineControl::EngineControl ()
state.input_channels = get_input_channels ();
state.output_channels = get_output_channels ();
state.midi_option = get_midi_option ();
state.midi_devices = _midi_devices;
}
void
@ -1053,6 +1127,7 @@ EngineControl::EngineControl ()
if (!state->midi_option.empty()) {
midi_option_combo.set_active_text (state->midi_option);
_midi_devices = state->midi_devices;
}
}
}
@ -1082,6 +1157,17 @@ EngineControl::EngineControl ()
node->add_property ("active", (*i).active ? "yes" : "no");
node->add_property ("midi-option", (*i).midi_option);
XMLNode* midi_devices = new XMLNode ("MIDIDevices");
for (std::vector<MidiDeviceSettings>::const_iterator p = (*i).midi_devices.begin(); p != (*i).midi_devices.end(); ++p) {
XMLNode* midi_device_stuff = new XMLNode ("MIDIDevice");
midi_device_stuff->add_property (X_("name"), (*p)->name);
midi_device_stuff->add_property (X_("enabled"), (*p)->enabled);
midi_device_stuff->add_property (X_("input-latency"), (*p)->input_latency);
midi_device_stuff->add_property (X_("output-latency"), (*p)->output_latency);
midi_devices->add_child_nocopy (*midi_device_stuff);
}
node->add_child_nocopy (*midi_devices);
state_nodes->add_child_nocopy (*node);
}
@ -1182,6 +1268,29 @@ EngineControl::EngineControl ()
}
state.midi_option = prop->value ();
state.midi_devices.clear();
XMLNode* midinode;
if ((midinode = find_named_node (*grandchild, "MIDIDevices")) != 0) {
const XMLNodeList mnc = midinode->children();
for (XMLNodeList::const_iterator n = mnc.begin(); n != mnc.end(); ++n) {
if ((*n)->property (X_("name")) == 0
|| (*n)->property (X_("enabled")) == 0
|| (*n)->property (X_("input-latency")) == 0
|| (*n)->property (X_("output-latency")) == 0
) {
continue;
}
MidiDeviceSettings ptr (new MidiDeviceSetting(
(*n)->property (X_("name"))->value (),
string_is_affirmative ((*n)->property (X_("enabled"))->value ()),
atoi ((*n)->property (X_("input-latency"))->value ()),
atoi ((*n)->property (X_("output-latency"))->value ())
));
state.midi_devices.push_back (ptr);
}
}
states.push_back (state);
}
}
@ -1428,6 +1537,24 @@ EngineControl::EngineControl ()
backend->set_midi_option (get_midi_option());
}
if (1 /* TODO */) {
for (vector<MidiDeviceSettings>::const_iterator p = _midi_devices.begin(); p != _midi_devices.end(); ++p) {
if (_measure_midi) {
if (*p == _measure_midi) {
backend->set_midi_device_enabled ((*p)->name, true);
} else {
backend->set_midi_device_enabled ((*p)->name, false);
}
continue;
}
backend->set_midi_device_enabled ((*p)->name, (*p)->enabled);
if (backend->can_set_systemic_midi_latencies()) {
backend->set_systemic_midi_input_latency ((*p)->name, (*p)->input_latency);
backend->set_systemic_midi_output_latency ((*p)->name, (*p)->output_latency);
}
}
}
if (start || (was_running && restart_required)) {
if (ARDOUR_UI::instance()->reconnect_to_engine()) {
return -1;
@ -1470,8 +1597,7 @@ EngineControl::EngineControl ()
}
/* schedule a redisplay of MIDI ports */
Glib::signal_timeout().connect (sigc::bind_return (sigc::mem_fun (*this, &EngineControl::refresh_midi_display), false), 1000);
//Glib::signal_timeout().connect (sigc::bind_return (sigc::mem_fun (*this, &EngineControl::refresh_midi_display), false), 1000);
}
@ -1594,6 +1720,7 @@ EngineControl::EngineControl ()
cancel_button->set_sensitive (true);
ok_button->set_sensitive (true);
apply_button->set_sensitive (true);
_measure_midi.reset();
} else {
cancel_button->set_sensitive (false);
ok_button->set_sensitive (false);
@ -1608,8 +1735,12 @@ EngineControl::EngineControl ()
if (page_num == latency_tab) {
/* latency tab */
if (!ARDOUR::AudioEngine::instance()->running()) {
if (ARDOUR::AudioEngine::instance()->running()) {
// TODO - mark as 'stopped for latency
ARDOUR_UI::instance()->disconnect_from_engine ();
}
{
PBD::Unwinder<uint32_t> protect_ignore_changes (ignore_changes, ignore_changes + 1);
/* save any existing latency values */
@ -1619,6 +1750,9 @@ EngineControl::EngineControl ()
/* reset to zero so that our new test instance
will be clean of any existing latency measures.
NB. this should really be done by the backend
when stated for latency measurement.
*/
input_latency.set_value (0);
@ -1632,7 +1766,7 @@ EngineControl::EngineControl ()
output_latency.set_value (ol);
}
// This should be done in push_state_to_backend()
if (ARDOUR::AudioEngine::instance()->prepare_for_latency_measurement()) {
disable_latency_tab ();
}
@ -1752,7 +1886,7 @@ EngineControl::check_midi_latency_measurement ()
if (solid) {
end_latency_detection ();
lm_use_button.set_sensitive (false); // XXX TODO
lm_use_button.set_sensitive (true);
have_lm_results = true;
}
@ -1767,7 +1901,7 @@ EngineControl::start_latency_detection ()
ARDOUR::AudioEngine::instance()->set_latency_input_port (lm_input_channel_combo.get_active_text());
ARDOUR::AudioEngine::instance()->set_latency_output_port (lm_output_channel_combo.get_active_text());
if (ARDOUR::AudioEngine::instance()->start_latency_detection (_measure_midi) == 0) {
if (ARDOUR::AudioEngine::instance()->start_latency_detection (_measure_midi ? true : false) == 0) {
lm_results.set_markup (string_compose (results_markup, _("Detecting ...")));
if (_measure_midi) {
latency_timeout = Glib::signal_timeout().connect (mem_fun (*this, &EngineControl::check_midi_latency_measurement), 100);
@ -1781,6 +1915,13 @@ EngineControl::start_latency_detection ()
lm_output_channel_combo.set_sensitive (false);
lm_running = true;
}
lm_back_button_signal.disconnect();
if (_measure_midi) {
lm_back_button_signal = lm_back_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (notebook, &Gtk::Notebook::set_current_page), midi_tab));
} else {
lm_back_button_signal = lm_back_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (notebook, &Gtk::Notebook::set_current_page), 0));
}
}
void
@ -1813,16 +1954,16 @@ void
EngineControl::use_latency_button_clicked ()
{
if (_measure_midi) {
#if 0 // TODO
ARDOUR::MIDIDM* mididm = ARDOUR::AudioEngine::instance()->mididm ();
if (!mididm) {
return;
}
ARDOUR::framecnt_t frames_total = mididm->latency();
ARDOUR::framecnt_t extra = frames_total - ARDOUR::AudioEngine::instance()->latency_signal_delay();
uint32_t one_way = extra / 2;
// TODO assign to all or one specific device
#endif
uint32_t one_way = max ((ARDOUR::framecnt_t) 0, extra / 2);
_measure_midi->input_latency = one_way;
_measure_midi->output_latency = one_way;
notebook.set_current_page (midi_tab);
} else {
MTDM* mtdm = ARDOUR::AudioEngine::instance()->mtdm ();
@ -1830,18 +1971,17 @@ EngineControl::use_latency_button_clicked ()
return;
}
uint32_t frames_total = mtdm->del();
uint32_t extra = frames_total - ARDOUR::AudioEngine::instance()->latency_signal_delay();
uint32_t one_way = extra/2;
double one_way = rint ((mtdm->del() - ARDOUR::AudioEngine::instance()->latency_signal_delay()) / 2.0);
one_way = std::max (0., one_way);
input_latency_adjustment.set_value (one_way);
output_latency_adjustment.set_value (one_way);
}
/* back to settings page */
notebook.set_current_page (0);
}
}
bool
EngineControl::on_delete_event (GdkEventAny* ev)
@ -1896,14 +2036,19 @@ EngineControl::connect_disconnect_click()
void
EngineControl::calibrate_audio_latency ()
{
_measure_midi = false;
_measure_midi.reset();
notebook.set_current_page (latency_tab);
}
void
EngineControl::calibrate_midi_latency ()
EngineControl::calibrate_midi_latency (MidiDeviceSettings s)
{
_measure_midi = true;
_measure_midi = s;
notebook.set_current_page (latency_tab);
}
void
EngineControl::configure_midi_devices ()
{
notebook.set_current_page (midi_tab);
}

View File

@ -79,6 +79,7 @@ class EngineControl : public ArdourDialog, public PBD::ScopedConnectionList {
Gtk::Label have_control_text;
Gtk::Button control_app_button;
ArdourButton midi_devices_button;
Gtk::Button connect_disconnect_button;
@ -91,7 +92,6 @@ class EngineControl : public ArdourDialog, public PBD::ScopedConnectionList {
Gtk::Button lm_use_button;
Gtk::Button lm_back_button;
ArdourButton lm_button_audio;
ArdourButton lm_button_midi;
Gtk::Label lm_title;
Gtk::Label lm_results;
Gtk::Table lm_table;
@ -106,7 +106,7 @@ class EngineControl : public ArdourDialog, public PBD::ScopedConnectionList {
/* MIDI Tab */
Gtk::VBox midi_vbox;
Gtk::Button midi_refresh_button;
Gtk::Button midi_back_button;
Gtk::Table midi_device_table;
/* MIDI ... JACK */
@ -145,6 +145,35 @@ class EngineControl : public ArdourDialog, public PBD::ScopedConnectionList {
void list_devices ();
void show_buffer_duration ();
void configure_midi_devices ();
struct MidiDeviceSetting {
std::string name;
bool enabled;
uint32_t input_latency;
uint32_t output_latency;
MidiDeviceSetting (std::string n, bool en = true, uint32_t inl = 0, uint32_t oul = 0)
: name (n)
, enabled (en)
, input_latency (inl)
, output_latency (oul)
{}
};
typedef boost::shared_ptr<MidiDeviceSetting> MidiDeviceSettings;
bool _can_set_midi_latencies;
std::vector<MidiDeviceSettings> _midi_devices;
MidiDeviceSettings find_midi_device(std::string devicename) const {
for (std::vector<MidiDeviceSettings>::const_iterator p = _midi_devices.begin(); p != _midi_devices.end(); ++p) {
if ((*p)->name == devicename) {
return *p;
}
}
return MidiDeviceSettings();
}
struct State {
std::string backend;
std::string driver;
@ -157,6 +186,7 @@ class EngineControl : public ArdourDialog, public PBD::ScopedConnectionList {
uint32_t output_channels;
bool active;
std::string midi_option;
std::vector<MidiDeviceSettings> midi_devices;
State()
: input_latency (0)
@ -215,8 +245,12 @@ class EngineControl : public ArdourDialog, public PBD::ScopedConnectionList {
void connect_disconnect_click ();
void calibrate_audio_latency ();
void calibrate_midi_latency ();
bool _measure_midi;
void calibrate_midi_latency (MidiDeviceSettings);
MidiDeviceSettings _measure_midi;
void midi_latency_adjustment_changed(Gtk::Adjustment *, MidiDeviceSettings, bool);
bool midi_device_enabled_toggled(GdkEventButton* ev, ArdourButton *, MidiDeviceSettings);
sigc::connection lm_back_button_signal;
};
#endif /* __gtk2_ardour_engine_dialog_h__ */