Remove internal ports.

git-svn-id: svn://localhost/ardour2/branches/3.0@4525 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Carl Hetherington 2009-02-11 00:58:24 +00:00
parent fe4e98a729
commit d469cc3e3a
19 changed files with 123 additions and 847 deletions

View file

@ -92,7 +92,6 @@ gain.cc
gdither.cc gdither.cc
globals.cc globals.cc
import.cc import.cc
internal_send.cc
io.cc io.cc
io_processor.cc io_processor.cc
jack_slave.cc jack_slave.cc

View file

@ -29,7 +29,7 @@ namespace ARDOUR {
class AudioPort : public Port class AudioPort : public Port
{ {
public: public:
~AudioPort(); ~AudioPort ();
DataType type () const { DataType type () const {
return DataType::AUDIO; return DataType::AUDIO;
@ -44,23 +44,14 @@ class AudioPort : public Port
AudioBuffer& get_audio_buffer (nframes_t, nframes_t); AudioBuffer& get_audio_buffer (nframes_t, nframes_t);
void reset ();
protected: protected:
friend class AudioEngine; friend class AudioEngine;
AudioPort (std::string const &, Flags, bool, nframes_t); AudioPort (std::string const &, Flags);
bool using_internal_data() const;
void use_internal_data ();
void use_external_data ();
private: private:
void mixdown (nframes_t, nframes_t, bool); bool _buffer_data_set;
bool _has_been_mixed_down;
AudioBuffer* _buffer; AudioBuffer* _buffer;
bool _internal_buffer;
}; };
} // namespace ARDOUR } // namespace ARDOUR

View file

@ -73,10 +73,6 @@ class AudioTrack : public Track
int deprecated_use_diskstream_connections (); int deprecated_use_diskstream_connections ();
void set_state_part_two (); void set_state_part_two ();
void set_state_part_three (); void set_state_part_three ();
void catch_up_on_busses (ARDOUR::RouteList&);
void add_internal_send (boost::shared_ptr<ARDOUR::Route>);
}; };
} // namespace ARDOUR } // namespace ARDOUR

View file

@ -120,8 +120,8 @@ class AudioEngine : public sigc::trackable
virtual const char *what() const throw() { return "could not connect to engine backend"; } virtual const char *what() const throw() { return "could not connect to engine backend"; }
}; };
Port *register_input_port (DataType, const std::string& portname, bool publish); Port *register_input_port (DataType, const std::string& portname);
Port *register_output_port (DataType, const std::string& portname, bool publish); Port *register_output_port (DataType, const std::string& portname);
int unregister_port (Port &); int unregister_port (Port &);
int connect (const std::string& source, const std::string& destination); int connect (const std::string& source, const std::string& destination);
@ -228,7 +228,7 @@ class AudioEngine : public sigc::trackable
SerializedRCUManager<Ports> ports; SerializedRCUManager<Ports> ports;
Port *register_port (DataType type, const std::string& portname, bool input, bool publish); Port *register_port (DataType type, const std::string& portname, bool input);
int process_callback (nframes_t nframes); int process_callback (nframes_t nframes);
void remove_all_ports (); void remove_all_ports ();

View file

@ -1,72 +0,0 @@
/*
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_internal_send_h__
#define __ardour_internal_send_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 InternalSend : public IOProcessor
{
public:
InternalSend (Session&, Placement, boost::shared_ptr<IO> destination);
virtual ~InternalSend ();
ChanCount output_streams() const;
ChanCount input_streams () const;
void run_in_place (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes, nframes_t offset);
void set_metering (bool yn);
void activate ();
void deactivate ();
XMLNode& get_state(void);
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);
static uint32_t how_many_sends();
private:
boost::shared_ptr<IO> destination;
bool _metering;
ChanCount expected_inputs;
uint32_t bitslot;
void destination_io_config_changed (IOChange,void*);
};
} // namespace ARDOUR
#endif /* __ardour_internal_send_h__ */

View file

@ -77,8 +77,7 @@ class IO : public SessionObject, public AutomatableControls, public Latent
IO (Session&, const string& name, IO (Session&, const string& name,
int input_min = -1, int input_max = -1, int input_min = -1, int input_max = -1,
int output_min = -1, int output_max = -1, int output_min = -1, int output_max = -1,
DataType default_type = DataType::AUDIO, DataType default_type = DataType::AUDIO);
bool public_ports = true);
IO (Session&, const XMLNode&, DataType default_type = DataType::AUDIO); IO (Session&, const XMLNode&, DataType default_type = DataType::AUDIO);
@ -286,7 +285,6 @@ class IO : public SessionObject, public AutomatableControls, public Latent
bool _denormal_protection; bool _denormal_protection;
XMLNode* deferred_state; XMLNode* deferred_state;
DataType _default_type; DataType _default_type;
bool _public_ports;
virtual void prepare_inputs (nframes_t nframes, nframes_t offset); virtual void prepare_inputs (nframes_t nframes, nframes_t offset);
virtual void flush_outputs (nframes_t nframes, nframes_t offset); virtual void flush_outputs (nframes_t nframes, nframes_t offset);

View file

@ -47,8 +47,7 @@ class IOProcessor : public Processor
public: public:
IOProcessor (Session&, const string& name, Placement, IOProcessor (Session&, const string& name, Placement,
int input_min = -1, int input_max = -1, int output_min = -1, int output_max = -1, int input_min = -1, int input_max = -1, int output_min = -1, int output_max = -1,
ARDOUR::DataType default_type = DataType::AUDIO, ARDOUR::DataType default_type = DataType::AUDIO);
bool public_ports = true);
IOProcessor (const IOProcessor&); IOProcessor (const IOProcessor&);
virtual ~IOProcessor (); virtual ~IOProcessor ();

View file

@ -49,10 +49,9 @@ class MidiPort : public Port {
protected: protected:
friend class AudioEngine; friend class AudioEngine;
MidiPort (const std::string& name, Flags, bool external, nframes_t bufsize); MidiPort (const std::string& name, Flags);
private: private:
void mixdown (nframes_t, nframes_t, bool);
MidiBuffer* _buffer; MidiBuffer* _buffer;
bool _has_been_mixed_down; bool _has_been_mixed_down;

View file

@ -65,13 +65,7 @@ public:
return _flags & IsOutput; return _flags & IsOutput;
} }
/* @return true if this port is visible outside Ardour (via JACK) */
bool external () const {
return _jack_port != 0;
}
bool connected () const; bool connected () const;
bool externally_connected () const;
int disconnect_all (); int disconnect_all ();
int get_connections (std::vector<std::string> &) const; int get_connections (std::vector<std::string> &) const;
@ -90,9 +84,8 @@ public:
nframes_t total_latency () const; nframes_t total_latency () const;
int reestablish (); int reestablish ();
int reconnect (); int reconnect ();
void set_latency (nframes_t);
void request_monitor_input (bool); void request_monitor_input (bool);
void make_external (); void set_latency (nframes_t);
virtual void reset (); virtual void reset ();
@ -108,36 +101,26 @@ public:
protected: protected:
Port (std::string const &, DataType, Flags, bool); Port (std::string const &, DataType, Flags);
jack_port_t* _jack_port; ///< JACK port, or 0 if we don't have one jack_port_t* _jack_port; ///< JACK port
std::set<Port*> _connections; ///< internal Ports that we are connected to
static AudioEngine* _engine; ///< the AudioEngine static AudioEngine* _engine; ///< the AudioEngine
virtual bool using_internal_data() const { return false; }
virtual void use_internal_data () {}
virtual void use_external_data () {}
void check_buffer_status ();
private: private:
friend class AudioEngine; friend class AudioEngine;
void recompute_total_latency () const; void recompute_total_latency () const;
void do_make_external (DataType);
/* XXX */ /* XXX */
bool _last_monitor; bool _last_monitor;
nframes_t _latency;
std::string _name; ///< port short name std::string _name; ///< port short name
Flags _flags; ///< flags Flags _flags; ///< flags
/// list of JACK ports that we are connected to; we only keep this around /** ports that we are connected to, kept so that we can
/// so that we can implement ::reconnect () reconnect to JACK when required */
std::set<std::string> _named_connections; std::set<std::string> _connections;
}; };
} }

View file

@ -25,30 +25,15 @@
using namespace ARDOUR; using namespace ARDOUR;
using namespace std; using namespace std;
AudioPort::AudioPort (const std::string& name, Flags flags, bool ext, nframes_t capacity) AudioPort::AudioPort (const std::string& name, Flags flags)
: Port (name, DataType::AUDIO, flags, ext) : Port (name, DataType::AUDIO, flags)
, _has_been_mixed_down (false) , _buffer_data_set (false)
, _buffer (0) , _buffer (new AudioBuffer (0))
, _internal_buffer (false)
{ {
assert (name.find_first_of (':') == string::npos); assert (name.find_first_of (':') == string::npos);
if (external ()) {
/* external ports use the external port buffer */
_buffer = new AudioBuffer (0);
} else {
/* internal ports need their own buffers */
_buffer = new AudioBuffer (capacity);
}
check_buffer_status ();
} }
AudioPort::~AudioPort() AudioPort::~AudioPort ()
{ {
delete _buffer; delete _buffer;
} }
@ -58,20 +43,22 @@ AudioPort::cycle_start (nframes_t nframes, nframes_t offset)
{ {
/* caller must hold process lock */ /* caller must hold process lock */
/* For external (JACK) ports, get_buffer() must only be run /* get_buffer() must only be run on outputs here in cycle_start().
on outputs here in cycle_start().
Inputs must be done in the correct processing order, which Inputs must be done in the correct processing order, which
requires interleaving with route processing. that will requires interleaving with route processing. that will
happen when Port::get_buffer() is called. happen when Port::get_buffer() is called.
*/ */
if (!receives_input() && external ()) { if (sends_output() && !_buffer_data_set) {
_buffer->set_data ((Sample *) jack_port_get_buffer (_jack_port, nframes) + offset, nframes); _buffer->set_data ((Sample *) jack_port_get_buffer (_jack_port, nframes) + offset, nframes);
_buffer_data_set = true;
} }
if (receives_input()) { if (receives_input()) {
_has_been_mixed_down = false; _buffer_data_set = false;
} else { } else {
_buffer->silence (nframes, offset); _buffer->silence (nframes, offset);
} }
@ -82,19 +69,10 @@ AudioPort::get_audio_buffer (nframes_t nframes, nframes_t offset)
{ {
/* caller must hold process lock */ /* caller must hold process lock */
if (receives_input () && !_has_been_mixed_down) { if (receives_input () && !_buffer_data_set) {
/* external ports use JACK's memory unless otherwise noted */
if (external()) {
if (!using_internal_data()) {
_buffer->set_data ((Sample *) jack_port_get_buffer (_jack_port, nframes) + offset, nframes); _buffer->set_data ((Sample *) jack_port_get_buffer (_jack_port, nframes) + offset, nframes);
} else {
_buffer->silence (nframes, offset);
}
}
mixdown (nframes, offset, !external ());
} }
return *_buffer; return *_buffer;
@ -103,82 +81,5 @@ AudioPort::get_audio_buffer (nframes_t nframes, nframes_t offset)
void void
AudioPort::cycle_end (nframes_t nframes, nframes_t offset) AudioPort::cycle_end (nframes_t nframes, nframes_t offset)
{ {
_has_been_mixed_down = false; _buffer_data_set = false;
}
void
AudioPort::mixdown (nframes_t cnt, nframes_t offset, bool first_overwrite)
{
/* note: this is only called for input ports */
if (_connections.empty()) {
/* no internal mixing to do, so for internal ports
just make sure the buffer is silent.
*/
if (!external()) {
_buffer->silence (cnt, offset);
}
} else {
set<Port*>::const_iterator p = _connections.begin();
/* mix in internally-connected ports. if this is an external port
then it may already have data present from JACK. in that case, we
do not want to overwrite that data, so we skip the initial ::read_from()
call and do everything with accumulate_from()
*/
if (!external()) {
_buffer->read_from (dynamic_cast<AudioPort*>(*p)->get_audio_buffer (cnt, offset), cnt, offset);
++p;
}
for (; p != _connections.end (); ++p) {
_buffer->accumulate_from (dynamic_cast<AudioPort*>(*p)->get_audio_buffer (cnt, offset), cnt, offset);
}
}
/* XXX horrible heuristic designed to check that we worked the whole buffer.
Needs fixing but its a hard problem.
*/
if (cnt && offset == 0) {
_has_been_mixed_down = true;
}
}
void
AudioPort::reset ()
{
Port::reset ();
if (_buffer->capacity () != 0) {
_buffer->resize (_engine->frames_per_cycle ());
_buffer->clear ();
}
}
bool
AudioPort::using_internal_data () const
{
return _internal_buffer;
}
void
AudioPort::use_internal_data ()
{
_buffer->replace_data (_buffer->capacity());
_internal_buffer = true;
}
void
AudioPort::use_external_data ()
{
_internal_buffer = false;
_buffer->drop_data ();
} }

View file

@ -40,7 +40,6 @@
#include <ardour/utils.h> #include <ardour/utils.h>
#include <ardour/buffer_set.h> #include <ardour/buffer_set.h>
#include <ardour/audio_buffer.h> #include <ardour/audio_buffer.h>
#include <ardour/internal_send.h>
#include "i18n.h" #include "i18n.h"
using namespace std; using namespace std;
@ -66,8 +65,6 @@ AudioTrack::AudioTrack (Session& sess, string name, Route::Flag flag, TrackMode
_session.add_diskstream (ds); _session.add_diskstream (ds);
_session.RouteAdded.connect (mem_fun (*this, &AudioTrack::catch_up_on_busses));
set_diskstream (boost::dynamic_pointer_cast<AudioDiskstream> (ds), this); set_diskstream (boost::dynamic_pointer_cast<AudioDiskstream> (ds), this);
} }
@ -75,47 +72,12 @@ AudioTrack::AudioTrack (Session& sess, const XMLNode& node)
: Track (sess, node) : Track (sess, node)
{ {
_set_state (node, false); _set_state (node, false);
_session.RouteAdded.connect (mem_fun (*this, &AudioTrack::catch_up_on_busses));
} }
AudioTrack::~AudioTrack () AudioTrack::~AudioTrack ()
{ {
} }
void
AudioTrack::catch_up_on_busses (RouteList& added)
{
if (is_hidden()) {
return;
}
for (RouteList::iterator x = added.begin(); x != added.end(); ++x) {
if (boost::dynamic_pointer_cast<Track>(*x) == 0 && (*x)->default_type() == DataType::AUDIO) {
/* Audio bus */
if (!(*x)->is_master() && !(*x)->is_control()) {
add_internal_send (*x);
}
}
}
}
void
AudioTrack::add_internal_send (boost::shared_ptr<Route> r)
{
boost::shared_ptr<InternalSend> is (new InternalSend (_session, PreFader, r));
cerr << name() << " Adding processor\n";
add_processor (is, 0);
cerr << "After add, we have " << _processors.size() << endl;
/* note: if adding failed, the InternalSend will be cleaned up automatically when
the shared_ptr goes out of scope.
*/
}
int int
AudioTrack::set_mode (TrackMode m) AudioTrack::set_mode (TrackMode m)
{ {

View file

@ -576,28 +576,23 @@ AudioEngine::port_registration_failure (const std::string& portname)
} }
Port * Port *
AudioEngine::register_port (DataType dtype, const string& portname, bool input, bool publish) AudioEngine::register_port (DataType dtype, const string& portname, bool input)
{ {
Port* newport = 0; Port* newport = 0;
/*cerr << "trying to register port with name " << portname << endl;*/
try { try {
if (dtype == DataType::AUDIO) { if (dtype == DataType::AUDIO) {
newport = new AudioPort (portname, (input ? Port::IsInput : Port::IsOutput), publish, frames_per_cycle()); newport = new AudioPort (portname, (input ? Port::IsInput : Port::IsOutput));
} else if (dtype == DataType::MIDI) { } else if (dtype == DataType::MIDI) {
newport = new MidiPort (portname, (input ? Port::IsInput : Port::IsOutput), publish, frames_per_cycle()); newport = new MidiPort (portname, (input ? Port::IsInput : Port::IsOutput));
} else { } else {
throw unknown_type(); throw unknown_type();
} }
/*cerr << "successfully got port " << portname << " with address " << newport << endl;*/
RCUWriter<Ports> writer (ports); RCUWriter<Ports> writer (ports);
boost::shared_ptr<Ports> ps = writer.get_copy (); boost::shared_ptr<Ports> ps = writer.get_copy ();
/*cerr << "Address of ports list: " << ps << endl
<< "Ports set size before insert: " << ps->size() << endl;*/
ps->insert (ps->begin(), newport); ps->insert (ps->begin(), newport);
/*cerr << "Ports set size after insert: " << ps->size() << endl;*/
/* writer goes out of scope, forces update */ /* writer goes out of scope, forces update */
@ -610,15 +605,15 @@ AudioEngine::register_port (DataType dtype, const string& portname, bool input,
} }
Port * Port *
AudioEngine::register_input_port (DataType type, const string& portname, bool publish) AudioEngine::register_input_port (DataType type, const string& portname)
{ {
return register_port (type, portname, true, publish); return register_port (type, portname, true);
} }
Port * Port *
AudioEngine::register_output_port (DataType type, const string& portname, bool publish) AudioEngine::register_output_port (DataType type, const string& portname)
{ {
return register_port (type, portname, false, publish); return register_port (type, portname, false);
} }
int int

View file

@ -1,213 +0,0 @@
/*
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 <algorithm>
#include <pbd/xml++.h>
#include <ardour/internal_send.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;
InternalSend::InternalSend (Session& s, Placement p, boost::shared_ptr<IO> dst)
: IOProcessor (s, string_compose (_(">%1"), dst->name()), p,
-1, -1, -1, -1,
DataType::AUDIO, false)
, destination (dst)
{
_metering = false;
destination->input_changed.connect (mem_fun (*this, &InternalSend::destination_io_config_changed));
destination_io_config_changed (ConfigurationChanged, this);
ProcessorCreated (this); /* EMIT SIGNAL */
}
InternalSend::~InternalSend ()
{
GoingAway ();
}
void
InternalSend::destination_io_config_changed (IOChange c, void* src)
{
if (!(c & ConfigurationChanged)) {
return;
}
_io->disconnect_outputs (this);
_io->ensure_io (ChanCount::ZERO, destination->n_inputs(), false, this);
PortSet::const_iterator us (_io->outputs().begin());
PortSet::const_iterator them (destination->inputs().begin ());
for (; us != _io->outputs().end() && them != destination->inputs().end(); ++us, ++them) {
(const_cast<Port*>(&(*us)))->connect (const_cast<Port*>(&(*them)));
}
}
XMLNode&
InternalSend::get_state(void)
{
fatal << X_("InternalSend::get_state() called - should never happen") << endmsg;
/*NOTREACHED*/
return *(new XMLNode ("foo"));
}
int
InternalSend::set_state(const XMLNode& node)
{
fatal << X_("InternalSend::set_state() called - should never happen") << endmsg;
/*NOTREACHED*/
return 0;
}
void
InternalSend::run_in_place (BufferSet& bufs, nframes_t start_frame, nframes_t end_frame, nframes_t nframes, nframes_t offset)
{
if (active()) {
// we have to copy the input, because IO::deliver_output may alter the buffers
// in-place, which a send must never do. otherwise its gain settings will
// affect the signal seen later in the parent Route.
// BufferSet& sendbufs = _session.get_mix_buffers(bufs.count());
// sendbufs.read_from (bufs, nframes);
// assert(sendbufs.count() == bufs.count());
_io->deliver_output (bufs, start_frame, end_frame, nframes, offset);
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, offset);
}
}
} else {
_io->silence (nframes, offset);
if (_metering) {
_io->peak_meter().reset();
}
}
}
void
InternalSend::set_metering (bool yn)
{
_metering = yn;
if (!_metering) {
/* XXX possible thread hazard here */
_io->peak_meter().reset();
}
}
bool
InternalSend::can_support_io_configuration (const ChanCount& in, ChanCount& out_is_ignored) const
{
/* number of outputs is fixed (though mutable by changing the I/O configuration
of the destination)
*/
cerr << "IS: testing I/O config in=" << in.n_audio() << " out=" << out_is_ignored.n_audio() << endl;
if (in == _io->n_outputs()) {
return 1;
}
return -1;
}
bool
InternalSend::configure_io (ChanCount in, ChanCount out)
{
cerr << "Configure IS for in " << in.n_audio() << " out = " << out.n_audio() << endl;
/* we're transparent no matter what. fight the power. */
if (out != in) {
return false;
}
_io->set_output_maximum (in);
_io->set_output_minimum (in);
_io->set_input_maximum (ChanCount::ZERO);
_io->set_input_minimum (ChanCount::ZERO);
out = _io->n_outputs();
Processor::configure_io(in, out);
_io->reset_panner();
return true;
}
ChanCount
InternalSend::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 _io->n_outputs ();
}
ChanCount
InternalSend::input_streams() const
{
return _configured_input;
}
void
InternalSend::expect_inputs (const ChanCount& expected)
{
if (expected != expected_inputs) {
expected_inputs = expected;
_io->reset_panner ();
}
}
void
InternalSend::activate ()
{
Processor::activate ();
}
void
InternalSend::deactivate ()
{
Processor::deactivate ();
}

View file

@ -102,13 +102,12 @@ static double direct_gain_to_control (gain_t gain) {
*/ */
IO::IO (Session& s, const string& name, IO::IO (Session& s, const string& name,
int input_min, int input_max, int output_min, int output_max, int input_min, int input_max, int output_min, int output_max,
DataType default_type, bool public_ports) DataType default_type)
: SessionObject(s, name), : SessionObject(s, name),
AutomatableControls (s), AutomatableControls (s),
_output_buffers (new BufferSet()), _output_buffers (new BufferSet()),
_active(true), _active(true),
_default_type (default_type), _default_type (default_type),
_public_ports (public_ports),
_input_minimum (ChanCount::ZERO), _input_minimum (ChanCount::ZERO),
_input_maximum (ChanCount::INFINITE), _input_maximum (ChanCount::INFINITE),
_output_minimum (ChanCount::ZERO), _output_minimum (ChanCount::ZERO),
@ -166,7 +165,6 @@ IO::IO (Session& s, const XMLNode& node, DataType dt)
_default_type (dt) _default_type (dt)
{ {
_meter = new PeakMeter (_session); _meter = new PeakMeter (_session);
_public_ports = true; // XXX get this from node
_panner = 0; _panner = 0;
deferred_state = 0; deferred_state = 0;
no_panner_reset = false; no_panner_reset = false;
@ -644,7 +642,7 @@ IO::add_output_port (string destination, void* src, DataType type)
string portname = build_legal_port_name (type, false); string portname = build_legal_port_name (type, false);
if ((our_port = _session.engine().register_output_port (type, portname, _public_ports)) == 0) { if ((our_port = _session.engine().register_output_port (type, portname)) == 0) {
error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg; error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg;
return -1; return -1;
} }
@ -748,7 +746,7 @@ IO::add_input_port (string source, void* src, DataType type)
string portname = build_legal_port_name (type, true); string portname = build_legal_port_name (type, true);
if ((our_port = _session.engine().register_input_port (type, portname, _public_ports)) == 0) { if ((our_port = _session.engine().register_input_port (type, portname)) == 0) {
error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg; error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg;
return -1; return -1;
} }
@ -850,7 +848,7 @@ IO::ensure_inputs_locked (ChanCount count, bool clear, void* src)
try { try {
if ((input_port = _session.engine().register_input_port (*t, portname, _public_ports)) == 0) { if ((input_port = _session.engine().register_input_port (*t, portname)) == 0) {
error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg; error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg;
return -1; return -1;
} }
@ -948,7 +946,7 @@ IO::ensure_io (ChanCount in, ChanCount out, bool clear, void* src)
string portname = build_legal_port_name (*t, true); string portname = build_legal_port_name (*t, true);
try { try {
if ((port = _session.engine().register_input_port (*t, portname, _public_ports)) == 0) { if ((port = _session.engine().register_input_port (*t, portname)) == 0) {
error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg; error << string_compose(_("IO: cannot register input port %1"), portname) << endmsg;
return -1; return -1;
} }
@ -972,7 +970,7 @@ IO::ensure_io (ChanCount in, ChanCount out, bool clear, void* src)
string portname = build_legal_port_name (*t, false); string portname = build_legal_port_name (*t, false);
try { try {
if ((port = _session.engine().register_output_port (*t, portname, _public_ports)) == 0) { if ((port = _session.engine().register_output_port (*t, portname)) == 0) {
error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg; error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg;
return -1; return -1;
} }
@ -1087,7 +1085,7 @@ IO::ensure_outputs_locked (ChanCount count, bool clear, void* src)
string portname = build_legal_port_name (*t, false); string portname = build_legal_port_name (*t, false);
if ((output_port = _session.engine().register_output_port (*t, portname, _public_ports)) == 0) { if ((output_port = _session.engine().register_output_port (*t, portname)) == 0) {
error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg; error << string_compose(_("IO: cannot register output port %1"), portname) << endmsg;
return -1; return -1;
} }

View file

@ -46,10 +46,9 @@ using namespace PBD;
IOProcessor::IOProcessor (Session& s, const string& name, Placement p, IOProcessor::IOProcessor (Session& s, const string& name, Placement p,
int input_min, int input_max, int input_min, int input_max,
int output_min, int output_max, int output_min, int output_max,
DataType dtype, DataType dtype)
bool public_ports)
: Processor(s, name, p) : Processor(s, name, p)
, _io (new IO(s, name, input_min, input_max, output_min, output_max, dtype, public_ports)) , _io (new IO(s, name, input_min, input_max, output_min, output_max, dtype))
{ {
_active = false; _active = false;
_sort_key = 0; _sort_key = 0;

View file

@ -25,13 +25,13 @@
using namespace ARDOUR; using namespace ARDOUR;
using namespace std; using namespace std;
MidiPort::MidiPort (const std::string& name, Flags flags, bool ext, nframes_t capacity) MidiPort::MidiPort (const std::string& name, Flags flags)
: Port (name, DataType::MIDI, flags, ext) : Port (name, DataType::MIDI, flags)
, _has_been_mixed_down (false) , _has_been_mixed_down (false)
{ {
// FIXME: size kludge (see BufferSet::ensure_buffers) // FIXME: size kludge (see BufferSet::ensure_buffers)
// Jack needs to tell us this // Jack needs to tell us this
_buffer = new MidiBuffer (capacity * 32); _buffer = new MidiBuffer (1024 * 32);
} }
MidiPort::~MidiPort() MidiPort::~MidiPort()
@ -43,14 +43,12 @@ MidiPort::~MidiPort()
void void
MidiPort::cycle_start (nframes_t nframes, nframes_t offset) MidiPort::cycle_start (nframes_t nframes, nframes_t offset)
{ {
if (external ()) {
_buffer->clear (); _buffer->clear ();
assert (_buffer->size () == 0); assert (_buffer->size () == 0);
if (sends_output ()) { if (sends_output ()) {
jack_midi_clear_buffer (jack_port_get_buffer (_jack_port, nframes)); jack_midi_clear_buffer (jack_port_get_buffer (_jack_port, nframes));
} }
}
} }
MidiBuffer & MidiBuffer &
@ -62,8 +60,6 @@ MidiPort::get_midi_buffer (nframes_t nframes, nframes_t offset)
if (receives_input ()) { if (receives_input ()) {
if (external ()) {
void* jack_buffer = jack_port_get_buffer (_jack_port, nframes); void* jack_buffer = jack_port_get_buffer (_jack_port, nframes);
const nframes_t event_count = jack_midi_get_event_count(jack_buffer); const nframes_t event_count = jack_midi_get_event_count(jack_buffer);
@ -84,19 +80,6 @@ MidiPort::get_midi_buffer (nframes_t nframes, nframes_t offset)
_has_been_mixed_down = true; _has_been_mixed_down = true;
} }
if (!_connections.empty()) {
mixdown (nframes, offset, false);
}
} else {
if (_connections.empty()) {
_buffer->silence (nframes, offset);
} else {
mixdown (nframes, offset, true);
}
}
} else { } else {
_buffer->silence (nframes, offset); _buffer->silence (nframes, offset);
} }
@ -114,7 +97,7 @@ MidiPort::cycle_end (nframes_t nframes, nframes_t offset)
{ {
#if 0 #if 0
if (external () && sends_output ()) { if (sends_output ()) {
/* FIXME: offset */ /* FIXME: offset */
// We're an output - copy events from source buffer to Jack buffer // We're an output - copy events from source buffer to Jack buffer
@ -142,7 +125,7 @@ MidiPort::flush_buffers (nframes_t nframes, nframes_t offset)
{ {
/* FIXME: offset */ /* FIXME: offset */
if (external () && sends_output ()) { if (sends_output ()) {
void* jack_buffer = jack_port_get_buffer (_jack_port, nframes); void* jack_buffer = jack_port_get_buffer (_jack_port, nframes);
@ -158,20 +141,3 @@ MidiPort::flush_buffers (nframes_t nframes, nframes_t offset)
} }
} }
void
MidiPort::mixdown (nframes_t cnt, nframes_t offset, bool first_overwrite)
{
set<Port*>::const_iterator p = _connections.begin();
if (first_overwrite) {
_buffer->read_from ((dynamic_cast<MidiPort*>(*p))->get_midi_buffer (cnt, offset), cnt, offset);
++p;
}
// XXX DAVE: this is just a guess
for (; p != _connections.end(); ++p) {
_buffer->merge (*_buffer, (dynamic_cast<MidiPort*>(*p))->get_midi_buffer (cnt, offset));
}
}

View file

@ -31,10 +31,8 @@ using namespace ARDOUR;
AudioEngine* Port::_engine = 0; AudioEngine* Port::_engine = 0;
/** @param n Port short name */ /** @param n Port short name */
Port::Port (std::string const & n, DataType t, Flags f, bool e) Port::Port (std::string const & n, DataType t, Flags f)
: _jack_port (0) : _last_monitor (false)
, _last_monitor (false)
, _latency (0)
, _name (n) , _name (n)
, _flags (f) , _flags (f)
{ {
@ -46,91 +44,29 @@ Port::Port (std::string const & n, DataType t, Flags f, bool e)
assert (_name.find_first_of (':') == std::string::npos); assert (_name.find_first_of (':') == std::string::npos);
if (e) { if ((_jack_port = jack_port_register (_engine->jack (), _name.c_str (), t.to_jack_type (), _flags, 0)) == 0) {
try {
cerr << "NEW PORT " << _name << " ext = " << e << endl;
do_make_external (t);
}
catch (...) {
throw failed_constructor (); throw failed_constructor ();
} }
}
} }
/** Port destructor */ /** Port destructor */
Port::~Port () Port::~Port ()
{ {
if (_jack_port) {
jack_port_unregister (_engine->jack (), _jack_port); jack_port_unregister (_engine->jack (), _jack_port);
}
}
/** Make this port externally visible by setting it up to use a JACK port.
* @param t Data type, so that we can call this method from the constructor.
*/
void
Port::do_make_external (DataType t)
{
if (_jack_port) {
/* already external */
return;
}
if ((_jack_port = jack_port_register (_engine->jack (), _name.c_str (), t.to_jack_type (), _flags, 0)) == 0) {
throw std::runtime_error ("Could not register JACK port");
}
}
void
Port::make_external ()
{
do_make_external (type ());
} }
/** @return true if this port is connected to anything */ /** @return true if this port is connected to anything */
bool bool
Port::connected () const Port::connected () const
{ {
if (!_connections.empty ()) {
/* connected to a Port* */
return true;
}
if (_jack_port == 0) {
/* not using a JACK port, so can't be connected to anything else */
return false;
}
return (jack_port_connected (_jack_port) != 0);
}
/** @return true if this port is connected to anything via an external port */
bool
Port::externally_connected () const
{
if (_jack_port == 0) {
/* not using a JACK port, so can't be connected to anything else */
return false;
}
return (jack_port_connected (_jack_port) != 0); return (jack_port_connected (_jack_port) != 0);
} }
int int
Port::disconnect_all () Port::disconnect_all ()
{ {
/* Disconnect from Port* connections */
for (std::set<Port*>::iterator i = _connections.begin (); i != _connections.end (); ++i) {
(*i)->_connections.erase (this);
}
_connections.clear ();
/* And JACK connections */
jack_port_disconnect (_engine->jack(), _jack_port); jack_port_disconnect (_engine->jack(), _jack_port);
_named_connections.clear (); _connections.clear ();
check_buffer_status ();
return 0; return 0;
} }
@ -141,22 +77,7 @@ Port::disconnect_all ()
bool bool
Port::connected_to (std::string const & o) const Port::connected_to (std::string const & o) const
{ {
std::string const full = _engine->make_port_name_non_relative (o); return jack_port_connected_to (_jack_port, _engine->make_port_name_non_relative(o).c_str ());
std::string const shrt = _engine->make_port_name_non_relative (o);
if (_jack_port && jack_port_connected_to (_jack_port, full.c_str ())) {
/* connected via JACK */
return true;
}
for (std::set<Port*>::iterator i = _connections.begin (); i != _connections.end (); ++i) {
if ((*i)->name () == shrt) {
/* connected internally */
return true;
}
}
return false;
} }
/** @param o Filled in with port full names of ports that we are connected to */ /** @param o Filled in with port full names of ports that we are connected to */
@ -165,8 +86,6 @@ Port::get_connections (std::vector<std::string> & c) const
{ {
int n = 0; int n = 0;
/* JACK connections */
if (_jack_port) {
const char** jc = jack_port_get_connections (_jack_port); const char** jc = jack_port_get_connections (_jack_port);
if (jc) { if (jc) {
for (int i = 0; jc[i]; ++i) { for (int i = 0; jc[i]; ++i) {
@ -174,14 +93,6 @@ Port::get_connections (std::vector<std::string> & c) const
++n; ++n;
} }
} }
}
/* Internal connections */
for (std::set<Port*>::iterator i = _connections.begin (); i != _connections.end (); ++i) {
std::string const full = _engine->make_port_name_non_relative ((*i)->name());
c.push_back (full);
++n;
}
return n; return n;
} }
@ -192,24 +103,10 @@ Port::connect (std::string const & other)
/* caller must hold process lock */ /* caller must hold process lock */
std::string const other_shrt = _engine->make_port_name_non_relative (other); std::string const other_shrt = _engine->make_port_name_non_relative (other);
Port* p = _engine->get_port_by_name_locked (other_shrt);
int r;
if (p && !p->external ()) {
/* non-external Ardour port; connect using Port* */
r = connect (p);
} else {
/* connect using name */
/* for this to work, we must be an external port */
if (!external ()) {
make_external ();
}
std::string const this_shrt = _engine->make_port_name_non_relative (_name); std::string const this_shrt = _engine->make_port_name_non_relative (_name);
int r = 0;
if (sends_output ()) { if (sends_output ()) {
r = jack_connect (_engine->jack (), this_shrt.c_str (), other_shrt.c_str ()); r = jack_connect (_engine->jack (), this_shrt.c_str (), other_shrt.c_str ());
} else { } else {
@ -217,11 +114,8 @@ Port::connect (std::string const & other)
} }
if (r == 0) { if (r == 0) {
_named_connections.insert (other); _connections.insert (other);
} }
}
check_buffer_status ();
return r; return r;
} }
@ -232,18 +126,10 @@ Port::disconnect (std::string const & other)
/* caller must hold process lock */ /* caller must hold process lock */
std::string const other_shrt = _engine->make_port_name_non_relative (other); std::string const other_shrt = _engine->make_port_name_non_relative (other);
Port* p = _engine->get_port_by_name_locked (other_shrt);
int r;
if (p && !p->external ()) {
/* non-external Ardour port; disconnect using Port* */
r = disconnect (p);
} else {
/* disconnect using name */
std::string const this_shrt = _engine->make_port_name_non_relative (_name); std::string const this_shrt = _engine->make_port_name_non_relative (_name);
int r = 0;
if (sends_output ()) { if (sends_output ()) {
r = jack_disconnect (_engine->jack (), this_shrt.c_str (), other_shrt.c_str ()); r = jack_disconnect (_engine->jack (), this_shrt.c_str (), other_shrt.c_str ());
} else { } else {
@ -251,13 +137,10 @@ Port::disconnect (std::string const & other)
} }
if (r == 0) { if (r == 0) {
_named_connections.erase (other); _connections.erase (other);
} }
check_buffer_status (); return r;
}
return r;
} }
@ -270,41 +153,13 @@ Port::connected_to (Port* o) const
int int
Port::connect (Port* o) Port::connect (Port* o)
{ {
/* caller must hold process lock */
if (external () && o->external ()) {
/* we're both external; connect using name */
return connect (o->name ()); return connect (o->name ());
}
/* otherwise connect by Port* */
_connections.insert (o);
o->_connections.insert (this);
check_buffer_status ();
o->check_buffer_status ();
return 0;
} }
int int
Port::disconnect (Port* o) Port::disconnect (Port* o)
{ {
if (external () && o->external ()) { return disconnect (o->name ());
/* we're both external; try disconnecting using name */
int const r = disconnect (o->name ());
if (r == 0) {
return 0;
}
}
_connections.erase (o);
o->_connections.erase (this);
check_buffer_status ();
o->check_buffer_status ();
return 0;
} }
void void
@ -316,19 +171,13 @@ Port::set_engine (AudioEngine* e)
void void
Port::ensure_monitor_input (bool yn) Port::ensure_monitor_input (bool yn)
{ {
if (_jack_port) {
jack_port_ensure_monitor (_jack_port, yn); jack_port_ensure_monitor (_jack_port, yn);
}
} }
bool bool
Port::monitoring_input () const Port::monitoring_input () const
{ {
if (_jack_port) {
return jack_port_monitoring_input (_jack_port); return jack_port_monitoring_input (_jack_port);
} else {
return false;
}
} }
void void
@ -345,29 +194,19 @@ void
Port::recompute_total_latency () const Port::recompute_total_latency () const
{ {
#ifdef HAVE_JACK_RECOMPUTE_LATENCY #ifdef HAVE_JACK_RECOMPUTE_LATENCY
if (_jack_port) {
jack_recompute_total_latency (_engine->jack (), _jack_port); jack_recompute_total_latency (_engine->jack (), _jack_port);
}
#endif #endif
} }
nframes_t nframes_t
Port::total_latency () const Port::total_latency () const
{ {
if (_jack_port) {
return jack_port_get_total_latency (_engine->jack (), _jack_port); return jack_port_get_total_latency (_engine->jack (), _jack_port);
} else {
return _latency;
}
} }
int int
Port::reestablish () Port::reestablish ()
{ {
if (!_jack_port) {
return 0;
}
_jack_port = jack_port_register (_engine->jack(), _name.c_str(), type().to_jack_type(), _flags, 0); _jack_port = jack_port_register (_engine->jack(), _name.c_str(), type().to_jack_type(), _flags, 0);
if (_jack_port == 0) { if (_jack_port == 0) {
@ -386,11 +225,7 @@ Port::reconnect ()
{ {
/* caller must hold process lock; intended to be used only after reestablish() */ /* caller must hold process lock; intended to be used only after reestablish() */
if (!_jack_port) { for (std::set<string>::iterator i = _connections.begin(); i != _connections.end(); ++i) {
return 0;
}
for (std::set<string>::iterator i = _named_connections.begin(); i != _named_connections.end(); ++i) {
if (connect (*i)) { if (connect (*i)) {
return -1; return -1;
} }
@ -405,63 +240,22 @@ Port::set_name (std::string const & n)
{ {
assert (_name.find_first_of (':') == std::string::npos); assert (_name.find_first_of (':') == std::string::npos);
int r = 0; int const r = jack_port_set_name (_jack_port, n.c_str());
if (_jack_port) {
r = jack_port_set_name (_jack_port, n.c_str());
if (r == 0) { if (r == 0) {
_name = n; _name = n;
} }
} else {
_name = n;
}
return r; return r;
} }
void
Port::set_latency (nframes_t n)
{
_latency = n;
}
void void
Port::request_monitor_input (bool yn) Port::request_monitor_input (bool yn)
{ {
if (_jack_port) {
jack_port_request_monitor (_jack_port, yn); jack_port_request_monitor (_jack_port, yn);
}
} }
void void
Port::check_buffer_status () Port::set_latency (nframes_t n)
{ {
if (external() && receives_input()) { jack_port_set_latency (_jack_port, n);
if (!externally_connected()) {
if (!_connections.empty()) {
/* There are no external connections, so the
external port buffer will be the silent buffer. We cannot write into it.
But we have to write somewhere because there is at least one internal
connection that is supplying us with data.
*/
if (!using_internal_data()) {
use_internal_data ();
}
} else {
/* There are no external connections and no internal ones
either, so we can revert to use the externally supplied
buffer which will be silent (whatever the semantics of
that are for a particular data type.
*/
if (using_internal_data()) {
use_external_data ();
}
}
}
}
} }

View file

@ -35,7 +35,6 @@
#include <ardour/plugin_insert.h> #include <ardour/plugin_insert.h>
#include <ardour/port_insert.h> #include <ardour/port_insert.h>
#include <ardour/send.h> #include <ardour/send.h>
#include <ardour/internal_send.h>
#include <ardour/session.h> #include <ardour/session.h>
#include <ardour/utils.h> #include <ardour/utils.h>
#include <ardour/configuration.h> #include <ardour/configuration.h>
@ -1608,8 +1607,6 @@ Route::_reset_processor_counts (ProcessorStreams* err)
} else if (boost::dynamic_pointer_cast<Send> (*r) != 0) { } else if (boost::dynamic_pointer_cast<Send> (*r) != 0) {
++send_cnt; ++send_cnt;
} else if (boost::dynamic_pointer_cast<InternalSend> (*r) != 0) {
++send_cnt;
} }
} }
@ -1673,7 +1670,6 @@ Route::_reset_processor_counts (ProcessorStreams* err)
for (r = _processors.begin(); r != _processors.end(); prev = r, ++r) { for (r = _processors.begin(); r != _processors.end(); prev = r, ++r) {
boost::shared_ptr<Send> s; boost::shared_ptr<Send> s;
boost::shared_ptr<InternalSend> is;
if ((s = boost::dynamic_pointer_cast<Send> (*r)) != 0) { if ((s = boost::dynamic_pointer_cast<Send> (*r)) != 0) {
@ -1687,16 +1683,6 @@ Route::_reset_processor_counts (ProcessorStreams* err)
s->expect_inputs ((*prev)->output_streams()); s->expect_inputs ((*prev)->output_streams());
} }
} else if ((is = boost::dynamic_pointer_cast<InternalSend> (*r)) != 0) {
/* XXX ditto, but clean this inheritance pattern up someday soon */
if (r == _processors.begin()) {
is->expect_inputs (n_inputs());
} else {
is->expect_inputs ((*prev)->output_streams());
}
} else { } else {
max_audio = max ((*r)->output_streams ().n_audio(), max_audio); max_audio = max ((*r)->output_streams ().n_audio(), max_audio);

View file

@ -60,7 +60,6 @@
#include <ardour/cycle_timer.h> #include <ardour/cycle_timer.h>
#include <ardour/data_type.h> #include <ardour/data_type.h>
#include <ardour/filename_extensions.h> #include <ardour/filename_extensions.h>
#include <ardour/internal_send.h>
#include <ardour/io_processor.h> #include <ardour/io_processor.h>
#include <ardour/midi_diskstream.h> #include <ardour/midi_diskstream.h>
#include <ardour/midi_playlist.h> #include <ardour/midi_playlist.h>
@ -3717,8 +3716,6 @@ Session::add_processor (Processor* processor)
_plugin_inserts.insert (_plugin_inserts.begin(), plugin_insert); _plugin_inserts.insert (_plugin_inserts.begin(), plugin_insert);
} else if ((send = dynamic_cast<Send *> (processor)) != 0) { } else if ((send = dynamic_cast<Send *> (processor)) != 0) {
_sends.insert (_sends.begin(), send); _sends.insert (_sends.begin(), send);
} else if (dynamic_cast<InternalSend *> (processor) != 0) {
/* relax */
} else { } else {
fatal << _("programming error: unknown type of Insert created!") << endmsg; fatal << _("programming error: unknown type of Insert created!") << endmsg;
/*NOTREACHED*/ /*NOTREACHED*/
@ -3744,8 +3741,6 @@ Session::remove_processor (Processor* processor)
} }
} else if ((plugin_insert = dynamic_cast<PluginInsert *> (processor)) != 0) { } else if ((plugin_insert = dynamic_cast<PluginInsert *> (processor)) != 0) {
_plugin_inserts.remove (plugin_insert); _plugin_inserts.remove (plugin_insert);
} else if (dynamic_cast<InternalSend *> (processor) != 0) {
/* relax */
} else if ((send = dynamic_cast<Send *> (processor)) != 0) { } else if ((send = dynamic_cast<Send *> (processor)) != 0) {
list<Send*>::iterator x = find (_sends.begin(), _sends.end(), send); list<Send*>::iterator x = find (_sends.begin(), _sends.end(), send);
if (x != _sends.end()) { if (x != _sends.end()) {