[Summary] Implemented channel control mechanism

[git-p4: depot-paths = "//Abdaw/dev_main/tracks/": change = 461673]
This commit is contained in:
Grygorii Zharun 2014-05-19 18:04:58 -05:00
parent 5f65b603ad
commit dfc0b58d14
18 changed files with 685 additions and 105 deletions

View file

@ -68,6 +68,7 @@
#include "ardour/audiofilesource.h"
#include "ardour/automation_watch.h"
#include "ardour/diskstream.h"
#include "ardour/engine_state_controller.h"
#include "ardour/filename_extensions.h"
#include "ardour/filesystem_paths.h"
#include "ardour/port.h"
@ -95,7 +96,6 @@ 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"

View file

@ -20,7 +20,7 @@
#include "device_connection_control.h"
#include "pbd/convert.h"
DeviceConnectionControl::DeviceConnectionControl (std::string device_capture_name, bool active, uint16_t capture_number, std::string track_name)
DeviceConnectionControl::DeviceConnectionControl (const std::string& device_capture_name, bool active, uint16_t capture_number, const std::string& track_name)
: Gtk::Layout()
, _active_on_button (NULL)
@ -38,7 +38,7 @@ DeviceConnectionControl::DeviceConnectionControl (std::string device_capture_nam
init(device_capture_name, active, capture_number, track_name);
}
DeviceConnectionControl::DeviceConnectionControl (std::string device_playback_name, bool active, uint16_t playback_number)
DeviceConnectionControl::DeviceConnectionControl (const std::string& device_playback_name, bool active, uint16_t playback_number)
: Gtk::Layout()
, _active_on_button (NULL)
@ -55,7 +55,7 @@ DeviceConnectionControl::DeviceConnectionControl (std::string device_playback_na
init(device_playback_name, active, playback_number);
}
DeviceConnectionControl::DeviceConnectionControl (std::string midi_capture_name, bool active)
DeviceConnectionControl::DeviceConnectionControl (const std::string& midi_capture_name, bool active)
: Gtk::Layout()
, _active_on_button (NULL)
@ -86,7 +86,7 @@ DeviceConnectionControl::DeviceConnectionControl (bool active)
init("", active, NoNumber);
}
void DeviceConnectionControl::init(std::string name, bool active, uint16_t number, std::string track_name)
void DeviceConnectionControl::init(const std::string& name, bool active, uint16_t number, const std::string& track_name)
{
_active_on_button->signal_clicked.connect (sigc::mem_fun (*this, &DeviceConnectionControl::on_active_on));
_active_off_button->signal_clicked.connect (sigc::mem_fun (*this, &DeviceConnectionControl::on_active_off));
@ -97,17 +97,22 @@ void DeviceConnectionControl::init(std::string name, bool active, uint16_t numbe
if (_number_label != NULL) {
_number_label->set_text(PBD::to_string (number, std::dec));
if (number == NoNumber) {
_number_label->get_parent()->hide ();
}
}
if (_track_name_label != NULL) {
_track_name_label->set_text (track_name);
}
set_active(active);
}
bool
DeviceConnectionControl::build_layout (std::string file_name)
DeviceConnectionControl::build_layout (const std::string& file_name)
{
const XMLTree* layout = WavesUI::load_layout(file_name);
if (layout == NULL) {
@ -144,6 +149,32 @@ DeviceConnectionControl::set_active (bool active)
_active = active;
}
void
DeviceConnectionControl::set_track_name (const std::string& new_track_name)
{
if (_track_name_label != NULL ) {
_track_name_label->set_text (new_track_name);
if (new_track_name.empty() ) {
_track_name_label->get_parent()->hide();
} else {
_track_name_label->get_parent()->show();
}
}
}
std::string
DeviceConnectionControl::get_name ()
{
std::string name;
if (_name_label != NULL) {
name = _name_label->get_text();
}
return name;
}
void
DeviceConnectionControl::on_active_on(WavesButton*)
{

View file

@ -33,18 +33,20 @@ class DeviceConnectionControl : public Gtk::Layout
NoNumber = 0
};
DeviceConnectionControl (std::string device_capture_name, bool active, uint16_t capture_number, std::string track_name);
DeviceConnectionControl (std::string device_playback_name, bool active, uint16_t playback_number);
DeviceConnectionControl (std::string midi_capture_name, bool active);
DeviceConnectionControl (const std::string& device_capture_name, bool active, uint16_t capture_number, const std::string& track_name);
DeviceConnectionControl (const std::string& device_playback_name, bool active, uint16_t playback_number);
DeviceConnectionControl (const std::string& midi_capture_name, bool active);
DeviceConnectionControl (bool active);
bool build_layout (std::string file_name);
bool build_layout (const std::string& file_name);
void set_number (uint16_t number);
void set_active (bool active);
void set_track_name (const std::string& new_track_name);
std::string get_name ();
sigc::signal2<void, DeviceConnectionControl*, bool> signal_active_changed;
private:
void init(std::string name, bool active, uint16_t number, std::string track_name="");
void init(const std::string& name, bool active, uint16_t number, const std::string& track_name="");
void on_active_on(WavesButton*);
void on_active_off(WavesButton*);

View file

@ -28,8 +28,6 @@
#include <gtkmm/filechooser.h>
#include "engine_state_controller.h"
#include "pbd/failed_constructor.h"
#include "pbd/file_utils.h"
#include "pbd/replace_all.h"
@ -38,6 +36,7 @@
#include "pbd/openuri.h"
#include "ardour/audioengine.h"
#include "ardour/engine_state_controller.h"
#include "ardour/filesystem_paths.h"
#include "ardour/recent_sessions.h"
#include "ardour/session.h"

View file

@ -25,8 +25,9 @@
#include <gtkmm2ext/utils.h>
#include "engine_state_controller.h"
#include "ardour/engine_state_controller.h"
#include "ardour/rc_configuration.h"
#include "device_connection_control.h"
#include "ardour_ui.h"
#include "gui_thread.h"
@ -58,13 +59,17 @@ TracksControlPanel::init ()
_stereo_out_button.signal_clicked.connect(sigc::mem_fun (*this, &TracksControlPanel::on_stereo_out));
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());
EngineStateController::instance ()->EngineRunning.connect (running_connection, MISSING_INVALIDATOR, boost::bind (&TracksControlPanel::engine_running, this), gui_context());
EngineStateController::instance ()->EngineStopped.connect (stopped_connection, MISSING_INVALIDATOR, boost::bind (&TracksControlPanel::engine_stopped, this), gui_context());
EngineStateController::instance ()->EngineHalted.connect (stopped_connection, MISSING_INVALIDATOR, boost::bind (&TracksControlPanel::engine_stopped, this), gui_context());
/* Subscribe for udpates from AudioEngine */
/* Subscribe for udpates from EngineStateController */
EngineStateController::instance()->BufferSizeChanged.connect (update_connections, MISSING_INVALIDATOR, boost::bind (&TracksControlPanel::on_buffer_size_update, this), gui_context());
EngineStateController::instance()->DeviceListChanged.connect (update_connections, MISSING_INVALIDATOR, boost::bind (&TracksControlPanel::on_device_list_update, this, _1), gui_context());
EngineStateController::instance()->InputConfigChanged.connect (update_connections, MISSING_INVALIDATOR, boost::bind (&TracksControlPanel::on_input_configuration_changed, this), gui_context());
EngineStateController::instance()->OutputConfigChanged.connect (update_connections, MISSING_INVALIDATOR, boost::bind (&TracksControlPanel::on_output_configuration_changed, this), gui_context());
/* Global configuration parameters update */
Config->ParameterChanged.connect (update_connections, MISSING_INVALIDATOR, boost::bind (&TracksControlPanel::on_parameter_changed, this, _1), gui_context());
_engine_combo.signal_changed().connect (sigc::mem_fun (*this, &TracksControlPanel::engine_changed));
@ -75,6 +80,9 @@ TracksControlPanel::init ()
populate_engine_combo ();
populate_output_mode();
populate_input_channels();
populate_output_channels();
_audio_settings_tab_button.set_active(true);
}
@ -227,30 +235,110 @@ TracksControlPanel::populate_output_mode()
_stereo_out_button.set_active(Config->get_output_auto_connect() & AutoConnectMaster);
}
void
TracksControlPanel::populate_input_channels()
{
cleanup_input_channels_list();
// process captures (inputs)
std::vector<EngineStateController::ChannelState> input_states;
EngineStateController::instance()->get_physical_audio_input_states(input_states);
std::vector<EngineStateController::ChannelState>::const_iterator input_iter;
uint16_t number_count = 1;
for (input_iter = input_states.begin(); input_iter != input_states.end(); ++input_iter ) {
uint16_t number = DeviceConnectionControl::NoNumber;
std::string track_name = "";
if (input_iter->active) {
number = number_count++;
if (Config->get_tracks_auto_naming() & UseDefaultNames) {
track_name = string_compose ("Track %1", number);
} else if (Config->get_tracks_auto_naming() & NameAfterDriver) {
track_name = input_iter->name;
}
}
add_device_capture_control (input_iter->name, input_iter->active, number, track_name);
}
}
void
TracksControlPanel::populate_output_channels()
{
cleanup_output_channels_list();
// process captures (outputs)
std::vector<EngineStateController::ChannelState> output_states;
EngineStateController::instance()->get_physical_audio_output_states(output_states);
std::vector<EngineStateController::ChannelState>::const_iterator output_iter;
uint16_t number_count = 1;
for (output_iter = output_states.begin(); output_iter != output_states.end(); ++output_iter ) {
uint16_t number = DeviceConnectionControl::NoNumber;
if (output_iter->active) {
number = number_count++;
}
add_device_playback_control (output_iter->name, output_iter->active, number);
}
}
void update_channel_numbers()
{
}
void update_channel_names()
{
}
void
TracksControlPanel::cleanup_input_channels_list()
{
std::vector<Gtk::Widget*> capture_controls = _device_capture_list.get_children();
while (capture_controls.size() != 0) {
Gtk::Widget* item = capture_controls.back();
capture_controls.pop_back();
_device_capture_list.remove(*item);
delete item;
}
}
void
TracksControlPanel::cleanup_output_channels_list()
{
std::vector<Gtk::Widget*> playback_controls = _device_playback_list.get_children();
while (playback_controls.size() != 0) {
Gtk::Widget* item = playback_controls.back();
playback_controls.pop_back();
_device_capture_list.remove(*item);
delete item;
}
}
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;
number++;
active = !active;
std::string name = string_compose (_("Audio Capture %1"), number);
add_device_capture_control (name, active, number, name);
name = string_compose (_("Audio Playback Output %1"), number);
add_device_playback_control (name, active, number);
name = string_compose (_("Midi Capture %1"), number);
add_midi_capture_control (name, active);
add_midi_playback_control (active);
*/
}
void TracksControlPanel::engine_changed ()
@ -372,6 +460,9 @@ TracksControlPanel::sample_rate_changed()
void
TracksControlPanel::engine_running ()
{
populate_input_channels();
populate_output_channels();
_buffer_size_combo.set_active_text (bufsize_as_string (EngineStateController::instance()->get_current_buffer_size() ) );
_sample_rate_combo.set_active_text (rate_as_string (EngineStateController::instance()->get_current_sample_rate() ) );
@ -471,19 +562,13 @@ TracksControlPanel::on_apply (WavesButton*)
void TracksControlPanel::on_capture_active_changed(DeviceConnectionControl* capture_control, bool active)
{
// ******************************* ATTENTION!!! ****************************
// here is just demo code to replace it with a meaningful app logic in future
// *************************************************************************
capture_control->set_number ( active ? 1000 : DeviceConnectionControl::NoNumber);
EngineStateController::instance()->set_physical_audio_input_state(capture_control->get_name(), active);
}
void TracksControlPanel::on_playback_active_changed(DeviceConnectionControl* playback_control, bool active)
{
// ******************************* ATTENTION!!! ****************************
// here is just demo code to replace it with a meaningful app logic in future
// *************************************************************************
playback_control->set_number ( active ? 1000 : DeviceConnectionControl::NoNumber);
EngineStateController::instance()->set_physical_audio_output_state(playback_control->get_name(), active);
}
@ -531,9 +616,75 @@ TracksControlPanel::on_parameter_changed (const std::string& parameter_name)
{
if (parameter_name == "output-auto-connect") {
populate_output_mode();
} else if (parameter_name == "tracks-auto-naming") {
on_input_configuration_changed ();
}
}
void
TracksControlPanel::on_input_configuration_changed ()
{
std::vector<Gtk::Widget*> capture_controls = _device_capture_list.get_children();
std::vector<Gtk::Widget*>::iterator control_iter = capture_controls.begin();
uint16_t number_count = 1;
for (; control_iter != capture_controls.end(); ++control_iter) {
DeviceConnectionControl* control = dynamic_cast<DeviceConnectionControl*> (*control_iter);
if (control) {
bool new_state = EngineStateController::instance()->get_physical_audio_input_state(control->get_name() );
uint16_t number = DeviceConnectionControl::NoNumber;
std::string track_name = "";
if (new_state) {
number = number_count++;
if (Config->get_tracks_auto_naming() & UseDefaultNames) {
track_name = string_compose ("Track %1", number);
} else if (Config->get_tracks_auto_naming() & NameAfterDriver) {
track_name = control->get_name();
}
}
control->set_track_name(track_name);
control->set_number(number);
control->set_active(new_state);
}
}
}
void
TracksControlPanel::on_output_configuration_changed()
{
std::vector<Gtk::Widget*> playback_controls = _device_playback_list.get_children();
std::vector<Gtk::Widget*>::iterator control_iter = playback_controls.begin();
uint16_t number_count = 1;
for (; control_iter != playback_controls.end(); ++control_iter) {
DeviceConnectionControl* control = dynamic_cast<DeviceConnectionControl*> (*control_iter);
if (control) {
bool new_state = EngineStateController::instance()->get_physical_audio_output_state(control->get_name() );
uint16_t number = DeviceConnectionControl::NoNumber;
if (new_state) {
number = number_count++;
}
control->set_number(number);
control->set_active(new_state);
}
}
}
std::string
TracksControlPanel::bufsize_as_string (uint32_t sz)

View file

@ -94,11 +94,18 @@
void populate_sample_rate_combo ();
void populate_buffer_size_combo ();
void populate_output_mode ();
void populate_input_channels();
void populate_output_channels();
// Engine State update callback handlers
void on_buffer_size_update ();
void on_device_list_update (bool current_device_disconnected);
void on_parameter_changed (const std::string& parameter_name);
void on_input_configuration_changed ();
void on_output_configuration_changed ();
void cleanup_input_channels_list();
void cleanup_output_channels_list();
std::string bufsize_as_string (uint32_t sz);

View file

@ -96,7 +96,6 @@ 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',

View file

@ -136,6 +136,8 @@ public:
void remove_session (); // not a replacement for SessionHandle::session_going_away()
Session* session() const { return _session; }
void reconnect_session_routes ();
class NoBackendAvailable : public std::exception {
public:
virtual const char *what() const throw() { return "could not connect to engine backend"; }

View file

@ -10,6 +10,7 @@
#define __gtk2_ardour__engine_state_controller__
#include <vector>
#include <list>
#include "ardour/types.h"
#include "ardour/audio_backend.h"
@ -21,6 +22,31 @@ class AudioBackendInfo;
class EngineStateController
{
public:
// public data types:
struct ChannelState {
std::string name;
bool active;
ChannelState ()
: name(""),
active(true)
{
}
ChannelState (const std::string& name)
: name(name),
active(true)
{
}
bool operator==(const ChannelState& rhs) {return rhs.name == name; }
};
typedef std::list<ChannelState> ChannelStateList;
static EngineStateController* instance();
//Interfaces
@ -40,10 +66,21 @@ public:
ARDOUR::pframes_t get_default_buffer_size() const;
void available_buffer_sizes_for_current_device(std::vector<ARDOUR::pframes_t>&) const;
uint32_t get_available_inputs_count() const {return 0; }
uint32_t get_available_outputs_count () const {return 0; }
uint32_t get_available_inputs_count() const {return _current_state->input_channel_states.size(); }
uint32_t get_available_outputs_count () const {return _current_state->output_channel_states.size(); }
bool is_setup_required() const {return ARDOUR::AudioEngine::instance()->setup_required (); }
void get_physical_audio_inputs (std::vector<std::string>&);
void get_physical_audio_outputs (std::vector<std::string>&);
void set_physical_audio_input_state(const std::string&, bool);
void set_physical_audio_output_state(const std::string&, bool);
bool get_physical_audio_input_state(const std::string&);
bool get_physical_audio_output_state(const std::string&);
void get_physical_audio_input_states(std::vector<ChannelState>&);
void get_physical_audio_output_states(std::vector<ChannelState>&);
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
@ -62,16 +99,26 @@ public:
void set_desired_sample_rate(framecnt_t);
//SIGNALS
//DATE UPDATE SIGNALS
/* this signal is emitted if the sample rate changes */
PBD::Signal0<void> SampleRateChanged;
/* this signal is emitted if the buffer size changes */
PBD::Signal0<void> BufferSizeChanged;
/* this signal is emitted if the device list changes */
PBD::Signal1<void, bool> DeviceListChanged;
//ENGINE STATE SIGNALS
/* this signal is emitted when the engine is started */
PBD::Signal0<void> EngineRunning;
/* this signal is emitted when the engine is stopped */
PBD::Signal0<void> EngineStopped;
/* this signal is emitted if the backend ever disconnects us */
PBD::Signal0<void> EngineHalted;
/* this signal is emitted if the i/o channel configuration changes */
PBD::Signal0<void> InputConfigChanged;
PBD::Signal0<void> OutputConfigChanged;
private:
EngineStateController(); // singleton
@ -79,7 +126,6 @@ private:
EngineStateController(const EngineStateController& ); // prohibited
EngineStateController& operator=(const EngineStateController&); // prohibited
// data types:
struct State {
std::string backend_name;
std::string device_name;
@ -87,17 +133,17 @@ private:
ARDOUR::pframes_t buffer_size;
uint32_t input_latency;
uint32_t output_latency;
uint32_t input_channels;
uint32_t output_channels;
bool active;
ChannelStateList input_channel_states;
ChannelStateList output_channel_states;
//bool active;
std::string midi_option;
State()
: input_latency (0)
, output_latency (0)
, input_channels (0)
, output_channels (0)
, active (false)
, input_channel_states (0)
, output_channel_states (0)
//, active (false)
{
}
@ -134,6 +180,10 @@ private:
// sets last active state as current state
// if no last active state found it loads default state
void _set_last_active_state_as_current();
// get gets available device channels from engine and updates internal controller state
void _update_device_channels_state(bool reconnect_session_routes = true);
// change channel configuration to stereo out mode
void _switch_to_stereo_out_io();
////////////////////////////////////////
// internal helper functions////////////
@ -144,11 +194,12 @@ private:
////////////////////////////////////////
// callbacks
void _on_engine_running();
void _on_engine_halted(const char*);
void _on_engine_halted();
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();
void _on_parameter_changed (const std::string&);
////////////////////////////////////////
////////////////////////////////////////

View file

@ -33,6 +33,9 @@ CONFIG_VARIABLE (bool, auto_connect_standard_busses, "auto-connect-standard-buss
CONFIG_VARIABLE (AutoConnectOption, output_auto_connect, "output-auto-connect", AutoConnectPhysical)
CONFIG_VARIABLE (AutoConnectOption, input_auto_connect, "input-auto-connect", AutoConnectPhysical)
/* Naming */
CONFIG_VARIABLE (TracksAutoNamingRule, tracks_auto_naming, "tracks-auto-naming", UseDefaultNames)
/* MIDI and MIDI related */
CONFIG_VARIABLE (bool, trace_midi_input, "trace-midi-input", false)

View file

@ -890,8 +890,8 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
friend class AudioEngine;
void set_block_size (pframes_t nframes);
void set_frame_rate (framecnt_t nframes);
void reconnect_existing_routes (bool withLock, bool reconnect_master = false);
void reconnect_existing_routes (bool withLock, bool reconnect_master = false);
protected:
friend class Route;
void schedule_curve_reallocation ();
@ -1337,7 +1337,6 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
void route_solo_changed (bool self_solo_change, void *src, boost::weak_ptr<Route>);
void route_solo_isolated_changed (void *src, boost::weak_ptr<Route>);
void update_route_solo_state (boost::shared_ptr<RouteList> r = boost::shared_ptr<RouteList>());
void update_output_mode();
void listen_position_changed ();
void solo_control_mode_changed ();

View file

@ -440,6 +440,11 @@ namespace ARDOUR {
AutoConnectPhysical = 0x1,
AutoConnectMaster = 0x2
};
enum TracksAutoNamingRule {
UseDefaultNames = 0x1,
NameAfterDriver = 0x2
};
enum SampleFormat {
FormatFloat = 0,
@ -613,6 +618,7 @@ namespace ARDOUR {
std::istream& operator>>(std::istream& o, ARDOUR::SampleFormat& sf);
std::istream& operator>>(std::istream& o, ARDOUR::HeaderFormat& sf);
std::istream& operator>>(std::istream& o, ARDOUR::AutoConnectOption& sf);
std::istream& operator>>(std::istream& o, ARDOUR::TracksAutoNamingRule& sf);
std::istream& operator>>(std::istream& o, ARDOUR::EditMode& sf);
std::istream& operator>>(std::istream& o, ARDOUR::MonitorModel& sf);
std::istream& operator>>(std::istream& o, ARDOUR::VUMeterStandard& sf);
@ -636,6 +642,7 @@ std::istream& operator>>(std::istream& o, ARDOUR::PositionLockStyle& sf);
std::ostream& operator<<(std::ostream& o, const ARDOUR::SampleFormat& sf);
std::ostream& operator<<(std::ostream& o, const ARDOUR::HeaderFormat& sf);
std::ostream& operator<<(std::ostream& o, const ARDOUR::AutoConnectOption& sf);
std::ostream& operator<<(std::ostream& o, const ARDOUR::TracksAutoNamingRule& sf);
std::ostream& operator<<(std::ostream& o, const ARDOUR::EditMode& sf);
std::ostream& operator<<(std::ostream& o, const ARDOUR::MonitorModel& sf);
std::ostream& operator<<(std::ostream& o, const ARDOUR::VUMeterStandard& sf);

View file

@ -442,6 +442,15 @@ AudioEngine::remove_session ()
}
void
AudioEngine::reconnect_session_routes()
{
if (_session) {
_session->reconnect_existing_routes(true, true);
}
}
void
AudioEngine::died ()
{

View file

@ -6,13 +6,15 @@
// Copyright (c) 2014 Waves. All rights reserved.
//
#include "engine_state_controller.h"
#include "ardour/engine_state_controller.h"
#include "ardour_ui.h"
#include "ardour/audioengine.h"
#include "ardour/rc_configuration.h"
#include "ardour/data_type.h"
#include "pbd/error.h"
#include "i18n.h"
#include "gui_thread.h"
using namespace ARDOUR;
using namespace PBD;
@ -50,14 +52,17 @@ EngineStateController::EngineStateController()
, _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());
AudioEngine::instance ()->Running.connect_same_thread (running_connection, boost::bind (&EngineStateController::_on_engine_running, this) );
AudioEngine::instance ()->Stopped.connect_same_thread (stopped_connection, boost::bind (&EngineStateController::_on_engine_stopped, this) );
AudioEngine::instance ()->Halted.connect_same_thread (stopped_connection, boost::bind (&EngineStateController::_on_engine_stopped, this) );
/* Subscribe for udpates from AudioEngine */
AudioEngine::instance()->SampleRateChanged.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());
AudioEngine::instance()->SampleRateChanged.connect_same_thread (update_connections, boost::bind (&EngineStateController::_on_sample_rate_change, this, _1) );
AudioEngine::instance()->BufferSizeChanged.connect_same_thread (update_connections, boost::bind (&EngineStateController::_on_buffer_size_change, this, _1) );
AudioEngine::instance()->DeviceListChanged.connect_same_thread (update_connections, boost::bind (&EngineStateController::_on_device_list_change, this) );
/* Global configuration parameters update */
Config->ParameterChanged.connect_same_thread (update_connections, boost::bind (&EngineStateController::_on_parameter_changed, this, _1) );
_deserialize_and_load_states();
_set_last_active_state_as_current();
@ -97,8 +102,7 @@ EngineStateController::_set_last_active_state_as_current()
std::vector<const AudioBackendInfo*> backends = AudioEngine::instance()->available_backends();
if (!backends.empty() )
{
if (!backends.empty() ) {
if (!set_new_backend_as_current(backends.front()->name ) ) {
std::cerr << "\tfailed to set backend [" << backends.front()->name << "]\n";
@ -378,6 +382,186 @@ EngineStateController::set_new_buffer_size_in_controller(pframes_t buffer_size)
}
void
EngineStateController::get_physical_audio_inputs(std::vector<std::string>& port_names)
{
port_names.clear();
boost::shared_ptr<AudioBackend> backend = AudioEngine::instance()->current_backend();
assert(backend);
// update audio input states
std::vector<std::string> phys_audio_inputs;
backend->get_physical_inputs(DataType::AUDIO, phys_audio_inputs);
ChannelStateList &input_states = _current_state->input_channel_states;
std::vector<std::string>::const_iterator input_iter = phys_audio_inputs.begin();
for (; input_iter != phys_audio_inputs.end(); ++input_iter) {
ChannelStateList::const_iterator found_state_iter;
found_state_iter = std::find(input_states.begin(), input_states.end(), ChannelState(*input_iter) );
if (found_state_iter != input_states.end() && found_state_iter->active) {
port_names.push_back(found_state_iter->name);
}
}
}
void
EngineStateController::get_physical_audio_outputs(std::vector<std::string>& port_names)
{
port_names.clear();
boost::shared_ptr<AudioBackend> backend = AudioEngine::instance()->current_backend();
assert(backend);
// update audio input states
std::vector<std::string> phys_audio_outputs;
backend->get_physical_outputs(DataType::AUDIO, phys_audio_outputs);
ChannelStateList &output_states = _current_state->output_channel_states;
std::vector<std::string>::const_iterator output_iter = phys_audio_outputs.begin();
for (; output_iter != phys_audio_outputs.end(); ++output_iter) {
ChannelStateList::const_iterator found_state_iter;
found_state_iter = std::find(output_states.begin(), output_states.end(), ChannelState(*output_iter) );
if (found_state_iter != output_states.end() && found_state_iter->active) {
port_names.push_back(found_state_iter->name);
}
}
}
void
EngineStateController::set_physical_audio_input_state(const std::string& port_name, bool state)
{
ChannelStateList &input_states = _current_state->input_channel_states;
ChannelStateList::iterator found_state_iter;
found_state_iter = std::find(input_states.begin(), input_states.end(), ChannelState(port_name) );
if (found_state_iter != input_states.end() && found_state_iter->active != state ) {
found_state_iter->active = state;
AudioEngine::instance()->reconnect_session_routes();
InputConfigChanged();
}
}
void
EngineStateController::set_physical_audio_output_state(const std::string& port_name, bool state)
{
ChannelStateList &output_states = _current_state->output_channel_states;
ChannelStateList::iterator target_state_iter;
target_state_iter = std::find(output_states.begin(), output_states.end(), ChannelState(port_name) );
if (target_state_iter != output_states.end() && target_state_iter->active != state ) {
target_state_iter->active = state;
// if StereoOut mode is used
if (Config->get_output_auto_connect() & AutoConnectMaster) {
// get next element
ChannelStateList::iterator next_state_iter(target_state_iter);
// loopback
if (++next_state_iter == output_states.end() ) {
next_state_iter = output_states.begin();
}
// if current was set to active - activate next and disable the rest
if (target_state_iter->active ) {
next_state_iter->active = true;
} else {
// if current was deactivated but the next is active
if (next_state_iter->active) {
if (++next_state_iter == output_states.end() ) {
next_state_iter = output_states.begin();
}
next_state_iter->active = true;
} else {
// if current was deactivated but the previous is active - restore the state of current
target_state_iter->active = true; // state restored;
--target_state_iter; // switch to previous to make it stop point
target_state_iter->active = true;
}
}
while (++next_state_iter != target_state_iter) {
if (next_state_iter == output_states.end() ) {
next_state_iter = output_states.begin();
// we jumped, so additional check is required
if (next_state_iter == target_state_iter) {
break;
}
}
next_state_iter->active = false;
}
}
AudioEngine::instance()->reconnect_session_routes();
OutputConfigChanged();
}
}
bool
EngineStateController::get_physical_audio_input_state(const std::string& port_name)
{
bool state = false;
ChannelStateList &input_states = _current_state->input_channel_states;
ChannelStateList::iterator found_state_iter;
found_state_iter = std::find(input_states.begin(), input_states.end(), ChannelState(port_name) );
if (found_state_iter != input_states.end() ) {
state = found_state_iter->active;
}
return state;
}
bool
EngineStateController::get_physical_audio_output_state(const std::string& port_name)
{
bool state = false;
ChannelStateList &output_states = _current_state->output_channel_states;
ChannelStateList::iterator found_state_iter;
found_state_iter = std::find(output_states.begin(), output_states.end(), ChannelState(port_name) );
if (found_state_iter != output_states.end() ) {
state = found_state_iter->active;
}
return state;
}
void
EngineStateController::get_physical_audio_input_states(std::vector<ChannelState>& channel_states)
{
ChannelStateList &input_states = _current_state->input_channel_states;
channel_states.assign(input_states.begin(), input_states.end());
}
void
EngineStateController::get_physical_audio_output_states(std::vector<ChannelState>& channel_states)
{
ChannelStateList &output_states = _current_state->output_channel_states;
channel_states.assign(output_states.begin(), output_states.end());
}
void
EngineStateController::_on_sample_rate_change(framecnt_t new_sample_rate)
{
@ -471,17 +655,125 @@ EngineStateController::_on_device_list_change()
}
void
EngineStateController::_update_device_channels_state(bool reconnect_session_routes/*=true*/)
{
boost::shared_ptr<AudioBackend> backend = AudioEngine::instance()->current_backend();
assert(backend);
// update audio input states
std::vector<std::string> phys_audio_inputs;
backend->get_physical_inputs(DataType::AUDIO, phys_audio_inputs);
ChannelStateList new_input_states;
ChannelStateList &input_states = _current_state->input_channel_states;
std::vector<std::string>::const_iterator input_iter = phys_audio_inputs.begin();
for (; input_iter != phys_audio_inputs.end(); ++input_iter) {
ChannelState state(*input_iter);
ChannelStateList::const_iterator found_state_iter = std::find(input_states.begin(), input_states.end(), state);
if (found_state_iter != input_states.end() ) {
new_input_states.push_back(*found_state_iter);
} else {
new_input_states.push_back(state);
}
}
_current_state->input_channel_states = new_input_states;
// update audio output state
std::vector<std::string> phys_audio_outputs;
backend->get_physical_outputs(DataType::AUDIO, phys_audio_outputs);
ChannelStateList new_output_states;
ChannelStateList &output_states = _current_state->output_channel_states;
std::vector<std::string>::const_iterator output_iter = phys_audio_outputs.begin();
for (; output_iter != phys_audio_outputs.end(); ++output_iter) {
ChannelState state(*output_iter);
ChannelStateList::const_iterator found_state_iter = std::find(output_states.begin(), output_states.end(), state);
if (found_state_iter != output_states.end() ) {
new_output_states.push_back(*found_state_iter);
} else {
new_output_states.push_back(state);
}
}
_current_state->output_channel_states = new_output_states;
if (Config->get_output_auto_connect() & AutoConnectMaster) {
_switch_to_stereo_out_io();
}
// update midi channels
/* provide implementation */
if (reconnect_session_routes) {
AudioEngine::instance()->reconnect_session_routes();
}
}
void
EngineStateController::_switch_to_stereo_out_io()
{
ChannelStateList &output_states = _current_state->output_channel_states;
ChannelStateList::iterator iter = output_states.begin();
uint32_t active_channels = 2;
for (; iter != output_states.end(); ++iter) {
if (active_channels) {
iter->active = true;
--active_channels;
} else {
iter->active = false;
}
}
}
void
EngineStateController::_on_engine_running ()
{
_update_device_channels_state();
_serialize_and_save_current_state();
EngineRunning();
}
void
EngineStateController::_on_engine_stopped ()
{
EngineStopped();
}
void
EngineStateController::_on_engine_halted ()
{
EngineHalted();
}
void
EngineStateController::_on_parameter_changed (const std::string& parameter_name)
{
if (parameter_name == "output-auto-connect") {
if (Config->get_output_auto_connect() & AutoConnectMaster) {
_switch_to_stereo_out_io();
AudioEngine::instance()->reconnect_session_routes();
OutputConfigChanged(); // emit a signal
}
}
}
bool
EngineStateController::push_current_state_to_backend(bool start)
{
@ -501,7 +793,7 @@ EngineStateController::push_current_state_to_backend(bool start)
if (state_changed) {
if (was_running) {
if (ARDOUR_UI::instance()->disconnect_from_engine () ) {
if (AudioEngine::instance()->stop () ) {
return false;
}
}
@ -539,10 +831,8 @@ EngineStateController::push_current_state_to_backend(bool start)
//}
}
_serialize_and_save_current_state();
if(start || (was_running && state_changed) ) {
if (ARDOUR_UI::instance()->reconnect_to_engine () ) {
if (AudioEngine::instance()->start () ) {
return false;
}
}

View file

@ -95,6 +95,7 @@ setup_enum_writer ()
AutoState _AutoState;
AutoStyle _AutoStyle;
AutoConnectOption _AutoConnectOption;
TracksAutoNamingRule _TracksAutoNamingRule;
Session::StateOfTheState _Session_StateOfTheState;
Route::Flag _Route_Flag;
Source::Flag _Source_Flag;
@ -314,6 +315,10 @@ setup_enum_writer ()
REGISTER_ENUM (AutoConnectMaster);
REGISTER_BITS (_AutoConnectOption);
REGISTER_ENUM (UseDefaultNames);
REGISTER_ENUM (NameAfterDriver);
REGISTER_BITS (_TracksAutoNamingRule);
REGISTER_ENUM (FormatFloat);
REGISTER_ENUM (FormatInt24);
REGISTER_ENUM (FormatInt16);
@ -657,6 +662,7 @@ std::ostream& operator<<(std::ostream& o, const SampleFormat& var)
std::string s = enum_2_string (var);
return o << s;
}
std::istream& operator>>(std::istream& o, AutoConnectOption& var)
{
std::string s;
@ -671,6 +677,20 @@ std::ostream& operator<<(std::ostream& o, const AutoConnectOption& var)
return o << s;
}
std::istream& operator>>(std::istream& o, TracksAutoNamingRule& var)
{
std::string s;
o >> s;
var = (TracksAutoNamingRule) string_2_enum (s, var);
return o;
}
std::ostream& operator<<(std::ostream& o, const TracksAutoNamingRule& var)
{
std::string s = enum_2_string (var);
return o << s;
}
std::istream& operator>>(std::istream& o, MonitorModel& var)
{
std::string s;

View file

@ -65,6 +65,7 @@
#include "ardour/control_protocol_manager.h"
#include "ardour/data_type.h"
#include "ardour/debug.h"
#include "ardour/engine_state_controller.h"
#include "ardour/filename_extensions.h"
#include "ardour/graph.h"
#include "ardour/midiport_manager.h"
@ -358,12 +359,11 @@ Session::Session (AudioEngine &eng,
*/
if (_is_new && ARDOUR::Profile->get_trx () ) {
uint32_t how_many (0);
if (_engine.current_backend()->input_channels () > 0){
how_many = _engine.current_backend()->input_channels ();
} else {
const string device_name = _engine.current_backend()->device_name ();
how_many = _engine.current_backend()->available_input_channel_count (device_name);
}
std::vector<std::string> inputs;
EngineStateController::instance()->get_physical_audio_inputs(inputs);
how_many = inputs.size();
list<boost::shared_ptr<AudioTrack> > tracks = new_audio_track (1, 1, Normal, 0, how_many, string() );
@ -813,7 +813,12 @@ Session::auto_connect_master_bus ()
vector<string> outputs[DataType::num_types];
for (uint32_t i = 0; i < DataType::num_types; ++i) {
_engine.get_physical_outputs (DataType (DataType::Symbol (i)), outputs[i]);
if ( Profile->get_trx() && DataType::Symbol (i) == DataType::AUDIO) {
EngineStateController::instance()->get_physical_audio_outputs(outputs[i]);
} else {
_engine.get_physical_outputs (DataType (DataType::Symbol (i)), outputs[i]);
}
}
for (uint32_t n = 0; n < limit; ++n) {
@ -973,7 +978,13 @@ Session::add_monitor_section ()
vector<string> outputs[DataType::num_types];
for (uint32_t i = 0; i < DataType::num_types; ++i) {
_engine.get_physical_outputs (DataType (DataType::Symbol (i)), outputs[i]);
if ( Profile->get_trx() && DataType::Symbol (i) == DataType::AUDIO) {
EngineStateController::instance()->get_physical_audio_outputs(outputs[i]);
} else {
_engine.get_physical_outputs (DataType (DataType::Symbol (i)), outputs[i]);
}
}
uint32_t mod = outputs[DataType::AUDIO].size();
@ -2000,8 +2011,17 @@ Session::auto_connect_route (boost::shared_ptr<Route> route, ChanCount& existing
vector<string> physinputs;
vector<string> physoutputs;
_engine.get_physical_outputs (*t, physoutputs);
_engine.get_physical_inputs (*t, physinputs);
if ( Profile->get_trx() && *t == DataType::AUDIO) {
EngineStateController::instance()->get_physical_audio_outputs(physoutputs);
} else {
_engine.get_physical_outputs (*t, physoutputs);
}
if ( Profile->get_trx() && *t == DataType::AUDIO) {
EngineStateController::instance()->get_physical_audio_inputs(physinputs);
} else {
_engine.get_physical_inputs (*t, physinputs);
}
if (!physinputs.empty() && connect_inputs) {
uint32_t nphysical_in = physinputs.size();
@ -2097,7 +2117,6 @@ Session::auto_connect_route (boost::shared_ptr<Route> route, ChanCount& existing
void
Session::reconnect_existing_routes (bool withLock, bool reconnect_master)
{
PBD::stacktrace (cerr, 20);
Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock (), Glib::Threads::NOT_LOCK);
if (withLock) {
@ -2125,8 +2144,8 @@ Session::reconnect_existing_routes (bool withLock, bool reconnect_master)
vector<string> physinputs;
vector<string> physoutputs;
_engine.get_physical_outputs (DataType::AUDIO, physoutputs);
_engine.get_physical_inputs (DataType::AUDIO, physinputs);
EngineStateController::instance()->get_physical_audio_outputs(physoutputs);
EngineStateController::instance()->get_physical_audio_inputs(physinputs);
uint32_t input_n = 0;
uint32_t output_n = 0;

View file

@ -3512,21 +3512,11 @@ Session::config_changed (std::string p, bool ours)
reconnect_ltc_output ();
} else if (p == "timecode-generator-offset") {
ltc_tx_parse_offset();
} else if (p == "output-auto-connect") {
if (ARDOUR::Profile->get_trx() ) {
update_output_mode();
}
}
}
set_dirty ();
}
void
Session::update_output_mode()
{
reconnect_existing_routes(true, true);
}
void
Session::set_history_depth (uint32_t d)
{

View file

@ -69,6 +69,7 @@ libardour_sources = [
'element_import_handler.cc',
'element_importer.cc',
'engine_slave.cc',
'engine_state_controller.cc',
'enums.cc',
'event_type_map.cc',
'export_channel.cc',