Rework Port class hierarchy a bit. Hopefully now simpler, and should

support connection of JACK ports with internal ones.


git-svn-id: svn://localhost/ardour2/branches/3.0@4417 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Carl Hetherington 2009-01-21 02:27:21 +00:00
parent 4476461443
commit d6637dad5a
40 changed files with 652 additions and 1853 deletions

View File

@ -30,6 +30,7 @@
#include "ardour/audio_track.h"
#include "ardour/midi_track.h"
#include "ardour/data_type.h"
#include "ardour/port.h"
#include "ardour/bundle.h"
#include "io_selector.h"

View File

@ -24,6 +24,7 @@
#include "ardour/audio_track.h"
#include "ardour/midi_track.h"
#include "ardour/audioengine.h"
#include "ardour/port.h"
#include "ardour/bundle.h"
#include <boost/shared_ptr.hpp>
#include <cstring>

View File

@ -52,8 +52,6 @@ automatable.cc
automation.cc
automation_control.cc
automation_list.cc
base_audio_port.cc
base_midi_port.cc
broadcast_info.cc
buffer.cc
buffer_set.cc
@ -96,9 +94,6 @@ globals.cc
import.cc
io.cc
io_processor.cc
jack_audio_port.cc
jack_midi_port.cc
jack_port.cc
jack_slave.cc
ladspa_plugin.cc
location.cc

View File

@ -39,10 +39,10 @@
#include <ardour/session.h>
#include <ardour/route_group.h>
#include <ardour/route.h>
#include <ardour/port.h>
#include <ardour/utils.h>
#include <ardour/diskstream.h>
#include <ardour/audioplaylist.h>
#include <ardour/port.h>
struct tm;

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2002 Paul Davis
Copyright (C) 2002-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
@ -21,28 +21,42 @@
#ifndef __ardour_audio_port_h__
#define __ardour_audio_port_h__
#include <ardour/base_audio_port.h>
#include <ardour/port.h>
#include <ardour/audio_buffer.h>
namespace ARDOUR {
class AudioPort : public BaseAudioPort, public PortFacade {
class AudioPort : public Port
{
public:
~AudioPort();
void reset ();
void cycle_start (nframes_t nframes, nframes_t offset);
void cycle_end (nframes_t nframes, nframes_t offset);
DataType type () const {
return DataType::AUDIO;
}
AudioBuffer& get_audio_buffer( nframes_t nframes, nframes_t offset );
void cycle_start (nframes_t, nframes_t);
void cycle_end (nframes_t, nframes_t);
Buffer& get_buffer (nframes_t nframes, nframes_t offset) {
return get_audio_buffer (nframes, offset);
}
AudioBuffer& get_audio_buffer (nframes_t, nframes_t);
void reset ();
protected:
friend class AudioEngine;
AudioPort (const std::string&, Flags, bool external, nframes_t);
AudioPort (std::string const &, Flags, bool, nframes_t);
private:
void mixdown (nframes_t, nframes_t, bool);
bool _has_been_mixed_down;
AudioBuffer* _buffer;
bool _own_buffer;
};
} // namespace ARDOUR

View File

@ -146,13 +146,11 @@ class AudioEngine : public sigc::trackable
return get_nth_physical (type, n, JackPortIsOutput);
}
nframes_t get_port_total_latency (const Port&);
void update_total_latencies ();
void update_total_latency (const Port&);
/** Caller may not delete the object pointed to by the return value
*/
Port *get_port_by_name (const std::string& name, bool keep = true);
Port *get_port_by_name (const std::string &);
Port *get_port_by_name_locked (const std::string &);
enum TransportState {
TransportStopped = JackTransportStopped,
@ -234,8 +232,6 @@ class AudioEngine : public sigc::trackable
int process_callback (nframes_t nframes);
void remove_all_ports ();
Port* get_port (const std::string& short_name);
typedef std::pair<std::string,std::string> PortConnection;
typedef std::list<PortConnection> PortConnections;

View File

@ -1,102 +0,0 @@
/*
Copyright (C) 2002 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.
$Id: port.h 712 2006-07-28 01:08:57Z drobilla $
*/
#ifndef __ardour_base_audio_port_h__
#define __ardour_base_audio_port_h__
#include <string>
#include <sigc++/signal.h>
#include <pbd/failed_constructor.h>
#include <ardour/ardour.h>
#include <ardour/port.h>
#include <ardour/audio_buffer.h>
namespace ARDOUR {
class AudioEngine;
class BaseAudioPort : public virtual Port {
public:
virtual ~BaseAudioPort();
DataType type() const { return DataType::AUDIO; }
virtual Buffer& get_buffer ( nframes_t nframes, nframes_t offset ) {
return get_audio_buffer( nframes, offset);
}
virtual AudioBuffer& get_audio_buffer (nframes_t nframes, nframes_t offset) = 0;
void reset ();
void reset_overs () {
/* XXX NOT THREAD SAFE */
_short_overs = 0;
_long_overs = 0;
_overlen = 0;
}
void reset_peak_meter () {
/* XXX NOT THREAD SAFE */
_peak = 0;
}
void reset_meters () {
/* XXX NOT THREAD SAFE */
reset_peak_meter ();
reset_overs ();
}
float peak_db() const { return _peak_db; }
Sample peak() const { return _peak; }
uint32_t short_overs () const { return _short_overs; }
uint32_t long_overs () const { return _long_overs; }
static void set_short_over_length (nframes_t);
static void set_long_over_length (nframes_t);
void set_mixdown_function (void (*func)(const std::set<Port*>&, AudioBuffer*, nframes_t, nframes_t, bool));
protected:
BaseAudioPort (const std::string& name, Flags flags);
AudioBuffer* _buffer;
nframes_t _overlen;
Sample _peak;
float _peak_db;
uint32_t _short_overs;
uint32_t _long_overs;
bool _own_buffer;
void (*_mixdown)(const std::set<Port*>&, AudioBuffer*, nframes_t, nframes_t, bool);
static void default_mixdown (const std::set<Port*>&, AudioBuffer*, nframes_t, nframes_t, bool);
static nframes_t _long_over_length;
static nframes_t _short_over_length;
};
} // namespace ARDOUR
#endif /* __ardour_base_audio_port_h__ */

View File

@ -1,63 +0,0 @@
/*
Copyright (C) 2002 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.
$Id: port.h 712 2006-07-28 01:08:57Z drobilla $
*/
#ifndef __ardour_base_midi_port_h__
#define __ardour_base_midi_port_h__
#include <sigc++/signal.h>
#include <pbd/failed_constructor.h>
#include <ardour/ardour.h>
#include <ardour/port.h>
#include <ardour/midi_buffer.h>
namespace ARDOUR {
class MidiEngine;
class BaseMidiPort : public virtual Port {
public:
virtual ~BaseMidiPort();
DataType type() const { return DataType::MIDI; }
Buffer& get_buffer( nframes_t nframes, nframes_t offset ) {
return get_midi_buffer( nframes, offset );
}
virtual MidiBuffer& get_midi_buffer (nframes_t nframes, nframes_t offset ) = 0;
size_t capacity() { return _buffer->capacity(); }
size_t size() { return _buffer->size(); }
void set_mixdown_function (void (*func)(const std::set<Port*>&, MidiBuffer*, nframes_t, nframes_t, bool));
protected:
BaseMidiPort (const std::string& name, Flags);
MidiBuffer* _buffer;
bool _own_buffer;
void (*_mixdown)(const std::set<Port*>&, MidiBuffer*, nframes_t, nframes_t, bool);
static void default_mixdown (const std::set<Port*>&, MidiBuffer*, nframes_t, nframes_t, bool);
};
} // namespace ARDOUR
#endif /* __ardour_base_midi_port_h__ */

View File

@ -40,7 +40,6 @@
#include <ardour/session.h>
#include <ardour/route_group.h>
#include <ardour/route.h>
#include <ardour/port.h>
#include <ardour/utils.h>
struct tm;

View File

@ -1,55 +0,0 @@
/*
Copyright (C) 2007 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.
$Id: port.h 712 2006-07-28 01:08:57Z drobilla $
*/
#ifndef __ardour_internal_audio_port_h__
#define __ardour_internal_audio_port_h__
#include <sigc++/signal.h>
#include <pbd/failed_constructor.h>
#include <ardour/ardour.h>
#include <ardour/internal_port.h>
#include <ardour/audio_port.h>
namespace ARDOUR {
class AudioEngine;
class InternalAudioPort : public AudioPort, public InternalPort {
public:
void cycle_start(nframes_t nframes) {
_buffer.silence (nframes);
}
AudioBuffer& get_audio_buffer();
void set_mixdown_function (void (*func)(const std::list<InternalPort*>&, AudioBuffer&, nframes_t, nframes_t));
void reset ();
protected:
friend class AudioEngine;
InternalAudioPort (const std::string& name, Flags flags);
void (*_mixdown)(const std::list<InternalPort*>&, AudioBuffer&, nframes_t, nframes_t);
static void default_mixdown (const std::list<InternalPort*>&, AudioBuffer&, nframes_t, nframes_t);
};
} // namespace ARDOUR
#endif /* __ardour_internal_audio_port_h__ */

View File

@ -1,82 +0,0 @@
/*
Copyright (C) 2007 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_port_h__
#define __ardour_internal_port_h__
#include <list>
#include <sigc++/signal.h>
#include <pbd/failed_constructor.h>
#include <ardour/port.h>
namespace ARDOUR {
class AudioEngine;
class Buffer;
/** Abstract class representing internal (ardour<->ardour only) ports
*/
class InternalPort : public virtual Port {
public:
~InternalPort();
std::string short_name();
int set_name (std::string str);
int connected () const;
int reestablish ();
bool connected_to (const std::string& portname) const;
const char ** get_connections () const;
bool monitoring_input () const { return false; }
void ensure_monitor_input (bool yn) {}
void request_monitor_input (bool yn) {}
nframes_t latency () const { return _latency; }
nframes_t total_latency() const { return _latency; }
void set_latency (nframes_t nframes);
static void connect (InternalPort& src, InternalPort& dst);
static void disconnect (InternalPort& a, InternalPort& b);
protected:
friend class AudioEngine;
InternalPort (const std::string&, DataType type, Flags flags);
int disconnect ();
void recompute_total_latency() const;
std::list<InternalPort*> _connections;
nframes_t _latency;
static AudioEngine* engine;
static void set_engine (AudioEngine* e);
};
} // namespace ARDOUR
#endif /* __ardour_internal_port_h__ */

View File

@ -1,54 +0,0 @@
/*
Copyright (C) 2002 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.
$Id: port.h 712 2006-07-28 01:08:57Z drobilla $
*/
#ifndef __ardour_jack_audio_port_h__
#define __ardour_jack_audio_port_h__
#include <sigc++/signal.h>
#include <pbd/failed_constructor.h>
#include <ardour/ardour.h>
#include <ardour/jack_port.h>
#include <ardour/audio_port.h>
namespace ARDOUR {
class AudioEngine;
class JackAudioPort : public JackPort, public BaseAudioPort {
public:
void cycle_end (nframes_t nframes, nframes_t offset);
void cycle_start (nframes_t nframes, nframes_t offset);
int reestablish ();
AudioBuffer& get_audio_buffer( nframes_t nframes, nframes_t offset );
protected:
friend class AudioPort;
JackAudioPort (const std::string& name, Flags flags, AudioBuffer* buf);
AudioBuffer* _source_buffer;
private:
bool _has_been_mixed_down;
};
} // namespace ARDOUR
#endif /* __ardour_jack_audio_port_h__ */

View File

@ -1,57 +0,0 @@
/*
Copyright (C) 2002 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.
$Id: port.h 712 2006-07-28 01:08:57Z drobilla $
*/
#ifndef __ardour_jack_midi_port_h__
#define __ardour_jack_midi_port_h__
#include <sigc++/signal.h>
#include <pbd/failed_constructor.h>
#include <ardour/ardour.h>
#include <jack/jack.h>
#include <jack/midiport.h>
#include <ardour/port.h>
#include <ardour/jack_port.h>
#include <ardour/base_midi_port.h>
#include <ardour/midi_buffer.h>
namespace ARDOUR {
class MidiEngine;
class JackMidiPort : public JackPort, public BaseMidiPort {
public:
void cycle_start (nframes_t nframes, nframes_t offset);
void cycle_end (nframes_t nframes, nframes_t offset);
void flush_buffers (nframes_t nframes, nframes_t offset);
void set_buffer (MidiBuffer& buf);
MidiBuffer& get_midi_buffer( nframes_t nframes, nframes_t offset );
protected:
friend class MidiPort;
JackMidiPort (const std::string&, Flags, MidiBuffer*);
private:
bool _has_been_mixed_down;
};
} // namespace ARDOUR
#endif /* __ardour_jack_midi_port_h__ */

View File

@ -34,14 +34,12 @@
#include <pbd/fastlog.h>
#include <pbd/ringbufferNPT.h>
#include <ardour/ardour.h>
#include <ardour/configuration.h>
#include <ardour/session.h>
#include <ardour/route_group.h>
#include <ardour/route.h>
#include <ardour/port.h>
#include <ardour/utils.h>
#include <ardour/diskstream.h>
#include <ardour/midi_playlist.h>

View File

@ -21,29 +21,40 @@
#ifndef __ardour_midi_port_h__
#define __ardour_midi_port_h__
#include <ardour/base_midi_port.h>
#include <ardour/port.h>
#include <ardour/midi_buffer.h>
namespace ARDOUR {
class MidiEngine;
class MidiPort : public BaseMidiPort, public PortFacade {
class MidiPort : public Port {
public:
~MidiPort();
void reset ();
DataType type () const {
return DataType::MIDI;
}
void cycle_start (nframes_t nframes, nframes_t offset);
void cycle_end (nframes_t nframes, nframes_t offset);
void flush_buffers (nframes_t nframes, nframes_t offset);
Buffer& get_buffer (nframes_t nframes, nframes_t offset) {
return get_midi_buffer (nframes, offset);
}
MidiBuffer& get_midi_buffer( nframes_t nframes, nframes_t offset );
protected:
friend class AudioEngine;
MidiPort (const std::string& name, Flags, bool external, nframes_t bufsize);
private:
void mixdown (nframes_t, nframes_t, bool);
MidiBuffer* _buffer;
bool _has_been_mixed_down;
};

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2002 Paul Davis
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
@ -20,167 +20,118 @@
#ifndef __ardour_port_h__
#define __ardour_port_h__
#include "ardour/data_type.h"
#include "ardour/types.h"
#include <sigc++/trackable.h>
#include <jack/jack.h>
#include <string>
#include <set>
#include <vector>
#include <string>
#include <cstring>
#include <sigc++/signal.h>
#include <pbd/failed_constructor.h>
#include <pbd/destructible.h>
#include <ardour/ardour.h>
#include <ardour/data_type.h>
#include <jack/jack.h>
namespace ARDOUR {
class AudioEngine;
class Buffer;
class Buffer;
/** Abstract base for ports
*/
class Port : public virtual PBD::Destructible {
public:
class Port : public sigc::trackable
{
public:
enum Flags {
IsInput = JackPortIsInput,
IsOutput = JackPortIsOutput,
IsPhysical = JackPortIsPhysical,
IsTerminal = JackPortIsTerminal,
CanMonitor = JackPortCanMonitor
};
virtual ~Port();
virtual ~Port ();
std::string name() const {
/** @return Port name (excluding prefix) */
std::string name () const {
return _name;
}
Flags flags() const {
int set_name (std::string const &);
/** @return flags */
Flags flags () const {
return _flags;
}
bool receives_input() const {
/** @return true if this Port receives input, otherwise false */
bool receives_input () const {
return _flags & IsInput;
}
/** @return true if this Port sends output, otherwise false */
bool sends_output () const {
return _flags & IsOutput;
}
bool can_monitor () const {
return _flags & CanMonitor;
/* @return true if this port is visible outside Ardour (via JACK) */
bool external () const {
return _jack_port != 0;
}
void enable_metering() {
_metering++;
}
void disable_metering () {
if (_metering) { _metering--; }
}
virtual void cycle_start (nframes_t nframes, nframes_t offset) {}
virtual void cycle_end (nframes_t nframes, nframes_t offset) {}
virtual void flush_buffers (nframes_t nframes, nframes_t offset ) {}
virtual DataType type() const = 0;
virtual Buffer& get_buffer( nframes_t nframes, nframes_t offset ) = 0;
virtual bool connected () const;
virtual bool connected_to (const std::string& portname) const;
virtual int get_connections (std::vector<std::string>&) const;
virtual int connect (Port& other);
virtual int disconnect (Port& other);
virtual int disconnect_all ();
virtual void reset ();
virtual int reestablish () {return 0; }
virtual int reconnect () { return 0; }
virtual int set_name (const std::string& str) {
_name = str;
return 0;
}
virtual std::string short_name() const = 0;
virtual bool monitoring_input () const = 0;
virtual void ensure_monitor_input (bool yn) = 0;
virtual void request_monitor_input (bool yn) = 0;
virtual nframes_t latency () const = 0;
virtual nframes_t total_latency () const = 0;
virtual void set_latency (nframes_t nframes) = 0;
sigc::signal<void,bool> MonitorInputChanged;
sigc::signal<void,bool> ClockSyncChanged;
static void set_engine (AudioEngine*);
protected:
friend class AudioEngine;
Port (const std::string& name, Flags flgs);
virtual void recompute_total_latency() const {}
/* engine isn't supposed to access below here */
Flags _flags;
std::string _type;
std::string _name;
unsigned short _metering;
bool _last_monitor;
nframes_t _latency;
std::set<Port*> _connections;
static AudioEngine* engine;
private:
void port_going_away (Port *);
};
class PortConnectableByName {
public:
PortConnectableByName() {}
virtual ~PortConnectableByName() {}
virtual int connect (const std::string& other_name) = 0;
virtual int disconnect (const std::string& other_name) = 0;
};
class PortFacade : public virtual Port, public PortConnectableByName {
public:
PortFacade (const std::string& name, Flags flgs) : Port (name, flgs), _ext_port (0) {}
~PortFacade() {}
void reset ();
int reestablish ();
int reconnect ();
int connect (Port& other);
int disconnect (Port& other);
int disconnect_all ();
int connect (const std::string& other_name);
int disconnect (const std::string& other_name);
bool connected () const;
bool connected_to (const std::string& portname) const;
int get_connections (std::vector<std::string>&) const;
int disconnect_all ();
int get_connections (std::vector<std::string> &) const;
std::string short_name() const;
int set_name (const std::string& str);
bool monitoring_input () const;
void ensure_monitor_input (bool yn);
void request_monitor_input (bool yn);
nframes_t latency () const;
nframes_t total_latency () const;
void set_latency (nframes_t nframes);
/* connection by name */
bool connected_to (std::string const &) const;
int connect (std::string const &);
int disconnect (std::string const &);
protected:
Port* _ext_port;
/* connection by Port* */
bool connected_to (Port *) const;
int connect (Port *);
int disconnect (Port *);
void ensure_monitor_input (bool);
bool monitoring_input () const;
nframes_t total_latency () const;
int reestablish ();
int reconnect ();
void set_latency (nframes_t);
void request_monitor_input (bool);
void make_external ();
virtual void reset ();
virtual DataType type () const = 0;
virtual void cycle_start (nframes_t, nframes_t) = 0;
virtual void cycle_end (nframes_t, nframes_t) = 0;
virtual Buffer& get_buffer (nframes_t, nframes_t) = 0;
virtual void flush_buffers (nframes_t, nframes_t) {}
static void set_engine (AudioEngine *);
sigc::signal<void, bool> MonitorInputChanged;
protected:
Port (std::string const &, DataType, Flags, bool);
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
static AudioEngine* _engine; ///< the AudioEngine
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 name (excluding prefix)
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;
};
} // namespace ARDOUR
}
#endif /* __ardour_port_h__ */
#endif

View File

@ -20,13 +20,13 @@
#define __ardour_port_set_h__
#include <vector>
#include <ardour/port.h>
#include <ardour/audio_port.h>
#include <ardour/midi_port.h>
#include <ardour/chan_count.h>
namespace ARDOUR {
class Port;
class AudioPort;
class MidiPort;
/** An ordered list of Ports, possibly of various types.
*

View File

@ -52,6 +52,7 @@
#include <ardour/audioregion.h>
#include <ardour/audio_port.h>
#include <ardour/source_factory.h>
#include <ardour/audio_buffer.h>
#include "i18n.h"
#include <locale.h>

View File

@ -18,118 +18,86 @@
#include <cassert>
#include <ardour/audio_port.h>
#include <ardour/jack_audio_port.h>
#include <ardour/audioengine.h>
#include <ardour/data_type.h>
#include <ardour/audio_buffer.h>
using namespace ARDOUR;
using namespace std;
AudioPort::AudioPort (const std::string& name, Flags flags, bool external, nframes_t capacity)
: Port (name, flags)
, BaseAudioPort (name, flags)
, PortFacade (name, flags)
, _has_been_mixed_down( false )
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)
{
if (!external || receives_input()) {
/* internal-only and input ports need their own buffers.
external output ports use the external port buffer.
*/
_buffer = new AudioBuffer (capacity);
_own_buffer = true;
}
if (!external) {
_ext_port = 0;
set_name (name);
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);
/* make the JackAudioPort create its own buffer. For input,
we will copy from it during cycle_start(). For output,
we will set up our buffer to point to its buffer, which
will in turn be using the JACK port buffer for data.
*/
_ext_port = new JackAudioPort (name, flags, 0);
//if (sends_output()) {
// _buffer = &dynamic_cast<JackAudioPort*>(_ext_port)->get_audio_buffer( nframes, offset );
//}
Port::set_name (_ext_port->name());
}
reset ();
}
AudioPort::~AudioPort()
{
delete _ext_port;
_ext_port = 0;
delete _buffer;
}
void
AudioPort::reset()
{
BaseAudioPort::reset();
if (_ext_port) {
_ext_port->reset ();
}
}
void
AudioPort::cycle_start (nframes_t nframes, nframes_t offset)
{
/* caller must hold process lock */
if (_ext_port) {
_ext_port->cycle_start (nframes, offset);
}
_has_been_mixed_down = false;
if (external ()) {
/* external ports use JACK's memory */
_buffer->set_data ((Sample *) jack_port_get_buffer (_jack_port, nframes), nframes + offset);
}
}
AudioBuffer &
AudioPort::get_audio_buffer( nframes_t nframes, nframes_t offset ) {
AudioPort::get_audio_buffer (nframes_t nframes, nframes_t offset)
{
/* caller must hold process lock */
if (_has_been_mixed_down)
if (_has_been_mixed_down) {
return *_buffer;
if (_flags & IsInput) {
if (_ext_port) {
_buffer->read_from (dynamic_cast<BaseAudioPort*>(_ext_port)->get_audio_buffer (nframes, offset), nframes, offset);
if (!_connections.empty()) {
(*_mixdown) (_connections, _buffer, nframes, offset, false);
}
} else {
if (_connections.empty()) {
_buffer->silence (nframes, offset);
} else {
(*_mixdown) (_connections, _buffer, nframes, offset, true);
}
}
} else {
// XXX if we could get the output stage to not purely mix into, but also
// to initially overwrite the buffer, we could avoid this silence step.
if (_ext_port) {
_buffer = & (dynamic_cast<BaseAudioPort*>(_ext_port)->get_audio_buffer( nframes, offset ));
}
if (nframes)
_buffer->silence (nframes, offset);
}
if (nframes)
if (receives_input ()) {
/* INPUT */
/* If we're external (), we have some data in our buffer set up by JACK;
otherwise, we have an undefined buffer. In either case we mix down
our non-JACK inputs; either accumulating into the JACK data or
overwriting the undefined data */
mixdown (nframes, offset, !external ());
} else {
/* OUTPUT */
if (!external ()) {
/* start internal output buffers with silence */
_buffer->silence (nframes, offset);
}
}
if (nframes) {
_has_been_mixed_down = true;
}
return *_buffer;
}
@ -137,5 +105,38 @@ 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;
_has_been_mixed_down = false;
}
void
AudioPort::mixdown (nframes_t cnt, nframes_t offset, bool first_overwrite)
{
if (_connections.empty()) {
if (first_overwrite) {
_buffer->silence (cnt, offset);
}
return;
}
set<Port*>::const_iterator p = _connections.begin();
if (first_overwrite) {
_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);
}
}
void
AudioPort::reset ()
{
Port::reset ();
if (_buffer->capacity () != 0) {
_buffer->resize (_engine->frames_per_cycle ());
_buffer->clear ();
}
}

View File

@ -39,6 +39,7 @@
#include <ardour/panner.h>
#include <ardour/utils.h>
#include <ardour/buffer_set.h>
#include <ardour/audio_buffer.h>
#include "i18n.h"
using namespace std;

View File

@ -34,10 +34,8 @@
#include <ardour/audioengine.h>
#include <ardour/buffer.h>
#include <ardour/port.h>
#include <ardour/jack_audio_port.h>
#include <ardour/jack_midi_port.h>
#include <ardour/midi_port.h>
#include <ardour/audio_port.h>
#include <ardour/midi_port.h>
#include <ardour/session.h>
#include <ardour/cycle_timer.h>
#include <ardour/utils.h>
@ -356,6 +354,7 @@ AudioEngine::process_callback (nframes_t nframes)
which requires interleaving with route processing.
*/
/* XXX: we're running this on both inputs and outputs... */
(*i)->cycle_start (nframes, 0);
}
@ -619,21 +618,6 @@ AudioEngine::register_port (DataType dtype, const string& portname, bool input,
}
}
Port*
AudioEngine::get_port (const std::string& full_name)
{
boost::shared_ptr<Ports> p = ports.reader();
for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
//cerr << "comparing port name '" << (*i)->name() << "' with '" << full_name << "'" << endl;
if ((*i)->name() == full_name) {
return *i;
}
}
return 0;
}
Port *
AudioEngine::register_input_port (DataType type, const string& portname, bool publish)
{
@ -692,6 +676,8 @@ AudioEngine::unregister_port (Port& port)
int
AudioEngine::connect (const string& source, const string& destination)
{
/* caller must hold process lock */
int ret;
if (!_running) {
@ -705,39 +691,24 @@ AudioEngine::connect (const string& source, const string& destination)
string s = make_port_name_non_relative (source);
string d = make_port_name_non_relative (destination);
//cerr << "Trying to connect source: " << s << " with destination " << d << endl;
Port* src = get_port (s);
Port* dst = get_port (d);
Port* src = get_port_by_name_locked (s);
Port* dst = get_port_by_name_locked (d);
if (src && dst) {
/* both ports are known to us, so do the internal connect stuff */
if ((ret = src->connect (*dst)) == 0) {
ret = dst->connect (*src);
}
ret = src->connect (dst);
} else if (src || dst) {
/* one port is known to us, try to connect it to something external */
PortConnectableByName* pcn;
string other;
if (src) {
pcn = dynamic_cast<PortConnectableByName*>(src);
other = d;
ret = src->connect (d);
} else {
pcn = dynamic_cast<PortConnectableByName*>(dst);
other = s;
}
if (pcn) {
ret = pcn->connect (other);
} else {
ret = -1;
ret = dst->connect (s);
}
} else {
@ -764,6 +735,8 @@ AudioEngine::connect (const string& source, const string& destination)
int
AudioEngine::disconnect (const string& source, const string& destination)
{
/* caller must hold process lock */
int ret;
if (!_running) {
@ -778,39 +751,23 @@ AudioEngine::disconnect (const string& source, const string& destination)
string s = make_port_name_non_relative (source);
string d = make_port_name_non_relative (destination);
//cerr << "trying to disconnect port '" << s << "' from port '" << d << endl;
Port* src = get_port (s);
Port* dst = get_port (d);
Port* src = get_port_by_name_locked (s);
Port* dst = get_port_by_name_locked (d);
if (src && dst) {
/* both ports are known to us, so do the internal connect stuff */
/* both ports are known to us, so do the internal disconnect stuff */
if ((ret = src->disconnect (*dst)) == 0) {
ret = dst->disconnect (*src);
}
ret = src->disconnect (dst);
} else if (src || dst) {
/* one port is known to us, try to connect it to something external */
PortConnectableByName* pcn;
string other;
/* one port is known to us, try to disconnect it from something external */
if (src) {
pcn = dynamic_cast<PortConnectableByName*>(src);
other = d;
ret = src->disconnect (d);
} else {
pcn = dynamic_cast<PortConnectableByName*>(dst);
other = s;
}
if (pcn) {
ret = pcn->disconnect (other);
} else {
ret = -1;
ret = dst->disconnect (s);
}
} else {
@ -873,34 +830,53 @@ AudioEngine::frames_per_cycle ()
}
}
/** Get a port by name.
* Note this can return NULL, it will NOT create a port if it is not found (any more).
/** @param name Full name of port (including prefix:)
* @return Corresponding Port*, or 0. This object remains the property of the AudioEngine
* so must not be deleted.
*/
Port *
AudioEngine::get_port_by_name (const string& portname, bool keep)
AudioEngine::get_port_by_name (const string& portname)
{
Glib::Mutex::Lock lm (_process_lock);
return get_port_by_name_locked (portname);
}
Port *
AudioEngine::get_port_by_name_locked (const string& portname)
{
/* caller must hold process lock */
if (!_running) {
if (!_has_run) {
fatal << _("get_port_by_name() called before engine was started") << endmsg;
fatal << _("get_port_by_name_locked() called before engine was started") << endmsg;
/*NOTREACHED*/
} else {
return 0;
}
}
if (portname.substr (0, jack_client_name.length ()) != jack_client_name) {
/* not an ardour: port */
return 0;
}
std::string const rel = make_port_name_relative (portname);
boost::shared_ptr<Ports> pr = ports.reader();
for (Ports::iterator i = pr->begin(); i != pr->end(); ++i) {
if (portname == (*i)->name()) {
return (*i);
if (rel == (*i)->name()) {
return *i;
}
}
return 0;
}
const char **
AudioEngine::get_ports (const string& port_name_pattern, const string& type_name_pattern, uint32_t flags)
{
@ -1071,12 +1047,6 @@ AudioEngine::get_nth_physical (DataType type, uint32_t n, int flag)
return ret;
}
ARDOUR::nframes_t
AudioEngine::get_port_total_latency (const Port& port)
{
return port.total_latency ();
}
void
AudioEngine::update_total_latency (const Port& port)
{

View File

@ -1,82 +0,0 @@
/*
Copyright (C) 2006 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 <cassert>
#include <glib.h>
#include <ardour/base_audio_port.h>
#include <ardour/audioengine.h>
#include <ardour/data_type.h>
using namespace ARDOUR;
using namespace std;
nframes_t BaseAudioPort::_short_over_length = 2;
nframes_t BaseAudioPort::_long_over_length = 10;
BaseAudioPort::BaseAudioPort (const std::string& name, Flags flgs)
: Port (name, flgs)
, _buffer (0)
, _own_buffer (false)
{
_type = DataType::AUDIO;
_mixdown = default_mixdown;
}
BaseAudioPort::~BaseAudioPort ()
{
if (_own_buffer) {
delete _buffer;
}
}
void
BaseAudioPort::reset()
{
Port::reset();
if (_own_buffer && _buffer) {
_buffer->resize (engine->frames_per_cycle());
_buffer->clear ();
}
_metering = 0;
reset_meters ();
}
void
BaseAudioPort::default_mixdown (const set<Port*>& ports, AudioBuffer* dest, nframes_t cnt, nframes_t offset, bool first_overwrite)
{
set<Port*>::const_iterator p = ports.begin();
if (first_overwrite) {
dest->read_from ((dynamic_cast<BaseAudioPort*>(*p))->get_audio_buffer( cnt, offset ), cnt, offset);
p++;
}
for (; p != ports.end(); ++p) {
dest->accumulate_from ((dynamic_cast<BaseAudioPort*>(*p))->get_audio_buffer( cnt, offset ), cnt, offset);
}
}
void
BaseAudioPort::set_mixdown_function (void (*func)(const set<Port*>&, AudioBuffer*, nframes_t, nframes_t, bool))
{
g_atomic_pointer_set(&_mixdown, func);
}

View File

@ -1,67 +0,0 @@
/*
Copyright (C) 2006 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 <cassert>
#include <iostream>
#include <glib.h>
#include <ardour/base_midi_port.h>
#include <ardour/data_type.h>
using namespace ARDOUR;
using namespace std;
BaseMidiPort::BaseMidiPort (const std::string& name, Flags flags)
: Port (name, flags)
, _buffer (0)
, _own_buffer (false)
{
_type = DataType::MIDI;
_mixdown = default_mixdown;
}
BaseMidiPort::~BaseMidiPort()
{
if (_own_buffer) {
delete _buffer;
}
}
void
BaseMidiPort::default_mixdown (const set<Port*>& ports, MidiBuffer* dest, nframes_t cnt, nframes_t offset, bool first_overwrite)
{
set<Port*>::const_iterator p = ports.begin();
if (first_overwrite) {
cout << "first overwrite" << endl;
dest->read_from ((dynamic_cast<BaseMidiPort*>(*p))->get_midi_buffer(cnt, offset), cnt, offset);
p++;
}
// XXX DAVE: this is just a guess
for (; p != ports.end(); ++p) {
//cout << "merge" << endl;
dest->merge (*dest, (dynamic_cast<BaseMidiPort*>(*p))->get_midi_buffer(cnt, offset));
}
}
void
BaseMidiPort::set_mixdown_function (void (*func)(const set<Port*>&, MidiBuffer*, nframes_t, nframes_t, bool))
{
g_atomic_pointer_set(&_mixdown, func);
}

View File

@ -22,6 +22,8 @@
#include <ardour/export_failed.h>
#include <ardour/audioengine.h>
#include <ardour/audio_port.h>
#include <ardour/audio_buffer.h>
using namespace ARDOUR;

View File

@ -1,71 +0,0 @@
/*
Copyright (C) 2006 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 <cassert>
#include <ardour/internal_audio_port.h>
#include <ardour/audioengine.h>
using namespace ARDOUR;
using namespace std;
void
InternalAudioPort::default_mixdown (const list<InternalPort*>& ports, AudioBuffer& dest, nframes_t cnt, nframes_t offset)
{
list<InternalPort*>::const_iterator p = ports.begin();
dest.read_from ((dynamic_cast<AudioPort*>(*p))->get_audio_buffer(), cnt, offset);
for (; p != ports.end(); ++p) {
dest.accumulate_from ((dynamic_cast<AudioPort*>(*p))->get_audio_buffer(), cnt, offset);
}
}
InternalAudioPort::InternalAudioPort(const string& name, Flags flags)
: Port (DataType::AUDIO, flags)
, AudioPort (flags, engine->frames_per_cycle())
, InternalPort (name, DataType::AUDIO, flags)
{
_mixdown = default_mixdown;
}
void
InternalAudioPort::set_mixdown_function (void (*func)(const list<InternalPort*>&, AudioBuffer&, nframes_t, nframes_t))
{
_mixdown = func;
}
void
InternalAudioPort::reset ()
{
_buffer.resize (engine->frames_per_cycle());
_buffer.silence (_buffer.size());
}
AudioBuffer&
InternalAudioPort::get_audio_buffer ()
{
if (_connections.empty()) {
return AudioPort::get_audio_buffer();
}
/* XXX what about offset/size being more dynamic ? */
(*_mixdown) (_connections, _buffer, _buffer.size(), 0);
return _buffer;
}

View File

@ -1,163 +0,0 @@
/*
Copyright (C) 2007 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 <pbd/error.h>
#include <ardour/internal_port.h>
#include <ardour/audioengine.h>
#include "i18n.h"
using namespace ARDOUR;
using namespace std;
AudioEngine* InternalPort::engine = 0;
void
InternalPort::set_engine (AudioEngine* e)
{
engine = e;
}
InternalPort::InternalPort (const string& str, DataType type, Flags flags)
: Port (type, flags)
{
set_name (str);
}
InternalPort::~InternalPort ()
{
disconnect ();
}
void
InternalPort::set_latency (nframes_t val)
{
_latency = val;
}
bool
InternalPort::connected_to (const string& portname) const
{
/* caller must hold process lock */
for (list<InternalPort*>::const_iterator p = _connections.begin(); p != _connections.end(); ++p) {
if ((*p)->name() == portname) {
return true;
}
}
return false;
}
const char**
InternalPort::get_connections () const
{
/* caller must hold process lock */
int i;
list<InternalPort*>::const_iterator p;
if (_connections.empty()) {
return 0;
}
char **names = (char**) malloc (sizeof (char*) * ( _connections.size() + 1));
for (i = 0, p = _connections.begin(); p != _connections.end(); ++p, ++i) {
names[i] = (char*) (*p)->name().c_str();
}
names[i] = 0;
return (const char**) names;
}
int
InternalPort::connected() const
{
/* caller must hold process lock */
return !_connections.empty();
}
int
InternalPort::set_name (string str)
{
_name = "internal:";
_name += str;
return 0;
}
string
InternalPort::short_name ()
{
return _name.substr (9);
}
void
InternalPort::connect (InternalPort& src, InternalPort& dst)
{
/* caller must hold process lock */
src._connections.push_back (&dst);
dst._connections.push_back (&src);
}
void
InternalPort::disconnect (InternalPort& a, InternalPort& b)
{
/* caller must hold process lock */
a._connections.remove (&b);
b._connections.remove (&a);
}
int
InternalPort::disconnect ()
{
/* caller must hold process lock */
for (list<InternalPort*>::const_iterator p = _connections.begin(); p != _connections.end(); ) {
list<InternalPort*>::const_iterator tmp;
tmp = p;
++tmp;
disconnect (*this, **p);
p = tmp;
}
_connections.clear ();
return 0;
}
int
InternalPort::reestablish ()
{
return 0;
}
void
InternalPort::recompute_total_latency () const
{
return;
}

View File

@ -1965,13 +1965,13 @@ IO::set_name (const string& requested_name)
}
for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
string current_name = i->short_name();
string current_name = i->name();
current_name.replace (current_name.find (_name), _name.length(), name);
i->set_name (current_name);
}
for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
string current_name = i->short_name();
string current_name = i->name();
current_name.replace (current_name.find (_name), _name.length(), name);
i->set_name (current_name);
}
@ -2028,7 +2028,7 @@ IO::output_latency () const
/* io lock not taken - must be protected by other means */
for (PortSet::const_iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
if ((latency = _session.engine().get_port_total_latency (*i)) > max_latency) {
if ((latency = i->total_latency ()) > max_latency) {
max_latency = latency;
}
}
@ -2047,7 +2047,7 @@ IO::input_latency () const
/* io lock not taken - must be protected by other means */
for (PortSet::const_iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
if ((latency = _session.engine().get_port_total_latency (*i)) > max_latency) {
if ((latency = i->total_latency ()) > max_latency) {
max_latency = latency;
}
}
@ -2473,7 +2473,7 @@ IO::find_input_port_hole (const char* base)
snprintf (buf, jack_port_name_size(), _("%s %u"), base, n);
for ( ; i != _inputs.end(); ++i) {
if (i->short_name() == buf) {
if (i->name() == buf) {
break;
}
}
@ -2506,7 +2506,7 @@ IO::find_output_port_hole (const char* base)
snprintf (buf, jack_port_name_size(), _("%s %u"), base, n);
for ( ; i != _outputs.end(); ++i) {
if (i->short_name() == buf) {
if (i->name() == buf) {
break;
}
}

View File

@ -1,82 +0,0 @@
/*
Copyright (C) 2006 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 <cassert>
#include <ardour/audioengine.h>
#include <ardour/jack_audio_port.h>
using namespace ARDOUR;
JackAudioPort::JackAudioPort (const std::string& name, Flags flgs, AudioBuffer* buf)
: Port (name, flgs)
, JackPort (name, DataType::AUDIO, flgs)
, BaseAudioPort (name, flgs)
, _has_been_mixed_down( false )
{
if (buf) {
_buffer = buf;
_own_buffer = false;
} else {
/* data space will be provided by JACK */
_buffer = new AudioBuffer (0);
_own_buffer = true;
}
}
int
JackAudioPort::reestablish ()
{
int ret = JackPort::reestablish ();
if (ret == 0 && _flags & IsOutput) {
_buffer->clear ();
}
return ret;
}
AudioBuffer&
JackAudioPort::get_audio_buffer (nframes_t nframes, nframes_t offset) {
assert (_buffer);
if (_has_been_mixed_down)
return *_buffer;
if( _flags & IsInput )
_buffer->set_data ((Sample*) jack_port_get_buffer (_port, nframes), nframes+offset);
if (nframes)
_has_been_mixed_down = true;
return *_buffer;
}
void
JackAudioPort::cycle_start (nframes_t nframes, nframes_t offset) {
if( _flags & IsOutput )
_buffer->set_data ((Sample*) jack_port_get_buffer (_port, nframes), nframes+offset);
}
void
JackAudioPort::cycle_end (nframes_t nframes, nframes_t offset) {
_has_been_mixed_down=false;
}

View File

@ -1,141 +0,0 @@
/*
Copyright (C) 2006 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 <cassert>
#include <ardour/jack_midi_port.h>
using namespace ARDOUR;
JackMidiPort::JackMidiPort (const std::string& name, Flags flgs, MidiBuffer* buf)
: Port (name, flgs)
, JackPort (name, DataType::MIDI, flgs)
, BaseMidiPort (name, flgs)
, _has_been_mixed_down (false)
{
// MIDI ports always need a buffer since jack buffer format is different
assert(buf);
_buffer = buf;
_own_buffer = false;
}
void
JackMidiPort::cycle_start (nframes_t nframes, nframes_t offset)
{
/* FIXME: offset */
_buffer->clear();
assert(_buffer->size() == 0);
if (_flags & IsInput) {
return;
}
// We're an output - delete the midi_events.
void* jack_buffer = jack_port_get_buffer (_port, nframes);
jack_midi_clear_buffer (jack_buffer);
}
MidiBuffer &
JackMidiPort::get_midi_buffer( nframes_t nframes, nframes_t offset ) {
if (_has_been_mixed_down)
return *_buffer;
if (_flags & IsOutput) {
return *_buffer;
}
// We're an input - copy Jack events to internal buffer
void* jack_buffer = jack_port_get_buffer(_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);
}
assert(_buffer->size() == event_count);
/*if (_buffer->size() > 0)
cerr << "JackMIDIPort got " << event_count << " events (buf " << _buffer << ")" << endl;*/
if (nframes)
_has_been_mixed_down = true;
return *_buffer;
}
void
JackMidiPort::cycle_end (nframes_t nframes, nframes_t offset)
{
/* FIXME: offset */
_has_been_mixed_down = false;
#if 0
if (_flags & IsInput) {
return;
}
// We're an output - copy events from source buffer to Jack buffer
void* jack_buffer = jack_port_get_buffer (_port, nframes);
jack_midi_clear_buffer (jack_buffer);
for (MidiBuffer::iterator i = _buffer->begin(); i != _buffer->end(); ++i) {
const Evoral::Event& ev = *i;
// event times should be frames, relative to cycle start
assert(ev.time() >= 0);
assert(ev.time() < nframes);
jack_midi_event_write (jack_buffer, (jack_nframes_t) ev.time(), ev.buffer(), ev.size());
}
#endif
}
void
JackMidiPort::flush_buffers (nframes_t nframes, nframes_t offset)
{
/* FIXME: offset */
if (_flags & IsInput) {
return;
}
void* jack_buffer = jack_port_get_buffer (_port, nframes);
for (MidiBuffer::iterator i = _buffer->begin(); i != _buffer->end(); ++i) {
const Evoral::Event& ev = *i;
// event times should be frames, relative to cycle start
assert(ev.time() >= 0);
assert(ev.time() < (nframes+offset));
if (ev.time() >= offset)
jack_midi_event_write (jack_buffer, (jack_nframes_t) ev.time(), ev.buffer(), ev.size());
}
}

View File

@ -1,179 +0,0 @@
/*
Copyright (C) 2002-2006 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 <pbd/error.h>
#include <ardour/jack_port.h>
#include <ardour/audioengine.h>
#include "i18n.h"
using namespace ARDOUR;
using namespace PBD;
using namespace std;
JackPort::JackPort (const std::string& name, DataType type, Flags flgs)
: Port (name, flgs), _port (0)
{
_port = jack_port_register (engine->jack(), name.c_str(), type.to_jack_type(), flgs, 0);
if (_port == 0) {
throw failed_constructor();
}
_flags = flgs;
_type = type;
_name = jack_port_name (_port);
}
JackPort::~JackPort ()
{
cerr << "deleting jack port " << _name << endl;
jack_port_unregister (engine->jack(), _port);
}
int
JackPort::set_name (const string& str)
{
int ret;
if ((ret = jack_port_set_name (_port, str.c_str())) == 0) {
_name = str;
}
return ret;
}
int
JackPort::disconnect ()
{
return jack_port_disconnect (engine->jack(), _port);
}
nframes_t
JackPort::total_latency () const
{
return jack_port_get_total_latency (engine->jack(), _port);
}
int
JackPort::reestablish ()
{
string short_name;
short_name = _name.substr (_name.find_last_of (':') + 1);
_port = jack_port_register (engine->jack(), short_name.c_str(), type().to_jack_type(), _flags, 0);
if (_port == 0) {
error << string_compose (_("could not reregister %1"), _name) << endmsg;
return -1;
}
reset ();
return 0;
}
void
JackPort::recompute_total_latency () const
{
#ifdef HAVE_JACK_RECOMPUTE_LATENCY
jack_recompute_total_latency (engine->jack(), _port);
#endif
}
int
JackPort::reconnect ()
{
/* caller must hold process lock; intended to be used only after reestablish() */
for (set<string>::iterator i = _named_connections.begin(); i != _named_connections.end(); ++i) {
if (connect (*i)) {
return -1;
}
}
return 0;
}
int
JackPort::connect (const std::string& other)
{
int ret;
if (_flags & IsOutput) {
/* this is the source */
ret = jack_connect (engine->jack(), _name.c_str(), other.c_str());
} else {
ret = jack_connect (engine->jack(), other.c_str(), _name.c_str());
}
if (ret == 0) {
_named_connections.insert (other);
}
return ret;
}
int
JackPort::disconnect (const std::string& other)
{
int ret;
if (_flags & IsInput) {
ret = jack_disconnect (engine->jack(), other.c_str(), _name.c_str());
} else {
ret = jack_disconnect (engine->jack(), _name.c_str(), other.c_str());
}
set<string>::iterator i = _named_connections.find (other);
if (i != _named_connections.end()) {
_named_connections.erase (i);
}
return ret;
}
int
JackPort::disconnect_all ()
{
_named_connections.clear ();
return jack_port_disconnect (engine->jack(), _port);
}
int
JackPort::get_connections (vector<string>& names) const
{
const char** cstrs = jack_port_get_connections (_port);
int i;
if (!cstrs) {
return 0;
}
for (i = 0; cstrs[i]; ++i) {
names.push_back (string (cstrs[i]));
}
return i;
}

View File

@ -23,8 +23,9 @@
#include <ardour/peak.h>
#include <ardour/dB.h>
#include <ardour/session.h>
#include <ardour/audio_buffer.h>
#include <ardour/midi_buffer.h>
#include <ardour/audio_buffer.h>
#include <ardour/runtime_functions.h>
namespace ARDOUR {

View File

@ -20,76 +20,74 @@
#include <iostream>
#include <ardour/midi_port.h>
#include <ardour/jack_midi_port.h>
#include <ardour/data_type.h>
using namespace ARDOUR;
using namespace std;
MidiPort::MidiPort (const std::string& name, Flags flags, bool external, nframes_t capacity)
: Port (name, flags)
, BaseMidiPort (name, flags)
, PortFacade (name, flags)
MidiPort::MidiPort (const std::string& name, Flags flags, bool ext, nframes_t capacity)
: Port (name, DataType::MIDI, flags, ext)
, _has_been_mixed_down (false)
{
// FIXME: size kludge (see BufferSet::ensure_buffers)
// Jack needs to tell us this
_buffer = new MidiBuffer (capacity * 8);
if (external) {
/* external ports use the same buffer for the jack port (_ext_port)
* and internal ports (this) */
_ext_port = new JackMidiPort (name, flags, _buffer);
Port::set_name (_ext_port->name());
} else {
/* internal ports just have a single buffer, no jack port */
_ext_port = 0;
set_name (name);
}
reset ();
}
MidiPort::~MidiPort()
{
delete _ext_port;
_ext_port = 0;
delete _buffer;
}
void
MidiPort::reset()
{
BaseMidiPort::reset();
if (_ext_port) {
_ext_port->reset ();
}
}
void
MidiPort::cycle_start (nframes_t nframes, nframes_t offset)
{
if (_ext_port) {
_ext_port->cycle_start (nframes, offset);
if (external ()) {
_buffer->clear ();
assert (_buffer->size () == 0);
if (sends_output ()) {
jack_midi_clear_buffer (jack_port_get_buffer (_jack_port, nframes));
}
}
}
MidiBuffer &
MidiPort::get_midi_buffer( nframes_t nframes, nframes_t offset ) {
if (_has_been_mixed_down)
if (_has_been_mixed_down) {
return *_buffer;
}
if (_flags & IsInput) {
if (receives_input ()) {
if (_ext_port) {
if (external ()) {
BaseMidiPort* mprt = dynamic_cast<BaseMidiPort*>(_ext_port);
assert(mprt);
assert(&mprt->get_midi_buffer(nframes,offset) == _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);
}
assert(_buffer->size() == event_count);
if (nframes) {
_has_been_mixed_down = true;
}
if (!_connections.empty()) {
(*_mixdown) (_connections, _buffer, nframes, offset, false);
mixdown (nframes, offset, false);
}
} else {
@ -97,15 +95,17 @@ MidiPort::get_midi_buffer( nframes_t nframes, nframes_t offset ) {
if (_connections.empty()) {
_buffer->silence (nframes, offset);
} else {
(*_mixdown) (_connections, _buffer, nframes, offset, true);
mixdown (nframes, offset, true);
}
}
} else {
_buffer->silence (nframes, offset);
}
if (nframes)
if (nframes) {
_has_been_mixed_down = true;
}
return *_buffer;
}
@ -114,16 +114,65 @@ MidiPort::get_midi_buffer( nframes_t nframes, nframes_t offset ) {
void
MidiPort::cycle_end (nframes_t nframes, nframes_t offset)
{
if (_ext_port) {
_ext_port->cycle_end (nframes, offset);
#if 0
if (external () && sends_output ()) {
/* FIXME: offset */
// We're an output - copy events from source buffer to Jack buffer
void* jack_buffer = jack_port_get_buffer (_jack_port, nframes);
jack_midi_clear_buffer (jack_buffer);
for (MidiBuffer::iterator i = _buffer->begin(); i != _buffer->end(); ++i) {
const Evoral::Event& ev = *i;
// event times should be frames, relative to cycle start
assert(ev.time() >= 0);
assert(ev.time() < nframes);
jack_midi_event_write (jack_buffer, (jack_nframes_t) ev.time(), ev.buffer(), ev.size());
}
}
#endif
_has_been_mixed_down = false;
}
void
MidiPort::flush_buffers (nframes_t nframes, nframes_t offset)
{
if (_ext_port) {
_ext_port->flush_buffers (nframes, offset);
/* FIXME: offset */
if (external () && sends_output ()) {
void* jack_buffer = jack_port_get_buffer (_jack_port, nframes);
for (MidiBuffer::iterator i = _buffer->begin(); i != _buffer->end(); ++i) {
const Evoral::Event& ev = *i;
// event times should be frames, relative to cycle start
assert(ev.time() >= 0);
assert(ev.time() < (nframes+offset));
if (ev.time() >= offset) {
jack_midi_event_write (jack_buffer, (jack_nframes_t) ev.time(), ev.buffer(), ev.size());
}
}
}
}
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

@ -21,6 +21,7 @@
#include <ardour/types.h>
#include <ardour/utils.h>
#include <ardour/mix.h>
#include <ardour/runtime_functions.h>
#include <stdint.h>
using namespace ARDOUR;

View File

@ -44,6 +44,7 @@
#include <ardour/runtime_functions.h>
#include <ardour/buffer_set.h>
#include <ardour/audio_buffer.h>
#include "i18n.h"

View File

@ -31,6 +31,7 @@
#include <ardour/ladspa_plugin.h>
#include <ardour/buffer_set.h>
#include <ardour/automation_list.h>
#include <ardour/audio_buffer.h>
#ifdef HAVE_SLV2
#include <ardour/lv2_plugin.h>

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2002-2006 Paul Davis
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
@ -17,101 +17,111 @@
*/
#include <ardour/port.h>
#include "ardour/port.h"
#include "ardour/audioengine.h"
#include "ardour/i18n.h"
#include "pbd/failed_constructor.h"
#include "pbd/error.h"
#include "pbd/compose.h"
#include <stdexcept>
using namespace ARDOUR;
using namespace std;
ARDOUR::AudioEngine* ARDOUR::Port::_engine = 0;
AudioEngine* Port::engine = 0;
Port::Port (const std::string& name, Flags flgs)
: _flags (flgs)
, _name (name)
, _metering (0)
, _last_monitor (false)
ARDOUR::Port::Port (std::string const & n, DataType t, Flags f, bool e) : _jack_port (0), _last_monitor (false), _latency (0), _name (n), _flags (f)
{
}
Port::~Port ()
{
drop_references ();
disconnect_all ();
}
void
Port::reset ()
{
_last_monitor = false;
}
void
Port::set_engine (AudioEngine* e)
{
engine = e;
}
int
Port::connect (Port& other)
{
/* caller must hold process lock */
pair<set<Port*>::iterator,bool> result;
result = _connections.insert (&other);
if (result.second) {
other.GoingAway.connect (sigc::bind (mem_fun (*this, &Port::port_going_away), &other));
return 0;
} else {
return 1;
}
}
int
Port::disconnect (Port& other)
{
/* caller must hold process lock */
/* Unfortunately we have to pass the DataType into this constructor so that we can
create the right kind of JACK port; aside from this we'll use the virtual function type ()
to establish type. */
for (set<Port*>::iterator i = _connections.begin(); i != _connections.end(); ++i) {
if ((*i) == &other) {
_connections.erase (i);
return 0;
if (e) {
try {
do_make_external (t);
}
catch (...) {
throw failed_constructor ();
}
}
return -1;
}
/** Port destructor */
ARDOUR::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
ARDOUR::Port::do_make_external (DataType t)
{
if (_jack_port) {
/* already external */
return;
}
_jack_port = jack_port_register (_engine->jack (), _name.c_str (), t.to_jack_type (), _flags, 0);
if (_jack_port == 0) {
throw std::runtime_error ("Could not register JACK port");
}
}
void
ARDOUR::Port::make_external ()
{
do_make_external (type ());
}
/** @return true if this port is connected to anything */
bool
ARDOUR::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);
}
int
Port::disconnect_all ()
ARDOUR::Port::disconnect_all ()
{
/* caller must hold process lock */
/* 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 ();
return 0;
}
void
Port::set_latency (nframes_t val)
{
_latency = val;
}
/** @param o Port name
* @return true if this port is connected to o, otherwise false.
*/
bool
Port::connected() const
ARDOUR::Port::connected_to (std::string const & o) const
{
/* caller must hold process lock */
return !_connections.empty();
}
if (_jack_port && jack_port_connected_to (_jack_port, o.c_str ())) {
/* connected via JACK */
return true;
}
bool
Port::connected_to (const string& portname) const
{
/* caller must hold process lock */
for (set<Port*>::const_iterator p = _connections.begin(); p != _connections.end(); ++p) {
if ((*p)->name() == portname) {
for (std::set<Port*>::iterator i = _connections.begin (); i != _connections.end (); ++i) {
if ((*i)->name () == o) {
/* connected internally */
return true;
}
}
@ -120,271 +130,259 @@ Port::connected_to (const string& portname) const
}
int
Port::get_connections (vector<string>& names) const
ARDOUR::Port::get_connections (std::vector<std::string> & c) const
{
/* caller must hold process lock */
int i = 0;
set<Port*>::const_iterator p;
int n = 0;
for (i = 0, p = _connections.begin(); p != _connections.end(); ++p, ++i) {
names.push_back ((*p)->name());
}
return i;
}
void
Port::port_going_away (Port* p)
{
/* caller must hold process lock */
disconnect (*p);
}
//-------------------------------------
int
PortFacade::set_name (const std::string& str)
{
int ret;
if (_ext_port) {
if ((ret = _ext_port->set_name (str)) == 0) {
_name = _ext_port->name();
/* 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;
}
}
} else {
_name = str;
ret = 0;
}
return ret;
}
string
PortFacade::short_name () const
{
if (_ext_port) {
return _ext_port->short_name();
} else {
return _name;
/* Internal connections */
for (std::set<Port*>::iterator i = _connections.begin (); i != _connections.end (); ++i) {
c.push_back ((*i)->name ());
++n;
}
}
return n;
}
int
PortFacade::reestablish ()
ARDOUR::Port::connect (std::string const & other)
{
if (_ext_port) {
return _ext_port->reestablish ();
/* caller must hold process lock */
Port* p = _engine->get_port_by_name_locked (other);
int r;
if (p && !p->external ()) {
/* non-external Ardour port; connect using Port* */
r = connect (p);
} else {
return 0;
/* connect using name */
/* for this to work, we must be an external port */
if (!external ()) {
make_external ();
}
std::string const this_nr = _engine->make_port_name_non_relative (_name);
std::string const other_nr = _engine->make_port_name_non_relative (other);
if (sends_output ()) {
r = jack_connect (_engine->jack (), this_nr.c_str (), other_nr.c_str ());
} else {
r = jack_connect (_engine->jack (), other_nr.c_str (), this_nr.c_str());
}
if (r == 0) {
_named_connections.insert (other);
}
}
return r;
}
int
ARDOUR::Port::disconnect (std::string const & other)
{
/* caller must hold process lock */
Port* p = _engine->get_port_by_name_locked (other);
int r;
if (p && !p->external ()) {
/* non-external Ardour port; disconnect using Port* */
r = disconnect (p);
} else {
/* disconnect using name */
std::string const this_nr = _engine->make_port_name_non_relative (_name);
std::string const other_nr = _engine->make_port_name_non_relative (other);
if (sends_output ()) {
r = jack_disconnect (_engine->jack (), this_nr.c_str (), other_nr.c_str ());
} else {
r = jack_disconnect (_engine->jack (), other_nr.c_str (), this_nr.c_str ());
}
if (r == 0) {
_named_connections.erase (other);
}
}
return r;
}
int
PortFacade::reconnect()
bool
ARDOUR::Port::connected_to (Port *o) const
{
if (_ext_port) {
return _ext_port->reconnect ();
} else {
return 0;
return connected_to (o->name ());
}
int
ARDOUR::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);
return 0;
}
int
ARDOUR::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);
return 0;
}
void
PortFacade::set_latency (nframes_t val)
ARDOUR::Port::set_engine (AudioEngine* e)
{
if (_ext_port) {
_ext_port->set_latency (val);
} else {
_latency = val;
}
_engine = e;
}
nframes_t
PortFacade::latency() const
void
ARDOUR::Port::ensure_monitor_input (bool yn)
{
if (_ext_port) {
return _ext_port->latency();
} else {
return _latency;
}
}
nframes_t
PortFacade::total_latency() const
{
if (_ext_port) {
return _ext_port->total_latency();
} else {
return _latency;
if (_jack_port) {
jack_port_ensure_monitor (_jack_port, yn);
}
}
bool
PortFacade::monitoring_input() const
ARDOUR::Port::monitoring_input () const
{
if (_ext_port) {
return _ext_port->monitoring_input ();
if (_jack_port) {
return jack_port_monitoring_input (_jack_port);
} else {
return false;
}
}
void
PortFacade::ensure_monitor_input (bool yn)
ARDOUR::Port::reset ()
{
if (_ext_port) {
_ext_port->ensure_monitor_input (yn);
}
_last_monitor = false;
// XXX
// _metering = 0;
// reset_meters ();
}
void
PortFacade::request_monitor_input (bool yn)
ARDOUR::Port::recompute_total_latency () const
{
if (_ext_port) {
_ext_port->request_monitor_input (yn);
}
#ifdef HAVE_JACK_RECOMPUTE_LATENCY
if (_jack_port) {
jack_recompute_total_latency (_engine->jack (), _jack_port);
}
#endif
}
nframes_t
ARDOUR::Port::total_latency () const
{
if (_jack_port) {
return jack_port_get_total_latency (_engine->jack (), _jack_port);
} else {
return _latency;
}
}
int
PortFacade::connect (Port& other)
ARDOUR::Port::reestablish ()
{
int ret;
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) {
PBD::error << string_compose (_("could not reregister %1"), _name) << endmsg;
return -1;
}
reset ();
return 0;
}
int
ARDOUR::Port::reconnect ()
{
/* caller must hold process lock; intended to be used only after reestablish() */
if (!_jack_port) {
return 0;
}
if (_ext_port) {
ret = _ext_port->connect (other);
} else {
ret = 0;
for (std::set<string>::iterator i = _named_connections.begin(); i != _named_connections.end(); ++i) {
if (connect (*i)) {
return -1;
}
}
if (ret == 0) {
ret = Port::connect (other);
}
return ret;
}
int
PortFacade::connect (const std::string& other)
{
PortConnectableByName* pcn;
if (!_ext_port) {
return -1;
}
pcn = dynamic_cast<PortConnectableByName*>(_ext_port);
if (pcn) {
return pcn->connect (other);
} else {
return -1;
}
return 0;
}
int
PortFacade::disconnect (Port& other)
ARDOUR::Port::set_name (std::string const & n)
{
int reta;
int retb;
int r = 0;
if (_ext_port) {
reta = _ext_port->disconnect (other);
if (_jack_port) {
r = jack_port_set_name (_jack_port, n.c_str());
if (r) {
_name = n;
}
} else {
reta = 0;
_name = n;
}
retb = Port::disconnect (other);
return reta || retb;
}
int
PortFacade::disconnect_all ()
{
int reta = 0;
int retb = 0;
if (_ext_port) {
reta = _ext_port->disconnect_all ();
}
retb = Port::disconnect_all ();
return reta || retb;
}
int
PortFacade::disconnect (const std::string& other)
{
PortConnectableByName* pcn;
if (!_ext_port) {
return -1;
}
pcn = dynamic_cast<PortConnectableByName*>(_ext_port);
if (pcn) {
return pcn->disconnect (other);
} else {
return -1;
}
}
bool
PortFacade::connected () const
{
if (Port::connected()) {
return true;
}
if (_ext_port) {
return _ext_port->connected();
}
return false;
}
bool
PortFacade::connected_to (const std::string& portname) const
{
if (Port::connected_to (portname)) {
return true;
}
if (_ext_port) {
return _ext_port->connected_to (portname);
}
return false;
}
int
PortFacade::get_connections (vector<string>& names) const
{
int i = 0;
if (_ext_port) {
i = _ext_port->get_connections (names);
}
i += Port::get_connections (names);
return i;
return r;
}
void
PortFacade::reset ()
ARDOUR::Port::set_latency (nframes_t n)
{
Port::reset ();
if (_ext_port) {
_ext_port->reset ();
}
_latency = n;
}
void
ARDOUR::Port::request_monitor_input (bool yn)
{
if (_jack_port) {
jack_port_request_monitor (_jack_port, yn);
}
}

View File

@ -17,6 +17,8 @@
*/
#include <ardour/port_set.h>
#include <ardour/midi_port.h>
#include <ardour/audio_port.h>
namespace ARDOUR {

View File

@ -81,6 +81,7 @@
#include <ardour/session_directory.h>
#include <ardour/tape_file_matcher.h>
#include <ardour/analyser.h>
#include <ardour/audio_buffer.h>
#include <ardour/bundle.h>
#include "i18n.h"

View File

@ -25,6 +25,7 @@
#include <ardour/tempo.h>
#include <ardour/io.h>
#include <ardour/buffer_set.h>
#include <ardour/audio_buffer.h>
#include <sndfile.h>

View File

@ -31,6 +31,7 @@
#include <ardour/audioplaylist.h>
#include <ardour/panner.h>
#include <ardour/utils.h>
#include <ardour/port.h>
#include "i18n.h"