diff options
Diffstat (limited to 'libs')
-rw-r--r-- | libs/ardour/ardour/chan_count.h | 8 | ||||
-rw-r--r-- | libs/ardour/ardour/io.h | 3 | ||||
-rw-r--r-- | libs/ardour/ardour/port_insert.h | 3 | ||||
-rw-r--r-- | libs/ardour/ardour/return.h | 71 | ||||
-rw-r--r-- | libs/ardour/ardour/send.h | 9 | ||||
-rw-r--r-- | libs/ardour/ardour/session.h | 5 | ||||
-rw-r--r-- | libs/ardour/io.cc | 34 | ||||
-rw-r--r-- | libs/ardour/port_insert.cc | 31 | ||||
-rw-r--r-- | libs/ardour/return.cc | 164 | ||||
-rw-r--r-- | libs/ardour/send.cc | 65 | ||||
-rw-r--r-- | libs/ardour/session.cc | 43 | ||||
-rw-r--r-- | libs/ardour/wscript | 1 |
12 files changed, 334 insertions, 103 deletions
diff --git a/libs/ardour/ardour/chan_count.h b/libs/ardour/ardour/chan_count.h index c9b543c4ba..ccae3920f6 100644 --- a/libs/ardour/ardour/chan_count.h +++ b/libs/ardour/ardour/chan_count.h @@ -106,6 +106,14 @@ public: return ( (*this > other) || (*this == other) ); } + ChanCount operator+(const ChanCount& other) const { + ChanCount ret; + for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) { + ret.set(*t, get(*t) + other.get(*t)); + } + return ret; + } + static ChanCount min(const ChanCount& a, const ChanCount& b) { ChanCount ret; for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) { diff --git a/libs/ardour/ardour/io.h b/libs/ardour/ardour/io.h index 3e36d10be3..fbaf379a30 100644 --- a/libs/ardour/ardour/io.h +++ b/libs/ardour/ardour/io.h @@ -102,7 +102,7 @@ class IO : public SessionObject, public AutomatableControls, public Latent virtual void silence (nframes_t); - void collect_input (BufferSet& bufs, nframes_t nframes); + void collect_input (BufferSet& bufs, nframes_t nframes, ChanCount offset=ChanCount::ZERO); void deliver_output (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes); void just_meter_input (nframes_t start_frame, nframes_t end_frame, nframes_t nframes); @@ -214,7 +214,6 @@ class IO : public SessionObject, public AutomatableControls, public Latent static sigc::signal<int> ConnectingLegal; /// raised when the number of input or output ports changes static sigc::signal<void,ChanCount> PortCountChanged; - static sigc::signal<int> PortsCreated; static sigc::signal<void,nframes_t> CycleStart; static void update_meters(); diff --git a/libs/ardour/ardour/port_insert.h b/libs/ardour/ardour/port_insert.h index 076e4af9d1..ce21d9f223 100644 --- a/libs/ardour/ardour/port_insert.h +++ b/libs/ardour/ardour/port_insert.h @@ -54,9 +54,6 @@ class PortInsert : public IOProcessor nframes_t signal_latency() const; - ChanCount output_streams() const; - ChanCount input_streams() const; - bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const; bool configure_io (ChanCount in, ChanCount out); diff --git a/libs/ardour/ardour/return.h b/libs/ardour/ardour/return.h new file mode 100644 index 0000000000..af55df59ed --- /dev/null +++ b/libs/ardour/ardour/return.h @@ -0,0 +1,71 @@ +/* + Copyright (C) 2009 Paul Davis + Author: Dave Robillard + + 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_return_h__ +#define __ardour_return_h__ + +#include <sigc++/signal.h> +#include <string> + + +#include "pbd/stateful.h" +#include "ardour/ardour.h" +#include "ardour/audioengine.h" +#include "ardour/io_processor.h" + +namespace ARDOUR { + +class Return : public IOProcessor +{ +public: + Return (Session&); + Return (Session&, const XMLNode&); + virtual ~Return (); + + uint32_t bit_slot() const { return _bitslot; } + + void run_in_place (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes); + + void activate() {} + void deactivate () {} + + XMLNode& state(bool full); + XMLNode& get_state(void); + int set_state(const XMLNode& node); + + uint32_t pans_required() const { return _configured_input.n_audio(); } + + 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 void make_unique (XMLNode &, Session &); + +private: + /* disallow copy construction */ + Return (const Return&); + + uint32_t _bitslot; +}; + +} // namespace ARDOUR + +#endif /* __ardour_return_h__ */ + diff --git a/libs/ardour/ardour/send.h b/libs/ardour/ardour/send.h index 77bb6d9017..825506f0e2 100644 --- a/libs/ardour/ardour/send.h +++ b/libs/ardour/ardour/send.h @@ -38,10 +38,7 @@ class Send : public IOProcessor Send (Session&, const XMLNode&); virtual ~Send (); - uint32_t bit_slot() const { return bitslot; } - - ChanCount output_streams() const; - ChanCount input_streams () const; + uint32_t bit_slot() const { return _bitslot; } void run_in_place (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes); @@ -55,7 +52,6 @@ class Send : public IOProcessor int set_state(const XMLNode& node); uint32_t pans_required() const { return _configured_input.n_audio(); } - void expect_inputs (const ChanCount&); bool can_support_io_configuration (const ChanCount& in, ChanCount& out) const; bool configure_io (ChanCount in, ChanCount out); @@ -68,8 +64,7 @@ class Send : public IOProcessor Send (const Send&); bool _metering; - ChanCount expected_inputs; - uint32_t bitslot; + uint32_t _bitslot; }; } // namespace ARDOUR diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h index 1e3855c308..86a2f778dc 100644 --- a/libs/ardour/ardour/session.h +++ b/libs/ardour/ardour/session.h @@ -101,6 +101,7 @@ class Port; class PortInsert; class Processor; class Region; +class Return; class Route; class RouteGroup; class SMFSource; @@ -764,8 +765,10 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable } uint32_t next_send_id(); + uint32_t next_return_id(); uint32_t next_insert_id(); void mark_send_id (uint32_t); + void mark_return_id (uint32_t); void mark_insert_id (uint32_t); /* s/w "RAID" management */ @@ -1566,7 +1569,9 @@ class Session : public PBD::StatefulDestructible, public boost::noncopyable list<PortInsert *> _port_inserts; list<PluginInsert *> _plugin_inserts; list<Send *> _sends; + list<Return *> _returns; boost::dynamic_bitset<uint32_t> send_bitset; + boost::dynamic_bitset<uint32_t> return_bitset; boost::dynamic_bitset<uint32_t> insert_bitset; uint32_t send_cnt; uint32_t insert_cnt; diff --git a/libs/ardour/io.cc b/libs/ardour/io.cc index 3e5b138fb7..c8e2c78cd2 100644 --- a/libs/ardour/io.cc +++ b/libs/ardour/io.cc @@ -74,7 +74,6 @@ sigc::signal<int> IO::ConnectingLegal; sigc::signal<int> IO::PortsLegal; sigc::signal<int> IO::PannersLegal; sigc::signal<void,ChanCount> IO::PortCountChanged; -sigc::signal<int> IO::PortsCreated; sigc::signal<void,nframes_t> IO::CycleStart; Glib::StaticMutex IO::m_meter_signal_lock = GLIBMM_STATIC_MUTEX_INIT; @@ -290,24 +289,31 @@ IO::copy_to_outputs (BufferSet& bufs, DataType type, nframes_t nframes) } void -IO::collect_input (BufferSet& outs, nframes_t nframes) +IO::collect_input (BufferSet& outs, nframes_t nframes, ChanCount offset) { assert(outs.available() >= n_inputs()); - if (n_inputs() == ChanCount::ZERO) + if (n_inputs() == ChanCount::ZERO) { return; + } outs.set_count(n_inputs()); - + for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) { - + PortSet::iterator i = _inputs.begin(*t); BufferSet::iterator o = outs.begin(*t); - PortSet::iterator e = _inputs.end (*t); - for (PortSet::iterator i = _inputs.begin(*t); i != e; ++i, ++o) { + + cerr << (*t).to_string() << endl; + for (uint32_t off = 0; off < offset.get(*t); ++off, ++o) { + if (o == outs.end(*t)) { + continue; + } + } + + for ( ; i != _inputs.end(*t); ++i, ++o) { Buffer& b (i->get_buffer (nframes)); o->read_from (b, nframes); } - } } @@ -795,7 +801,8 @@ IO::ensure_inputs_locked (ChanCount count, bool clear, void* src) { Port* input_port = 0; bool changed = false; - + + _configured_inputs = count; for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) { @@ -867,14 +874,14 @@ IO::ensure_io (ChanCount in, ChanCount out, bool clear, void* src) in = ChanCount::min (_input_maximum, in); out = ChanCount::min (_output_maximum, out); + + _configured_inputs = in; + _configured_outputs = out; if (in == n_inputs() && out == n_outputs() && !clear) { return 0; } - _configured_inputs = in; - _configured_outputs = out; - { BLOCK_PROCESS_CALLBACK (); Glib::Mutex::Lock lm (io_lock); @@ -1034,6 +1041,8 @@ IO::ensure_outputs_locked (ChanCount count, bool clear, void* src) Port* output_port = 0; bool changed = false; bool need_pan_reset = false; + + _configured_outputs = count; if (n_outputs() != count) { need_pan_reset = true; @@ -1708,7 +1717,6 @@ IO::create_ports (const XMLNode& node) set_deferred_state (); - PortsCreated(); return 0; } diff --git a/libs/ardour/port_insert.cc b/libs/ardour/port_insert.cc index 606b055dab..73a70861ea 100644 --- a/libs/ardour/port_insert.cc +++ b/libs/ardour/port_insert.cc @@ -162,23 +162,7 @@ PortInsert::signal_latency() const bool PortInsert::configure_io (ChanCount in, ChanCount out) { - /* do not allow configuration to be changed outside the range of - the last request config. or something like that. - */ - - /* this is a bit odd: - - the number of inputs we are required to handle corresponds - to the number of output ports we need. - - the number of outputs we are required to have corresponds - to the number of input ports we need. - */ - - /*_io->set_output_maximum (in); - _io->set_output_minimum (in); - _io->set_input_maximum (out); - _io->set_input_minimum (out);*/ + /* for an insert, processor input corresponds to IO output, and vice versa */ if (_io->ensure_io (out, in, false, this) != 0) { return false; @@ -187,21 +171,10 @@ PortInsert::configure_io (ChanCount in, ChanCount out) return Processor::configure_io (in, out); } -ChanCount -PortInsert::output_streams() const -{ - return _io->n_inputs (); -} - -ChanCount -PortInsert::input_streams() const -{ - return _io->n_outputs (); -} - bool PortInsert::can_support_io_configuration (const ChanCount& in, ChanCount& out) const { out = in; return true; } + diff --git a/libs/ardour/return.cc b/libs/ardour/return.cc new file mode 100644 index 0000000000..fdc2b259e1 --- /dev/null +++ b/libs/ardour/return.cc @@ -0,0 +1,164 @@ +/* + Copyright (C) 2000 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 <algorithm> + +#include "pbd/xml++.h" + +#include "ardour/return.h" +#include "ardour/session.h" +#include "ardour/port.h" +#include "ardour/audio_port.h" +#include "ardour/buffer_set.h" +#include "ardour/meter.h" +#include "ardour/panner.h" +#include "ardour/io.h" + +#include "i18n.h" + +using namespace ARDOUR; +using namespace PBD; + +Return::Return (Session& s) + : IOProcessor (s, string_compose (_("return %1"), (_bitslot = s.next_return_id()) + 1)) +{ + ProcessorCreated (this); /* EMIT SIGNAL */ +} + +Return::Return (Session& s, const XMLNode& node) + : IOProcessor (s, "return") +{ + if (set_state (node)) { + throw failed_constructor(); + } + + ProcessorCreated (this); /* EMIT SIGNAL */ +} + +Return::~Return () +{ + GoingAway (); +} + +XMLNode& +Return::get_state(void) +{ + return state (true); +} + +XMLNode& +Return::state(bool full) +{ + XMLNode& node = IOProcessor::state(full); + char buf[32]; + node.add_property ("type", "return"); + snprintf (buf, sizeof (buf), "%" PRIu32, _bitslot); + node.add_property ("bitslot", buf); + + return node; +} + +int +Return::set_state(const XMLNode& node) +{ + XMLNodeList nlist = node.children(); + XMLNodeIterator niter; + const XMLProperty* prop; + + if ((prop = node.property ("bitslot")) == 0) { + _bitslot = _session.next_return_id(); + } else { + sscanf (prop->value().c_str(), "%" PRIu32, &_bitslot); + _session.mark_return_id (_bitslot); + } + + const XMLNode* insert_node = &node; + + /* Return has regular IO automation (gain, pan) */ + + for (niter = nlist.begin(); niter != nlist.end(); ++niter) { + if ((*niter)->name() == "IOProcessor") { + insert_node = *niter; + } else if ((*niter)->name() == X_("Automation")) { + // _io->set_automation_state (*(*niter), Evoral::Parameter(GainAutomation)); + } + } + + IOProcessor::set_state (*insert_node); + + return 0; +} + +void +Return::run_in_place (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes) +{ + if (active()) { + _io->collect_input (bufs, nframes, _configured_input); + bufs.set_count(_configured_output); + } +} + +bool +Return::can_support_io_configuration (const ChanCount& in, ChanCount& out) const +{ + out = in + _io->n_inputs(); + return true; +} + +bool +Return::configure_io (ChanCount in, ChanCount out) +{ + if (out != in + _io->n_inputs()) { + return false; + } + + // Ensure there are enough buffers (since we add some) + if (_session.get_scratch_buffers(in).count() < out) { + Glib::Mutex::Lock em (_session.engine().process_lock()); + IO::PortCountChanged(out); + } + + Processor::configure_io(in, out); + + return true; +} + +/** Set up the XML description of a return so that its name is unique. + * @param state XML return state. + * @param session Session. + */ +void +Return::make_unique (XMLNode &state, Session &session) +{ + uint32_t const bitslot = session.next_return_id() + 1; + + char buf[32]; + snprintf (buf, sizeof (buf), "%" PRIu32, bitslot); + state.property("bitslot")->set_value (buf); + + std::string const name = string_compose (_("return %1"), bitslot); + + state.property("name")->set_value (name); + + XMLNode* io = state.child ("IO"); + if (io) { + io->property("name")->set_value (name); + } +} + diff --git a/libs/ardour/send.cc b/libs/ardour/send.cc index 9246db9458..2c28fb5dcd 100644 --- a/libs/ardour/send.cc +++ b/libs/ardour/send.cc @@ -36,7 +36,7 @@ using namespace ARDOUR; using namespace PBD; Send::Send (Session& s) - : IOProcessor (s, string_compose (_("send %1"), (bitslot = s.next_send_id()) + 1)) + : IOProcessor (s, string_compose (_("send %1"), (_bitslot = s.next_send_id()) + 1)) { _metering = false; ProcessorCreated (this); /* EMIT SIGNAL */ @@ -71,7 +71,7 @@ Send::state(bool full) XMLNode& node = IOProcessor::state(full); char buf[32]; node.add_property ("type", "send"); - snprintf (buf, sizeof (buf), "%" PRIu32, bitslot); + snprintf (buf, sizeof (buf), "%" PRIu32, _bitslot); node.add_property ("bitslot", buf); return node; @@ -85,10 +85,10 @@ Send::set_state(const XMLNode& node) const XMLProperty* prop; if ((prop = node.property ("bitslot")) == 0) { - bitslot = _session.next_send_id(); + _bitslot = _session.next_send_id(); } else { - sscanf (prop->value().c_str(), "%" PRIu32, &bitslot); - _session.mark_send_id (bitslot); + sscanf (prop->value().c_str(), "%" PRIu32, &_bitslot); + _session.mark_send_id (_bitslot); } const XMLNode* insert_node = &node; @@ -113,15 +113,7 @@ Send::run_in_place (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, { if (active()) { - // 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); + _io->deliver_output (bufs, start_frame, end_frame, nframes); if (_metering) { if (_io->effective_gain() == 0) { @@ -152,26 +144,27 @@ Send::set_metering (bool yn) } bool -Send::can_support_io_configuration (const ChanCount& in, ChanCount& out_is_ignored) const +Send::can_support_io_configuration (const ChanCount& in, ChanCount& out) const { - if (_io->input_maximum() == ChanCount::INFINITE && _io->output_maximum() == ChanCount::INFINITE) { + if (_io->input_maximum() == ChanCount::INFINITE + && _io->output_maximum() == ChanCount::INFINITE) { - /* not configured yet */ + /* not configured yet, we can support anything */ - return 1; /* we can support anything the first time we're asked */ + out = in; + return true; /* we can support anything the first time we're asked */ } else { - /* the "input" config for a port insert corresponds to how - many output ports it will have. - */ + /* for a send, processor input corresponds to IO output */ if (_io->output_maximum() == in) { - return 1; + out = in; + return true; } } - return -1; + return false; } bool @@ -198,32 +191,6 @@ Send::configure_io (ChanCount in, ChanCount out) return true; } -ChanCount -Send::output_streams() const -{ - // this method reflects the idea that from the perspective of the Route's ProcessorList, - // a send is just a passthrough. that doesn't match what the Send actually does with its - // data, but since what it does is invisible to the Route, it appears to be a passthrough. - - return _configured_input; -} - -ChanCount -Send::input_streams() const -{ - return _configured_input; -} - - -void -Send::expect_inputs (const ChanCount& expected) -{ - if (expected != expected_inputs) { - expected_inputs = expected; - _io->reset_panner (); - } -} - /** Set up the XML description of a send so that its name is unique. * @param state XML send state. * @param session Session. diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index db66c2dc30..302bf87f64 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -72,6 +72,7 @@ #include "ardour/processor.h" #include "ardour/recent_sessions.h" #include "ardour/region_factory.h" +#include "ardour/return.h" #include "ardour/route_group.h" #include "ardour/send.h" #include "ardour/session.h" @@ -3666,6 +3667,7 @@ void Session::add_processor (Processor* processor) { Send* send; + Return* retrn; PortInsert* port_insert; PluginInsert* plugin_insert; @@ -3675,6 +3677,8 @@ Session::add_processor (Processor* processor) _plugin_inserts.insert (_plugin_inserts.begin(), plugin_insert); } else if ((send = dynamic_cast<Send *> (processor)) != 0) { _sends.insert (_sends.begin(), send); + } else if ((retrn = dynamic_cast<Return *> (processor)) != 0) { + _returns.insert (_returns.begin(), retrn); } else { fatal << _("programming error: unknown type of Insert created!") << endmsg; /*NOTREACHED*/ @@ -3689,6 +3693,7 @@ void Session::remove_processor (Processor* processor) { Send* send; + Return* retrn; PortInsert* port_insert; PluginInsert* plugin_insert; @@ -3706,6 +3711,12 @@ Session::remove_processor (Processor* processor) send_bitset[send->bit_slot()] = false; _sends.erase (x); } + } else if ((retrn = dynamic_cast<Return *> (processor)) != 0) { + list<Return*>::iterator x = find (_returns.begin(), _returns.end(), retrn); + if (x != _returns.end()) { + return_bitset[send->bit_slot()] = false; + _returns.erase (x); + } } else { fatal << _("programming error: unknown type of Insert deleted!") << endmsg; /*NOTREACHED*/ @@ -3884,6 +3895,26 @@ Session::next_send_id () } } +uint32_t +Session::next_return_id () +{ + /* this doesn't really loop forever. just think about it */ + + while (true) { + for (boost::dynamic_bitset<uint32_t>::size_type n = 0; n < return_bitset.size(); ++n) { + if (!return_bitset[n]) { + return_bitset[n] = true; + return n; + + } + } + + /* none available, so resize and try again */ + + return_bitset.resize (return_bitset.size() + 16, false); + } +} + void Session::mark_send_id (uint32_t id) { @@ -3897,6 +3928,18 @@ Session::mark_send_id (uint32_t id) } void +Session::mark_return_id (uint32_t id) +{ + if (id >= return_bitset.size()) { + return_bitset.resize (id+16, false); + } + if (return_bitset[id]) { + warning << string_compose (_("return ID %1 appears to be in use already"), id) << endmsg; + } + return_bitset[id] = true; +} + +void Session::mark_insert_id (uint32_t id) { if (id >= insert_bitset.size()) { diff --git a/libs/ardour/wscript b/libs/ardour/wscript index adcf3a5f0b..fc0e8107f9 100644 --- a/libs/ardour/wscript +++ b/libs/ardour/wscript @@ -175,6 +175,7 @@ def build(bld): region.cc region_factory.cc resampled_source.cc + return.cc reverse.cc route.cc route_group.cc |