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:
parent
4476461443
commit
d6637dad5a
|
@ -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"
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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__ */
|
|
@ -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__ */
|
|
@ -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;
|
||||
|
|
|
@ -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__ */
|
|
@ -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__ */
|
|
@ -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__ */
|
|
@ -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__ */
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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 ();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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 {
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
|
||||
#include <ardour/runtime_functions.h>
|
||||
#include <ardour/buffer_set.h>
|
||||
#include <ardour/audio_buffer.h>
|
||||
|
||||
#include "i18n.h"
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
*/
|
||||
|
||||
#include <ardour/port_set.h>
|
||||
#include <ardour/midi_port.h>
|
||||
#include <ardour/audio_port.h>
|
||||
|
||||
namespace ARDOUR {
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <ardour/audioplaylist.h>
|
||||
#include <ardour/panner.h>
|
||||
#include <ardour/utils.h>
|
||||
#include <ardour/port.h>
|
||||
|
||||
#include "i18n.h"
|
||||
|
||||
|
|
Loading…
Reference in New Issue