#include <gtkmm/messagedialog.h>
#include "pbd/error.h"
+#include "pbd/locale_guard.h"
#include "pbd/xml++.h"
#include "pbd/unwind.h"
#include "pbd/failed_constructor.h"
#include "ardour_ui.h"
#include "engine_dialog.h"
#include "gui_thread.h"
+#include "ui_config.h"
+#include "public_editor.h"
#include "utils.h"
#include "pbd/i18n.h"
+#include "splash.h"
using namespace std;
using namespace Gtk;
start_stop_button.set_sensitive (false);
start_stop_button.set_name ("generic button");
start_stop_button.set_can_focus(true);
+ start_stop_button.set_can_default(true);
+ start_stop_button.set_act_on_release (false);
update_devices_button.signal_clicked.connect (mem_fun (*this, &EngineControl::update_devices_button_clicked));
update_devices_button.set_sensitive (false);
use_buffered_io_button.set_name ("generic button");
use_buffered_io_button.set_can_focus(true);
- cancel_button = add_button (Gtk::Stock::CLOSE, Gtk::RESPONSE_CANCEL);
- ok_button = add_button (Gtk::Stock::OK, Gtk::RESPONSE_OK);
-
/* Pick up any existing audio setup configuration, if appropriate */
XMLNode* audio_setup = ARDOUR::Config->extra_xml ("AudioMIDISetup");
backend_changed ();
}
device_changed ();
- ok_button->grab_focus();
+ start_stop_button.grab_focus();
+}
+
+void
+EngineControl::on_map ()
+{
+ if (!ARDOUR_UI::instance()->session_loaded && !PublicEditor::_instance) {
+ set_type_hint (Gdk::WINDOW_TYPE_HINT_NORMAL);
+ } else if (UIConfiguration::instance().get_all_floating_windows_are_dialogs()) {
+ set_type_hint (Gdk::WINDOW_TYPE_HINT_DIALOG);
+ } else {
+ set_type_hint (Gdk::WINDOW_TYPE_HINT_UTILITY);
+ }
+ ArdourDialog::on_map ();
}
bool
return true;
}
-void
-EngineControl::on_response (int response_id)
-{
- ArdourDialog::on_response (response_id);
-
- switch (response_id) {
- case RESPONSE_OK:
- hide();
- if (!start_engine()) {
- show();
- return;
- }
-#ifdef PLATFORM_WINDOWS
-
- // But if there's no session open, this can produce
- // a long gap when nothing appears to be happening.
- // Let's show the splash image while we're waiting.
- if (!ARDOUR_COMMAND_LINE::no_splash) {
- if (ARDOUR_UI::instance()) {
- if (!ARDOUR_UI::instance()->session_loaded) {
- ARDOUR_UI::instance()->show_splash();
- }
- }
- }
-#endif
- break;
- case RESPONSE_DELETE_EVENT: {
- GdkEventButton ev;
- ev.type = GDK_BUTTON_PRESS;
- ev.button = 1;
- on_delete_event((GdkEventAny*)&ev);
- break;
- }
- case RESPONSE_CANCEL:
- if (ARDOUR_UI::instance() && ARDOUR_UI::instance()->session_loaded) {
- ARDOUR_UI::instance()->check_audioengine(*this);
- }
- // fall through
- default:
- hide();
- }
-}
-
void
EngineControl::build_notebook ()
{
{
boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
if (!backend) {
- ok_button->set_sensitive (false);
start_stop_button.set_sensitive (false);
return;
}
bool valid = true;
size_t devices_available = 0;
+ bool engine_running = ARDOUR::AudioEngine::instance()->running();
if (backend->use_separate_input_and_output_devices ()) {
devices_available += get_popdown_string_count (input_device_combo);
} else {
input_latency.set_sensitive (true);
output_latency.set_sensitive (true);
- input_channels.set_sensitive (true);
- output_channels.set_sensitive (true);
+ input_channels.set_sensitive (!engine_running);
+ output_channels.set_sensitive (!engine_running);
}
if (get_popdown_string_count (buffer_size_combo) > 0) {
- if (!ARDOUR::AudioEngine::instance()->running()) {
+ if (!engine_running) {
buffer_size_combo.set_sensitive (valid);
} else if (backend->can_change_sample_rate_when_running()) {
buffer_size_combo.set_sensitive (valid || !_have_control);
if (get_popdown_string_count (sample_rate_combo) > 0) {
bool allow_to_set_rate = false;
- if (!ARDOUR::AudioEngine::instance()->running()) {
+ if (!engine_running) {
if (!ARDOUR_UI::instance()->session_loaded) {
// engine is not running, no session loaded -> anything goes.
allow_to_set_rate = true;
}
if (get_popdown_string_count (nperiods_combo) > 0) {
- if (!ARDOUR::AudioEngine::instance()->running()) {
+ if (!engine_running) {
nperiods_combo.set_sensitive (true);
} else {
nperiods_combo.set_sensitive (false);
if (_have_control) {
start_stop_button.set_sensitive(true);
start_stop_button.show();
- if (ARDOUR::AudioEngine::instance()->running()) {
+ if (engine_running) {
start_stop_button.set_text("Stop");
update_devices_button.set_sensitive(false);
use_buffered_io_button.set_sensitive(false);
start_stop_button.hide();
}
- if (ARDOUR::AudioEngine::instance()->running() && _have_control) {
+ if (engine_running && _have_control) {
input_device_combo.set_sensitive (false);
output_device_combo.set_sensitive (false);
device_combo.set_sensitive (false);
}
}
- if (valid || !_have_control) {
- ok_button->set_sensitive (true);
- } else {
- ok_button->set_sensitive (false);
- }
+ midi_option_combo.set_sensitive (!engine_running);
}
void
// set driver & devices
State state = get_matching_state (backend_combo.get_active_text());
if (state) {
+ DEBUG_ECONTROL ("backend-changed(): found prior state for backend");
PBD::Unwinder<uint32_t> protect_ignore_changes (ignore_changes, ignore_changes + 1);
set_current_state (state);
+ } else {
+ DEBUG_ECONTROL ("backend-changed(): no prior state for backend");
}
+ } else {
+ DEBUG_ECONTROL (string_compose ("backend-changed(): _have_control=%1 ignore_changes=%2", _have_control, ignore_changes));
}
if (!ignore_changes) {
}
for (vector<uint32_t>::const_iterator x = np.begin(); x != np.end(); ++x) {
- s.push_back (nperiods_as_string (*x));
+ s.push_back (to_string (*x));
}
set_popdown_strings (nperiods_combo, s);
if (!s.empty()) {
- set_active_text_if_present (nperiods_combo, nperiods_as_string (backend->period_size())); // XXX
+ set_active_text_if_present (nperiods_combo, to_string (backend->period_size())); // XXX
}
update_sensitivity ();
EngineControl::input_device_changed ()
{
DEBUG_ECONTROL ("input_device_changed");
+
+ boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
+ if (backend && backend->match_input_output_devices_or_none ()) {
+ const std::string& dev_none = ARDOUR::AudioBackend::get_standard_device_name (ARDOUR::AudioBackend::DeviceNone);
+
+ if (get_output_device_name () != dev_none
+ && get_input_device_name () != dev_none
+ && get_input_device_name () != get_output_device_name ()) {
+ block_changed_signals ();
+ if (contains_value (output_device_combo, get_input_device_name ())) {
+ output_device_combo.set_active_text (get_input_device_name ());
+ } else {
+ assert (contains_value (output_device_combo, dev_none));
+ output_device_combo.set_active_text (dev_none);
+ }
+ unblock_changed_signals ();
+ }
+ }
device_changed ();
}
EngineControl::output_device_changed ()
{
DEBUG_ECONTROL ("output_device_changed");
+ boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
+ if (backend && backend->match_input_output_devices_or_none ()) {
+ const std::string& dev_none = ARDOUR::AudioBackend::get_standard_device_name (ARDOUR::AudioBackend::DeviceNone);
+
+ if (get_input_device_name () != dev_none
+ && get_input_device_name () != dev_none
+ && get_input_device_name () != get_output_device_name ()) {
+ block_changed_signals ();
+ if (contains_value (input_device_combo, get_output_device_name ())) {
+ input_device_combo.set_active_text (get_output_device_name ());
+ } else {
+ assert (contains_value (input_device_combo, dev_none));
+ input_device_combo.set_active_text (dev_none);
+ }
+ unblock_changed_signals ();
+ }
+ }
device_changed ();
}
string
EngineControl::bufsize_as_string (uint32_t sz)
{
- return string_compose (P_("%1 sample", "%1 samples", sz), sz);
-}
-
-string
-EngineControl::nperiods_as_string (uint32_t np)
-{
- char buf[8];
- snprintf (buf, sizeof (buf), "%u", np);
- return buf;
+ return string_compose (P_("%1 sample", "%1 samples", sz), to_string(sz));
}
-
void
EngineControl::sample_rate_changed ()
{
return false;
}
+// sort active first, then most recently used to the beginning of the list
bool
EngineControl::state_sort_cmp (const State &a, const State &b) {
if (a->active) {
return false;
}
else {
- return a->lru < b->lru;
+ return a->lru > b->lru;
}
}
}
set_active_text_if_present (buffer_size_combo, bufsize_as_string (state->buffer_size));
- set_active_text_if_present (nperiods_combo, nperiods_as_string (state->n_periods));
+ set_active_text_if_present (nperiods_combo, to_string(state->n_periods));
/* call this explicitly because we're ignoring changes to
the controls at this point.
*/
XMLNode* node = new XMLNode ("State");
- node->add_property ("backend", (*i)->backend);
- node->add_property ("driver", (*i)->driver);
- node->add_property ("device", (*i)->device);
- node->add_property ("input-device", (*i)->input_device);
- node->add_property ("output-device", (*i)->output_device);
- node->add_property ("sample-rate", (*i)->sample_rate);
- node->add_property ("buffer-size", (*i)->buffer_size);
- node->add_property ("n-periods", (*i)->n_periods);
- node->add_property ("input-latency", (*i)->input_latency);
- node->add_property ("output-latency", (*i)->output_latency);
- node->add_property ("input-channels", (*i)->input_channels);
- node->add_property ("output-channels", (*i)->output_channels);
- node->add_property ("active", (*i)->active ? "yes" : "no");
- node->add_property ("use-buffered-io", (*i)->use_buffered_io ? "yes" : "no");
- node->add_property ("midi-option", (*i)->midi_option);
- node->add_property ("lru", (*i)->active ? time (NULL) : (*i)->lru);
+ node->set_property ("backend", (*i)->backend);
+ node->set_property ("driver", (*i)->driver);
+ node->set_property ("device", (*i)->device);
+ node->set_property ("input-device", (*i)->input_device);
+ node->set_property ("output-device", (*i)->output_device);
+ node->set_property ("sample-rate", (*i)->sample_rate);
+ node->set_property ("buffer-size", (*i)->buffer_size);
+ node->set_property ("n-periods", (*i)->n_periods);
+ node->set_property ("input-latency", (*i)->input_latency);
+ node->set_property ("output-latency", (*i)->output_latency);
+ node->set_property ("input-channels", (*i)->input_channels);
+ node->set_property ("output-channels", (*i)->output_channels);
+ node->set_property ("active", (*i)->active);
+ node->set_property ("use-buffered-io", (*i)->use_buffered_io);
+ node->set_property ("midi-option", (*i)->midi_option);
+ int32_t lru_val = (*i)->active ? time (NULL) : (*i)->lru;
+ node->set_property ("lru", lru_val );
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_device_stuff->set_property (X_("name"), (*p)->name);
+ midi_device_stuff->set_property (X_("enabled"), (*p)->enabled);
+ midi_device_stuff->set_property (X_("input-latency"), (*p)->input_latency);
+ midi_device_stuff->set_property (X_("output-latency"), (*p)->output_latency);
midi_devices->add_child_nocopy (*midi_device_stuff);
}
node->add_child_nocopy (*midi_devices);
XMLNodeConstIterator citer, cciter;
XMLNode const * child;
XMLNode const * grandchild;
- XMLProperty const * prop = NULL;
if (root.name() != "AudioMIDISetup") {
return false;
continue;
}
- if ((prop = grandchild->property ("backend")) == 0) {
- continue;
- }
- state->backend = prop->value ();
-
- if ((prop = grandchild->property ("driver")) == 0) {
- continue;
- }
- state->driver = prop->value ();
-
- if ((prop = grandchild->property ("device")) == 0) {
- continue;
- }
- state->device = prop->value ();
-
- if ((prop = grandchild->property ("input-device")) == 0) {
+ if (!grandchild->get_property ("backend", state->backend)) {
continue;
}
- state->input_device = prop->value ();
- if ((prop = grandchild->property ("output-device")) == 0) {
+ // If any of the required properties are not found in the state node
+ // then continue/skip to the next engine state
+ if (!grandchild->get_property ("driver", state->driver) ||
+ !grandchild->get_property ("device", state->device) ||
+ !grandchild->get_property ("input-device", state->input_device) ||
+ !grandchild->get_property ("output-device", state->output_device) ||
+ !grandchild->get_property ("sample-rate", state->sample_rate) ||
+ !grandchild->get_property ("buffer-size", state->buffer_size) ||
+ !grandchild->get_property ("input-latency", state->input_latency) ||
+ !grandchild->get_property ("output-latency", state->output_latency) ||
+ !grandchild->get_property ("input-channels", state->input_channels) ||
+ !grandchild->get_property ("output-channels", state->output_channels) ||
+ !grandchild->get_property ("active", state->active) ||
+ !grandchild->get_property ("use-buffered-io", state->use_buffered_io) ||
+ !grandchild->get_property ("midi-option", state->midi_option)) {
continue;
}
- state->output_device = prop->value ();
- if ((prop = grandchild->property ("sample-rate")) == 0) {
- continue;
- }
- state->sample_rate = atof (prop->value ());
-
- if ((prop = grandchild->property ("buffer-size")) == 0) {
- continue;
- }
- state->buffer_size = atoi (prop->value ());
-
- if ((prop = grandchild->property ("n-periods")) == 0) {
+ if (!grandchild->get_property ("n-periods", state->n_periods)) {
// optional (new value in 4.5)
state->n_periods = 0;
- } else {
- state->n_periods = atoi (prop->value ());
- }
-
- if ((prop = grandchild->property ("input-latency")) == 0) {
- continue;
- }
- state->input_latency = atoi (prop->value ());
-
- if ((prop = grandchild->property ("output-latency")) == 0) {
- continue;
}
- state->output_latency = atoi (prop->value ());
-
- if ((prop = grandchild->property ("input-channels")) == 0) {
- continue;
- }
- state->input_channels = atoi (prop->value ());
-
- if ((prop = grandchild->property ("output-channels")) == 0) {
- continue;
- }
- state->output_channels = atoi (prop->value ());
-
- if ((prop = grandchild->property ("active")) == 0) {
- continue;
- }
- state->active = string_is_affirmative (prop->value ());
-
- if ((prop = grandchild->property ("use-buffered-io")) == 0) {
- continue;
- }
- state->use_buffered_io = string_is_affirmative (prop->value ());
-
- if ((prop = grandchild->property ("midi-option")) == 0) {
- continue;
- }
- state->midi_option = prop->value ();
state->midi_devices.clear();
XMLNode* midinode;
if ((midinode = ARDOUR::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
- ) {
+ std::string name;
+ bool enabled;
+ uint32_t input_latency;
+ uint32_t output_latency;
+
+ if (!(*n)->get_property (X_("name"), name) ||
+ !(*n)->get_property (X_("enabled"), enabled) ||
+ !(*n)->get_property (X_("input-latency"), input_latency) ||
+ !(*n)->get_property (X_("output-latency"), output_latency)) {
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 ())
- ));
+ MidiDeviceSettings ptr (
+ new MidiDeviceSetting (name, enabled, input_latency, output_latency));
state->midi_devices.push_back (ptr);
}
}
- if ((prop = grandchild->property ("lru"))) {
- state->lru = atoi (prop->value ());
+ int32_t lru_val;
+ if (grandchild->get_property ("lru", lru_val)) {
+ state->lru = lru_val;
}
-#if 1
- /* remove accumulated duplicates (due to bug in ealier version)
- * this can be removed again before release
- */
- for (StateList::iterator i = states.begin(); i != states.end();) {
- if ((*i)->backend == state->backend &&
- (*i)->driver == state->driver &&
- (*i)->device == state->device) {
- i = states.erase(i);
- } else {
- ++i;
- }
- }
-#endif
-
states.push_back (state);
}
}
/* now see if there was an active state and switch the setup to it */
- // purge states of backend that are not available in this built
+ /* purge states of backend that are not available in this built */
vector<const ARDOUR::AudioBackendInfo*> backends = ARDOUR::AudioEngine::instance()->available_backends();
vector<std::string> backend_names;
states.sort (state_sort_cmp);
+ /* purge old states referring to the same backend */
+ const time_t now = time (NULL);
+ for (vector<std::string>::const_iterator bi = backend_names.begin(); bi != backend_names.end(); ++bi) {
+ bool first = true;
+ for (StateList::iterator i = states.begin(); i != states.end();) {
+ if ((*i)->backend != *bi) {
+ ++i; continue;
+ }
+ // keep at latest one for every audio-system
+ if (first) {
+ first = false;
+ ++i; continue;
+ }
+ // also keep states used in the last 90 days.
+ if ((now - (*i)->lru) < 86400 * 90) {
+ ++i; continue;
+ }
+ assert (!(*i)->active);
+ i = states.erase(i);
+ }
+ }
+
for (StateList::const_iterator i = states.begin(); i != states.end(); ++i) {
if ((*i)->active) {
sample_rate_combo.set_active_text (rate_as_string (state->sample_rate));
}
set_active_text_if_present (buffer_size_combo, bufsize_as_string (state->buffer_size));
- set_active_text_if_present (nperiods_combo, nperiods_as_string (state->n_periods));
+ set_active_text_if_present (nperiods_combo, to_string (state->n_periods));
input_latency.set_value (state->input_latency);
output_latency.set_value (state->output_latency);
midi_option_combo.set_active_text (state->midi_option);
if (ARDOUR::AudioEngine::instance()->running()) {
ARDOUR::AudioEngine::instance()->stop ();
} else {
+ if (!ARDOUR_UI::instance()->session_loaded) {
+ pop_splash ();
+ hide ();
+ ARDOUR::GUIIdle ();
+ }
start_engine ();
+ if (!ARDOUR_UI::instance()->session_loaded) {
+ ArdourDialog::on_response (RESPONSE_OK);
+ }
}
}
EngineControl::on_switch_page (GtkNotebookPage*, guint page_num)
{
if (page_num == 0) {
- cancel_button->set_sensitive (true);
_measure_midi.reset();
update_sensitivity ();
- } else {
- cancel_button->set_sensitive (false);
- ok_button->set_sensitive (false);
}
if (page_num == midi_tab) {
void
EngineControl::latency_back_button_clicked ()
{
- ARDOUR::AudioEngine::instance()->stop(true);
+ ARDOUR::AudioEngine::instance()->stop_latency_detection ();
notebook.set_current_page(0);
}
void
EngineControl::use_latency_button_clicked ()
{
+ boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
if (_measure_midi) {
ARDOUR::MIDIDM* mididm = ARDOUR::AudioEngine::instance()->mididm ();
if (!mididm) {
uint32_t one_way = max ((ARDOUR::framecnt_t) 0, extra / 2);
_measure_midi->input_latency = one_way;
_measure_midi->output_latency = one_way;
+ if (backend->can_change_systemic_latency_when_running ()) {
+ backend->set_systemic_midi_input_latency (_measure_midi->name, one_way);
+ backend->set_systemic_midi_output_latency (_measure_midi->name, one_way);
+ }
notebook.set_current_page (midi_tab);
} else {
MTDM* mtdm = ARDOUR::AudioEngine::instance()->mtdm ();
input_latency_adjustment.set_value (one_way);
output_latency_adjustment.set_value (one_way);
+ if (backend->can_change_systemic_latency_when_running ()) {
+ backend->set_systemic_input_latency (one_way);
+ backend->set_systemic_output_latency (one_way);
+ }
/* back to settings page */
notebook.set_current_page (0);
sample_rate_combo.set_active_text (rate_as_string (backend->sample_rate()));
if (backend->can_set_period_size ()) {
- set_active_text_if_present (nperiods_combo, nperiods_as_string (backend->period_size()));
+ set_active_text_if_present (nperiods_combo, to_string (backend->period_size()));
}
connect_disconnect_button.set_label (string_compose (_("Disconnect from %1"), backend->name()));
if (ARDOUR::AudioEngine::instance()->running()) {
stop_engine ();
} else {
+ if (!ARDOUR_UI::instance()->session_loaded) {
+ pop_splash ();
+ hide ();
+ ARDOUR::GUIIdle ();
+ }
start_engine ();
+ if (!ARDOUR_UI::instance()->session_loaded) {
+ ArdourDialog::on_response (RESPONSE_OK);
+ }
}
}