mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-06 14:54:56 +01:00
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
40 changed files with 652 additions and 1853 deletions
|
|
@ -30,6 +30,7 @@
|
||||||
#include "ardour/audio_track.h"
|
#include "ardour/audio_track.h"
|
||||||
#include "ardour/midi_track.h"
|
#include "ardour/midi_track.h"
|
||||||
#include "ardour/data_type.h"
|
#include "ardour/data_type.h"
|
||||||
|
#include "ardour/port.h"
|
||||||
#include "ardour/bundle.h"
|
#include "ardour/bundle.h"
|
||||||
|
|
||||||
#include "io_selector.h"
|
#include "io_selector.h"
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@
|
||||||
#include "ardour/audio_track.h"
|
#include "ardour/audio_track.h"
|
||||||
#include "ardour/midi_track.h"
|
#include "ardour/midi_track.h"
|
||||||
#include "ardour/audioengine.h"
|
#include "ardour/audioengine.h"
|
||||||
|
#include "ardour/port.h"
|
||||||
#include "ardour/bundle.h"
|
#include "ardour/bundle.h"
|
||||||
#include <boost/shared_ptr.hpp>
|
#include <boost/shared_ptr.hpp>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
|
||||||
|
|
@ -52,8 +52,6 @@ automatable.cc
|
||||||
automation.cc
|
automation.cc
|
||||||
automation_control.cc
|
automation_control.cc
|
||||||
automation_list.cc
|
automation_list.cc
|
||||||
base_audio_port.cc
|
|
||||||
base_midi_port.cc
|
|
||||||
broadcast_info.cc
|
broadcast_info.cc
|
||||||
buffer.cc
|
buffer.cc
|
||||||
buffer_set.cc
|
buffer_set.cc
|
||||||
|
|
@ -96,9 +94,6 @@ globals.cc
|
||||||
import.cc
|
import.cc
|
||||||
io.cc
|
io.cc
|
||||||
io_processor.cc
|
io_processor.cc
|
||||||
jack_audio_port.cc
|
|
||||||
jack_midi_port.cc
|
|
||||||
jack_port.cc
|
|
||||||
jack_slave.cc
|
jack_slave.cc
|
||||||
ladspa_plugin.cc
|
ladspa_plugin.cc
|
||||||
location.cc
|
location.cc
|
||||||
|
|
|
||||||
|
|
@ -39,10 +39,10 @@
|
||||||
#include <ardour/session.h>
|
#include <ardour/session.h>
|
||||||
#include <ardour/route_group.h>
|
#include <ardour/route_group.h>
|
||||||
#include <ardour/route.h>
|
#include <ardour/route.h>
|
||||||
#include <ardour/port.h>
|
|
||||||
#include <ardour/utils.h>
|
#include <ardour/utils.h>
|
||||||
#include <ardour/diskstream.h>
|
#include <ardour/diskstream.h>
|
||||||
#include <ardour/audioplaylist.h>
|
#include <ardour/audioplaylist.h>
|
||||||
|
#include <ardour/port.h>
|
||||||
|
|
||||||
struct tm;
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|
@ -21,28 +21,42 @@
|
||||||
#ifndef __ardour_audio_port_h__
|
#ifndef __ardour_audio_port_h__
|
||||||
#define __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 {
|
namespace ARDOUR {
|
||||||
|
|
||||||
class AudioPort : public BaseAudioPort, public PortFacade {
|
class AudioPort : public Port
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
~AudioPort();
|
~AudioPort();
|
||||||
|
|
||||||
void reset ();
|
DataType type () const {
|
||||||
|
return DataType::AUDIO;
|
||||||
void cycle_start (nframes_t nframes, nframes_t offset);
|
}
|
||||||
void cycle_end (nframes_t nframes, nframes_t offset);
|
|
||||||
|
|
||||||
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:
|
protected:
|
||||||
friend class AudioEngine;
|
friend class AudioEngine;
|
||||||
|
|
||||||
AudioPort (const std::string&, Flags, bool external, nframes_t);
|
AudioPort (std::string const &, Flags, bool, nframes_t);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void mixdown (nframes_t, nframes_t, bool);
|
||||||
|
|
||||||
bool _has_been_mixed_down;
|
bool _has_been_mixed_down;
|
||||||
|
AudioBuffer* _buffer;
|
||||||
|
bool _own_buffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ARDOUR
|
} // namespace ARDOUR
|
||||||
|
|
|
||||||
|
|
@ -146,13 +146,11 @@ class AudioEngine : public sigc::trackable
|
||||||
return get_nth_physical (type, n, JackPortIsOutput);
|
return get_nth_physical (type, n, JackPortIsOutput);
|
||||||
}
|
}
|
||||||
|
|
||||||
nframes_t get_port_total_latency (const Port&);
|
|
||||||
void update_total_latencies ();
|
void update_total_latencies ();
|
||||||
void update_total_latency (const Port&);
|
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 &);
|
||||||
*/
|
Port *get_port_by_name_locked (const std::string &);
|
||||||
Port *get_port_by_name (const std::string& name, bool keep = true);
|
|
||||||
|
|
||||||
enum TransportState {
|
enum TransportState {
|
||||||
TransportStopped = JackTransportStopped,
|
TransportStopped = JackTransportStopped,
|
||||||
|
|
@ -234,8 +232,6 @@ class AudioEngine : public sigc::trackable
|
||||||
int process_callback (nframes_t nframes);
|
int process_callback (nframes_t nframes);
|
||||||
void remove_all_ports ();
|
void remove_all_ports ();
|
||||||
|
|
||||||
Port* get_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;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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/session.h>
|
||||||
#include <ardour/route_group.h>
|
#include <ardour/route_group.h>
|
||||||
#include <ardour/route.h>
|
#include <ardour/route.h>
|
||||||
#include <ardour/port.h>
|
|
||||||
#include <ardour/utils.h>
|
#include <ardour/utils.h>
|
||||||
|
|
||||||
struct tm;
|
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/fastlog.h>
|
||||||
#include <pbd/ringbufferNPT.h>
|
#include <pbd/ringbufferNPT.h>
|
||||||
|
|
||||||
|
|
||||||
#include <ardour/ardour.h>
|
#include <ardour/ardour.h>
|
||||||
#include <ardour/configuration.h>
|
#include <ardour/configuration.h>
|
||||||
#include <ardour/session.h>
|
#include <ardour/session.h>
|
||||||
#include <ardour/route_group.h>
|
#include <ardour/route_group.h>
|
||||||
#include <ardour/route.h>
|
#include <ardour/route.h>
|
||||||
#include <ardour/port.h>
|
|
||||||
#include <ardour/utils.h>
|
#include <ardour/utils.h>
|
||||||
#include <ardour/diskstream.h>
|
#include <ardour/diskstream.h>
|
||||||
#include <ardour/midi_playlist.h>
|
#include <ardour/midi_playlist.h>
|
||||||
|
|
|
||||||
|
|
@ -21,29 +21,40 @@
|
||||||
#ifndef __ardour_midi_port_h__
|
#ifndef __ardour_midi_port_h__
|
||||||
#define __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 {
|
namespace ARDOUR {
|
||||||
|
|
||||||
class MidiEngine;
|
class MidiEngine;
|
||||||
|
|
||||||
class MidiPort : public BaseMidiPort, public PortFacade {
|
class MidiPort : public Port {
|
||||||
public:
|
public:
|
||||||
~MidiPort();
|
~MidiPort();
|
||||||
|
|
||||||
void reset ();
|
DataType type () const {
|
||||||
|
return DataType::MIDI;
|
||||||
|
}
|
||||||
|
|
||||||
void cycle_start (nframes_t nframes, nframes_t offset);
|
void cycle_start (nframes_t nframes, nframes_t offset);
|
||||||
void cycle_end (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 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 );
|
MidiBuffer& get_midi_buffer( nframes_t nframes, nframes_t offset );
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class AudioEngine;
|
friend class AudioEngine;
|
||||||
|
|
||||||
MidiPort (const std::string& name, Flags, bool external, nframes_t bufsize);
|
MidiPort (const std::string& name, Flags, bool external, nframes_t bufsize);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void mixdown (nframes_t, nframes_t, bool);
|
||||||
|
|
||||||
|
MidiBuffer* _buffer;
|
||||||
bool _has_been_mixed_down;
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|
@ -20,167 +20,118 @@
|
||||||
#ifndef __ardour_port_h__
|
#ifndef __ardour_port_h__
|
||||||
#define __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 <set>
|
||||||
#include <vector>
|
#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 {
|
namespace ARDOUR {
|
||||||
|
|
||||||
class AudioEngine;
|
class AudioEngine;
|
||||||
class Buffer;
|
class Buffer;
|
||||||
|
|
||||||
/** Abstract base for ports
|
class Port : public sigc::trackable
|
||||||
*/
|
{
|
||||||
class Port : public virtual PBD::Destructible {
|
public:
|
||||||
public:
|
|
||||||
enum Flags {
|
enum Flags {
|
||||||
IsInput = JackPortIsInput,
|
IsInput = JackPortIsInput,
|
||||||
IsOutput = JackPortIsOutput,
|
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;
|
return _name;
|
||||||
}
|
}
|
||||||
|
|
||||||
Flags flags() const {
|
int set_name (std::string const &);
|
||||||
|
|
||||||
|
/** @return flags */
|
||||||
|
Flags flags () const {
|
||||||
return _flags;
|
return _flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool receives_input() const {
|
/** @return true if this Port receives input, otherwise false */
|
||||||
|
bool receives_input () const {
|
||||||
return _flags & IsInput;
|
return _flags & IsInput;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @return true if this Port sends output, otherwise false */
|
||||||
bool sends_output () const {
|
bool sends_output () const {
|
||||||
return _flags & IsOutput;
|
return _flags & IsOutput;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool can_monitor () const {
|
/* @return true if this port is visible outside Ardour (via JACK) */
|
||||||
return _flags & CanMonitor;
|
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 () const;
|
||||||
bool connected_to (const std::string& portname) const;
|
int disconnect_all ();
|
||||||
int get_connections (std::vector<std::string>&) const;
|
int get_connections (std::vector<std::string> &) const;
|
||||||
|
|
||||||
std::string short_name() const;
|
/* connection by name */
|
||||||
int set_name (const std::string& str);
|
bool connected_to (std::string const &) const;
|
||||||
bool monitoring_input () const;
|
int connect (std::string const &);
|
||||||
void ensure_monitor_input (bool yn);
|
int disconnect (std::string const &);
|
||||||
void request_monitor_input (bool yn);
|
|
||||||
nframes_t latency () const;
|
|
||||||
nframes_t total_latency () const;
|
|
||||||
void set_latency (nframes_t nframes);
|
|
||||||
|
|
||||||
protected:
|
/* connection by Port* */
|
||||||
Port* _ext_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__
|
#define __ardour_port_set_h__
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <ardour/port.h>
|
|
||||||
#include <ardour/audio_port.h>
|
|
||||||
#include <ardour/midi_port.h>
|
|
||||||
#include <ardour/chan_count.h>
|
#include <ardour/chan_count.h>
|
||||||
|
|
||||||
namespace ARDOUR {
|
namespace ARDOUR {
|
||||||
|
|
||||||
|
class Port;
|
||||||
|
class AudioPort;
|
||||||
|
class MidiPort;
|
||||||
|
|
||||||
/** An ordered list of Ports, possibly of various types.
|
/** An ordered list of Ports, possibly of various types.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,7 @@
|
||||||
#include <ardour/audioregion.h>
|
#include <ardour/audioregion.h>
|
||||||
#include <ardour/audio_port.h>
|
#include <ardour/audio_port.h>
|
||||||
#include <ardour/source_factory.h>
|
#include <ardour/source_factory.h>
|
||||||
|
#include <ardour/audio_buffer.h>
|
||||||
|
|
||||||
#include "i18n.h"
|
#include "i18n.h"
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
|
|
|
||||||
|
|
@ -18,118 +18,86 @@
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <ardour/audio_port.h>
|
#include <ardour/audio_port.h>
|
||||||
#include <ardour/jack_audio_port.h>
|
|
||||||
#include <ardour/audioengine.h>
|
#include <ardour/audioengine.h>
|
||||||
#include <ardour/data_type.h>
|
#include <ardour/data_type.h>
|
||||||
|
#include <ardour/audio_buffer.h>
|
||||||
|
|
||||||
using namespace ARDOUR;
|
using namespace ARDOUR;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
AudioPort::AudioPort (const std::string& name, Flags flags, bool external, nframes_t capacity)
|
AudioPort::AudioPort (const std::string& name, Flags flags, bool ext, nframes_t capacity)
|
||||||
: Port (name, flags)
|
: Port (name, DataType::AUDIO, flags, ext)
|
||||||
, BaseAudioPort (name, flags)
|
, _has_been_mixed_down (false)
|
||||||
, PortFacade (name, flags)
|
, _buffer (0)
|
||||||
, _has_been_mixed_down( false )
|
|
||||||
{
|
{
|
||||||
if (!external || receives_input()) {
|
assert (name.find_first_of (':') == string::npos);
|
||||||
|
|
||||||
/* internal-only and input ports need their own buffers.
|
if (external ()) {
|
||||||
external output ports use the external port buffer.
|
|
||||||
*/
|
/* external ports use the external port buffer */
|
||||||
|
_buffer = new AudioBuffer (0);
|
||||||
_buffer = new AudioBuffer (capacity);
|
|
||||||
_own_buffer = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!external) {
|
|
||||||
|
|
||||||
_ext_port = 0;
|
|
||||||
set_name (name);
|
|
||||||
|
|
||||||
} else {
|
} 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()
|
AudioPort::~AudioPort()
|
||||||
{
|
{
|
||||||
delete _ext_port;
|
delete _buffer;
|
||||||
_ext_port = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
AudioPort::reset()
|
|
||||||
{
|
|
||||||
BaseAudioPort::reset();
|
|
||||||
|
|
||||||
if (_ext_port) {
|
|
||||||
_ext_port->reset ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
AudioPort::cycle_start (nframes_t nframes, nframes_t offset)
|
AudioPort::cycle_start (nframes_t nframes, nframes_t offset)
|
||||||
{
|
{
|
||||||
/* caller must hold process lock */
|
/* caller must hold process lock */
|
||||||
|
|
||||||
if (_ext_port) {
|
|
||||||
_ext_port->cycle_start (nframes, offset);
|
|
||||||
}
|
|
||||||
_has_been_mixed_down = false;
|
_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 &
|
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;
|
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;
|
_has_been_mixed_down = true;
|
||||||
|
}
|
||||||
|
|
||||||
return *_buffer;
|
return *_buffer;
|
||||||
}
|
}
|
||||||
|
|
@ -137,5 +105,38 @@ AudioPort::get_audio_buffer( nframes_t nframes, nframes_t offset ) {
|
||||||
void
|
void
|
||||||
AudioPort::cycle_end (nframes_t nframes, nframes_t offset)
|
AudioPort::cycle_end (nframes_t nframes, nframes_t offset)
|
||||||
{
|
{
|
||||||
_has_been_mixed_down=false;
|
_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/panner.h>
|
||||||
#include <ardour/utils.h>
|
#include <ardour/utils.h>
|
||||||
#include <ardour/buffer_set.h>
|
#include <ardour/buffer_set.h>
|
||||||
|
#include <ardour/audio_buffer.h>
|
||||||
#include "i18n.h"
|
#include "i18n.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
|
||||||
|
|
@ -34,10 +34,8 @@
|
||||||
#include <ardour/audioengine.h>
|
#include <ardour/audioengine.h>
|
||||||
#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_midi_port.h>
|
|
||||||
#include <ardour/midi_port.h>
|
|
||||||
#include <ardour/audio_port.h>
|
#include <ardour/audio_port.h>
|
||||||
|
#include <ardour/midi_port.h>
|
||||||
#include <ardour/session.h>
|
#include <ardour/session.h>
|
||||||
#include <ardour/cycle_timer.h>
|
#include <ardour/cycle_timer.h>
|
||||||
#include <ardour/utils.h>
|
#include <ardour/utils.h>
|
||||||
|
|
@ -356,6 +354,7 @@ AudioEngine::process_callback (nframes_t nframes)
|
||||||
which requires interleaving with route processing.
|
which requires interleaving with route processing.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* XXX: we're running this on both inputs and outputs... */
|
||||||
(*i)->cycle_start (nframes, 0);
|
(*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 *
|
Port *
|
||||||
AudioEngine::register_input_port (DataType type, const string& portname, bool publish)
|
AudioEngine::register_input_port (DataType type, const string& portname, bool publish)
|
||||||
{
|
{
|
||||||
|
|
@ -692,6 +676,8 @@ AudioEngine::unregister_port (Port& port)
|
||||||
int
|
int
|
||||||
AudioEngine::connect (const string& source, const string& destination)
|
AudioEngine::connect (const string& source, const string& destination)
|
||||||
{
|
{
|
||||||
|
/* caller must hold process lock */
|
||||||
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!_running) {
|
if (!_running) {
|
||||||
|
|
@ -705,39 +691,24 @@ AudioEngine::connect (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);
|
||||||
|
|
||||||
//cerr << "Trying to connect source: " << s << " with destination " << d << endl;
|
Port* src = get_port_by_name_locked (s);
|
||||||
|
Port* dst = get_port_by_name_locked (d);
|
||||||
Port* src = get_port (s);
|
|
||||||
Port* dst = get_port (d);
|
|
||||||
|
|
||||||
if (src && dst) {
|
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 connect stuff */
|
||||||
|
|
||||||
if ((ret = src->connect (*dst)) == 0) {
|
ret = src->connect (dst);
|
||||||
ret = dst->connect (*src);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (src || dst) {
|
} else if (src || dst) {
|
||||||
|
|
||||||
/* one port is known to us, try to connect it to something external */
|
/* one port is known to us, try to connect it to something external */
|
||||||
|
|
||||||
PortConnectableByName* pcn;
|
|
||||||
string other;
|
|
||||||
|
|
||||||
if (src) {
|
if (src) {
|
||||||
pcn = dynamic_cast<PortConnectableByName*>(src);
|
ret = src->connect (d);
|
||||||
other = d;
|
|
||||||
} else {
|
} else {
|
||||||
pcn = dynamic_cast<PortConnectableByName*>(dst);
|
ret = dst->connect (s);
|
||||||
other = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pcn) {
|
|
||||||
ret = pcn->connect (other);
|
|
||||||
} else {
|
|
||||||
ret = -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -764,6 +735,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)
|
||||||
{
|
{
|
||||||
|
/* caller must hold process lock */
|
||||||
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!_running) {
|
if (!_running) {
|
||||||
|
|
@ -778,39 +751,23 @@ 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);
|
||||||
|
|
||||||
//cerr << "trying to disconnect port '" << s << "' from port '" << d << endl;
|
Port* src = get_port_by_name_locked (s);
|
||||||
|
Port* dst = get_port_by_name_locked (d);
|
||||||
Port* src = get_port (s);
|
|
||||||
Port* dst = get_port (d);
|
|
||||||
|
|
||||||
if (src && dst) {
|
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 = src->disconnect (dst);
|
||||||
ret = dst->disconnect (*src);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (src || dst) {
|
} else if (src || dst) {
|
||||||
|
|
||||||
/* one port is known to us, try to connect it to something external */
|
/* one port is known to us, try to disconnect it from something external */
|
||||||
|
|
||||||
|
|
||||||
PortConnectableByName* pcn;
|
|
||||||
string other;
|
|
||||||
|
|
||||||
if (src) {
|
if (src) {
|
||||||
pcn = dynamic_cast<PortConnectableByName*>(src);
|
ret = src->disconnect (d);
|
||||||
other = d;
|
|
||||||
} else {
|
} else {
|
||||||
pcn = dynamic_cast<PortConnectableByName*>(dst);
|
ret = dst->disconnect (s);
|
||||||
other = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pcn) {
|
|
||||||
ret = pcn->disconnect (other);
|
|
||||||
} else {
|
|
||||||
ret = -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -873,34 +830,53 @@ AudioEngine::frames_per_cycle ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Get a port by name.
|
/** @param name Full name of port (including prefix:)
|
||||||
* Note this can return NULL, it will NOT create a port if it is not found (any more).
|
* @return Corresponding Port*, or 0. This object remains the property of the AudioEngine
|
||||||
|
* so must not be deleted.
|
||||||
*/
|
*/
|
||||||
Port *
|
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);
|
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 (!_running) {
|
||||||
if (!_has_run) {
|
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*/
|
/*NOTREACHED*/
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
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();
|
boost::shared_ptr<Ports> pr = ports.reader();
|
||||||
|
|
||||||
for (Ports::iterator i = pr->begin(); i != pr->end(); ++i) {
|
for (Ports::iterator i = pr->begin(); i != pr->end(); ++i) {
|
||||||
if (portname == (*i)->name()) {
|
if (rel == (*i)->name()) {
|
||||||
return (*i);
|
return *i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const char **
|
const char **
|
||||||
AudioEngine::get_ports (const string& port_name_pattern, const string& type_name_pattern, uint32_t flags)
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ARDOUR::nframes_t
|
|
||||||
AudioEngine::get_port_total_latency (const Port& port)
|
|
||||||
{
|
|
||||||
return port.total_latency ();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
AudioEngine::update_total_latency (const Port& port)
|
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/export_failed.h>
|
||||||
#include <ardour/audioengine.h>
|
#include <ardour/audioengine.h>
|
||||||
|
#include <ardour/audio_port.h>
|
||||||
|
#include <ardour/audio_buffer.h>
|
||||||
|
|
||||||
using namespace ARDOUR;
|
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) {
|
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);
|
current_name.replace (current_name.find (_name), _name.length(), name);
|
||||||
i->set_name (current_name);
|
i->set_name (current_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
|
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);
|
current_name.replace (current_name.find (_name), _name.length(), name);
|
||||||
i->set_name (current_name);
|
i->set_name (current_name);
|
||||||
}
|
}
|
||||||
|
|
@ -2028,7 +2028,7 @@ IO::output_latency () const
|
||||||
/* io lock not taken - must be protected by other means */
|
/* io lock not taken - must be protected by other means */
|
||||||
|
|
||||||
for (PortSet::const_iterator i = _outputs.begin(); i != _outputs.end(); ++i) {
|
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;
|
max_latency = latency;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2047,7 +2047,7 @@ IO::input_latency () const
|
||||||
/* io lock not taken - must be protected by other means */
|
/* io lock not taken - must be protected by other means */
|
||||||
|
|
||||||
for (PortSet::const_iterator i = _inputs.begin(); i != _inputs.end(); ++i) {
|
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;
|
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);
|
snprintf (buf, jack_port_name_size(), _("%s %u"), base, n);
|
||||||
|
|
||||||
for ( ; i != _inputs.end(); ++i) {
|
for ( ; i != _inputs.end(); ++i) {
|
||||||
if (i->short_name() == buf) {
|
if (i->name() == buf) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2506,7 +2506,7 @@ IO::find_output_port_hole (const char* base)
|
||||||
snprintf (buf, jack_port_name_size(), _("%s %u"), base, n);
|
snprintf (buf, jack_port_name_size(), _("%s %u"), base, n);
|
||||||
|
|
||||||
for ( ; i != _outputs.end(); ++i) {
|
for ( ; i != _outputs.end(); ++i) {
|
||||||
if (i->short_name() == buf) {
|
if (i->name() == buf) {
|
||||||
break;
|
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/peak.h>
|
||||||
#include <ardour/dB.h>
|
#include <ardour/dB.h>
|
||||||
#include <ardour/session.h>
|
#include <ardour/session.h>
|
||||||
#include <ardour/audio_buffer.h>
|
|
||||||
#include <ardour/midi_buffer.h>
|
#include <ardour/midi_buffer.h>
|
||||||
|
#include <ardour/audio_buffer.h>
|
||||||
|
#include <ardour/runtime_functions.h>
|
||||||
|
|
||||||
namespace ARDOUR {
|
namespace ARDOUR {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,76 +20,74 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include <ardour/midi_port.h>
|
#include <ardour/midi_port.h>
|
||||||
#include <ardour/jack_midi_port.h>
|
|
||||||
#include <ardour/data_type.h>
|
#include <ardour/data_type.h>
|
||||||
|
|
||||||
using namespace ARDOUR;
|
using namespace ARDOUR;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
MidiPort::MidiPort (const std::string& name, Flags flags, bool external, nframes_t capacity)
|
MidiPort::MidiPort (const std::string& name, Flags flags, bool ext, nframes_t capacity)
|
||||||
: Port (name, flags)
|
: Port (name, DataType::MIDI, flags, ext)
|
||||||
, BaseMidiPort (name, flags)
|
|
||||||
, PortFacade (name, flags)
|
|
||||||
, _has_been_mixed_down (false)
|
, _has_been_mixed_down (false)
|
||||||
{
|
{
|
||||||
// FIXME: size kludge (see BufferSet::ensure_buffers)
|
// FIXME: size kludge (see BufferSet::ensure_buffers)
|
||||||
// Jack needs to tell us this
|
// Jack needs to tell us this
|
||||||
_buffer = new MidiBuffer (capacity * 8);
|
_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()
|
MidiPort::~MidiPort()
|
||||||
{
|
{
|
||||||
delete _ext_port;
|
delete _buffer;
|
||||||
_ext_port = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
MidiPort::reset()
|
|
||||||
{
|
|
||||||
BaseMidiPort::reset();
|
|
||||||
|
|
||||||
if (_ext_port) {
|
|
||||||
_ext_port->reset ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
MidiPort::cycle_start (nframes_t nframes, nframes_t offset)
|
MidiPort::cycle_start (nframes_t nframes, nframes_t offset)
|
||||||
{
|
{
|
||||||
if (_ext_port) {
|
if (external ()) {
|
||||||
_ext_port->cycle_start (nframes, offset);
|
_buffer->clear ();
|
||||||
|
assert (_buffer->size () == 0);
|
||||||
|
|
||||||
|
if (sends_output ()) {
|
||||||
|
jack_midi_clear_buffer (jack_port_get_buffer (_jack_port, nframes));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MidiBuffer &
|
MidiBuffer &
|
||||||
MidiPort::get_midi_buffer( nframes_t nframes, nframes_t offset ) {
|
MidiPort::get_midi_buffer( nframes_t nframes, nframes_t offset ) {
|
||||||
|
|
||||||
if (_has_been_mixed_down)
|
if (_has_been_mixed_down) {
|
||||||
return *_buffer;
|
return *_buffer;
|
||||||
|
}
|
||||||
|
|
||||||
if (_flags & IsInput) {
|
if (receives_input ()) {
|
||||||
|
|
||||||
if (_ext_port) {
|
if (external ()) {
|
||||||
|
|
||||||
BaseMidiPort* mprt = dynamic_cast<BaseMidiPort*>(_ext_port);
|
void* jack_buffer = jack_port_get_buffer (_jack_port, nframes);
|
||||||
assert(mprt);
|
const nframes_t event_count = jack_midi_get_event_count(jack_buffer);
|
||||||
assert(&mprt->get_midi_buffer(nframes,offset) == _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()) {
|
if (!_connections.empty()) {
|
||||||
(*_mixdown) (_connections, _buffer, nframes, offset, false);
|
mixdown (nframes, offset, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -97,15 +95,17 @@ MidiPort::get_midi_buffer( nframes_t nframes, nframes_t offset ) {
|
||||||
if (_connections.empty()) {
|
if (_connections.empty()) {
|
||||||
_buffer->silence (nframes, offset);
|
_buffer->silence (nframes, offset);
|
||||||
} else {
|
} else {
|
||||||
(*_mixdown) (_connections, _buffer, nframes, offset, true);
|
mixdown (nframes, offset, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
_buffer->silence (nframes, offset);
|
_buffer->silence (nframes, offset);
|
||||||
}
|
}
|
||||||
if (nframes)
|
|
||||||
|
if (nframes) {
|
||||||
_has_been_mixed_down = true;
|
_has_been_mixed_down = true;
|
||||||
|
}
|
||||||
|
|
||||||
return *_buffer;
|
return *_buffer;
|
||||||
}
|
}
|
||||||
|
|
@ -114,16 +114,65 @@ MidiPort::get_midi_buffer( nframes_t nframes, nframes_t offset ) {
|
||||||
void
|
void
|
||||||
MidiPort::cycle_end (nframes_t nframes, nframes_t offset)
|
MidiPort::cycle_end (nframes_t nframes, nframes_t offset)
|
||||||
{
|
{
|
||||||
if (_ext_port) {
|
#if 0
|
||||||
_ext_port->cycle_end (nframes, offset);
|
|
||||||
|
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;
|
_has_been_mixed_down = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MidiPort::flush_buffers (nframes_t nframes, nframes_t offset)
|
MidiPort::flush_buffers (nframes_t nframes, nframes_t offset)
|
||||||
{
|
{
|
||||||
if (_ext_port) {
|
/* FIXME: offset */
|
||||||
_ext_port->flush_buffers (nframes, 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/types.h>
|
||||||
#include <ardour/utils.h>
|
#include <ardour/utils.h>
|
||||||
#include <ardour/mix.h>
|
#include <ardour/mix.h>
|
||||||
|
#include <ardour/runtime_functions.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
using namespace ARDOUR;
|
using namespace ARDOUR;
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@
|
||||||
|
|
||||||
#include <ardour/runtime_functions.h>
|
#include <ardour/runtime_functions.h>
|
||||||
#include <ardour/buffer_set.h>
|
#include <ardour/buffer_set.h>
|
||||||
|
#include <ardour/audio_buffer.h>
|
||||||
|
|
||||||
#include "i18n.h"
|
#include "i18n.h"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@
|
||||||
#include <ardour/ladspa_plugin.h>
|
#include <ardour/ladspa_plugin.h>
|
||||||
#include <ardour/buffer_set.h>
|
#include <ardour/buffer_set.h>
|
||||||
#include <ardour/automation_list.h>
|
#include <ardour/automation_list.h>
|
||||||
|
#include <ardour/audio_buffer.h>
|
||||||
|
|
||||||
#ifdef HAVE_SLV2
|
#ifdef HAVE_SLV2
|
||||||
#include <ardour/lv2_plugin.h>
|
#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
|
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
|
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;
|
ARDOUR::AudioEngine* ARDOUR::Port::_engine = 0;
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
AudioEngine* Port::engine = 0;
|
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 (const std::string& name, Flags flgs)
|
|
||||||
: _flags (flgs)
|
|
||||||
, _name (name)
|
|
||||||
, _metering (0)
|
|
||||||
, _last_monitor (false)
|
|
||||||
{
|
{
|
||||||
}
|
/* 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 ()
|
||||||
Port::~Port ()
|
to establish type. */
|
||||||
{
|
|
||||||
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 */
|
|
||||||
|
|
||||||
for (set<Port*>::iterator i = _connections.begin(); i != _connections.end(); ++i) {
|
if (e) {
|
||||||
if ((*i) == &other) {
|
try {
|
||||||
_connections.erase (i);
|
do_make_external (t);
|
||||||
return 0;
|
}
|
||||||
|
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
|
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 ();
|
_connections.clear ();
|
||||||
|
|
||||||
|
/* And JACK connections */
|
||||||
|
jack_port_disconnect (_engine->jack(), _jack_port);
|
||||||
|
_named_connections.clear ();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
/** @param o Port name
|
||||||
Port::set_latency (nframes_t val)
|
* @return true if this port is connected to o, otherwise false.
|
||||||
{
|
*/
|
||||||
_latency = val;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Port::connected() const
|
ARDOUR::Port::connected_to (std::string const & o) const
|
||||||
{
|
{
|
||||||
/* caller must hold process lock */
|
if (_jack_port && jack_port_connected_to (_jack_port, o.c_str ())) {
|
||||||
return !_connections.empty();
|
/* connected via JACK */
|
||||||
}
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
for (std::set<Port*>::iterator i = _connections.begin (); i != _connections.end (); ++i) {
|
||||||
Port::connected_to (const string& portname) const
|
if ((*i)->name () == o) {
|
||||||
{
|
/* connected internally */
|
||||||
/* caller must hold process lock */
|
|
||||||
|
|
||||||
for (set<Port*>::const_iterator p = _connections.begin(); p != _connections.end(); ++p) {
|
|
||||||
if ((*p)->name() == portname) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -120,271 +130,259 @@ Port::connected_to (const string& portname) const
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
Port::get_connections (vector<string>& names) const
|
ARDOUR::Port::get_connections (std::vector<std::string> & c) const
|
||||||
{
|
{
|
||||||
/* caller must hold process lock */
|
int n = 0;
|
||||||
int i = 0;
|
|
||||||
set<Port*>::const_iterator p;
|
|
||||||
|
|
||||||
for (i = 0, p = _connections.begin(); p != _connections.end(); ++p, ++i) {
|
/* JACK connections */
|
||||||
names.push_back ((*p)->name());
|
if (_jack_port) {
|
||||||
}
|
const char** jc = jack_port_get_connections (_jack_port);
|
||||||
|
if (jc) {
|
||||||
return i;
|
for (int i = 0; jc[i]; ++i) {
|
||||||
}
|
c.push_back (jc[i]);
|
||||||
|
++n;
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
_name = str;
|
|
||||||
ret = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
/* Internal connections */
|
||||||
}
|
for (std::set<Port*>::iterator i = _connections.begin (); i != _connections.end (); ++i) {
|
||||||
|
c.push_back ((*i)->name ());
|
||||||
string
|
++n;
|
||||||
PortFacade::short_name () const
|
|
||||||
{
|
|
||||||
if (_ext_port) {
|
|
||||||
return _ext_port->short_name();
|
|
||||||
} else {
|
|
||||||
return _name;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
PortFacade::reestablish ()
|
ARDOUR::Port::connect (std::string const & other)
|
||||||
{
|
{
|
||||||
if (_ext_port) {
|
/* caller must hold process lock */
|
||||||
return _ext_port->reestablish ();
|
|
||||||
|
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 {
|
} 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
|
bool
|
||||||
PortFacade::reconnect()
|
ARDOUR::Port::connected_to (Port *o) const
|
||||||
{
|
{
|
||||||
if (_ext_port) {
|
return connected_to (o->name ());
|
||||||
return _ext_port->reconnect ();
|
}
|
||||||
} else {
|
|
||||||
return 0;
|
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
|
void
|
||||||
PortFacade::set_latency (nframes_t val)
|
ARDOUR::Port::set_engine (AudioEngine* e)
|
||||||
{
|
{
|
||||||
if (_ext_port) {
|
_engine = e;
|
||||||
_ext_port->set_latency (val);
|
|
||||||
} else {
|
|
||||||
_latency = val;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nframes_t
|
void
|
||||||
PortFacade::latency() const
|
ARDOUR::Port::ensure_monitor_input (bool yn)
|
||||||
{
|
{
|
||||||
if (_ext_port) {
|
if (_jack_port) {
|
||||||
return _ext_port->latency();
|
jack_port_ensure_monitor (_jack_port, yn);
|
||||||
} else {
|
|
||||||
return _latency;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
nframes_t
|
|
||||||
PortFacade::total_latency() const
|
|
||||||
{
|
|
||||||
if (_ext_port) {
|
|
||||||
return _ext_port->total_latency();
|
|
||||||
} else {
|
|
||||||
return _latency;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
PortFacade::monitoring_input() const
|
ARDOUR::Port::monitoring_input () const
|
||||||
{
|
{
|
||||||
if (_ext_port) {
|
if (_jack_port) {
|
||||||
return _ext_port->monitoring_input ();
|
return jack_port_monitoring_input (_jack_port);
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
PortFacade::ensure_monitor_input (bool yn)
|
ARDOUR::Port::reset ()
|
||||||
{
|
{
|
||||||
if (_ext_port) {
|
_last_monitor = false;
|
||||||
_ext_port->ensure_monitor_input (yn);
|
|
||||||
}
|
// XXX
|
||||||
|
// _metering = 0;
|
||||||
|
// reset_meters ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
PortFacade::request_monitor_input (bool yn)
|
ARDOUR::Port::recompute_total_latency () const
|
||||||
{
|
{
|
||||||
if (_ext_port) {
|
#ifdef HAVE_JACK_RECOMPUTE_LATENCY
|
||||||
_ext_port->request_monitor_input (yn);
|
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
|
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) {
|
for (std::set<string>::iterator i = _named_connections.begin(); i != _named_connections.end(); ++i) {
|
||||||
ret = _ext_port->connect (other);
|
if (connect (*i)) {
|
||||||
} else {
|
return -1;
|
||||||
ret = 0;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret == 0) {
|
return 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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
PortFacade::disconnect (Port& other)
|
ARDOUR::Port::set_name (std::string const & n)
|
||||||
{
|
{
|
||||||
int reta;
|
int r = 0;
|
||||||
int retb;
|
|
||||||
|
|
||||||
if (_ext_port) {
|
if (_jack_port) {
|
||||||
reta = _ext_port->disconnect (other);
|
r = jack_port_set_name (_jack_port, n.c_str());
|
||||||
|
if (r) {
|
||||||
|
_name = n;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
reta = 0;
|
_name = n;
|
||||||
}
|
}
|
||||||
|
|
||||||
retb = Port::disconnect (other);
|
return r;
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
PortFacade::reset ()
|
ARDOUR::Port::set_latency (nframes_t n)
|
||||||
{
|
{
|
||||||
Port::reset ();
|
_latency = n;
|
||||||
|
|
||||||
if (_ext_port) {
|
|
||||||
_ext_port->reset ();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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/port_set.h>
|
||||||
|
#include <ardour/midi_port.h>
|
||||||
|
#include <ardour/audio_port.h>
|
||||||
|
|
||||||
namespace ARDOUR {
|
namespace ARDOUR {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -81,6 +81,7 @@
|
||||||
#include <ardour/session_directory.h>
|
#include <ardour/session_directory.h>
|
||||||
#include <ardour/tape_file_matcher.h>
|
#include <ardour/tape_file_matcher.h>
|
||||||
#include <ardour/analyser.h>
|
#include <ardour/analyser.h>
|
||||||
|
#include <ardour/audio_buffer.h>
|
||||||
#include <ardour/bundle.h>
|
#include <ardour/bundle.h>
|
||||||
|
|
||||||
#include "i18n.h"
|
#include "i18n.h"
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@
|
||||||
#include <ardour/tempo.h>
|
#include <ardour/tempo.h>
|
||||||
#include <ardour/io.h>
|
#include <ardour/io.h>
|
||||||
#include <ardour/buffer_set.h>
|
#include <ardour/buffer_set.h>
|
||||||
|
#include <ardour/audio_buffer.h>
|
||||||
|
|
||||||
#include <sndfile.h>
|
#include <sndfile.h>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@
|
||||||
#include <ardour/audioplaylist.h>
|
#include <ardour/audioplaylist.h>
|
||||||
#include <ardour/panner.h>
|
#include <ardour/panner.h>
|
||||||
#include <ardour/utils.h>
|
#include <ardour/utils.h>
|
||||||
|
#include <ardour/port.h>
|
||||||
|
|
||||||
#include "i18n.h"
|
#include "i18n.h"
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue