13
0

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
globals.cc
import.cc
internal_send.cc
io.cc
io_processor.cc
jack_slave.cc

View File

@ -29,8 +29,8 @@ namespace ARDOUR {
class AudioPort : public Port
{
public:
~AudioPort();
~AudioPort ();
DataType type () const {
return DataType::AUDIO;
}
@ -44,23 +44,14 @@ class AudioPort : public Port
AudioBuffer& get_audio_buffer (nframes_t, nframes_t);
void reset ();
protected:
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:
void mixdown (nframes_t, nframes_t, bool);
bool _has_been_mixed_down;
bool _buffer_data_set;
AudioBuffer* _buffer;
bool _internal_buffer;
};
} // namespace ARDOUR

View File

@ -73,10 +73,6 @@ class AudioTrack : public Track
int deprecated_use_diskstream_connections ();
void set_state_part_two ();
void set_state_part_three ();
void catch_up_on_busses (ARDOUR::RouteList&);
void add_internal_send (boost::shared_ptr<ARDOUR::Route>);
};
} // 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"; }
};
Port *register_input_port (DataType, const std::string& portname, bool publish);
Port *register_output_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);
int unregister_port (Port &);
int connect (const std::string& source, const std::string& destination);
@ -228,7 +228,7 @@ class AudioEngine : public sigc::trackable
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);
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,
int input_min = -1, int input_max = -1,
int output_min = -1, int output_max = -1,
DataType default_type = DataType::AUDIO,
bool public_ports = true);
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;
XMLNode* deferred_state;
DataType _default_type;
bool _public_ports;
virtual void prepare_inputs (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:
IOProcessor (Session&, const string& name, Placement,
int input_min = -1, int input_max = -1, int output_min = -1, int output_max = -1,
ARDOUR::DataType default_type = DataType::AUDIO,
bool public_ports = true);
ARDOUR::DataType default_type = DataType::AUDIO);
IOProcessor (const IOProcessor&);
virtual ~IOProcessor ();

View File

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

View File

@ -65,13 +65,7 @@ public:
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 externally_connected () const;
int disconnect_all ();
int get_connections (std::vector<std::string> &) const;
@ -90,9 +84,8 @@ public:
nframes_t total_latency () const;
int reestablish ();
int reconnect ();
void set_latency (nframes_t);
void request_monitor_input (bool);
void make_external ();
void set_latency (nframes_t);
virtual void reset ();
@ -108,36 +101,26 @@ public:
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
std::set<Port*> _connections; ///< internal Ports that we are connected to
jack_port_t* _jack_port; ///< JACK port
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:
friend class AudioEngine;
void recompute_total_latency () const;
void do_make_external (DataType);
/* XXX */
bool _last_monitor;
nframes_t _latency;
std::string _name; ///< port short name
Flags _flags; ///< flags
/// list of JACK ports that we are connected to; we only keep this around
/// so that we can implement ::reconnect ()
std::set<std::string> _named_connections;
/** ports that we are connected to, kept so that we can
reconnect to JACK when required */
std::set<std::string> _connections;
};
}

View File

@ -25,30 +25,15 @@
using namespace ARDOUR;
using namespace std;
AudioPort::AudioPort (const std::string& name, Flags flags, bool ext, nframes_t capacity)
: Port (name, DataType::AUDIO, flags, ext)
, _has_been_mixed_down (false)
, _buffer (0)
, _internal_buffer (false)
AudioPort::AudioPort (const std::string& name, Flags flags)
: Port (name, DataType::AUDIO, flags)
, _buffer_data_set (false)
, _buffer (new AudioBuffer (0))
{
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;
}
@ -58,20 +43,22 @@ AudioPort::cycle_start (nframes_t nframes, nframes_t offset)
{
/* caller must hold process lock */
/* For external (JACK) ports, get_buffer() must only be run
on outputs here in cycle_start().
/* get_buffer() must only be run on outputs here in cycle_start().
Inputs must be done in the correct processing order, which
requires interleaving with route processing. that will
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_data_set = true;
}
if (receives_input()) {
_has_been_mixed_down = false;
_buffer_data_set = false;
} else {
_buffer->silence (nframes, offset);
}
@ -82,19 +69,10 @@ AudioPort::get_audio_buffer (nframes_t nframes, nframes_t offset)
{
/* 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 */
_buffer->set_data ((Sample *) jack_port_get_buffer (_jack_port, nframes) + offset, nframes);
if (external()) {
if (!using_internal_data()) {
_buffer->set_data ((Sample *) jack_port_get_buffer (_jack_port, nframes) + offset, nframes);
} else {
_buffer->silence (nframes, offset);
}
}
mixdown (nframes, offset, !external ());
}
return *_buffer;
@ -103,82 +81,5 @@ AudioPort::get_audio_buffer (nframes_t nframes, nframes_t offset)
void
AudioPort::cycle_end (nframes_t nframes, nframes_t offset)
{
_has_been_mixed_down = 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 ();
_buffer_data_set = false;
}

View File

@ -40,7 +40,6 @@
#include <ardour/utils.h>
#include <ardour/buffer_set.h>
#include <ardour/audio_buffer.h>
#include <ardour/internal_send.h>
#include "i18n.h"
using namespace std;
@ -66,8 +65,6 @@ AudioTrack::AudioTrack (Session& sess, string name, Route::Flag flag, TrackMode
_session.add_diskstream (ds);
_session.RouteAdded.connect (mem_fun (*this, &AudioTrack::catch_up_on_busses));
set_diskstream (boost::dynamic_pointer_cast<AudioDiskstream> (ds), this);
}
@ -75,47 +72,12 @@ AudioTrack::AudioTrack (Session& sess, const XMLNode& node)
: Track (sess, node)
{
_set_state (node, false);
_session.RouteAdded.connect (mem_fun (*this, &AudioTrack::catch_up_on_busses));
}
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
AudioTrack::set_mode (TrackMode m)
{

View File

@ -576,28 +576,23 @@ AudioEngine::port_registration_failure (const std::string& portname)
}
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;
/*cerr << "trying to register port with name " << portname << endl;*/
try {
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) {
newport = new MidiPort (portname, (input ? Port::IsInput : Port::IsOutput), publish, frames_per_cycle());
newport = new MidiPort (portname, (input ? Port::IsInput : Port::IsOutput));
} else {
throw unknown_type();
}
/*cerr << "successfully got port " << portname << " with address " << newport << endl;*/
RCUWriter<Ports> writer (ports);
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);
/*cerr << "Ports set size after insert: " << ps->size() << endl;*/
/* writer goes out of scope, forces update */
@ -610,15 +605,15 @@ AudioEngine::register_port (DataType dtype, const string& portname, bool input,
}
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 *
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

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,
int input_min, int input_max, int output_min, int output_max,
DataType default_type, bool public_ports)
DataType default_type)
: SessionObject(s, name),
AutomatableControls (s),
_output_buffers (new BufferSet()),
_active(true),
_default_type (default_type),
_public_ports (public_ports),
_input_minimum (ChanCount::ZERO),
_input_maximum (ChanCount::INFINITE),
_output_minimum (ChanCount::ZERO),
@ -166,7 +165,6 @@ IO::IO (Session& s, const XMLNode& node, DataType dt)
_default_type (dt)
{
_meter = new PeakMeter (_session);
_public_ports = true; // XXX get this from node
_panner = 0;
deferred_state = 0;
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);
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;
return -1;
}
@ -748,7 +746,7 @@ IO::add_input_port (string source, void* src, DataType type)
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;
return -1;
}
@ -850,7 +848,7 @@ IO::ensure_inputs_locked (ChanCount count, bool clear, void* src)
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;
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);
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;
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);
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;
return -1;
}
@ -1087,7 +1085,7 @@ IO::ensure_outputs_locked (ChanCount count, bool clear, void* src)
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;
return -1;
}

View File

@ -46,10 +46,9 @@ using namespace PBD;
IOProcessor::IOProcessor (Session& s, const string& name, Placement p,
int input_min, int input_max,
int output_min, int output_max,
DataType dtype,
bool public_ports)
DataType dtype)
: 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;
_sort_key = 0;

View File

@ -25,13 +25,13 @@
using namespace ARDOUR;
using namespace std;
MidiPort::MidiPort (const std::string& name, Flags flags, bool ext, nframes_t capacity)
: Port (name, DataType::MIDI, flags, ext)
MidiPort::MidiPort (const std::string& name, Flags flags)
: Port (name, DataType::MIDI, flags)
, _has_been_mixed_down (false)
{
// FIXME: size kludge (see BufferSet::ensure_buffers)
// Jack needs to tell us this
_buffer = new MidiBuffer (capacity * 32);
_buffer = new MidiBuffer (1024 * 32);
}
MidiPort::~MidiPort()
@ -43,13 +43,11 @@ MidiPort::~MidiPort()
void
MidiPort::cycle_start (nframes_t nframes, nframes_t offset)
{
if (external ()) {
_buffer->clear ();
assert (_buffer->size () == 0);
if (sends_output ()) {
jack_midi_clear_buffer (jack_port_get_buffer (_jack_port, nframes));
}
_buffer->clear ();
assert (_buffer->size () == 0);
if (sends_output ()) {
jack_midi_clear_buffer (jack_port_get_buffer (_jack_port, nframes));
}
}
@ -62,41 +60,26 @@ MidiPort::get_midi_buffer (nframes_t nframes, nframes_t offset)
if (receives_input ()) {
if (external ()) {
void* jack_buffer = jack_port_get_buffer (_jack_port, nframes);
const nframes_t event_count = jack_midi_get_event_count(jack_buffer);
void* jack_buffer = jack_port_get_buffer (_jack_port, nframes);
const nframes_t event_count = jack_midi_get_event_count(jack_buffer);
assert (event_count < _buffer->capacity());
jack_midi_event_t ev;
for (nframes_t i = 0; i < event_count; ++i) {
jack_midi_event_get (&ev, jack_buffer, i);
// i guess this should do but i leave it off to test the rest first.
//if (ev.time > offset && ev.time < offset+nframes)
_buffer->push_back (ev);
}
if (nframes) {
_has_been_mixed_down = true;
}
if (!_connections.empty()) {
mixdown (nframes, offset, false);
}
} else {
assert (event_count < _buffer->capacity());
if (_connections.empty()) {
_buffer->silence (nframes, offset);
} else {
mixdown (nframes, offset, true);
}
jack_midi_event_t ev;
for (nframes_t i = 0; i < event_count; ++i) {
jack_midi_event_get (&ev, jack_buffer, i);
// i guess this should do but i leave it off to test the rest first.
//if (ev.time > offset && ev.time < offset+nframes)
_buffer->push_back (ev);
}
if (nframes) {
_has_been_mixed_down = true;
}
} else {
_buffer->silence (nframes, offset);
}
@ -114,7 +97,7 @@ MidiPort::cycle_end (nframes_t nframes, nframes_t offset)
{
#if 0
if (external () && sends_output ()) {
if (sends_output ()) {
/* FIXME: offset */
// 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 */
if (external () && sends_output ()) {
if (sends_output ()) {
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;
/** @param n Port short name */
Port::Port (std::string const & n, DataType t, Flags f, bool e)
: _jack_port (0)
, _last_monitor (false)
, _latency (0)
Port::Port (std::string const & n, DataType t, Flags f)
: _last_monitor (false)
, _name (n)
, _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);
if (e) {
try {
cerr << "NEW PORT " << _name << " ext = " << e << endl;
do_make_external (t);
}
catch (...) {
throw failed_constructor ();
}
if ((_jack_port = jack_port_register (_engine->jack (), _name.c_str (), t.to_jack_type (), _flags, 0)) == 0) {
throw failed_constructor ();
}
}
/** Port destructor */
Port::~Port ()
{
if (_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 ());
jack_port_unregister (_engine->jack (), _jack_port);
}
/** @return true if this port is connected to anything */
bool
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);
}
int
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);
_named_connections.clear ();
check_buffer_status ();
_connections.clear ();
return 0;
}
@ -141,22 +77,7 @@ Port::disconnect_all ()
bool
Port::connected_to (std::string const & o) const
{
std::string const full = _engine->make_port_name_non_relative (o);
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;
return jack_port_connected_to (_jack_port, _engine->make_port_name_non_relative(o).c_str ());
}
/** @param o Filled in with port full names of ports that we are connected to */
@ -165,24 +86,14 @@ Port::get_connections (std::vector<std::string> & c) const
{
int n = 0;
/* JACK connections */
if (_jack_port) {
const char** jc = jack_port_get_connections (_jack_port);
if (jc) {
for (int i = 0; jc[i]; ++i) {
c.push_back (jc[i]);
++n;
}
const char** jc = jack_port_get_connections (_jack_port);
if (jc) {
for (int i = 0; jc[i]; ++i) {
c.push_back (jc[i]);
++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;
}
@ -192,36 +103,19 @@ Port::connect (std::string const & other)
/* caller must hold process lock */
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);
std::string const this_shrt = _engine->make_port_name_non_relative (_name);
int r = 0;
if (sends_output ()) {
r = jack_connect (_engine->jack (), this_shrt.c_str (), other_shrt.c_str ());
} 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);
if (sends_output ()) {
r = jack_connect (_engine->jack (), this_shrt.c_str (), other_shrt.c_str ());
} else {
r = jack_connect (_engine->jack (), other_shrt.c_str (), this_shrt.c_str());
}
if (r == 0) {
_named_connections.insert (other);
}
r = jack_connect (_engine->jack (), other_shrt.c_str (), this_shrt.c_str());
}
if (r == 0) {
_connections.insert (other);
}
check_buffer_status ();
return r;
}
@ -232,32 +126,21 @@ Port::disconnect (std::string const & other)
/* caller must hold process lock */
std::string const other_shrt = _engine->make_port_name_non_relative (other);
std::string const this_shrt = _engine->make_port_name_non_relative (_name);
int r = 0;
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);
if (sends_output ()) {
r = jack_disconnect (_engine->jack (), this_shrt.c_str (), other_shrt.c_str ());
} else {
/* disconnect using name */
std::string const this_shrt = _engine->make_port_name_non_relative (_name);
if (sends_output ()) {
r = jack_disconnect (_engine->jack (), this_shrt.c_str (), other_shrt.c_str ());
} else {
r = jack_disconnect (_engine->jack (), other_shrt.c_str (), this_shrt.c_str ());
}
if (r == 0) {
_named_connections.erase (other);
}
check_buffer_status ();
r = jack_disconnect (_engine->jack (), other_shrt.c_str (), this_shrt.c_str ());
}
return r;
if (r == 0) {
_connections.erase (other);
}
return r;
}
@ -270,41 +153,13 @@ Port::connected_to (Port* o) const
int
Port::connect (Port* o)
{
/* caller must hold process lock */
if (external () && o->external ()) {
/* we're both external; connect using 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;
return connect (o->name ());
}
int
Port::disconnect (Port* o)
{
if (external () && o->external ()) {
/* 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;
return disconnect (o->name ());
}
void
@ -316,19 +171,13 @@ Port::set_engine (AudioEngine* e)
void
Port::ensure_monitor_input (bool yn)
{
if (_jack_port) {
jack_port_ensure_monitor (_jack_port, yn);
}
jack_port_ensure_monitor (_jack_port, yn);
}
bool
Port::monitoring_input () const
{
if (_jack_port) {
return jack_port_monitoring_input (_jack_port);
} else {
return false;
}
return jack_port_monitoring_input (_jack_port);
}
void
@ -345,29 +194,19 @@ void
Port::recompute_total_latency () const
{
#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
}
nframes_t
Port::total_latency () const
{
if (_jack_port) {
return jack_port_get_total_latency (_engine->jack (), _jack_port);
} else {
return _latency;
}
return jack_port_get_total_latency (_engine->jack (), _jack_port);
}
int
Port::reestablish ()
{
if (!_jack_port) {
return 0;
}
_jack_port = jack_port_register (_engine->jack(), _name.c_str(), type().to_jack_type(), _flags, 0);
if (_jack_port == 0) {
@ -386,11 +225,7 @@ Port::reconnect ()
{
/* caller must hold process lock; intended to be used only after reestablish() */
if (!_jack_port) {
return 0;
}
for (std::set<string>::iterator i = _named_connections.begin(); i != _named_connections.end(); ++i) {
for (std::set<string>::iterator i = _connections.begin(); i != _connections.end(); ++i) {
if (connect (*i)) {
return -1;
}
@ -405,63 +240,22 @@ Port::set_name (std::string const & n)
{
assert (_name.find_first_of (':') == std::string::npos);
int r = 0;
if (_jack_port) {
r = jack_port_set_name (_jack_port, n.c_str());
if (r == 0) {
_name = n;
}
} else {
int const r = jack_port_set_name (_jack_port, n.c_str());
if (r == 0) {
_name = n;
}
return r;
}
void
Port::set_latency (nframes_t n)
{
_latency = n;
}
void
Port::request_monitor_input (bool yn)
{
if (_jack_port) {
jack_port_request_monitor (_jack_port, yn);
}
jack_port_request_monitor (_jack_port, yn);
}
void
Port::check_buffer_status ()
Port::set_latency (nframes_t n)
{
if (external() && receives_input()) {
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 ();
}
}
}
}
jack_port_set_latency (_jack_port, n);
}

View File

@ -35,7 +35,6 @@
#include <ardour/plugin_insert.h>
#include <ardour/port_insert.h>
#include <ardour/send.h>
#include <ardour/internal_send.h>
#include <ardour/session.h>
#include <ardour/utils.h>
#include <ardour/configuration.h>
@ -1608,8 +1607,6 @@ Route::_reset_processor_counts (ProcessorStreams* err)
} else if (boost::dynamic_pointer_cast<Send> (*r) != 0) {
++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) {
boost::shared_ptr<Send> s;
boost::shared_ptr<InternalSend> is;
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());
}
} 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 {
max_audio = max ((*r)->output_streams ().n_audio(), max_audio);

View File

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