mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-16 11:46:25 +01:00
new internal port type, round I, plus tiny fix for legalize_for_xml() (also for 2.0-ongoing)
git-svn-id: svn://localhost/ardour2/trunk@2559 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
df28e90c67
commit
239ec39da6
18 changed files with 546 additions and 48 deletions
|
|
@ -1694,7 +1694,7 @@ static string
|
||||||
legalize_for_xml_node (string str)
|
legalize_for_xml_node (string str)
|
||||||
{
|
{
|
||||||
string::size_type pos;
|
string::size_type pos;
|
||||||
string legal_chars = "abcdefghijklmnopqrtsuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_+=:";
|
string legal_chars = "abcdefghijklmnopqrtsuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_=:";
|
||||||
string legal;
|
string legal;
|
||||||
|
|
||||||
legal = str;
|
legal = str;
|
||||||
|
|
|
||||||
|
|
@ -65,6 +65,8 @@ gain.cc
|
||||||
gdither.cc
|
gdither.cc
|
||||||
globals.cc
|
globals.cc
|
||||||
import.cc
|
import.cc
|
||||||
|
internal_port.cc
|
||||||
|
internal_audio_port.cc
|
||||||
io.cc
|
io.cc
|
||||||
io_processor.cc
|
io_processor.cc
|
||||||
jack_port.cc
|
jack_port.cc
|
||||||
|
|
|
||||||
|
|
@ -102,6 +102,12 @@ public:
|
||||||
_silent = false;
|
_silent = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Reallocate the buffer used internally to handle at least @nframes of data
|
||||||
|
*
|
||||||
|
* Constructor MUST have been passed capacity!=0 or this will die (to prevent mem leaks).
|
||||||
|
*/
|
||||||
|
void resize (size_t nframes);
|
||||||
|
|
||||||
const Sample* data () const { return _data; }
|
const Sample* data () const { return _data; }
|
||||||
Sample* data () { return _data; }
|
Sample* data () { return _data; }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -35,11 +35,11 @@ class AudioPort : public virtual Port {
|
||||||
public:
|
public:
|
||||||
DataType type() const { return DataType::AUDIO; }
|
DataType type() const { return DataType::AUDIO; }
|
||||||
|
|
||||||
Buffer& get_buffer () {
|
virtual Buffer& get_buffer () {
|
||||||
return _buffer;
|
return _buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioBuffer& get_audio_buffer() {
|
virtual AudioBuffer& get_audio_buffer() {
|
||||||
return _buffer;
|
return _buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -70,7 +70,8 @@ class AudioPort : public virtual Port {
|
||||||
protected:
|
protected:
|
||||||
friend class AudioEngine;
|
friend class AudioEngine;
|
||||||
|
|
||||||
AudioPort ();
|
AudioPort (); // data buffer comes from elsewhere (e.g. JACK)
|
||||||
|
AudioPort (nframes_t); // data buffer owned by ardour
|
||||||
void reset ();
|
void reset ();
|
||||||
|
|
||||||
/* engine isn't supposed to access below here */
|
/* engine isn't supposed to access below here */
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@ namespace ARDOUR {
|
||||||
|
|
||||||
class Session;
|
class Session;
|
||||||
class Port;
|
class Port;
|
||||||
|
class InternalPort;
|
||||||
|
|
||||||
class AudioEngine : public sigc::trackable
|
class AudioEngine : public sigc::trackable
|
||||||
{
|
{
|
||||||
|
|
@ -113,8 +114,8 @@ class AudioEngine : public sigc::trackable
|
||||||
virtual const char *what() const throw() { return "could not connect to engine backend"; }
|
virtual const char *what() const throw() { return "could not connect to engine backend"; }
|
||||||
};
|
};
|
||||||
|
|
||||||
Port *register_input_port (DataType type, const std::string& portname);
|
Port *register_input_port (PortType, DataType, const std::string& portname);
|
||||||
Port *register_output_port (DataType type, const std::string& portname);
|
Port *register_output_port (PortType, DataType, const std::string& portname);
|
||||||
int unregister_port (Port &);
|
int unregister_port (Port &);
|
||||||
|
|
||||||
int connect (const std::string& source, const std::string& destination);
|
int connect (const std::string& source, const std::string& destination);
|
||||||
|
|
@ -219,11 +220,13 @@ class AudioEngine : public sigc::trackable
|
||||||
|
|
||||||
SerializedRCUManager<Ports> ports;
|
SerializedRCUManager<Ports> ports;
|
||||||
|
|
||||||
Port *register_port (DataType type, const std::string& portname, bool input);
|
Port *register_port (PortType ptype, DataType type, const std::string& portname, bool input);
|
||||||
|
|
||||||
int process_callback (nframes_t nframes);
|
int process_callback (nframes_t nframes);
|
||||||
void remove_all_ports ();
|
void remove_all_ports ();
|
||||||
|
|
||||||
|
InternalPort* get_internal_port (const std::string& short_name);
|
||||||
|
|
||||||
typedef std::pair<std::string,std::string> PortConnection;
|
typedef std::pair<std::string,std::string> PortConnection;
|
||||||
typedef std::list<PortConnection> PortConnections;
|
typedef std::list<PortConnection> PortConnections;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,13 @@ public:
|
||||||
DataType type() const { return _type; }
|
DataType type() const { return _type; }
|
||||||
|
|
||||||
bool silent() const { return _silent; }
|
bool silent() const { return _silent; }
|
||||||
|
|
||||||
|
/** Reallocate the buffer used internally to handle at least @a size_t units of data.
|
||||||
|
*
|
||||||
|
* The buffer is not silent after this operation. the @a capacity argument
|
||||||
|
* passed to the constructor must have been non-zero.
|
||||||
|
*/
|
||||||
|
virtual void resize(size_t) = 0;
|
||||||
|
|
||||||
/** Clear (eg zero, or empty) buffer starting at TIME @a offset */
|
/** Clear (eg zero, or empty) buffer starting at TIME @a offset */
|
||||||
virtual void silence(nframes_t len, nframes_t offset=0) = 0;
|
virtual void silence(nframes_t len, nframes_t offset=0) = 0;
|
||||||
|
|
|
||||||
55
libs/ardour/ardour/internal_audio_port.h
Normal file
55
libs/ardour/ardour/internal_audio_port.h
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
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__ */
|
||||||
82
libs/ardour/ardour/internal_port.h
Normal file
82
libs/ardour/ardour/internal_port.h
Normal file
|
|
@ -0,0 +1,82 @@
|
||||||
|
/*
|
||||||
|
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__ */
|
||||||
|
|
@ -42,6 +42,8 @@ public:
|
||||||
bool push_back(const ARDOUR::MidiEvent& event);
|
bool push_back(const ARDOUR::MidiEvent& event);
|
||||||
bool push_back(const jack_midi_event_t& event);
|
bool push_back(const jack_midi_event_t& event);
|
||||||
Byte* reserve(double time, size_t size);
|
Byte* reserve(double time, size_t size);
|
||||||
|
|
||||||
|
void resize(size_t);
|
||||||
|
|
||||||
bool merge(const MidiBuffer& a, const MidiBuffer& b);
|
bool merge(const MidiBuffer& a, const MidiBuffer& b);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -379,6 +379,11 @@ namespace ARDOUR {
|
||||||
SrcFastest
|
SrcFastest
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum PortType {
|
||||||
|
Jack,
|
||||||
|
Internal
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace ARDOUR
|
} // namespace ARDOUR
|
||||||
|
|
||||||
std::istream& operator>>(std::istream& o, ARDOUR::SampleFormat& sf);
|
std::istream& operator>>(std::istream& o, ARDOUR::SampleFormat& sf);
|
||||||
|
|
|
||||||
|
|
@ -29,19 +29,13 @@ namespace ARDOUR {
|
||||||
|
|
||||||
AudioBuffer::AudioBuffer(size_t capacity)
|
AudioBuffer::AudioBuffer(size_t capacity)
|
||||||
: Buffer(DataType::AUDIO, capacity)
|
: Buffer(DataType::AUDIO, capacity)
|
||||||
, _owns_data(false)
|
, _owns_data (false)
|
||||||
, _data(NULL)
|
, _data (0)
|
||||||
{
|
{
|
||||||
_size = capacity; // For audio buffers, size = capacity (always)
|
if (_capacity) {
|
||||||
if (capacity > 0) {
|
_owns_data = true; // prevent resize() from gagging
|
||||||
#ifdef NO_POSIX_MEMALIGN
|
resize (_capacity);
|
||||||
_data = (Sample *) malloc(sizeof(Sample) * capacity);
|
silence (_capacity);
|
||||||
#else
|
|
||||||
posix_memalign((void**)&_data, CPU_CACHE_ALIGN, sizeof(Sample) * capacity);
|
|
||||||
#endif
|
|
||||||
assert(_data);
|
|
||||||
_owns_data = true;
|
|
||||||
clear();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -51,6 +45,31 @@ AudioBuffer::~AudioBuffer()
|
||||||
free(_data);
|
free(_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
AudioBuffer::resize (size_t size)
|
||||||
|
{
|
||||||
|
assert (_owns_data);
|
||||||
|
|
||||||
|
if (size < _capacity) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_data) {
|
||||||
|
free (_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
_capacity = size;
|
||||||
|
_size = size;
|
||||||
|
_silent = false;
|
||||||
|
|
||||||
|
#ifdef NO_POSIX_MEMALIGN
|
||||||
|
_data = (Sample *) malloc(sizeof(Sample) * _capacity);
|
||||||
|
#else
|
||||||
|
posix_memalign((void**)&_data, CPU_CACHE_ALIGN, sizeof(Sample) * _capacity);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
_owns_data = true;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ARDOUR
|
} // namespace ARDOUR
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,13 @@ AudioPort::AudioPort()
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AudioPort::AudioPort(nframes_t nframes)
|
||||||
|
: _buffer (nframes)
|
||||||
|
{
|
||||||
|
_type = DataType::AUDIO;
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
AudioPort::reset()
|
AudioPort::reset()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@
|
||||||
#include <ardour/buffer.h>
|
#include <ardour/buffer.h>
|
||||||
#include <ardour/port.h>
|
#include <ardour/port.h>
|
||||||
#include <ardour/jack_audio_port.h>
|
#include <ardour/jack_audio_port.h>
|
||||||
|
#include <ardour/internal_audio_port.h>
|
||||||
#include <ardour/jack_midi_port.h>
|
#include <ardour/jack_midi_port.h>
|
||||||
#include <ardour/session.h>
|
#include <ardour/session.h>
|
||||||
#include <ardour/cycle_timer.h>
|
#include <ardour/cycle_timer.h>
|
||||||
|
|
@ -508,17 +509,33 @@ AudioEngine::remove_session ()
|
||||||
}
|
}
|
||||||
|
|
||||||
Port *
|
Port *
|
||||||
AudioEngine::register_port (DataType type, const string& portname, bool input)
|
AudioEngine::register_port (PortType ptype, DataType dtype, const string& portname, bool input)
|
||||||
{
|
{
|
||||||
Port* newport = 0;
|
Port* newport = 0;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (type == DataType::AUDIO)
|
switch (ptype) {
|
||||||
newport = new JackAudioPort (portname, (input ? Port::IsInput : Port::IsOutput));
|
case Jack:
|
||||||
else if (type == DataType::MIDI)
|
if (dtype == DataType::AUDIO) {
|
||||||
newport = new JackMidiPort (portname, (input ? Port::IsInput : Port::IsOutput));
|
newport = new JackAudioPort (portname, (input ? Port::IsInput : Port::IsOutput));
|
||||||
else
|
} else if (dtype == DataType::MIDI) {
|
||||||
throw unknown_type();
|
newport = new JackMidiPort (portname, (input ? Port::IsInput : Port::IsOutput));
|
||||||
|
} else {
|
||||||
|
throw unknown_type();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Internal:
|
||||||
|
if (dtype == DataType::AUDIO) {
|
||||||
|
newport = new InternalAudioPort (portname, (input ? Port::IsInput : Port::IsOutput));
|
||||||
|
} else if (dtype == DataType::MIDI) {
|
||||||
|
error << _("Internal MIDI ports are not implemented yet!") << endmsg;
|
||||||
|
throw unknown_type();
|
||||||
|
} else {
|
||||||
|
throw unknown_type();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (newport != 0) {
|
if (newport != 0) {
|
||||||
RCUWriter<Ports> writer (ports);
|
RCUWriter<Ports> writer (ports);
|
||||||
|
|
@ -535,16 +552,30 @@ AudioEngine::register_port (DataType type, const string& portname, bool input)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Port *
|
InternalPort*
|
||||||
AudioEngine::register_input_port (DataType type, const string& portname)
|
AudioEngine::get_internal_port (const std::string& short_name)
|
||||||
{
|
{
|
||||||
return register_port (type, portname, true);
|
boost::shared_ptr<Ports> p = ports.reader();
|
||||||
|
|
||||||
|
for (Ports::iterator i = p->begin(); i != p->end(); ++i) {
|
||||||
|
if ((*i)->short_name() == short_name) {
|
||||||
|
return dynamic_cast<InternalPort*> (*i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Port *
|
||||||
|
AudioEngine::register_input_port (PortType ptype, DataType type, const string& portname)
|
||||||
|
{
|
||||||
|
return register_port (ptype, type, portname, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Port *
|
Port *
|
||||||
AudioEngine::register_output_port (DataType type, const string& portname)
|
AudioEngine::register_output_port (PortType ptype, DataType type, const string& portname)
|
||||||
{
|
{
|
||||||
return register_port (type, portname, false);
|
return register_port (ptype, type, portname, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
@ -565,7 +596,6 @@ AudioEngine::unregister_port (Port& port)
|
||||||
for (Ports::iterator i = ps->begin(); i != ps->end(); ++i) {
|
for (Ports::iterator i = ps->begin(); i != ps->end(); ++i) {
|
||||||
if ((*i) == &port) {
|
if ((*i) == &port) {
|
||||||
remove_connections_for (port);
|
remove_connections_for (port);
|
||||||
cerr << "eraseing " << (*i)->name() << endl;
|
|
||||||
delete *i;
|
delete *i;
|
||||||
ps->erase (i);
|
ps->erase (i);
|
||||||
break;
|
break;
|
||||||
|
|
@ -581,6 +611,8 @@ AudioEngine::unregister_port (Port& port)
|
||||||
int
|
int
|
||||||
AudioEngine::connect (const string& source, const string& destination)
|
AudioEngine::connect (const string& source, const string& destination)
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (!_running) {
|
if (!_running) {
|
||||||
if (!_has_run) {
|
if (!_has_run) {
|
||||||
fatal << _("connect called before engine was started") << endmsg;
|
fatal << _("connect called before engine was started") << endmsg;
|
||||||
|
|
@ -589,11 +621,26 @@ AudioEngine::connect (const string& source, const string& destination)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
string s = make_port_name_non_relative (source);
|
string s = make_port_name_non_relative (source);
|
||||||
string d = make_port_name_non_relative (destination);
|
string d = make_port_name_non_relative (destination);
|
||||||
|
|
||||||
|
if (source.substr (0, 9) == "internal:") {
|
||||||
|
if (destination.substr (0, 9) == "internal:") {
|
||||||
|
InternalPort* src = get_internal_port (source);
|
||||||
|
InternalPort* dst = get_internal_port (destination);
|
||||||
|
|
||||||
int ret = jack_connect (_jack, s.c_str(), d.c_str());
|
InternalPort::connect (*src, *dst);
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
ret = jack_connect (_jack, s.c_str(), d.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
pair<string,string> c (s, d);
|
pair<string,string> c (s, d);
|
||||||
|
|
@ -614,6 +661,8 @@ AudioEngine::connect (const string& source, const string& destination)
|
||||||
int
|
int
|
||||||
AudioEngine::disconnect (const string& source, const string& destination)
|
AudioEngine::disconnect (const string& source, const string& destination)
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (!_running) {
|
if (!_running) {
|
||||||
if (!_has_run) {
|
if (!_has_run) {
|
||||||
fatal << _("disconnect called before engine was started") << endmsg;
|
fatal << _("disconnect called before engine was started") << endmsg;
|
||||||
|
|
@ -626,7 +675,21 @@ AudioEngine::disconnect (const string& source, const string& destination)
|
||||||
string s = make_port_name_non_relative (source);
|
string s = make_port_name_non_relative (source);
|
||||||
string d = make_port_name_non_relative (destination);
|
string d = make_port_name_non_relative (destination);
|
||||||
|
|
||||||
int ret = jack_disconnect (_jack, s.c_str(), d.c_str());
|
if (source.substr (0, 9) == "internal:") {
|
||||||
|
if (destination.substr (0, 9) == "internal:") {
|
||||||
|
InternalPort* src = get_internal_port (source);
|
||||||
|
InternalPort* dst = get_internal_port (destination);
|
||||||
|
|
||||||
|
InternalPort::disconnect (*src, *dst);
|
||||||
|
ret = 0;
|
||||||
|
} else {
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
ret = jack_disconnect (_jack, s.c_str(), d.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
pair<string,string> c (s, d);
|
pair<string,string> c (s, d);
|
||||||
|
|
|
||||||
70
libs/ardour/internal_audio_port.cc
Normal file
70
libs/ardour/internal_audio_port.cc
Normal file
|
|
@ -0,0 +1,70 @@
|
||||||
|
/*
|
||||||
|
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 flgs)
|
||||||
|
: AudioPort (engine->frames_per_cycle())
|
||||||
|
, InternalPort (name, DataType::AUDIO, flgs)
|
||||||
|
{
|
||||||
|
_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;
|
||||||
|
}
|
||||||
164
libs/ardour/internal_port.cc
Normal file
164
libs/ardour/internal_port.cc
Normal file
|
|
@ -0,0 +1,164 @@
|
||||||
|
/*
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
set_name (str);
|
||||||
|
_type = type;
|
||||||
|
_flags = flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -602,7 +602,7 @@ IO::add_output_port (string destination, void* src, DataType type)
|
||||||
snprintf (name, sizeof (name), _("%s/out %u"), _name.c_str(), find_output_port_hole());
|
snprintf (name, sizeof (name), _("%s/out %u"), _name.c_str(), find_output_port_hole());
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((our_port = _session.engine().register_output_port (type, name)) == 0) {
|
if ((our_port = _session.engine().register_output_port (Jack, type, name)) == 0) {
|
||||||
error << string_compose(_("IO: cannot register output port %1"), name) << endmsg;
|
error << string_compose(_("IO: cannot register output port %1"), name) << endmsg;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
@ -713,7 +713,7 @@ IO::add_input_port (string source, void* src, DataType type)
|
||||||
snprintf (name, sizeof (name), _("%s/in %u"), _name.c_str(), find_input_port_hole());
|
snprintf (name, sizeof (name), _("%s/in %u"), _name.c_str(), find_input_port_hole());
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((our_port = _session.engine().register_input_port (type, name)) == 0) {
|
if ((our_port = _session.engine().register_input_port (Jack, type, name)) == 0) {
|
||||||
error << string_compose(_("IO: cannot register input port %1"), name) << endmsg;
|
error << string_compose(_("IO: cannot register input port %1"), name) << endmsg;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
@ -822,7 +822,7 @@ IO::ensure_inputs_locked (ChanCount count, bool clear, void* src)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
if ((input_port = _session.engine().register_input_port (*t, buf)) == 0) {
|
if ((input_port = _session.engine().register_input_port (Jack, *t, buf)) == 0) {
|
||||||
error << string_compose(_("IO: cannot register input port %1"), buf) << endmsg;
|
error << string_compose(_("IO: cannot register input port %1"), buf) << endmsg;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
@ -938,7 +938,7 @@ IO::ensure_io (ChanCount in, ChanCount out, bool clear, void* src)
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if ((port = _session.engine().register_input_port (*t, buf)) == 0) {
|
if ((port = _session.engine().register_input_port (Jack, *t, buf)) == 0) {
|
||||||
error << string_compose(_("IO: cannot register input port %1"), buf) << endmsg;
|
error << string_compose(_("IO: cannot register input port %1"), buf) << endmsg;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
@ -970,7 +970,7 @@ IO::ensure_io (ChanCount in, ChanCount out, bool clear, void* src)
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if ((port = _session.engine().register_output_port (*t, buf)) == 0) {
|
if ((port = _session.engine().register_output_port (Jack, *t, buf)) == 0) {
|
||||||
error << string_compose(_("IO: cannot register output port %1"), buf) << endmsg;
|
error << string_compose(_("IO: cannot register output port %1"), buf) << endmsg;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
@ -1090,7 +1090,7 @@ IO::ensure_outputs_locked (ChanCount count, bool clear, void* src)
|
||||||
snprintf (buf, sizeof (buf), _("%s/out %u"), _name.c_str(), find_output_port_hole());
|
snprintf (buf, sizeof (buf), _("%s/out %u"), _name.c_str(), find_output_port_hole());
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((output_port = _session.engine().register_output_port (*t, buf)) == 0) {
|
if ((output_port = _session.engine().register_output_port (Jack, *t, buf)) == 0) {
|
||||||
error << string_compose(_("IO: cannot register output port %1"), buf) << endmsg;
|
error << string_compose(_("IO: cannot register output port %1"), buf) << endmsg;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -109,3 +109,4 @@ JackPort::recompute_total_latency () const
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -38,20 +38,31 @@ MidiBuffer::MidiBuffer(size_t capacity)
|
||||||
, _events(NULL)
|
, _events(NULL)
|
||||||
, _data(NULL)
|
, _data(NULL)
|
||||||
{
|
{
|
||||||
assert(capacity > 0);
|
_data = 0;
|
||||||
|
resize (_capacity);
|
||||||
|
silence(_capacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MidiBuffer::resize (size_t size)
|
||||||
|
{
|
||||||
|
assert(size > 0);
|
||||||
|
|
||||||
|
if (_data) {
|
||||||
|
free (_data);
|
||||||
|
}
|
||||||
|
|
||||||
_size = 0;
|
_size = 0;
|
||||||
|
_capacity = size;
|
||||||
#ifdef NO_POSIX_MEMALIGN
|
#ifdef NO_POSIX_MEMALIGN
|
||||||
_events = (MidiEvent *) malloc(sizeof(MidiEvent) * capacity);
|
_events = (MidiEvent *) malloc(sizeof(MidiEvent) * _capacity);
|
||||||
_data = (Byte *) malloc(sizeof(Byte) * capacity * MAX_EVENT_SIZE);
|
_data = (Byte *) malloc(sizeof(Byte) * _capacity * MAX_EVENT_SIZE);
|
||||||
#else
|
#else
|
||||||
posix_memalign((void**)&_events, CPU_CACHE_ALIGN, sizeof(MidiEvent) * capacity);
|
posix_memalign((void**)&_events, CPU_CACHE_ALIGN, sizeof(MidiEvent) * _capacity);
|
||||||
posix_memalign((void**)&_data, CPU_CACHE_ALIGN, sizeof(Byte) * capacity * MAX_EVENT_SIZE);
|
posix_memalign((void**)&_data, CPU_CACHE_ALIGN, sizeof(Byte) * _capacity * MAX_EVENT_SIZE);
|
||||||
#endif
|
#endif
|
||||||
assert(_data);
|
assert(_data);
|
||||||
assert(_events);
|
assert(_events);
|
||||||
silence(_capacity);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue