tempo_label.set_no_show_all();
meter_label.set_name ("EditorTimeButton");
meter_label.set_size_request (-1, (int)timebar_height);
- meter_label.set_alignment (1.0, 0.5);
+ meter_label.set_alignment (0.0, 0.5);
meter_label.set_padding (5,0);
meter_label.hide();
meter_label.set_no_show_all();
ruler_label_event_box.add (ruler_label_vbox);
ruler_label_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
- ruler_label_event_box.set_name ("TimebarLabelBase");
ruler_label_event_box.signal_button_release_event().connect (mem_fun(*this, &Editor::ruler_label_button_release));
time_button_event_box.add (time_button_vbox);
- time_button_event_box.set_name ("TimebarLabelBase");
time_button_event_box.set_events (Gdk::BUTTON_PRESS_MASK|Gdk::BUTTON_RELEASE_MASK);
time_button_event_box.signal_button_release_event().connect (mem_fun(*this, &Editor::ruler_label_button_release));
edit_packer.set_border_width (0);
edit_packer.set_name ("EditorWindow");
- /* summary */
- edit_packer.attach (*_summary, 0, 2, 0, 1, FILL|EXPAND, SHRINK, 0, 0);
+ edit_packer.attach (ruler_label_event_box, 1, 2, 0, 1, FILL, SHRINK, 0, 0);
+ edit_packer.attach (time_button_event_box, 1, 2, 1, 2, FILL, SHRINK, 0, 0);
- /* labels for rulers (mins:secs, timecode, samples, bars:beats) */
- edit_packer.attach (ruler_label_event_box, 0, 1, 1, 2, FILL, SHRINK, 0, 0);
+ edit_packer.attach (time_canvas_event_box, 2, 3, 0, 1, FILL|EXPAND, FILL, 0, 0);
- /* labels for time lines (meter, tempo, markers) */
- edit_packer.attach (time_button_event_box, 0, 1, 2, 3, FILL, SHRINK, 0, 0);
+ edit_packer.attach (controls_layout, 1, 2, 2, 3, FILL, FILL|EXPAND, 0, 0);
+ edit_packer.attach (track_canvas_event_box, 2, 3, 1, 3, FILL|EXPAND, FILL|EXPAND, 0, 0);
- /* rulers */
- edit_packer.attach (time_canvas_event_box, 1, 2, 1, 2, FILL|EXPAND, FILL, 0, 0);
-
- /* LHS controls for tracks */
- edit_packer.attach (controls_layout, 0, 1, 3, 4, FILL, FILL|EXPAND, 0, 0);
-
- /* main canvas (which has the time line canvas items at the top of it) */
- edit_packer.attach (track_canvas_event_box, 1, 2, 2, 4, FILL|EXPAND, FILL|EXPAND, 0, 0);
-
- /* zoom controls */
- edit_packer.attach (zoom_box, 0, 1, 4, 5, FILL, FILL, 0, 0);
-
- /* h scroller */
- edit_packer.attach (edit_hscrollbar, 1, 2, 4, 5, FILL|EXPAND, FILL, 0, 0);
-
- /* v scroller */
- edit_packer.attach (edit_vscrollbar, 3, 4, 3, 4, FILL, FILL|EXPAND, 0, 0);
+ edit_packer.attach (*_summary, 0, 3, 3, 4, FILL|EXPAND, SHRINK, 0, 0);
bottom_hbox.set_border_width (2);
bottom_hbox.set_spacing (3);
zoom_focus_selector.signal_changed().connect (mem_fun(*this, &Editor::zoom_focus_selection_done));
ARDOUR_UI::instance()->tooltips().set_tip (zoom_focus_selector, _("Zoom focus"));
- zoom_box.pack_start (zoom_focus_selector, true, true);
zoom_box.pack_start (zoom_out_button, false, false);
zoom_box.pack_start (zoom_in_button, false, false);
zoom_box.pack_start (zoom_out_full_button, false, false);
+ HBox* zbc = manage (new HBox);
+ zbc->pack_start (zoom_focus_selector, false, false);
+ zoom_vbox.pack_start (*zbc, false, false);
+ zoom_vbox.pack_start (zoom_box, false, false);
+
snap_box.set_spacing (1);
snap_box.set_border_width (2);
Glib::RefPtr<Gtk::RadioAction> zoom_focus_action (Editing::ZoomFocus);
Gtk::HBox zoom_box;
+ Gtk::VBox zoom_vbox;
void zoom_adjustment_changed();
mem_fun (*_rc_config, &RCConfiguration::set_solo_model)
);
- sm->add (InverseMute, _("in place"));
+ sm->add (SoloInPlace, _("in place"));
sm->add (SoloBus, _("via bus"));
add_option (_("Audio"), sm);
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 set_solo_level (int32_t sl) { _solo_level = sl; }
+ void set_solo_isolated (bool yn) { _solo_isolated = yn; }
void cycle_start (nframes_t);
void increment_output_offset (nframes_t);
CONFIG_VARIABLE (bool, mute_affects_control_outs, "mute-affects-control-outs", true)
CONFIG_VARIABLE (bool, mute_affects_main_outs, "mute-affects-main-outs", true)
CONFIG_VARIABLE (MonitorModel, monitoring_model, "monitoring-model", ExternalMonitoring)
-CONFIG_VARIABLE (SoloModel, solo_model, "solo-model", InverseMute)
+CONFIG_VARIABLE (SoloModel, solo_model, "solo-model", SoloInPlace)
CONFIG_VARIABLE (bool, solo_latched, "solo-latched", true)
CONFIG_VARIABLE (bool, latched_record_enable, "latched-record-enable", false)
CONFIG_VARIABLE (bool, all_safe, "all-safe", false)
void set_mute (bool yn, void* src);
bool muted () const;
+ /* controls use set_solo() to modify this route's solo state
+ */
+
void set_solo (bool yn, void *src);
- bool soloed() const;
+ bool soloed () const { return (bool) _solo_level; }
void set_solo_isolated (bool yn, void *src);
bool solo_isolated() const;
void catch_up_on_solo_mute_override ();
void mod_solo_level (int32_t);
+ uint32_t solo_level () const { return _solo_level; }
void set_block_size (nframes_t nframes);
bool has_external_redirects() const;
void curve_reallocate ();
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
+ boost::shared_ptr<Delivery> _control_outs;
boost::shared_ptr<InternalReturn> _intreturn;
Flag _flags;
int _pending_declick;
MeterPoint _meter_point;
uint32_t _phase_invert;
+ uint32_t _solo_level;
+ bool _solo_isolated;
+
bool _denormal_protection;
bool _recordable : 1;
};
enum SoloModel {
- InverseMute,
+ SoloInPlace,
SoloBus
};
, _solo_level (0)
, _solo_isolated (false)
, _mute_master (mm)
+
{
_output_offset = 0;
_current_gain = 1.0;
if ((prop = node.property ("role")) != 0) {
_role = Role (string_2_enum (prop->value(), _role));
- }
-
- 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 ("solo-isolated")) != 0) {
- set_solo_isolated (prop->value() == "yes");
+ // std::cerr << this << ' ' << _name << " set role to " << enum_2_string (_role) << std::endl;
+ } else {
+ // std::cerr << this << ' ' << _name << " NO ROLE INFO\n";
}
XMLNode* pan_node = node.child (X_("Panner"));
break;
}
+
if (_solo_level) {
desired_gain = 1.0;
} else {
- if (_solo_isolated) {
+ if (_solo_isolated) {
+
+ /* ... but we are isolated from all that nonsense */
+
desired_gain = _mute_master->mute_gain_at (mp);
} else if (_session.soloing()) {
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)
{
REGISTER_ENUM (AddHigher);
REGISTER (_LayerModel);
- REGISTER_ENUM (InverseMute);
+ REGISTER_ENUM (SoloInPlace);
REGISTER_ENUM (SoloBus);
REGISTER (_SoloModel);
BufferSet& sendbufs = _session.get_mix_buffers (bufs.count());
sendbufs.read_from (bufs, nframes);
assert(sendbufs.count() == bufs.count());
-
+
/* gain control */
+ gain_t tgain = target_gain ();
+
+ if (tgain != _current_gain) {
+
+ /* target gain has changed */
+
+ Amp::apply_gain (sendbufs, nframes, _current_gain, tgain);
+ _current_gain = tgain;
+
+ } else if (tgain == 0.0) {
+
+ /* we were quiet last time, and we're still supposed to be quiet.
+ */
+
+ _meter->reset ();
+ Amp::apply_simple_gain (sendbufs, nframes, 0.0);
+
+ return;
+
+ } else if (tgain != 1.0) {
+
+ /* target gain has not changed, but is not unity */
+ Amp::apply_simple_gain (sendbufs, nframes, tgain);
+ }
+
// 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 (sendbufs, start_frame, end_frame, nframes);
/* consider metering */
{
const XMLProperty* prop;
+ Send::set_state (node);
+
if ((prop = node.property ("target")) != 0) {
_send_to_id = prop->value();
if (!IO::connecting_legal) {
connect_c = IO::ConnectingLegal.connect (mem_fun (*this, &InternalSend::connect_when_legal));
- std::cerr << "connect later!\n";
} else {
- std::cerr << "connect NOW!\n";
connect_when_legal ();
}
}
int
InternalSend::connect_when_legal ()
{
- std::cerr << "IOP/send connecting now that its legal\n";
-
connect_c.disconnect ();
if (_send_to_id == "0") {
if ((_send_to = _session.route_by_id (_send_to_id)) == 0) {
error << X_("cannot find route to connect to") << endmsg;
- std::cerr << "cannot find route with ID " << _send_to_id << std::endl;
- } else {
- std::cerr << "got target send as " << _send_to << std::endl;
- }
+ return -1;
+ }
if ((target = _send_to->get_return_buffer ()) == 0) {
error << X_("target for internal send has no return buffer") << endmsg;
+ return -1;
}
return 0;
if (with_output) {
_output.reset (new IO(s, io_name.empty() ? proc_name : io_name, IO::Output, dtype));
}
-
- cerr << "fresh create IOP name = " << proc_name << " in = " << _input << " out = " << _output << endl;
}
/* create an IOProcessor that proxies to an existing IO object */
, _input (in)
, _output (out)
{
- cerr << "XML create IOP name = " << proc_name << " in = " << in << " out = " << out << endl;
if (in) {
_own_input = false;
} else {
_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 */
XMLNodeList nlist = node.children();
// may not exist for legacy 3.0 sessions
if ((prop = node.property ("id")) != 0) {
_id = prop->value();
- cerr << "---------------- ID for processor " << name() << " = " << _id << endl;
- } else {
- cerr << "---------------- NO ID for processor " << name() << endl;
- }
+ }
XMLNodeList nlist = node.children();
XMLNodeIterator niter;
#include "ardour/buffer_set.h"
#include "ardour/configuration.h"
#include "ardour/cycle_timer.h"
+#include "ardour/delivery.h"
#include "ardour/dB.h"
#include "ardour/internal_send.h"
#include "ardour/internal_return.h"
void
Route::init ()
{
+ _solo_level = 0;
+ _solo_isolated = false;
_active = true;
processor_max_streams.reset();
_solo_safe = false;
void
Route::set_solo (bool yn, void *src)
{
- if (_solo_safe) {
+ if (_solo_safe || _solo_isolated) {
return;
}
return;
}
- if (_main_outs->soloed() != yn) {
- _main_outs->mod_solo_level (yn ? 1 : -1);
+ if (soloed() != yn) {
+ mod_solo_level (yn ? 1 : -1);
solo_changed (src); /* EMIT SIGNAL */
_solo_control->Changed (); /* EMIT SIGNAL */
}
}
-bool
-Route::soloed() const
+void
+Route::mod_solo_level (int32_t delta)
{
- return _main_outs->soloed ();
+ if (delta < 0) {
+ if (_solo_level >= (uint32_t) delta) {
+ _solo_level += delta;
+ } else {
+ _solo_level = 0;
+ }
+ } else {
+ _solo_level += delta;
+ }
+
+ /* tell "special" delivery units what the solo situation is
+ */
+
+ switch (Config->get_solo_model()) {
+ case SoloInPlace:
+ /* main outs are used for soloing */
+ _main_outs->set_solo_level (_solo_level);
+ _main_outs->set_solo_isolated (_solo_isolated);
+ if (_control_outs) {
+ /* control outs just keep on playing */
+ _control_outs->set_solo_level (0);
+ _control_outs->set_solo_isolated (true);
+ }
+ break;
+
+ case SoloBus:
+ /* control outs are used for soloing */
+ if (_control_outs) {
+ _control_outs->set_solo_level (_solo_level);
+ _control_outs->set_solo_isolated (_solo_isolated);
+ }
+ /* main outs just keep on playing */
+ _main_outs->set_solo_level (0);
+ _main_outs->set_solo_isolated (true);
+ break;
+ }
}
void
return;
}
- _main_outs->set_solo_isolated (yn);
- solo_isolated_changed (src);
+ if (yn != _solo_isolated) {
+ _solo_isolated = yn;
+
+ /* tell "special" delivery units what the solo situation is
+ */
+
+ switch (Config->get_solo_model()) {
+ case SoloInPlace:
+ _main_outs->set_solo_level (_solo_level);
+ _main_outs->set_solo_isolated (_solo_isolated);
+ if (_control_outs) {
+ _main_outs->set_solo_level (1);
+ _main_outs->set_solo_isolated (false);
+ }
+ break;
+ case SoloBus:
+ if (_control_outs) {
+ _control_outs->set_solo_level (_solo_level);
+ _control_outs->set_solo_isolated (_solo_isolated);
+ }
+ _main_outs->set_solo_level (1);
+ _main_outs->set_solo_isolated (false);
+ break;
+ }
+
+ solo_isolated_changed (src);
+ }
}
bool
Route::solo_isolated () const
{
- return _main_outs->solo_isolated();
+ return _solo_isolated;
}
void
return _mute_master->muted ();
}
+#if 0
static void
dump_processors(const string& name, const list<boost::shared_ptr<Processor> >& procs)
{
}
cerr << "}" << endl;
}
+#endif
int
Route::add_processor (boost::shared_ptr<Processor> processor, Placement placement, ProcessorStreams* err)
ProcessorList::iterator p;
p = _processors.end();
--p;
- cerr << "Let's check " << (*p)->name() << " vis ? " << (*p)->visible() << endl;
while (!(*p)->visible() && p != _processors.begin()) {
--p;
}
loc = iter;
}
- cerr << "Adding " << processor->name() << " @ " << processor << endl;
-
_processors.insert (loc, processor);
// Set up processor list channels. This will set processor->[input|output]_streams(),
try {
if ((prop = node.property ("type")) != 0) {
-
- cerr << _name << " : got processor type " << prop->value() << endl;
-
boost::shared_ptr<Processor> processor;
if (prop->value() == "ladspa" || prop->value() == "Ladspa" ||
} else if (prop->value() == "intsend") {
processor.reset (new InternalSend (_session, _mute_master, node));
-
+
} else if (prop->value() == "intreturn") {
if (_intreturn) {
ProcessorList::iterator p;
p = _processors.end();
--p;
- cerr << "Let's check " << (*p)->name() << " vis ? " << (*p)->visible() << endl;
while (!(*p)->visible() && p != _processors.begin()) {
--p;
}
list< pair<ChanCount,ChanCount> > configuration;
uint32_t index = 0;
- cerr << "Processor check with " << _processors.size() << endl;
-
for (ProcessorList::iterator p = _processors.begin(); p != _processors.end(); ++p, ++index) {
- cerr << "Checking out " << (*p)->name() << " type = " << endl;
if ((*p)->can_support_io_configuration(in, out)) {
configuration.push_back(make_pair(in, out));
in = out;
set_processor_state (processor_state);
+ if ((prop = node.property ("solo_level")) != 0) {
+ _solo_level = 0; // needed for mod_solo_level() to work
+ mod_solo_level (atoi (prop->value()));
+ }
+
+ if ((prop = node.property ("solo-isolated")) != 0) {
+ set_solo_isolated (prop->value() == "yes", this);
+ }
+
if ((prop = node.property (X_("phase-invert"))) != 0) {
set_phase_invert (prop->value()=="yes"?true:false);
}
XMLNodeConstIterator niter;
ProcessorList::iterator i, o;
- dump_processors ("set processor states", _processors);
-
// Iterate through existing processors, remove those which are not in the state list
for (i = _processors.begin(); i != _processors.end(); ) {
{
Glib::RWLock::ReaderLock rm (_processor_lock);
- for (ProcessorList::const_iterator x = _processors.begin(); x != _processors.end(); ++x) {
- boost::shared_ptr<const InternalSend> d = boost::dynamic_pointer_cast<const InternalSend>(*x);
+ for (ProcessorList::iterator x = _processors.begin(); x != _processors.end(); ++x) {
+ boost::shared_ptr<InternalSend> d = boost::dynamic_pointer_cast<InternalSend>(*x);
if (d && d->target_route() == route) {
+
+ /* if the target is the control outs, then make sure
+ we take note of which i-send is doing that.
+ */
+
+ if (route == _session.control_out()) {
+ _control_outs = boost::dynamic_pointer_cast<Delivery>(d);
+ }
+
/* already listening via the specified IO: do nothing */
+
return 0;
}
}
}
rl.release ();
+
+ if (route == _session.control_out()) {
+ _control_outs.reset ();
+ }
}
void
XMLNode&
Send::state(bool full)
{
- XMLNode& node = IOProcessor::state(full);
+ XMLNode& node = Delivery::state(full);
char buf[32];
node.add_property ("type", "send");
_state_of_the_state = StateOfTheState (_state_of_the_state & ~InitialConnecting);
-
/* now handle the whole enchilada as if it was one
graph reorder event.
*/
if ((*i)->feeds (route)) {
/* do it */
-
- (*i)->main_outs()->mod_solo_level (delta);
+ (*i)->mod_solo_level (delta);
}
}
/* make sure master is never muted by solo */
- if (_master_out->main_outs()->solo_level() == 0) {
- _master_out->main_outs()->mod_solo_level (1);
+ if (_master_out->solo_level() == 0) {
+ _master_out->mod_solo_level (1);
+ }
+
+ /* ditto for control outs make sure master is never muted by solo */
+
+ if (_control_out && _control_out->solo_level() == 0) {
+ _control_out->mod_solo_level (1);
}
solo_update_disabled = false;
}
for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
- if (!(*i)->is_master() && !(*i)->is_hidden() && (*i)->soloed()) {
+ if (!(*i)->is_master() && !(*i)->is_control() && !(*i)->is_hidden() && (*i)->soloed()) {
something_soloed = true;
break;
}
void
Session::catch_up_on_solo_mute_override ()
{
- if (Config->get_solo_model() != InverseMute) {
+ if (Config->get_solo_model() != SoloInPlace) {
return;
}