mirror of
https://github.com/Ardour/ardour.git
synced 2026-01-09 15:15:41 +01:00
[Summary] Implemented Engine state controller
[Reviewed by] Conceptual review has been done with VKamishniy [git-p4: depot-paths = "//Abdaw/dev_main/tracks/": change = 460058]
This commit is contained in:
parent
f99d057421
commit
50b5a3df07
10 changed files with 853 additions and 338 deletions
|
|
@ -95,6 +95,7 @@ typedef uint64_t microseconds_t;
|
|||
#include "add_route_dialog.h"
|
||||
#include "ambiguous_file_dialog.h"
|
||||
#include "ardour_ui.h"
|
||||
#include "engine_state_controller.h"
|
||||
#include "audio_clock.h"
|
||||
#include "big_clock_window.h"
|
||||
#include "bundle_manager.h"
|
||||
|
|
@ -283,7 +284,7 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir)
|
|||
|
||||
/* handle Audio/MIDI setup when session requires it */
|
||||
|
||||
ARDOUR::Session::AudioEngineSetupRequired.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::do_tracks_control_panel, this, _1));
|
||||
ARDOUR::Session::AudioEngineSetupRequired.connect_same_thread (forever_connections, boost::bind (&ARDOUR_UI::do_engine_setup, this, _1));
|
||||
|
||||
/* handle sr mismatch with a dialog (PROBLEM: needs to return a value and thus cannot be x-thread) */
|
||||
|
||||
|
|
@ -389,7 +390,15 @@ ARDOUR_UI::ARDOUR_UI (int *argcp, char **argvp[], const char* localedir)
|
|||
|
||||
DPIReset.connect (sigc::mem_fun (*this, &ARDOUR_UI::resize_text_widgets));
|
||||
|
||||
// start the engine:
|
||||
// initialize engin state controller
|
||||
EngineStateController::instance();
|
||||
|
||||
// attach to the engine signals
|
||||
attach_to_engine ();
|
||||
|
||||
// start the engine pushing state from the state controller
|
||||
EngineStateController::instance()->push_current_state_to_backend(true);
|
||||
}
|
||||
|
||||
GlobalPortMatrixWindow*
|
||||
|
|
@ -426,7 +435,7 @@ ARDOUR_UI::engine_running ()
|
|||
|
||||
update_disk_space ();
|
||||
update_cpu_load ();
|
||||
update_sample_rate (AudioEngine::instance()->sample_rate());
|
||||
update_sample_rate (EngineStateController::instance()->get_current_sample_rate() );
|
||||
update_timecode_format ();
|
||||
}
|
||||
|
||||
|
|
@ -1152,7 +1161,7 @@ ARDOUR_UI::update_sample_rate (framecnt_t)
|
|||
|
||||
} else {
|
||||
|
||||
framecnt_t rate = AudioEngine::instance()->sample_rate();
|
||||
framecnt_t rate = EngineStateController::instance()->get_current_sample_rate();
|
||||
|
||||
if (rate == 0) {
|
||||
/* no sample rate available */
|
||||
|
|
@ -4392,19 +4401,9 @@ ARDOUR_UI::reset_route_peak_display (Route* route)
|
|||
|
||||
#define dbg_msg(a) MessageDialog(a, PROGRAM_NAME).run();
|
||||
int
|
||||
ARDOUR_UI::do_tracks_control_panel (uint32_t desired_sample_rate)
|
||||
ARDOUR_UI::do_engine_setup (framecnt_t desired_sample_rate)
|
||||
{
|
||||
tracks_control_panel->set_desired_sample_rate (desired_sample_rate);
|
||||
tracks_control_panel->set_position (WIN_POS_CENTER);
|
||||
|
||||
switch (tracks_control_panel->run()) {
|
||||
case Gtk::RESPONSE_OK:
|
||||
return 0;
|
||||
case Gtk::RESPONSE_APPLY:
|
||||
return 0;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
ARDOUR::EngineStateController::instance()->set_desired_sample_rate (desired_sample_rate);
|
||||
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -758,7 +758,7 @@ class ARDOUR_UI : public Gtkmm2ext::UI, public ARDOUR::SessionHandlePtr
|
|||
std::string _announce_string;
|
||||
void check_announcements ();
|
||||
|
||||
int do_tracks_control_panel(uint32_t);
|
||||
int do_engine_setup(ARDOUR::framecnt_t desired_sample_rate);
|
||||
};
|
||||
|
||||
#endif /* __ardour_gui_h__ */
|
||||
|
|
|
|||
544
gtk2_ardour/engine_state_controller.cc
Normal file
544
gtk2_ardour/engine_state_controller.cc
Normal file
|
|
@ -0,0 +1,544 @@
|
|||
//
|
||||
// engine_state_controller.cpp
|
||||
// Tracks
|
||||
//
|
||||
// Created by Grygorii Zharun on 4/30/14.
|
||||
// Copyright (c) 2014 Waves. All rights reserved.
|
||||
//
|
||||
|
||||
#include "engine_state_controller.h"
|
||||
|
||||
#include "ardour_ui.h"
|
||||
#include "ardour/audioengine.h"
|
||||
#include "pbd/error.h"
|
||||
#include "i18n.h"
|
||||
#include "gui_thread.h"
|
||||
|
||||
using namespace ARDOUR;
|
||||
using namespace PBD;
|
||||
|
||||
namespace {
|
||||
|
||||
struct DevicePredicate
|
||||
{
|
||||
DevicePredicate(const std::string& device_name)
|
||||
: _device_name(device_name)
|
||||
{}
|
||||
|
||||
bool operator()(const AudioBackend::DeviceStatus& rhs)
|
||||
{
|
||||
return _device_name == rhs.name;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string _device_name;
|
||||
};
|
||||
}
|
||||
|
||||
EngineStateController*
|
||||
EngineStateController::instance()
|
||||
{
|
||||
static EngineStateController instance;
|
||||
return &instance;
|
||||
}
|
||||
|
||||
|
||||
EngineStateController::EngineStateController()
|
||||
: _current_state()
|
||||
, _last_used_real_device("")
|
||||
, _desired_sample_rate(0)
|
||||
, _have_control(false)
|
||||
|
||||
{
|
||||
AudioEngine::instance ()->Running.connect (running_connection, MISSING_INVALIDATOR, boost::bind (&EngineStateController::_on_engine_running, this), gui_context());
|
||||
AudioEngine::instance ()->Stopped.connect (stopped_connection, MISSING_INVALIDATOR, boost::bind (&EngineStateController::_on_engine_stopped, this), gui_context());
|
||||
AudioEngine::instance ()->Halted.connect (stopped_connection, MISSING_INVALIDATOR, boost::bind (&EngineStateController::_on_engine_stopped, this), gui_context());
|
||||
|
||||
/* Subscribe for udpates from AudioEngine */
|
||||
AudioEngine::instance()->BufferSizeChanged.connect (update_connections, MISSING_INVALIDATOR, boost::bind (&EngineStateController::_on_sample_rate_change, this, _1), gui_context());
|
||||
AudioEngine::instance()->BufferSizeChanged.connect (update_connections, MISSING_INVALIDATOR, boost::bind (&EngineStateController::_on_buffer_size_change, this, _1), gui_context());
|
||||
AudioEngine::instance()->DeviceListChanged.connect (update_connections, MISSING_INVALIDATOR, boost::bind (&EngineStateController::_on_device_list_change, this), gui_context());
|
||||
|
||||
_deserialize_and_load_states();
|
||||
_set_last_active_state_as_current();
|
||||
|
||||
// now push the sate to the backend
|
||||
push_current_state_to_backend(false);
|
||||
}
|
||||
|
||||
|
||||
EngineStateController::~EngineStateController()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
EngineStateController::_deserialize_and_load_states()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
EngineStateController::_serialize_and_save_current_state()
|
||||
{
|
||||
// **** add code to save the state list to the file ****
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
EngineStateController::_set_last_active_state_as_current()
|
||||
{
|
||||
// if we have no saved state load default values
|
||||
if (!_states.empty() ) {
|
||||
} else {
|
||||
_current_state = boost::shared_ptr<State>(new State() );
|
||||
|
||||
std::vector<const AudioBackendInfo*> backends = AudioEngine::instance()->available_backends();
|
||||
|
||||
if (!backends.empty() )
|
||||
{
|
||||
|
||||
if (set_new_backend_as_current(backends.front()->name ) ) {
|
||||
_current_state->device_name = "None";
|
||||
_validate_current_device_state();
|
||||
_states.push_front(_current_state);
|
||||
} else {
|
||||
std::cerr << "\tfailed to set backend [" << backends.front()->name << "]\n";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
EngineStateController::_validate_current_device_state()
|
||||
{
|
||||
boost::shared_ptr<AudioBackend> backend = AudioEngine::instance()->current_backend();
|
||||
assert(backend);
|
||||
|
||||
// check if device parameters from the state record are still valid
|
||||
// validate sample rate
|
||||
std::vector<float> sample_rates = backend->available_sample_rates (_current_state->device_name);
|
||||
|
||||
// check if session desired sample rate (if it's set) could be used with this device
|
||||
if (_desired_sample_rate != 0) {
|
||||
std::vector<float>::iterator sr_iter = std::find (sample_rates.begin(), sample_rates.end(), (float)_desired_sample_rate);
|
||||
|
||||
if (sr_iter != sample_rates.end() ) {
|
||||
_current_state->sample_rate = _desired_sample_rate;
|
||||
} else {
|
||||
_current_state->sample_rate = backend->default_sample_rate();
|
||||
}
|
||||
|
||||
} else {
|
||||
// check if current sample rate is supported because we have no session desired sample rate value
|
||||
std::vector<float>::iterator sr_iter = std::find (sample_rates.begin(), sample_rates.end(), (float)_current_state->sample_rate);
|
||||
// switch to default if current sample rate is not supported
|
||||
if (sr_iter == sample_rates.end() ) {
|
||||
|
||||
_current_state->sample_rate = backend->default_sample_rate();
|
||||
}
|
||||
}
|
||||
|
||||
// validate buffer size
|
||||
std::vector<pframes_t> buffer_sizes = backend->available_buffer_sizes (_current_state->device_name);
|
||||
// check if buffer size is supported
|
||||
std::vector<pframes_t>::iterator bs_iter = std::find (buffer_sizes.begin(), buffer_sizes.end(), _current_state->buffer_size);
|
||||
// switch to default if not supported
|
||||
if (bs_iter == buffer_sizes.end() ) {
|
||||
_current_state->buffer_size = backend->default_buffer_size ();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const std::string&
|
||||
EngineStateController::get_current_backend_name() const
|
||||
{
|
||||
return _current_state->backend_name;
|
||||
}
|
||||
|
||||
|
||||
const std::string&
|
||||
EngineStateController::get_current_device_name() const
|
||||
{
|
||||
return _current_state->device_name;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
EngineStateController::available_backends(std::vector<const AudioBackendInfo*>& available_backends)
|
||||
{
|
||||
available_backends = AudioEngine::instance()->available_backends();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
EngineStateController::enumerate_devices (std::vector<AudioBackend::DeviceStatus>& device_vector) const
|
||||
{
|
||||
boost::shared_ptr<AudioBackend> backend = AudioEngine::instance()->current_backend();
|
||||
assert(backend);
|
||||
device_vector = backend->enumerate_devices();
|
||||
}
|
||||
|
||||
|
||||
framecnt_t
|
||||
EngineStateController::get_current_sample_rate() const
|
||||
{
|
||||
return _current_state->sample_rate;
|
||||
}
|
||||
|
||||
|
||||
framecnt_t
|
||||
EngineStateController::get_default_sample_rate() const
|
||||
{
|
||||
boost::shared_ptr<AudioBackend> backend = AudioEngine::instance()->current_backend();
|
||||
assert(backend);
|
||||
return backend->default_sample_rate();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
EngineStateController::available_sample_rates_for_current_device(std::vector<float>& sample_rates) const
|
||||
{
|
||||
boost::shared_ptr<AudioBackend> backend = AudioEngine::instance()->current_backend();
|
||||
assert(backend);
|
||||
sample_rates = backend->available_sample_rates (_current_state->device_name);
|
||||
}
|
||||
|
||||
|
||||
uint32_t
|
||||
EngineStateController::get_current_buffer_size() const
|
||||
{
|
||||
return _current_state->buffer_size;
|
||||
}
|
||||
|
||||
|
||||
uint32_t
|
||||
EngineStateController::get_default_buffer_size() const
|
||||
{
|
||||
boost::shared_ptr<AudioBackend> backend = AudioEngine::instance()->current_backend();
|
||||
assert(backend);
|
||||
return backend->default_buffer_size();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
EngineStateController::available_buffer_sizes_for_current_device(std::vector<pframes_t>& buffer_sizes) const
|
||||
{
|
||||
boost::shared_ptr<AudioBackend> backend = AudioEngine::instance()->current_backend();
|
||||
assert(backend);
|
||||
buffer_sizes = backend->available_buffer_sizes (_current_state->device_name);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
EngineStateController::set_new_backend_as_current(const std::string& backend_name)
|
||||
{
|
||||
if (backend_name == AudioEngine::instance()->current_backend_name () ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
boost::shared_ptr<AudioBackend> backend = AudioEngine::instance()->set_backend (backend_name, "ardour", "");
|
||||
if (backend)
|
||||
{
|
||||
StateList::iterator found_state_iter = find_if (_states.begin(), _states.end(),
|
||||
State::StatePredicate(backend_name, "None") );
|
||||
|
||||
if (found_state_iter != _states.end() ) {
|
||||
// we found a record for new engine with None device - switch to it
|
||||
_current_state = *found_state_iter;
|
||||
|
||||
} else {
|
||||
// create new record for this engine with default device
|
||||
_current_state = boost::shared_ptr<State>(new State() );
|
||||
_current_state->backend_name = backend_name;
|
||||
_current_state->device_name = "None";
|
||||
_validate_current_device_state();
|
||||
_states.push_front(_current_state);
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
EngineStateController::set_new_current_device_in_controller(const std::string& device_name)
|
||||
{
|
||||
if (_current_state->device_name == device_name) {
|
||||
return true;
|
||||
}
|
||||
|
||||
_last_used_real_device.clear();
|
||||
|
||||
if (device_name != "None") {
|
||||
_last_used_real_device = device_name;
|
||||
}
|
||||
|
||||
boost::shared_ptr<AudioBackend> backend = AudioEngine::instance()->current_backend();
|
||||
assert(backend);
|
||||
|
||||
std::vector<AudioBackend::DeviceStatus> device_vector = backend->enumerate_devices();
|
||||
|
||||
// validate the device
|
||||
std::vector<AudioBackend::DeviceStatus>::iterator device_iter;
|
||||
device_iter = std::find_if (device_vector.begin(), device_vector.end(), DevicePredicate(device_name) );
|
||||
|
||||
// device is available
|
||||
if (device_iter != device_vector.end() ) {
|
||||
|
||||
// look through state list and find the record for this device and current engine
|
||||
StateList::iterator found_state_iter = find_if (_states.begin(), _states.end(),
|
||||
State::StatePredicate(backend->name(), device_name) );
|
||||
|
||||
if (found_state_iter != _states.end() )
|
||||
{
|
||||
// we found a record for current engine and provided device name - switch to it
|
||||
_current_state = *found_state_iter;
|
||||
_validate_current_device_state();
|
||||
|
||||
} else {
|
||||
|
||||
// the record is not found, create new one
|
||||
_current_state = boost::shared_ptr<State>(new State() );
|
||||
|
||||
_current_state->backend_name = backend->name();
|
||||
_current_state->device_name = device_name;
|
||||
_validate_current_device_state();
|
||||
_states.push_front(_current_state);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// device is not supported by current backend
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool
|
||||
EngineStateController::set_new_sample_rate_in_controller(framecnt_t sample_rate)
|
||||
{
|
||||
if (_current_state->sample_rate == sample_rate) {
|
||||
return true;
|
||||
}
|
||||
|
||||
boost::shared_ptr<AudioBackend> backend = AudioEngine::instance()->current_backend();
|
||||
assert(backend);
|
||||
|
||||
std::vector<float> sample_rates = backend->available_sample_rates (_current_state->device_name);
|
||||
std::vector<float>::iterator iter = std::find (sample_rates.begin(), sample_rates.end(), (float)sample_rate);
|
||||
|
||||
if (iter != sample_rates.end() ) {
|
||||
_current_state->sample_rate = sample_rate;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
bool
|
||||
EngineStateController::set_new_buffer_size_in_controller(pframes_t buffer_size)
|
||||
{
|
||||
if (_current_state->buffer_size == buffer_size) {
|
||||
return true;
|
||||
}
|
||||
|
||||
boost::shared_ptr<AudioBackend> backend = AudioEngine::instance()->current_backend();
|
||||
assert(backend);
|
||||
|
||||
std::vector<uint32_t> buffer_sizes = backend->available_buffer_sizes (_current_state->device_name);
|
||||
std::vector<uint32_t>::iterator iter = std::find (buffer_sizes.begin(), buffer_sizes.end(), buffer_size);
|
||||
|
||||
if (iter != buffer_sizes.end() ) {
|
||||
_current_state->buffer_size = buffer_size;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
EngineStateController::_on_sample_rate_change(framecnt_t new_sample_rate)
|
||||
{
|
||||
set_new_sample_rate_in_controller(new_sample_rate);
|
||||
|
||||
SampleRateChanged(new_sample_rate); // emit a signal
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
EngineStateController::_on_buffer_size_change(pframes_t new_buffer_size)
|
||||
{
|
||||
set_new_buffer_size_in_controller(new_buffer_size);
|
||||
|
||||
BufferSizeChanged(new_buffer_size); // emit a signal
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
EngineStateController::_on_device_list_change()
|
||||
{
|
||||
boost::shared_ptr<AudioBackend> backend = AudioEngine::instance()->current_backend();
|
||||
assert(backend);
|
||||
|
||||
std::vector<AudioBackend::DeviceStatus> device_vector = backend->enumerate_devices();
|
||||
|
||||
// find out out if current device is still available if it's not None
|
||||
if (_current_state->device_name != "None")
|
||||
{
|
||||
std::vector<AudioBackend::DeviceStatus>::iterator device_iter;
|
||||
device_iter = std::find_if (device_vector.begin(), device_vector.end(), DevicePredicate(_current_state->device_name) );
|
||||
|
||||
// if current device is not available any more - switch to None device
|
||||
if (device_iter == device_vector.end() ) {
|
||||
|
||||
StateList::iterator found_state_iter = find_if (_states.begin(), _states.end(),
|
||||
State::StatePredicate(_current_state->backend_name, "None") );
|
||||
|
||||
if (found_state_iter != _states.end() ) {
|
||||
// found the record - switch to it
|
||||
_current_state = *found_state_iter;
|
||||
} else {
|
||||
// create new record for this engine with default device
|
||||
_current_state = boost::shared_ptr<State>(new State() );
|
||||
_current_state->backend_name = backend->name();
|
||||
_current_state->device_name = "None";
|
||||
_validate_current_device_state();
|
||||
_states.push_front(_current_state);
|
||||
}
|
||||
|
||||
push_current_state_to_backend(false);
|
||||
}
|
||||
} else {
|
||||
// if the device which was active before is available now - switch to it
|
||||
|
||||
std::vector<AudioBackend::DeviceStatus>::iterator device_iter;
|
||||
device_iter = std::find_if (device_vector.begin(), device_vector.end(), DevicePredicate(_last_used_real_device) );
|
||||
|
||||
if (device_iter != device_vector.end() ) {
|
||||
StateList::iterator found_state_iter = find_if (_states.begin(), _states.end(),
|
||||
State::StatePredicate(_current_state->backend_name,
|
||||
_last_used_real_device) );
|
||||
|
||||
if (found_state_iter != _states.end() ) {
|
||||
_current_state = *found_state_iter;
|
||||
_validate_current_device_state();
|
||||
|
||||
push_current_state_to_backend(false);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
DeviceListChanged(); // emit a signal
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
EngineStateController::_on_engine_running ()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
EngineStateController::_on_engine_stopped ()
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
EngineStateController::push_current_state_to_backend(bool start)
|
||||
{
|
||||
boost::shared_ptr<AudioBackend> backend = AudioEngine::instance()->current_backend();
|
||||
|
||||
if (!backend) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// check if anything changed
|
||||
bool state_changed = (_current_state->device_name != backend->device_name() ) ||
|
||||
(_current_state->sample_rate != backend->sample_rate() ) ||
|
||||
(_current_state->buffer_size != backend->buffer_size() );
|
||||
|
||||
bool was_running = AudioEngine::instance()->running();
|
||||
|
||||
if (state_changed) {
|
||||
|
||||
if (was_running) {
|
||||
if (ARDOUR_UI::instance()->disconnect_from_engine () ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if ((_current_state->device_name != backend->device_name()) && backend->set_device_name (_current_state->device_name)) {
|
||||
error << string_compose (_("Cannot set device name to %1"), get_current_device_name()) << endmsg;
|
||||
}
|
||||
|
||||
if (backend->set_sample_rate (_current_state->sample_rate )) {
|
||||
error << string_compose (_("Cannot set sample rate to %1"), get_current_sample_rate()) << endmsg;
|
||||
}
|
||||
|
||||
if (backend->set_buffer_size (_current_state->buffer_size )) {
|
||||
error << string_compose (_("Cannot set buffer size to %1"), get_current_buffer_size()) << endmsg;
|
||||
}
|
||||
|
||||
//if (backend->set_input_channels (get_input_channels())) {
|
||||
// error << string_compose (_("Cannot set input channels to %1"), get_input_channels()) << endmsg;
|
||||
// return -1;
|
||||
//}
|
||||
|
||||
//if (backend->set_output_channels (get_output_channels())) {
|
||||
// error << string_compose (_("Cannot set output channels to %1"), get_output_channels()) << endmsg;
|
||||
// return -1;
|
||||
//}
|
||||
|
||||
//if (backend->set_systemic_input_latency (get_input_latency())) {
|
||||
// error << string_compose (_("Cannot set input latency to %1"), get_input_latency()) << endmsg;
|
||||
// return -1;
|
||||
//}
|
||||
|
||||
//if (backend->set_systemic_output_latency (get_output_latency())) {
|
||||
// error << string_compose (_("Cannot set output latency to %1"), get_output_latency()) << endmsg;
|
||||
// return -1;
|
||||
//}
|
||||
}
|
||||
|
||||
_serialize_and_save_current_state();
|
||||
|
||||
if(start || (was_running && state_changed) ) {
|
||||
if (ARDOUR_UI::instance()->reconnect_to_engine () ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
EngineStateController::set_desired_sample_rate(framecnt_t session_desired_sr)
|
||||
{
|
||||
if (session_desired_sr == 0 || session_desired_sr == _desired_sample_rate) {
|
||||
return;
|
||||
}
|
||||
|
||||
_desired_sample_rate = session_desired_sr;
|
||||
_validate_current_device_state();
|
||||
|
||||
// if we swithced to new desired sample rate successfuly - push the new state to the backend
|
||||
if (_current_state->sample_rate == session_desired_sr) {
|
||||
push_current_state_to_backend(false);
|
||||
}
|
||||
}
|
||||
|
||||
172
gtk2_ardour/engine_state_controller.h
Normal file
172
gtk2_ardour/engine_state_controller.h
Normal file
|
|
@ -0,0 +1,172 @@
|
|||
//
|
||||
// engine_state_controller.h
|
||||
// Tracks
|
||||
//
|
||||
// Created by Grygorii Zharun on 4/30/14.
|
||||
// Copyright (c) 2014 Waves. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef __gtk2_ardour__engine_state_controller__
|
||||
#define __gtk2_ardour__engine_state_controller__
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "ardour/types.h"
|
||||
#include "ardour/audio_backend.h"
|
||||
|
||||
namespace ARDOUR {
|
||||
|
||||
class AudioBackendInfo;
|
||||
|
||||
class EngineStateController
|
||||
{
|
||||
public:
|
||||
static EngineStateController* instance();
|
||||
|
||||
//Interfaces
|
||||
void available_backends(std::vector<const AudioBackendInfo*>&);
|
||||
|
||||
const std::string& get_current_backend_name() const;
|
||||
|
||||
const std::string& get_current_device_name() const;
|
||||
void change_current_device_to(const std::string&) const;
|
||||
void enumerate_devices (std::vector<ARDOUR::AudioBackend::DeviceStatus>&) const;
|
||||
|
||||
ARDOUR::framecnt_t get_current_sample_rate() const;
|
||||
ARDOUR::framecnt_t get_default_sample_rate() const;
|
||||
void available_sample_rates_for_current_device(std::vector<float>&) const;
|
||||
|
||||
ARDOUR::pframes_t get_current_buffer_size() const;
|
||||
ARDOUR::pframes_t get_default_buffer_size() const;
|
||||
void available_buffer_sizes_for_current_device(std::vector<ARDOUR::pframes_t>&) const;
|
||||
|
||||
bool is_setup_required() const {return ARDOUR::AudioEngine::instance()->setup_required (); }
|
||||
|
||||
// set parameters inside the controller,
|
||||
// the state of engine won't change untill we make a "push" of this state to the backend
|
||||
// NOTE: Use push_state_to_backend() method to update backend with the most recent controller state
|
||||
bool set_new_current_device_in_controller(const std::string& device_name);
|
||||
bool set_new_sample_rate_in_controller(framecnt_t);
|
||||
bool set_new_buffer_size_in_controller(pframes_t);
|
||||
|
||||
|
||||
// push current controller state to backend
|
||||
bool push_current_state_to_backend(bool);
|
||||
// switch engine to new backend
|
||||
bool set_new_backend_as_current(const std::string&);
|
||||
// switch backend to session sample rate
|
||||
void set_desired_sample_rate(framecnt_t);
|
||||
|
||||
|
||||
//SIGNALS
|
||||
/* this signal is emitted if the sample rate changes */
|
||||
PBD::Signal1<void, ARDOUR::framecnt_t> SampleRateChanged;
|
||||
|
||||
/* this signal is emitted if the buffer size changes */
|
||||
PBD::Signal1<void, ARDOUR::pframes_t> BufferSizeChanged;
|
||||
|
||||
/* this signal is emitted if the device list changes */
|
||||
PBD::Signal0<void> DeviceListChanged;
|
||||
|
||||
private:
|
||||
|
||||
EngineStateController(); // singleton
|
||||
~EngineStateController(); // singleton
|
||||
EngineStateController(const EngineStateController& ); // prohibited
|
||||
EngineStateController& operator=(const EngineStateController&); // prohibited
|
||||
|
||||
// data types:
|
||||
struct State {
|
||||
std::string backend_name;
|
||||
std::string device_name;
|
||||
ARDOUR::framecnt_t sample_rate;
|
||||
ARDOUR::pframes_t buffer_size;
|
||||
uint32_t input_latency;
|
||||
uint32_t output_latency;
|
||||
uint32_t input_channels;
|
||||
uint32_t output_channels;
|
||||
bool active;
|
||||
std::string midi_option;
|
||||
|
||||
State()
|
||||
: input_latency (0)
|
||||
, output_latency (0)
|
||||
, input_channels (0)
|
||||
, output_channels (0)
|
||||
, active (false)
|
||||
{
|
||||
}
|
||||
|
||||
bool operator==(const State& rhs)
|
||||
{
|
||||
return (backend_name == rhs.backend_name) && (device_name == rhs.device_name);
|
||||
}
|
||||
|
||||
// predicates for search
|
||||
struct StatePredicate
|
||||
{
|
||||
StatePredicate(const std::string& backend_name, const std::string& device_name)
|
||||
: _backend_name (backend_name)
|
||||
, _device_name (device_name)
|
||||
{}
|
||||
|
||||
bool operator()(boost::shared_ptr<ARDOUR::EngineStateController::State> rhs)
|
||||
{
|
||||
return (_backend_name == rhs->backend_name) && (_device_name == rhs->device_name);
|
||||
}
|
||||
|
||||
private:
|
||||
std::string _backend_name;
|
||||
std::string _device_name;
|
||||
};
|
||||
};
|
||||
|
||||
typedef boost::shared_ptr<State> StatePtr;
|
||||
typedef std::list<StatePtr> StateList;
|
||||
|
||||
// state control methods////////////////
|
||||
void _deserialize_and_load_states();
|
||||
void _serialize_and_save_current_state();
|
||||
// sets last active state as current state
|
||||
// if no last active state found it loads default state
|
||||
void _set_last_active_state_as_current();
|
||||
////////////////////////////////////////
|
||||
|
||||
// internal helper functions////////////
|
||||
// make sure that current device parameters are supported and fit session requirements
|
||||
void _validate_current_device_state();
|
||||
////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////
|
||||
// callbacks
|
||||
void _on_engine_running();
|
||||
void _on_engine_halted(const char*);
|
||||
void _on_engine_stopped();
|
||||
void _on_sample_rate_change(ARDOUR::framecnt_t);
|
||||
void _on_buffer_size_change(ARDOUR::pframes_t);
|
||||
void _on_device_list_change();
|
||||
////////////////////////////////////////
|
||||
|
||||
////////////////////////////////////////
|
||||
// attributes
|
||||
StatePtr _current_state;
|
||||
// list of system states
|
||||
StateList _states;
|
||||
|
||||
// last active non-default (real) device
|
||||
std::string _last_used_real_device;
|
||||
|
||||
ARDOUR::framecnt_t _desired_sample_rate;
|
||||
bool _have_control;
|
||||
|
||||
// Engine connections stuff
|
||||
PBD::ScopedConnectionList update_connections;
|
||||
PBD::ScopedConnection running_connection;
|
||||
PBD::ScopedConnection halt_connection;
|
||||
PBD::ScopedConnection stopped_connection;
|
||||
|
||||
};
|
||||
|
||||
} // namespace ARDOUR
|
||||
|
||||
#endif /* defined(__gtk2_ardour__engine_state_controller__) */
|
||||
|
|
@ -28,6 +28,8 @@
|
|||
|
||||
#include <gtkmm/filechooser.h>
|
||||
|
||||
#include "engine_state_controller.h"
|
||||
|
||||
#include "pbd/failed_constructor.h"
|
||||
#include "pbd/file_utils.h"
|
||||
#include "pbd/replace_all.h"
|
||||
|
|
@ -213,15 +215,11 @@ SessionDialog::on_new_session (WavesButton*)
|
|||
|
||||
void SessionDialog::redisplay_system_configuration ()
|
||||
{
|
||||
// Temp solution:
|
||||
TracksControlPanel* panel = dynamic_cast<TracksControlPanel*>(_system_configuration_dialog.get(false));
|
||||
if (panel) {
|
||||
_session_details_label.set_text(string_compose (_("%1\n\n\n\n%2"),
|
||||
panel->get_device_name(),
|
||||
panel->get_sample_rate()));
|
||||
} else {
|
||||
_session_details_label.set_text("");
|
||||
}
|
||||
ARDOUR::EngineStateController* eng_controller (ARDOUR::EngineStateController::instance() );
|
||||
|
||||
_session_details_label.set_text(string_compose (_("%1\n\n\n\n%2"),
|
||||
eng_controller->get_current_device_name(),
|
||||
eng_controller->get_current_sample_rate()));
|
||||
}
|
||||
|
||||
int
|
||||
|
|
|
|||
|
|
@ -53,7 +53,6 @@
|
|||
//#include "utils.h"
|
||||
#include "i18n.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace Gtk;
|
||||
using namespace Gtkmm2ext;
|
||||
using namespace PBD;
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@
|
|||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "ardour/types.h"
|
||||
|
||||
#include <gtkmm/layout.h>
|
||||
|
||||
#include "pbd/signals.h"
|
||||
|
|
|
|||
|
|
@ -23,8 +23,7 @@
|
|||
|
||||
#include <gtkmm2ext/utils.h>
|
||||
|
||||
#include "ardour/audio_backend.h"
|
||||
#include "ardour/audioengine.h"
|
||||
#include "engine_state_controller.h"
|
||||
#include "ardour/rc_configuration.h"
|
||||
#include "device_connection_control.h"
|
||||
#include "ardour_ui.h"
|
||||
|
|
@ -33,7 +32,7 @@
|
|||
#include "i18n.h"
|
||||
#include "pbd/convert.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace ARDOUR;
|
||||
using namespace Gtk;
|
||||
using namespace Gtkmm2ext;
|
||||
using namespace PBD;
|
||||
|
|
@ -56,13 +55,14 @@ TracksControlPanel::init ()
|
|||
_multi_out_button.signal_clicked.connect(sigc::mem_fun (*this, &TracksControlPanel::on_multi_out));
|
||||
_stereo_out_button.signal_clicked.connect(sigc::mem_fun (*this, &TracksControlPanel::on_stereo_out));
|
||||
|
||||
ARDOUR::AudioEngine::instance ()->Running.connect (running_connection, MISSING_INVALIDATOR, boost::bind (&TracksControlPanel::engine_running, this), gui_context());
|
||||
ARDOUR::AudioEngine::instance ()->Stopped.connect (stopped_connection, MISSING_INVALIDATOR, boost::bind (&TracksControlPanel::engine_stopped, this), gui_context());
|
||||
ARDOUR::AudioEngine::instance ()->Halted.connect (stopped_connection, MISSING_INVALIDATOR, boost::bind (&TracksControlPanel::engine_stopped, this), gui_context());
|
||||
|
||||
AudioEngine::instance ()->Running.connect (running_connection, MISSING_INVALIDATOR, boost::bind (&TracksControlPanel::engine_running, this), gui_context());
|
||||
AudioEngine::instance ()->Stopped.connect (stopped_connection, MISSING_INVALIDATOR, boost::bind (&TracksControlPanel::engine_stopped, this), gui_context());
|
||||
AudioEngine::instance ()->Halted.connect (stopped_connection, MISSING_INVALIDATOR, boost::bind (&TracksControlPanel::engine_stopped, this), gui_context());
|
||||
|
||||
/* Subscribe for udpates from AudioEngine */
|
||||
ARDOUR::AudioEngine::instance()->BufferSizeChanged.connect (update_connections, MISSING_INVALIDATOR, boost::bind (&TracksControlPanel::update_current_buffer_size, this, _1), gui_context());
|
||||
ARDOUR::AudioEngine::instance()->DeviceListChanged.connect (update_connections, MISSING_INVALIDATOR, boost::bind (&TracksControlPanel::update_device_list, this), gui_context());
|
||||
EngineStateController::instance()->BufferSizeChanged.connect (update_connections, MISSING_INVALIDATOR, boost::bind (&TracksControlPanel::populate_buffer_size_combo, this), gui_context());
|
||||
EngineStateController::instance()->DeviceListChanged.connect (update_connections, MISSING_INVALIDATOR, boost::bind (&TracksControlPanel::populate_device_combo, this), gui_context());
|
||||
|
||||
_engine_combo.signal_changed().connect (sigc::mem_fun (*this, &TracksControlPanel::engine_changed));
|
||||
_device_combo.signal_changed().connect (sigc::mem_fun (*this, &TracksControlPanel::device_changed));
|
||||
|
|
@ -70,9 +70,9 @@ TracksControlPanel::init ()
|
|||
_buffer_size_combo.signal_changed().connect (sigc::mem_fun (*this, &TracksControlPanel::buffer_size_changed));
|
||||
|
||||
populate_engine_combo ();
|
||||
populate_output_mode();
|
||||
|
||||
_audio_settings_tab_button.set_active(true);
|
||||
_multi_out_button.set_active(ARDOUR::Config->get_output_auto_connect() & ARDOUR::AutoConnectPhysical);
|
||||
_stereo_out_button.set_active(ARDOUR::Config->get_output_auto_connect() & ARDOUR::AutoConnectMaster);
|
||||
}
|
||||
|
||||
DeviceConnectionControl& TracksControlPanel::add_device_capture_control(std::string device_capture_name, bool active, uint16_t capture_number, std::string track_name)
|
||||
|
|
@ -115,14 +115,15 @@ TracksControlPanel::populate_engine_combo()
|
|||
}
|
||||
|
||||
std::vector<std::string> strings;
|
||||
vector<const ARDOUR::AudioBackendInfo*> backends = ARDOUR::AudioEngine::instance()->available_backends();
|
||||
std::vector<const AudioBackendInfo*> backends;
|
||||
EngineStateController::instance()->available_backends(backends);
|
||||
|
||||
if (backends.empty()) {
|
||||
MessageDialog msg (string_compose (_("No audio/MIDI backends detected. %1 cannot run\n\n(This is a build/packaging/system error. It should never happen.)"), PROGRAM_NAME));
|
||||
msg.run ();
|
||||
throw failed_constructor ();
|
||||
}
|
||||
for (vector<const ARDOUR::AudioBackendInfo*>::const_iterator b = backends.begin(); b != backends.end(); ++b) {
|
||||
for (std::vector<const AudioBackendInfo*>::const_iterator b = backends.begin(); b != backends.end(); ++b) {
|
||||
strings.push_back ((*b)->name);
|
||||
}
|
||||
|
||||
|
|
@ -135,20 +136,19 @@ TracksControlPanel::populate_engine_combo()
|
|||
|
||||
if (!strings.empty() )
|
||||
{
|
||||
_engine_combo.set_active_text (strings.front());
|
||||
_engine_combo.set_active_text (EngineStateController::instance()->get_current_backend_name() );
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TracksControlPanel::populate_device_combo()
|
||||
{
|
||||
boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
|
||||
assert (backend);
|
||||
std::vector<AudioBackend::DeviceStatus> all_devices;
|
||||
EngineStateController::instance()->enumerate_devices (all_devices);
|
||||
|
||||
vector<ARDOUR::AudioBackend::DeviceStatus> all_devices = backend->enumerate_devices ();
|
||||
vector<string> available_devices;
|
||||
std::vector<std::string> available_devices;
|
||||
|
||||
for (vector<ARDOUR::AudioBackend::DeviceStatus>::const_iterator i = all_devices.begin(); i != all_devices.end(); ++i) {
|
||||
for (std::vector<AudioBackend::DeviceStatus>::const_iterator i = all_devices.begin(); i != all_devices.end(); ++i) {
|
||||
available_devices.push_back (i->name);
|
||||
}
|
||||
|
||||
|
|
@ -160,7 +160,7 @@ TracksControlPanel::populate_device_combo()
|
|||
}
|
||||
|
||||
if(!available_devices.empty() ) {
|
||||
_device_combo.set_active_text (available_devices.front() );
|
||||
_device_combo.set_active_text (EngineStateController::instance()->get_current_device_name() );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -168,14 +168,11 @@ TracksControlPanel::populate_device_combo()
|
|||
void
|
||||
TracksControlPanel::populate_sample_rate_combo()
|
||||
{
|
||||
boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
|
||||
assert (backend);
|
||||
std::string device_name = _device_combo.get_active_text ();
|
||||
std::vector<float> sample_rates;
|
||||
EngineStateController::instance()->available_sample_rates_for_current_device(sample_rates);
|
||||
|
||||
std::vector<std::string> s;
|
||||
vector<float> sr;
|
||||
|
||||
sr = backend->available_sample_rates (device_name);
|
||||
for (vector<float>::const_iterator x = sr.begin(); x != sr.end(); ++x) {
|
||||
for (std::vector<float>::const_iterator x = sample_rates.begin(); x != sample_rates.end(); ++x) {
|
||||
s.push_back (rate_as_string (*x));
|
||||
}
|
||||
|
||||
|
|
@ -187,12 +184,8 @@ TracksControlPanel::populate_sample_rate_combo()
|
|||
}
|
||||
|
||||
if (!s.empty() ) {
|
||||
std::string active_sr = rate_as_string((_desired_sample_rate != 0) ?
|
||||
_desired_sample_rate :
|
||||
backend->default_sample_rate());
|
||||
if (std::find(s.begin(), s.end(), active_sr) == s.end()) {
|
||||
active_sr = s.front();
|
||||
}
|
||||
std::string active_sr = rate_as_string(EngineStateController::instance()->get_current_sample_rate() );
|
||||
|
||||
_sample_rate_combo.set_active_text(active_sr);
|
||||
}
|
||||
}
|
||||
|
|
@ -200,14 +193,11 @@ TracksControlPanel::populate_sample_rate_combo()
|
|||
void
|
||||
TracksControlPanel::populate_buffer_size_combo()
|
||||
{
|
||||
boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
|
||||
assert (backend);
|
||||
std::string device_name = _device_combo.get_active_text ();
|
||||
std::vector<std::string> s;
|
||||
std::vector<uint32_t> bs;
|
||||
std::vector<std::string> s;
|
||||
std::vector<pframes_t> buffer_sizes;
|
||||
|
||||
bs = backend->available_buffer_sizes(device_name);
|
||||
for (std::vector<uint32_t>::const_iterator x = bs.begin(); x != bs.end(); ++x) {
|
||||
EngineStateController::instance()->available_buffer_sizes_for_current_device(buffer_sizes);
|
||||
for (std::vector<pframes_t>::const_iterator x = buffer_sizes.begin(); x != buffer_sizes.end(); ++x) {
|
||||
s.push_back (bufsize_as_string (*x));
|
||||
}
|
||||
|
||||
|
|
@ -219,20 +209,25 @@ TracksControlPanel::populate_buffer_size_combo()
|
|||
}
|
||||
|
||||
if (!s.empty() ) {
|
||||
std::string active_bs = bufsize_as_string(backend->default_buffer_size());
|
||||
if (std::find(s.begin(), s.end(), active_bs) == s.end() ) {
|
||||
active_bs = s.front();
|
||||
}
|
||||
std::string active_bs = bufsize_as_string(EngineStateController::instance()->get_current_buffer_size());
|
||||
_buffer_size_combo.set_active_text(active_bs);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TracksControlPanel::populate_output_mode()
|
||||
{
|
||||
_multi_out_button.set_active(Config->get_output_auto_connect() & AutoConnectPhysical);
|
||||
_stereo_out_button.set_active(Config->get_output_auto_connect() & AutoConnectMaster);
|
||||
}
|
||||
|
||||
void
|
||||
TracksControlPanel::on_control_panel(WavesButton*)
|
||||
{
|
||||
// ******************************* ATTENTION!!! ****************************
|
||||
// here is just demo code to remove it in future
|
||||
// *************************************************************************
|
||||
/*
|
||||
static uint16_t number = 0;
|
||||
static bool active = false;
|
||||
|
||||
|
|
@ -249,6 +244,7 @@ TracksControlPanel::on_control_panel(WavesButton*)
|
|||
add_midi_capture_control (name, active);
|
||||
|
||||
add_midi_playback_control (active);
|
||||
*/
|
||||
}
|
||||
|
||||
void TracksControlPanel::engine_changed ()
|
||||
|
|
@ -257,17 +253,16 @@ void TracksControlPanel::engine_changed ()
|
|||
return;
|
||||
}
|
||||
|
||||
string backend_name = _engine_combo.get_active_text();
|
||||
boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->set_backend (backend_name, "ardour", "");
|
||||
if (!backend)
|
||||
std::string backend_name = _engine_combo.get_active_text();
|
||||
|
||||
if ( EngineStateController::instance()->set_new_backend_as_current (backend_name) )
|
||||
{
|
||||
std::cerr << "\tfailed to set backend [" << backend_name << "]\n";
|
||||
return;
|
||||
_have_control = EngineStateController::instance()->is_setup_required ();
|
||||
populate_device_combo();
|
||||
return;
|
||||
}
|
||||
|
||||
_have_control = ARDOUR::AudioEngine::instance()->setup_required ();
|
||||
|
||||
populate_device_combo();
|
||||
|
||||
std::cerr << "\tfailed to set backend [" << backend_name << "]\n";
|
||||
}
|
||||
|
||||
void TracksControlPanel::device_changed ()
|
||||
|
|
@ -275,14 +270,23 @@ void TracksControlPanel::device_changed ()
|
|||
if (_ignore_changes) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::string newDevice = _device_combo.get_active_text();
|
||||
if (newDevice != "None") {
|
||||
_current_device = newDevice;
|
||||
|
||||
std::string device_name = _device_combo.get_active_text ();
|
||||
if (EngineStateController::instance()->set_new_current_device_in_controller(device_name) )
|
||||
{
|
||||
populate_buffer_size_combo();
|
||||
populate_sample_rate_combo();
|
||||
return;
|
||||
}
|
||||
|
||||
populate_buffer_size_combo();
|
||||
populate_sample_rate_combo();
|
||||
{
|
||||
// set _ignore_changes flag to ignore changes in combo-box callbacks
|
||||
PBD::Unwinder<uint32_t> protect_ignore_changes (_ignore_changes, _ignore_changes + 1);
|
||||
// restore previous device name in combo box
|
||||
_device_combo.set_active_text (EngineStateController::instance()->get_current_device_name() );
|
||||
}
|
||||
|
||||
MessageDialog( _("Selected device is not available for current engine"), PROGRAM_NAME).run();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -292,7 +296,22 @@ TracksControlPanel::buffer_size_changed()
|
|||
return;
|
||||
}
|
||||
|
||||
show_buffer_duration();
|
||||
pframes_t new_buffer_size = get_buffer_size();
|
||||
if (EngineStateController::instance()->set_new_buffer_size_in_controller(new_buffer_size) )
|
||||
{
|
||||
show_buffer_duration();
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
// set _ignore_changes flag to ignore changes in combo-box callbacks
|
||||
PBD::Unwinder<uint32_t> protect_ignore_changes (_ignore_changes, _ignore_changes + 1);
|
||||
// restore previous buffer size value in combo box
|
||||
std::string buffer_size_str = bufsize_as_string (EngineStateController::instance()->get_current_buffer_size() );
|
||||
_buffer_size_combo.set_active_text(buffer_size_str);
|
||||
}
|
||||
|
||||
MessageDialog( _("Buffer size set to the value which is not supported"), PROGRAM_NAME).run();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -302,129 +321,31 @@ TracksControlPanel::sample_rate_changed()
|
|||
return;
|
||||
}
|
||||
|
||||
show_buffer_duration();
|
||||
}
|
||||
|
||||
void
|
||||
TracksControlPanel::update_current_buffer_size (uint32_t new_buffer_size)
|
||||
{
|
||||
boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
|
||||
assert (backend);
|
||||
|
||||
std::string new_buffer_size_str = bufsize_as_string(new_buffer_size);
|
||||
|
||||
/* check if new buffer size value is no the same as already set in combobox */
|
||||
if ( new_buffer_size_str != _buffer_size_combo.get_active_text() ) {
|
||||
vector<string> s;
|
||||
vector<uint32_t> bs;
|
||||
std::string device_name = _device_combo.get_active_text ();
|
||||
bs = backend->available_buffer_sizes(device_name);
|
||||
|
||||
for (vector<uint32_t>::const_iterator x = bs.begin(); x != bs.end(); ++x) {
|
||||
s.push_back (bufsize_as_string (*x) );
|
||||
}
|
||||
|
||||
{
|
||||
// set _ignore_changes flag to ignore changes in combo-box callbacks
|
||||
PBD::Unwinder<uint32_t> protect_ignore_changes (_ignore_changes, _ignore_changes + 1);
|
||||
set_popdown_strings (_buffer_size_combo, s);
|
||||
_buffer_size_combo.set_sensitive (s.size() > 1);
|
||||
}
|
||||
|
||||
if (!s.empty() ) {
|
||||
if (std::find(s.begin(), s.end(), new_buffer_size_str) == s.end() ) {
|
||||
_buffer_size_combo.set_active_text (new_buffer_size_str );
|
||||
} else {
|
||||
MessageDialog( _("Buffer size changed to the value which is not supported"), PROGRAM_NAME).run();
|
||||
}
|
||||
}
|
||||
framecnt_t new_sample_rate = get_sample_rate ();
|
||||
if (EngineStateController::instance()->set_new_sample_rate_in_controller(new_sample_rate) )
|
||||
{
|
||||
show_buffer_duration();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TracksControlPanel::update_device_list ()
|
||||
{
|
||||
boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
|
||||
assert (backend);
|
||||
|
||||
/* now fill out devices, mark sample rates, buffer sizes insensitive */
|
||||
|
||||
vector<ARDOUR::AudioBackend::DeviceStatus> all_devices = backend->enumerate_devices ();
|
||||
|
||||
vector<string> available_devices;
|
||||
|
||||
for (vector<ARDOUR::AudioBackend::DeviceStatus>::const_iterator i = all_devices.begin(); i != all_devices.end(); ++i) {
|
||||
available_devices.push_back (i->name);
|
||||
}
|
||||
|
||||
if (!available_devices.empty()) {
|
||||
|
||||
/* Now get current device name */
|
||||
std::string current_active_device = _device_combo.get_active_text ();
|
||||
|
||||
/* If previous device is available again we should switch to it from "None" */
|
||||
std::string newDevice;
|
||||
if (current_active_device == "None" && !_current_device.empty() ){
|
||||
newDevice = _current_device;
|
||||
} else {
|
||||
newDevice = current_active_device;
|
||||
}
|
||||
|
||||
bool deviceFound(false);
|
||||
{
|
||||
// set _ignore_changes flag to ignore changes in combo-box callbacks
|
||||
PBD::Unwinder<uint32_t> protect_ignore_changes (_ignore_changes, _ignore_changes + 1);
|
||||
set_popdown_strings (_device_combo, available_devices);
|
||||
_device_combo.set_sensitive (available_devices.size() > 1);
|
||||
|
||||
for (vector<string>::const_iterator i = available_devices.begin(); i != available_devices.end(); ++i) {
|
||||
if (newDevice == *i) {
|
||||
deviceFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (deviceFound) {
|
||||
switch_to_device(newDevice);
|
||||
|
||||
} else if (current_active_device != "None") {
|
||||
switch_to_device("None");
|
||||
MessageDialog( _("Current device is not available! Switched to NONE device."), PROGRAM_NAME).run();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TracksControlPanel::switch_to_device(const std::string& device_name)
|
||||
{
|
||||
boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
|
||||
|
||||
{
|
||||
// set _ignore_changes flag to ignore changes in combo-box callbacks
|
||||
PBD::Unwinder<uint32_t> protect_ignore_changes (_ignore_changes, _ignore_changes + 1);
|
||||
_device_combo.set_active_text(device_name);
|
||||
}
|
||||
|
||||
if (backend->device_name() != device_name) {
|
||||
|
||||
// push state to backend, but do not start unless it was running
|
||||
push_state_to_backend (false);
|
||||
// set _ignore_changes flag to ignore changes in combo-box callbacks
|
||||
PBD::Unwinder<uint32_t> protect_ignore_changes (_ignore_changes, _ignore_changes + 1);
|
||||
// restore previous buffer size value in combo box
|
||||
std::string sample_rate_str = rate_as_string (EngineStateController::instance()->get_current_sample_rate() );
|
||||
_sample_rate_combo.set_active_text(sample_rate_str);
|
||||
}
|
||||
|
||||
MessageDialog( _("Sample rate set to the value which is not supported"), PROGRAM_NAME).run();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TracksControlPanel::engine_running ()
|
||||
{
|
||||
boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
|
||||
assert (backend);
|
||||
_buffer_size_combo.set_active_text (bufsize_as_string (EngineStateController::instance()->get_current_buffer_size() ) );
|
||||
|
||||
_buffer_size_combo.set_active_text (bufsize_as_string (backend->buffer_size()));
|
||||
|
||||
_sample_rate_combo.set_active_text (rate_as_string (backend->sample_rate()));
|
||||
_sample_rate_combo.set_active_text (rate_as_string (EngineStateController::instance()->get_current_sample_rate() ) );
|
||||
|
||||
_buffer_size_combo.set_sensitive (true);
|
||||
_sample_rate_combo.set_sensitive (true);
|
||||
|
|
@ -476,11 +397,11 @@ TracksControlPanel::on_session_settings (WavesButton*)
|
|||
void
|
||||
TracksControlPanel::on_multi_out (WavesButton*)
|
||||
{
|
||||
if (ARDOUR::Config->get_output_auto_connect() & ARDOUR::AutoConnectPhysical) {
|
||||
if (Config->get_output_auto_connect() & AutoConnectPhysical) {
|
||||
return;
|
||||
}
|
||||
|
||||
ARDOUR::Config->set_output_auto_connect(ARDOUR::AutoConnectPhysical);
|
||||
Config->set_output_auto_connect(AutoConnectPhysical);
|
||||
_stereo_out_button.set_active(false);
|
||||
_multi_out_button.set_active(true);
|
||||
}
|
||||
|
|
@ -490,11 +411,11 @@ void
|
|||
TracksControlPanel::on_stereo_out (WavesButton*)
|
||||
{
|
||||
|
||||
if (ARDOUR::Config->get_output_auto_connect() & ARDOUR::AutoConnectMaster) {
|
||||
if (Config->get_output_auto_connect() & AutoConnectMaster) {
|
||||
return;
|
||||
}
|
||||
|
||||
ARDOUR::Config->set_output_auto_connect(ARDOUR::AutoConnectMaster);
|
||||
Config->set_output_auto_connect(AutoConnectMaster);
|
||||
_multi_out_button.set_active(false);
|
||||
_stereo_out_button.set_active(true);
|
||||
}
|
||||
|
|
@ -503,7 +424,7 @@ void
|
|||
TracksControlPanel::on_ok (WavesButton*)
|
||||
{
|
||||
hide();
|
||||
push_state_to_backend (true);
|
||||
EngineStateController::instance()->push_current_state_to_backend(true);
|
||||
response(Gtk::RESPONSE_OK);
|
||||
}
|
||||
|
||||
|
|
@ -519,7 +440,7 @@ TracksControlPanel::on_cancel (WavesButton*)
|
|||
void
|
||||
TracksControlPanel::on_apply (WavesButton*)
|
||||
{
|
||||
push_state_to_backend (true);
|
||||
EngineStateController::instance()->push_current_state_to_backend(true);
|
||||
response(Gtk::RESPONSE_APPLY);
|
||||
}
|
||||
|
||||
|
|
@ -563,62 +484,8 @@ TracksControlPanel::bufsize_as_string (uint32_t sz)
|
|||
return buf;
|
||||
}
|
||||
|
||||
void
|
||||
TracksControlPanel::set_desired_sample_rate (uint32_t sr)
|
||||
{
|
||||
_desired_sample_rate = sr;
|
||||
std::string active_sr = rate_as_string(_desired_sample_rate);
|
||||
std::string prev_selected = _sample_rate_combo.get_active_text();
|
||||
_sample_rate_combo.set_active_text(active_sr);
|
||||
active_sr = _sample_rate_combo.get_active_text();
|
||||
if (active_sr.empty()) {
|
||||
_sample_rate_combo.set_active_text(prev_selected);
|
||||
}
|
||||
}
|
||||
|
||||
XMLNode&
|
||||
TracksControlPanel::get_state ()
|
||||
{
|
||||
return *new XMLNode ("TracksPreferences");// !!!!!!!!!!!!!!!
|
||||
/*
|
||||
XMLNode* root = new XMLNode ("TracksPreferences");
|
||||
std::string path;
|
||||
|
||||
if (!states.empty()) {
|
||||
XMLNode* state_nodes = new XMLNode ("EngineStates");
|
||||
|
||||
for (StateList::const_iterator i = states.begin(); i != states.end(); ++i) {
|
||||
|
||||
XMLNode* node = new XMLNode ("State");
|
||||
|
||||
node->add_property ("backend", (*i).backend);
|
||||
node->add_property ("driver", (*i).driver);
|
||||
node->add_property ("device", (*i).device);
|
||||
node->add_property ("sample-rate", (*i).sample_rate);
|
||||
node->add_property ("buffer-size", (*i).buffer_size);
|
||||
node->add_property ("input-latency", (*i).input_latency);
|
||||
node->add_property ("output-latency", (*i).output_latency);
|
||||
node->add_property ("input-channels", (*i).input_channels);
|
||||
node->add_property ("output-channels", (*i).output_channels);
|
||||
node->add_property ("active", (*i).active ? "yes" : "no");
|
||||
node->add_property ("midi-option", (*i).midi_option);
|
||||
|
||||
state_nodes->add_child_nocopy (*node);
|
||||
}
|
||||
|
||||
root->add_child_nocopy (*state_nodes);
|
||||
}
|
||||
|
||||
return *root;
|
||||
*/
|
||||
}
|
||||
|
||||
void
|
||||
TracksControlPanel::set_state (const XMLNode& root)
|
||||
{
|
||||
}
|
||||
|
||||
float
|
||||
framecnt_t
|
||||
TracksControlPanel::get_sample_rate () const
|
||||
{
|
||||
float r = atof (_sample_rate_combo.get_active_text ());
|
||||
|
|
@ -631,10 +498,10 @@ TracksControlPanel::get_sample_rate () const
|
|||
return r;
|
||||
}
|
||||
|
||||
uint32_t TracksControlPanel::get_buffer_size() const
|
||||
pframes_t TracksControlPanel::get_buffer_size() const
|
||||
{
|
||||
string bs_text = _buffer_size_combo.get_active_text ();
|
||||
uint32_t samples = atoi (bs_text); /* will ignore trailing text */
|
||||
std::string bs_text = _buffer_size_combo.get_active_text ();
|
||||
pframes_t samples = atoi (bs_text); /* will ignore trailing text */
|
||||
return samples;
|
||||
}
|
||||
|
||||
|
|
@ -648,63 +515,3 @@ TracksControlPanel::show_buffer_duration ()
|
|||
latency, latency, 2*latency);
|
||||
_latency_label.set_text (buf);
|
||||
}
|
||||
|
||||
int
|
||||
TracksControlPanel::push_state_to_backend (bool start)
|
||||
{
|
||||
boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
|
||||
|
||||
if (!backend) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool was_running = ARDOUR::AudioEngine::instance()->running();
|
||||
if (was_running) {
|
||||
if (ARDOUR_UI::instance()->disconnect_from_engine ()) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if ((get_device_name() != backend->device_name()) && backend->set_device_name (get_device_name())) {
|
||||
error << string_compose (_("Cannot set device name to %1"), get_device_name()) << endmsg;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (backend->set_sample_rate (get_sample_rate())) {
|
||||
error << string_compose (_("Cannot set sample rate to %1"), get_sample_rate()) << endmsg;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (backend->set_buffer_size (get_buffer_size())) {
|
||||
error << string_compose (_("Cannot set buffer size to %1"), get_buffer_size()) << endmsg;
|
||||
return -1;
|
||||
}
|
||||
|
||||
//if (backend->set_input_channels (get_input_channels())) {
|
||||
// error << string_compose (_("Cannot set input channels to %1"), get_input_channels()) << endmsg;
|
||||
// return -1;
|
||||
//}
|
||||
|
||||
//if (backend->set_output_channels (get_output_channels())) {
|
||||
// error << string_compose (_("Cannot set output channels to %1"), get_output_channels()) << endmsg;
|
||||
// return -1;
|
||||
//}
|
||||
|
||||
//if (backend->set_systemic_input_latency (get_input_latency())) {
|
||||
// error << string_compose (_("Cannot set input latency to %1"), get_input_latency()) << endmsg;
|
||||
// return -1;
|
||||
//}
|
||||
|
||||
//if (backend->set_systemic_output_latency (get_output_latency())) {
|
||||
// error << string_compose (_("Cannot set output latency to %1"), get_output_latency()) << endmsg;
|
||||
// return -1;
|
||||
//}
|
||||
|
||||
if(start || was_running)
|
||||
{
|
||||
//dbg_msg("ARDOUR_UI::instance()->reconnect_to_engine ()");
|
||||
ARDOUR_UI::instance()->reconnect_to_engine ();
|
||||
//dbg_msg("Done");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,17 +16,9 @@
|
|||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
*/
|
||||
|
||||
// class TracksControlPanel : public WavesDialog {
|
||||
public:
|
||||
void set_desired_sample_rate (uint32_t sr);
|
||||
XMLNode& get_state ();
|
||||
|
||||
void update_current_buffer_size (uint32_t new_buffer_size);
|
||||
void update_device_list ();
|
||||
void switch_to_device(const std::string& device_name);
|
||||
|
||||
float get_sample_rate() const;
|
||||
std::string get_device_name() const { return _device_combo.get_active_text (); };
|
||||
|
||||
private:
|
||||
// data types:
|
||||
|
|
@ -101,16 +93,17 @@
|
|||
void populate_device_combo ();
|
||||
void populate_sample_rate_combo ();
|
||||
void populate_buffer_size_combo ();
|
||||
void populate_output_mode ();
|
||||
|
||||
std::string bufsize_as_string (uint32_t sz);
|
||||
void set_state (const XMLNode&);
|
||||
int push_state_to_backend (bool start);
|
||||
|
||||
uint32_t get_buffer_size () const;
|
||||
uint32_t get_input_channels () const { return 0; };
|
||||
uint32_t get_output_channels () const { return 0; };
|
||||
uint32_t get_input_latency () const { return 0; };
|
||||
uint32_t get_output_latency () const { return 0; };
|
||||
std::string get_device_name() const { return _device_combo.get_active_text (); };
|
||||
ARDOUR::framecnt_t get_sample_rate() const;
|
||||
ARDOUR::pframes_t get_buffer_size () const;
|
||||
uint32_t get_input_channels () const { return 0; };
|
||||
uint32_t get_output_channels () const { return 0; };
|
||||
uint32_t get_input_latency () const { return 0; };
|
||||
uint32_t get_output_latency () const { return 0; };
|
||||
|
||||
void show_buffer_duration ();
|
||||
//};
|
||||
|
|
|
|||
|
|
@ -94,6 +94,7 @@ gtk2_ardour_sources = [
|
|||
'editor_summary.cc',
|
||||
'editor_tempodisplay.cc',
|
||||
'editor_timefx.cc',
|
||||
'engine_state_controller.cc',
|
||||
'engine_dialog.cc',
|
||||
'enums.cc',
|
||||
'export_channel_selector.cc',
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue