2 Copyright (C) 2014 Waves Audio Ltd.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include "ardour/engine_state_controller.h"
22 #include "ardour/audioengine.h"
23 #include "ardour/session.h"
24 #include "ardour/rc_configuration.h"
25 #include "ardour/data_type.h"
27 #include "pbd/pthread_utils.h"
28 #include "pbd/error.h"
32 using namespace ARDOUR;
37 struct DevicePredicate
39 DevicePredicate(const std::string& device_name)
40 : _device_name(device_name)
43 bool operator()(const AudioBackend::DeviceStatus& rhs)
45 return _device_name == rhs.name;
49 std::string _device_name;
53 EngineStateController*
54 EngineStateController::instance()
56 static EngineStateController instance;
61 EngineStateController::EngineStateController()
63 , _last_used_real_device("")
66 AudioEngine::instance ()->Running.connect_same_thread (running_connection, boost::bind (&EngineStateController::_on_engine_running, this) );
67 AudioEngine::instance ()->Stopped.connect_same_thread (stopped_connection, boost::bind (&EngineStateController::_on_engine_stopped, this) );
68 AudioEngine::instance ()->Halted.connect_same_thread (stopped_connection, boost::bind (&EngineStateController::_on_engine_stopped, this) );
70 /* Subscribe for udpates from AudioEngine */
71 AudioEngine::instance ()->PortRegisteredOrUnregistered.connect_same_thread (update_connections, boost::bind (&EngineStateController::_on_ports_registration_update, this) );
72 AudioEngine::instance()->SampleRateChanged.connect_same_thread (update_connections, boost::bind (&EngineStateController::_on_sample_rate_change, this, _1) );
73 AudioEngine::instance()->BufferSizeChanged.connect_same_thread (update_connections, boost::bind (&EngineStateController::_on_buffer_size_change, this, _1) );
74 AudioEngine::instance()->DeviceListChanged.connect_same_thread (update_connections, boost::bind (&EngineStateController::_on_device_list_change, this) );
75 AudioEngine::instance()->DeviceError.connect_same_thread (update_connections, boost::bind (&EngineStateController::_on_device_error, this) );
77 /* Global configuration parameters update */
78 Config->ParameterChanged.connect_same_thread (update_connections, boost::bind (&EngineStateController::_on_parameter_changed, this, _1) );
80 _deserialize_and_load_engine_states();
81 _deserialize_and_load_midi_port_states();
82 _do_initial_engine_setup();
84 // now push the sate to the backend
85 push_current_state_to_backend(false);
89 EngineStateController::~EngineStateController()
95 EngineStateController::set_session(Session* session)
98 _session->SessionLoaded.connect_same_thread (session_connections, boost::bind (&EngineStateController::_on_session_loaded, this) );
103 EngineStateController::remove_session ()
105 session_connections.drop_connections ();
111 EngineStateController::serialize_audio_midi_settings()
114 XMLNode* root = new XMLNode ("AudioMidiSettings");
116 _serialize_engine_states(root);
117 _serialize_midi_port_states(root);
124 EngineStateController::save_audio_midi_settings()
126 Config->add_extra_xml (serialize_audio_midi_settings() );
127 Config->save_state ();
132 EngineStateController::_deserialize_and_load_engine_states()
134 XMLNode* audio_midi_settings_root = ARDOUR::Config->extra_xml ("AudioMidiSettings");
136 if (!audio_midi_settings_root) {
140 XMLNode* engine_states = audio_midi_settings_root->child("EngineStates");
142 if (!engine_states) {
146 XMLNodeList state_nodes_list = engine_states->children();
147 XMLNodeConstIterator state_node_iter = state_nodes_list.begin();
149 for (; state_node_iter != state_nodes_list.end(); ++state_node_iter) {
151 XMLNode* state_node = *state_node_iter;
152 StatePtr engine_state(new State);
153 XMLProperty* prop = NULL;
155 if ((prop = state_node->property ("backend-name")) == 0) {
158 engine_state->backend_name = prop->value ();
160 if ((prop = state_node->property ("device-name")) == 0) {
163 engine_state->device_name = prop->value ();
165 if ((prop = state_node->property ("sample-rate")) == 0) {
168 engine_state->sample_rate = atoi (prop->value ());
170 if ((prop = state_node->property ("buffer-size")) == 0) {
173 engine_state->buffer_size = atoi (prop->value ());
175 if ((prop = state_node->property ("active")) == 0) {
178 engine_state->active = string_is_affirmative (prop->value ());
180 XMLNodeList state_children_list = state_node->children();
181 XMLNodeConstIterator state_child_iter = state_children_list.begin();
183 for (; state_child_iter != state_children_list.end(); ++state_child_iter) {
184 XMLNode* state_child = *state_child_iter;
186 if (state_child->name() == "InputConfiguration") {
188 XMLNodeList input_states_nodes = state_child->children();
189 XMLNodeConstIterator input_state_node_iter = input_states_nodes.begin();
190 PortStateList& input_states = engine_state->input_channel_states;
192 for (; input_state_node_iter != input_states_nodes.end(); ++input_state_node_iter) {
194 XMLNode* input_state_node = *input_state_node_iter;
196 if (input_state_node->name() != "input") {
199 PortState input_state (input_state_node->name() );
201 if ((prop = input_state_node->property ("name")) == 0) {
204 input_state.name = prop->value();
206 if ((prop = input_state_node->property ("active")) == 0) {
209 input_state.active = string_is_affirmative (prop->value ());
211 input_states.push_back(input_state);
214 } else if (state_child->name() == "MultiOutConfiguration") {
216 XMLNodeList multi_out_state_nodes = state_child->children();
217 XMLNodeConstIterator multi_out_state_node_iter = multi_out_state_nodes.begin();
218 PortStateList& multi_out_states = engine_state->multi_out_channel_states;
220 for (; multi_out_state_node_iter != multi_out_state_nodes.end(); ++multi_out_state_node_iter) {
222 XMLNode* multi_out_state_node = *multi_out_state_node_iter;
224 if (multi_out_state_node->name() != "output") {
227 PortState multi_out_state (multi_out_state_node->name() );
229 if ((prop = multi_out_state_node->property ("name")) == 0) {
232 multi_out_state.name = prop->value();
234 if ((prop = multi_out_state_node->property ("active")) == 0) {
237 multi_out_state.active = string_is_affirmative (prop->value ());
239 multi_out_states.push_back(multi_out_state);
241 } else if (state_child->name() == "StereoOutConfiguration") {
243 XMLNodeList stereo_out_state_nodes = state_child->children();
244 XMLNodeConstIterator stereo_out_state_node_iter = stereo_out_state_nodes.begin();
245 PortStateList& stereo_out_states = engine_state->stereo_out_channel_states;
247 for (; stereo_out_state_node_iter != stereo_out_state_nodes.end(); ++stereo_out_state_node_iter) {
249 XMLNode* stereo_out_state_node = *stereo_out_state_node_iter;
251 if (stereo_out_state_node->name() != "output") {
254 PortState stereo_out_state (stereo_out_state_node->name() );
256 if ((prop = stereo_out_state_node->property ("name")) == 0) {
259 stereo_out_state.name = prop->value();
261 if ((prop = stereo_out_state_node->property ("active")) == 0) {
264 stereo_out_state.active = string_is_affirmative (prop->value ());
266 stereo_out_states.push_back(stereo_out_state);
271 _states.push_back (engine_state);
277 EngineStateController::_deserialize_and_load_midi_port_states()
279 XMLNode* audio_midi_settings_root = ARDOUR::Config->extra_xml ("AudioMidiSettings");
281 if (!audio_midi_settings_root) {
285 XMLNode* midi_states = audio_midi_settings_root->child("MidiStates");
291 XMLNodeList state_nodes_list = midi_states->children();
292 XMLNodeConstIterator state_node_iter = state_nodes_list.begin();
293 for (; state_node_iter != state_nodes_list.end(); ++state_node_iter) {
295 XMLNode* state_node = *state_node_iter;
296 if (state_node->name() == "MidiInputs") {
298 XMLNodeList input_state_nodes = state_node->children();
299 XMLNodeConstIterator input_state_node_iter = input_state_nodes.begin();
300 _midi_inputs.clear();
302 for (; input_state_node_iter != input_state_nodes.end(); ++input_state_node_iter) {
304 XMLNode* input_state_node = *input_state_node_iter;
305 XMLProperty* prop = NULL;
307 if (input_state_node->name() != "input") {
310 MidiPortState input_state (input_state_node->name() );
312 if ((prop = input_state_node->property ("name")) == 0) {
315 input_state.name = prop->value();
317 if ((prop = input_state_node->property ("active")) == 0) {
320 input_state.active = string_is_affirmative (prop->value ());
322 if ((prop = input_state_node->property ("scene-connected")) == 0) {
325 input_state.scene_connected = string_is_affirmative (prop->value ());
327 if ((prop = input_state_node->property ("mtc-in")) == 0) {
330 input_state.mtc_in = string_is_affirmative (prop->value ());
332 _midi_inputs.push_back(input_state);
335 } else if (state_node->name() == "MidiOutputs") {
337 XMLNodeList output_state_nodes = state_node->children();
338 XMLNodeConstIterator output_state_node_iter = output_state_nodes.begin();
339 _midi_outputs.clear();
341 for (; output_state_node_iter != output_state_nodes.end(); ++output_state_node_iter) {
343 XMLNode* output_state_node = *output_state_node_iter;
344 XMLProperty* prop = NULL;
346 if (output_state_node->name() != "output") {
349 MidiPortState output_state (output_state_node->name() );
351 if ((prop = output_state_node->property ("name")) == 0) {
354 output_state.name = prop->value();
356 if ((prop = output_state_node->property ("active")) == 0) {
359 output_state.active = string_is_affirmative (prop->value ());
361 if ((prop = output_state_node->property ("scene-connected")) == 0) {
364 output_state.scene_connected = string_is_affirmative (prop->value ());
366 if ((prop = output_state_node->property ("mtc-in")) == 0) {
369 output_state.mtc_in = string_is_affirmative (prop->value ());
371 _midi_outputs.push_back(output_state);
379 EngineStateController::_serialize_engine_states(XMLNode* audio_midi_settings_node)
381 if (!audio_midi_settings_node) {
385 // clean up state data first
386 audio_midi_settings_node->remove_nodes_and_delete("EngineStates" );
388 XMLNode* engine_states = new XMLNode("EngineStates" );
390 StateList::const_iterator state_iter = _states.begin();
391 for (; state_iter != _states.end(); ++state_iter) {
393 StatePtr state_ptr = *state_iter;
395 // create new node for the state
396 XMLNode* state_node = new XMLNode("State");
398 state_node->add_property ("backend-name", state_ptr->backend_name);
399 state_node->add_property ("device-name", state_ptr->device_name);
400 state_node->add_property ("sample-rate", state_ptr->sample_rate);
401 state_node->add_property ("buffer-size", state_ptr->buffer_size);
402 state_node->add_property ("active", state_ptr->active ? "yes" : "no");
404 // store channel states:
406 XMLNode* input_config_node = new XMLNode("InputConfiguration");
407 PortStateList& input_channels = state_ptr->input_channel_states;
408 PortStateList::const_iterator input_state_iter = input_channels.begin();
409 for (; input_state_iter != input_channels.end(); ++input_state_iter) {
410 XMLNode* input_state_node = new XMLNode("input");
411 input_state_node->add_property ("name", input_state_iter->name);
412 input_state_node->add_property ("active", input_state_iter->active ? "yes" : "no");
413 input_config_node->add_child_nocopy(*input_state_node);
415 state_node->add_child_nocopy(*input_config_node);
418 XMLNode* multi_out_config_node = new XMLNode("MultiOutConfiguration");
419 PortStateList& multi_out_channels = state_ptr->multi_out_channel_states;
420 PortStateList::const_iterator multi_out_state_iter = multi_out_channels.begin();
421 for (; multi_out_state_iter != multi_out_channels.end(); ++multi_out_state_iter) {
422 XMLNode* multi_out_state_node = new XMLNode("output" );
423 multi_out_state_node->add_property ("name", multi_out_state_iter->name);
424 multi_out_state_node->add_property ("active", multi_out_state_iter->active ? "yes" : "no");
425 multi_out_config_node->add_child_nocopy(*multi_out_state_node);
427 state_node->add_child_nocopy(*multi_out_config_node);
429 // stereo out outputs
430 XMLNode* stereo_out_config_node = new XMLNode("StereoOutConfiguration");
431 PortStateList& stereo_out_channels = state_ptr->stereo_out_channel_states;
432 PortStateList::const_iterator stereo_out_state_iter = stereo_out_channels.begin();
433 for (; stereo_out_state_iter != stereo_out_channels.end(); ++stereo_out_state_iter) {
434 XMLNode* stereo_out_state_node = new XMLNode("output" );
435 stereo_out_state_node->add_property ("name", stereo_out_state_iter->name);
436 stereo_out_state_node->add_property ("active", stereo_out_state_iter->active ? "yes" : "no");
437 stereo_out_config_node->add_child_nocopy(*stereo_out_state_node);
439 state_node->add_child_nocopy(*stereo_out_config_node);
441 engine_states->add_child_nocopy(*state_node);
444 audio_midi_settings_node->add_child_nocopy(*engine_states);
449 EngineStateController::_serialize_midi_port_states(XMLNode* audio_midi_settings_node)
451 if (!audio_midi_settings_node) {
455 // clean up state data first
456 audio_midi_settings_node->remove_nodes_and_delete("MidiStates" );
458 XMLNode* midi_states_node = new XMLNode("MidiStates" );
460 XMLNode* midi_input_states_node = new XMLNode("MidiInputs" );
461 MidiPortStateList::const_iterator midi_input_state_iter = _midi_inputs.begin();
462 for (; midi_input_state_iter != _midi_inputs.end(); ++midi_input_state_iter) {
463 XMLNode* midi_input_node = new XMLNode("input" );
464 midi_input_node->add_property ("name", midi_input_state_iter->name);
465 midi_input_node->add_property ("active", midi_input_state_iter->active ? "yes" : "no");
466 midi_input_node->add_property ("scene_connected", midi_input_state_iter->scene_connected ? "yes" : "no");
467 midi_input_node->add_property ("mtc-in", midi_input_state_iter->mtc_in ? "yes" : "no");
468 midi_input_states_node->add_child_nocopy(*midi_input_node);
470 midi_states_node->add_child_nocopy(*midi_input_states_node);
472 XMLNode* midi_output_states_node = new XMLNode("MidiOutputs" );
473 MidiPortStateList::const_iterator midi_output_state_iter = _midi_outputs.begin();
474 for (; midi_output_state_iter != _midi_outputs.end(); ++midi_output_state_iter) {
475 XMLNode* midi_output_node = new XMLNode("output" );
476 midi_output_node->add_property ("name", midi_output_state_iter->name);
477 midi_output_node->add_property ("active", midi_output_state_iter->active ? "yes" : "no");
478 midi_output_node->add_property ("scene_connected", midi_output_state_iter->scene_connected ? "yes" : "no");
479 midi_output_node->add_property ("mtc-in", midi_output_state_iter->mtc_in ? "yes" : "no");
480 midi_output_states_node->add_child_nocopy(*midi_output_node);
482 midi_states_node->add_child_nocopy(*midi_output_states_node);
484 audio_midi_settings_node->add_child_nocopy(*midi_states_node);
489 EngineStateController::_apply_state(const StatePtr& state)
491 bool applied = false;
493 if (set_new_backend_as_current(state->backend_name) ) {
494 applied = set_new_device_as_current(state->device_name);
502 EngineStateController::_do_initial_engine_setup()
504 bool state_applied = false;
506 // if we have no saved state load default values
507 if (!_states.empty() ) {
509 // look for last active state first
510 StateList::const_iterator state_iter = _states.begin();
511 for (; state_iter != _states.end(); ++state_iter) {
512 if ( (*state_iter)->active ) {
513 state_applied = _apply_state(*state_iter);
518 // last active state was not applied
520 if (!state_applied) {
521 StateList::const_iterator state_iter = _states.begin();
522 for (; state_iter != _states.end(); ++state_iter) {
523 state_applied = _apply_state(*state_iter);
529 if (!state_applied ){
530 std::vector<const AudioBackendInfo*> backends = AudioEngine::instance()->available_backends();
532 if (!backends.empty() ) {
534 if (!set_new_backend_as_current(backends.front()->name ) ) {
535 std::cerr << "\tfailed to set backend [" << backends.front()->name << "]\n";
544 EngineStateController::_validate_current_device_state()
546 boost::shared_ptr<AudioBackend> backend = AudioEngine::instance()->current_backend();
549 // check if device parameters from the state record are still valid
550 // validate sample rate
551 std::vector<float> sample_rates = backend->available_sample_rates (_current_state->device_name);
553 if (sample_rates.empty() ) {
557 // check if session desired sample rate (if it's set) could be used with this device
560 if ( !set_new_sample_rate_in_controller (_session->nominal_frame_rate ()) ) {
561 if ( !set_new_sample_rate_in_controller (backend->default_sample_rate() ) ) {
562 if (!set_new_sample_rate_in_controller (sample_rates.front() ) ) {
569 // check if current sample rate is supported because we have no session desired sample rate value
570 if ( !set_new_sample_rate_in_controller (_current_state->sample_rate) ) {
571 if ( !set_new_sample_rate_in_controller (backend->default_sample_rate() ) ) {
572 if (!set_new_sample_rate_in_controller (sample_rates.front() ) ) {
579 // validate buffer size
580 std::vector<pframes_t> buffer_sizes = backend->available_buffer_sizes (_current_state->device_name);
581 // check if buffer size is supported
582 std::vector<pframes_t>::iterator bs_iter = std::find (buffer_sizes.begin(), buffer_sizes.end(), _current_state->buffer_size);
583 // if current is not found switch to default if is supported
584 if (bs_iter == buffer_sizes.end() ) {
585 bs_iter = std::find (buffer_sizes.begin(), buffer_sizes.end(), backend->default_buffer_size () );
587 if (bs_iter != buffer_sizes.end() ) {
588 _current_state->buffer_size = backend->default_buffer_size ();
590 if (!buffer_sizes.empty() ) {
591 _current_state->buffer_size = buffer_sizes.front();
602 EngineStateController::get_current_backend_name() const
604 return _current_state->backend_name;
609 EngineStateController::get_current_device_name() const
611 return _current_state->device_name;
616 EngineStateController::available_backends(std::vector<const AudioBackendInfo*>& available_backends)
618 available_backends = AudioEngine::instance()->available_backends();
623 EngineStateController::enumerate_devices (std::vector<AudioBackend::DeviceStatus>& device_vector) const
625 boost::shared_ptr<AudioBackend> backend = AudioEngine::instance()->current_backend();
627 device_vector = backend->enumerate_devices();
632 EngineStateController::get_current_sample_rate() const
634 return _current_state->sample_rate;
639 EngineStateController::get_default_sample_rate() const
641 boost::shared_ptr<AudioBackend> backend = AudioEngine::instance()->current_backend();
643 return backend->default_sample_rate();
648 EngineStateController::available_sample_rates_for_current_device(std::vector<float>& sample_rates) const
650 boost::shared_ptr<AudioBackend> backend = AudioEngine::instance()->current_backend();
652 sample_rates = backend->available_sample_rates (_current_state->device_name);
657 EngineStateController::get_current_buffer_size() const
659 return _current_state->buffer_size;
664 EngineStateController::get_default_buffer_size() const
666 boost::shared_ptr<AudioBackend> backend = AudioEngine::instance()->current_backend();
668 return backend->default_buffer_size();
673 EngineStateController::available_buffer_sizes_for_current_device(std::vector<pframes_t>& buffer_sizes) const
675 boost::shared_ptr<AudioBackend> backend = AudioEngine::instance()->current_backend();
677 buffer_sizes = backend->available_buffer_sizes (_current_state->device_name);
682 EngineStateController::set_new_backend_as_current(const std::string& backend_name)
684 if (backend_name == AudioEngine::instance()->current_backend_name () ) {
688 boost::shared_ptr<AudioBackend> backend = AudioEngine::instance()->set_backend (backend_name, PROGRAM_NAME, "");
691 if (_current_state != NULL) {
692 _current_state->active = false;
695 StateList::iterator found_state_iter = find_if (_states.begin(), _states.end(),
696 State::StatePredicate(backend_name, "None") );
698 if (found_state_iter != _states.end() ) {
699 // we found a record for new engine with None device - switch to it
700 _current_state = *found_state_iter;
701 _validate_current_device_state();
703 // create new record for this engine with default device
704 _current_state = boost::shared_ptr<State>(new State() );
705 _current_state->backend_name = backend_name;
706 _current_state->device_name = "None";
707 _validate_current_device_state();
708 _states.push_front(_current_state);
711 push_current_state_to_backend(false);
721 EngineStateController::set_new_device_as_current(const std::string& device_name)
723 if (_current_state->device_name == device_name) {
727 boost::shared_ptr<AudioBackend> backend = AudioEngine::instance()->current_backend();
730 std::vector<AudioBackend::DeviceStatus> device_vector = backend->enumerate_devices();
732 // validate the device
733 std::vector<AudioBackend::DeviceStatus>::iterator device_iter;
734 device_iter = std::find_if (device_vector.begin(), device_vector.end(), DevicePredicate(device_name) );
736 // device is available
737 if (device_iter != device_vector.end() ) {
739 boost::shared_ptr<State> previous_state (_current_state);
741 // look through state list and find the record for this device and current engine
742 StateList::iterator found_state_iter = find_if (_states.begin(), _states.end(),
743 State::StatePredicate(backend->name(), device_name) );
745 if (found_state_iter != _states.end() )
747 // we found a record for current engine and provided device name - switch to it
749 _current_state = *found_state_iter;
751 if (!_validate_current_device_state() ) {
752 _current_state = previous_state;
758 // the record is not found, create new one
759 _current_state = boost::shared_ptr<State>(new State() );
761 _current_state->backend_name = backend->name();
762 _current_state->device_name = device_name;
764 if (!_validate_current_device_state() ) {
765 _current_state = previous_state;
769 _states.push_front(_current_state);
772 if (previous_state != NULL) {
773 previous_state->active = false;
776 push_current_state_to_backend(false);
778 _last_used_real_device.clear();
780 if (device_name != "None") {
781 _last_used_real_device = device_name;
787 // device is not supported by current backend
794 EngineStateController::set_new_sample_rate_in_controller(framecnt_t sample_rate)
796 boost::shared_ptr<AudioBackend> backend = AudioEngine::instance()->current_backend();
799 std::vector<float> sample_rates = backend->available_sample_rates (_current_state->device_name);
800 std::vector<float>::iterator iter = std::find (sample_rates.begin(), sample_rates.end(), (float)sample_rate);
802 if (iter != sample_rates.end() ) {
803 _current_state->sample_rate = sample_rate;
812 EngineStateController::set_new_buffer_size_in_controller(pframes_t buffer_size)
814 boost::shared_ptr<AudioBackend> backend = AudioEngine::instance()->current_backend();
817 std::vector<uint32_t> buffer_sizes = backend->available_buffer_sizes (_current_state->device_name);
818 std::vector<uint32_t>::iterator iter = std::find (buffer_sizes.begin(), buffer_sizes.end(), buffer_size);
820 if (iter != buffer_sizes.end() ) {
821 _current_state->buffer_size = buffer_size;
830 EngineStateController::get_available_inputs_count() const
832 uint32_t available_channel_count = 0;
834 PortStateList::const_iterator iter = _current_state->input_channel_states.begin();
836 for (; iter != _current_state->input_channel_states.end(); ++iter) {
838 ++available_channel_count;
842 return available_channel_count;
847 EngineStateController::get_available_outputs_count () const
849 uint32_t available_channel_count = 0;
851 PortStateList* output_states;
852 if (Config->get_output_auto_connect() & AutoConnectMaster) {
853 output_states = &_current_state->stereo_out_channel_states;
855 output_states = &_current_state->multi_out_channel_states;
858 PortStateList::const_iterator iter = output_states->begin();
860 for (; iter != output_states->end(); ++iter) {
862 ++available_channel_count;
866 return available_channel_count;
871 EngineStateController::get_physical_audio_inputs(std::vector<std::string>& port_names)
875 PortStateList &input_states = _current_state->input_channel_states;
877 PortStateList::iterator iter = input_states.begin();
878 for (; iter != input_states.end(); ++iter) {
880 port_names.push_back(iter->name);
887 EngineStateController::get_physical_audio_outputs(std::vector<std::string>& port_names)
891 PortStateList* output_states;
892 if (Config->get_output_auto_connect() & AutoConnectMaster) {
893 output_states = &_current_state->stereo_out_channel_states;
895 output_states = &_current_state->multi_out_channel_states;
898 PortStateList::iterator iter = output_states->begin();
899 for (; iter != output_states->end(); ++iter) {
901 port_names.push_back(iter->name);
908 EngineStateController::get_physical_midi_inputs (std::vector<std::string>& port_names)
912 MidiPortStateList::iterator iter = _midi_inputs.begin();
913 for (; iter != _midi_inputs.end(); ++iter) {
914 if (iter->available && iter->active) {
915 port_names.push_back(iter->name);
922 EngineStateController::get_physical_midi_outputs (std::vector<std::string>& port_names)
926 MidiPortStateList::iterator iter = _midi_outputs.begin();
927 for (; iter != _midi_outputs.end(); ++iter) {
928 if (iter->available && iter->active) {
929 port_names.push_back(iter->name);
936 EngineStateController::set_physical_audio_input_state(const std::string& port_name, bool state)
938 PortStateList &input_states = _current_state->input_channel_states;
939 PortStateList::iterator found_state_iter;
940 found_state_iter = std::find(input_states.begin(), input_states.end(), PortState(port_name) );
942 if (found_state_iter != input_states.end() && found_state_iter->active != state ) {
943 found_state_iter->active = state;
944 AudioEngine::instance()->reconnect_session_routes(true, false);
946 InputConfigChanged();
952 EngineStateController::set_physical_audio_output_state(const std::string& port_name, bool state)
954 PortStateList* output_states;
955 if (Config->get_output_auto_connect() & AutoConnectMaster) {
956 output_states = &_current_state->stereo_out_channel_states;
958 output_states = &_current_state->multi_out_channel_states;
961 PortStateList::iterator target_state_iter;
962 target_state_iter = std::find(output_states->begin(), output_states->end(), PortState(port_name) );
964 if (target_state_iter != output_states->end() && target_state_iter->active != state ) {
965 target_state_iter->active = state;
967 // if StereoOut mode is used
968 if (Config->get_output_auto_connect() & AutoConnectMaster) {
971 PortStateList::iterator next_state_iter(target_state_iter);
974 if (++next_state_iter == output_states->end() ) {
975 next_state_iter = output_states->begin();
979 // only two outputs should be enabled
980 if (output_states->size() <= 2) {
982 target_state_iter->active = true;
983 next_state_iter->active = true;
987 // if current was set to active - activate next and disable the rest
988 if (target_state_iter->active ) {
989 next_state_iter->active = true;
991 // if current was deactivated but the next is active
992 if (next_state_iter->active) {
993 if (++next_state_iter == output_states->end() ) {
994 next_state_iter = output_states->begin();
996 next_state_iter->active = true;
998 // if current was deactivated but the previous is active - restore the state of current
999 target_state_iter->active = true; // state restored;
1000 --target_state_iter; // switch to previous to make it stop point in the next cycle
1001 target_state_iter->active = true;
1005 // now deactivate the rest
1006 while (++next_state_iter != target_state_iter) {
1008 if (next_state_iter == output_states->end() ) {
1009 next_state_iter = output_states->begin();
1010 // we jumped, so additional check is required
1011 if (next_state_iter == target_state_iter) {
1016 next_state_iter->active = false;
1022 AudioEngine::instance()->reconnect_session_routes(false, true);
1023 OutputConfigChanged();
1029 EngineStateController::get_physical_audio_input_state(const std::string& port_name)
1033 PortStateList &input_states = _current_state->input_channel_states;
1034 PortStateList::iterator found_state_iter;
1035 found_state_iter = std::find(input_states.begin(), input_states.end(), PortState(port_name) );
1037 if (found_state_iter != input_states.end() ) {
1038 state = found_state_iter->active;
1046 EngineStateController::get_physical_audio_output_state(const std::string& port_name)
1050 PortStateList* output_states;
1051 if (Config->get_output_auto_connect() & AutoConnectMaster) {
1052 output_states = &_current_state->stereo_out_channel_states;
1054 output_states = &_current_state->multi_out_channel_states;
1057 PortStateList::iterator found_state_iter;
1058 found_state_iter = std::find(output_states->begin(), output_states->end(), PortState(port_name) );
1060 if (found_state_iter != output_states->end() ) {
1061 state = found_state_iter->active;
1069 EngineStateController::set_physical_midi_input_state(const std::string& port_name, bool state) {
1071 MidiPortStateList::iterator found_state_iter;
1072 found_state_iter = std::find(_midi_inputs.begin(), _midi_inputs.end(), MidiPortState(port_name) );
1074 if (found_state_iter != _midi_inputs.end() && found_state_iter->available && found_state_iter->active != state ) {
1075 found_state_iter->active = state;
1078 // reconnect MTC inputs as well
1079 if (found_state_iter->mtc_in) {
1080 _session->reconnect_mtc_ports ();
1082 _session->reconnect_mmc_ports(true);
1085 MIDIInputConfigChanged();
1091 EngineStateController::set_physical_midi_output_state(const std::string& port_name, bool state) {
1093 MidiPortStateList::iterator found_state_iter;
1094 found_state_iter = std::find(_midi_outputs.begin(), _midi_outputs.end(), MidiPortState(port_name) );
1096 if (found_state_iter != _midi_outputs.end() && found_state_iter->available && found_state_iter->active != state ) {
1097 found_state_iter->active = state;
1100 _session->reconnect_mmc_ports(false);
1103 MIDIOutputConfigChanged();
1109 EngineStateController::get_physical_midi_input_state(const std::string& port_name, bool& scene_connected) {
1113 MidiPortStateList::iterator found_state_iter;
1114 found_state_iter = std::find(_midi_inputs.begin(), _midi_inputs.end(), MidiPortState(port_name) );
1116 if (found_state_iter != _midi_inputs.end() && found_state_iter->available) {
1117 state = found_state_iter->active;
1118 scene_connected = found_state_iter->scene_connected;
1126 EngineStateController::get_physical_midi_output_state(const std::string& port_name, bool& scene_connected) {
1130 MidiPortStateList::iterator found_state_iter;
1131 found_state_iter = std::find(_midi_outputs.begin(), _midi_outputs.end(), MidiPortState(port_name) );
1133 if (found_state_iter != _midi_outputs.end() && found_state_iter->available) {
1134 state = found_state_iter->active;
1135 scene_connected = found_state_iter->scene_connected;
1143 EngineStateController::set_physical_midi_scene_in_connection_state(const std::string& port_name, bool state) {
1145 MidiPortStateList::iterator found_state_iter;
1146 found_state_iter = std::find(_midi_inputs.begin(), _midi_inputs.end(), MidiPortState(port_name) );
1148 if (found_state_iter != _midi_inputs.end() && found_state_iter->available && found_state_iter->active ) {
1149 found_state_iter->scene_connected = state;
1151 std::vector<std::string> ports;
1152 ports.push_back(port_name);
1153 MIDISceneInputConnectionChanged(ports, state);
1160 EngineStateController::set_physical_midi_scenen_out_connection_state(const std::string& port_name, bool state) {
1162 MidiPortStateList::iterator found_state_iter;
1163 found_state_iter = std::find(_midi_outputs.begin(), _midi_outputs.end(), MidiPortState(port_name) );
1165 if (found_state_iter != _midi_outputs.end() && found_state_iter->available && found_state_iter->active ) {
1166 found_state_iter->scene_connected = state;
1168 std::vector<std::string> ports;
1169 ports.push_back(port_name);
1170 MIDISceneOutputConnectionChanged(ports, state);
1177 EngineStateController::set_all_midi_scene_inputs_disconnected()
1179 MidiPortStateList::iterator iter = _midi_inputs.begin();
1180 for (; iter != _midi_inputs.end(); ++iter) {
1181 iter->scene_connected = false;
1184 std::vector<std::string> ports;
1185 MIDISceneInputConnectionChanged(ports, false);
1190 EngineStateController::set_all_midi_scene_outputs_disconnected()
1192 MidiPortStateList::iterator iter = _midi_outputs.begin();
1193 for (; iter != _midi_outputs.end(); ++iter) {
1194 iter->scene_connected = false;
1197 std::vector<std::string> ports;
1198 MIDISceneOutputConnectionChanged(ports, false);
1203 EngineStateController::set_mtc_input(const std::string& port_name)
1205 MidiPortStateList::iterator iter = _midi_inputs.begin();
1206 for (; iter != _midi_inputs.end(); ++iter) {
1207 iter->mtc_in = false;
1209 if (iter->name == port_name) {
1210 iter->mtc_in = true;
1213 _session->reconnect_mtc_ports ();
1218 MTCInputChanged(port_name);
1223 EngineStateController::set_state_to_all_inputs(bool state)
1225 bool something_changed = false;
1227 PortStateList::iterator iter = _current_state->input_channel_states.begin();
1228 for (; iter != _current_state->input_channel_states.end(); ++iter) {
1229 if (iter->active != state) {
1230 iter->active = state;
1231 something_changed = true;
1235 if (something_changed) {
1236 AudioEngine::instance()->reconnect_session_routes(true, false);
1237 InputConfigChanged();
1243 EngineStateController::set_state_to_all_outputs(bool state)
1245 // unapplicable in Stereo Out mode, just return
1246 if (Config->get_output_auto_connect() & AutoConnectMaster) {
1250 bool something_changed = false;
1252 PortStateList::iterator iter = _current_state->multi_out_channel_states.begin();
1253 for (; iter != _current_state->multi_out_channel_states.end(); ++iter) {
1254 if (iter->active != state) {
1255 iter->active = state;
1256 something_changed = true;
1260 if (something_changed) {
1261 AudioEngine::instance()->reconnect_session_routes(false, true);
1262 OutputConfigChanged();
1268 EngineStateController::get_physical_audio_input_states(std::vector<PortState>& channel_states)
1270 PortStateList &input_states = _current_state->input_channel_states;
1271 channel_states.assign(input_states.begin(), input_states.end());
1276 EngineStateController::get_physical_audio_output_states(std::vector<PortState>& channel_states)
1278 PortStateList* output_states;
1279 if (Config->get_output_auto_connect() & AutoConnectMaster) {
1280 output_states = &_current_state->stereo_out_channel_states;
1282 output_states = &_current_state->multi_out_channel_states;
1285 channel_states.assign(output_states->begin(), output_states->end());
1290 EngineStateController::get_physical_midi_input_states (std::vector<MidiPortState>& channel_states)
1292 channel_states.clear();
1294 MidiPortStateList::iterator iter = _midi_inputs.begin();
1296 for (; iter != _midi_inputs.end(); ++iter ) {
1297 if (iter->available) {
1298 MidiPortState state(iter->name);
1299 state.active = iter->active;
1300 state.available = true;
1301 state.scene_connected = iter->scene_connected;
1302 state.mtc_in = iter->mtc_in;
1303 channel_states.push_back(state);
1309 EngineStateController::get_physical_midi_output_states (std::vector<MidiPortState>& channel_states)
1311 channel_states.clear();
1313 MidiPortStateList::iterator iter = _midi_outputs.begin();
1315 for (; iter != _midi_outputs.end(); ++iter ) {
1316 if (iter->available) {
1317 MidiPortState state(iter->name);
1318 state.active = iter->active;
1319 state.available = true;
1320 state.scene_connected = iter->scene_connected;
1321 state.mtc_in = iter->mtc_in;
1322 channel_states.push_back(state);
1329 EngineStateController::_on_session_loaded ()
1335 AudioEngine::instance()->reconnect_session_routes(true, true);
1336 _session->reconnect_mtc_ports ();
1337 _session->reconnect_mmc_ports (true);
1338 _session->reconnect_mmc_ports (false);
1340 framecnt_t desired_sample_rate = _session->nominal_frame_rate ();
1341 if ( desired_sample_rate > 0 && set_new_sample_rate_in_controller(desired_sample_rate) )
1343 push_current_state_to_backend(false);
1344 SampleRateChanged(); // emit a signal
1350 EngineStateController::_on_sample_rate_change(framecnt_t new_sample_rate)
1352 if (_current_state->sample_rate != new_sample_rate) {
1354 // if sample rate has been changed
1355 framecnt_t sample_rate_to_set = new_sample_rate;
1356 if (AudioEngine::instance()->session() ) {
1357 // and we have current session we should restore it back to the one tracks uses
1358 sample_rate_to_set = AudioEngine::instance()->session()->frame_rate ();
1361 if ( !set_new_sample_rate_in_controller (sample_rate_to_set) ) {
1362 // if sample rate can't be set
1363 // switch to NONE device
1364 set_new_device_as_current ("None");
1365 DeviceListChanged(false);
1370 SampleRateChanged(); // emit a signal
1375 EngineStateController::_on_buffer_size_change(pframes_t new_buffer_size)
1377 if (_current_state->buffer_size != new_buffer_size) {
1378 _current_state->buffer_size = new_buffer_size;
1381 BufferSizeChanged(); // emit a signal
1386 EngineStateController::_on_device_list_change()
1388 bool current_device_disconnected = false;
1390 boost::shared_ptr<AudioBackend> backend = AudioEngine::instance()->current_backend();
1393 std::vector<AudioBackend::DeviceStatus> device_vector = backend->enumerate_devices();
1395 // find out out if current device is still available if it's not None
1396 if (_current_state->device_name != "None")
1398 std::vector<AudioBackend::DeviceStatus>::iterator device_iter;
1399 device_iter = std::find_if (device_vector.begin(), device_vector.end(), DevicePredicate(_current_state->device_name) );
1401 // if current device is not available any more - switch to None device
1402 if (device_iter == device_vector.end() ) {
1404 StateList::iterator found_state_iter = find_if (_states.begin(), _states.end(),
1405 State::StatePredicate(_current_state->backend_name, "None") );
1407 if (found_state_iter != _states.end() ) {
1408 // found the record - switch to it
1409 _current_state = *found_state_iter;
1410 _validate_current_device_state();
1412 // create new record for this engine with default device
1413 _current_state = boost::shared_ptr<State>(new State() );
1414 _current_state->backend_name = backend->name();
1415 _current_state->device_name = "None";
1416 _validate_current_device_state();
1417 _states.push_front(_current_state);
1420 push_current_state_to_backend(true);
1421 current_device_disconnected = true;
1424 // if the device which was active before is available now - switch to it
1426 std::vector<AudioBackend::DeviceStatus>::iterator device_iter;
1427 device_iter = std::find_if (device_vector.begin(), device_vector.end(), DevicePredicate(_last_used_real_device) );
1429 if (device_iter != device_vector.end() ) {
1430 StateList::iterator found_state_iter = find_if (_states.begin(), _states.end(),
1431 State::StatePredicate(_current_state->backend_name,
1432 _last_used_real_device) );
1434 if (found_state_iter != _states.end() ) {
1436 boost::shared_ptr<State> previous_state (_current_state);
1437 _current_state = *found_state_iter;
1439 if (_validate_current_device_state() ) {
1440 push_current_state_to_backend(false);
1442 // cannot use this device right now
1443 _last_used_real_device.clear();
1444 _current_state = previous_state;
1450 DeviceListChanged(current_device_disconnected); // emit a signal
1455 EngineStateController::_update_device_channels_state()
1457 boost::shared_ptr<AudioBackend> backend = AudioEngine::instance()->current_backend();
1460 // update audio input states
1461 std::vector<std::string> phys_audio_inputs;
1462 backend->get_physical_inputs(DataType::AUDIO, phys_audio_inputs);
1464 PortStateList new_input_states;
1465 PortStateList &input_states = _current_state->input_channel_states;
1467 std::vector<std::string>::const_iterator input_iter = phys_audio_inputs.begin();
1468 for (; input_iter != phys_audio_inputs.end(); ++input_iter) {
1470 PortState state(*input_iter);
1471 state.active = true;
1472 PortStateList::const_iterator found_state_iter = std::find(input_states.begin(), input_states.end(), state);
1474 if (found_state_iter != input_states.end() ) {
1475 new_input_states.push_back(*found_state_iter);
1477 new_input_states.push_back(state);
1480 _current_state->input_channel_states = new_input_states;
1482 // update audio output states (multi out mode)
1483 std::vector<std::string> phys_audio_outputs;
1484 backend->get_physical_outputs(DataType::AUDIO, phys_audio_outputs);
1486 PortStateList new_output_states;
1487 PortStateList &output_multi_states = _current_state->multi_out_channel_states;
1489 std::vector<std::string>::const_iterator output_iter = phys_audio_outputs.begin();
1490 for (; output_iter != phys_audio_outputs.end(); ++output_iter) {
1492 PortState state(*output_iter);
1493 state.active = true;
1494 PortStateList::const_iterator found_state_iter = std::find(output_multi_states.begin(), output_multi_states.end(), state);
1496 if (found_state_iter != output_multi_states.end() ) {
1497 new_output_states.push_back(*found_state_iter);
1499 new_output_states.push_back(state);
1503 _current_state->multi_out_channel_states = new_output_states;
1505 // update audio output states (stereo out mode)
1506 new_output_states.clear();
1507 PortStateList &output_stereo_states = _current_state->stereo_out_channel_states;
1509 output_iter = phys_audio_outputs.begin();
1510 for (; output_iter != phys_audio_outputs.end(); ++output_iter) {
1512 PortState state(*output_iter);
1513 state.active = true;
1514 PortStateList::const_iterator found_state_iter = std::find(output_stereo_states.begin(), output_stereo_states.end(), state);
1516 if (found_state_iter != output_stereo_states.end() ) {
1517 new_output_states.push_back(*found_state_iter);
1519 new_output_states.push_back(state);
1523 _current_state->stereo_out_channel_states = new_output_states;
1524 _refresh_stereo_out_channel_states();
1527 // update midi ports: unlike audio ports which states are saved per device
1528 // each midi port state is saved individualy
1529 // so get all midi ports from the backend
1530 // and compare to the list of midi ports we have
1531 // if physical port is new, add it to our state list
1532 // if physical port is present in our state list - mark it available
1533 // if there is no corresponding physical port to one we have in a list - leave it unavailable
1534 MidiPortStateList::iterator iter = _midi_inputs.begin();
1535 for (; iter != _midi_inputs.end(); ++iter) {
1536 iter->available = false;
1539 for (iter = _midi_outputs.begin(); iter != _midi_outputs.end(); ++iter) {
1540 iter->available = false;
1543 // update midi input ports
1544 std::vector<std::string> phys_midi_inputs;
1545 backend->get_physical_inputs(DataType::MIDI, phys_midi_inputs);
1547 std::vector<std::string>::const_iterator midi_input_iter = phys_midi_inputs.begin();
1548 for (; midi_input_iter != phys_midi_inputs.end(); ++midi_input_iter) {
1550 MidiPortState state(*midi_input_iter);
1551 state.active = false;
1552 state.available = true;
1553 MidiPortStateList::iterator found_state_iter = std::find(_midi_inputs.begin(), _midi_inputs.end(), state);
1555 if (found_state_iter != _midi_inputs.end() ) {
1556 found_state_iter->available = true;
1558 _midi_inputs.push_back(state);
1562 // update midi output ports
1563 std::vector<std::string> phys_midi_outputs;
1564 backend->get_physical_outputs(DataType::MIDI, phys_midi_outputs);
1566 std::vector<std::string>::const_iterator midi_output_iter = phys_midi_outputs.begin();
1567 for (; midi_output_iter != phys_midi_outputs.end(); ++midi_output_iter) {
1569 MidiPortState state(*midi_output_iter);
1570 state.active = false;
1571 state.available = true;
1572 MidiPortStateList::iterator found_state_iter = std::find(_midi_outputs.begin(), _midi_outputs.end(), state);
1574 if (found_state_iter != _midi_outputs.end() ) {
1575 found_state_iter->available = true;
1577 _midi_outputs.push_back(state);
1584 EngineStateController::_refresh_stereo_out_channel_states()
1586 PortStateList &output_states = _current_state->stereo_out_channel_states;
1587 PortStateList::iterator active_iter = output_states.begin();
1589 for (; active_iter != output_states.end(); ++active_iter) {
1590 if (active_iter->active) {
1595 uint32_t pending_active_channels = 2;
1596 PortStateList::iterator iter = output_states.begin();
1598 if (active_iter != output_states.end() ) {
1600 if (++iter == output_states.end() ) {
1601 iter = output_states.begin();
1604 (iter++)->active = true;
1605 pending_active_channels = 0;
1608 // drop the rest of the states to false (until we reach the end or first existing active channel)
1609 for (; iter != output_states.end() && iter != active_iter; ++iter) {
1610 if (pending_active_channels) {
1611 iter->active = true;
1612 --pending_active_channels;
1614 iter->active = false;
1621 EngineStateController::_on_engine_running ()
1623 AudioEngine::instance()->reconnect_session_routes(true, true);
1624 _current_state->active = true;
1626 EngineRunning(); // emit a signal
1631 EngineStateController::_on_engine_stopped ()
1638 EngineStateController::_on_engine_halted ()
1645 EngineStateController::_on_device_error()
1647 set_new_device_as_current ("None");
1648 push_current_state_to_backend(true);
1649 DeviceListChanged(false);
1655 EngineStateController::_on_parameter_changed (const std::string& parameter_name)
1657 if (parameter_name == "output-auto-connect") {
1659 AudioEngine::instance()->reconnect_session_routes(false, true);
1660 OutputConfigChanged(); // emit a signal
1661 OutputConnectionModeChanged(); // emit signal
1667 EngineStateController::_on_ports_registration_update ()
1669 _update_device_channels_state();
1671 // update MIDI connections
1673 _session->reconnect_midi_scene_ports (true);
1674 _session->reconnect_midi_scene_ports (false);
1676 _session->reconnect_mtc_ports ();
1678 _session->reconnect_mmc_ports (true);
1679 _session->reconnect_mmc_ports (false);
1682 PortRegistrationChanged(); // emit a signal
1687 EngineStateController::push_current_state_to_backend(bool start)
1689 boost::shared_ptr<AudioBackend> backend = AudioEngine::instance()->current_backend();
1695 // check if anything changed
1696 bool state_changed = (_current_state->device_name != backend->device_name() ) ||
1697 (_current_state->sample_rate != backend->sample_rate() ) ||
1698 (_current_state->buffer_size != backend->buffer_size() );
1700 bool was_running = AudioEngine::instance()->running();
1702 Glib::Threads::RecMutex::Lock sl (AudioEngine::instance()->state_lock() );
1703 if (state_changed) {
1706 if (AudioEngine::instance()->stop () ) {
1713 std::cout << "EngineStateController::Setting device: " << _current_state->device_name << std::endl;
1714 if ((_current_state->device_name != backend->device_name()) && (result = backend->set_device_name (_current_state->device_name)) ) {
1715 error << string_compose (_("Cannot set device name to %1"), get_current_device_name()) << endmsg;
1719 std::cout << "EngineStateController::Setting device sample rate " << _current_state->sample_rate << std::endl;
1720 result = backend->set_sample_rate (_current_state->sample_rate);
1723 error << string_compose (_("Cannot set sample rate to %1"), get_current_sample_rate()) << endmsg;
1728 std::cout << "EngineStateController::Setting device buffer size " << _current_state->buffer_size << std::endl;
1729 result = backend->set_buffer_size (_current_state->buffer_size);
1732 error << string_compose (_("Cannot set buffer size to %1"), get_current_buffer_size()) << endmsg;
1737 if (result) // error during device setup
1739 //switch to None device and notify about the issue
1740 set_new_device_as_current ("None");
1741 DeviceListChanged(false);
1745 if (AudioEngine::instance()->backend_reset_requested() ) {
1746 // device asked for reset, do not start engine now
1747 // free sate lock and let Engine reset the device as it's required
1752 if(start || (was_running && state_changed) ) {
1753 if (AudioEngine::instance()->start () && !AudioEngine::instance()->is_reset_requested() ) {
1754 //switch to None device and notify about the issue
1755 set_new_device_as_current ("None");
1756 AudioEngine::instance()->start ();
1757 DeviceListChanged(false);
1763 save_audio_midi_settings();