the big Route structure refactor. !!!! THIS WILL ***NOT LOAD*** PRIOR 3.0 or 2.X SESSIONS !!!! BREAKAGE IS EXPECTED !!!! IF YOU HAVE AND NEED A WORKING 3.0 DO **NOT** UPDATE. !!!! otherwise, update and enjoy the steadily emerging joys of this major reworking of ardour internals

git-svn-id: svn://localhost/ardour2/branches/3.0@5137 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Paul Davis 2009-06-09 20:21:19 +00:00
parent 9bd274bfde
commit e6eb059576
77 changed files with 2688 additions and 3801 deletions

View File

@ -324,7 +324,7 @@ ActionManager::set_sensitive (vector<RefPtr<Action> >& actions, bool state)
void
ActionManager::uncheck_toggleaction (const char * name)
{
char *last_slash = strrchr (name, '/');
const char *last_slash = strrchr (name, '/');
if (last_slash == 0) {
fatal << string_compose (_("programmer error: %1 %2"), X_("illegal toggle action name"), name) << endmsg;
@ -339,7 +339,7 @@ ActionManager::uncheck_toggleaction (const char * name)
memcpy (group_name, name + 10, len);
group_name[len] = '\0';
char* action_name = last_slash + 1;
const char* action_name = last_slash + 1;
RefPtr<Action> act = get_action (group_name, action_name);
if (act) {

View File

@ -1835,44 +1835,6 @@ ARDOUR_UI::stop_blinking ()
}
}
void
ARDOUR_UI::name_io_setup (AudioEngine& engine,
string& buf,
IO& io,
bool in)
{
vector<string> connections;
if (in) {
if (io.n_inputs().n_total() == 0) {
buf = _("none");
return;
}
/* XXX we're not handling multiple ports yet. */
if (io.input(0)->get_connections(connections) == 0) {
buf = _("off");
} else {
buf = connections.front();
}
} else {
if (io.n_outputs().n_total() == 0) {
buf = _("none");
return;
}
/* XXX we're not handling multiple ports yet. */
if (io.output(0)->get_connections(connections) == 0) {
buf = _("off");
} else {
buf = connections.front();
}
}
}
/** Ask the user for the name of a new shapshot and then take it.
*/

View File

@ -176,8 +176,6 @@ class ARDOUR_UI : public Gtkmm2ext::UI
static sigc::signal<void> SuperRapidScreenUpdate;
static sigc::signal<void,nframes_t, bool, nframes_t> Clock;
void name_io_setup (ARDOUR::AudioEngine&, std::string&, ARDOUR::IO& io, bool in);
XMLNode* editor_settings() const;
XMLNode* mixer_settings () const;
XMLNode* keyboard_settings () const;

View File

@ -37,6 +37,7 @@
#include <gtkmm2ext/bindable_button.h>
#include <gtkmm2ext/utils.h>
#include "ardour/amp.h"
#include "ardour/audio_diskstream.h"
#include "ardour/audioplaylist.h"
#include "ardour/event_type_map.h"
@ -347,13 +348,14 @@ AudioTimeAxisView::create_automation_child (const Evoral::Parameter& param, bool
return;
}
boost::shared_ptr<AutomationTimeAxisView> gain_track(new AutomationTimeAxisView (_session,
_route, _route, c,
_editor,
*this,
false,
parent_canvas,
_route->describe_parameter(param)));
boost::shared_ptr<AutomationTimeAxisView>
gain_track(new AutomationTimeAxisView (_session,
_route, _route->amp(), c,
_editor,
*this,
false,
parent_canvas,
_route->amp()->describe_parameter(param)));
add_automation_child(Evoral::Parameter(GainAutomation), gain_track, show);
@ -396,11 +398,11 @@ AudioTimeAxisView::ensure_pan_views (bool show)
/* we don't already have an AutomationTimeAxisView for this parameter */
std::string const name = _route->describe_parameter (pan_control->parameter ());
std::string const name = _route->panner()->describe_parameter (pan_control->parameter ());
boost::shared_ptr<AutomationTimeAxisView> pan_track (
new AutomationTimeAxisView (_session,
_route, _route, pan_control,
_route, _route->panner(), pan_control,
_editor,
*this,
false,

View File

@ -255,15 +255,20 @@ void
AutomationTimeAxisView::set_automation_state (AutoState state)
{
if (!ignore_state_request) {
_automatable->set_parameter_automation_state (_control->parameter(), state);
#if 0
if (_route == _automatable) { // This is a time axis for route (not region) automation
_route->set_parameter_automation_state (_control->parameter(), state);
}
if (_control->list())
_control->alist()->set_automation_state(state);
#endif
}
if (_view)
if (_view) {
_view->set_automation_state (state);
}
}
void

View File

@ -67,10 +67,12 @@ Editor::handle_new_route (RouteList& routes)
if (route->is_hidden()) {
continue;
}
if (route->default_type() == ARDOUR::DataType::AUDIO)
DataType dt = route->input()->default_type();
if (dt == ARDOUR::DataType::AUDIO)
tv = new AudioTimeAxisView (*this, *session, route, *track_canvas);
else if (route->default_type() == ARDOUR::DataType::MIDI)
else if (dt == ARDOUR::DataType::MIDI)
tv = new MidiTimeAxisView (*this, *session, route, *track_canvas);
else
throw unknown_type();

View File

@ -112,14 +112,14 @@ PortExportChannelSelector::fill_route_list ()
/* Add master bus and then everything else */
ARDOUR::IO * master = session->master_out().get();
ARDOUR::IO* master = session->master_out()->output().get();
channel_view.add_route (master);
for (RouteList::iterator it = routes.begin(); it != routes.end(); ++it) {
if (it->get() == master) {
if ((*it)->output().get() == master) {
continue;
}
channel_view.add_route (it->get());
channel_view.add_route ((*it)->output().get());
}
update_channel_count ();
@ -261,27 +261,27 @@ PortExportChannelSelector::ChannelTreeView::set_config (ChannelConfigPtr c)
}
void
PortExportChannelSelector::ChannelTreeView::add_route (ARDOUR::IO * route)
PortExportChannelSelector::ChannelTreeView::add_route (ARDOUR::IO * io)
{
Gtk::TreeModel::iterator iter = route_list->append();
Gtk::TreeModel::Row row = *iter;
row[route_cols.selected] = false;
row[route_cols.name] = route->name();
row[route_cols.io] = route;
row[route_cols.name] = io->name();
row[route_cols.io] = io;
/* Initialize port list */
Glib::RefPtr<Gtk::ListStore> port_list = Gtk::ListStore::create (route_cols.port_cols);
row[route_cols.port_list_col] = port_list;
uint32_t outs = route->n_outputs().n_audio();
uint32_t outs = io->n_ports().n_audio();
for (uint32_t i = 0; i < outs; ++i) {
iter = port_list->append();
row = *iter;
row[route_cols.port_cols.selected] = false;
row[route_cols.port_cols.port] = route->audio_output (i);
row[route_cols.port_cols.port] = io->audio (i);
std::ostringstream oss;
oss << "Out-" << (i + 1);

View File

@ -160,57 +160,58 @@ GainMeterBase::~GainMeterBase ()
}
void
GainMeterBase::set_io (boost::shared_ptr<IO> io)
GainMeterBase::set_controls (boost::shared_ptr<Route> r,
boost::shared_ptr<PeakMeter> pm,
boost::shared_ptr<AutomationControl> gc,
boost::shared_ptr<Automatable> gc_owner)
{
connections.clear ();
_io = io;
if (!_io) {
if (!pm && !gc) {
level_meter->set_meter (0);
gain_slider->set_controllable (boost::shared_ptr<PBD::Controllable>());
_meter.reset ();
_gain_control.reset ();
_route.reset ();
return;
}
level_meter->set_meter (&_io->peak_meter());
gain_slider->set_controllable (_io->gain_control());
_meter = pm;
_gain_control = gc;
_route = r;
boost::shared_ptr<Route> r;
if ((r = boost::dynamic_pointer_cast<Route> (_io)) != 0) {
if (!r->is_hidden()) {
using namespace Menu_Helpers;
level_meter->set_meter (pm.get());
gain_slider->set_controllable (gc);
gain_astate_menu.items().clear ();
gain_astate_menu.items().push_back (MenuElem (_("Manual"),
bind (mem_fun (*_io, &IO::set_parameter_automation_state),
Evoral::Parameter(GainAutomation), (AutoState) Off)));
gain_astate_menu.items().push_back (MenuElem (_("Play"),
bind (mem_fun (*_io, &IO::set_parameter_automation_state),
Evoral::Parameter(GainAutomation), (AutoState) Play)));
gain_astate_menu.items().push_back (MenuElem (_("Write"),
bind (mem_fun (*_io, &IO::set_parameter_automation_state),
Evoral::Parameter(GainAutomation), (AutoState) Write)));
gain_astate_menu.items().push_back (MenuElem (_("Touch"),
bind (mem_fun (*_io, &IO::set_parameter_automation_state),
Evoral::Parameter(GainAutomation), (AutoState) Touch)));
connections.push_back (gain_automation_style_button.signal_button_press_event().connect (mem_fun(*this, &GainMeterBase::gain_automation_style_button_event), false));
connections.push_back (gain_automation_state_button.signal_button_press_event().connect (mem_fun(*this, &GainMeterBase::gain_automation_state_button_event), false));
connections.push_back (r->gain_control()->alist()->automation_state_changed.connect (mem_fun(*this, &GainMeter::gain_automation_state_changed)));
connections.push_back (r->gain_control()->alist()->automation_style_changed.connect (mem_fun(*this, &GainMeter::gain_automation_style_changed)));
gain_automation_state_changed ();
}
if (!_route || !_route->is_hidden()) {
using namespace Menu_Helpers;
gain_astate_menu.items().clear ();
gain_astate_menu.items().push_back (MenuElem (_("Manual"),
bind (mem_fun (*(gc_owner.get()), &Automatable::set_parameter_automation_state),
Evoral::Parameter(GainAutomation), (AutoState) Off)));
gain_astate_menu.items().push_back (MenuElem (_("Play"),
bind (mem_fun (*(gc_owner.get()), &Automatable::set_parameter_automation_state),
Evoral::Parameter(GainAutomation), (AutoState) Play)));
gain_astate_menu.items().push_back (MenuElem (_("Write"),
bind (mem_fun (*(gc_owner.get()), &Automatable::set_parameter_automation_state),
Evoral::Parameter(GainAutomation), (AutoState) Write)));
gain_astate_menu.items().push_back (MenuElem (_("Touch"),
bind (mem_fun (*(gc_owner.get()), &Automatable::set_parameter_automation_state),
Evoral::Parameter(GainAutomation), (AutoState) Touch)));
connections.push_back (gain_automation_style_button.signal_button_press_event().connect (mem_fun(*this, &GainMeterBase::gain_automation_style_button_event), false));
connections.push_back (gain_automation_state_button.signal_button_press_event().connect (mem_fun(*this, &GainMeterBase::gain_automation_state_button_event), false));
connections.push_back (gc->alist()->automation_state_changed.connect (mem_fun(*this, &GainMeter::gain_automation_state_changed)));
connections.push_back (gc->alist()->automation_style_changed.connect (mem_fun(*this, &GainMeter::gain_automation_style_changed)));
gain_automation_state_changed ();
}
//cerr << "Connect " << this << " to gain change for " << _io->name() << endl;
connections.push_back (_io->gain_control()->Changed.connect (mem_fun(*this, &GainMeterBase::gain_changed)));
connections.push_back (gc->Changed.connect (mem_fun (*this, &GainMeterBase::gain_changed)));
gain_changed ();
show_gain ();
@ -272,10 +273,8 @@ GainMeterBase::peak_button_release (GdkEventButton* ev)
if (ev->button == 1 && Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier|Keyboard::TertiaryModifier)) {
ResetAllPeakDisplays ();
} else if (ev->button == 1 && Keyboard::modifier_state_equals (ev->state, Keyboard::PrimaryModifier)) {
boost::shared_ptr<Route> r;
if ((r = boost::dynamic_pointer_cast<Route> (_io)) != 0) {
ResetGroupPeakDisplays (r->mix_group());
if (_route) {
ResetGroupPeakDisplays (_route->mix_group());
}
} else {
reset_peak_display ();
@ -287,12 +286,7 @@ GainMeterBase::peak_button_release (GdkEventButton* ev)
void
GainMeterBase::reset_peak_display ()
{
boost::shared_ptr<Route> r;
if ((r = boost::dynamic_pointer_cast<Route> (_io)) != 0) {
r->peak_meter().reset_max();
}
_meter->reset_max();
level_meter->clear_meters();
max_peak = -INFINITY;
peak_display.set_label (_("-Inf"));
@ -302,13 +296,9 @@ GainMeterBase::reset_peak_display ()
void
GainMeterBase::reset_group_peak_display (RouteGroup* group)
{
boost::shared_ptr<Route> r;
if ((r = boost::dynamic_pointer_cast<Route> (_io)) != 0) {
if (group == r->mix_group()) {
reset_peak_display ();
if (_route && group == _route->mix_group()) {
reset_peak_display ();
}
}
}
void
@ -354,7 +344,7 @@ GainMeterBase::gain_activated ()
f = min (f, 6.0f);
_io->gain_control()->set_value (dB_to_coefficient(f));
_gain_control->set_value (dB_to_coefficient(f));
if (gain_display.has_focus()) {
PublicEditor::instance().reset_focus();
@ -384,7 +374,7 @@ GainMeterBase::gain_adjusted ()
//cerr << this << " for " << _io->name() << " GAIN ADJUSTED\n";
if (!ignore_toggle) {
//cerr << "Set GC\n";
_io->gain_control()->set_value (slider_position_to_gain (gain_adjustment.get_value()));
_gain_control->set_value (slider_position_to_gain (gain_adjustment.get_value()));
//cerr << "Set GC OUT\n";
}
show_gain ();
@ -393,7 +383,7 @@ GainMeterBase::gain_adjusted ()
void
GainMeterBase::effective_gain_display ()
{
gfloat value = gain_to_slider_position (_io->effective_gain());
gfloat value = gain_to_slider_position (_gain_control->get_value());
//cerr << this << " for " << _io->name() << " EGAIN = " << value
// << " AGAIN = " << gain_adjustment.get_value () << endl;
@ -428,7 +418,7 @@ void
GainMeterBase::update_gain_sensitive ()
{
static_cast<Gtkmm2ext::SliderController*>(gain_slider)->set_sensitive (
!(_io->gain_control()->alist()->automation_state() & Play));
!(_gain_control->alist()->automation_state() & Play));
}
@ -459,7 +449,7 @@ GainMeterBase::meter_press(GdkEventButton* ev)
wait_for_release = false;
if ((_route = boost::dynamic_pointer_cast<Route>(_io)) == 0) {
if (!_route) {
return FALSE;
}
@ -482,10 +472,10 @@ GainMeterBase::meter_press(GdkEventButton* ev)
}
}
if (ev->button == 1 || Keyboard::is_button2_event (ev)) {
if (_route && (ev->button == 1 || Keyboard::is_button2_event (ev))) {
if (Keyboard::modifier_state_equals (ev->state, Keyboard::ModifierMask (Keyboard::PrimaryModifier|Keyboard::TertiaryModifier))) {
/* Primary+Tertiary-click applies change to all routes */
_session.begin_reversible_command (_("meter point change"));
@ -534,10 +524,8 @@ GainMeterBase::meter_release(GdkEventButton* ev)
if (wait_for_release){
wait_for_release = false;
boost::shared_ptr<Route> r;
if ((r = boost::dynamic_pointer_cast<Route>(_io)) != 0) {
set_meter_point (*r, old_meter_point);
if (_route) {
set_meter_point (*_route, old_meter_point);
}
}
}
@ -566,9 +554,7 @@ GainMeterBase::set_mix_group_meter_point (Route& route, MeterPoint mp)
void
GainMeterBase::meter_point_clicked ()
{
boost::shared_ptr<Route> r;
if ((r = boost::dynamic_pointer_cast<Route> (_io)) != 0) {
if (_route) {
/* WHAT? */
}
}
@ -576,14 +562,14 @@ GainMeterBase::meter_point_clicked ()
gint
GainMeterBase::start_gain_touch (GdkEventButton* ev)
{
_io->gain_control()->start_touch ();
_gain_control->start_touch ();
return FALSE;
}
gint
GainMeterBase::end_gain_touch (GdkEventButton* ev)
{
_io->gain_control()->stop_touch ();
_gain_control->stop_touch ();
return FALSE;
}
@ -686,10 +672,10 @@ GainMeterBase::gain_automation_style_changed ()
{
switch (_width) {
case Wide:
gain_automation_style_button.set_label (astyle_string(_io->gain_control()->alist()->automation_style()));
gain_automation_style_button.set_label (astyle_string(_gain_control->alist()->automation_style()));
break;
case Narrow:
gain_automation_style_button.set_label (short_astyle_string(_io->gain_control()->alist()->automation_style()));
gain_automation_style_button.set_label (short_astyle_string(_gain_control->alist()->automation_style()));
break;
}
}
@ -703,14 +689,14 @@ GainMeterBase::gain_automation_state_changed ()
switch (_width) {
case Wide:
gain_automation_state_button.set_label (astate_string(_io->gain_control()->alist()->automation_state()));
gain_automation_state_button.set_label (astate_string(_gain_control->alist()->automation_state()));
break;
case Narrow:
gain_automation_state_button.set_label (short_astate_string(_io->gain_control()->alist()->automation_state()));
gain_automation_state_button.set_label (short_astate_string(_gain_control->alist()->automation_state()));
break;
}
x = (_io->gain_control()->alist()->automation_state() != Off);
x = (_gain_control->alist()->automation_state() != Off);
if (gain_automation_state_button.get_active() != x) {
ignore_toggle = true;
@ -811,8 +797,11 @@ GainMeter::GainMeter (Session& s)
meter_metric_area.signal_expose_event().connect (mem_fun(*this, &GainMeter::meter_metrics_expose));
}
void
GainMeter::set_io (boost::shared_ptr<IO> io)
void
GainMeter::set_controls (boost::shared_ptr<Route> r,
boost::shared_ptr<PeakMeter> meter,
boost::shared_ptr<AutomationControl> gain_control,
boost::shared_ptr<Automatable> gc_owner)
{
if (level_meter->get_parent()) {
hbox.remove (*level_meter);
@ -826,30 +815,17 @@ GainMeter::set_io (boost::shared_ptr<IO> io)
fader_vbox->remove (gain_automation_state_button);
}
GainMeterBase::set_io (io);
GainMeterBase::set_controls (r, meter, gain_control, gc_owner);
boost::shared_ptr<Route> r;
if ((r = boost::dynamic_pointer_cast<Route> (_io)) != 0) {
/*
if we have a non-hidden route (ie. we're not the click or the auditioner),
pack some route-dependent stuff.
*/
gain_display_box.pack_end (peak_display, true, true);
hbox.pack_end (*level_meter, true, true);
if (!r->is_hidden()) {
fader_vbox->pack_start (gain_automation_state_button, false, false, 0);
}
} else {
/* we're managing a non-Route IO (e.g. Send) */
gain_display_box.pack_end (peak_display, true, true);
hbox.pack_end (*level_meter, true, true);
/*
if we have a non-hidden route (ie. we're not the click or the auditioner),
pack some route-dependent stuff.
*/
gain_display_box.pack_end (peak_display, true, true);
hbox.pack_end (*level_meter, true, true);
if (!r->is_hidden()) {
fader_vbox->pack_start (gain_automation_state_button, false, false, 0);
}
}
@ -941,7 +917,7 @@ GainMeter::meter_metrics_expose (GdkEventExpose *ev)
boost::shared_ptr<PBD::Controllable>
GainMeterBase::get_controllable()
{
return _io->gain_control();
return _gain_control;
}

View File

@ -46,6 +46,8 @@ namespace ARDOUR {
class Session;
class Route;
class RouteGroup;
class PeakMeter;
class Automatable;
}
namespace Gtkmm2ext {
class FastMeter;
@ -62,8 +64,10 @@ class GainMeterBase : virtual public sigc::trackable
bool horizontal);
virtual ~GainMeterBase ();
virtual void set_io (boost::shared_ptr<ARDOUR::IO>);
boost::shared_ptr<ARDOUR::IO> io() const { return _io; }
virtual void set_controls (boost::shared_ptr<ARDOUR::Route> route,
boost::shared_ptr<ARDOUR::PeakMeter> meter,
boost::shared_ptr<ARDOUR::AutomationControl> gain_control,
boost::shared_ptr<ARDOUR::Automatable> gc_owner);
void update_gain_sensitive ();
void update_meters ();
@ -83,7 +87,9 @@ class GainMeterBase : virtual public sigc::trackable
protected:
friend class MixerStrip;
boost::shared_ptr<ARDOUR::IO> _io;
boost::shared_ptr<ARDOUR::Route> _route;
boost::shared_ptr<ARDOUR::PeakMeter> _meter;
boost::shared_ptr<ARDOUR::AutomationControl> _gain_control;
ARDOUR::Session& _session;
std::vector<sigc::connection> connections;
@ -176,7 +182,10 @@ class GainMeter : public GainMeterBase, public Gtk::VBox
GainMeter (ARDOUR::Session&);
~GainMeter () {}
void set_io (boost::shared_ptr<ARDOUR::IO>);
virtual void set_controls (boost::shared_ptr<ARDOUR::Route> route,
boost::shared_ptr<ARDOUR::PeakMeter> meter,
boost::shared_ptr<ARDOUR::AutomationControl> gain_control,
boost::shared_ptr<ARDOUR::Automatable> gc_owner);
int get_gm_width ();
void setup_meters (int len=0);

View File

@ -41,12 +41,14 @@
using namespace ARDOUR;
using namespace Gtk;
IOSelector::IOSelector (ARDOUR::Session& session, boost::shared_ptr<ARDOUR::IO> io, bool in)
IOSelector::IOSelector (ARDOUR::Session& session, boost::shared_ptr<ARDOUR::IO> io)
: PortMatrix (session, io->default_type())
, _io (io)
, _find_inputs_for_io_outputs (in)
{
/* signal flow from 0 to 1 */
_find_inputs_for_io_outputs = (_io->direction() == IO::Output);
if (_find_inputs_for_io_outputs) {
_other = 1;
_ours = 0;
@ -73,9 +75,7 @@ IOSelector::setup_ports (int dim)
} else {
_port_group->clear ();
_port_group->add_bundle (
_find_inputs_for_io_outputs ? _io->bundle_for_outputs() : _io->bundle_for_inputs()
);
_port_group->add_bundle (_io->bundle ());
}
_ports[dim].resume_signals ();
@ -96,17 +96,9 @@ IOSelector::set_state (ARDOUR::BundleChannel c[2], bool s)
}
if (s) {
if (!_find_inputs_for_io_outputs) {
_io->connect_input (f, *j, 0);
} else {
_io->connect_output (f, *j, 0);
}
_io->connect (f, *j, 0);
} else {
if (!_find_inputs_for_io_outputs) {
_io->disconnect_input (f, *j, 0);
} else {
_io->disconnect_output (f, *j, 0);
}
_io->disconnect (f, *j, 0);
}
}
}
@ -147,9 +139,9 @@ uint32_t
IOSelector::n_io_ports () const
{
if (!_find_inputs_for_io_outputs) {
return _io->inputs().num_ports (_io->default_type());
return _io->n_ports().get (_io->default_type());
} else {
return _io->outputs().num_ports (_io->default_type());
return _io->n_ports().get (_io->default_type());
}
}
@ -161,27 +153,13 @@ IOSelector::add_channel (boost::shared_ptr<ARDOUR::Bundle> b)
// The IO selector only works for single typed IOs
const ARDOUR::DataType t = _io->default_type ();
if (!_find_inputs_for_io_outputs) {
try {
_io->add_input_port ("", this);
}
catch (AudioEngine::PortRegistrationFailure& err) {
MessageDialog msg (_("There are no more JACK ports available."));
msg.run ();
}
} else {
try {
_io->add_output_port ("", this);
}
catch (AudioEngine::PortRegistrationFailure& err) {
MessageDialog msg (_("There are no more JACK ports available."));
msg.run ();
}
try {
_io->add_port ("", this);
}
catch (AudioEngine::PortRegistrationFailure& err) {
MessageDialog msg (_("There are no more JACK ports available."));
msg.run ();
}
}
@ -193,11 +171,7 @@ IOSelector::remove_channel (ARDOUR::BundleChannel bc)
return;
}
if (_find_inputs_for_io_outputs) {
_io->remove_output_port (f, this);
} else {
_io->remove_input_port (f, this);
}
_io->remove_port (f, this);
}
bool
@ -206,9 +180,9 @@ IOSelector::list_is_global (int dim) const
return (dim == _other);
}
IOSelectorWindow::IOSelectorWindow (ARDOUR::Session& session, boost::shared_ptr<ARDOUR::IO> io, bool for_input, bool can_cancel)
IOSelectorWindow::IOSelectorWindow (ARDOUR::Session& session, boost::shared_ptr<ARDOUR::IO> io, bool can_cancel)
: ArdourDialog ("I/O selector")
, _selector (session, io, !for_input)
, _selector (session, io)
, add_button (_("Add Port"))
, disconnect_button (_("Disconnect All"))
, ok_button (can_cancel ? _("OK"): _("Close"))
@ -327,8 +301,8 @@ IOSelectorWindow::io_name_changed (void* src)
}
PortInsertUI::PortInsertUI (ARDOUR::Session& sess, boost::shared_ptr<ARDOUR::PortInsert> pi)
: input_selector (sess, pi->io(), true),
output_selector (sess, pi->io(), false)
: input_selector (sess, pi->input())
, output_selector (sess, pi->output())
{
output_selector.set_min_height_divisor (2);
input_selector.set_min_height_divisor (2);

View File

@ -30,7 +30,7 @@ namespace ARDOUR {
class IOSelector : public PortMatrix
{
public:
IOSelector (ARDOUR::Session&, boost::shared_ptr<ARDOUR::IO>, bool);
IOSelector (ARDOUR::Session&, boost::shared_ptr<ARDOUR::IO>);
void set_state (ARDOUR::BundleChannel c[2], bool);
PortMatrixNode::State get_state (ARDOUR::BundleChannel c[2]) const;
@ -74,7 +74,7 @@ class IOSelector : public PortMatrix
class IOSelectorWindow : public ArdourDialog
{
public:
IOSelectorWindow (ARDOUR::Session&, boost::shared_ptr<ARDOUR::IO>, bool for_input, bool can_cancel = false);
IOSelectorWindow (ARDOUR::Session&, boost::shared_ptr<ARDOUR::IO>, bool can_cancel = false);
IOSelector& selector() { return _selector; }

View File

@ -506,13 +506,7 @@ MidiTimeAxisView::create_automation_child (const Evoral::Parameter& param, bool
if (existing != _automation_tracks.end())
return;
boost::shared_ptr<AutomationControl> c
= boost::dynamic_pointer_cast<AutomationControl>(_route->data().control(param));
if (!c) {
c = boost::dynamic_pointer_cast<AutomationControl>(_route->control_factory(param));
_route->add_control(c);
}
boost::shared_ptr<AutomationControl> c = _route->get_control (param);
assert(c);

View File

@ -34,6 +34,7 @@
#include <gtkmm2ext/bindable_button.h>
#include "ardour/ardour.h"
#include "ardour/amp.h"
#include "ardour/session.h"
#include "ardour/audioengine.h"
#include "ardour/route.h"
@ -71,20 +72,6 @@ sigc::signal<void,boost::shared_ptr<Route> > MixerStrip::SwitchIO;
int MixerStrip::scrollbar_height = 0;
#ifdef VARISPEED_IN_MIXER_STRIP
static void
speed_printer (char buf[32], Gtk::Adjustment& adj, void* arg)
{
float val = adj.get_value ();
if (val == 1.0) {
strcpy (buf, "1");
} else {
snprintf (buf, 32, "%.3f", val);
}
}
#endif
MixerStrip::MixerStrip (Mixer_UI& mx, Session& sess, bool in_mixer)
: AxisView(sess)
, RouteUI (sess, _("Mute"), _("Solo"), _("Record"))
@ -99,8 +86,6 @@ MixerStrip::MixerStrip (Mixer_UI& mx, Session& sess, bool in_mixer)
, bottom_button_table (1, 2)
, meter_point_label (_("pre"))
, comment_button (_("Comments"))
, speed_adjustment (1.0, 0.001, 4.0, 0.001, 0.1)
, speed_spinner (&speed_adjustment, "MixerStripSpeedBase", true)
{
init ();
@ -128,8 +113,6 @@ MixerStrip::MixerStrip (Mixer_UI& mx, Session& sess, boost::shared_ptr<Route> rt
, bottom_button_table (1, 2)
, meter_point_label (_("pre"))
, comment_button (_("Comments"))
, speed_adjustment (1.0, 0.001, 4.0, 0.001, 0.1)
, speed_spinner (&speed_adjustment, "MixerStripSpeedBase", true)
{
init ();
@ -146,7 +129,6 @@ MixerStrip::init ()
route_ops_menu = 0;
ignore_comment_edit = false;
ignore_toggle = false;
ignore_speed_adjustment = false;
comment_window = 0;
comment_area = 0;
_width_owner = 0;
@ -340,12 +322,6 @@ MixerStrip::set_route (boost::shared_ptr<Route> rt)
button_table.remove (*show_sends_button);
}
#ifdef VARISPEED_IN_MIXER_STRIP
if (speed_frame->get_parent()) {
button_table.remove (*speed_frame);
}
#endif
RouteUI::set_route (rt);
delete input_selector;
@ -354,14 +330,16 @@ MixerStrip::set_route (boost::shared_ptr<Route> rt)
delete output_selector;
output_selector = 0;
if (_current_send) {
_current_send->set_metering (false);
boost::shared_ptr<Send> send;
if (_current_delivery && (send = boost::dynamic_pointer_cast<Send>(_current_delivery))) {
send->set_metering (false);
}
_current_send.reset ();
_current_delivery = _route->main_outs ();
panners.set_io (rt);
gpm.set_io (rt);
panners.set_panner (rt->main_outs()->panner());
gpm.set_controls (rt, rt->shared_peak_meter(), rt->gain_control(), rt->amp());
pre_processor_box.set_route (rt);
post_processor_box.set_route (rt);
@ -388,20 +366,6 @@ MixerStrip::set_route (boost::shared_ptr<Route> rt)
connections.push_back (at->FreezeChange.connect (mem_fun(*this, &MixerStrip::map_frozen)));
#ifdef VARISPEED_IN_MIXER_STRIP
speed_adjustment.signal_value_changed().connect (mem_fun(*this, &MixerStrip::speed_adjustment_changed));
speed_frame.set_name ("BaseFrame");
speed_frame.set_shadow_type (Gtk::SHADOW_IN);
speed_frame.add (speed_spinner);
speed_spinner.set_print_func (speed_printer, 0);
ARDOUR_UI::instance()->tooltips().set_tip (speed_spinner, _("Varispeed"));
button_table.attach (speed_frame, 0, 2, 5, 6);
#endif /* VARISPEED_IN_MIXER_STRIP */
button_table.attach (*rec_enable_button, 0, 2, 2, 3);
rec_enable_button->show();
@ -443,9 +407,9 @@ MixerStrip::set_route (boost::shared_ptr<Route> rt)
connections.push_back (_route->meter_change.connect (
mem_fun(*this, &MixerStrip::meter_changed)));
connections.push_back (_route->input_changed.connect (
connections.push_back (_route->input()->changed.connect (
mem_fun(*this, &MixerStrip::input_changed)));
connections.push_back (_route->output_changed.connect (
connections.push_back (_route->output()->changed.connect (
mem_fun(*this, &MixerStrip::output_changed)));
connections.push_back (_route->mix_group_changed.connect (
mem_fun(*this, &MixerStrip::mix_group_changed)));
@ -458,8 +422,6 @@ MixerStrip::set_route (boost::shared_ptr<Route> rt)
if (is_audio_track()) {
connections.push_back (audio_track()->DiskstreamChanged.connect (
mem_fun(*this, &MixerStrip::diskstream_changed)));
connections.push_back (get_diskstream()->SpeedChanged.connect (
mem_fun(*this, &MixerStrip::speed_changed)));
}
connections.push_back (_route->NameChanged.connect (
@ -485,10 +447,6 @@ MixerStrip::set_route (boost::shared_ptr<Route> rt)
panners.setup_pan ();
if (is_audio_track()) {
speed_changed ();
}
update_diskstream_display ();
update_input_display ();
update_output_display ();
@ -530,9 +488,6 @@ MixerStrip::set_route (boost::shared_ptr<Route> rt)
comment_button.show();
group_button.show();
group_label.show();
speed_spinner.show();
speed_label.show();
speed_frame.show();
show ();
}
@ -703,7 +658,7 @@ MixerStrip::output_press (GdkEventButton *ev)
citems.push_back (MenuElem (_("Disconnect"), mem_fun (*(static_cast<RouteUI*>(this)), &RouteUI::disconnect_output)));
citems.push_back (SeparatorElem());
ARDOUR::BundleList current = _route->bundles_connected_to_outputs ();
ARDOUR::BundleList current = _route->output()->bundles_connected ();
boost::shared_ptr<ARDOUR::BundleList> b = _session.bundles ();
for (ARDOUR::BundleList::iterator i = b->begin(); i != b->end(); ++i) {
@ -712,7 +667,7 @@ MixerStrip::output_press (GdkEventButton *ev)
boost::shared_ptr<ARDOUR::RouteList> routes = _session.get_routes ();
for (ARDOUR::RouteList::const_iterator i = routes->begin(); i != routes->end(); ++i) {
maybe_add_bundle_to_output_menu ((*i)->bundle_for_inputs(), current);
maybe_add_bundle_to_output_menu ((*i)->input()->bundle(), current);
}
if (citems.size() == 2) {
@ -734,7 +689,7 @@ void
MixerStrip::edit_output_configuration ()
{
if (output_selector == 0) {
output_selector = new IOSelectorWindow (_session, _route, false);
output_selector = new IOSelectorWindow (_session, _route->output());
}
if (output_selector->is_visible()) {
@ -748,7 +703,7 @@ void
MixerStrip::edit_input_configuration ()
{
if (input_selector == 0) {
input_selector = new IOSelectorWindow (_session, _route, true);
input_selector = new IOSelectorWindow (_session, _route->input());
}
if (input_selector->is_visible()) {
@ -784,7 +739,7 @@ MixerStrip::input_press (GdkEventButton *ev)
citems.push_back (MenuElem (_("Disconnect"), mem_fun (*(static_cast<RouteUI*>(this)), &RouteUI::disconnect_input)));
citems.push_back (SeparatorElem());
ARDOUR::BundleList current = _route->bundles_connected_to_inputs ();
ARDOUR::BundleList current = _route->input()->bundles_connected ();
boost::shared_ptr<ARDOUR::BundleList> b = _session.bundles ();
for (ARDOUR::BundleList::iterator i = b->begin(); i != b->end(); ++i) {
@ -793,7 +748,7 @@ MixerStrip::input_press (GdkEventButton *ev)
boost::shared_ptr<ARDOUR::RouteList> routes = _session.get_routes ();
for (ARDOUR::RouteList::const_iterator i = routes->begin(); i != routes->end(); ++i) {
maybe_add_bundle_to_input_menu ((*i)->bundle_for_outputs(), current);
maybe_add_bundle_to_input_menu ((*i)->output()->bundle(), current);
}
if (citems.size() == 2) {
@ -817,12 +772,12 @@ MixerStrip::bundle_input_toggled (boost::shared_ptr<ARDOUR::Bundle> c)
return;
}
ARDOUR::BundleList current = _route->bundles_connected_to_inputs ();
ARDOUR::BundleList current = _route->input()->bundles_connected ();
if (std::find (current.begin(), current.end(), c) == current.end()) {
_route->connect_input_ports_to_bundle (c, this);
_route->input()->connect_ports_to_bundle (c, this);
} else {
_route->disconnect_input_ports_from_bundle (c, this);
_route->input()->disconnect_ports_from_bundle (c, this);
}
}
@ -833,12 +788,12 @@ MixerStrip::bundle_output_toggled (boost::shared_ptr<ARDOUR::Bundle> c)
return;
}
ARDOUR::BundleList current = _route->bundles_connected_to_outputs ();
ARDOUR::BundleList current = _route->output()->bundles_connected ();
if (std::find (current.begin(), current.end(), c) == current.end()) {
_route->connect_output_ports_to_bundle (c, this);
_route->output()->connect_ports_to_bundle (c, this);
} else {
_route->disconnect_output_ports_from_bundle (c, this);
_route->output()->disconnect_ports_from_bundle (c, this);
}
}
@ -848,7 +803,7 @@ MixerStrip::maybe_add_bundle_to_input_menu (boost::shared_ptr<Bundle> b, ARDOUR:
using namespace Menu_Helpers;
if (b->ports_are_outputs() == false ||
route()->default_type() != b->type() ||
route()->input()->default_type() != b->type() ||
b->nchannels() != _route->n_inputs().get (b->type ())) {
return;
@ -874,7 +829,7 @@ MixerStrip::maybe_add_bundle_to_output_menu (boost::shared_ptr<Bundle> b, ARDOUR
using namespace Menu_Helpers;
if (b->ports_are_inputs() == false ||
route()->default_type() != b->type() ||
route()->output()->default_type() != b->type() ||
b->nchannels() != _route->n_outputs().get (b->type ())) {
return;
@ -938,7 +893,7 @@ MixerStrip::connect_to_pan ()
void
MixerStrip::update_input_display ()
{
ARDOUR::BundleList const c = _route->bundles_connected_to_inputs ();
ARDOUR::BundleList const c = _route->input()->bundles_connected();
if (c.size() > 1) {
input_label.set_text (_("Inputs"));
@ -960,7 +915,7 @@ MixerStrip::update_input_display ()
void
MixerStrip::update_output_display ()
{
ARDOUR::BundleList const c = _route->bundles_connected_to_outputs ();
ARDOUR::BundleList const c = _route->output()->bundles_connected ();
/* XXX: how do we represent >1 connected bundle? */
if (c.size() > 1) {
@ -1269,43 +1224,6 @@ MixerStrip::list_route_operations ()
refresh_remote_control_menu();
}
void
MixerStrip::speed_adjustment_changed ()
{
/* since there is a usable speed adjustment, there has to be a diskstream */
if (!ignore_speed_adjustment) {
get_diskstream()->set_speed (speed_adjustment.get_value());
}
}
void
MixerStrip::speed_changed ()
{
Gtkmm2ext::UI::instance()->call_slot (mem_fun(*this, &MixerStrip::update_speed_display));
}
void
MixerStrip::update_speed_display ()
{
float val;
val = get_diskstream()->speed();
if (val != 1.0) {
speed_spinner.set_name ("MixerStripSpeedBaseNotOne");
} else {
speed_spinner.set_name ("MixerStripSpeedBase");
}
if (speed_adjustment.get_value() != val) {
ignore_speed_adjustment = true;
speed_adjustment.set_value (val);
ignore_speed_adjustment = false;
}
}
void
MixerStrip::set_selected (bool yn)
{
@ -1383,12 +1301,10 @@ MixerStrip::map_frozen ()
case AudioTrack::Frozen:
pre_processor_box.set_sensitive (false);
post_processor_box.set_sensitive (false);
speed_spinner.set_sensitive (false);
break;
default:
pre_processor_box.set_sensitive (true);
post_processor_box.set_sensitive (true);
speed_spinner.set_sensitive (true);
// XXX need some way, maybe, to retoggle redirect editors
break;
}
@ -1499,8 +1415,6 @@ MixerStrip::meter_changed (void *src)
void
MixerStrip::switch_io (boost::shared_ptr<Route> target)
{
boost::shared_ptr<IO> to_display;
if (_route == target || _route->is_master()) {
/* don't change the display for the target or the master bus */
return;
@ -1519,22 +1433,28 @@ MixerStrip::switch_io (boost::shared_ptr<Route> target)
return;
}
if (_current_send) {
_current_send->set_metering (false);
boost::shared_ptr<Send> send;
if (_current_delivery && (send = boost::dynamic_pointer_cast<Send>(_current_delivery))) {
send->set_metering (false);
}
_current_send = _route->send_for (target);
_current_delivery = _route->send_for (target->input());
if (_current_send) {
to_display = _current_send->io();
if (_current_delivery) {
send = boost::dynamic_pointer_cast<Send>(_current_delivery);
send->set_metering (true);
_current_delivery->GoingAway.connect (mem_fun (*this, &MixerStrip::revert_to_default_display));
gain_meter().set_controls (_route, send->meter(), send->amp()->gain_control(), send->amp());
panner_ui().set_panner (_current_delivery->panner());
_current_send->set_metering (true);
_current_send->GoingAway.connect (mem_fun (*this, &MixerStrip::revert_to_default_display));
} else {
_current_delivery = _route->main_outs ();
gain_meter().set_controls (_route, _route->shared_peak_meter(), _route->gain_control(), _route->amp());
panner_ui().set_panner (_route->main_outs()->panner());
}
gain_meter().set_io (to_display);
gain_meter().setup_meters ();
panner_ui().set_io (to_display);
panner_ui().setup_pan ();
}
@ -1544,14 +1464,17 @@ MixerStrip::revert_to_default_display ()
{
show_sends_button->set_active (false);
if (_current_send) {
_current_send->set_metering (false);
_current_send.reset();
}
boost::shared_ptr<Send> send;
gain_meter().set_io (_route);
if (_current_delivery && (send = boost::dynamic_pointer_cast<Send>(_current_delivery))) {
send->set_metering (false);
}
_current_delivery = _route->main_outs();
gain_meter().set_controls (_route, _route->shared_peak_meter(), _route->gain_control(), _route->amp());
gain_meter().setup_meters ();
panner_ui().set_io (_route);
panner_ui().set_panner (_route->main_outs()->panner());
panner_ui().setup_pan ();
}

View File

@ -242,15 +242,6 @@ class MixerStrip : public RouteUI, public Gtk::EventBox
void route_active_changed ();
/* speed control (for tracks only) */
Gtk::Adjustment speed_adjustment;
Gtkmm2ext::ClickBox speed_spinner;
Gtk::Label speed_label;
Gtk::Frame speed_frame;
void speed_adjustment_changed ();
void speed_changed ();
void name_changed ();
void update_speed_display ();
void map_frozen ();
@ -263,7 +254,7 @@ class MixerStrip : public RouteUI, public Gtk::EventBox
void engine_stopped();
void switch_io (boost::shared_ptr<ARDOUR::Route>);
boost::shared_ptr<ARDOUR::Send> _current_send;
boost::shared_ptr<ARDOUR::Delivery> _current_delivery;
void revert_to_default_display ();
static int scrollbar_height;

View File

@ -25,6 +25,7 @@
#include <gtkmm2ext/barcontroller.h>
#include "midi++/manager.h"
#include "pbd/fastlog.h"
#include "pbd/stacktrace.h"
#include "ardour_ui.h"
#include "panner_ui.h"
@ -33,6 +34,7 @@
#include "panner.h"
#include "gui_thread.h"
#include "ardour/delivery.h"
#include "ardour/session.h"
#include "ardour/panner.h"
#include "ardour/route.h"
@ -131,13 +133,8 @@ PannerUI::PannerUI (Session& s)
}
void
PannerUI::set_io (boost::shared_ptr<IO> io)
PannerUI::set_panner (boost::shared_ptr<Panner> p)
{
if (io && !io->panner()) {
cerr << "PannerUI::set_io IO has no panners" << endl;
return;
}
connections.clear ();
delete pan_astyle_menu;
@ -146,18 +143,18 @@ PannerUI::set_io (boost::shared_ptr<IO> io)
delete pan_astate_menu;
pan_astate_menu = 0;
_io = io;
_panner = p;
delete panner;
panner = 0;
if (!_io) {
if (!_panner) {
return;
}
connections.push_back (_io->panner()->Changed.connect (mem_fun(*this, &PannerUI::panner_changed)));
connections.push_back (_io->panner()->LinkStateChanged.connect (mem_fun(*this, &PannerUI::update_pan_linkage)));
connections.push_back (_io->panner()->StateChanged.connect (mem_fun(*this, &PannerUI::update_pan_state)));
connections.push_back (_panner->Changed.connect (mem_fun(*this, &PannerUI::panner_changed)));
connections.push_back (_panner->LinkStateChanged.connect (mem_fun(*this, &PannerUI::update_pan_linkage)));
connections.push_back (_panner->StateChanged.connect (mem_fun(*this, &PannerUI::update_pan_state)));
setup_pan ();
@ -196,16 +193,16 @@ PannerUI::build_astate_menu ()
}
pan_astate_menu->items().push_back (MenuElem (_("Manual"), bind (
mem_fun (_io->panner().get(), &Panner::set_automation_state),
mem_fun (_panner.get(), &Panner::set_automation_state),
(AutoState) Off)));
pan_astate_menu->items().push_back (MenuElem (_("Play"), bind (
mem_fun (_io->panner().get(), &Panner::set_automation_state),
mem_fun (_panner.get(), &Panner::set_automation_state),
(AutoState) Play)));
pan_astate_menu->items().push_back (MenuElem (_("Write"), bind (
mem_fun (_io->panner().get(), &Panner::set_automation_state),
mem_fun (_panner.get(), &Panner::set_automation_state),
(AutoState) Write)));
pan_astate_menu->items().push_back (MenuElem (_("Touch"), bind (
mem_fun (_io->panner().get(), &Panner::set_automation_state),
mem_fun (_panner.get(), &Panner::set_automation_state),
(AutoState) Touch)));
}
@ -242,7 +239,7 @@ bool
PannerUI::panning_link_button_release (GdkEventButton* ev)
{
if (!ignore_toggle) {
_io->panner()->set_linked (!_io->panner()->linked());
_panner->set_linked (!_panner->linked());
}
return true;
}
@ -250,12 +247,12 @@ PannerUI::panning_link_button_release (GdkEventButton* ev)
void
PannerUI::panning_link_direction_clicked()
{
switch (_io->panner()->link_direction()) {
switch (_panner->link_direction()) {
case Panner::SameDirection:
_io->panner()->set_link_direction (Panner::OppositeDirection);
_panner->set_link_direction (Panner::OppositeDirection);
break;
default:
_io->panner()->set_link_direction (Panner::SameDirection);
_panner->set_link_direction (Panner::SameDirection);
break;
}
}
@ -265,7 +262,7 @@ PannerUI::update_pan_linkage ()
{
ENSURE_GUI_THREAD(mem_fun(*this, &PannerUI::update_pan_linkage));
bool x = _io->panner()->linked();
bool x = _panner->linked();
bool bx = panning_link_button.get_active();
if (x != bx) {
@ -277,7 +274,7 @@ PannerUI::update_pan_linkage ()
panning_link_direction_button.set_sensitive (x);
switch (_io->panner()->link_direction()) {
switch (_panner->link_direction()) {
case Panner::SameDirection:
panning_link_direction_button.set_image (*(manage (new Image (get_xpm ("forwardblarrow.xpm")))));
break;
@ -339,11 +336,16 @@ PannerUI::update_pan_state ()
void
PannerUI::setup_pan ()
{
if (!_io || !_io->panner()) {
cerr << "Setup pan for " << _panner->name() << endl;
// PBD::stacktrace (cerr, 5);
if (!_panner) {
return;
}
uint32_t nouts = _io->n_outputs ().n_audio();
uint32_t nouts = _panner->nouts();
cerr << "\tnouts = " << nouts << endl;
if (nouts == 0 || nouts == 1) {
@ -364,7 +366,7 @@ PannerUI::setup_pan ()
} else if (nouts == 2) {
vector<Adjustment*>::size_type asz;
uint32_t npans = _io->panner()->npanners();
uint32_t npans = _panner->npanners();
while (!pan_adjustments.empty()) {
delete pan_bars.back();
@ -381,7 +383,7 @@ PannerUI::setup_pan ()
/* initialize adjustment with 0.0 (L) or 1.0 (R) for the first and second panners,
which serves as a default, otherwise use current value */
rx = _io->panner()->pan_control( asz)->get_value();
rx = _panner->pan_control( asz)->get_value();
if (npans == 1) {
x = 0.5;
@ -395,20 +397,24 @@ PannerUI::setup_pan ()
pan_adjustments.push_back (new Adjustment (x, 0, 1.0, 0.005, 0.05));
bc = new PannerBar (*pan_adjustments[asz],
boost::static_pointer_cast<PBD::Controllable>( _io->panner()->pan_control( asz )) );
boost::static_pointer_cast<PBD::Controllable>( _panner->pan_control( asz )) );
/* now set adjustment with current value of panner, then connect the signals */
pan_adjustments.back()->set_value(rx);
pan_adjustments.back()->signal_value_changed().connect (bind (mem_fun(*this, &PannerUI::pan_adjustment_changed), (uint32_t) asz));
_io->panner()->pan_control( asz )->Changed.connect (bind (mem_fun(*this, &PannerUI::pan_value_changed), (uint32_t) asz));
_panner->pan_control( asz )->Changed.connect (bind (mem_fun(*this, &PannerUI::pan_value_changed), (uint32_t) asz));
bc->set_name ("PanSlider");
bc->set_shadow_type (Gtk::SHADOW_NONE);
bc->StartGesture.connect (bind (mem_fun (*_io, &IO::start_pan_touch), (uint32_t) asz));
bc->StopGesture.connect (bind (mem_fun (*_io, &IO::end_pan_touch), (uint32_t) asz));
boost::shared_ptr<AutomationControl> ac = _panner->pan_control (asz);
if (asz) {
bc->StartGesture.connect (mem_fun (*ac, &AutomationControl::start_touch));
bc->StopGesture.connect (mem_fun (*ac, &AutomationControl::stop_touch));
}
char buf[64];
snprintf (buf, sizeof (buf), _("panner for channel %zu"), asz + 1);
@ -437,7 +443,7 @@ PannerUI::setup_pan ()
} else {
if (!panner) {
panner = new Panner2d (_io->panner(), 61);
panner = new Panner2d (_panner, 61);
panner->set_name ("MixerPanZone");
panner->show ();
@ -446,9 +452,9 @@ PannerUI::setup_pan ()
}
update_pan_sensitive ();
panner->reset (_io->n_inputs().n_audio());
panner->reset (nouts);
if (big_window) {
big_window->reset (_io->n_inputs().n_audio());
big_window->reset (_panner->npanners());
}
panner->set_size_request (-1, 61);
@ -467,7 +473,7 @@ PannerUI::pan_button_event (GdkEventButton* ev, uint32_t which)
case 1:
if (panner && ev->type == GDK_2BUTTON_PRESS) {
if (!big_window) {
big_window = new Panner2dWindow (panner->get_panner(), 400, _io->n_inputs().n_audio());
big_window = new Panner2dWindow (_panner, 400, _panner->npanners());
}
big_window->show ();
return true;
@ -502,7 +508,7 @@ PannerUI::build_pan_menu (uint32_t which)
/* set state first, connect second */
(dynamic_cast<CheckMenuItem*> (&items.back()))->set_active (_io->panner()->streampanner(which).muted());
(dynamic_cast<CheckMenuItem*> (&items.back()))->set_active (_panner->streampanner(which).muted());
(dynamic_cast<CheckMenuItem*> (&items.back()))->signal_toggled().connect
(bind (mem_fun(*this, &PannerUI::pan_mute), which));
@ -511,7 +517,7 @@ PannerUI::build_pan_menu (uint32_t which)
/* set state first, connect second */
bypass_menu_item->set_active (_io->panner()->bypassed());
bypass_menu_item->set_active (_panner->bypassed());
bypass_menu_item->signal_toggled().connect (mem_fun(*this, &PannerUI::pan_bypass_toggle));
items.push_back (MenuElem (_("Reset"), bind (mem_fun (*this, &PannerUI::pan_reset), which)));
@ -522,38 +528,38 @@ PannerUI::build_pan_menu (uint32_t which)
void
PannerUI::pan_mute (uint32_t which)
{
StreamPanner& sp = _io->panner()->streampanner(which);
StreamPanner& sp = _panner->streampanner(which);
sp.set_muted (!sp.muted());
}
void
PannerUI::pan_bypass_toggle ()
{
if (bypass_menu_item && (_io->panner()->bypassed() != bypass_menu_item->get_active())) {
_io->panner()->set_bypassed (!_io->panner()->bypassed());
if (bypass_menu_item && (_panner->bypassed() != bypass_menu_item->get_active())) {
_panner->set_bypassed (!_panner->bypassed());
}
}
void
PannerUI::pan_reset (uint32_t which)
{
_io->panner()->reset_streampanner (which);
_panner->reset_streampanner (which);
}
void
PannerUI::pan_reset_all ()
{
_io->panner()->reset_to_default ();
_panner->reset_to_default ();
}
void
PannerUI::effective_pan_display ()
{
if (_io->panner()->empty()) {
if (_panner->empty()) {
return;
}
switch (_io->n_outputs().n_audio()) {
switch (_panner->nouts()) {
case 0:
case 1:
/* relax */
@ -576,7 +582,7 @@ PannerUI::pan_changed (void *src)
return;
}
switch (_io->panner()->npanners()) {
switch (_panner->npanners()) {
case 0:
panning_link_direction_button.set_sensitive (false);
panning_link_button.set_sensitive (false);
@ -590,7 +596,7 @@ PannerUI::pan_changed (void *src)
panning_link_button.set_sensitive (true);
}
uint32_t nouts = _io->n_outputs().n_audio();
uint32_t nouts = _panner->nouts();
switch (nouts) {
case 0:
@ -612,11 +618,11 @@ PannerUI::pan_changed (void *src)
void
PannerUI::pan_adjustment_changed (uint32_t which)
{
if (!in_pan_update && which < _io->panner()->npanners()) {
if (!in_pan_update && which < _panner->npanners()) {
float xpos;
float val = pan_adjustments[which]->get_value ();
xpos = _io->panner()->pan_control( which )->get_value();
xpos = _panner->pan_control( which )->get_value();
/* add a kinda-sorta detent for the middle */
@ -633,7 +639,7 @@ PannerUI::pan_adjustment_changed (uint32_t which)
if (!Panner::equivalent (val, xpos)) {
_io->panner()->streampanner(which).set_position (val);
_panner->streampanner(which).set_position (val);
/* XXX
the panner objects have no access to the session,
so do this here. ick.
@ -648,11 +654,11 @@ PannerUI::pan_value_changed (uint32_t which)
{
ENSURE_GUI_THREAD (bind (mem_fun(*this, &PannerUI::pan_value_changed), which));
if (_io->n_outputs().n_audio() > 1 && which < _io->panner()->npanners()) {
if (_panner->npanners() > 1 && which < _panner->npanners()) {
float xpos;
float val = pan_adjustments[which]->get_value ();
_io->panner()->streampanner(which).get_position (xpos);
_panner->streampanner(which).get_position (xpos);
if (!Panner::equivalent (val, xpos)) {
in_pan_update = true;
@ -678,14 +684,14 @@ PannerUI::update_pan_bars (bool only_if_aplay)
float xpos, val;
if (only_if_aplay) {
boost::shared_ptr<AutomationList> alist (_io->panner()->streampanner(n).pan_control()->alist());
boost::shared_ptr<AutomationList> alist (_panner->streampanner(n).pan_control()->alist());
if (!alist->automation_playback()) {
continue;
}
}
_io->panner()->streampanner(n).get_effective_position (xpos);
_panner->streampanner(n).get_effective_position (xpos);
val = (*i)->get_value ();
if (!Panner::equivalent (val, xpos)) {
@ -699,9 +705,9 @@ PannerUI::update_pan_bars (bool only_if_aplay)
void
PannerUI::update_pan_sensitive ()
{
bool sensitive = !(_io->panner()->automation_state() & Play);
bool sensitive = !(_panner->automation_state() & Play);
switch (_io->n_outputs().n_audio()) {
switch (_panner->nouts()) {
case 0:
case 1:
break;
@ -771,10 +777,10 @@ PannerUI::pan_automation_style_changed ()
switch (_width) {
case Wide:
pan_automation_style_button.set_label (astyle_string(_io->panner()->automation_style()));
pan_automation_style_button.set_label (astyle_string(_panner->automation_style()));
break;
case Narrow:
pan_automation_style_button.set_label (short_astyle_string(_io->panner()->automation_style()));
pan_automation_style_button.set_label (short_astyle_string(_panner->automation_style()));
break;
}
}
@ -788,10 +794,10 @@ PannerUI::pan_automation_state_changed ()
switch (_width) {
case Wide:
pan_automation_state_button.set_label (astate_string(_io->panner()->automation_state()));
pan_automation_state_button.set_label (astate_string(_panner->automation_state()));
break;
case Narrow:
pan_automation_state_button.set_label (short_astate_string(_io->panner()->automation_state()));
pan_automation_state_button.set_label (short_astate_string(_panner->automation_state()));
break;
}
@ -800,11 +806,11 @@ PannerUI::pan_automation_state_changed ()
here.
*/
if (_io->panner()->empty()) {
if (_panner->empty()) {
return;
}
x = (_io->panner()->streampanner(0).pan_control()->alist()->automation_state() != Off);
x = (_panner->streampanner(0).pan_control()->alist()->automation_state() != Off);
if (pan_automation_state_button.get_active() != x) {
ignore_toggle = true;

View File

@ -40,8 +40,9 @@ class PannerBar;
class Panner2dWindow;
namespace ARDOUR {
class IO;
class Session;
class Panner;
class Delivery;
}
namespace Gtkmm2ext {
class FastMeter;
@ -58,7 +59,7 @@ class PannerUI : public Gtk::HBox
PannerUI (ARDOUR::Session&);
~PannerUI ();
virtual void set_io (boost::shared_ptr<ARDOUR::IO>);
virtual void set_panner (boost::shared_ptr<ARDOUR::Panner>);
void pan_changed (void *);
@ -76,7 +77,7 @@ class PannerUI : public Gtk::HBox
private:
friend class MixerStrip;
boost::shared_ptr<ARDOUR::IO> _io;
boost::shared_ptr<ARDOUR::Panner> _panner;
ARDOUR::Session& _session;
std::vector<sigc::connection> connections;

View File

@ -36,6 +36,7 @@
using namespace std;
using namespace Gtk;
using namespace ARDOUR;
/** PortGroup constructor.
* @param n Name.
@ -50,7 +51,7 @@ PortGroup::PortGroup (std::string const & n)
* @param b Bundle.
*/
void
PortGroup::add_bundle (boost::shared_ptr<ARDOUR::Bundle> b)
PortGroup::add_bundle (boost::shared_ptr<Bundle> b)
{
assert (b.get());
_bundles.push_back (b);
@ -62,11 +63,11 @@ PortGroup::add_bundle (boost::shared_ptr<ARDOUR::Bundle> b)
}
void
PortGroup::remove_bundle (boost::shared_ptr<ARDOUR::Bundle> b)
PortGroup::remove_bundle (boost::shared_ptr<Bundle> b)
{
assert (b.get());
ARDOUR::BundleList::iterator i = std::find (_bundles.begin(), _bundles.end(), b);
BundleList::iterator i = std::find (_bundles.begin(), _bundles.end(), b);
if (i == _bundles.end()) {
return;
}
@ -78,7 +79,7 @@ PortGroup::remove_bundle (boost::shared_ptr<ARDOUR::Bundle> b)
}
void
PortGroup::bundle_changed (ARDOUR::Bundle::Change c)
PortGroup::bundle_changed (Bundle::Change c)
{
BundleChanged (c);
}
@ -103,7 +104,7 @@ PortGroup::clear ()
bool
PortGroup::has_port (std::string const& p) const
{
for (ARDOUR::BundleList::const_iterator i = _bundles.begin(); i != _bundles.end(); ++i) {
for (BundleList::const_iterator i = _bundles.begin(); i != _bundles.end(); ++i) {
if ((*i)->offers_port_alone (p)) {
return true;
}
@ -112,7 +113,7 @@ PortGroup::has_port (std::string const& p) const
return false;
}
boost::shared_ptr<ARDOUR::Bundle>
boost::shared_ptr<Bundle>
PortGroup::only_bundle ()
{
assert (_bundles.size() == 1);
@ -124,7 +125,7 @@ uint32_t
PortGroup::total_channels () const
{
uint32_t n = 0;
for (ARDOUR::BundleList::const_iterator i = _bundles.begin(); i != _bundles.end(); ++i) {
for (BundleList::const_iterator i = _bundles.begin(); i != _bundles.end(); ++i) {
n += (*i)->nchannels ();
}
@ -135,21 +136,49 @@ PortGroup::total_channels () const
/** PortGroupList constructor.
*/
PortGroupList::PortGroupList ()
: _type (ARDOUR::DataType::AUDIO), _signals_suspended (false), _pending_change (false)
: _type (DataType::AUDIO), _signals_suspended (false), _pending_change (false)
{
}
void
PortGroupList::set_type (ARDOUR::DataType t)
PortGroupList::set_type (DataType t)
{
_type = t;
clear ();
}
void
PortGroupList::maybe_add_processor_to_bundle (boost::weak_ptr<Processor> wp, boost::shared_ptr<RouteBundle> rb, bool inputs)
{
boost::shared_ptr<Processor> p (wp.lock());
if (!p) {
return;
}
boost::shared_ptr<IOProcessor> iop = boost::dynamic_pointer_cast<IOProcessor> (p);
if (iop) {
if (inputs) {
if (!iop->output()) {
return;
}
} else {
if (!iop->input()) {
return;
}
}
rb->add_processor_bundle (inputs ? iop->output()->bundle() : iop->input()->bundle());
}
}
/** Gather bundles from around the system and put them in this PortGroupList */
void
PortGroupList::gather (ARDOUR::Session& session, bool inputs)
PortGroupList::gather (Session& session, bool inputs)
{
clear ();
@ -162,49 +191,28 @@ PortGroupList::gather (ARDOUR::Session& session, bool inputs)
the route's IO bundles and processor bundles together so that they
are presented as one bundle in the matrix. */
boost::shared_ptr<ARDOUR::RouteList> routes = session.get_routes ();
boost::shared_ptr<RouteList> routes = session.get_routes ();
for (ARDOUR::RouteList::const_iterator i = routes->begin(); i != routes->end(); ++i) {
for (RouteList::const_iterator i = routes->begin(); i != routes->end(); ++i) {
boost::shared_ptr<RouteBundle> rb (
new RouteBundle (
inputs ? (*i)->bundle_for_inputs() : (*i)->bundle_for_outputs()
)
);
boost::shared_ptr<RouteBundle> rb (new RouteBundle (inputs ? (*i)->output()->bundle() : (*i)->input()->bundle()));
uint32_t n = 0;
while (1) {
boost::shared_ptr<ARDOUR::Processor> p = (*i)->nth_processor (n);
if (p == 0) {
break;
}
(*i)->foreach_processor (bind (mem_fun (*this, &PortGroupList::maybe_add_processor_to_bundle), rb, inputs));
boost::shared_ptr<ARDOUR::IOProcessor> iop = boost::dynamic_pointer_cast<ARDOUR::IOProcessor> (p);
if (iop) {
rb->add_processor_bundle (
inputs ? iop->io()->bundle_for_inputs() : iop->io()->bundle_for_outputs()
);
}
++n;
}
/* Work out which group to put this bundle in */
boost::shared_ptr<PortGroup> g;
if (_type == ARDOUR::DataType::AUDIO) {
if (_type == DataType::AUDIO) {
if (boost::dynamic_pointer_cast<ARDOUR::AudioTrack> (*i)) {
if (boost::dynamic_pointer_cast<AudioTrack> (*i)) {
g = track;
} else if (!boost::dynamic_pointer_cast<ARDOUR::MidiTrack>(*i)) {
} else if (!boost::dynamic_pointer_cast<MidiTrack>(*i)) {
g = bus;
}
} else if (_type == ARDOUR::DataType::MIDI) {
} else if (_type == DataType::MIDI) {
if (boost::dynamic_pointer_cast<ARDOUR::MidiTrack> (*i)) {
if (boost::dynamic_pointer_cast<MidiTrack> (*i)) {
g = track;
}
@ -219,11 +227,11 @@ PortGroupList::gather (ARDOUR::Session& session, bool inputs)
/* Bundles owned by the session. We only add the mono ones and the User ones
otherwise there is duplication of the same ports within the matrix */
boost::shared_ptr<ARDOUR::BundleList> b = session.bundles ();
for (ARDOUR::BundleList::iterator i = b->begin(); i != b->end(); ++i) {
boost::shared_ptr<BundleList> b = session.bundles ();
for (BundleList::iterator i = b->begin(); i != b->end(); ++i) {
if ((*i)->ports_are_inputs() == inputs && (*i)->type() == _type) {
if ((*i)->nchannels() == 1 || boost::dynamic_pointer_cast<ARDOUR::UserBundle> (*i)) {
if ((*i)->nchannels() == 1 || boost::dynamic_pointer_cast<UserBundle> (*i)) {
system->add_bundle (*i);
}
@ -282,10 +290,10 @@ PortGroupList::gather (ARDOUR::Session& session, bool inputs)
emit_changed ();
}
boost::shared_ptr<ARDOUR::Bundle>
boost::shared_ptr<Bundle>
PortGroupList::make_bundle_from_ports (std::vector<std::string> const & p, bool inputs) const
{
boost::shared_ptr<ARDOUR::Bundle> b (new ARDOUR::Bundle ("", _type, inputs));
boost::shared_ptr<Bundle> b (new Bundle ("", _type, inputs));
std::string const pre = common_prefix (p);
if (!pre.empty()) {
@ -366,7 +374,7 @@ PortGroupList::clear ()
}
ARDOUR::BundleList const &
BundleList const &
PortGroupList::bundles () const
{
_bundles.clear ();
@ -410,7 +418,7 @@ PortGroupList::add_group (boost::shared_ptr<PortGroup> g)
}
void
PortGroupList::remove_bundle (boost::shared_ptr<ARDOUR::Bundle> b)
PortGroupList::remove_bundle (boost::shared_ptr<Bundle> b)
{
for (List::iterator i = _groups.begin(); i != _groups.end(); ++i) {
(*i)->remove_bundle (b);
@ -446,7 +454,7 @@ PortGroupList::resume_signals ()
_signals_suspended = false;
}
RouteBundle::RouteBundle (boost::shared_ptr<ARDOUR::Bundle> r)
RouteBundle::RouteBundle (boost::shared_ptr<Bundle> r)
: _route (r)
{
_route->Changed.connect (sigc::hide (sigc::mem_fun (*this, &RouteBundle::reread_component_bundles)));
@ -470,7 +478,7 @@ RouteBundle::reread_component_bundles ()
}
}
for (std::vector<boost::shared_ptr<ARDOUR::Bundle> >::iterator i = _processor.begin(); i != _processor.end(); ++i) {
for (std::vector<boost::shared_ptr<Bundle> >::iterator i = _processor.begin(); i != _processor.end(); ++i) {
add_channels_from_bundle (*i);
}
@ -478,7 +486,7 @@ RouteBundle::reread_component_bundles ()
}
void
RouteBundle::add_processor_bundle (boost::shared_ptr<ARDOUR::Bundle> p)
RouteBundle::add_processor_bundle (boost::shared_ptr<Bundle> p)
{
p->Changed.connect (sigc::hide (sigc::mem_fun (*this, &RouteBundle::reread_component_bundles)));
_processor.push_back (p);

View File

@ -31,9 +31,11 @@
namespace ARDOUR {
class Session;
class Bundle;
class Processor;
}
class PortMatrix;
class RouteBundle;
/** A list of bundles and ports, grouped by some aspect of their
* type e.g. busses, tracks, system. Each group has 0 or more bundles
@ -119,7 +121,8 @@ class PortGroupList : public sigc::trackable
std::string common_prefix_before (std::vector<std::string> const &, std::string const &) const;
void emit_changed ();
boost::shared_ptr<ARDOUR::Bundle> make_bundle_from_ports (std::vector<std::string> const &, bool) const;
void maybe_add_processor_to_bundle (boost::weak_ptr<ARDOUR::Processor>, boost::shared_ptr<RouteBundle>, bool);
ARDOUR::DataType _type;
mutable ARDOUR::BundleList _bundles;
List _groups;

View File

@ -452,7 +452,7 @@ ProcessorBox::use_plugins (const SelectedPlugins& plugins)
}
if (_route->add_processor (processor, _placement, &err_streams)) {
weird_plugin_dialog (**p, err_streams, _route);
weird_plugin_dialog (**p, err_streams);
// XXX SHAREDPTR delete plugin here .. do we even need to care?
} else {
@ -467,7 +467,7 @@ ProcessorBox::use_plugins (const SelectedPlugins& plugins)
}
void
ProcessorBox::weird_plugin_dialog (Plugin& p, Route::ProcessorStreams streams, boost::shared_ptr<IO> io)
ProcessorBox::weird_plugin_dialog (Plugin& p, Route::ProcessorStreams streams)
{
ArdourDialog dialog (_("ardour: weird plugin dialog"));
Label label;
@ -511,7 +511,7 @@ ProcessorBox::weird_plugin_dialog (Plugin& p, Route::ProcessorStreams streams, b
void
ProcessorBox::choose_insert ()
{
boost::shared_ptr<Processor> processor (new PortInsert (_session));
boost::shared_ptr<Processor> processor (new PortInsert (_session, _route->mute_master()));
processor->ActiveChanged.connect (bind (
mem_fun(*this, &ProcessorBox::show_processor_active),
boost::weak_ptr<Processor>(processor)));
@ -522,7 +522,7 @@ ProcessorBox::choose_insert ()
void
ProcessorBox::choose_send ()
{
boost::shared_ptr<Send> send (new Send (_session));
boost::shared_ptr<Send> send (new Send (_session, _route->mute_master()));
/* make an educated guess at the initial number of outputs for the send */
ChanCount outs = (_session.master_out())
@ -531,14 +531,14 @@ ProcessorBox::choose_send ()
/* XXX need processor lock on route */
try {
send->io()->ensure_io (ChanCount::ZERO, outs, false, this);
send->output()->ensure_io (outs, false, this);
} catch (AudioEngine::PortRegistrationFailure& err) {
error << string_compose (_("Cannot set up new send: %1"), err.what()) << endmsg;
return;
}
/* let the user adjust the IO setup before creation */
IOSelectorWindow *ios = new IOSelectorWindow (_session, send->io(), false, true);
IOSelectorWindow *ios = new IOSelectorWindow (_session, send->output(), true);
ios->show_all ();
/* keep a reference to the send so it doesn't get deleted while
@ -588,14 +588,14 @@ ProcessorBox::choose_return ()
/* XXX need processor lock on route */
try {
retrn->io()->ensure_io (ins, ChanCount::ZERO, false, this);
retrn->input()->ensure_io (ins, false, this);
} catch (AudioEngine::PortRegistrationFailure& err) {
error << string_compose (_("Cannot set up new return: %1"), err.what()) << endmsg;
return;
}
/* let the user adjust the IO setup before creation */
IOSelectorWindow *ios = new IOSelectorWindow (_session, retrn->io(), true, true);
IOSelectorWindow *ios = new IOSelectorWindow (_session, retrn->output(), true);
ios->show_all ();
/* keep a reference to the send so it doesn't get deleted while
@ -1050,7 +1050,7 @@ ProcessorBox::paste_processor_state (const XMLNodeList& nlist)
if (type->value() == "send") {
XMLNode n (**niter);
Send::make_unique (n, _session);
p.reset (new Send (_session, n));
p.reset (new Send (_session, _route->mute_master(), n));
} else if (type->value() == "meter") {
p = _route->shared_peak_meter();
@ -1064,7 +1064,7 @@ ProcessorBox::paste_processor_state (const XMLNodeList& nlist)
continue;
} else if (type->value() == "listen") {
p.reset (new Delivery (_session, **niter));
p.reset (new Delivery (_session, _route->mute_master(), **niter));
} else {
p.reset (new PluginInsert (_session, **niter));
@ -1214,8 +1214,8 @@ ProcessorBox::edit_processor (boost::shared_ptr<Processor> processor)
gidget = send_ui;
#else
if (_parent_strip) {
_parent_strip->gain_meter().set_io (send->io());
_parent_strip->panner_ui().set_io (send->io());
_parent_strip->gain_meter().set_controls (_route, send->meter(), send->amp()->gain_control(), send->amp());
_parent_strip->panner_ui().set_panner (send->panner());
}
#endif

View File

@ -205,7 +205,7 @@ class ProcessorBox : public Gtk::HBox, public PluginInterestedObject
gint idle_delete_processor (boost::weak_ptr<ARDOUR::Processor>);
void weird_plugin_dialog (ARDOUR::Plugin& p, ARDOUR::Route::ProcessorStreams streams, boost::shared_ptr<ARDOUR::IO> io);
void weird_plugin_dialog (ARDOUR::Plugin& p, ARDOUR::Route::ProcessorStreams streams);
static ProcessorBox* _current_processor_box;
static bool enter_box (GdkEventCrossing*, ProcessorBox*);

View File

@ -19,6 +19,7 @@
#include <gtkmm2ext/doi.h>
#include "ardour/amp.h"
#include "ardour/io.h"
#include "ardour/return.h"
@ -37,7 +38,7 @@ ReturnUI::ReturnUI (boost::shared_ptr<Return> r, Session& se)
, _session (se)
, _gpm (se)
{
_gpm.set_io (r->io());
_gpm.set_controls (boost::shared_ptr<Route>(), r->meter(), r->amp()->gain_control(), r->amp());
_hbox.pack_start (_gpm, true, true);
set_name ("ReturnUIFrame");
@ -47,7 +48,7 @@ ReturnUI::ReturnUI (boost::shared_ptr<Return> r, Session& se)
_vbox.pack_start (_hbox, false, false, false);
io = manage (new IOSelector (se, r->io(), true));
io = manage (new IOSelector (se, r->output()));
pack_start (_vbox, false, false);
@ -55,21 +56,19 @@ ReturnUI::ReturnUI (boost::shared_ptr<Return> r, Session& se)
show_all ();
//_return->set_metering (true);
_return->io()->input_changed.connect (mem_fun (*this, &ReturnUI::ins_changed));
//_return->io()->output_changed.connect (mem_fun (*this, &ReturnUI::outs_changed));
_return->set_metering (true);
_return->input()->changed.connect (mem_fun (*this, &ReturnUI::ins_changed));
_gpm.setup_meters ();
_gpm.set_fader_name ("ReturnUIFrame");
// screen_update_connection = ARDOUR_UI::instance()->RapidScreenUpdate.connect (mem_fun (*this, &ReturnUI::update));
fast_screen_update_connection = ARDOUR_UI::instance()->SuperRapidScreenUpdate.connect (mem_fun (*this, &ReturnUI::fast_update));
}
ReturnUI::~ReturnUI ()
{
//_return->set_metering (false);
_return->set_metering (false);
/* XXX not clear that we need to do this */
@ -111,12 +110,8 @@ ReturnUIWindow::ReturnUIWindow (boost::shared_ptr<Return> s, Session& ss)
set_name ("ReturnUIWindow");
going_away_connection = s->GoingAway.connect (
mem_fun (*this, &ReturnUIWindow::return_going_away));
signal_delete_event().connect (bind (
sigc::ptr_fun (just_hide_it),
reinterpret_cast<Window *> (this)));
going_away_connection = s->GoingAway.connect (mem_fun (*this, &ReturnUIWindow::return_going_away));
signal_delete_event().connect (bind (sigc::ptr_fun (just_hide_it), reinterpret_cast<Window *> (this)));
}
ReturnUIWindow::~ReturnUIWindow ()

View File

@ -298,7 +298,7 @@ RouteParams_UI::cleanup_latency_frame ()
void
RouteParams_UI::setup_latency_frame ()
{
latency_widget = new LatencyGUI (*(_route.get()), session->frame_rate(), session->engine().frames_per_cycle());
latency_widget = new LatencyGUI (*(_route->output()), session->frame_rate(), session->engine().frames_per_cycle());
char buf[128];
snprintf (buf, sizeof (buf), _("Playback delay: %u samples"), _route->initial_delay());
@ -322,13 +322,13 @@ RouteParams_UI::setup_io_frames()
cleanup_io_frames();
// input
_input_iosel = new IOSelector (*session, _route, false);
_input_iosel = new IOSelector (*session, _route->input());
_input_iosel->setup ();
input_frame.add (*_input_iosel);
input_frame.show_all();
// output
_output_iosel = new IOSelector (*session, _route, true);
_output_iosel = new IOSelector (*session, _route->output());
_output_iosel->setup ();
output_frame.add (*_output_iosel);
output_frame.show_all();

View File

@ -40,6 +40,7 @@
#include <gtkmm2ext/bindable_button.h>
#include <gtkmm2ext/utils.h>
#include "ardour/amp.h"
#include "ardour/audioplaylist.h"
#include "ardour/diskstream.h"
#include "ardour/event_type_map.h"
@ -110,7 +111,7 @@ RouteTimeAxisView::RouteTimeAxisView (PublicEditor& ed, Session& sess, boost::sh
visual_button (_("v")),
gm (sess, slider, true)
{
gm.set_io (rt);
gm.set_controls (_route, _route->shared_peak_meter(), _route->gain_control(), _route->amp());
gm.get_level_meter().set_no_show_all();
gm.get_level_meter().setup_meters(50);
@ -187,8 +188,8 @@ RouteTimeAxisView::RouteTimeAxisView (PublicEditor& ed, Session& sess, boost::sh
controls_hbox.pack_start(gm.get_level_meter(), false, false);
_route->meter_change.connect (mem_fun(*this, &RouteTimeAxisView::meter_changed));
_route->input_changed.connect (mem_fun(*this, &RouteTimeAxisView::io_changed));
_route->output_changed.connect (mem_fun(*this, &RouteTimeAxisView::io_changed));
_route->input()->changed.connect (mem_fun(*this, &RouteTimeAxisView::io_changed));
_route->output()->changed.connect (mem_fun(*this, &RouteTimeAxisView::io_changed));
controls_table.attach (*mute_button, 6, 7, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND, 0, 0);
controls_table.attach (*solo_button, 7, 8, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND, 0, 0);
@ -231,7 +232,7 @@ RouteTimeAxisView::RouteTimeAxisView (PublicEditor& ed, Session& sess, boost::sh
_route->solo_changed.connect (mem_fun(*this, &RouteUI::solo_changed));
_route->processors_changed.connect (mem_fun(*this, &RouteTimeAxisView::processors_changed));
_route->NameChanged.connect (mem_fun(*this, &RouteTimeAxisView::route_name_changed));
_route->solo_safe_changed.connect (mem_fun(*this, &RouteUI::solo_changed));
_route->solo_isolated_changed.connect (mem_fun(*this, &RouteUI::solo_changed));
if (is_track()) {

View File

@ -101,7 +101,6 @@ RouteUI::init ()
ignore_toggle = false;
wait_for_release = false;
route_active_menu_item = 0;
was_solo_safe = false;
polarity_menu_item = 0;
denormal_menu_item = 0;
multiple_mute_change = false;
@ -192,7 +191,7 @@ RouteUI::set_route (boost::shared_ptr<Route> rp)
connections.push_back (_route->active_changed.connect (mem_fun (*this, &RouteUI::route_active_changed)));
connections.push_back (_route->mute_changed.connect (mem_fun(*this, &RouteUI::mute_changed)));
connections.push_back (_route->solo_changed.connect (mem_fun(*this, &RouteUI::solo_changed)));
connections.push_back (_route->solo_safe_changed.connect (mem_fun(*this, &RouteUI::solo_changed)));
connections.push_back (_route->solo_isolated_changed.connect (mem_fun(*this, &RouteUI::solo_changed)));
if (is_track()) {
boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track>(_route);
@ -396,7 +395,7 @@ RouteUI::solo_press(GdkEventButton* ev)
Config->set_solo_latched (false);
}
} else {
_route->set_solo_safe (!_route->solo_safe(), this);
_route->set_solo_isolated (!_route->solo_isolated(), this);
wait_for_release = false;
}
@ -621,7 +620,7 @@ RouteUI::update_solo_display ()
ignore_toggle = false;
}
if (_route->solo_safe()) {
if (_route->solo_isolated()) {
solo_button->set_visual_state (2);
} else if (_route->soloed()) {
solo_button->set_visual_state (1);
@ -663,8 +662,7 @@ RouteUI::update_mute_display ()
if (Config->get_show_solo_mutes()) {
if (_route->muted()) {
mute_button->set_visual_state (2);
} else if (!_route->soloed() && _route->solo_muted()) {
} else if (!_route->soloed() && _session.soloing()) {
mute_button->set_visual_state (1);
} else {
mute_button->set_visual_state (0);
@ -804,10 +802,10 @@ RouteUI::build_solo_menu (void)
MenuList& items = solo_menu->items();
CheckMenuItem* check;
check = new CheckMenuItem(_("Solo Lock"));
check->set_active (_route->solo_safe());
check->signal_toggled().connect (bind (mem_fun (*this, &RouteUI::toggle_solo_safe), check));
_route->solo_safe_changed.connect(bind (mem_fun (*this, &RouteUI::solo_safe_toggle), check));
check = new CheckMenuItem(_("Solo Isolate"));
check->set_active (_route->solo_isolated());
check->signal_toggled().connect (bind (mem_fun (*this, &RouteUI::toggle_solo_isolated), check));
_route->solo_isolated_changed.connect(bind (mem_fun (*this, &RouteUI::solo_isolated_toggle), check));
items.push_back (CheckMenuElem(*check));
check->show_all();
@ -823,9 +821,11 @@ RouteUI::build_mute_menu(void)
mute_menu = new Menu;
mute_menu->set_name ("ArdourContextMenu");
#if FIX_ME_IN_3_0
MenuList& items = mute_menu->items();
CheckMenuItem* check;
check = new CheckMenuItem(_("Pre Fader"));
init_mute_menu(PRE_FADER, check);
check->signal_toggled().connect(bind (mem_fun (*this, &RouteUI::toggle_mute_menu), PRE_FADER, check));
@ -853,29 +853,27 @@ RouteUI::build_mute_menu(void)
_route->main_outs_changed.connect(bind (mem_fun (*this, &RouteUI::main_outs_toggle), check));
items.push_back (CheckMenuElem(*check));
check->show_all();
#endif
//items.push_back (SeparatorElem());
// items.push_back (MenuElem (_("MIDI Bind"), mem_fun (*mute_button, &BindableToggleButton::midi_learn)));
}
void
RouteUI::init_mute_menu(mute_type type, CheckMenuItem* check)
RouteUI::init_mute_menu(MuteMaster::MutePoint mp, CheckMenuItem* check)
{
if (_route->get_mute_config (type)) {
check->set_active (true);
}
check->set_active (_route->mute_master()->muted_at (mp));
}
void
RouteUI::toggle_mute_menu(mute_type type, Gtk::CheckMenuItem* check)
RouteUI::toggle_mute_menu(MuteMaster::MutePoint mp, Gtk::CheckMenuItem* check)
{
_route->set_mute_config(type, check->get_active(), this);
// _route->set_mute_config(type, check->get_active(), this);
}
void
RouteUI::toggle_solo_safe (Gtk::CheckMenuItem* check)
RouteUI::toggle_solo_isolated (Gtk::CheckMenuItem* check)
{
_route->set_solo_safe (check->get_active(), this);
_route->set_solo_isolated (check->get_active(), this);
}
void
@ -1166,16 +1164,17 @@ RouteUI::denormal_protection_changed ()
/* no signal for this yet */
}
void
RouteUI::solo_safe_toggle(void* src, Gtk::CheckMenuItem* check)
RouteUI::solo_isolated_toggle(void* src, Gtk::CheckMenuItem* check)
{
bool yn = _route->solo_safe ();
bool yn = _route->solo_isolated ();
if (check->get_active() != yn) {
check->set_active (yn);
}
}
#ifdef FIX_THIS_FOR_3_0
void
RouteUI::pre_fader_toggle(void* src, Gtk::CheckMenuItem* check)
{
@ -1219,17 +1218,18 @@ RouteUI::main_outs_toggle(void* src, Gtk::CheckMenuItem* check)
check->set_active (yn);
}
}
#endif
void
RouteUI::disconnect_input ()
{
_route->disconnect_inputs (this);
_route->input()->disconnect (this);
}
void
RouteUI::disconnect_output ()
{
_route->disconnect_outputs (this);
_route->output()->disconnect (this);
}
bool
@ -1308,7 +1308,7 @@ RouteUI::map_frozen ()
void
RouteUI::adjust_latency ()
{
LatencyDialog dialog (_route->name() + _("latency"), *(_route.get()), _session.frame_rate(), _session.engine().frames_per_cycle());
LatencyDialog dialog (_route->name() + _("latency"), *(_route->output()), _session.frame_rate(), _session.engine().frames_per_cycle());
}
void

View File

@ -24,6 +24,7 @@
#include "pbd/xml++.h"
#include "ardour/ardour.h"
#include "ardour/mute_master.h"
#include "ardour/route.h"
#include "ardour/track.h"
@ -125,17 +126,17 @@ class RouteUI : public virtual AxisView
void build_remote_control_menu (void);
void refresh_remote_control_menu ();
void solo_safe_toggle (void*, Gtk::CheckMenuItem*);
void toggle_solo_safe (Gtk::CheckMenuItem*);
void solo_isolated_toggle (void*, Gtk::CheckMenuItem*);
void toggle_solo_isolated (Gtk::CheckMenuItem*);
void toggle_mute_menu(ARDOUR::mute_type, Gtk::CheckMenuItem*);
void toggle_mute_menu(ARDOUR::MuteMaster::MutePoint, Gtk::CheckMenuItem*);
void pre_fader_toggle(void*, Gtk::CheckMenuItem*);
void post_fader_toggle(void*, Gtk::CheckMenuItem*);
void control_outs_toggle(void*, Gtk::CheckMenuItem*);
void main_outs_toggle(void*, Gtk::CheckMenuItem*);
void build_mute_menu(void);
void init_mute_menu(ARDOUR::mute_type, Gtk::CheckMenuItem*);
void init_mute_menu(ARDOUR::MuteMaster::MutePoint, Gtk::CheckMenuItem*);
void set_mix_group_solo(boost::shared_ptr<ARDOUR::Route>, bool);
void set_mix_group_mute(boost::shared_ptr<ARDOUR::Route>, bool);
@ -169,7 +170,6 @@ class RouteUI : public virtual AxisView
virtual void update_rec_display ();
void update_mute_display ();
bool was_solo_safe;
void update_solo_display ();
virtual void map_frozen ();

View File

@ -19,6 +19,7 @@
#include <gtkmm2ext/doi.h>
#include "ardour/amp.h"
#include "ardour/io.h"
#include "ardour/send.h"
@ -38,8 +39,8 @@ SendUI::SendUI (boost::shared_ptr<Send> s, Session& se)
, _gpm (se)
, _panners (se)
{
_panners.set_io (s->io());
_gpm.set_io (s->io());
_panners.set_panner (s->panner());
_gpm.set_controls (boost::shared_ptr<Route>(), s->meter(), s->amp()->gain_control(), s->amp());
_hbox.pack_start (_gpm, true, true);
set_name ("SendUIFrame");
@ -50,7 +51,7 @@ SendUI::SendUI (boost::shared_ptr<Send> s, Session& se)
_vbox.pack_start (_hbox, false, false, false);
_vbox.pack_start (_panners, false,false);
io = manage (new IOSelector (se, s->io(), true));
io = manage (new IOSelector (se, s->output()));
pack_start (_vbox, false, false);
@ -60,8 +61,8 @@ SendUI::SendUI (boost::shared_ptr<Send> s, Session& se)
_send->set_metering (true);
_send->io()->input_changed.connect (mem_fun (*this, &SendUI::ins_changed));
_send->io()->output_changed.connect (mem_fun (*this, &SendUI::outs_changed));
_send->input()->changed.connect (mem_fun (*this, &SendUI::ins_changed));
_send->output()->changed.connect (mem_fun (*this, &SendUI::outs_changed));
_panners.set_width (Wide);
_panners.setup_pan ();

View File

@ -25,12 +25,12 @@ public:
void setup_ports (int dim)
{
cerr << _session.the_auditioner()->outputs().num_ports() << "\n";
cerr << _session.the_auditioner()->output()->n_ports() << "\n";
if (dim == OURS) {
_port_group->clear ();
_port_group->add_bundle (_session.click_io()->bundle_for_outputs());
_port_group->add_bundle (_session.the_auditioner()->bundle_for_outputs());
_port_group->add_bundle (_session.click_io()->bundle());
_port_group->add_bundle (_session.the_auditioner()->output()->bundle());
} else {
_ports[OTHER].gather (_session, true);
}
@ -41,7 +41,7 @@ public:
Bundle::PortList const & our_ports = c[OURS].bundle->channel_ports (c[OURS].channel);
Bundle::PortList const & other_ports = c[OTHER].bundle->channel_ports (c[OTHER].channel);
if (c[OURS].bundle == _session.click_io()->bundle_for_outputs()) {
if (c[OURS].bundle == _session.click_io()->bundle()) {
for (ARDOUR::Bundle::PortList::const_iterator i = our_ports.begin(); i != our_ports.end(); ++i) {
for (ARDOUR::Bundle::PortList::const_iterator j = other_ports.begin(); j != other_ports.end(); ++j) {
@ -50,9 +50,9 @@ public:
assert (f);
if (s) {
_session.click_io()->connect_output (f, *j, 0);
_session.click_io()->connect (f, *j, 0);
} else {
_session.click_io()->disconnect_output (f, *j, 0);
_session.click_io()->disconnect (f, *j, 0);
}
}
}
@ -64,7 +64,7 @@ public:
Bundle::PortList const & our_ports = c[OURS].bundle->channel_ports (c[OURS].channel);
Bundle::PortList const & other_ports = c[OTHER].bundle->channel_ports (c[OTHER].channel);
if (c[OURS].bundle == _session.click_io()->bundle_for_outputs()) {
if (c[OURS].bundle == _session.click_io()->bundle()) {
for (ARDOUR::Bundle::PortList::const_iterator i = our_ports.begin(); i != our_ports.end(); ++i) {
for (ARDOUR::Bundle::PortList::const_iterator j = other_ports.begin(); j != other_ports.end(); ++j) {

View File

@ -39,6 +39,7 @@
#include "evoral/SMF.hpp"
#include "ardour/amp.h"
#include "ardour/audio_library.h"
#include "ardour/auditioner.h"
#include "ardour/audioregion.h"
@ -594,7 +595,10 @@ SoundFileBrowser::add_gain_meter ()
delete gm;
gm = new GainMeter (*session);
gm->set_io (session->the_auditioner());
boost::shared_ptr<Route> r = session->the_auditioner ();
gm->set_controls (r, r->shared_peak_meter(), r->gain_control(), r->amp());
meter_packer.set_border_width (12);
meter_packer.pack_start (*gm, false, true);

View File

@ -118,6 +118,7 @@ midi_stretch.cc
midi_track.cc
mix.cc
mtc_slave.cc
mute_master.cc
named_selection.cc
onset_detector.cc
panner.cc

View File

@ -19,24 +19,31 @@
#include <cstring>
#include <cmath>
#include <algorithm>
#include "evoral/Curve.hpp"
#include "ardour/amp.h"
#include "ardour/audio_buffer.h"
#include "ardour/buffer_set.h"
#include "ardour/configuration.h"
#include "ardour/io.h"
#include "ardour/mute_master.h"
#include "ardour/session.h"
namespace ARDOUR {
#include "i18n.h"
Amp::Amp(Session& s, IO& io)
using namespace ARDOUR;
Amp::Amp(Session& s, boost::shared_ptr<MuteMaster> mm)
: Processor(s, "Amp")
, _io(io)
, _mute(false)
, _apply_gain(true)
, _apply_gain_automation(false)
, _current_gain(1.0)
, _desired_gain(1.0)
, _mute_master (mm)
{
boost::shared_ptr<AutomationList> gl(new AutomationList(Evoral::Parameter(GainAutomation)));
_gain_control = boost::shared_ptr<GainControl>( new GainControl(X_("gaincontrol"), s, this, Evoral::Parameter(GainAutomation), gl ));
add_control(_gain_control);
}
bool
@ -59,64 +66,92 @@ Amp::configure_io (ChanCount in, ChanCount out)
void
Amp::run_in_place (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes)
{
gain_t* gab = _session.gain_automation_buffer();
gain_t mute_gain;
if (_mute && !bufs.is_silent()) {
Amp::apply_gain (bufs, nframes, _current_mute_gain, _desired_mute_gain, false);
if (_desired_mute_gain == 0.0f) {
bufs.is_silent(true);
}
if (_mute_master) {
mute_gain = _mute_master->mute_gain_at (MuteMaster::PreFader);
} else {
mute_gain = 1.0;
}
if (_apply_gain) {
if (_apply_gain_automation) {
if (_io.phase_invert()) {
gain_t* gab = _session.gain_automation_buffer ();
if (mute_gain == 0.0) {
/* absolute mute */
if (_current_gain == 0.0) {
/* already silent */
for (BufferSet::audio_iterator i = bufs.audio_begin(); i != bufs.audio_end(); ++i) {
i->clear ();
}
} else {
/* cut to silence */
Amp::apply_gain (bufs, nframes, _current_gain, 0.0);
_current_gain = 0.0;
}
} else if (mute_gain != 1.0) {
/* mute dimming */
for (BufferSet::audio_iterator i = bufs.audio_begin(); i != bufs.audio_end(); ++i) {
Sample* const sp = i->data();
for (nframes_t nx = 0; nx < nframes; ++nx) {
sp[nx] *= -gab[nx];
sp[nx] *= gab[nx] * mute_gain;
}
}
_current_gain = gab[nframes-1] * mute_gain;
} else {
/* no mute */
for (BufferSet::audio_iterator i = bufs.audio_begin(); i != bufs.audio_end(); ++i) {
Sample* const sp = i->data();
for (nframes_t nx = 0; nx < nframes; ++nx) {
sp[nx] *= gab[nx];
}
}
_current_gain = gab[nframes-1];
}
} else { /* manual (scalar) gain */
gain_t dg = _gain_control->user_float() * mute_gain;
if (_current_gain != _desired_gain) {
if (_current_gain != dg) {
Amp::apply_gain (bufs, nframes, _current_gain, _desired_gain, _io.phase_invert());
_current_gain = _desired_gain;
Amp::apply_gain (bufs, nframes, _current_gain, dg);
_current_gain = dg;
} else if (_current_gain != 0.0f && (_io.phase_invert() || _current_gain != 1.0f)) {
} else if ((_current_gain != 0.0f) && (_current_gain != 1.0f)) {
/* no need to interpolate current gain value,
but its non-unity, so apply it. if the gain
is zero, do nothing because we'll ship silence
below.
/* gain has not changed, but its non-unity, so apply it unless
its zero.
*/
gain_t this_gain;
if (_io.phase_invert()) {
this_gain = -_current_gain;
} else {
this_gain = _current_gain;
}
for (BufferSet::audio_iterator i = bufs.audio_begin(); i != bufs.audio_end(); ++i) {
Sample* const sp = i->data();
apply_gain_to_buffer(sp, nframes, this_gain);
apply_gain_to_buffer(sp, nframes, _current_gain);
}
} else if (_current_gain == 0.0f) {
/* silence! */
for (BufferSet::audio_iterator i = bufs.audio_begin(); i != bufs.audio_end(); ++i) {
i->clear();
}
@ -125,30 +160,19 @@ Amp::run_in_place (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame,
}
}
/** Apply a declicked gain to the audio buffers of @a bufs */
void
Amp::apply_gain (BufferSet& bufs, nframes_t nframes,
gain_t initial, gain_t target, bool invert_polarity)
Amp::apply_gain (BufferSet& bufs, nframes_t nframes, gain_t initial, gain_t target)
{
if (nframes == 0) {
return;
}
if (bufs.count().n_audio() == 0) {
/** Apply a (potentially) declicked gain to the audio buffers of @a bufs
*/
if (nframes == 0 || bufs.count().n_audio() == 0) {
return;
}
// if we don't need to declick, defer to apply_simple_gain
if (initial == target) {
if (target == 0.0) {
for (BufferSet::audio_iterator i = bufs.audio_begin(); i != bufs.audio_end(); ++i) {
memset (i->data(), 0, sizeof (Sample) * nframes);
}
} else if (target != 1.0) {
for (BufferSet::audio_iterator i = bufs.audio_begin(); i != bufs.audio_end(); ++i) {
apply_gain_to_buffer (i->data(), nframes, target);
}
}
apply_simple_gain (bufs, nframes, target);
return;
}
@ -156,7 +180,7 @@ Amp::apply_gain (BufferSet& bufs, nframes_t nframes,
gain_t delta;
double fractional_shift = -1.0/declick;
double fractional_pos;
gain_t polscale = invert_polarity ? -1.0f : 1.0f;
gain_t polscale = 1.0f;
if (target < initial) {
/* fade out: remove more and more of delta from initial */
@ -180,10 +204,6 @@ Amp::apply_gain (BufferSet& bufs, nframes_t nframes,
if (declick != nframes) {
if (invert_polarity) {
target = -target;
}
if (target == 0.0) {
memset (&buffer[declick], 0, sizeof (Sample) * (nframes - declick));
} else if (target != 1.0) {
@ -196,6 +216,62 @@ Amp::apply_gain (BufferSet& bufs, nframes_t nframes,
void
Amp::apply_simple_gain (BufferSet& bufs, nframes_t nframes, gain_t target)
{
if (target == 0.0) {
for (BufferSet::audio_iterator i = bufs.audio_begin(); i != bufs.audio_end(); ++i) {
memset (i->data(), 0, sizeof (Sample) * nframes);
}
} else if (target != 1.0) {
for (BufferSet::audio_iterator i = bufs.audio_begin(); i != bufs.audio_end(); ++i) {
apply_gain_to_buffer (i->data(), nframes, target);
}
}
}
void
Amp::inc_gain (gain_t factor, void *src)
{
float desired_gain = _gain_control->user_float();
if (desired_gain == 0.0f) {
set_gain (0.000001f + (0.000001f * factor), src);
} else {
set_gain (desired_gain + (desired_gain * factor), src);
}
}
void
Amp::set_gain (gain_t val, void *src)
{
// max gain at about +6dB (10.0 ^ ( 6 dB * 0.05))
if (val > 1.99526231f) {
val = 1.99526231f;
}
//cerr << "set desired gain to " << val << " when curgain = " << _gain_control->get_value () << endl;
if (src != _gain_control.get()) {
_gain_control->set_value(val);
// bit twisty, this will come back and call us again
// (this keeps control in sync with reality)
return;
}
{
// Glib::Mutex::Lock dm (declick_lock);
_gain_control->set_float(val, false);
}
if (_session.transport_stopped()) {
// _gain = val;
}
/*
if (_session.transport_stopped() && src != 0 && src != this && _gain_control->automation_write()) {
_gain_control->list()->add (_session.transport_frame(), val);
}
*/
_session.set_dirty();
}
XMLNode&
@ -206,4 +282,33 @@ Amp::state (bool full_state)
return node;
}
} // namespace ARDOUR
void
Amp::GainControl::set_value (float val)
{
// max gain at about +6dB (10.0 ^ ( 6 dB * 0.05))
if (val > 1.99526231f)
val = 1.99526231f;
_amp->set_gain (val, this);
AutomationControl::set_value(val);
}
float
Amp::GainControl::get_value (void) const
{
return AutomationControl::get_value();
}
void
Amp::setup_gain_automation (sframes_t start_frame, sframes_t end_frame, nframes_t nframes)
{
Glib::Mutex::Lock am (data().control_lock(), Glib::TRY_LOCK);
if (am.locked() && _session.transport_rolling() && _gain_control->automation_playback()) {
_apply_gain_automation = _gain_control->list()->curve().rt_safe_get_vector (
start_frame, end_frame, _session.gain_automation_buffer(), nframes);
} else {
_apply_gain_automation = false;
}
}

View File

@ -22,19 +22,20 @@
#include "ardour/types.h"
#include "ardour/chan_count.h"
#include "ardour/processor.h"
#include "ardour/automation_control.h"
namespace ARDOUR {
class BufferSet;
class IO;
class MuteMaster;
/** Applies a declick operation to all audio inputs, passing the same number of
* audio outputs, and passing through any other types unchanged.
*/
class Amp : public Processor {
public:
Amp(Session& s, IO& io);
Amp(Session& s, boost::shared_ptr<MuteMaster> m);
bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const;
bool configure_io (ChanCount in, ChanCount out);
@ -44,38 +45,54 @@ public:
bool apply_gain() const { return _apply_gain; }
void apply_gain(bool yn) { _apply_gain = yn; }
void setup_gain_automation (sframes_t start_frame, sframes_t end_frame, nframes_t nframes);
bool apply_gain_automation() const { return _apply_gain_automation; }
void apply_gain_automation(bool yn) { _apply_gain_automation = yn; }
void muute(bool yn) { _mute = yn; }
void set_gain(float current, float desired) {
_current_gain = current;
_desired_gain = desired;
}
void apply_mute(bool yn, float current=1.0, float desired=0.0) {
_mute = yn;
_current_mute_gain = current;
_desired_mute_gain = desired;
}
XMLNode& state (bool full);
static void apply_gain (BufferSet& bufs, nframes_t nframes,
gain_t initial, gain_t target, bool invert_polarity);
static void apply_gain (BufferSet& bufs, nframes_t nframes, gain_t initial, gain_t target);
static void apply_simple_gain(BufferSet& bufs, nframes_t nframes, gain_t target);
gain_t gain () const { return _gain_control->user_float(); }
virtual void set_gain (gain_t g, void *src);
void inc_gain (gain_t delta, void *src);
static void update_meters();
/* automation */
struct GainControl : public AutomationControl {
GainControl (std::string name, Session& session, Amp* a, const Evoral::Parameter &param,
boost::shared_ptr<AutomationList> al = boost::shared_ptr<AutomationList>() )
: AutomationControl (session, param, al, name )
, _amp (a)
{}
void set_value (float val);
float get_value (void) const;
Amp* _amp;
};
boost::shared_ptr<GainControl> gain_control() {
return _gain_control;
}
boost::shared_ptr<const GainControl> gain_control() const {
return _gain_control;
}
private:
IO& _io;
bool _mute;
bool _apply_gain;
bool _apply_gain_automation;
float _current_gain;
float _desired_gain;
float _current_mute_gain;
float _desired_mute_gain;
bool _denormal_protection;
bool _apply_gain;
bool _apply_gain_automation;
float _current_gain;
boost::shared_ptr<GainControl> _gain_control;
boost::shared_ptr<MuteMaster> _mute_master;
};

View File

@ -58,7 +58,7 @@ public:
virtual void add_control(boost::shared_ptr<Evoral::Control>);
virtual void automation_snapshot(nframes_t now, bool force);
virtual void transport_stopped(nframes_t now);
virtual void transport_stopped (sframes_t now);
virtual std::string describe_parameter(Evoral::Parameter param);

View File

@ -27,7 +27,7 @@ namespace ARDOUR {
class ClickIO : public IO
{
public:
ClickIO (Session& s, const std::string& name) : IO (s, name) {}
ClickIO (Session& s, const std::string& name) : IO (s, name, IO::Output) {}
~ClickIO() {}
protected:

View File

@ -28,48 +28,91 @@ namespace ARDOUR {
class BufferSet;
class IO;
class MuteMaster;
class Panner;
class Delivery : public IOProcessor {
public:
enum Role {
Send = 0x1,
Solo = 0x2,
Insert = 0x1,
Send = 0x2,
Listen = 0x4,
Main = 0x8
};
Delivery (Session& s, IO* io, const std::string& name, Role);
Delivery (Session& s, const std::string& name, Role);
Delivery (Session&, const XMLNode&);
Delivery (Session& s, boost::shared_ptr<IO> io, boost::shared_ptr<MuteMaster> mm, const std::string& name, Role);
Delivery (Session& s, boost::shared_ptr<MuteMaster> mm, const std::string& name, Role);
Delivery (Session&, boost::shared_ptr<MuteMaster> mm, const XMLNode&);
bool set_name (const std::string& name);
bool visible() const;
Role role() const { return _role; }
bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const;
bool configure_io (ChanCount in, ChanCount out);
void run_in_place (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes);
void set_metering (bool yn);
bool muted_by_self() const { return _muted_by_self; }
bool muted_by_others() const { return _muted_by_others; }
/* supplemental method use with MIDI */
void set_self_mute (bool);
void set_nonself_mute (bool);
sigc::signal<void> SelfMuteChange;
sigc::signal<void> OtherMuteChange;
void flush (nframes_t nframes);
void no_outs_cuz_we_no_monitor(bool);
void mod_solo_level (int32_t);
uint32_t solo_level() const { return _solo_level; }
bool soloed () const { return (bool) _solo_level; }
bool solo_isolated() const { return _solo_isolated; }
void set_solo_isolated (bool);
void cycle_start (nframes_t);
void increment_output_offset (nframes_t);
void transport_stopped (sframes_t frame);
BufferSet& output_buffers() { return *_output_buffers; }
sigc::signal<void> MuteChange;
static sigc::signal<void,nframes_t> CycleStart;
XMLNode& state (bool full);
int set_state (const XMLNode&);
private:
Role _role;
bool _metering;
bool _muted_by_self;
bool _muted_by_others;
/* Panning */
static int disable_panners (void);
static int reset_panners (void);
boost::shared_ptr<Panner> panner() const { return _panner; }
void reset_panner ();
void defer_pan_reset ();
void allow_pan_reset ();
uint32_t pans_required() const { return _configured_input.n_audio(); }
void start_pan_touch (uint32_t which);
void end_pan_touch (uint32_t which);
protected:
Role _role;
BufferSet* _output_buffers;
gain_t _current_gain;
nframes_t _output_offset;
bool _no_outs_cuz_we_no_monitor;
uint32_t _solo_level;
bool _solo_isolated;
boost::shared_ptr<MuteMaster> _mute_master;
bool no_panner_reset;
boost::shared_ptr<Panner> _panner;
static bool panners_legal;
static sigc::signal<int> PannersLegal;
int panners_became_legal ();
sigc::connection panner_legal_c;
void output_changed (IOChange, void*);
gain_t target_gain ();
};

View File

@ -55,134 +55,83 @@ class AudioPort;
class BufferSet;
class Bundle;
class MidiPort;
class Panner;
class PeakMeter;
class Port;
class Processor;
class Session;
class UserBundle;
/** A collection of input and output ports with connections.
/** A collection of ports (all input or all output) with connections.
*
* An IO can contain ports of varying types, making routes/inserts/etc with
* varied combinations of types (eg MIDI and audio) possible.
*/
class IO : public SessionObject, public AutomatableControls, public Latent
class IO : public SessionObject, public Latent
{
public:
static const std::string state_node_name;
IO (Session&, const std::string& name, DataType default_type = DataType::AUDIO);
enum Direction {
Input,
Output
};
IO (Session&, const std::string& name, Direction, DataType default_type = DataType::AUDIO);
IO (Session&, const XMLNode&, DataType default_type = DataType::AUDIO);
virtual ~IO();
bool active() const { return _active; }
void set_active (bool yn);
Direction direction() const { return _direction; }
DataType default_type() const { return _default_type; }
void set_default_type(DataType t) { _default_type = t; }
bool active() const { return _active; }
void set_active(bool yn) { _active = yn; }
bool set_name (const std::string& str);
virtual void silence (nframes_t);
void collect_input (BufferSet& bufs, nframes_t nframes, ChanCount offset=ChanCount::ZERO);
void deliver_output (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes);
void just_meter_input (sframes_t start_frame, sframes_t end_frame, nframes_t nframes);
int ensure_io (ChanCount cnt, bool clear, void *src);
BufferSet& output_buffers() { return *_output_buffers; }
int connect_ports_to_bundle (boost::shared_ptr<Bundle>, void *);
int disconnect_ports_from_bundle (boost::shared_ptr<Bundle>, void *);
gain_t gain () const { return _gain_control->user_float(); }
virtual gain_t effective_gain () const;
BundleList bundles_connected ();
boost::shared_ptr<Bundle> bundle () { return _bundle; }
void set_denormal_protection (bool yn, void *src);
bool denormal_protection() const { return _denormal_protection; }
void set_phase_invert (bool yn, void *src);
bool phase_invert() const { return _phase_invert; }
void reset_panner ();
boost::shared_ptr<Amp> amp() const { return _amp; }
PeakMeter& peak_meter() { return *_meter.get(); }
const PeakMeter& peak_meter() const { return *_meter.get(); }
boost::shared_ptr<PeakMeter> shared_peak_meter() const { return _meter; }
boost::shared_ptr<Panner> panner() const { return _panner; }
int ensure_io (ChanCount in, ChanCount out, bool clear, void *src);
int connect_input_ports_to_bundle (boost::shared_ptr<Bundle>, void *);
int disconnect_input_ports_from_bundle (boost::shared_ptr<Bundle>, void *);
int connect_output_ports_to_bundle (boost::shared_ptr<Bundle>, void *);
int disconnect_output_ports_from_bundle (boost::shared_ptr<Bundle>, void *);
BundleList bundles_connected_to_inputs ();
BundleList bundles_connected_to_outputs ();
boost::shared_ptr<Bundle> bundle_for_inputs () { return _bundle_for_inputs; }
boost::shared_ptr<Bundle> bundle_for_outputs () { return _bundle_for_outputs; }
int add_input_port (std::string source, void *src, DataType type = DataType::NIL);
int add_output_port (std::string destination, void *src, DataType type = DataType::NIL);
int remove_input_port (Port *, void *src);
int remove_output_port (Port *, void *src);
int set_input (Port *, void *src);
int connect_input (Port *our_port, std::string other_port, void *src);
int connect_output (Port *our_port, std::string other_port, void *src);
int disconnect_input (Port *our_port, std::string other_port, void *src);
int disconnect_output (Port *our_port, std::string other_port, void *src);
int disconnect_inputs (void *src);
int disconnect_outputs (void *src);
int add_port (std::string connection, void *src, DataType type = DataType::NIL);
int remove_port (Port *, void *src);
int connect (Port *our_port, std::string other_port, void *src);
int disconnect (Port *our_port, std::string other_port, void *src);
int disconnect (void *src);
bool connected_to (boost::shared_ptr<const IO>) const;
nframes_t signal_latency() const { return _own_latency; }
nframes_t output_latency() const;
nframes_t input_latency() const;
nframes_t latency() const;
void set_port_latency (nframes_t);
void update_port_total_latencies ();
const PortSet& inputs() const { return _inputs; }
const PortSet& outputs() const { return _outputs; }
PortSet& ports() { return _ports; }
const PortSet& ports() const { return _ports; }
Port *output (uint32_t n) const {
if (n < _outputs.num_ports()) {
return _outputs.port(n);
Port *nth (uint32_t n) const {
if (n < _ports.num_ports()) {
return _ports.port(n);
} else {
return 0;
}
}
Port *input (uint32_t n) const {
if (n < _inputs.num_ports()) {
return _inputs.port(n);
} else {
return 0;
}
}
AudioPort* audio(uint32_t n) const;
MidiPort* midi(uint32_t n) const;
AudioPort* audio_input(uint32_t n) const;
AudioPort* audio_output(uint32_t n) const;
MidiPort* midi_input(uint32_t n) const;
MidiPort* midi_output(uint32_t n) const;
const ChanCount& n_ports () const { return _ports.count(); }
const ChanCount& n_inputs () const { return _inputs.count(); }
const ChanCount& n_outputs () const { return _outputs.count(); }
void attach_buffers(ChanCount ignored);
sigc::signal<void> active_changed;
sigc::signal<void,IOChange,void*> input_changed;
sigc::signal<void,IOChange,void*> output_changed;
sigc::signal<void,IOChange,void*> changed;
virtual XMLNode& state (bool full);
XMLNode& get_state (void);
@ -192,130 +141,45 @@ class IO : public SessionObject, public AutomatableControls, public Latent
static int enable_connecting (void);
static int disable_ports (void);
static int enable_ports (void);
static int disable_panners (void);
static int reset_panners (void);
static sigc::signal<int> PortsLegal;
static sigc::signal<int> PannersLegal;
static sigc::signal<int> ConnectingLegal;
/// raised when the number of input or output ports changes
static sigc::signal<void,ChanCount> PortCountChanged;
static sigc::signal<void,nframes_t> CycleStart;
static sigc::signal<void,ChanCount> PortCountChanged; // emitted when the number of ports changes
static void update_meters();
static std::string name_from_state (const XMLNode&);
static void set_name_in_state (XMLNode&, const std::string&);
private:
static sigc::signal<void> Meter;
static Glib::StaticMutex m_meter_signal_lock;
sigc::connection m_meter_connection;
public:
/* automation */
struct GainControl : public AutomationControl {
GainControl (std::string name, IO* i, const Evoral::Parameter &param,
boost::shared_ptr<AutomationList> al = boost::shared_ptr<AutomationList>() )
: AutomationControl (i->_session, param, al, name )
, _io (i)
{}
void set_value (float val);
float get_value (void) const;
IO* _io;
};
boost::shared_ptr<GainControl> gain_control() {
return _gain_control;
}
boost::shared_ptr<const GainControl> gain_control() const {
return _gain_control;
}
void clear_automation ();
void set_parameter_automation_state (Evoral::Parameter, AutoState);
virtual void transport_stopped (nframes_t now);
virtual void automation_snapshot (nframes_t now, bool force);
void start_pan_touch (uint32_t which);
void end_pan_touch (uint32_t which);
void defer_pan_reset ();
void allow_pan_reset ();
/* the session calls this for master outs before
anyone else. controls outs too, at some point.
/* we have to defer/order port connection. this is how we do it.
*/
static sigc::signal<int> ConnectingLegal;
static bool connecting_legal;
XMLNode *pending_state_node;
int ports_became_legal ();
/* three utility functions - this just seems to be simplest place to put them */
void collect_input (BufferSet& bufs, nframes_t nframes, ChanCount offset);
void process_input (boost::shared_ptr<Processor>, sframes_t start_frame, sframes_t end_frame, nframes_t nframes);
void copy_to_outputs (BufferSet& bufs, DataType type, nframes_t nframes, nframes_t offset);
/* AudioTrack::deprecated_use_diskstream_connections() needs these */
int set_ports (const std::string& str);
private:
mutable Glib::Mutex io_lock;
protected:
BufferSet* _output_buffers; //< Set directly to output port buffers
bool _active;
gain_t _gain;
Glib::Mutex declick_lock;
PortSet _outputs;
PortSet _inputs;
bool no_panner_reset;
bool _phase_invert;
bool _denormal_protection;
XMLNode* deferred_state;
DataType _default_type;
nframes_t _output_offset;
boost::shared_ptr<Amp> _amp;
boost::shared_ptr<PeakMeter> _meter;
boost::shared_ptr<Panner> _panner;
virtual void prepare_inputs (nframes_t nframes);
virtual void flush_outputs (nframes_t nframes);
virtual void set_deferred_state() {}
virtual uint32_t pans_required() const
{ return _inputs.count().n_audio(); }
boost::shared_ptr<GainControl> _gain_control;
virtual void set_gain (gain_t g, void *src);
void inc_gain (gain_t delta, void *src);
virtual int load_automation (std::string path);
/* AudioTrack::deprecated_use_diskstream_connections() needs these */
int set_inputs (const std::string& str);
int set_outputs (const std::string& str);
void increment_output_offset (nframes_t);
void cycle_start (nframes_t);
static bool connecting_legal;
static bool ports_legal;
PortSet _ports;
Direction _direction;
DataType _default_type;
bool _active;
private:
static bool panners_legal;
void copy_to_outputs (BufferSet& bufs, DataType type, nframes_t nframes);
int connecting_became_legal ();
int panners_became_legal ();
sigc::connection connection_legal_c;
sigc::connection port_legal_c;
sigc::connection panner_legal_c;
boost::shared_ptr<Bundle> _bundle_for_inputs; ///< a bundle representing our inputs
boost::shared_ptr<Bundle> _bundle_for_outputs; ///< a bundle representing our outputs
boost::shared_ptr<Bundle> _bundle; ///< a bundle representing our ports
struct UserBundleInfo {
UserBundleInfo (IO*, boost::shared_ptr<UserBundle> b);
@ -324,45 +188,31 @@ class IO : public SessionObject, public AutomatableControls, public Latent
sigc::connection changed;
};
std::vector<UserBundleInfo> _bundles_connected_to_outputs; ///< user bundles connected to our outputs
std::vector<UserBundleInfo> _bundles_connected_to_inputs; ///< user bundles connected to our inputs
std::vector<UserBundleInfo> _bundles_connected; ///< user bundles connected to our ports
static int parse_io_string (const std::string&, std::vector<std::string>& chns);
static int parse_gain_string (const std::string&, std::vector<std::string>& chns);
int set_sources (std::vector<std::string>&, void *src, bool add);
int set_destinations (std::vector<std::string>&, void *src, bool add);
int ensure_ports (ChanCount, bool clear, bool lockit, void *src);
int ensure_inputs (ChanCount, bool clear, bool lockit, void *src);
int ensure_outputs (ChanCount, bool clear, bool lockit, void *src);
void check_bundles_connected_to_inputs ();
void check_bundles_connected_to_outputs ();
void check_bundles_connected ();
void check_bundles (std::vector<UserBundleInfo>&, const PortSet&);
void bundle_changed (Bundle::Change);
int get_port_counts (const XMLNode& node, ChanCount& in, ChanCount& out,
boost::shared_ptr<Bundle>& ic, boost::shared_ptr<Bundle>& oc);
int get_port_counts (const XMLNode& node, ChanCount& n, boost::shared_ptr<Bundle>& c);
int create_ports (const XMLNode&);
int make_connections (const XMLNode&);
boost::shared_ptr<Bundle> find_possible_bundle (const std::string &desired_name, const std::string &default_name, const std::string &connection_type_name);
virtual void setup_peak_meters ();
void meter ();
boost::shared_ptr<Bundle> find_possible_bundle (const std::string &desired_name);
bool ensure_inputs_locked (ChanCount, bool clear, void *src);
bool ensure_outputs_locked (ChanCount, bool clear, void *src);
bool ensure_ports_locked (ChanCount, bool clear, void *src);
std::string build_legal_port_name (DataType type, bool for_input);
int32_t find_input_port_hole (const char* base);
int32_t find_output_port_hole (const char* base);
std::string build_legal_port_name (DataType type);
int32_t find_port_hole (const char* base);
void setup_bundles_for_inputs_and_outputs ();
void setup_bundle_for_inputs ();
void setup_bundle_for_outputs ();
void setup_bundles ();
std::string bundle_channel_name (uint32_t, uint32_t) const;
};

View File

@ -38,15 +38,16 @@ namespace ARDOUR {
class Session;
class IO;
/** A mixer strip element (Processor) with Jack ports (IO).
/** A mixer strip element (Processor) with 1 or 2 IO elements.
*/
class IOProcessor : public Processor
{
public:
IOProcessor (Session&, const std::string& proc_name, const std::string io_name="",
ARDOUR::DataType default_type = DataType::AUDIO);
IOProcessor (Session&, IO* io, const std::string& proc_name,
IOProcessor (Session&, bool with_input, bool with_output,
const std::string& proc_name, const std::string io_name="",
ARDOUR::DataType default_type = DataType::AUDIO);
IOProcessor (Session&, boost::shared_ptr<IO> input, boost::shared_ptr<IO> output,
const std::string& proc_name, ARDOUR::DataType default_type = DataType::AUDIO);
virtual ~IOProcessor ();
bool set_name (const std::string& str);
@ -56,13 +57,14 @@ class IOProcessor : public Processor
virtual ChanCount natural_output_streams() const;
virtual ChanCount natural_input_streams () const;
boost::shared_ptr<IO> io() { return _io; }
boost::shared_ptr<const IO> io() const { return _io; }
void set_io (boost::shared_ptr<IO>);
boost::shared_ptr<IO> input() { return _input; }
boost::shared_ptr<const IO> input() const { return _input; }
boost::shared_ptr<IO> output() { return _output; }
boost::shared_ptr<const IO> output() const { return _output; }
void set_input (boost::shared_ptr<IO>);
void set_output (boost::shared_ptr<IO>);
virtual void automation_snapshot (nframes_t now, bool force);
virtual void run_in_place (BufferSet& in, sframes_t start, sframes_t end, nframes_t nframes) = 0;
void run_in_place (BufferSet& in, sframes_t start, sframes_t end, nframes_t nframes) = 0;
void silence (nframes_t nframes);
sigc::signal<void,IOProcessor*,bool> AutomationPlaybackChanged;
@ -72,12 +74,14 @@ class IOProcessor : public Processor
int set_state (const XMLNode&);
protected:
boost::shared_ptr<IO> _io;
boost::shared_ptr<IO> _input;
boost::shared_ptr<IO> _output;
private:
/* disallow copy construction */
IOProcessor (const IOProcessor&);
bool _own_io;
bool _own_input;
bool _own_output;
};

View File

@ -20,6 +20,7 @@
#define __ardour_meter_h__
#include <vector>
#include <sigc++/slot.h>
#include "ardour/types.h"
#include "ardour/processor.h"
#include "pbd/fastlog.h"
@ -30,6 +31,20 @@ class BufferSet;
class ChanCount;
class Session;
class Metering {
public:
static void update_meters ();
static sigc::signal<void> Meter;
static sigc::connection connect (sigc::slot<void> the_slot);
static void disconnect (sigc::connection& c);
private:
/* this object is not meant to be instantiated */
virtual void foo() = 0;
static Glib::StaticMutex m_meter_signal_lock;
};
/** Meters peaks on the input and stores them for access.
*/
@ -37,6 +52,8 @@ class PeakMeter : public Processor {
public:
PeakMeter(Session& s) : Processor(s, "Meter") {}
void meter();
void reset ();
void reset_max ();
@ -66,7 +83,6 @@ public:
private:
friend class IO;
void meter();
std::vector<float> _peak_power;
std::vector<float> _visible_peak_power;

View File

@ -0,0 +1,77 @@
/*
Copyright (C) 2009 Paul Davis
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __ardour_mute_master_h__
#define __ardour_mute_master_h__
#include "evoral/Parameter.hpp"
#include "ardour/automation_control.h"
#include "ardour/automation_list.h"
namespace ARDOUR {
class Session;
class MuteMaster : public AutomationControl
{
public:
enum MutePoint {
PreFader = 0x1,
PostFader = 0x2,
Listen = 0x4,
Main = 0x8
};
MuteMaster (Session& s, const std::string& name);
~MuteMaster() {}
bool muted_pre_fader() const { return _mute_point & PreFader; }
bool muted_post_fader() const { return _mute_point & PostFader; }
bool muted_listen() const { return _mute_point & Listen; }
bool muted_main () const { return _mute_point & Main; }
bool muted_at (MutePoint mp) const { return _mute_point & mp; }
bool muted() const { return _mute_point != MutePoint (0) && get_value() != 0.0; }
gain_t mute_gain_at (MutePoint) const;
void clear_mute ();
void mute_at (MutePoint);
void unmute_at (MutePoint);
void mute (bool yn);
/* Controllable interface */
void set_value (float); /* note: float is used as a bitfield of MutePoints */
float get_value () const;
sigc::signal<void> MutePointChanged;
XMLNode& get_state();
int set_state(const XMLNode& node);
private:
AutomationList* _automation;
MutePoint _mute_point;
};
} // namespace ARDOUR
#endif /*__ardour_mute_master_h__ */

View File

@ -183,7 +183,7 @@ class Multi2dPanner : public StreamPanner
};
class Panner : public Processor
class Panner : public SessionObject, public AutomatableControls
{
public:
struct Output {
@ -204,18 +204,16 @@ class Panner : public Processor
void clear_panners ();
bool empty() const { return _streampanners.empty(); }
/// The fundamental Panner function
void set_automation_state (AutoState);
AutoState automation_state() const;
void set_automation_style (AutoStyle);
AutoStyle automation_style() const;
bool touching() const;
bool is_in_place () const { return false; }
bool is_out_of_place () const { return true; }
bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const { return true; };
void run_out_of_place(BufferSet& src, BufferSet& dest, sframes_t start_frame, sframes_t end_frames, nframes_t nframes);
/// The fundamental Panner function
void run (BufferSet& src, BufferSet& dest, sframes_t start_frame, sframes_t end_frames, nframes_t nframes);
//void* get_inline_gui() const = 0;
//void* get_full_gui() const = 0;

View File

@ -34,25 +34,28 @@ class XMLNode;
namespace ARDOUR {
class Session;
class IO;
class Delivery;
class MuteMaster;
/** Port inserts: send output to a Jack port, pick up input at a Jack port
*/
class PortInsert : public IOProcessor
{
public:
PortInsert (Session&);
PortInsert (Session&, const XMLNode&);
PortInsert (Session&, boost::shared_ptr<MuteMaster> mm);
PortInsert (Session&, boost::shared_ptr<MuteMaster> mm, const XMLNode&);
~PortInsert ();
XMLNode& state(bool full);
XMLNode& get_state(void);
int set_state(const XMLNode&);
void init ();
void run_in_place (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes);
nframes_t signal_latency() const;
bool set_name (const std::string& name);
bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const;
bool configure_io (ChanCount in, ChanCount out);
@ -62,6 +65,8 @@ class PortInsert : public IOProcessor
private:
/* disallow copy construction */
PortInsert (const PortInsert&);
boost::shared_ptr<Delivery> _out;
uint32_t bitslot;
};

View File

@ -53,24 +53,26 @@ class Processor : public SessionObject, public AutomatableControls, public Laten
virtual ~Processor() { }
/** Configuration of a processor on a bus
* (i.e. how to apply to a BufferSet)
*/
struct Mapping {
ChanCount in;
ChanCount out;
};
virtual bool visible() const { return true; }
bool active () const { return _active; }
/* we keep loose tabs on the "placement" of a Processor. Ultimately,
they are all executed as a single list, but there are some
semantics that require knowing whether a Processor is before
or after the fader, or panner etc. See Route::reorder_processors()
to see where this gets set.
*/
Placement placement() const { return _placement; }
void set_placement (Placement p) { _placement = p; }
bool get_next_ab_is_active () const { return _next_ab_is_active; }
void set_next_ab_is_active (bool yn) { _next_ab_is_active = yn; }
virtual nframes_t signal_latency() const { return 0; }
virtual void transport_stopped (nframes_t frame) {}
virtual void transport_stopped (sframes_t frame) {}
virtual void set_block_size (nframes_t nframes) {}
@ -127,7 +129,7 @@ protected:
ChanCount _configured_input;
ChanCount _configured_output;
void* _gui; /* generic, we don't know or care what this is */
Mapping _mapping;
Placement _placement;
};
} // namespace ARDOUR

View File

@ -84,6 +84,7 @@ CONFIG_VARIABLE (bool, all_safe, "all-safe", false)
CONFIG_VARIABLE (bool, show_solo_mutes, "show-solo-mutes", false)
CONFIG_VARIABLE (bool, solo_mute_override, "solo-mute-override", false)
CONFIG_VARIABLE (bool, tape_machine_mode, "tape-machine-mode", false)
CONFIG_VARIABLE (gain_t, solo_mute_gain, "solo_mute-gain", 0.0)
/* click */

View File

@ -32,6 +32,9 @@
namespace ARDOUR {
class Amp;
class PeakMeter;
class Return : public IOProcessor
{
public:
@ -43,9 +46,12 @@ public:
void run_in_place (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes);
void activate() {}
void deactivate () {}
boost::shared_ptr<Amp> amp() const { return _amp; }
boost::shared_ptr<PeakMeter> meter() const { return _meter; }
bool metering() const { return _metering; }
void set_metering (bool yn) { _metering = yn; }
XMLNode& state(bool full);
XMLNode& get_state(void);
int set_state(const XMLNode& node);
@ -55,14 +61,22 @@ public:
bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const;
bool configure_io (ChanCount in, ChanCount out);
static uint32_t how_many_sends();
static uint32_t how_many_returns();
static void make_unique (XMLNode &, Session &);
protected:
bool _metering;
boost::shared_ptr<Amp> _amp;
boost::shared_ptr<PeakMeter> _meter;
private:
/* disallow copy construction */
Return (const Return&);
uint32_t _bitslot;
void collect_input (BufferSet& bufs, nframes_t nframes, ChanCount offset=ChanCount::ZERO);
void just_meter_input (sframes_t start_frame, sframes_t end_frame, nframes_t nframes);
};
} // namespace ARDOUR

View File

@ -41,24 +41,19 @@
#include "ardour/ardour.h"
#include "ardour/io.h"
#include "ardour/types.h"
#include "ardour/mute_master.h"
namespace ARDOUR {
class Amp;
class Delivery;
class IOProcessor;
class Panner;
class Processor;
class RouteGroup;
class Send;
enum mute_type {
PRE_FADER = 0x1,
POST_FADER = 0x2,
CONTROL_OUTS = 0x4,
MAIN_OUTS = 0x8
};
class Route : public IO
class Route : public SessionObject, public AutomatableControls
{
public:
@ -75,6 +70,16 @@ class Route : public IO
Route (Session&, const XMLNode&, DataType default_type = DataType::AUDIO);
virtual ~Route();
boost::shared_ptr<IO> input() const { return _input; }
boost::shared_ptr<IO> output() const { return _output; }
ChanCount n_inputs() const { return _input->n_ports(); }
ChanCount n_outputs() const { return _output->n_ports(); }
bool active() const { return _active; }
void set_active (bool yn);
static std::string ensure_track_or_route_name(std::string, Session &);
std::string comment() { return _comment; }
@ -102,6 +107,7 @@ class Route : public IO
virtual void toggle_monitor_input ();
virtual bool can_record() { return false; }
virtual void set_record_enable (bool yn, void *src) {}
virtual bool record_enabled() const { return false; }
virtual void handle_transport_stopped (bool abort, bool did_locate, bool flush_processors);
@ -110,38 +116,44 @@ class Route : public IO
/* end of vfunc-based API */
void shift (nframes64_t, nframes64_t);
/* override IO::set_gain() to provide group control */
void set_gain (gain_t val, void *src);
void inc_gain (gain_t delta, void *src);
void set_mute (bool yn, void* src);
bool muted () const;
void set_solo (bool yn, void *src);
bool soloed() const { return _soloed; }
bool soloed() const;
void set_solo_safe (bool yn, void *src);
bool solo_safe() const { return _solo_safe; }
void set_solo_isolated (bool yn, void *src);
bool solo_isolated() const;
void set_mute (bool yn, void *src);
bool muted() const { return _muted; }
bool solo_muted() const { return desired_solo_gain == 0.0; }
void set_phase_invert (bool yn, void* src);
bool phase_invert() const;
void set_mute_config (mute_type, bool, void *src);
bool get_mute_config (mute_type);
void set_denormal_protection (bool yn, void* src);
bool denormal_protection() const;
void set_edit_group (RouteGroup *, void *);
void drop_edit_group (void *);
RouteGroup *edit_group () { return _edit_group; }
RouteGroup *edit_group () const { return _edit_group; }
void set_mix_group (RouteGroup *, void *);
void drop_mix_group (void *);
RouteGroup *mix_group () { return _mix_group; }
RouteGroup *mix_group () const { return _mix_group; }
virtual void set_meter_point (MeterPoint, void *src);
MeterPoint meter_point() const { return _meter_point; }
void meter ();
/* Processors */
boost::shared_ptr<Amp> amp() const { return _amp; }
PeakMeter& peak_meter() { return *_meter.get(); }
const PeakMeter& peak_meter() const { return *_meter.get(); }
boost::shared_ptr<PeakMeter> shared_peak_meter() const { return _meter; }
void flush_processors ();
void foreach_processor (sigc::slot<void, boost::weak_ptr<Processor> > method) {
@ -180,7 +192,7 @@ class Route : public IO
boost::shared_ptr<Delivery> control_outs() const { return _control_outs; }
boost::shared_ptr<Delivery> main_outs() const { return _main_outs; }
boost::shared_ptr<Send> send_for (boost::shared_ptr<const IO> target) const;
/** A record of the stream configuration at some point in the processor list.
@ -213,8 +225,10 @@ class Route : public IO
void set_user_latency (nframes_t);
nframes_t initial_delay() const { return _initial_delay; }
sigc::signal<void> active_changed;
sigc::signal<void,void*> solo_changed;
sigc::signal<void,void*> solo_safe_changed;
sigc::signal<void,void*> solo_isolated_changed;
sigc::signal<void,void*> comment_changed;
sigc::signal<void,void*> mute_changed;
sigc::signal<void,void*> pre_fader_changed;
@ -240,8 +254,8 @@ class Route : public IO
virtual XMLNode& get_template();
XMLNode& get_processor_state ();
int set_processor_state (const XMLNode&);
virtual void set_processor_state (const XMLNode&);
int save_as_template (const std::string& path, const std::string& name);
sigc::signal<void,void*> SelectedChanged;
@ -252,28 +266,38 @@ class Route : public IO
bool feeds (boost::shared_ptr<IO>);
std::set<boost::shared_ptr<Route> > fed_by;
struct ToggleControllable : public PBD::Controllable {
enum ToggleType {
MuteControl = 0,
SoloControl
};
ToggleControllable (std::string name, Route&, ToggleType);
void set_value (float);
float get_value (void) const;
/* Controls (not all directly owned by the Route */
Route& route;
ToggleType type;
boost::shared_ptr<AutomationControl> get_control (const Evoral::Parameter& param);
struct SoloControllable : public AutomationControl {
SoloControllable (std::string name, Route&);
void set_value (float);
float get_value (void) const;
Route& route;
};
boost::shared_ptr<PBD::Controllable> solo_control() {
boost::shared_ptr<AutomationControl> solo_control() const {
return _solo_control;
}
boost::shared_ptr<PBD::Controllable> mute_control() {
return _mute_control;
boost::shared_ptr<AutomationControl> mute_control() const {
return _mute_master;
}
boost::shared_ptr<MuteMaster> mute_master() const {
return _mute_master;
}
/* Route doesn't own these items, but sub-objects that it does own have them
and to make UI code a bit simpler, we provide direct access to them
here.
*/
boost::shared_ptr<Panner> panner() const;
boost::shared_ptr<AutomationControl> gain_control() const;
void automation_snapshot (nframes_t now, bool force=false);
void protect_automation ();
@ -288,10 +312,11 @@ class Route : public IO
friend class Session;
void catch_up_on_solo_mute_override ();
void set_solo_mute (bool yn);
void mod_solo_level (int32_t);
void set_block_size (nframes_t nframes);
bool has_external_redirects() const;
void curve_reallocate ();
void just_meter_input (sframes_t start_frame, sframes_t end_frame, nframes_t nframes);
protected:
nframes_t check_initial_delay (nframes_t, nframes_t&);
@ -303,44 +328,38 @@ class Route : public IO
sframes_t start_frame, sframes_t end_frame,
nframes_t nframes, bool with_processors, int declick);
Flag _flags;
int _pending_declick;
MeterPoint _meter_point;
boost::shared_ptr<IO> _input;
boost::shared_ptr<IO> _output;
gain_t solo_gain;
gain_t mute_gain;
gain_t desired_solo_gain;
gain_t desired_mute_gain;
bool _active;
nframes_t _initial_delay;
nframes_t _roll_delay;
ProcessorList _processors;
mutable Glib::RWLock _processor_lock;
boost::shared_ptr<Delivery> _main_outs;
boost::shared_ptr<Delivery> _control_outs; // XXX to be removed/generalized by listen points
RouteGroup *_edit_group;
RouteGroup *_mix_group;
std::string _comment;
bool _have_internal_generator;
Flag _flags;
int _pending_declick;
MeterPoint _meter_point;
uint32_t _phase_invert;
bool _denormal_protection;
boost::shared_ptr<ToggleControllable> _solo_control;
boost::shared_ptr<ToggleControllable> _mute_control;
/* tight cache-line access here is more important than sheer speed of access.
keep these after things that should be aligned
*/
bool _muted : 1;
bool _soloed : 1;
bool _solo_safe : 1;
bool _recordable : 1;
bool _mute_affects_pre_fader : 1;
bool _mute_affects_post_fader : 1;
bool _mute_affects_control_outs : 1;
bool _mute_affects_main_outs : 1;
bool _silent : 1;
bool _declickable : 1;
boost::shared_ptr<SoloControllable> _solo_control;
boost::shared_ptr<MuteMaster> _mute_master;
RouteGroup* _edit_group;
RouteGroup* _mix_group;
std::string _comment;
bool _have_internal_generator;
bool _solo_safe;
DataType _default_type;
protected:
virtual XMLNode& state(bool);
@ -358,13 +377,14 @@ class Route : public IO
uint32_t pans_required() const;
ChanCount n_process_buffers ();
void setup_peak_meters ();
virtual int _set_state (const XMLNode&, bool call_base);
virtual void _set_processor_states (const XMLNodeList&);
boost::shared_ptr<Delivery> add_listener (boost::shared_ptr<IO>, const std::string&);
boost::shared_ptr<Amp> _amp;
boost::shared_ptr<PeakMeter> _meter;
sigc::connection _meter_connection;
private:
void init ();
@ -386,8 +406,7 @@ class Route : public IO
int configure_processors (ProcessorStreams*);
int configure_processors_unlocked (ProcessorStreams*);
void set_deferred_state ();
bool add_processor_from_xml (const XMLNode&, Placement);
bool add_processor_from_xml (const XMLNode&, ProcessorList::iterator iter);

View File

@ -23,40 +23,52 @@
#include <sigc++/signal.h>
#include <string>
#include "pbd/stateful.h"
#include "ardour/ardour.h"
#include "ardour/audioengine.h"
#include "ardour/delivery.h"
namespace ARDOUR {
class PeakMeter;
class Amp;
class Send : public Delivery
{
public:
Send (Session&);
Send (Session&, const XMLNode&);
Send (Session&, boost::shared_ptr<MuteMaster>);
Send (Session&, boost::shared_ptr<MuteMaster>, const XMLNode&);
virtual ~Send ();
uint32_t bit_slot() const { return _bitslot; }
void activate() {}
void deactivate () {}
boost::shared_ptr<Amp> amp() const { return _amp; }
boost::shared_ptr<PeakMeter> meter() const { return _meter; }
bool metering() const { return _metering; }
void set_metering (bool yn) { _metering = yn; }
XMLNode& state(bool full);
XMLNode& get_state(void);
int set_state(const XMLNode& node);
uint32_t pans_required() const { return _configured_input.n_audio(); }
void run_in_place (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes);
bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const;
bool configure_io (ChanCount in, ChanCount out);
bool set_name (const std::string& str);
static uint32_t how_many_sends();
static void make_unique (XMLNode &, Session &);
protected:
bool _metering;
boost::shared_ptr<Amp> _amp;
boost::shared_ptr<PeakMeter> _meter;
private:
/* disallow copy construction */
Send (const Send&);

View File

@ -730,8 +730,8 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable
/* session-wide solo/mute/rec-enable */
bool soloing() const { return currently_soloing; }
bool soloing() const { return _non_soloed_outs_muted; }
void set_all_solo (bool);
void set_all_mute (bool);
@ -743,8 +743,8 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable
/* control/master out */
boost::shared_ptr<IO> control_out() const { return _control_out; }
boost::shared_ptr<IO> master_out() const { return _master_out; }
boost::shared_ptr<Route> control_out() const { return _control_out; }
boost::shared_ptr<Route> master_out() const { return _master_out; }
/* insert/send management */
@ -1040,6 +1040,7 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable
bool _have_captured;
float _meter_hold;
float _meter_falloff;
bool _non_soloed_outs_muted;
void set_worst_io_latencies ();
void set_worst_io_latencies_x (IOChange asifwecare, void *ignored) {
@ -1688,8 +1689,8 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable
/* main outs */
uint32_t main_outs;
boost::shared_ptr<IO> _master_out;
boost::shared_ptr<IO> _control_out;
boost::shared_ptr<Route> _master_out;
boost::shared_ptr<Route> _control_out;
gain_t* _gain_automation_buffer;
pan_t** _pan_automation_buffer;

View File

@ -160,6 +160,8 @@ AudioDiskstream::free_working_buffers()
void
AudioDiskstream::non_realtime_input_change ()
{
cerr << "AD::NRIC ... " << name() << endl;
{
Glib::Mutex::Lock lm (state_lock);
@ -173,10 +175,10 @@ AudioDiskstream::non_realtime_input_change ()
_n_channels.set(DataType::AUDIO, c->size());
if (_io->n_inputs().n_audio() > _n_channels.n_audio()) {
add_channel_to (c, _io->n_inputs().n_audio() - _n_channels.n_audio());
} else if (_io->n_inputs().n_audio() < _n_channels.n_audio()) {
remove_channel_from (c, _n_channels.n_audio() - _io->n_inputs().n_audio());
if (_io->n_ports().n_audio() > _n_channels.n_audio()) {
add_channel_to (c, _io->n_ports().n_audio() - _n_channels.n_audio());
} else if (_io->n_ports().n_audio() < _n_channels.n_audio()) {
remove_channel_from (c, _n_channels.n_audio() - _io->n_ports().n_audio());
}
}
@ -227,14 +229,14 @@ AudioDiskstream::get_input_sources ()
uint32_t n;
ChannelList::iterator chan;
uint32_t ni = _io->n_inputs().n_audio();
uint32_t ni = _io->n_ports().n_audio();
vector<string> connections;
for (n = 0, chan = c->begin(); chan != c->end() && n < ni; ++chan, ++n) {
connections.clear ();
if (_io->input(n)->get_connections (connections) == 0) {
if (_io->nth (n)->get_connections (connections) == 0) {
if ((*chan)->source) {
// _source->disable_metering ();
@ -633,7 +635,7 @@ AudioDiskstream::process (nframes_t transport_frame, nframes_t nframes, bool can
if (nominally_recording || rec_nframes) {
uint32_t limit = _io->n_inputs ().n_audio();
uint32_t limit = _io->n_ports ().n_audio();
/* one or more ports could already have been removed from _io, but our
channel setup hasn't yet been updated. prevent us from trying to
@ -656,7 +658,7 @@ AudioDiskstream::process (nframes_t transport_frame, nframes_t nframes, bool can
for recording, and use rec_offset
*/
AudioPort* const ap = _io->audio_input(n);
AudioPort* const ap = _io->audio (n);
assert(ap);
assert(rec_nframes <= ap->get_audio_buffer(nframes).capacity());
memcpy (chaninfo->current_capture_buffer, ap->get_audio_buffer (rec_nframes).data(rec_offset), sizeof (Sample) * rec_nframes);
@ -671,7 +673,7 @@ AudioDiskstream::process (nframes_t transport_frame, nframes_t nframes, bool can
goto out;
}
AudioPort* const ap = _io->audio_input(n);
AudioPort* const ap = _io->audio (n);
assert(ap);
Sample* buf = ap->get_audio_buffer(nframes).data();
@ -1822,7 +1824,7 @@ AudioDiskstream::finish_capture (bool rec_monitors_input, boost::shared_ptr<Chan
void
AudioDiskstream::set_record_enabled (bool yn)
{
if (!recordable() || !_session.record_enabling_legal() || _io->n_inputs().n_audio() == 0) {
if (!recordable() || !_session.record_enabling_legal() || _io->n_ports().n_audio() == 0) {
return;
}
@ -2110,6 +2112,8 @@ AudioDiskstream::reset_write_sources (bool mark_write_complete, bool force)
boost::shared_ptr<ChannelList> c = channels.reader();
uint32_t n;
cerr << _name << " RWS!!!\n";
if (!recordable()) {
return;
}

View File

@ -36,6 +36,7 @@
#include "ardour/buffer_set.h"
#include "ardour/io_processor.h"
#include "ardour/panner.h"
#include "ardour/meter.h"
#include "ardour/playlist_factory.h"
#include "ardour/plugin_insert.h"
#include "ardour/processor.h"
@ -140,8 +141,7 @@ AudioTrack::deprecated_use_diskstream_connections ()
diskstream->deprecated_io_node = 0;
if ((prop = node.property ("gain")) != 0) {
set_gain (atof (prop->value().c_str()), this);
_gain = _gain_control->user_float();
_amp->set_gain (atof (prop->value().c_str()), this);
}
if ((prop = node.property ("input-connection")) != 0) {
@ -160,10 +160,10 @@ AudioTrack::deprecated_use_diskstream_connections ()
}
}
connect_input_ports_to_bundle (c, this);
_input->connect_ports_to_bundle (c, this);
} else if ((prop = node.property ("inputs")) != 0) {
if (set_inputs (prop->value())) {
if (_input->set_ports (prop->value())) {
error << string_compose(_("improper input channel list in XML node (%1)"), prop->value()) << endmsg;
return -1;
}
@ -176,14 +176,14 @@ int
AudioTrack::set_diskstream (boost::shared_ptr<AudioDiskstream> ds, void *src)
{
_diskstream = ds;
_diskstream->set_io (*this);
_diskstream->set_io (*(_input.get()));
_diskstream->set_destructive (_mode == Destructive);
_diskstream->set_non_layered (_mode == NonLayered);
if (audio_diskstream()->deprecated_io_node) {
if (!connecting_legal) {
ConnectingLegal.connect (mem_fun (*this, &AudioTrack::deprecated_use_diskstream_connections));
if (!IO::connecting_legal) {
IO::ConnectingLegal.connect (mem_fun (*this, &AudioTrack::deprecated_use_diskstream_connections));
} else {
deprecated_use_diskstream_connections ();
}
@ -193,7 +193,7 @@ AudioTrack::set_diskstream (boost::shared_ptr<AudioDiskstream> ds, void *src)
_diskstream->monitor_input (false);
ic_connection.disconnect();
ic_connection = input_changed.connect (mem_fun (*_diskstream, &Diskstream::handle_input_change));
ic_connection = _input->changed.connect (mem_fun (*_diskstream, &Diskstream::handle_input_change));
DiskstreamChanged (); /* EMIT SIGNAL */
@ -479,8 +479,6 @@ AudioTrack::roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame,
transport_frame = _session.transport_frame();
prepare_inputs (nframes);
if ((nframes = check_initial_delay (nframes, transport_frame)) == 0) {
/* need to do this so that the diskstream sets its
@ -501,7 +499,7 @@ AudioTrack::roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame,
/* special condition applies */
if (_meter_point == MeterInput) {
just_meter_input (start_frame, end_frame, nframes);
_input->process_input (_meter, start_frame, end_frame, nframes);
}
if (diskstream->record_enabled() && !can_record && !_session.config.get_auto_input()) {
@ -599,6 +597,7 @@ AudioTrack::roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame,
/* don't waste time with automation if we're recording or we've just stopped (yes it can happen) */
if (!diskstream->record_enabled() && _session.transport_rolling()) {
#ifdef XXX_MOVE_THIS_TO_AMP
Glib::Mutex::Lock am (data().control_lock(), Glib::TRY_LOCK);
if (am.locked() && gain_control()->automation_playback()) {
@ -606,6 +605,7 @@ AudioTrack::roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame,
gain_control()->list()->curve().rt_safe_get_vector (
start_frame, end_frame, _session.gain_automation_buffer(), nframes));
}
#endif
}
process_output_buffers (bufs, start_frame, end_frame, nframes, (!_session.get_record_enabled() || !Config->get_do_not_record_plugins()), declick);
@ -759,9 +759,9 @@ AudioTrack::freeze (InterThreadInfo& itt)
new_playlist = PlaylistFactory::create (DataType::AUDIO, _session, new_playlist_name, false);
_freeze_record.gain = _gain;
_freeze_record.gain_automation_state = _gain_control->automation_state();
_freeze_record.pan_automation_state = _panner->automation_state();
_freeze_record.gain = _amp->gain();
_freeze_record.gain_automation_state = _amp->gain_control()->automation_state();
/* XXX need main outs automation state _freeze_record.pan_automation_state = _mainpanner->automation_state(); */
region_name = new_playlist_name;
@ -784,8 +784,8 @@ AudioTrack::freeze (InterThreadInfo& itt)
/* reset stuff that has already been accounted for in the freeze process */
set_gain (1.0, this);
_gain_control->set_automation_state (Off);
_panner->set_automation_state (Off);
_amp->gain_control()->set_automation_state (Off);
/* XXX need to use _main_outs _panner->set_automation_state (Off); */
_freeze_record.state = Frozen;
FreezeChange(); /* EMIT SIGNAL */
@ -811,8 +811,8 @@ AudioTrack::unfreeze ()
_freeze_record.playlist.reset ();
set_gain (_freeze_record.gain, this);
_gain_control->set_automation_state (_freeze_record.gain_automation_state);
_panner->set_automation_state (_freeze_record.pan_automation_state);
_amp->gain_control()->set_automation_state (_freeze_record.gain_automation_state);
/* XXX need to use _main_outs _panner->set_automation_state (_freeze_record.pan_automation_state); */
}
_freeze_record.state = UnFrozen;

View File

@ -33,9 +33,11 @@
#include "ardour/audioengine.h"
#include "ardour/buffer.h"
#include "ardour/delivery.h"
#include "ardour/port.h"
#include "ardour/audio_port.h"
#include "ardour/midi_port.h"
#include "ardour/meter.h"
#include "ardour/session.h"
#include "ardour/cycle_timer.h"
#include "ardour/utils.h"
@ -358,9 +360,9 @@ AudioEngine::process_callback (nframes_t nframes)
return 0;
}
/* tell all IO objects that we're starting a new cycle */
/* tell all relevant objects that we're starting a new cycle */
IO::CycleStart (nframes);
Delivery::CycleStart (nframes);
Port::set_port_offset (0);
/* tell all Ports that we're starting a new cycle */
@ -519,7 +521,7 @@ AudioEngine::meter_thread ()
if (g_atomic_int_get(&m_meter_exit)) {
break;
}
IO::update_meters ();
Metering::update_meters ();
}
}

View File

@ -24,6 +24,7 @@
#include "ardour/audio_diskstream.h"
#include "ardour/audioregion.h"
#include "ardour/audioengine.h"
#include "ardour/delivery.h"
#include "ardour/route.h"
#include "ardour/session.h"
#include "ardour/auditioner.h"
@ -57,22 +58,21 @@ Auditioner::Auditioner (Session& s)
return;
}
defer_pan_reset ();
_main_outs->defer_pan_reset ();
if (left.length()) {
add_output_port (left, this, DataType::AUDIO);
_output->add_port (left, this, DataType::AUDIO);
}
if (right.length()) {
audio_diskstream()->add_channel (1);
add_output_port (right, this, DataType::AUDIO);
_output->add_port (right, this, DataType::AUDIO);
}
allow_pan_reset ();
reset_panner ();
_main_outs->allow_pan_reset ();
_main_outs->reset_panner ();
IO::output_changed.connect (mem_fun (*this, &Auditioner::output_changed));
_output->changed.connect (mem_fun (*this, &Auditioner::output_changed));
the_region.reset ((AudioRegion*) 0);
g_atomic_int_set (&_active, 0);
@ -110,7 +110,7 @@ Auditioner::audition_current_playlist ()
/* force a panner reset now that we have all channels */
_panner->reset (n_outputs().n_audio(), _diskstream->n_channels().n_audio());
_main_outs->panner()->reset (n_outputs().n_audio(), _diskstream->n_channels().n_audio());
g_atomic_int_set (&_active, 1);
}
@ -148,7 +148,7 @@ Auditioner::audition_region (boost::shared_ptr<Region> region)
/* force a panner reset now that we have all channels */
reset_panner();
_main_outs->reset_panner();
length = the_region->length();
@ -206,7 +206,7 @@ Auditioner::output_changed (IOChange change, void* src)
if (change & ConnectionsChanged) {
vector<string> connections;
if (output (0)->get_connections (connections)) {
if (_output->nth (0)->get_connections (connections)) {
phys = _session.engine().get_nth_physical_output (DataType::AUDIO, 0);
if (phys != connections[0]) {
_session.config.set_auditioner_output_left (connections[0]);
@ -219,7 +219,7 @@ Auditioner::output_changed (IOChange change, void* src)
connections.clear ();
if (output (1)->get_connections (connections)) {
if (_output->nth (1)->get_connections (connections)) {
phys = _session.engine().get_nth_physical_output (DataType::AUDIO, 1);
if (phys != connections[0]) {
_session.config.set_auditioner_output_right (connections[0]);

View File

@ -24,8 +24,11 @@
#include <errno.h>
#include "pbd/error.h"
#include "pbd/enumwriter.h"
#include "midi++/names.h"
#include "ardour/automatable.h"
#include "ardour/amp.h"
#include "ardour/event_type_map.h"
#include "ardour/midi_track.h"
#include "ardour/panner.h"
@ -382,7 +385,7 @@ Automatable::automation_snapshot (nframes_t now, bool force)
}
void
Automatable::transport_stopped (nframes_t now)
Automatable::transport_stopped (sframes_t now)
{
for (Controls::iterator li = controls().begin(); li != controls().end(); ++li) {
@ -409,7 +412,7 @@ Automatable::control_factory(const Evoral::Parameter& param)
} else if (param.type() == PluginAutomation) {
control = new PluginInsert::PluginControl((PluginInsert*)this, param);
} else if (param.type() == GainAutomation) {
control = new IO::GainControl( X_("gaincontrol"), (IO*)this, param);
control = new Amp::GainControl( X_("gaincontrol"), _a_session, (Amp*)this, param);
} else if (param.type() == PanAutomation) {
Panner* me = dynamic_cast<Panner*>(this);
if (me) {

View File

@ -20,58 +20,102 @@
#include <algorithm>
#include "pbd/enumwriter.h"
#include "pbd/convert.h"
#include "ardour/delivery.h"
#include "ardour/audio_buffer.h"
#include "ardour/amp.h"
#include "ardour/buffer_set.h"
#include "ardour/configuration.h"
#include "ardour/io.h"
#include "ardour/meter.h"
#include "ardour/mute_master.h"
#include "ardour/panner.h"
#include "ardour/port.h"
#include "ardour/session.h"
#include "i18n.h"
using namespace std;
using namespace PBD;
using namespace ARDOUR;
sigc::signal<void,nframes_t> Delivery::CycleStart;
sigc::signal<int> Delivery::PannersLegal;
bool Delivery::panners_legal = false;
/* deliver to an existing IO object */
Delivery::Delivery (Session& s, IO* io, const string& name, Role r)
: IOProcessor(s, io, name)
Delivery::Delivery (Session& s, boost::shared_ptr<IO> io, boost::shared_ptr<MuteMaster> mm, const string& name, Role r)
: IOProcessor(s, boost::shared_ptr<IO>(), io, name)
, _role (r)
, _metering (false)
, _muted_by_self (false)
, _muted_by_others (false)
, _output_buffers (new BufferSet())
, _solo_level (0)
, _solo_isolated (false)
, _mute_master (mm)
{
_output_offset = 0;
_current_gain = 1.0;
_panner = boost::shared_ptr<Panner>(new Panner (_name, _session));
_output->changed.connect (mem_fun (*this, &Delivery::output_changed));
}
/* deliver to a new IO object */
Delivery::Delivery (Session& s, const string& name, Role r)
: IOProcessor(s, name)
Delivery::Delivery (Session& s, boost::shared_ptr<MuteMaster> mm, const string& name, Role r)
: IOProcessor(s, false, true, name)
, _role (r)
, _metering (false)
, _muted_by_self (false)
, _muted_by_others (false)
, _output_buffers (new BufferSet())
, _solo_level (0)
, _solo_isolated (false)
, _mute_master (mm)
{
_output_offset = 0;
_current_gain = 1.0;
_panner = boost::shared_ptr<Panner>(new Panner (_name, _session));
_output->changed.connect (mem_fun (*this, &Delivery::output_changed));
}
/* reconstruct from XML */
/* deliver to a new IO object, reconstruct from XML */
Delivery::Delivery (Session& s, const XMLNode& node)
: IOProcessor (s, "reset")
Delivery::Delivery (Session& s, boost::shared_ptr<MuteMaster> mm, const XMLNode& node)
: IOProcessor (s, false, true, "reset")
, _role (Role (0))
, _metering (false)
, _muted_by_self (false)
, _muted_by_others (false)
, _output_buffers (new BufferSet())
, _solo_level (0)
, _solo_isolated (false)
, _mute_master (mm)
{
_output_offset = 0;
_current_gain = 1.0;
_panner = boost::shared_ptr<Panner>(new Panner (_name, _session));
if (set_state (node)) {
throw failed_constructor ();
}
_output->changed.connect (mem_fun (*this, &Delivery::output_changed));
}
void
Delivery::cycle_start (nframes_t nframes)
{
_output_offset = 0;
_no_outs_cuz_we_no_monitor = false;
}
void
Delivery::increment_output_offset (nframes_t n)
{
_output_offset += n;
}
bool
Delivery::visible () const
{
if (_role & (Main|Solo)) {
if (_role & Main) {
return false;
}
@ -91,6 +135,8 @@ Delivery::configure_io (ChanCount in, ChanCount out)
if (out != in) { // always 1:1
return false;
}
reset_panner ();
return Processor::configure_io (in, out);
}
@ -98,64 +144,46 @@ Delivery::configure_io (ChanCount in, ChanCount out)
void
Delivery::run_in_place (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes)
{
if (_io->n_outputs().get (_io->default_type()) == 0) {
if (_output->n_ports ().get (_output->default_type()) == 0) {
return;
}
if (!active() || _muted_by_self || _muted_by_others) {
silence (nframes);
if (_metering) {
_io->peak_meter().reset();
}
} else {
// this Delivery processor is not a derived type, and thus we assume
// we really can modify the buffers passed in (it is almost certainly
// the main output stage of a Route). Contrast with Send::run_in_place()
// which cannot do this.
// we have to copy the input, because IO::deliver_output may alter the buffers
// in-place, which a send must never do.
BufferSet& sendbufs = _session.get_mix_buffers (bufs.count());
sendbufs.read_from(bufs, nframes);
assert(sendbufs.count() == bufs.count());
_io->deliver_output (sendbufs, start_frame, end_frame, nframes);
if (_metering) {
if (_io->effective_gain() == 0) {
_io->peak_meter().reset();
} else {
_io->peak_meter().run_in_place(_io->output_buffers(), start_frame, end_frame, nframes);
}
}
}
}
void
Delivery::set_metering (bool yn)
{
_metering = yn;
gain_t tgain = target_gain ();
if (!_metering) {
/* XXX possible thread hazard here */
_io->peak_meter().reset();
if (tgain != _current_gain) {
Amp::apply_gain (bufs, nframes, _current_gain, tgain);
_current_gain = tgain;
}
}
void
Delivery::set_self_mute (bool yn)
{
if (yn != _muted_by_self) {
_muted_by_self = yn;
SelfMuteChange (); // emit signal
// Attach output buffers to port buffers
PortSet& ports (_output->ports());
output_buffers().attach_buffers (ports, nframes, _output_offset);
if (_panner && _panner->npanners() && !_panner->bypassed()) {
// Use the panner to distribute audio to output port buffers
_panner->run (bufs, output_buffers(), start_frame, end_frame, nframes);
} else {
// Do a 1:1 copy of data to output ports
if (bufs.count().n_audio() > 0 && ports.count().n_audio () > 0) {
_output->copy_to_outputs (bufs, DataType::AUDIO, nframes, _output_offset);
}
if (bufs.count().n_midi() > 0 && ports.count().n_midi () > 0) {
_output->copy_to_outputs (bufs, DataType::MIDI, nframes, _output_offset);
}
}
}
void
Delivery::set_nonself_mute (bool yn)
{
if (yn != _muted_by_others) {
_muted_by_others = yn;
OtherMuteChange (); // emit signal
}
}
XMLNode&
Delivery::state (bool full_state)
@ -170,10 +198,8 @@ Delivery::state (bool full_state)
node.add_property("type", "delivery");
}
node.add_property("metering", (_metering ? "yes" : "no"));
node.add_property("self-muted", (_muted_by_self ? "yes" : "no"));
node.add_property("other-muted", (_muted_by_others ? "yes" : "no"));
node.add_property("role", enum_2_string(_role));
node.add_child_nocopy (_panner->state (full_state));
return node;
}
@ -182,22 +208,236 @@ int
Delivery::set_state (const XMLNode& node)
{
const XMLProperty* prop;
if (IOProcessor::set_state (node)) {
return -1;
}
if ((prop = node.property ("role")) != 0) {
_role = Role (string_2_enum (prop->value(), _role));
}
if ((prop = node.property ("metering")) != 0) {
set_metering (prop->value() == "yes");
if ((prop = node.property ("solo_level")) != 0) {
_solo_level = 0; // needed for the reset to work
mod_solo_level (atoi (prop->value()));
}
if ((prop = node.property ("self-muted")) != 0) {
set_self_mute (prop->value() == "yes");
if ((prop = node.property ("solo-isolated")) != 0) {
set_solo_isolated (prop->value() == "yes");
}
if ((prop = node.property ("other-muted")) != 0) {
set_nonself_mute (prop->value() == "yes");
}
XMLNode* pan_node = node.child (X_("Panner"));
if (pan_node) {
cerr << _name << " reset pan state from XML\n";
_panner->set_state (*pan_node);
}
reset_panner ();
return 0;
}
void
Delivery::reset_panner ()
{
cerr << _name << " reset panner - plegal ? " << panners_legal << endl;
if (panners_legal) {
if (!no_panner_reset) {
cerr << "\treset panner with " << _output->name() << " = " << _output->n_ports()
<< " vs. " << pans_required () << endl;
_panner->reset (_output->n_ports().n_audio(), pans_required());
}
} else {
cerr << "\tdefer pan reset till later\n";
panner_legal_c.disconnect ();
panner_legal_c = PannersLegal.connect (mem_fun (*this, &Delivery::panners_became_legal));
}
}
int
Delivery::panners_became_legal ()
{
cerr << _name << " panners now legal, outputs @ " << _output << " on " << _output->name()
<< " = " << _output->n_ports() << " vs. " << pans_required() << endl;
_panner->reset (_output->n_ports().n_audio(), pans_required());
_panner->load (); // automation
panner_legal_c.disconnect ();
return 0;
}
void
Delivery::defer_pan_reset ()
{
no_panner_reset = true;
}
void
Delivery::allow_pan_reset ()
{
no_panner_reset = false;
reset_panner ();
}
int
Delivery::disable_panners (void)
{
panners_legal = false;
return 0;
}
int
Delivery::reset_panners ()
{
panners_legal = true;
return PannersLegal ();
}
void
Delivery::start_pan_touch (uint32_t which)
{
if (which < _panner->npanners()) {
_panner->pan_control(which)->start_touch();
}
}
void
Delivery::end_pan_touch (uint32_t which)
{
if (which < _panner->npanners()) {
_panner->pan_control(which)->stop_touch();
}
}
void
Delivery::transport_stopped (sframes_t frame)
{
_panner->transport_stopped (frame);
}
void
Delivery::flush (nframes_t nframes)
{
/* io_lock, not taken: function must be called from Session::process() calltree */
PortSet& ports (_output->ports());
for (PortSet::iterator i = ports.begin(); i != ports.end(); ++i) {
(*i).flush_buffers (nframes, _output_offset);
}
}
gain_t
Delivery::target_gain ()
{
/* if we've been told not to output because its a monitoring situation and
we're not monitoring, then be quiet.
*/
if (_no_outs_cuz_we_no_monitor) {
return 0.0;
}
gain_t desired_gain;
MuteMaster::MutePoint mp;
if (_solo_level) {
desired_gain = 1.0;
} else {
if (_solo_isolated) {
switch (_role) {
case Main:
mp = MuteMaster::Main;
break;
case Listen:
mp = MuteMaster::Listen;
break;
case Send:
case Insert:
if (_placement == PreFader) {
mp = MuteMaster::PreFader;
} else {
mp = MuteMaster::PostFader;
}
break;
}
desired_gain = _mute_master->mute_gain_at (mp);
} else if (_session.soloing()) {
switch (_role) {
case Main:
mp = MuteMaster::Main;
break;
case Listen:
mp = MuteMaster::Listen;
break;
case Send:
case Insert:
if (_placement == PreFader) {
mp = MuteMaster::PreFader;
} else {
mp = MuteMaster::PostFader;
}
break;
}
desired_gain = min (Config->get_solo_mute_gain(), _mute_master->mute_gain_at (mp));
} else {
desired_gain = 1.0;
}
}
return desired_gain;
}
void
Delivery::mod_solo_level (int32_t delta)
{
if (delta < 0) {
if (_solo_level >= (uint32_t) delta) {
_solo_level += delta;
} else {
_solo_level = 0;
}
} else {
_solo_level += delta;
}
}
void
Delivery::set_solo_isolated (bool yn)
{
_solo_isolated = yn;
}
void
Delivery::no_outs_cuz_we_no_monitor (bool yn)
{
_no_outs_cuz_we_no_monitor = yn;
}
bool
Delivery::set_name (const std::string& name)
{
bool ret = IOProcessor::set_name (name);
if (ret) {
ret = _panner->set_name (name);
}
return ret;
}
void
Delivery::output_changed (IOChange change, void* src)
{
if (change & ARDOUR::ConfigurationChanged) {
reset_panner ();
}
}

View File

@ -138,6 +138,8 @@ void
Diskstream::set_io (IO& io)
{
_io = &io;
input_change_pending = ConfigurationChanged;
non_realtime_input_change ();
set_align_style_from_io ();
}
@ -233,7 +235,7 @@ Diskstream::set_capture_offset ()
return;
}
_capture_offset = _io->input_latency();
_capture_offset = _io->latency();
}
void
@ -420,6 +422,11 @@ Diskstream::remove_region_from_last_capture (boost::weak_ptr<Region> wregion)
void
Diskstream::playlist_ranges_moved (list< Evoral::RangeMove<nframes_t> > const & movements_frames)
{
#if 0
XXX THIS HAS TO BE FIXED FOR 3.0
if (Config->get_automation_follows_regions () == false) {
return;
}
@ -431,7 +438,7 @@ Diskstream::playlist_ranges_moved (list< Evoral::RangeMove<nframes_t> > const &
}
/* move gain automation */
boost::shared_ptr<AutomationList> gain_alist = _io->gain_control()->alist();
boost::shared_ptr<AutomationList> gain_alist = _io->gain_control()->list();
XMLNode & before = gain_alist->get_state ();
gain_alist->move_ranges (movements);
_session.add_command (
@ -458,11 +465,12 @@ Diskstream::playlist_ranges_moved (list< Evoral::RangeMove<nframes_t> > const &
if (route) {
route->foreach_processor (sigc::bind (sigc::mem_fun (*this, &Diskstream::move_processor_automation), movements_frames));
}
#endif
}
void
Diskstream::move_processor_automation (boost::weak_ptr<Processor> p,
list< Evoral::RangeMove<nframes_t> > const & movements_frames)
list< Evoral::RangeMove<nframes_t> > const & movements_frames)
{
boost::shared_ptr<Processor> processor (p.lock ());
if (!processor) {

View File

@ -19,20 +19,21 @@
#include "pbd/enumwriter.h"
#include "ardour/types.h"
#include "ardour/delivery.h"
#include "ardour/session.h"
#include "ardour/location.h"
#include "ardour/audiofilesource.h"
#include "ardour/diskstream.h"
#include "ardour/audioregion.h"
#include "ardour/route_group.h"
#include "ardour/panner.h"
#include "ardour/track.h"
#include "ardour/midi_track.h"
#include "ardour/delivery.h"
#include "ardour/diskstream.h"
#include "ardour/export_filename.h"
#include "ardour/export_format_base.h"
#include "ardour/export_profile_manager.h"
#include "ardour/io.h"
#include "ardour/location.h"
#include "ardour/midi_track.h"
#include "ardour/panner.h"
#include "ardour/route_group.h"
#include "ardour/session.h"
#include "ardour/track.h"
#include "ardour/types.h"
using namespace std;
using namespace PBD;
@ -70,7 +71,6 @@ setup_enum_writer ()
SlaveSource _SlaveSource;
ShuttleBehaviour _ShuttleBehaviour;
ShuttleUnits _ShuttleUnits;
mute_type _mute_type;
Session::RecordState _Session_RecordState;
Session::Event::Type _Session_Event_Type;
SmpteFormat _Session_SmpteFormat;
@ -105,6 +105,7 @@ setup_enum_writer ()
ExportFormatBase::SRCQuality _ExportFormatBase_SRCQuality;
ExportProfileManager::TimeFormat _ExportProfileManager_TimeFormat;
Delivery::Role _Delivery_Role;
IO::Direction _IO_Direction;
#define REGISTER(e) enum_writer->register_distinct (typeid(e).name(), i, s); i.clear(); s.clear()
#define REGISTER_BITS(e) enum_writer->register_bits (typeid(e).name(), i, s); i.clear(); s.clear()
@ -328,12 +329,6 @@ setup_enum_writer ()
REGISTER_CLASS_ENUM (Session, pullup_Minus4Minus1);
REGISTER (_Session_PullupFormat);
REGISTER_ENUM (PRE_FADER);
REGISTER_ENUM (POST_FADER);
REGISTER_ENUM (CONTROL_OUTS);
REGISTER_ENUM (MAIN_OUTS);
REGISTER (_mute_type);
REGISTER_CLASS_ENUM (Route, Hidden);
REGISTER_CLASS_ENUM (Route, MasterOut);
REGISTER_CLASS_ENUM (Route, ControlOut);
@ -502,9 +497,13 @@ setup_enum_writer ()
REGISTER_CLASS_ENUM (ExportProfileManager, Off);
REGISTER (_ExportProfileManager_TimeFormat);
REGISTER_CLASS_ENUM (Delivery, Solo);
REGISTER_CLASS_ENUM (Delivery, Insert);
REGISTER_CLASS_ENUM (Delivery, Send);
REGISTER_CLASS_ENUM (Delivery, Listen);
REGISTER_CLASS_ENUM (Delivery, Main);
REGISTER_BITS (_Delivery_Role);
REGISTER_CLASS_ENUM (IO, Input);
REGISTER_CLASS_ENUM (IO, Output);
REGISTER (_IO_Direction);
}

File diff suppressed because it is too large Load Diff

View File

@ -46,20 +46,36 @@ using namespace PBD;
/* create an IOProcessor that proxies to a new IO object */
IOProcessor::IOProcessor (Session& s, const string& proc_name, const string io_name, DataType dtype)
IOProcessor::IOProcessor (Session& s, bool with_input, bool with_output,
const string& proc_name, const string io_name, DataType dtype)
: Processor(s, proc_name)
, _io (new IO(s, io_name.empty() ? proc_name : io_name, dtype))
{
_own_io = true;
/* these are true in this constructor whether we actually create the associated
IO objects or not.
*/
_own_input = true;
_own_output = true;
if (with_input) {
_input.reset (new IO(s, io_name.empty() ? proc_name : io_name, IO::Input, dtype));
}
if (with_output) {
_output.reset (new IO(s, io_name.empty() ? proc_name : io_name, IO::Output, dtype));
}
}
/* create an IOProcessor that proxies to an existing IO object */
IOProcessor::IOProcessor (Session& s, IO* io, const string& proc_name, DataType dtype)
IOProcessor::IOProcessor (Session& s, boost::shared_ptr<IO> in, boost::shared_ptr<IO> out,
const string& proc_name, DataType dtype)
: Processor(s, proc_name)
, _io (io)
, _input (in)
, _output (out)
{
_own_io = false;
_own_input = false;
_own_output = false;
}
IOProcessor::~IOProcessor ()
@ -68,12 +84,21 @@ IOProcessor::~IOProcessor ()
}
void
IOProcessor::set_io (boost::shared_ptr<IO> io)
IOProcessor::set_input (boost::shared_ptr<IO> io)
{
/* CALLER MUST HOLD PROCESS LOCK */
_io = io;
_own_io = false;
_input = io;
_own_input = false;
}
void
IOProcessor::set_output (boost::shared_ptr<IO> io)
{
/* CALLER MUST HOLD PROCESS LOCK */
_output = io;
_own_output = false;
}
XMLNode&
@ -81,12 +106,28 @@ IOProcessor::state (bool full_state)
{
XMLNode& node (Processor::state (full_state));
if (_own_io) {
node.add_child_nocopy (_io->state (full_state));
node.add_property ("own-io", "yes");
if (_own_input) {
XMLNode& i (_input->state (full_state));
// i.name() = X_("output");
node.add_child_nocopy (i);
node.add_property ("own-input", "yes");
} else {
node.add_property ("own-io", "no");
node.add_property ("io", _io->name());
node.add_property ("own-input", "no");
if (_input) {
node.add_property ("input", _input->name());
}
}
if (_own_output) {
XMLNode& o (_output->state (full_state));
// o.name() = X_("output");
node.add_child_nocopy (o);
node.add_property ("own-output", "yes");
} else {
node.add_property ("own-output", "no");
if (_output) {
node.add_property ("output", _output->name());
}
}
return node;
@ -100,67 +141,59 @@ IOProcessor::set_state (const XMLNode& node)
Processor::set_state(node);
if ((prop = node.property ("own-io")) != 0) {
_own_io = prop->value() == "yes";
if ((prop = node.property ("own-input")) != 0) {
_own_input = (prop->value() == "yes");
}
if ((prop = node.property ("own-output")) != 0) {
_own_output = (prop->value() == "yes");
}
cerr << _name << " own input = " << _own_input << " output = " << _own_output << endl;
/* don't attempt to set state for a proxied IO that we don't own */
if (!_own_io) {
/* look up the IO object we're supposed to proxy to */
if ((prop = node.property ("io")) == 0) {
fatal << "IOProcessor has no named IO object" << endmsg;
/*NOTREACHED*/
}
boost::shared_ptr<Route> r = _session.route_by_name (prop->value());
if (!r) {
fatal << string_compose ("IOProcessor uses an unknown IO object called %1", prop->value()) << endmsg;
/*NOTREACHED*/
}
/* gotcha */
_io = boost::static_pointer_cast<IO> (r);
return 0;
}
XMLNodeList nlist = node.children();
XMLNodeIterator niter;
for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
if ((*niter)->name() == IO::state_node_name) {
io_node = (*niter);
break;
} else if ((*niter)->name() == "Redirect") {
XMLNodeList rlist = (*niter)->children();
XMLNodeIterator riter;
for (riter = rlist.begin(); riter != rlist.end(); ++riter) {
if ( (*riter)->name() == IO::state_node_name) {
warning << _("Found legacy IO in a redirect") << endmsg;
io_node = (*riter);
break;
}
if (_own_input) {
for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
if ((*niter)->name() == "input") {
io_node = (*niter);
break;
}
}
}
if (io_node) {
_io->set_state(*io_node);
// legacy sessions: use IO name
if ((prop = node.property ("name")) == 0) {
set_name (_io->name());
if (io_node) {
_input->set_state(*io_node);
// legacy sessions: use IO name
if ((prop = node.property ("name")) == 0) {
set_name (_input->name());
}
} else {
error << _("XML node describing an IOProcessor is missing an IO node") << endmsg;
return -1;
}
} else {
error << _("XML node describing a redirect is missing an IO node") << endmsg;
return -1;
}
if (_own_output) {
for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
if ((*niter)->name() == "output") {
io_node = (*niter);
break;
}
}
if (io_node) {
_output->set_state(*io_node);
// legacy sessions: use IO name
if ((prop = node.property ("name")) == 0) {
set_name (_output->name());
}
}
}
return 0;
@ -169,41 +202,33 @@ IOProcessor::set_state (const XMLNode& node)
void
IOProcessor::silence (nframes_t nframes)
{
if (_own_io) {
_io->silence (nframes);
if (_own_output && _output) {
_output->silence (nframes);
}
}
ChanCount
IOProcessor::output_streams() const
{
return _io->n_outputs();
return _output ? _output->n_ports() : ChanCount::ZERO;
}
ChanCount
IOProcessor::input_streams () const
{
return _io->n_inputs();
return _input ? _input->n_ports() : ChanCount::ZERO;
}
ChanCount
IOProcessor::natural_output_streams() const
{
return _io->n_outputs();
return _output ? _output->n_ports() : ChanCount::ZERO;
}
ChanCount
IOProcessor::natural_input_streams () const
{
return _io->n_inputs();
}
void
IOProcessor::automation_snapshot (nframes_t now, bool force)
{
if (_own_io) {
_io->automation_snapshot(now, force);
}
return _input ? _input->n_ports() : ChanCount::ZERO;
}
bool
@ -211,8 +236,12 @@ IOProcessor::set_name (const std::string& name)
{
bool ret = SessionObject::set_name (name);
if (ret && _own_io) {
ret = _io->set_name (name);
if (ret && _own_input && _input) {
ret = _input->set_name (name);
}
if (ret && _own_output && _output) {
ret = _output->set_name (name);
}
return ret;

View File

@ -29,8 +29,41 @@
using namespace std;
namespace ARDOUR {
using namespace ARDOUR;
sigc::signal<void> Metering::Meter;
Glib::StaticMutex Metering::m_meter_signal_lock;
sigc::connection
Metering::connect (sigc::slot<void> the_slot)
{
// SignalProcessor::Meter is emitted from another thread so the
// Meter signal must be protected.
Glib::Mutex::Lock guard (m_meter_signal_lock);
return Meter.connect (the_slot);
}
void
Metering::disconnect (sigc::connection& c)
{
Glib::Mutex::Lock guard (m_meter_signal_lock);
c.disconnect ();
}
/**
Update the meters.
The meter signal lock is taken to prevent modification of the
Meter signal while updating the meters, taking the meter signal
lock prior to taking the io_lock ensures that all IO will remain
valid while metering.
*/
void
Metering::update_meters()
{
Glib::Mutex::Lock guard (m_meter_signal_lock);
Meter(); /* EMIT SIGNAL */
}
/** Get peaks from @a bufs
* Input acceptance is lenient - the first n buffers from @a bufs will
@ -128,8 +161,10 @@ PeakMeter::configure_io (ChanCount in, ChanCount out)
}
/** To be driven by the Meter signal from IO.
* Caller MUST hold io_lock!
* Caller MUST hold its own processor_lock to prevent reconfiguration
* of meter size during this call.
*/
void
PeakMeter::meter ()
{
@ -139,12 +174,10 @@ PeakMeter::meter ()
for (size_t n = 0; n < limit; ++n) {
/* XXX we should use atomic exchange here */
/* grab peak since last read */
float new_peak = _peak_power[n];
_peak_power[n] = 0;
float new_peak = _peak_power[n]; /* XXX we should use atomic exchange from here ... */
_peak_power[n] = 0; /* ... to here */
/* compute new visible value using falloff */
@ -176,4 +209,3 @@ PeakMeter::state (bool full_state)
return node;
}
} // namespace ARDOUR

View File

@ -159,8 +159,8 @@ MidiDiskstream::non_realtime_input_change ()
}
if (input_change_pending & ConfigurationChanged) {
if (_io->n_inputs().n_midi() != _n_channels.n_midi()) {
error << "Can not feed IO " << _io->n_inputs()
if (_io->n_ports().n_midi() != _n_channels.n_midi()) {
error << "Can not feed IO " << _io->n_ports()
<< " with diskstream " << _n_channels << endl;
}
}
@ -199,7 +199,7 @@ MidiDiskstream::non_realtime_input_change ()
void
MidiDiskstream::get_input_sources ()
{
uint32_t ni = _io->n_inputs().n_midi();
uint32_t ni = _io->n_ports().n_midi();
if (ni == 0) {
return;
@ -208,7 +208,7 @@ MidiDiskstream::get_input_sources ()
// This is all we do for now at least
assert(ni == 1);
_source_port = _io->midi_input(0);
_source_port = _io->midi(0);
// do... stuff?
}
@ -421,6 +421,7 @@ MidiDiskstream::check_record_status (nframes_t transport_frame, nframes_t nframe
last_possibly_recording = possibly_recording;
}
#if 0
static void
trace_midi (ostream& o, MIDI::byte *msg, size_t len)
{
@ -587,6 +588,7 @@ trace_midi (ostream& o, MIDI::byte *msg, size_t len)
break;
}
}
#endif
int
MidiDiskstream::process (nframes_t transport_frame, nframes_t nframes, bool can_record, bool rec_monitors_input)

View File

@ -27,6 +27,7 @@
#include "ardour/amp.h"
#include "ardour/buffer_set.h"
#include "ardour/delivery.h"
#include "ardour/io_processor.h"
#include "ardour/meter.h"
#include "ardour/midi_diskstream.h"
@ -94,14 +95,14 @@ int
MidiTrack::set_diskstream (boost::shared_ptr<MidiDiskstream> ds)
{
_diskstream = ds;
_diskstream->set_io (*this);
_diskstream->set_io (*(_input.get()));
_diskstream->set_destructive (_mode == Destructive);
_diskstream->set_record_enabled (false);
//_diskstream->monitor_input (false);
ic_connection.disconnect();
ic_connection = input_changed.connect (mem_fun (*_diskstream, &MidiDiskstream::handle_input_change));
ic_connection = _input->changed.connect (mem_fun (*_diskstream, &MidiDiskstream::handle_input_change));
DiskstreamChanged (); /* EMIT SIGNAL */
@ -113,11 +114,14 @@ MidiTrack::use_diskstream (string name)
{
boost::shared_ptr<MidiDiskstream> dstream;
cerr << "\n\n\nMIDI use diskstream\n";
if ((dstream = boost::dynamic_pointer_cast<MidiDiskstream>(_session.diskstream_by_name (name))) == 0) {
error << string_compose(_("MidiTrack: midi diskstream \"%1\" not known by session"), name) << endmsg;
return -1;
}
cerr << "\n\n\nMIDI found DS\n";
return set_diskstream (dstream);
}
@ -191,6 +195,8 @@ MidiTrack::_set_state (const XMLNode& node, bool call_base)
that means "you should create a new diskstream here, not look for
an old one.
*/
cerr << "\n\n\n\n MIDI track " << name() << " found DS id " << id << endl;
if (id == zero) {
use_new_diskstream ();
@ -363,8 +369,6 @@ MidiTrack::roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame,
int dret;
boost::shared_ptr<MidiDiskstream> diskstream = midi_diskstream();
prepare_inputs (nframes);
{
Glib::RWLock::ReaderLock lm (_processor_lock, Glib::TRY_LOCK);
if (lm.locked()) {
@ -405,7 +409,7 @@ MidiTrack::roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame,
/* special condition applies */
if (_meter_point == MeterInput) {
just_meter_input (start_frame, end_frame, nframes);
_input->process_input (_meter, start_frame, end_frame, nframes);
}
if (diskstream->record_enabled() && !can_record && !_session.config.get_auto_input()) {
@ -438,7 +442,7 @@ MidiTrack::roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame,
}
flush_outputs (nframes);
_main_outs->flush (nframes);
return 0;
}

109
libs/ardour/mute_master.cc Normal file
View File

@ -0,0 +1,109 @@
/*
Copyright (C) 2009 Paul Davis
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "ardour/mute_master.h"
#include "ardour/rc_configuration.h"
#include "i18n.h"
using namespace ARDOUR;
MuteMaster::MuteMaster (Session& s, const std::string& name)
: AutomationControl (s, Evoral::Parameter (MuteAutomation), boost::shared_ptr<AutomationList>(), name)
, _mute_point (MutePoint (0))
{
// default range for parameter is fine
_automation = new AutomationList (MuteAutomation);
set_list (boost::shared_ptr<AutomationList>(_automation));
}
void
MuteMaster::clear_mute ()
{
if (_mute_point != MutePoint (0)) {
_mute_point = MutePoint (0);
MutePointChanged (); // EMIT SIGNAL
}
}
void
MuteMaster::mute_at (MutePoint mp)
{
if ((_mute_point & mp) != mp) {
_mute_point = MutePoint (_mute_point | mp);
MutePointChanged (); // EMIT SIGNAL
}
}
void
MuteMaster::unmute_at (MutePoint mp)
{
if ((_mute_point & mp) == mp) {
_mute_point = MutePoint (_mute_point & ~mp);
MutePointChanged (); // EMIT SIGNAL
}
}
void
MuteMaster::mute (bool yn)
{
/* convenience wrapper around AutomationControl method */
if (yn) {
set_value (1.0f);
} else {
set_value (0.0f);
}
}
gain_t
MuteMaster::mute_gain_at (MutePoint mp) const
{
if (_mute_point & mp) {
return Config->get_solo_mute_gain ();
} else {
return 1.0;
}
}
void
MuteMaster::set_value (float f)
{
mute_at ((MutePoint) ((int) rint (f)));
}
float
MuteMaster::get_value () const
{
return (float) _mute_point;
}
int
MuteMaster::set_state (const XMLNode& node)
{
return 0;
}
XMLNode&
MuteMaster::get_state()
{
return *(new XMLNode (X_("MuteMaster")));
}

View File

@ -703,7 +703,8 @@ Multi2dPanner::set_state (const XMLNode& node)
/*---------------------------------------------------------------------- */
Panner::Panner (string name, Session& s)
: Processor(s, name)
: SessionObject (s, name)
, AutomatableControls (s)
{
//set_name_old_auto (name);
set_name (name);
@ -829,6 +830,8 @@ Panner::reset (uint32_t nouts, uint32_t npans)
bool changed = false;
bool do_not_and_did_not_need_panning = ((nouts < 2) && (outputs.size() < 2));
cerr << "panner " << _name << " reset to " << nouts << " / " << npans << endl;
/* if new and old config don't need panning, or if
the config hasn't changed, we're done.
*/
@ -1058,15 +1061,13 @@ Panner::get_state (void)
XMLNode&
Panner::state (bool full)
{
XMLNode& node = Processor::state(full);
node.add_property ("type", "panner");
XMLNode* node = new XMLNode ("Panner");
char buf[32];
node.add_property (X_("linked"), (_linked ? "yes" : "no"));
node.add_property (X_("link_direction"), enum_2_string (_link_direction));
node.add_property (X_("bypassed"), (bypassed() ? "yes" : "no"));
node->add_property (X_("linked"), (_linked ? "yes" : "no"));
node->add_property (X_("link_direction"), enum_2_string (_link_direction));
node->add_property (X_("bypassed"), (bypassed() ? "yes" : "no"));
for (vector<Panner::Output>::iterator o = outputs.begin(); o != outputs.end(); ++o) {
XMLNode* onode = new XMLNode (X_("Output"));
@ -1074,15 +1075,15 @@ Panner::state (bool full)
onode->add_property (X_("x"), buf);
snprintf (buf, sizeof (buf), "%.12g", (*o).y);
onode->add_property (X_("y"), buf);
node.add_child_nocopy (*onode);
node->add_child_nocopy (*onode);
}
for (vector<StreamPanner*>::const_iterator i = _streampanners.begin(); i != _streampanners.end(); ++i) {
node.add_child_nocopy ((*i)->state (full));
node->add_child_nocopy ((*i)->state (full));
}
return node;
return *node;
}
int
@ -1098,8 +1099,6 @@ Panner::set_state (const XMLNode& node)
clear_panners ();
Processor::set_state(node);
ChanCount ins = ChanCount::ZERO;
ChanCount outs = ChanCount::ZERO;
@ -1419,7 +1418,7 @@ Panner::distribute_no_automation (BufferSet& inbufs, BufferSet& outbufs, nframes
}
void
Panner::run_out_of_place (BufferSet& inbufs, BufferSet& outbufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes)
Panner::run (BufferSet& inbufs, BufferSet& outbufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes)
{
if (outbufs.count().n_audio() == 0) {
// Failing to deliver audio we were asked to deliver is a bug
@ -1432,16 +1431,16 @@ Panner::run_out_of_place (BufferSet& inbufs, BufferSet& outbufs, sframes_t start
assert(!empty());
// If we shouldn't play automation defer to distribute_no_automation
if ( !( automation_state() & Play ||
((automation_state() & Touch) && !touching()) ) ) {
if (!(automation_state() & Play || ((automation_state() & Touch) && !touching()))) {
// Speed quietning
gain_t gain_coeff = 1.0;
if (fabsf(_session.transport_speed()) > 1.5f) {
gain_coeff = speed_quietning;
}
distribute_no_automation(inbufs, outbufs, nframes, gain_coeff);
distribute_no_automation (inbufs, outbufs, nframes, gain_coeff);
return;
}

View File

@ -24,6 +24,7 @@
#include "pbd/failed_constructor.h"
#include "pbd/xml++.h"
#include "ardour/delivery.h"
#include "ardour/port_insert.h"
#include "ardour/plugin.h"
#include "ardour/port.h"
@ -40,15 +41,17 @@ using namespace std;
using namespace ARDOUR;
using namespace PBD;
PortInsert::PortInsert (Session& s)
: IOProcessor (s, string_compose (_("insert %1"), (bitslot = s.next_insert_id()) + 1), "")
PortInsert::PortInsert (Session& s, boost::shared_ptr<MuteMaster> mm)
: IOProcessor (s, true, true, string_compose (_("insert %1"), (bitslot = s.next_insert_id()) + 1), "")
, _out (new Delivery (s, _output, mm, _name, Delivery::Insert))
{
init ();
ProcessorCreated (this); /* EMIT SIGNAL */
}
PortInsert::PortInsert (Session& s, const XMLNode& node)
: IOProcessor (s, "unnamed port insert")
PortInsert::PortInsert (Session& s, boost::shared_ptr<MuteMaster> mm, const XMLNode& node)
: IOProcessor (s, true, true, "unnamed port insert")
, _out (new Delivery (s, _output, mm, _name, Delivery::Insert))
{
if (set_state (node)) {
throw failed_constructor();
@ -62,30 +65,21 @@ PortInsert::~PortInsert ()
GoingAway ();
}
void
PortInsert::init ()
{
if (_io->ensure_io(output_streams(), input_streams(), false, this)) { // sic
error << _("PortInsert: cannot create ports") << endmsg;
throw failed_constructor();
}
}
void
PortInsert::run_in_place (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes)
{
if (_io->n_outputs().n_total() == 0) {
if (_output->n_ports().n_total() == 0) {
return;
}
if (!active()) {
/* deliver silence */
_io->silence (nframes);
silence (nframes);
return;
}
_io->deliver_output (bufs, start_frame, end_frame, nframes);
_io->collect_input (bufs, nframes);
_out->run_in_place (bufs, start_frame, end_frame, nframes);
_input->collect_input (bufs, nframes, ChanCount::ZERO);
}
XMLNode&
@ -97,7 +91,7 @@ PortInsert::get_state(void)
XMLNode&
PortInsert::state (bool full)
{
XMLNode& node = IOProcessor::state(full);
XMLNode& node = Processor::state(full);
char buf[32];
node.add_property ("type", "port");
snprintf (buf, sizeof (buf), "%" PRIu32, bitslot);
@ -141,7 +135,7 @@ PortInsert::set_state(const XMLNode& node)
}
}
IOProcessor::set_state (*insert_node);
Processor::set_state (*insert_node);
return 0;
}
@ -156,7 +150,7 @@ PortInsert::signal_latency() const
need to take that into account too.
*/
return _session.engine().frames_per_cycle() + _io->input_latency();
return _session.engine().frames_per_cycle() + _input->signal_latency();
}
bool
@ -164,7 +158,11 @@ PortInsert::configure_io (ChanCount in, ChanCount out)
{
/* for an insert, processor input corresponds to IO output, and vice versa */
if (_io->ensure_io (out, in, false, this) != 0) {
if (_input->ensure_io (in, false, this) != 0) {
return false;
}
if (_output->ensure_io (out, false, this) != 0) {
return false;
}
@ -178,3 +176,12 @@ PortInsert::can_support_io_configuration (const ChanCount& in, ChanCount& out) c
return true;
}
bool
PortInsert::set_name (const std::string& name)
{
bool ret = Processor::set_name (name);
ret = (_input->set_name (name) || _output->set_name (name));
return ret;
}

View File

@ -211,7 +211,8 @@ Processor::configure_io (ChanCount in, ChanCount out)
{
/* This class assumes 1:1 input:output.static output stream count.
Derived classes must override and set _configured_output appropriately
if this is not the case */
if this is not the case
*/
_configured_input = in;
_configured_output = out;

View File

@ -21,14 +21,15 @@
#include "pbd/xml++.h"
#include "ardour/return.h"
#include "ardour/session.h"
#include "ardour/port.h"
#include "ardour/amp.h"
#include "ardour/audio_port.h"
#include "ardour/buffer_set.h"
#include "ardour/io.h"
#include "ardour/meter.h"
#include "ardour/panner.h"
#include "ardour/io.h"
#include "ardour/port.h"
#include "ardour/return.h"
#include "ardour/session.h"
#include "i18n.h"
@ -36,14 +37,26 @@ using namespace ARDOUR;
using namespace PBD;
Return::Return (Session& s)
: IOProcessor (s, string_compose (_("return %1"), (_bitslot = s.next_return_id()) + 1))
: IOProcessor (s, true, false, string_compose (_("return %1"), (_bitslot = s.next_return_id()) + 1))
, _metering (false)
{
/* never muted */
_amp.reset (new Amp (_session, boost::shared_ptr<MuteMaster>()));
_meter.reset (new PeakMeter (_session));
ProcessorCreated (this); /* EMIT SIGNAL */
}
Return::Return (Session& s, const XMLNode& node)
: IOProcessor (s, "return")
: IOProcessor (s, true, false, "return")
, _metering (false)
{
/* never muted */
_amp.reset (new Amp (_session, boost::shared_ptr<MuteMaster>()));
_meter.reset (new PeakMeter (_session));
if (set_state (node)) {
throw failed_constructor();
}
@ -108,23 +121,38 @@ Return::set_state(const XMLNode& node)
void
Return::run_in_place (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes)
{
if (active()) {
_io->collect_input (bufs, nframes, _configured_input);
bufs.set_count(_configured_output);
if (!active() || _input->n_ports() == ChanCount::ZERO) {
return;
}
_input->collect_input (bufs, nframes, _configured_input);
bufs.set_count(_configured_output);
// Can't automate gain for sends or returns yet because we need different buffers
// so that we don't overwrite the main automation data for the route amp
// _amp->setup_gain_automation (start_frame, end_frame, nframes);
_amp->run_in_place (bufs, start_frame, end_frame, nframes);
if (_metering) {
if (_amp->gain_control()->get_value() == 0) {
_meter->reset();
} else {
_meter->run_in_place (bufs, start_frame, end_frame, nframes);
}
}
}
bool
Return::can_support_io_configuration (const ChanCount& in, ChanCount& out) const
{
out = in + _io->n_inputs();
out = in + _input->n_ports();
return true;
}
bool
Return::configure_io (ChanCount in, ChanCount out)
{
if (out != in + _io->n_inputs()) {
if (out != in + _input->n_ports()) {
return false;
}
@ -162,3 +190,4 @@ Return::make_unique (XMLNode &state, Session &session)
}
}

File diff suppressed because it is too large Load Diff

View File

@ -27,6 +27,7 @@
#include "pbd/error.h"
#include "pbd/enumwriter.h"
#include "ardour/amp.h"
#include "ardour/route_group.h"
#include "ardour/audio_track.h"
#include "ardour/audio_diskstream.h"
@ -87,7 +88,7 @@ RouteGroup::get_min_factor(gain_t factor)
gain_t g;
for (list<Route *>::iterator i = routes.begin(); i != routes.end(); i++) {
g = (*i)->gain();
g = (*i)->amp()->gain();
if ( (g+g*factor) >= 0.0f)
continue;
@ -106,7 +107,7 @@ RouteGroup::get_max_factor(gain_t factor)
gain_t g;
for (list<Route *>::iterator i = routes.begin(); i != routes.end(); i++) {
g = (*i)->gain();
g = (*i)->amp()->gain();
// if the current factor woulnd't raise this route above maximum
if ( (g+g*factor) <= 1.99526231f)

View File

@ -21,6 +21,7 @@
#include "pbd/xml++.h"
#include "ardour/amp.h"
#include "ardour/send.h"
#include "ardour/session.h"
#include "ardour/port.h"
@ -35,15 +36,23 @@
using namespace ARDOUR;
using namespace PBD;
Send::Send (Session& s)
: Delivery (s, string_compose (_("send %1"), (_bitslot = s.next_send_id()) + 1), Delivery::Send)
Send::Send (Session& s, boost::shared_ptr<MuteMaster> mm)
: Delivery (s, mm, string_compose (_("send %1"), (_bitslot = s.next_send_id()) + 1), Delivery::Send)
, _metering (false)
{
_amp.reset (new Amp (_session, _mute_master));
_meter.reset (new PeakMeter (_session));
ProcessorCreated (this); /* EMIT SIGNAL */
}
Send::Send (Session& s, const XMLNode& node)
: Delivery (s, "send", Delivery::Send)
Send::Send (Session& s, boost::shared_ptr<MuteMaster> mm, const XMLNode& node)
: Delivery (s, mm, "send", Delivery::Send)
, _metering (false)
{
_amp.reset (new Amp (_session, _mute_master));
_meter.reset (new PeakMeter (_session));
if (set_state (node)) {
throw failed_constructor();
}
@ -56,6 +65,43 @@ Send::~Send ()
GoingAway ();
}
void
Send::run_in_place (BufferSet& bufs, sframes_t start_frame, sframes_t end_frame, nframes_t nframes)
{
if (!_active || _output->n_ports() == ChanCount::ZERO) {
_meter->reset ();
return;
}
// we have to copy the input, because deliver_output() may alter the buffers
// in-place, which a send must never do.
BufferSet& sendbufs = _session.get_mix_buffers (bufs.count());
sendbufs.read_from (bufs, nframes);
assert(sendbufs.count() == bufs.count());
/* gain control */
// Can't automate gain for sends or returns yet because we need different buffers
// so that we don't overwrite the main automation data for the route amp
// _amp->setup_gain_automation (start_frame, end_frame, nframes);
_amp->run_in_place (sendbufs, start_frame, end_frame, nframes);
/* deliver to outputs */
Delivery::run_in_place (sendbufs, start_frame, end_frame, nframes);
/* consider metering */
if (_metering) {
if (_amp->gain_control()->get_value() == 0) {
_meter->reset();
} else {
_meter->run_in_place (*_output_buffers, start_frame, end_frame, nframes);
}
}
}
XMLNode&
Send::get_state(void)
{
@ -90,17 +136,9 @@ Send::set_state(const XMLNode& node)
const XMLNode* insert_node = &node;
/* Send has regular IO automation (gain, pan) */
for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
if ((*niter)->name() == IOProcessor::state_node_name) {
insert_node = *niter;
} else if ((*niter)->name() == X_("Automation")) {
// _io->set_automation_state (*(*niter), Evoral::Parameter(GainAutomation));
}
}
/* XXX need to load automation state & data for amp */
IOProcessor::set_state (*insert_node);
Delivery::set_state (*insert_node);
return 0;
}
@ -108,7 +146,7 @@ Send::set_state(const XMLNode& node)
bool
Send::can_support_io_configuration (const ChanCount& in, ChanCount& out) const
{
if (_io->n_inputs() == ChanCount::ZERO && _io->n_outputs() == ChanCount::ZERO) {
if (_output->n_ports() == ChanCount::ZERO) {
/* not configured yet, we can support anything */
@ -126,25 +164,6 @@ Send::can_support_io_configuration (const ChanCount& in, ChanCount& out) const
return false;
}
bool
Send::configure_io (ChanCount in, ChanCount out)
{
/* we're transparent no matter what. fight the power. */
if (out != in) {
return false;
}
if (_io->ensure_io (ChanCount::ZERO, in, false, this) != 0) {
return false;
}
Processor::configure_io(in, out);
_io->reset_panner();
return true;
}
/** Set up the XML description of a send so that its name is unique.
* @param state XML send state.
* @param session Session.

View File

@ -272,7 +272,8 @@ Session::Session (AudioEngine &eng,
if (control_out_channels) {
ChanCount count(DataType::AUDIO, control_out_channels);
shared_ptr<Route> r (new Route (*this, _("monitor"), Route::ControlOut, DataType::AUDIO));
r->ensure_io (count, count, false, this);
r->input()->ensure_io (count, false, this);
r->output()->ensure_io (count, false, this);
r->set_remote_control_id (control_id++);
rl.push_back (r);
@ -280,9 +281,9 @@ Session::Session (AudioEngine &eng,
if (master_out_channels) {
ChanCount count(DataType::AUDIO, master_out_channels);
cerr << "new MO with " << count << endl;
shared_ptr<Route> r (new Route (*this, _("master"), Route::MasterOut, DataType::AUDIO));
r->ensure_io (count, count, false, this);
r->input()->ensure_io (count, false, this);
r->output()->ensure_io (count, false, this);
r->set_remote_control_id (control_id);
rl.push_back (r);
@ -516,8 +517,8 @@ Session::set_worst_io_latencies ()
boost::shared_ptr<RouteList> r = routes.reader ();
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
_worst_output_latency = max (_worst_output_latency, (*i)->output_latency());
_worst_input_latency = max (_worst_input_latency, (*i)->input_latency());
_worst_output_latency = max (_worst_output_latency, (*i)->output()->latency());
_worst_input_latency = max (_worst_input_latency, (*i)->input()->latency());
}
}
@ -574,15 +575,15 @@ Session::when_engine_running ()
for (int physport = 0; physport < 2; ++physport) {
string physical_output = _engine.get_nth_physical_output (DataType::AUDIO, physport);
if (physical_output.length()) {
if (_click_io->add_output_port (physical_output, this)) {
if (_click_io->add_port (physical_output, this)) {
// relax, even though its an error
}
}
}
if (_click_io->n_outputs () > ChanCount::ZERO) {
if (_click_io->n_ports () > ChanCount::ZERO) {
_clicking = Config->get_clicking ();
}
}
@ -665,12 +666,6 @@ Session::when_engine_running ()
if (_master_out) {
/* force the master to ignore any later call to this
*/
if (_master_out->pending_state_node) {
_master_out->ports_became_legal();
}
/* if requested auto-connect the outputs to the first N physical ports.
*/
@ -678,11 +673,11 @@ Session::when_engine_running ()
uint32_t limit = _master_out->n_outputs().n_total();
for (uint32_t n = 0; n < limit; ++n) {
Port* p = _master_out->output (n);
Port* p = _master_out->output()->nth (n);
string connect_to = _engine.get_nth_physical_output (DataType (p->type()), n);
if (!connect_to.empty()) {
if (_master_out->connect_output (p, connect_to, this)) {
if (_master_out->output()->connect (p, connect_to, this)) {
error << string_compose (_("cannot connect master output %1 to %2"), n, connect_to)
<< endmsg;
break;
@ -760,10 +755,6 @@ Session::hookup_io ()
}
}
/* Tell all IO objects to create their ports */
IO::enable_ports ();
/* Connect track to listen/solo etc. busses XXX generalize this beyond control_out */
if (_control_out) {
@ -777,7 +768,7 @@ Session::hookup_io ()
boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track> (*x);
if (t) {
t->listen_via (_control_out, X_("listen"));
t->listen_via (_control_out->input(), X_("listen"));
}
}
}
@ -794,7 +785,7 @@ Session::hookup_io ()
/* Now reset all panners */
IO::reset_panners ();
Delivery::reset_panners ();
/* Anyone who cares about input state, wake up and do something */
@ -1468,7 +1459,7 @@ Session::resort_routes_using (shared_ptr<RouteList> r)
continue;
}
if ((*j)->feeds (*i)) {
if ((*j)->feeds ((*i)->input())) {
(*i)->fed_by.insert (*j);
}
}
@ -1553,7 +1544,13 @@ Session::new_midi_track (TrackMode mode, uint32_t how_many)
try {
track = boost::shared_ptr<MidiTrack>((new MidiTrack (*this, track_name, Route::Flag (0), mode)));
if (track->ensure_io (ChanCount(DataType::MIDI, 1), ChanCount(DataType::AUDIO, 1), false, this)) {
if (track->input()->ensure_io (ChanCount(DataType::MIDI, 1), false, this)) {
error << "cannot configure 1 in/1 out configuration for new midi track" << endmsg;
goto failed;
}
if (track->output()->ensure_io (ChanCount(DataType::AUDIO, 1), false, this)) {
error << "cannot configure 1 in/1 out configuration for new midi track" << endmsg;
goto failed;
}
@ -1711,7 +1708,14 @@ Session::new_audio_track (int input_channels, int output_channels, TrackMode mod
try {
track = boost::shared_ptr<AudioTrack>((new AudioTrack (*this, track_name, Route::Flag (0), mode)));
if (track->ensure_io (ChanCount(DataType::AUDIO, input_channels), ChanCount(DataType::AUDIO, output_channels), false, this)) {
if (track->input()->ensure_io (ChanCount(DataType::AUDIO, input_channels), false, this)) {
error << string_compose (_("cannot configure %1 in/%2 out configuration for new audio track"),
input_channels, output_channels)
<< endmsg;
goto failed;
}
if (track->output()->ensure_io (ChanCount(DataType::AUDIO, output_channels), false, this)) {
error << string_compose (_("cannot configure %1 in/%2 out configuration for new audio track"),
input_channels, output_channels)
<< endmsg;
@ -1729,7 +1733,7 @@ Session::new_audio_track (int input_channels, int output_channels, TrackMode mod
port = physinputs[(channels_used+x)%nphysical_in];
}
if (port.length() && track->connect_input (track->input (x), port, this)) {
if (port.length() && track->input()->connect (track->input()->nth(x), port, this)) {
break;
}
}
@ -1745,11 +1749,11 @@ Session::new_audio_track (int input_channels, int output_channels, TrackMode mod
port = physoutputs[(channels_used+x)%nphysical_out];
} else if (Config->get_output_auto_connect() & AutoConnectMaster) {
if (_master_out && _master_out->n_inputs().n_audio() > 0) {
port = _master_out->input (x % _master_out->n_inputs().n_audio())->name();
port = _master_out->input()->nth (x % _master_out->input()->n_ports().n_audio())->name();
}
}
if (port.length() && track->connect_output (track->output (x), port, this)) {
if (port.length() && track->output()->connect (track->output()->nth(x), port, this)) {
break;
}
}
@ -1889,7 +1893,15 @@ Session::new_audio_route (int input_channels, int output_channels, uint32_t how_
try {
shared_ptr<Route> bus (new Route (*this, bus_name, Route::Flag(0), DataType::AUDIO));
if (bus->ensure_io (ChanCount(DataType::AUDIO, input_channels), ChanCount(DataType::AUDIO, output_channels), false, this)) {
if (bus->output()->ensure_io (ChanCount(DataType::AUDIO, input_channels), false, this)) {
error << string_compose (_("cannot configure %1 in/%2 out configuration for new audio track"),
input_channels, output_channels)
<< endmsg;
goto failure;
}
if (bus->output()->ensure_io (ChanCount(DataType::AUDIO, output_channels), false, this)) {
error << string_compose (_("cannot configure %1 in/%2 out configuration for new audio track"),
input_channels, output_channels)
<< endmsg;
@ -1920,11 +1932,11 @@ Session::new_audio_route (int input_channels, int output_channels, uint32_t how_
port = physoutputs[((n+x)%n_physical_outputs)];
} else if (Config->get_output_auto_connect() & AutoConnectMaster) {
if (_master_out) {
port = _master_out->input (x%_master_out->n_inputs().n_audio())->name();
port = _master_out->input()->nth (x%_master_out->input()->n_ports().n_audio())->name();
}
}
if (port.length() && bus->connect_output (bus->output (x), port, this)) {
if (port.length() && bus->output()->connect (bus->output()->nth(x), port, this)) {
break;
}
}
@ -2023,8 +2035,8 @@ Session::new_route_from_template (uint32_t how_many, const std::string& template
picks up the configuration of the route. During session
loading this normally happens in a different way.
*/
route->input_changed (IOChange (ConfigurationChanged|ConnectionsChanged), this);
route->output_changed (IOChange (ConfigurationChanged|ConnectionsChanged), this);
route->input()->changed (IOChange (ConfigurationChanged|ConnectionsChanged), this);
route->output()->changed (IOChange (ConfigurationChanged|ConnectionsChanged), this);
}
route->set_remote_control_id (control_id);
@ -2070,7 +2082,7 @@ Session::add_routes (RouteList& new_routes, bool save)
(*x)->solo_changed.connect (sigc::bind (mem_fun (*this, &Session::route_solo_changed), wpr));
(*x)->mute_changed.connect (mem_fun (*this, &Session::route_mute_changed));
(*x)->output_changed.connect (mem_fun (*this, &Session::set_worst_io_latencies_x));
(*x)->output()->changed.connect (mem_fun (*this, &Session::set_worst_io_latencies_x));
(*x)->processors_changed.connect (bind (mem_fun (*this, &Session::update_latency_compensation), false, false));
if ((*x)->is_master()) {
@ -2085,7 +2097,7 @@ Session::add_routes (RouteList& new_routes, bool save)
if (_control_out && IO::connecting_legal) {
for (RouteList::iterator x = new_routes.begin(); x != new_routes.end(); ++x) {
(*x)->listen_via (_control_out, "control");
(*x)->listen_via (_control_out->input(), "control");
}
}
@ -2145,7 +2157,7 @@ Session::remove_route (shared_ptr<Route> route)
/* cancel control outs for all routes */
for (RouteList::iterator r = rs->begin(); r != rs->end(); ++r) {
(*r)->drop_listen (_control_out);
(*r)->drop_listen (_control_out->input());
}
_control_out = shared_ptr<Route> ();
@ -2176,8 +2188,8 @@ Session::remove_route (shared_ptr<Route> route)
// We need to disconnect the routes inputs and outputs
route->disconnect_inputs (0);
route->disconnect_outputs (0);
route->input()->disconnect (0);
route->output()->disconnect (0);
update_latency_compensation (false, false);
set_dirty();
@ -2215,7 +2227,6 @@ Session::route_solo_changed (void* src, boost::weak_ptr<Route> wpr)
return;
}
bool is_track;
boost::shared_ptr<Route> route = wpr.lock ();
if (!route) {
@ -2224,86 +2235,39 @@ Session::route_solo_changed (void* src, boost::weak_ptr<Route> wpr)
return;
}
is_track = (boost::dynamic_pointer_cast<AudioTrack>(route) != 0);
shared_ptr<RouteList> r = routes.reader ();
int32_t delta;
if (route->soloed()) {
delta = 1;
} else {
delta = -1;
}
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
/* soloing a track mutes all other tracks, soloing a bus mutes all other busses */
if (is_track) {
/* don't mess with busses */
if (boost::dynamic_pointer_cast<Track>(*i) == 0) {
continue;
}
} else {
/* don't mess with tracks */
if (boost::dynamic_pointer_cast<Track>(*i) != 0) {
continue;
}
}
if ((*i) != route &&
((*i)->mix_group () == 0 ||
(*i)->mix_group () != route->mix_group () ||
!route->mix_group ()->is_active())) {
if ((*i)->soloed()) {
/* if its already soloed, and solo latching is enabled,
then leave it as it is.
*/
if (Config->get_solo_latched()) {
continue;
}
}
if ((*i)->feeds (route->input())) {
/* do it */
solo_update_disabled = true;
(*i)->set_solo (false, src);
(*i)->main_outs()->mod_solo_level (delta);
solo_update_disabled = false;
}
}
bool something_soloed = false;
bool same_thing_soloed = false;
bool signal = false;
/* now figure out if anything is soloed */
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
bool something_soloed = false;
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
if ((*i)->soloed()) {
something_soloed = true;
if (boost::dynamic_pointer_cast<Track>(*i)) {
if (is_track) {
same_thing_soloed = true;
break;
}
} else {
if (!is_track) {
same_thing_soloed = true;
break;
}
}
break;
}
}
if (something_soloed != currently_soloing) {
signal = true;
currently_soloing = something_soloed;
}
modify_solo_mute (is_track, same_thing_soloed);
if (signal) {
SoloActive (currently_soloing); /* EMIT SIGNAL */
if (something_soloed != _non_soloed_outs_muted) {
_non_soloed_outs_muted = something_soloed;
SoloActive (_non_soloed_outs_muted); /* EMIT SIGNAL */
}
SoloChanged (); /* EMIT SIGNAL */
@ -2343,70 +2307,18 @@ Session::update_route_solo_state ()
/* nothing is soloed */
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
(*i)->set_solo_mute (false);
}
if (signal) {
SoloActive (false);
}
return;
}
modify_solo_mute (is_track, mute);
if (signal) {
SoloActive (currently_soloing);
}
}
void
Session::modify_solo_mute (bool is_track, bool mute)
{
shared_ptr<RouteList> r = routes.reader ();
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
if (is_track) {
/* only alter track solo mute */
if (boost::dynamic_pointer_cast<Track>(*i)) {
if ((*i)->soloed()) {
(*i)->set_solo_mute (!mute);
} else {
(*i)->set_solo_mute (mute);
}
}
} else {
/* only alter bus solo mute */
if (!boost::dynamic_pointer_cast<Track>(*i)) {
if ((*i)->soloed()) {
(*i)->set_solo_mute (false);
} else {
/* don't mute master or control outs
in response to another bus solo
*/
if ((*i) != _master_out &&
(*i) != _control_out) {
(*i)->set_solo_mute (mute);
}
}
}
}
}
}
void
Session::catch_up_on_solo ()
@ -2432,7 +2344,7 @@ Session::catch_up_on_solo_mute_override ()
shared_ptr<RouteList> r = routes.reader ();
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
(*i)->catch_up_on_solo_mute_override ();
// (*i)->catch_up_on_solo_mute_override ();
}
}

View File

@ -127,7 +127,7 @@ Session::click (nframes_t start, nframes_t nframes)
i = next;
}
_click_io->deliver_output (bufs, start, end, nframes);
_click_io->copy_to_outputs (bufs, DataType::AUDIO, nframes, 0);
}
void

View File

@ -151,7 +151,7 @@ Session::first_stage_init (string fullpath, string snapshot_name)
_tempo_map->StateChanged.connect (mem_fun (*this, &Session::tempo_map_changed));
_non_soloed_outs_muted = false;
g_atomic_int_set (&processing_prohibited, 0);
insert_cnt = 0;
_transport_speed = 0;
@ -272,8 +272,7 @@ Session::first_stage_init (string fullpath, string snapshot_name)
/* stop IO objects from doing stuff until we're ready for them */
IO::disable_panners ();
IO::disable_ports ();
Delivery::disable_panners ();
IO::disable_connecting ();
}
@ -1155,7 +1154,6 @@ Session::set_state (const XMLNode& node)
}
IO::disable_ports ();
IO::disable_connecting ();
/* Object loading order:
@ -3215,7 +3213,7 @@ Session::config_changed (std::string p, bool ours)
// deliver_midi (_mmc_port, buf, 2);
}
} else if (p == "solo-mute-override") {
catch_up_on_solo_mute_override ();
// catch_up_on_solo_mute_override ();
}
set_dirty ();

View File

@ -1335,11 +1335,12 @@ Session::update_latency_compensation (bool with_stop, bool abort)
(!(post_transport_work & PostTransportLocate) || pending_locate_flush));
}
nframes_t old_latency = (*i)->signal_latency ();
nframes_t old_latency = (*i)->output()->signal_latency ();
nframes_t track_latency = (*i)->update_total_latency ();
if (old_latency != track_latency) {
(*i)->update_port_total_latencies ();
(*i)->input()->update_port_total_latencies ();
(*i)->output()->update_port_total_latencies ();
update_jack = true;
}

View File

@ -26,7 +26,7 @@
#include "ardour/audiosource.h"
#include "ardour/diskstream.h"
#include "ardour/io_processor.h"
#include "ardour/panner.h"
#include "ardour/meter.h"
#include "ardour/port.h"
#include "ardour/processor.h"
#include "ardour/route_group_specialized.h"
@ -84,7 +84,7 @@ Track::get_template ()
void
Track::toggle_monitor_input ()
{
for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
for (PortSet::iterator i = _input->ports().begin(); i != _input->ports().end(); ++i) {
i->ensure_monitor_input(!i->monitoring_input());
}
}
@ -92,32 +92,28 @@ Track::toggle_monitor_input ()
ARDOUR::nframes_t
Track::update_total_latency ()
{
nframes_t old = _own_latency;
if (_user_latency) {
_own_latency = _user_latency;
} else {
_own_latency = 0;
for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
if ((*i)->active ()) {
_own_latency += (*i)->signal_latency ();
}
nframes_t old = _output->effective_latency();
nframes_t own_latency = _output->user_latency();
for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
if ((*i)->active ()) {
own_latency += (*i)->signal_latency ();
}
}
#undef DEBUG_LATENCY
#ifdef DEBUG_LATENCY
cerr << _name << ": internal redirect (final) latency = " << _own_latency << endl;
cerr << _name << ": internal redirect (final) latency = " << own_latency << endl;
#endif
set_port_latency (_own_latency);
if (old != _own_latency) {
_output->set_port_latency (own_latency);
if (old != own_latency) {
_output->set_latency_delay (own_latency);
signal_latency_changed (); /* EMIT SIGNAL */
}
return _own_latency;
return _output->effective_latency();
}
Track::FreezeRecord::~FreezeRecord ()
@ -155,14 +151,14 @@ Track::RecEnableControllable::get_value (void) const
bool
Track::record_enabled () const
{
return _diskstream->record_enabled ();
return _diskstream && _diskstream->record_enabled ();
}
bool
Track::can_record()
{
bool will_record = true;
for (PortSet::iterator i = _inputs.begin(); i != _inputs.end() && will_record; ++i) {
for (PortSet::iterator i = _input->ports().begin(); i != _input->ports().end() && will_record; ++i) {
if (!i->connected())
will_record = false;
}
@ -307,7 +303,7 @@ Track::no_roll (nframes_t nframes, sframes_t start_frame, sframes_t end_frame,
passthru_silence (start_frame, end_frame, nframes, 0);
} else {
if (_meter_point == MeterInput) {
just_meter_input (start_frame, end_frame, nframes);
_input->process_input (_meter, start_frame, end_frame, nframes);
}
passthru_silence (start_frame, end_frame, nframes, 0);
}

View File

@ -135,7 +135,7 @@ def build(bld):
gdither.cc
globals.cc
import.cc
io.cc
io.cc
io_processor.cc
jack_slave.cc
ladspa_plugin.cc
@ -157,6 +157,7 @@ def build(bld):
midi_track.cc
mix.cc
mtc_slave.cc
mute_master.cc
named_selection.cc
onset_detector.cc
panner.cc
@ -178,7 +179,7 @@ def build(bld):
resampled_source.cc
return.cc
reverse.cc
route.cc
route.cc
route_group.cc
send.cc
session.cc

View File

@ -23,9 +23,6 @@
#include <gtkmm/drawingarea.h>
#include <gtkmm2ext/binding_proxy.h>
namespace ARDOUR {
class Controllable;
}
namespace Gtkmm2ext {

View File

@ -158,7 +158,7 @@ MIDI::byte
MIDI::decode_controller_name (const char *name)
{
char *lparen;
const char *lparen;
size_t len;
if ((lparen = strrchr (name, '(')) != 0) {

View File

@ -18,11 +18,12 @@
*/
#include <ardour/session.h>
#include <ardour/route.h>
#include <ardour/audio_track.h>
#include <ardour/meter.h>
#include <control_protocol/control_protocol.h>
#include "ardour/session.h"
#include "ardour/route.h"
#include "ardour/audio_track.h"
#include "ardour/meter.h"
#include "ardour/amp.h"
#include "control_protocol/control_protocol.h"
using namespace ARDOUR;
using namespace std;
@ -212,7 +213,7 @@ ControlProtocol::route_get_gain (uint32_t table_index)
return 0.0f;
}
return r->gain ();
return r->amp()->gain ();
}
void
@ -242,7 +243,7 @@ ControlProtocol::route_get_effective_gain (uint32_t table_index)
return 0.0f;
}
return r->effective_gain ();
return r->amp()->gain_control()->get_value();
}

View File

@ -95,7 +95,7 @@ def set_options(opt):
help='Compile with support for LV2 (if slv2 is available)')
opt.add_option('--nls', action='store_true', default=True, dest='nls',
help='Enable i18n (native language support)')
opt.add_option('--surfaces', action='store_true', default=True, dest='surfaces',
opt.add_option('--surfaces', action='store_true', default=False, dest='surfaces',
help='Build support for control surfaces')
opt.add_option('--syslibs', action='store_true', default=True, dest='syslibs',
help='Use existing system versions of various libraries instead of internal ones')