noop: fix indentation to match style guide
[ardour.git] / libs / ardour / engine_state_controller.cc
1 /*
2   Copyright (C) 2014 Waves Audio Ltd.
3  
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.
8  
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.
13  
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.
17  
18 */
19
20 #include "ardour/engine_state_controller.h"
21
22 #include "ardour/audioengine.h"
23 #include "ardour/session.h"
24 #include "ardour/rc_configuration.h"
25 #include "ardour/data_type.h"
26
27 #include "pbd/pthread_utils.h"
28 #include "pbd/error.h"
29 #include "i18n.h"
30
31
32 using namespace ARDOUR;
33 using namespace PBD;
34
35 namespace {
36     
37 struct DevicePredicate
38 {
39         DevicePredicate(const std::string& device_name)
40                 : _device_name(device_name)
41         {}
42         
43         bool operator()(const AudioBackend::DeviceStatus& rhs)
44         {
45                 return _device_name == rhs.name;
46         }
47         
48     private:
49         std::string _device_name;
50 };
51 }
52
53 EngineStateController*
54 EngineStateController::instance()
55 {
56         static EngineStateController instance;
57         return &instance;
58 }
59
60
61 EngineStateController::EngineStateController()
62         : _current_state()
63         , _last_used_real_device("")
64
65 {
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) );
69     
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) );
76     
77         /* Global configuration parameters update */
78         Config->ParameterChanged.connect_same_thread (update_connections, boost::bind (&EngineStateController::_on_parameter_changed, this, _1) );
79     
80         _deserialize_and_load_engine_states();
81         _deserialize_and_load_midi_port_states();
82         _do_initial_engine_setup();
83     
84         // now push the sate to the backend
85         push_current_state_to_backend(false);
86 }
87
88
89 EngineStateController::~EngineStateController()
90 {
91 }
92
93
94 void
95 EngineStateController::set_session(Session* session)
96 {
97         _session = session;
98         _session->SessionLoaded.connect_same_thread (session_connections, boost::bind (&EngineStateController::_on_session_loaded, this) );
99 }
100
101
102 void
103 EngineStateController::remove_session ()
104 {
105         session_connections.drop_connections ();
106         _session = 0;
107 }
108
109
110 XMLNode&
111 EngineStateController::serialize_audio_midi_settings()
112 {
113     
114         XMLNode* root = new XMLNode ("AudioMidiSettings");
115     
116         _serialize_engine_states(root);
117         _serialize_midi_port_states(root);
118     
119         return *root;
120 }
121
122
123 void
124 EngineStateController::save_audio_midi_settings()
125 {
126         Config->add_extra_xml (serialize_audio_midi_settings() );
127         Config->save_state ();
128 }
129
130
131 void
132 EngineStateController::_deserialize_and_load_engine_states()
133 {
134         XMLNode* audio_midi_settings_root = ARDOUR::Config->extra_xml ("AudioMidiSettings");
135     
136         if (!audio_midi_settings_root) {
137                 return;
138         }
139     
140         XMLNode* engine_states = audio_midi_settings_root->child("EngineStates");
141     
142         if (!engine_states) {
143                 return;
144         }
145     
146         XMLNodeList state_nodes_list = engine_states->children();
147         XMLNodeConstIterator state_node_iter = state_nodes_list.begin();
148     
149         for (; state_node_iter != state_nodes_list.end(); ++state_node_iter) {
150         
151                 XMLNode* state_node = *state_node_iter;
152                 StatePtr engine_state(new State);
153                 XMLProperty* prop = NULL;
154         
155                 if ((prop = state_node->property ("backend-name")) == 0) {
156                         continue;
157                 }
158                 engine_state->backend_name = prop->value ();
159         
160                 if ((prop = state_node->property ("device-name")) == 0) {
161                         continue;
162                 }
163                 engine_state->device_name = prop->value ();
164         
165                 if ((prop = state_node->property ("sample-rate")) == 0) {
166                         continue;
167                 }
168                 engine_state->sample_rate = atoi (prop->value ());
169         
170                 if ((prop = state_node->property ("buffer-size")) == 0) {
171                         continue;
172                 }
173                 engine_state->buffer_size = atoi (prop->value ());
174         
175                 if ((prop = state_node->property ("active")) == 0) {
176                         continue;
177                 }
178                 engine_state->active = string_is_affirmative (prop->value ());
179         
180                 XMLNodeList state_children_list = state_node->children();
181                 XMLNodeConstIterator state_child_iter = state_children_list.begin();
182         
183                 for (; state_child_iter != state_children_list.end(); ++state_child_iter) {
184                         XMLNode* state_child = *state_child_iter;
185                 
186                         if (state_child->name() == "InputConfiguration") {
187                     
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;
191                     
192                                 for (; input_state_node_iter != input_states_nodes.end(); ++input_state_node_iter) {
193                         
194                                         XMLNode* input_state_node = *input_state_node_iter;
195                         
196                                         if (input_state_node->name() != "input") {
197                                                 continue;
198                                         }
199                                         PortState input_state (input_state_node->name() );
200                         
201                                         if ((prop = input_state_node->property ("name")) == 0) {
202                                                 continue;
203                                         }
204                                         input_state.name = prop->value();
205                         
206                                         if ((prop = input_state_node->property ("active")) == 0) {
207                                                 continue;
208                                         }
209                                         input_state.active = string_is_affirmative (prop->value ());
210                         
211                                         input_states.push_back(input_state);
212                                 }
213                     
214                         } else if (state_child->name() == "MultiOutConfiguration") {
215                     
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;
219                     
220                                 for (; multi_out_state_node_iter != multi_out_state_nodes.end(); ++multi_out_state_node_iter) {
221                         
222                                         XMLNode* multi_out_state_node = *multi_out_state_node_iter;
223                         
224                                         if (multi_out_state_node->name() != "output") {
225                                                 continue;
226                                         }
227                                         PortState multi_out_state (multi_out_state_node->name() );
228                         
229                                         if ((prop = multi_out_state_node->property ("name")) == 0) {
230                                                 continue;
231                                         }
232                                         multi_out_state.name = prop->value();
233                         
234                                         if ((prop = multi_out_state_node->property ("active")) == 0) {
235                                                 continue;
236                                         }
237                                         multi_out_state.active = string_is_affirmative (prop->value ());
238                         
239                                         multi_out_states.push_back(multi_out_state);
240                                 }
241                         } else if (state_child->name() == "StereoOutConfiguration") {
242                     
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;
246                     
247                                 for (; stereo_out_state_node_iter != stereo_out_state_nodes.end(); ++stereo_out_state_node_iter) {
248                         
249                                         XMLNode* stereo_out_state_node = *stereo_out_state_node_iter;
250                         
251                                         if (stereo_out_state_node->name() != "output") {
252                                                 continue;
253                                         }
254                                         PortState stereo_out_state (stereo_out_state_node->name() );
255                         
256                                         if ((prop = stereo_out_state_node->property ("name")) == 0) {
257                                                 continue;
258                                         }
259                                         stereo_out_state.name = prop->value();
260                         
261                                         if ((prop = stereo_out_state_node->property ("active")) == 0) {
262                                                 continue;
263                                         }                      
264                                         stereo_out_state.active = string_is_affirmative (prop->value ());
265                         
266                                         stereo_out_states.push_back(stereo_out_state);
267                                 }
268                         }
269                 }
270         
271                 _states.push_back (engine_state);
272         }
273 }
274
275
276 void
277 EngineStateController::_deserialize_and_load_midi_port_states()
278 {  
279         XMLNode* audio_midi_settings_root = ARDOUR::Config->extra_xml ("AudioMidiSettings");
280     
281         if (!audio_midi_settings_root) {
282                 return;
283         }
284     
285         XMLNode* midi_states = audio_midi_settings_root->child("MidiStates");
286     
287         if (!midi_states) {
288                 return;
289         }
290     
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) {
294         
295                 XMLNode* state_node = *state_node_iter;
296                 if (state_node->name() == "MidiInputs") {
297             
298                         XMLNodeList input_state_nodes = state_node->children();
299                         XMLNodeConstIterator input_state_node_iter = input_state_nodes.begin();
300                         _midi_inputs.clear();
301             
302                         for (; input_state_node_iter != input_state_nodes.end(); ++input_state_node_iter) {
303                 
304                                 XMLNode* input_state_node = *input_state_node_iter;
305                                 XMLProperty* prop = NULL;
306                 
307                                 if (input_state_node->name() != "input") {
308                                         continue;
309                                 }
310                                 MidiPortState input_state (input_state_node->name() );
311                 
312                                 if ((prop = input_state_node->property ("name")) == 0) {
313                                         continue;
314                                 }
315                                 input_state.name = prop->value();
316                 
317                                 if ((prop = input_state_node->property ("active")) == 0) {
318                                         continue;
319                                 }
320                                 input_state.active = string_is_affirmative (prop->value ());
321                 
322                                 if ((prop = input_state_node->property ("scene-connected")) == 0) {
323                                         continue;
324                                 }
325                                 input_state.scene_connected = string_is_affirmative (prop->value ());
326                 
327                                 if ((prop = input_state_node->property ("mtc-in")) == 0) {
328                                         continue;
329                                 }
330                                 input_state.mtc_in = string_is_affirmative (prop->value ());
331                 
332                                 _midi_inputs.push_back(input_state);
333                         }
334             
335                 } else if (state_node->name() == "MidiOutputs") {
336             
337                         XMLNodeList output_state_nodes = state_node->children();
338                         XMLNodeConstIterator output_state_node_iter = output_state_nodes.begin();
339                         _midi_outputs.clear();
340             
341                         for (; output_state_node_iter != output_state_nodes.end(); ++output_state_node_iter) {
342                 
343                                 XMLNode* output_state_node = *output_state_node_iter;
344                                 XMLProperty* prop = NULL;
345                 
346                                 if (output_state_node->name() != "output") {
347                                         continue;
348                                 }
349                                 MidiPortState output_state (output_state_node->name() );
350                 
351                                 if ((prop = output_state_node->property ("name")) == 0) {
352                                         continue;
353                                 }
354                                 output_state.name = prop->value();
355                 
356                                 if ((prop = output_state_node->property ("active")) == 0) {
357                                         continue;
358                                 }
359                                 output_state.active = string_is_affirmative (prop->value ());
360                 
361                                 if ((prop = output_state_node->property ("scene-connected")) == 0) {
362                                         continue;
363                                 }
364                                 output_state.scene_connected = string_is_affirmative (prop->value ());
365                 
366                                 if ((prop = output_state_node->property ("mtc-in")) == 0) {
367                                         continue;
368                                 }
369                                 output_state.mtc_in = string_is_affirmative (prop->value ());
370                 
371                                 _midi_outputs.push_back(output_state);
372                         }
373                 }
374         }
375 }
376
377
378 void
379 EngineStateController::_serialize_engine_states(XMLNode* audio_midi_settings_node)
380 {
381         if (!audio_midi_settings_node) {
382                 return;
383         }
384     
385         // clean up state data first
386         audio_midi_settings_node->remove_nodes_and_delete("EngineStates" );
387     
388         XMLNode* engine_states = new XMLNode("EngineStates" );
389     
390         StateList::const_iterator state_iter = _states.begin();
391         for (; state_iter != _states.end(); ++state_iter) {
392         
393                 StatePtr state_ptr = *state_iter;
394         
395                 // create new node for the state
396                 XMLNode* state_node = new XMLNode("State");
397         
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");
403         
404                 // store channel states:
405                 // inputs
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);
414                 }
415                 state_node->add_child_nocopy(*input_config_node);
416         
417                 // multi out outputs
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);
426                 }
427                 state_node->add_child_nocopy(*multi_out_config_node);
428         
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);
438                 }
439                 state_node->add_child_nocopy(*stereo_out_config_node);
440     
441                 engine_states->add_child_nocopy(*state_node);
442         }
443
444         audio_midi_settings_node->add_child_nocopy(*engine_states);
445 }
446
447
448 void
449 EngineStateController::_serialize_midi_port_states(XMLNode* audio_midi_settings_node)
450 {
451         if (!audio_midi_settings_node) {
452                 return;
453         }
454     
455         // clean up state data first
456         audio_midi_settings_node->remove_nodes_and_delete("MidiStates" );
457     
458         XMLNode* midi_states_node = new XMLNode("MidiStates" );
459     
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);
469         }
470         midi_states_node->add_child_nocopy(*midi_input_states_node);
471     
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);
481         }
482         midi_states_node->add_child_nocopy(*midi_output_states_node);
483
484         audio_midi_settings_node->add_child_nocopy(*midi_states_node);
485 }
486
487
488 bool
489 EngineStateController::_apply_state(const StatePtr& state)
490 {
491         bool applied = false;
492     
493         if (set_new_backend_as_current(state->backend_name) ) {
494                 applied = set_new_device_as_current(state->device_name);
495         }
496     
497         return applied;
498 }
499
500
501 void
502 EngineStateController::_do_initial_engine_setup()
503 {
504         bool state_applied = false;
505     
506         // if we have no saved state load default values
507         if (!_states.empty() ) {
508         
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);
514                                 break;
515                         }
516                 }
517         
518                 // last active state was not applied
519                 // try others
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);
524                                 break;
525                         }
526                 }
527         }
528
529         if (!state_applied ){
530                 std::vector<const AudioBackendInfo*> backends = AudioEngine::instance()->available_backends();
531         
532                 if (!backends.empty() ) {
533             
534                         if (!set_new_backend_as_current(backends.front()->name ) ) {
535                                 std::cerr << "\tfailed to set backend [" << backends.front()->name << "]\n";
536                         }
537                 }
538         
539         }
540 }
541
542
543 bool
544 EngineStateController::_validate_current_device_state()
545 {
546         boost::shared_ptr<AudioBackend> backend = AudioEngine::instance()->current_backend();
547         assert(backend);
548     
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);
552     
553         if (sample_rates.empty() ) {
554                 return false;
555         }
556
557         // check if session desired sample rate (if it's set) could be used with this device
558         if (_session != 0) {
559         
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() ) ) {
563                                         return false;
564                                 }
565                         }
566                 }
567     
568         } else {
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() ) ) {
573                                         return false;
574                                 }
575                         }
576                 }
577         }
578     
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 () );
586         
587                 if (bs_iter != buffer_sizes.end() ) {
588                         _current_state->buffer_size = backend->default_buffer_size ();
589                 } else {
590                         if (!buffer_sizes.empty() ) {
591                                 _current_state->buffer_size = buffer_sizes.front();
592                         }
593                 }
594
595         }
596
597         return true;
598 }
599
600
601 const std::string&
602 EngineStateController::get_current_backend_name() const
603 {
604         return _current_state->backend_name;
605 }
606
607
608 const std::string&
609 EngineStateController::get_current_device_name() const
610 {
611         return _current_state->device_name;
612 }
613
614
615 void
616 EngineStateController::available_backends(std::vector<const AudioBackendInfo*>& available_backends)
617 {
618         available_backends = AudioEngine::instance()->available_backends();
619 }
620
621
622 void
623 EngineStateController::enumerate_devices (std::vector<AudioBackend::DeviceStatus>& device_vector) const
624 {
625         boost::shared_ptr<AudioBackend> backend = AudioEngine::instance()->current_backend();
626         assert(backend);
627         device_vector = backend->enumerate_devices();
628 }
629
630
631 framecnt_t
632 EngineStateController::get_current_sample_rate() const
633 {
634         return _current_state->sample_rate;
635 }
636
637
638 framecnt_t
639 EngineStateController::get_default_sample_rate() const
640 {
641         boost::shared_ptr<AudioBackend> backend = AudioEngine::instance()->current_backend();
642         assert(backend);
643         return backend->default_sample_rate();
644 }
645
646
647 void
648 EngineStateController::available_sample_rates_for_current_device(std::vector<float>& sample_rates) const
649 {
650         boost::shared_ptr<AudioBackend> backend = AudioEngine::instance()->current_backend();
651         assert(backend);
652         sample_rates = backend->available_sample_rates (_current_state->device_name);
653 }
654
655
656 uint32_t
657 EngineStateController::get_current_buffer_size() const
658 {
659         return _current_state->buffer_size;
660 }
661
662
663 uint32_t
664 EngineStateController::get_default_buffer_size() const
665 {
666         boost::shared_ptr<AudioBackend> backend = AudioEngine::instance()->current_backend();
667         assert(backend);
668         return backend->default_buffer_size();
669 }
670
671
672 void
673 EngineStateController::available_buffer_sizes_for_current_device(std::vector<pframes_t>& buffer_sizes) const
674 {
675         boost::shared_ptr<AudioBackend> backend = AudioEngine::instance()->current_backend();
676         assert(backend);
677         buffer_sizes = backend->available_buffer_sizes (_current_state->device_name);
678 }
679
680
681 bool
682 EngineStateController::set_new_backend_as_current(const std::string& backend_name)
683 {
684         if (backend_name == AudioEngine::instance()->current_backend_name () ) {
685                 return true;
686         }
687     
688         boost::shared_ptr<AudioBackend> backend = AudioEngine::instance()->set_backend (backend_name, PROGRAM_NAME, "");
689         if (backend)
690         {
691                 if (_current_state != NULL) {
692                         _current_state->active = false;
693                 }
694         
695                 StateList::iterator found_state_iter = find_if (_states.begin(), _states.end(),
696                                                                 State::StatePredicate(backend_name, "None") );
697         
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();
702                 } else {
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);
709                 }
710         
711                 push_current_state_to_backend(false);
712         
713                 return true;
714         }
715     
716         return false;
717 }
718
719
720 bool
721 EngineStateController::set_new_device_as_current(const std::string& device_name)
722 {
723         if (_current_state->device_name == device_name) {
724                 return true;
725         }
726     
727         boost::shared_ptr<AudioBackend> backend = AudioEngine::instance()->current_backend();
728         assert(backend);
729     
730         std::vector<AudioBackend::DeviceStatus> device_vector = backend->enumerate_devices();
731     
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) );
735     
736         // device is available
737         if (device_iter != device_vector.end() ) {
738         
739                 boost::shared_ptr<State> previous_state (_current_state);
740         
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) );
744         
745                 if (found_state_iter != _states.end() )
746                 {
747                         // we found a record for current engine and provided device name - switch to it
748             
749                         _current_state = *found_state_iter;
750             
751                         if (!_validate_current_device_state() ) {
752                                 _current_state = previous_state;
753                                 return false;
754                         }
755         
756                 } else {
757        
758                         // the record is not found, create new one
759                         _current_state = boost::shared_ptr<State>(new State() );
760             
761                         _current_state->backend_name = backend->name();
762                         _current_state->device_name = device_name;
763             
764                         if (!_validate_current_device_state() ) {
765                                 _current_state = previous_state;
766                                 return false;
767                         }
768             
769                         _states.push_front(_current_state);
770                 }
771         
772                 if (previous_state != NULL) {
773                         previous_state->active = false;
774                 }
775         
776                 push_current_state_to_backend(false);
777
778                 _last_used_real_device.clear();
779         
780                 if (device_name != "None") {
781                         _last_used_real_device = device_name;
782                 }
783         
784                 return true;
785         }
786     
787         // device is not supported by current backend
788         return false;
789 }
790
791
792
793 bool
794 EngineStateController::set_new_sample_rate_in_controller(framecnt_t sample_rate)
795 {
796         boost::shared_ptr<AudioBackend> backend = AudioEngine::instance()->current_backend();
797         assert(backend);
798     
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);
801     
802         if (iter != sample_rates.end() ) {
803                 _current_state->sample_rate = sample_rate;
804                 return true;
805         }
806     
807         return false;
808 }
809
810
811 bool
812 EngineStateController::set_new_buffer_size_in_controller(pframes_t buffer_size)
813 {    
814         boost::shared_ptr<AudioBackend> backend = AudioEngine::instance()->current_backend();
815         assert(backend);
816     
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);
819
820         if (iter != buffer_sizes.end() ) {
821                 _current_state->buffer_size = buffer_size;
822                 return true;
823         }
824     
825         return false;
826 }
827
828
829 uint32_t
830 EngineStateController::get_available_inputs_count() const
831 {
832         uint32_t available_channel_count = 0;
833     
834         PortStateList::const_iterator iter = _current_state->input_channel_states.begin();
835     
836         for (; iter != _current_state->input_channel_states.end(); ++iter) {
837                 if (iter->active) {
838                         ++available_channel_count;
839                 }
840         }
841     
842         return available_channel_count;
843 }
844
845
846 uint32_t
847 EngineStateController::get_available_outputs_count () const
848 {
849         uint32_t available_channel_count = 0;
850     
851         PortStateList* output_states;
852         if (Config->get_output_auto_connect() & AutoConnectMaster) {
853                 output_states = &_current_state->stereo_out_channel_states;
854         } else {
855                 output_states = &_current_state->multi_out_channel_states;
856         }
857     
858         PortStateList::const_iterator iter = output_states->begin();
859     
860         for (; iter != output_states->end(); ++iter) {
861                 if (iter->active) {
862                         ++available_channel_count;
863                 }
864         }
865     
866         return available_channel_count;
867 }
868
869
870 void
871 EngineStateController::get_physical_audio_inputs(std::vector<std::string>& port_names)
872 {
873         port_names.clear();
874     
875         PortStateList &input_states = _current_state->input_channel_states;
876     
877         PortStateList::iterator iter = input_states.begin();
878         for (; iter != input_states.end(); ++iter) {
879                 if (iter->active) {
880                         port_names.push_back(iter->name);
881                 }
882         }
883 }
884
885
886 void
887 EngineStateController::get_physical_audio_outputs(std::vector<std::string>& port_names)
888 {
889         port_names.clear();
890     
891         PortStateList* output_states;
892         if (Config->get_output_auto_connect() & AutoConnectMaster) {
893                 output_states = &_current_state->stereo_out_channel_states;
894         } else {
895                 output_states = &_current_state->multi_out_channel_states;
896         }
897     
898         PortStateList::iterator iter = output_states->begin();
899         for (; iter != output_states->end(); ++iter) {
900                 if (iter->active) {
901                         port_names.push_back(iter->name);
902                 }
903         }
904 }
905
906
907 void
908 EngineStateController::get_physical_midi_inputs (std::vector<std::string>& port_names)
909 {
910         port_names.clear();
911     
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);
916                 }
917         }
918 }
919
920
921 void
922 EngineStateController::get_physical_midi_outputs (std::vector<std::string>& port_names)
923 {
924         port_names.clear();
925     
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);
930                 }
931         }
932 }
933
934
935 void
936 EngineStateController::set_physical_audio_input_state(const std::string& port_name, bool state)
937 {
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) );
941     
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);
945         
946                 InputConfigChanged();
947         }
948 }
949
950
951 void
952 EngineStateController::set_physical_audio_output_state(const std::string& port_name, bool state)
953 {
954         PortStateList* output_states;
955         if (Config->get_output_auto_connect() & AutoConnectMaster) {
956                 output_states = &_current_state->stereo_out_channel_states;
957         } else {
958                 output_states = &_current_state->multi_out_channel_states;
959         }
960     
961         PortStateList::iterator target_state_iter;
962         target_state_iter = std::find(output_states->begin(), output_states->end(), PortState(port_name) );
963     
964         if (target_state_iter != output_states->end() && target_state_iter->active != state ) {
965                 target_state_iter->active = state;
966         
967                 // if StereoOut mode is used
968                 if (Config->get_output_auto_connect() & AutoConnectMaster) {
969         
970                         // get next element
971                         PortStateList::iterator next_state_iter(target_state_iter);
972             
973                         // loopback
974                         if (++next_state_iter == output_states->end() ) {
975                                 next_state_iter = output_states->begin();
976                         }
977             
978             
979                         // only two outputs should be enabled
980                         if (output_states->size() <= 2) {
981                 
982                                 target_state_iter->active = true;
983                                 next_state_iter->active = true;
984                 
985                         } else {
986                 
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;
990                                 } else {
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();
995                                                 }
996                                                 next_state_iter->active = true;
997                                         } else {
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;
1002                                         }
1003                                 }
1004                 
1005                                 // now deactivate the rest
1006                                 while (++next_state_iter != target_state_iter) {
1007                     
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) {
1012                                                         break;
1013                                                 }
1014                                         }
1015                     
1016                                         next_state_iter->active = false;
1017                                 }
1018                 
1019                         }
1020                 }
1021             
1022                 AudioEngine::instance()->reconnect_session_routes(false, true);
1023                 OutputConfigChanged();
1024         }
1025 }
1026
1027
1028 bool
1029 EngineStateController::get_physical_audio_input_state(const std::string& port_name)
1030 {
1031         bool state = false;
1032     
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) );
1036     
1037         if (found_state_iter != input_states.end() ) {
1038                 state = found_state_iter->active;
1039         }
1040     
1041         return state;
1042 }
1043
1044
1045 bool
1046 EngineStateController::get_physical_audio_output_state(const std::string& port_name)
1047 {
1048         bool state = false;
1049     
1050         PortStateList* output_states;
1051         if (Config->get_output_auto_connect() & AutoConnectMaster) {
1052                 output_states = &_current_state->stereo_out_channel_states;
1053         } else {
1054                 output_states = &_current_state->multi_out_channel_states;
1055         }
1056     
1057         PortStateList::iterator found_state_iter;
1058         found_state_iter = std::find(output_states->begin(), output_states->end(), PortState(port_name) );
1059     
1060         if (found_state_iter != output_states->end() ) {
1061                 state = found_state_iter->active;
1062         }
1063
1064         return state;
1065 }
1066
1067
1068 void
1069 EngineStateController::set_physical_midi_input_state(const std::string& port_name, bool state) {
1070     
1071         MidiPortStateList::iterator found_state_iter;
1072         found_state_iter = std::find(_midi_inputs.begin(), _midi_inputs.end(), MidiPortState(port_name) );
1073     
1074         if (found_state_iter != _midi_inputs.end() && found_state_iter->available && found_state_iter->active != state ) {
1075                 found_state_iter->active = state;
1076         
1077                 if (_session) {
1078                         // reconnect MTC inputs as well
1079                         if (found_state_iter->mtc_in) {
1080                                 _session->reconnect_mtc_ports ();
1081                         }
1082                         _session->reconnect_mmc_ports(true);
1083                 }
1084         
1085                 MIDIInputConfigChanged();
1086         }
1087 }
1088
1089
1090 void
1091 EngineStateController::set_physical_midi_output_state(const std::string& port_name, bool state) {
1092     
1093         MidiPortStateList::iterator found_state_iter;
1094         found_state_iter = std::find(_midi_outputs.begin(), _midi_outputs.end(), MidiPortState(port_name) );
1095     
1096         if (found_state_iter != _midi_outputs.end() && found_state_iter->available && found_state_iter->active != state ) {
1097                 found_state_iter->active = state;
1098         
1099                 if (_session) {
1100                         _session->reconnect_mmc_ports(false);
1101                 }
1102         
1103                 MIDIOutputConfigChanged();
1104         }
1105 }
1106
1107
1108 bool
1109 EngineStateController::get_physical_midi_input_state(const std::string& port_name, bool& scene_connected) {
1110     
1111         bool state = false;
1112     
1113         MidiPortStateList::iterator found_state_iter;
1114         found_state_iter = std::find(_midi_inputs.begin(), _midi_inputs.end(), MidiPortState(port_name) );
1115     
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;
1119         }
1120     
1121         return state;
1122 }
1123
1124
1125 bool
1126 EngineStateController::get_physical_midi_output_state(const std::string& port_name, bool& scene_connected) {
1127     
1128         bool state = false;
1129     
1130         MidiPortStateList::iterator found_state_iter;
1131         found_state_iter = std::find(_midi_outputs.begin(), _midi_outputs.end(), MidiPortState(port_name) );
1132     
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;
1136         }
1137     
1138         return state;
1139 }
1140
1141
1142 void
1143 EngineStateController::set_physical_midi_scene_in_connection_state(const std::string& port_name, bool state) {
1144     
1145         MidiPortStateList::iterator found_state_iter;
1146         found_state_iter = std::find(_midi_inputs.begin(), _midi_inputs.end(), MidiPortState(port_name) );
1147     
1148         if (found_state_iter != _midi_inputs.end() && found_state_iter->available && found_state_iter->active ) {
1149                 found_state_iter->scene_connected = state;
1150         
1151                 std::vector<std::string> ports;
1152                 ports.push_back(port_name);
1153                 MIDISceneInputConnectionChanged(ports, state);
1154         }
1155
1156 }
1157
1158
1159 void
1160 EngineStateController::set_physical_midi_scenen_out_connection_state(const std::string& port_name, bool state) {
1161    
1162         MidiPortStateList::iterator found_state_iter;
1163         found_state_iter = std::find(_midi_outputs.begin(), _midi_outputs.end(), MidiPortState(port_name) );
1164     
1165         if (found_state_iter != _midi_outputs.end() && found_state_iter->available && found_state_iter->active ) {
1166                 found_state_iter->scene_connected = state;
1167         
1168                 std::vector<std::string> ports;
1169                 ports.push_back(port_name);
1170                 MIDISceneOutputConnectionChanged(ports, state);
1171         }
1172
1173 }
1174
1175
1176 void
1177 EngineStateController::set_all_midi_scene_inputs_disconnected()
1178 {
1179         MidiPortStateList::iterator iter = _midi_inputs.begin();
1180         for (; iter != _midi_inputs.end(); ++iter) {
1181                 iter->scene_connected = false;
1182         }
1183
1184         std::vector<std::string> ports;
1185         MIDISceneInputConnectionChanged(ports, false);
1186 }
1187
1188
1189 void
1190 EngineStateController::set_all_midi_scene_outputs_disconnected()
1191 {
1192         MidiPortStateList::iterator iter = _midi_outputs.begin();
1193         for (; iter != _midi_outputs.end(); ++iter) {
1194                 iter->scene_connected = false;
1195         }
1196     
1197         std::vector<std::string> ports;
1198         MIDISceneOutputConnectionChanged(ports, false);
1199 }
1200
1201
1202 void
1203 EngineStateController::set_mtc_input(const std::string& port_name)
1204 {
1205         MidiPortStateList::iterator iter = _midi_inputs.begin();
1206         for (; iter != _midi_inputs.end(); ++iter) {
1207                 iter->mtc_in = false;
1208         
1209                 if (iter->name == port_name) {
1210                         iter->mtc_in = true;
1211             
1212                         if (_session) {
1213                                 _session->reconnect_mtc_ports ();
1214                         }
1215                 }
1216         }
1217     
1218         MTCInputChanged(port_name);
1219 }
1220
1221
1222 void
1223 EngineStateController::set_state_to_all_inputs(bool state)
1224 {
1225         bool something_changed = false;
1226     
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;
1232                 }
1233         }
1234     
1235         if (something_changed) {
1236                 AudioEngine::instance()->reconnect_session_routes(true, false);
1237                 InputConfigChanged();
1238         }
1239 }
1240
1241
1242 void
1243 EngineStateController::set_state_to_all_outputs(bool state)
1244 {
1245         // unapplicable in Stereo Out mode, just return
1246         if (Config->get_output_auto_connect() & AutoConnectMaster) {
1247                 return;
1248         }
1249     
1250         bool something_changed = false;
1251     
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;
1257                 }
1258         }
1259     
1260         if (something_changed) {
1261                 AudioEngine::instance()->reconnect_session_routes(false, true);
1262                 OutputConfigChanged();
1263         }
1264 }
1265
1266
1267 void
1268 EngineStateController::get_physical_audio_input_states(std::vector<PortState>& channel_states)
1269 {
1270         PortStateList &input_states = _current_state->input_channel_states;
1271         channel_states.assign(input_states.begin(), input_states.end());
1272 }
1273
1274
1275 void
1276 EngineStateController::get_physical_audio_output_states(std::vector<PortState>& channel_states)
1277 {
1278         PortStateList* output_states;
1279         if (Config->get_output_auto_connect() & AutoConnectMaster) {
1280                 output_states = &_current_state->stereo_out_channel_states;
1281         } else {
1282                 output_states = &_current_state->multi_out_channel_states;
1283         }
1284     
1285         channel_states.assign(output_states->begin(), output_states->end());
1286 }
1287
1288
1289 void
1290 EngineStateController::get_physical_midi_input_states (std::vector<MidiPortState>& channel_states)
1291 {
1292         channel_states.clear();
1293     
1294         MidiPortStateList::iterator iter = _midi_inputs.begin();
1295     
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);
1304                 }
1305         }    
1306 }
1307
1308 void
1309 EngineStateController::get_physical_midi_output_states (std::vector<MidiPortState>& channel_states)
1310 {
1311         channel_states.clear();
1312     
1313         MidiPortStateList::iterator iter = _midi_outputs.begin();
1314     
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);
1323                 }
1324         }
1325 }
1326
1327
1328 void
1329 EngineStateController::_on_session_loaded ()
1330 {
1331         if (!_session) {
1332                 return;
1333         }
1334     
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);
1339         
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) )
1342         {
1343                 push_current_state_to_backend(false);
1344                 SampleRateChanged(); // emit a signal
1345         }
1346 }
1347
1348
1349 void
1350 EngineStateController::_on_sample_rate_change(framecnt_t new_sample_rate)
1351 {
1352         if (_current_state->sample_rate != new_sample_rate) {
1353         
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 ();
1359                 }
1360         
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);
1366                         DeviceError();
1367                 }
1368         }
1369     
1370         SampleRateChanged(); // emit a signal
1371 }
1372
1373
1374 void
1375 EngineStateController::_on_buffer_size_change(pframes_t new_buffer_size)
1376 {
1377         if (_current_state->buffer_size != new_buffer_size) {
1378                 _current_state->buffer_size = new_buffer_size;
1379         }
1380     
1381         BufferSizeChanged(); // emit a signal
1382 }
1383
1384
1385 void
1386 EngineStateController::_on_device_list_change()
1387 {
1388         bool current_device_disconnected = false;
1389     
1390         boost::shared_ptr<AudioBackend> backend = AudioEngine::instance()->current_backend();
1391         assert(backend);
1392     
1393         std::vector<AudioBackend::DeviceStatus> device_vector = backend->enumerate_devices();
1394     
1395         // find out out if current device is still available if it's not None
1396         if (_current_state->device_name != "None")
1397         {
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) );
1400         
1401                 // if current device is not available any more - switch to None device
1402                 if (device_iter == device_vector.end() ) {
1403             
1404                         StateList::iterator found_state_iter = find_if (_states.begin(), _states.end(),
1405                                                                         State::StatePredicate(_current_state->backend_name, "None") );
1406             
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();
1411                         } else {
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);
1418                         }
1419             
1420                         push_current_state_to_backend(true);
1421                         current_device_disconnected = true;
1422                 }
1423         } else {
1424                 // if the device which was active before is available now - switch to it
1425         
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) );
1428         
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) );
1433             
1434                         if (found_state_iter != _states.end() ) {
1435                 
1436                                 boost::shared_ptr<State> previous_state (_current_state);
1437                                 _current_state = *found_state_iter;
1438                 
1439                                 if (_validate_current_device_state() ) {
1440                                         push_current_state_to_backend(false);
1441                                 } else {
1442                                         // cannot use this device right now
1443                                         _last_used_real_device.clear();
1444                                         _current_state = previous_state;
1445                                 }
1446                         }
1447                 }
1448         }
1449     
1450         DeviceListChanged(current_device_disconnected); // emit a signal    
1451 }
1452
1453
1454 void
1455 EngineStateController::_update_device_channels_state()
1456 {
1457         boost::shared_ptr<AudioBackend> backend = AudioEngine::instance()->current_backend();
1458         assert(backend);
1459     
1460         // update audio input states
1461         std::vector<std::string> phys_audio_inputs;
1462         backend->get_physical_inputs(DataType::AUDIO, phys_audio_inputs);
1463     
1464         PortStateList new_input_states;
1465         PortStateList &input_states = _current_state->input_channel_states;
1466     
1467         std::vector<std::string>::const_iterator input_iter = phys_audio_inputs.begin();
1468         for (; input_iter != phys_audio_inputs.end(); ++input_iter) {
1469         
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);
1473         
1474                 if (found_state_iter != input_states.end() ) {
1475                         new_input_states.push_back(*found_state_iter);
1476                 } else {
1477                         new_input_states.push_back(state);
1478                 }
1479         }
1480         _current_state->input_channel_states = new_input_states;
1481     
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);
1485     
1486         PortStateList new_output_states;
1487         PortStateList &output_multi_states = _current_state->multi_out_channel_states;
1488     
1489         std::vector<std::string>::const_iterator output_iter = phys_audio_outputs.begin();
1490         for (; output_iter != phys_audio_outputs.end(); ++output_iter) {
1491         
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);
1495         
1496                 if (found_state_iter != output_multi_states.end() ) {
1497                         new_output_states.push_back(*found_state_iter);
1498                 } else {
1499                         new_output_states.push_back(state);
1500                 }
1501         }
1502     
1503         _current_state->multi_out_channel_states = new_output_states;
1504     
1505         // update audio output states (stereo out mode)
1506         new_output_states.clear();
1507         PortStateList &output_stereo_states = _current_state->stereo_out_channel_states;
1508     
1509         output_iter = phys_audio_outputs.begin();
1510         for (; output_iter != phys_audio_outputs.end(); ++output_iter) {
1511         
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);
1515         
1516                 if (found_state_iter != output_stereo_states.end() ) {
1517                         new_output_states.push_back(*found_state_iter);
1518                 } else {
1519                         new_output_states.push_back(state);
1520                 }
1521         }
1522
1523         _current_state->stereo_out_channel_states = new_output_states;
1524         _refresh_stereo_out_channel_states();
1525     
1526     
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;
1537         }
1538     
1539         for (iter = _midi_outputs.begin(); iter != _midi_outputs.end(); ++iter) {
1540                 iter->available = false;
1541         }
1542     
1543         // update midi input ports
1544         std::vector<std::string> phys_midi_inputs;
1545         backend->get_physical_inputs(DataType::MIDI, phys_midi_inputs);
1546     
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) {
1549         
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);
1554         
1555                 if (found_state_iter != _midi_inputs.end() ) {
1556                         found_state_iter->available = true;
1557                 } else {
1558                         _midi_inputs.push_back(state);
1559                 }
1560         }
1561     
1562         // update midi output ports
1563         std::vector<std::string> phys_midi_outputs;
1564         backend->get_physical_outputs(DataType::MIDI, phys_midi_outputs);
1565     
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) {
1568         
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);
1573         
1574                 if (found_state_iter != _midi_outputs.end() ) {
1575                         found_state_iter->available = true;
1576                 } else {
1577                         _midi_outputs.push_back(state);
1578                 }
1579         }
1580 }
1581
1582
1583 void
1584 EngineStateController::_refresh_stereo_out_channel_states()
1585 {
1586         PortStateList &output_states = _current_state->stereo_out_channel_states;
1587         PortStateList::iterator active_iter = output_states.begin();
1588
1589         for (; active_iter != output_states.end(); ++active_iter) {
1590                 if (active_iter->active) {
1591                         break;
1592                 }
1593         }
1594     
1595         uint32_t pending_active_channels = 2;
1596         PortStateList::iterator iter = output_states.begin();
1597         // if found active
1598         if (active_iter != output_states.end() ) {
1599                 iter = active_iter;
1600                 if (++iter == output_states.end() ) {
1601                         iter = output_states.begin();
1602                 }
1603             
1604                 (iter++)->active = true;
1605                 pending_active_channels = 0;
1606         }
1607
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;
1613                 } else {
1614                         iter->active = false;
1615                 }
1616         }
1617 }
1618
1619
1620 void
1621 EngineStateController::_on_engine_running ()
1622 {
1623         AudioEngine::instance()->reconnect_session_routes(true, true);
1624         _current_state->active = true;
1625     
1626         EngineRunning(); // emit a signal
1627 }
1628
1629
1630 void
1631 EngineStateController::_on_engine_stopped ()
1632 {
1633         EngineStopped();
1634 }
1635
1636
1637 void
1638 EngineStateController::_on_engine_halted ()
1639 {
1640         EngineHalted();
1641 }
1642
1643
1644 void
1645 EngineStateController::_on_device_error()
1646 {
1647         set_new_device_as_current ("None");
1648         push_current_state_to_backend(true);
1649         DeviceListChanged(false);
1650         DeviceError();
1651 }
1652
1653
1654 void
1655 EngineStateController::_on_parameter_changed (const std::string& parameter_name)
1656 {
1657         if (parameter_name == "output-auto-connect") {
1658         
1659                 AudioEngine::instance()->reconnect_session_routes(false, true);
1660                 OutputConfigChanged(); // emit a signal
1661                 OutputConnectionModeChanged(); // emit signal
1662         }
1663 }
1664
1665
1666 void
1667 EngineStateController::_on_ports_registration_update ()
1668 {
1669         _update_device_channels_state();
1670     
1671         // update MIDI connections
1672         if (_session) {
1673                 _session->reconnect_midi_scene_ports (true);
1674                 _session->reconnect_midi_scene_ports (false);
1675         
1676                 _session->reconnect_mtc_ports ();
1677         
1678                 _session->reconnect_mmc_ports (true);
1679                 _session->reconnect_mmc_ports (false);
1680         }
1681     
1682         PortRegistrationChanged(); // emit a signal
1683 }
1684
1685
1686 bool
1687 EngineStateController::push_current_state_to_backend(bool start)
1688 {
1689         boost::shared_ptr<AudioBackend> backend = AudioEngine::instance()->current_backend();
1690         
1691         if (!backend) {
1692                 return false;
1693         }
1694     
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() );
1699     
1700         bool was_running = AudioEngine::instance()->running();
1701     
1702         Glib::Threads::RecMutex::Lock sl (AudioEngine::instance()->state_lock() );
1703         if (state_changed) {
1704
1705                 if (was_running) {
1706                         if (AudioEngine::instance()->stop () ) {
1707                                 return false;
1708                         }
1709                 }
1710
1711                 int result = 0;
1712                 {
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;
1716                         }
1717         
1718                         if (!result ) {
1719                                 std::cout << "EngineStateController::Setting device sample rate " << _current_state->sample_rate << std::endl;
1720                                 result = backend->set_sample_rate (_current_state->sample_rate);
1721                                 
1722                                 if (result) {
1723                                         error << string_compose (_("Cannot set sample rate to %1"), get_current_sample_rate()) << endmsg;
1724                                 }
1725                         }
1726         
1727                         if (!result ) {
1728                                 std::cout << "EngineStateController::Setting device buffer size " << _current_state->buffer_size << std::endl;
1729                                 result = backend->set_buffer_size (_current_state->buffer_size);
1730
1731                                 if (result) {
1732                                         error << string_compose (_("Cannot set buffer size to %1"), get_current_buffer_size()) << endmsg;
1733                                 }
1734                         }
1735                 }
1736         
1737                 if (result) // error during device setup
1738                 {
1739                         //switch to None device and notify about the issue
1740                         set_new_device_as_current ("None");
1741                         DeviceListChanged(false);
1742                         DeviceError();
1743                 }
1744
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
1748                         return true;
1749                 }
1750         }
1751     
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);
1758                         DeviceError();
1759                         return false;
1760                 }
1761         }
1762     
1763         save_audio_midi_settings();
1764     
1765         return true;
1766 }