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:
parent
9bd274bfde
commit
e6eb059576
|
@ -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) {
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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; }
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 ();
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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*);
|
||||
|
|
|
@ -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 ()
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 ¶m,
|
||||
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;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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 ();
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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 ¶m,
|
||||
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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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__ */
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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&);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 ();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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]);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 ();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
2012
libs/ardour/io.cc
2012
libs/ardour/io.cc
File diff suppressed because it is too large
Load Diff
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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")));
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
1027
libs/ardour/route.cc
1027
libs/ardour/route.cc
File diff suppressed because it is too large
Load Diff
|
@ -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)
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 ();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -23,9 +23,6 @@
|
|||
#include <gtkmm/drawingarea.h>
|
||||
#include <gtkmm2ext/binding_proxy.h>
|
||||
|
||||
namespace ARDOUR {
|
||||
class Controllable;
|
||||
}
|
||||
|
||||
namespace Gtkmm2ext {
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
|
2
wscript
2
wscript
|
@ -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')
|
||||
|
|
Loading…
Reference in New Issue