From d6637dad5a239d74038fdf9e5800e5108ba0c44f Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Wed, 21 Jan 2009 02:27:21 +0000 Subject: [PATCH] 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 --- gtk2_ardour/io_selector.cc | 1 + gtk2_ardour/port_group.cc | 1 + libs/ardour/SConscript | 5 - libs/ardour/ardour/audio_diskstream.h | 2 +- libs/ardour/ardour/audio_port.h | 34 +- libs/ardour/ardour/audioengine.h | 8 +- libs/ardour/ardour/base_audio_port.h | 102 ---- libs/ardour/ardour/base_midi_port.h | 63 --- libs/ardour/ardour/diskstream.h | 1 - libs/ardour/ardour/internal_audio_port.h | 55 --- libs/ardour/ardour/internal_port.h | 82 ---- libs/ardour/ardour/jack_audio_port.h | 54 --- libs/ardour/ardour/jack_midi_port.h | 57 --- libs/ardour/ardour/midi_diskstream.h | 2 - libs/ardour/ardour/midi_port.h | 17 +- libs/ardour/ardour/port.h | 213 ++++----- libs/ardour/ardour/port_set.h | 6 +- libs/ardour/audio_diskstream.cc | 1 + libs/ardour/audio_port.cc | 167 +++---- libs/ardour/audio_track.cc | 1 + libs/ardour/audioengine.cc | 122 ++--- libs/ardour/base_audio_port.cc | 82 ---- libs/ardour/base_midi_port.cc | 67 --- libs/ardour/export_channel.cc | 2 + libs/ardour/internal_audio_port.cc | 71 --- libs/ardour/internal_port.cc | 163 ------- libs/ardour/io.cc | 12 +- libs/ardour/jack_audio_port.cc | 82 ---- libs/ardour/jack_midi_port.cc | 141 ------ libs/ardour/jack_port.cc | 179 ------- libs/ardour/meter.cc | 3 +- libs/ardour/midi_port.cc | 137 ++++-- libs/ardour/mix.cc | 1 + libs/ardour/panner.cc | 1 + libs/ardour/plugin_insert.cc | 1 + libs/ardour/port.cc | 564 +++++++++++------------ libs/ardour/port_set.cc | 2 + libs/ardour/session.cc | 1 + libs/ardour/session_click.cc | 1 + libs/ardour/track.cc | 1 + 40 files changed, 652 insertions(+), 1853 deletions(-) delete mode 100644 libs/ardour/ardour/base_audio_port.h delete mode 100644 libs/ardour/ardour/base_midi_port.h delete mode 100644 libs/ardour/ardour/internal_audio_port.h delete mode 100644 libs/ardour/ardour/internal_port.h delete mode 100644 libs/ardour/ardour/jack_audio_port.h delete mode 100644 libs/ardour/ardour/jack_midi_port.h delete mode 100644 libs/ardour/base_audio_port.cc delete mode 100644 libs/ardour/base_midi_port.cc delete mode 100644 libs/ardour/internal_audio_port.cc delete mode 100644 libs/ardour/internal_port.cc delete mode 100644 libs/ardour/jack_audio_port.cc delete mode 100644 libs/ardour/jack_midi_port.cc delete mode 100644 libs/ardour/jack_port.cc diff --git a/gtk2_ardour/io_selector.cc b/gtk2_ardour/io_selector.cc index 06274df95e..f438c21d3f 100644 --- a/gtk2_ardour/io_selector.cc +++ b/gtk2_ardour/io_selector.cc @@ -30,6 +30,7 @@ #include "ardour/audio_track.h" #include "ardour/midi_track.h" #include "ardour/data_type.h" +#include "ardour/port.h" #include "ardour/bundle.h" #include "io_selector.h" diff --git a/gtk2_ardour/port_group.cc b/gtk2_ardour/port_group.cc index 4157348d8e..228b5f0a4d 100644 --- a/gtk2_ardour/port_group.cc +++ b/gtk2_ardour/port_group.cc @@ -24,6 +24,7 @@ #include "ardour/audio_track.h" #include "ardour/midi_track.h" #include "ardour/audioengine.h" +#include "ardour/port.h" #include "ardour/bundle.h" #include #include diff --git a/libs/ardour/SConscript b/libs/ardour/SConscript index f21b623ed2..f34dd9b078 100644 --- a/libs/ardour/SConscript +++ b/libs/ardour/SConscript @@ -52,8 +52,6 @@ automatable.cc automation.cc automation_control.cc automation_list.cc -base_audio_port.cc -base_midi_port.cc broadcast_info.cc buffer.cc buffer_set.cc @@ -96,9 +94,6 @@ globals.cc import.cc io.cc io_processor.cc -jack_audio_port.cc -jack_midi_port.cc -jack_port.cc jack_slave.cc ladspa_plugin.cc location.cc diff --git a/libs/ardour/ardour/audio_diskstream.h b/libs/ardour/ardour/audio_diskstream.h index 79ffe3d490..92c8e82df8 100644 --- a/libs/ardour/ardour/audio_diskstream.h +++ b/libs/ardour/ardour/audio_diskstream.h @@ -39,10 +39,10 @@ #include #include #include -#include #include #include #include +#include struct tm; diff --git a/libs/ardour/ardour/audio_port.h b/libs/ardour/ardour/audio_port.h index fa416864e9..339165da0f 100644 --- a/libs/ardour/ardour/audio_port.h +++ b/libs/ardour/ardour/audio_port.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2002 Paul Davis + Copyright (C) 2002-2009 Paul Davis This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -21,28 +21,42 @@ #ifndef __ardour_audio_port_h__ #define __ardour_audio_port_h__ -#include +#include +#include namespace ARDOUR { -class AudioPort : public BaseAudioPort, public PortFacade { - +class AudioPort : public Port +{ public: ~AudioPort(); - void reset (); - - void cycle_start (nframes_t nframes, nframes_t offset); - void cycle_end (nframes_t nframes, nframes_t offset); + DataType type () const { + return DataType::AUDIO; + } - AudioBuffer& get_audio_buffer( nframes_t nframes, nframes_t offset ); + void cycle_start (nframes_t, nframes_t); + void cycle_end (nframes_t, nframes_t); + + Buffer& get_buffer (nframes_t nframes, nframes_t offset) { + return get_audio_buffer (nframes, offset); + } + + AudioBuffer& get_audio_buffer (nframes_t, nframes_t); + + void reset (); protected: friend class AudioEngine; - AudioPort (const std::string&, Flags, bool external, nframes_t); + AudioPort (std::string const &, Flags, bool, nframes_t); + private: + void mixdown (nframes_t, nframes_t, bool); + bool _has_been_mixed_down; + AudioBuffer* _buffer; + bool _own_buffer; }; } // namespace ARDOUR diff --git a/libs/ardour/ardour/audioengine.h b/libs/ardour/ardour/audioengine.h index 89abc6669a..16090a7d77 100644 --- a/libs/ardour/ardour/audioengine.h +++ b/libs/ardour/ardour/audioengine.h @@ -146,13 +146,11 @@ class AudioEngine : public sigc::trackable return get_nth_physical (type, n, JackPortIsOutput); } - nframes_t get_port_total_latency (const Port&); void update_total_latencies (); void update_total_latency (const Port&); - /** Caller may not delete the object pointed to by the return value - */ - Port *get_port_by_name (const std::string& name, bool keep = true); + Port *get_port_by_name (const std::string &); + Port *get_port_by_name_locked (const std::string &); enum TransportState { TransportStopped = JackTransportStopped, @@ -234,8 +232,6 @@ class AudioEngine : public sigc::trackable int process_callback (nframes_t nframes); void remove_all_ports (); - Port* get_port (const std::string& short_name); - typedef std::pair PortConnection; typedef std::list PortConnections; diff --git a/libs/ardour/ardour/base_audio_port.h b/libs/ardour/ardour/base_audio_port.h deleted file mode 100644 index 5bad90150b..0000000000 --- a/libs/ardour/ardour/base_audio_port.h +++ /dev/null @@ -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 - -#include - -#include - -#include -#include -#include - -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&, 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&, AudioBuffer*, nframes_t, nframes_t, bool); - - static void default_mixdown (const std::set&, 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__ */ diff --git a/libs/ardour/ardour/base_midi_port.h b/libs/ardour/ardour/base_midi_port.h deleted file mode 100644 index 5ea18fce43..0000000000 --- a/libs/ardour/ardour/base_midi_port.h +++ /dev/null @@ -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 -#include -#include -#include -#include - -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&, MidiBuffer*, nframes_t, nframes_t, bool)); - - protected: - BaseMidiPort (const std::string& name, Flags); - - MidiBuffer* _buffer; - bool _own_buffer; - - void (*_mixdown)(const std::set&, MidiBuffer*, nframes_t, nframes_t, bool); - static void default_mixdown (const std::set&, MidiBuffer*, nframes_t, nframes_t, bool); -}; - -} // namespace ARDOUR - -#endif /* __ardour_base_midi_port_h__ */ diff --git a/libs/ardour/ardour/diskstream.h b/libs/ardour/ardour/diskstream.h index 24655a1d41..b0ac26342f 100644 --- a/libs/ardour/ardour/diskstream.h +++ b/libs/ardour/ardour/diskstream.h @@ -40,7 +40,6 @@ #include #include #include -#include #include struct tm; diff --git a/libs/ardour/ardour/internal_audio_port.h b/libs/ardour/ardour/internal_audio_port.h deleted file mode 100644 index 7b70989d4b..0000000000 --- a/libs/ardour/ardour/internal_audio_port.h +++ /dev/null @@ -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 -#include -#include -#include -#include - -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&, AudioBuffer&, nframes_t, nframes_t)); - void reset (); - - protected: - friend class AudioEngine; - - InternalAudioPort (const std::string& name, Flags flags); - void (*_mixdown)(const std::list&, AudioBuffer&, nframes_t, nframes_t); - - static void default_mixdown (const std::list&, AudioBuffer&, nframes_t, nframes_t); -}; - -} // namespace ARDOUR - -#endif /* __ardour_internal_audio_port_h__ */ diff --git a/libs/ardour/ardour/internal_port.h b/libs/ardour/ardour/internal_port.h deleted file mode 100644 index e6053c0e58..0000000000 --- a/libs/ardour/ardour/internal_port.h +++ /dev/null @@ -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 - -#include -#include -#include - -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 _connections; - nframes_t _latency; - - static AudioEngine* engine; - static void set_engine (AudioEngine* e); -}; - -} // namespace ARDOUR - -#endif /* __ardour_internal_port_h__ */ diff --git a/libs/ardour/ardour/jack_audio_port.h b/libs/ardour/ardour/jack_audio_port.h deleted file mode 100644 index 5ca27132e0..0000000000 --- a/libs/ardour/ardour/jack_audio_port.h +++ /dev/null @@ -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 -#include -#include -#include -#include - -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__ */ diff --git a/libs/ardour/ardour/jack_midi_port.h b/libs/ardour/ardour/jack_midi_port.h deleted file mode 100644 index 91cbd400aa..0000000000 --- a/libs/ardour/ardour/jack_midi_port.h +++ /dev/null @@ -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 -#include -#include -#include -#include -#include -#include -#include -#include - -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__ */ diff --git a/libs/ardour/ardour/midi_diskstream.h b/libs/ardour/ardour/midi_diskstream.h index 56e704f88e..02b0132f7a 100644 --- a/libs/ardour/ardour/midi_diskstream.h +++ b/libs/ardour/ardour/midi_diskstream.h @@ -34,14 +34,12 @@ #include #include - #include #include #include #include #include -#include #include #include #include diff --git a/libs/ardour/ardour/midi_port.h b/libs/ardour/ardour/midi_port.h index a5a269b1ef..a3c87ff702 100644 --- a/libs/ardour/ardour/midi_port.h +++ b/libs/ardour/ardour/midi_port.h @@ -21,29 +21,40 @@ #ifndef __ardour_midi_port_h__ #define __ardour_midi_port_h__ -#include +#include +#include namespace ARDOUR { class MidiEngine; -class MidiPort : public BaseMidiPort, public PortFacade { +class MidiPort : public Port { public: ~MidiPort(); - void reset (); + DataType type () const { + return DataType::MIDI; + } void cycle_start (nframes_t nframes, nframes_t offset); void cycle_end (nframes_t nframes, nframes_t offset); void flush_buffers (nframes_t nframes, nframes_t offset); + Buffer& get_buffer (nframes_t nframes, nframes_t offset) { + return get_midi_buffer (nframes, offset); + } + MidiBuffer& get_midi_buffer( nframes_t nframes, nframes_t offset ); protected: friend class AudioEngine; MidiPort (const std::string& name, Flags, bool external, nframes_t bufsize); + private: + void mixdown (nframes_t, nframes_t, bool); + + MidiBuffer* _buffer; bool _has_been_mixed_down; }; diff --git a/libs/ardour/ardour/port.h b/libs/ardour/ardour/port.h index 6bd607c334..cf62429db3 100644 --- a/libs/ardour/ardour/port.h +++ b/libs/ardour/ardour/port.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2002 Paul Davis + Copyright (C) 2009 Paul Davis This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -20,167 +20,118 @@ #ifndef __ardour_port_h__ #define __ardour_port_h__ +#include "ardour/data_type.h" +#include "ardour/types.h" +#include +#include +#include #include #include -#include -#include -#include -#include -#include -#include -#include -#include namespace ARDOUR { class AudioEngine; -class Buffer; +class Buffer; -/** Abstract base for ports - */ -class Port : public virtual PBD::Destructible { - public: +class Port : public sigc::trackable +{ +public: enum Flags { IsInput = JackPortIsInput, IsOutput = JackPortIsOutput, - IsPhysical = JackPortIsPhysical, - IsTerminal = JackPortIsTerminal, - CanMonitor = JackPortCanMonitor }; - virtual ~Port(); + virtual ~Port (); - std::string name() const { + /** @return Port name (excluding prefix) */ + std::string name () const { return _name; } - Flags flags() const { + int set_name (std::string const &); + + /** @return flags */ + Flags flags () const { return _flags; } - bool receives_input() const { + /** @return true if this Port receives input, otherwise false */ + bool receives_input () const { return _flags & IsInput; } + /** @return true if this Port sends output, otherwise false */ bool sends_output () const { return _flags & IsOutput; } - bool can_monitor () const { - return _flags & CanMonitor; + /* @return true if this port is visible outside Ardour (via JACK) */ + bool external () const { + return _jack_port != 0; } - void enable_metering() { - _metering++; - } - - void disable_metering () { - if (_metering) { _metering--; } - } - - virtual void cycle_start (nframes_t nframes, nframes_t offset) {} - virtual void cycle_end (nframes_t nframes, nframes_t offset) {} - virtual void flush_buffers (nframes_t nframes, nframes_t offset ) {} - virtual DataType type() const = 0; - virtual Buffer& get_buffer( nframes_t nframes, nframes_t offset ) = 0; - - virtual bool connected () const; - virtual bool connected_to (const std::string& portname) const; - virtual int get_connections (std::vector&) 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 MonitorInputChanged; - sigc::signal 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 _connections; - - static AudioEngine* engine; - - private: - - void port_going_away (Port *); -}; - -class PortConnectableByName { - public: - PortConnectableByName() {} - virtual ~PortConnectableByName() {} - - virtual int connect (const std::string& other_name) = 0; - virtual int disconnect (const std::string& other_name) = 0; -}; - -class PortFacade : public virtual Port, public PortConnectableByName { - public: - PortFacade (const std::string& name, Flags flgs) : Port (name, flgs), _ext_port (0) {} - ~PortFacade() {} - - void reset (); - int reestablish (); - int reconnect (); - - int connect (Port& other); - int disconnect (Port& other); - int disconnect_all (); - - int connect (const std::string& other_name); - int disconnect (const std::string& other_name); - bool connected () const; - bool connected_to (const std::string& portname) const; - int get_connections (std::vector&) const; + int disconnect_all (); + int get_connections (std::vector &) const; - std::string short_name() const; - int set_name (const std::string& str); - bool monitoring_input () const; - void ensure_monitor_input (bool yn); - void request_monitor_input (bool yn); - nframes_t latency () const; - nframes_t total_latency () const; - void set_latency (nframes_t nframes); + /* connection by name */ + bool connected_to (std::string const &) const; + int connect (std::string const &); + int disconnect (std::string const &); - protected: - Port* _ext_port; + /* connection by Port* */ + bool connected_to (Port *) const; + int connect (Port *); + int disconnect (Port *); + + void ensure_monitor_input (bool); + bool monitoring_input () const; + nframes_t total_latency () const; + int reestablish (); + int reconnect (); + void set_latency (nframes_t); + void request_monitor_input (bool); + void make_external (); + + virtual void reset (); + + virtual DataType type () const = 0; + virtual void cycle_start (nframes_t, nframes_t) = 0; + virtual void cycle_end (nframes_t, nframes_t) = 0; + virtual Buffer& get_buffer (nframes_t, nframes_t) = 0; + virtual void flush_buffers (nframes_t, nframes_t) {} + + static void set_engine (AudioEngine *); + + sigc::signal 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 _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 _named_connections; }; -} // namespace ARDOUR +} -#endif /* __ardour_port_h__ */ +#endif diff --git a/libs/ardour/ardour/port_set.h b/libs/ardour/ardour/port_set.h index 51673472c3..7b9e716e4a 100644 --- a/libs/ardour/ardour/port_set.h +++ b/libs/ardour/ardour/port_set.h @@ -20,13 +20,13 @@ #define __ardour_port_set_h__ #include -#include -#include -#include #include namespace ARDOUR { +class Port; +class AudioPort; +class MidiPort; /** An ordered list of Ports, possibly of various types. * diff --git a/libs/ardour/audio_diskstream.cc b/libs/ardour/audio_diskstream.cc index 36903f7699..0661cb27a9 100644 --- a/libs/ardour/audio_diskstream.cc +++ b/libs/ardour/audio_diskstream.cc @@ -52,6 +52,7 @@ #include #include #include +#include #include "i18n.h" #include diff --git a/libs/ardour/audio_port.cc b/libs/ardour/audio_port.cc index 7e57a734b8..55d65d850d 100644 --- a/libs/ardour/audio_port.cc +++ b/libs/ardour/audio_port.cc @@ -18,118 +18,86 @@ #include #include -#include #include #include +#include using namespace ARDOUR; using namespace std; -AudioPort::AudioPort (const std::string& name, Flags flags, bool external, nframes_t capacity) - : Port (name, flags) - , BaseAudioPort (name, flags) - , PortFacade (name, flags) - , _has_been_mixed_down( false ) +AudioPort::AudioPort (const std::string& name, Flags flags, bool ext, nframes_t capacity) + : Port (name, DataType::AUDIO, flags, ext) + , _has_been_mixed_down (false) + , _buffer (0) { - if (!external || receives_input()) { - - /* internal-only and input ports need their own buffers. - external output ports use the external port buffer. - */ - - _buffer = new AudioBuffer (capacity); - _own_buffer = true; - } - - if (!external) { - - _ext_port = 0; - set_name (name); + assert (name.find_first_of (':') == string::npos); + + if (external ()) { + + /* external ports use the external port buffer */ + _buffer = new AudioBuffer (0); } else { + + /* internal ports need their own buffers */ + _buffer = new AudioBuffer (capacity); - /* make the JackAudioPort create its own buffer. For input, - we will copy from it during cycle_start(). For output, - we will set up our buffer to point to its buffer, which - will in turn be using the JACK port buffer for data. - */ - - _ext_port = new JackAudioPort (name, flags, 0); - - //if (sends_output()) { - // _buffer = &dynamic_cast(_ext_port)->get_audio_buffer( nframes, offset ); - //} - - Port::set_name (_ext_port->name()); } - - reset (); + } AudioPort::~AudioPort() { - delete _ext_port; - _ext_port = 0; + delete _buffer; } -void -AudioPort::reset() -{ - BaseAudioPort::reset(); - - if (_ext_port) { - _ext_port->reset (); - } -} - - void AudioPort::cycle_start (nframes_t nframes, nframes_t offset) { /* caller must hold process lock */ - if (_ext_port) { - _ext_port->cycle_start (nframes, offset); - } _has_been_mixed_down = false; + + if (external ()) { + /* external ports use JACK's memory */ + _buffer->set_data ((Sample *) jack_port_get_buffer (_jack_port, nframes), nframes + offset); + } } AudioBuffer & -AudioPort::get_audio_buffer( nframes_t nframes, nframes_t offset ) { +AudioPort::get_audio_buffer (nframes_t nframes, nframes_t offset) +{ + /* caller must hold process lock */ - if (_has_been_mixed_down) + if (_has_been_mixed_down) { return *_buffer; - - if (_flags & IsInput) { - - if (_ext_port) { - _buffer->read_from (dynamic_cast(_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(_ext_port)->get_audio_buffer( nframes, offset )); - } - if (nframes) - _buffer->silence (nframes, offset); } - if (nframes) + + if (receives_input ()) { + + /* INPUT */ + + /* If we're external (), we have some data in our buffer set up by JACK; + otherwise, we have an undefined buffer. In either case we mix down + our non-JACK inputs; either accumulating into the JACK data or + overwriting the undefined data */ + + mixdown (nframes, offset, !external ()); + + } else { + + /* OUTPUT */ + + if (!external ()) { + /* start internal output buffers with silence */ + _buffer->silence (nframes, offset); + } + + } + + if (nframes) { _has_been_mixed_down = true; + } return *_buffer; } @@ -137,5 +105,38 @@ AudioPort::get_audio_buffer( nframes_t nframes, nframes_t offset ) { void AudioPort::cycle_end (nframes_t nframes, nframes_t offset) { - _has_been_mixed_down=false; + _has_been_mixed_down = false; +} + +void +AudioPort::mixdown (nframes_t cnt, nframes_t offset, bool first_overwrite) +{ + if (_connections.empty()) { + if (first_overwrite) { + _buffer->silence (cnt, offset); + } + return; + } + + set::const_iterator p = _connections.begin(); + + if (first_overwrite) { + _buffer->read_from (dynamic_cast(*p)->get_audio_buffer (cnt, offset), cnt, offset); + ++p; + } + + for (; p != _connections.end (); ++p) { + _buffer->accumulate_from (dynamic_cast(*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 (); + } } diff --git a/libs/ardour/audio_track.cc b/libs/ardour/audio_track.cc index 816f08cbd5..e1c21a5d63 100644 --- a/libs/ardour/audio_track.cc +++ b/libs/ardour/audio_track.cc @@ -39,6 +39,7 @@ #include #include #include +#include #include "i18n.h" using namespace std; diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc index 0c36db6b01..095fb205c1 100644 --- a/libs/ardour/audioengine.cc +++ b/libs/ardour/audioengine.cc @@ -34,10 +34,8 @@ #include #include #include -#include -#include -#include #include +#include #include #include #include @@ -356,6 +354,7 @@ AudioEngine::process_callback (nframes_t nframes) which requires interleaving with route processing. */ + /* XXX: we're running this on both inputs and outputs... */ (*i)->cycle_start (nframes, 0); } @@ -619,21 +618,6 @@ AudioEngine::register_port (DataType dtype, const string& portname, bool input, } } -Port* -AudioEngine::get_port (const std::string& full_name) -{ - boost::shared_ptr p = ports.reader(); - - for (Ports::iterator i = p->begin(); i != p->end(); ++i) { - //cerr << "comparing port name '" << (*i)->name() << "' with '" << full_name << "'" << endl; - if ((*i)->name() == full_name) { - return *i; - } - } - return 0; -} - - Port * AudioEngine::register_input_port (DataType type, const string& portname, bool publish) { @@ -692,6 +676,8 @@ AudioEngine::unregister_port (Port& port) int AudioEngine::connect (const string& source, const string& destination) { + /* caller must hold process lock */ + int ret; if (!_running) { @@ -705,39 +691,24 @@ AudioEngine::connect (const string& source, const string& destination) string s = make_port_name_non_relative (source); string d = make_port_name_non_relative (destination); - - //cerr << "Trying to connect source: " << s << " with destination " << d << endl; - - Port* src = get_port (s); - Port* dst = get_port (d); + + Port* src = get_port_by_name_locked (s); + Port* dst = get_port_by_name_locked (d); if (src && dst) { /* both ports are known to us, so do the internal connect stuff */ - if ((ret = src->connect (*dst)) == 0) { - ret = dst->connect (*src); - } + ret = src->connect (dst); } else if (src || dst) { /* one port is known to us, try to connect it to something external */ - PortConnectableByName* pcn; - string other; - if (src) { - pcn = dynamic_cast(src); - other = d; + ret = src->connect (d); } else { - pcn = dynamic_cast(dst); - other = s; - } - - if (pcn) { - ret = pcn->connect (other); - } else { - ret = -1; + ret = dst->connect (s); } } else { @@ -764,6 +735,8 @@ AudioEngine::connect (const string& source, const string& destination) int AudioEngine::disconnect (const string& source, const string& destination) { + /* caller must hold process lock */ + int ret; if (!_running) { @@ -778,39 +751,23 @@ AudioEngine::disconnect (const string& source, const string& destination) string s = make_port_name_non_relative (source); string d = make_port_name_non_relative (destination); - //cerr << "trying to disconnect port '" << s << "' from port '" << d << endl; - - Port* src = get_port (s); - Port* dst = get_port (d); + Port* src = get_port_by_name_locked (s); + Port* dst = get_port_by_name_locked (d); if (src && dst) { - /* both ports are known to us, so do the internal connect stuff */ + /* both ports are known to us, so do the internal disconnect stuff */ - if ((ret = src->disconnect (*dst)) == 0) { - ret = dst->disconnect (*src); - } + ret = src->disconnect (dst); } else if (src || dst) { - /* one port is known to us, try to connect it to something external */ - - - PortConnectableByName* pcn; - string other; + /* one port is known to us, try to disconnect it from something external */ if (src) { - pcn = dynamic_cast(src); - other = d; + ret = src->disconnect (d); } else { - pcn = dynamic_cast(dst); - other = s; - } - - if (pcn) { - ret = pcn->disconnect (other); - } else { - ret = -1; + ret = dst->disconnect (s); } } else { @@ -873,34 +830,53 @@ AudioEngine::frames_per_cycle () } } -/** Get a port by name. - * Note this can return NULL, it will NOT create a port if it is not found (any more). +/** @param name Full name of port (including prefix:) + * @return Corresponding Port*, or 0. This object remains the property of the AudioEngine + * so must not be deleted. */ Port * -AudioEngine::get_port_by_name (const string& portname, bool keep) +AudioEngine::get_port_by_name (const string& portname) { Glib::Mutex::Lock lm (_process_lock); + return get_port_by_name_locked (portname); +} + +Port * +AudioEngine::get_port_by_name_locked (const string& portname) +{ + /* caller must hold process lock */ if (!_running) { if (!_has_run) { - fatal << _("get_port_by_name() called before engine was started") << endmsg; + fatal << _("get_port_by_name_locked() called before engine was started") << endmsg; /*NOTREACHED*/ } else { return 0; } } - + + if (portname.substr (0, jack_client_name.length ()) != jack_client_name) { + /* not an ardour: port */ + return 0; + } + + std::string const rel = make_port_name_relative (portname); + boost::shared_ptr pr = ports.reader(); - + for (Ports::iterator i = pr->begin(); i != pr->end(); ++i) { - if (portname == (*i)->name()) { - return (*i); + if (rel == (*i)->name()) { + return *i; } } return 0; } + + + + const char ** AudioEngine::get_ports (const string& port_name_pattern, const string& type_name_pattern, uint32_t flags) { @@ -1071,12 +1047,6 @@ AudioEngine::get_nth_physical (DataType type, uint32_t n, int flag) return ret; } -ARDOUR::nframes_t -AudioEngine::get_port_total_latency (const Port& port) -{ - return port.total_latency (); -} - void AudioEngine::update_total_latency (const Port& port) { diff --git a/libs/ardour/base_audio_port.cc b/libs/ardour/base_audio_port.cc deleted file mode 100644 index 7110102db3..0000000000 --- a/libs/ardour/base_audio_port.cc +++ /dev/null @@ -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 -#include -#include -#include -#include - -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& ports, AudioBuffer* dest, nframes_t cnt, nframes_t offset, bool first_overwrite) -{ - set::const_iterator p = ports.begin(); - - if (first_overwrite) { - dest->read_from ((dynamic_cast(*p))->get_audio_buffer( cnt, offset ), cnt, offset); - p++; - } - - for (; p != ports.end(); ++p) { - dest->accumulate_from ((dynamic_cast(*p))->get_audio_buffer( cnt, offset ), cnt, offset); - } -} - -void -BaseAudioPort::set_mixdown_function (void (*func)(const set&, AudioBuffer*, nframes_t, nframes_t, bool)) -{ - g_atomic_pointer_set(&_mixdown, func); -} - - diff --git a/libs/ardour/base_midi_port.cc b/libs/ardour/base_midi_port.cc deleted file mode 100644 index 0ba4b7c7b2..0000000000 --- a/libs/ardour/base_midi_port.cc +++ /dev/null @@ -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 -#include -#include -#include -#include - -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& ports, MidiBuffer* dest, nframes_t cnt, nframes_t offset, bool first_overwrite) -{ - set::const_iterator p = ports.begin(); - - if (first_overwrite) { - cout << "first overwrite" << endl; - dest->read_from ((dynamic_cast(*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(*p))->get_midi_buffer(cnt, offset)); - } -} - -void -BaseMidiPort::set_mixdown_function (void (*func)(const set&, MidiBuffer*, nframes_t, nframes_t, bool)) -{ - g_atomic_pointer_set(&_mixdown, func); -} diff --git a/libs/ardour/export_channel.cc b/libs/ardour/export_channel.cc index 865c8fbf3b..ccb481dc8f 100644 --- a/libs/ardour/export_channel.cc +++ b/libs/ardour/export_channel.cc @@ -22,6 +22,8 @@ #include #include +#include +#include using namespace ARDOUR; diff --git a/libs/ardour/internal_audio_port.cc b/libs/ardour/internal_audio_port.cc deleted file mode 100644 index e5362cde95..0000000000 --- a/libs/ardour/internal_audio_port.cc +++ /dev/null @@ -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 -#include -#include - -using namespace ARDOUR; -using namespace std; - -void -InternalAudioPort::default_mixdown (const list& ports, AudioBuffer& dest, nframes_t cnt, nframes_t offset) -{ - list::const_iterator p = ports.begin(); - - dest.read_from ((dynamic_cast(*p))->get_audio_buffer(), cnt, offset); - - for (; p != ports.end(); ++p) { - dest.accumulate_from ((dynamic_cast(*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&, 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; -} diff --git a/libs/ardour/internal_port.cc b/libs/ardour/internal_port.cc deleted file mode 100644 index cec11742e0..0000000000 --- a/libs/ardour/internal_port.cc +++ /dev/null @@ -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 -#include -#include - -#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::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::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::const_iterator p = _connections.begin(); p != _connections.end(); ) { - list::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; -} - diff --git a/libs/ardour/io.cc b/libs/ardour/io.cc index 2b8f12680f..671ade36ea 100644 --- a/libs/ardour/io.cc +++ b/libs/ardour/io.cc @@ -1965,13 +1965,13 @@ IO::set_name (const string& requested_name) } for (PortSet::iterator i = _inputs.begin(); i != _inputs.end(); ++i) { - string current_name = i->short_name(); + string current_name = i->name(); current_name.replace (current_name.find (_name), _name.length(), name); i->set_name (current_name); } for (PortSet::iterator i = _outputs.begin(); i != _outputs.end(); ++i) { - string current_name = i->short_name(); + string current_name = i->name(); current_name.replace (current_name.find (_name), _name.length(), name); i->set_name (current_name); } @@ -2028,7 +2028,7 @@ IO::output_latency () const /* io lock not taken - must be protected by other means */ for (PortSet::const_iterator i = _outputs.begin(); i != _outputs.end(); ++i) { - if ((latency = _session.engine().get_port_total_latency (*i)) > max_latency) { + if ((latency = i->total_latency ()) > max_latency) { max_latency = latency; } } @@ -2047,7 +2047,7 @@ IO::input_latency () const /* io lock not taken - must be protected by other means */ for (PortSet::const_iterator i = _inputs.begin(); i != _inputs.end(); ++i) { - if ((latency = _session.engine().get_port_total_latency (*i)) > max_latency) { + if ((latency = i->total_latency ()) > max_latency) { max_latency = latency; } } @@ -2473,7 +2473,7 @@ IO::find_input_port_hole (const char* base) snprintf (buf, jack_port_name_size(), _("%s %u"), base, n); for ( ; i != _inputs.end(); ++i) { - if (i->short_name() == buf) { + if (i->name() == buf) { break; } } @@ -2506,7 +2506,7 @@ IO::find_output_port_hole (const char* base) snprintf (buf, jack_port_name_size(), _("%s %u"), base, n); for ( ; i != _outputs.end(); ++i) { - if (i->short_name() == buf) { + if (i->name() == buf) { break; } } diff --git a/libs/ardour/jack_audio_port.cc b/libs/ardour/jack_audio_port.cc deleted file mode 100644 index ed52eada9c..0000000000 --- a/libs/ardour/jack_audio_port.cc +++ /dev/null @@ -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 -#include -#include - -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; -} diff --git a/libs/ardour/jack_midi_port.cc b/libs/ardour/jack_midi_port.cc deleted file mode 100644 index 4b7b66c659..0000000000 --- a/libs/ardour/jack_midi_port.cc +++ /dev/null @@ -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 -#include - -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()); - } -} diff --git a/libs/ardour/jack_port.cc b/libs/ardour/jack_port.cc deleted file mode 100644 index 5fac52af68..0000000000 --- a/libs/ardour/jack_port.cc +++ /dev/null @@ -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 - -#include -#include - -#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::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::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& 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; -} diff --git a/libs/ardour/meter.cc b/libs/ardour/meter.cc index ebfefeee36..3a2ac2e77b 100644 --- a/libs/ardour/meter.cc +++ b/libs/ardour/meter.cc @@ -23,8 +23,9 @@ #include #include #include -#include #include +#include +#include namespace ARDOUR { diff --git a/libs/ardour/midi_port.cc b/libs/ardour/midi_port.cc index 93ea3b7c60..23fff7c976 100644 --- a/libs/ardour/midi_port.cc +++ b/libs/ardour/midi_port.cc @@ -20,76 +20,74 @@ #include #include -#include #include using namespace ARDOUR; using namespace std; -MidiPort::MidiPort (const std::string& name, Flags flags, bool external, nframes_t capacity) - : Port (name, flags) - , BaseMidiPort (name, flags) - , PortFacade (name, flags) +MidiPort::MidiPort (const std::string& name, Flags flags, bool ext, nframes_t capacity) + : Port (name, DataType::MIDI, flags, ext) , _has_been_mixed_down (false) { // FIXME: size kludge (see BufferSet::ensure_buffers) // Jack needs to tell us this _buffer = new MidiBuffer (capacity * 8); - - if (external) { - /* external ports use the same buffer for the jack port (_ext_port) - * and internal ports (this) */ - _ext_port = new JackMidiPort (name, flags, _buffer); - Port::set_name (_ext_port->name()); - } else { - /* internal ports just have a single buffer, no jack port */ - _ext_port = 0; - set_name (name); - } - - reset (); } MidiPort::~MidiPort() { - delete _ext_port; - _ext_port = 0; + delete _buffer; } -void -MidiPort::reset() -{ - BaseMidiPort::reset(); - - if (_ext_port) { - _ext_port->reset (); - } -} void MidiPort::cycle_start (nframes_t nframes, nframes_t offset) { - if (_ext_port) { - _ext_port->cycle_start (nframes, offset); + if (external ()) { + _buffer->clear (); + assert (_buffer->size () == 0); + + if (sends_output ()) { + jack_midi_clear_buffer (jack_port_get_buffer (_jack_port, nframes)); + } } } MidiBuffer & MidiPort::get_midi_buffer( nframes_t nframes, nframes_t offset ) { - if (_has_been_mixed_down) + if (_has_been_mixed_down) { return *_buffer; + } - if (_flags & IsInput) { + if (receives_input ()) { - if (_ext_port) { + if (external ()) { - BaseMidiPort* mprt = dynamic_cast(_ext_port); - assert(mprt); - assert(&mprt->get_midi_buffer(nframes,offset) == _buffer); + void* jack_buffer = jack_port_get_buffer (_jack_port, nframes); + const nframes_t event_count = jack_midi_get_event_count(jack_buffer); + + assert (event_count < _buffer->capacity()); + + jack_midi_event_t ev; + + for (nframes_t i = 0; i < event_count; ++i) { + + jack_midi_event_get (&ev, jack_buffer, i); + + // i guess this should do but i leave it off to test the rest first. + //if (ev.time > offset && ev.time < offset+nframes) + _buffer->push_back (ev); + } + + assert(_buffer->size() == event_count); + + if (nframes) { + _has_been_mixed_down = true; + } if (!_connections.empty()) { - (*_mixdown) (_connections, _buffer, nframes, offset, false); + mixdown (nframes, offset, false); } } else { @@ -97,15 +95,17 @@ MidiPort::get_midi_buffer( nframes_t nframes, nframes_t offset ) { if (_connections.empty()) { _buffer->silence (nframes, offset); } else { - (*_mixdown) (_connections, _buffer, nframes, offset, true); + mixdown (nframes, offset, true); } } } else { _buffer->silence (nframes, offset); } - if (nframes) + + if (nframes) { _has_been_mixed_down = true; + } return *_buffer; } @@ -114,16 +114,65 @@ MidiPort::get_midi_buffer( nframes_t nframes, nframes_t offset ) { void MidiPort::cycle_end (nframes_t nframes, nframes_t offset) { - if (_ext_port) { - _ext_port->cycle_end (nframes, offset); +#if 0 + + if (external () && sends_output ()) { + /* FIXME: offset */ + + // We're an output - copy events from source buffer to Jack buffer + + void* jack_buffer = jack_port_get_buffer (_jack_port, nframes); + + jack_midi_clear_buffer (jack_buffer); + + for (MidiBuffer::iterator i = _buffer->begin(); i != _buffer->end(); ++i) { + const Evoral::Event& ev = *i; + + // event times should be frames, relative to cycle start + assert(ev.time() >= 0); + assert(ev.time() < nframes); + jack_midi_event_write (jack_buffer, (jack_nframes_t) ev.time(), ev.buffer(), ev.size()); + } } +#endif + _has_been_mixed_down = false; } void MidiPort::flush_buffers (nframes_t nframes, nframes_t offset) { - if (_ext_port) { - _ext_port->flush_buffers (nframes, offset); + /* FIXME: offset */ + + if (external () && sends_output ()) { + + void* jack_buffer = jack_port_get_buffer (_jack_port, nframes); + + for (MidiBuffer::iterator i = _buffer->begin(); i != _buffer->end(); ++i) { + const Evoral::Event& ev = *i; + // event times should be frames, relative to cycle start + assert(ev.time() >= 0); + assert(ev.time() < (nframes+offset)); + if (ev.time() >= offset) { + jack_midi_event_write (jack_buffer, (jack_nframes_t) ev.time(), ev.buffer(), ev.size()); + } + } + } +} + +void +MidiPort::mixdown (nframes_t cnt, nframes_t offset, bool first_overwrite) +{ + set::const_iterator p = _connections.begin(); + + if (first_overwrite) { + _buffer->read_from ((dynamic_cast(*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(*p))->get_midi_buffer (cnt, offset)); } } diff --git a/libs/ardour/mix.cc b/libs/ardour/mix.cc index 726d375453..4b9c31dc4f 100644 --- a/libs/ardour/mix.cc +++ b/libs/ardour/mix.cc @@ -21,6 +21,7 @@ #include #include #include +#include #include using namespace ARDOUR; diff --git a/libs/ardour/panner.cc b/libs/ardour/panner.cc index c5e28321bf..a7cf405190 100644 --- a/libs/ardour/panner.cc +++ b/libs/ardour/panner.cc @@ -44,6 +44,7 @@ #include #include +#include #include "i18n.h" diff --git a/libs/ardour/plugin_insert.cc b/libs/ardour/plugin_insert.cc index e199dbcec5..431c91762e 100644 --- a/libs/ardour/plugin_insert.cc +++ b/libs/ardour/plugin_insert.cc @@ -31,6 +31,7 @@ #include #include #include +#include #ifdef HAVE_SLV2 #include diff --git a/libs/ardour/port.cc b/libs/ardour/port.cc index f3e0739e83..208c391432 100644 --- a/libs/ardour/port.cc +++ b/libs/ardour/port.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2006 Paul Davis + Copyright (C) 2009 Paul Davis This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -17,101 +17,111 @@ */ -#include +#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 -using namespace ARDOUR; -using namespace std; +ARDOUR::AudioEngine* ARDOUR::Port::_engine = 0; -AudioEngine* Port::engine = 0; - -Port::Port (const std::string& name, Flags flgs) - : _flags (flgs) - , _name (name) - , _metering (0) - , _last_monitor (false) +ARDOUR::Port::Port (std::string const & n, DataType t, Flags f, bool e) : _jack_port (0), _last_monitor (false), _latency (0), _name (n), _flags (f) { -} - -Port::~Port () -{ - drop_references (); - disconnect_all (); -} - -void -Port::reset () -{ - _last_monitor = false; -} - -void -Port::set_engine (AudioEngine* e) -{ - engine = e; -} - -int -Port::connect (Port& other) -{ - /* caller must hold process lock */ - - pair::iterator,bool> result; - - result = _connections.insert (&other); - - if (result.second) { - other.GoingAway.connect (sigc::bind (mem_fun (*this, &Port::port_going_away), &other)); - return 0; - } else { - return 1; - } -} - -int -Port::disconnect (Port& other) -{ - /* caller must hold process lock */ + /* Unfortunately we have to pass the DataType into this constructor so that we can + create the right kind of JACK port; aside from this we'll use the virtual function type () + to establish type. */ - for (set::iterator i = _connections.begin(); i != _connections.end(); ++i) { - if ((*i) == &other) { - _connections.erase (i); - return 0; + if (e) { + try { + do_make_external (t); + } + catch (...) { + throw failed_constructor (); } } - - return -1; } +/** Port destructor */ +ARDOUR::Port::~Port () +{ + if (_jack_port) { + jack_port_unregister (_engine->jack (), _jack_port); + } +} + +/** Make this port externally visible by setting it up to use a JACK port. + * @param t Data type, so that we can call this method from the constructor. + */ +void +ARDOUR::Port::do_make_external (DataType t) +{ + if (_jack_port) { + /* already external */ + return; + } + + _jack_port = jack_port_register (_engine->jack (), _name.c_str (), t.to_jack_type (), _flags, 0); + if (_jack_port == 0) { + throw std::runtime_error ("Could not register JACK port"); + } +} + +void +ARDOUR::Port::make_external () +{ + do_make_external (type ()); +} + +/** @return true if this port is connected to anything */ +bool +ARDOUR::Port::connected () const +{ + if (!_connections.empty ()) { + /* connected to a Port* */ + return true; + } + + if (_jack_port == 0) { + /* not using a JACK port, so can't be connected to anything else */ + return false; + } + + return (jack_port_connected (_jack_port) != 0); +} int -Port::disconnect_all () +ARDOUR::Port::disconnect_all () { - /* caller must hold process lock */ + /* Disconnect from Port* connections */ + for (std::set::iterator i = _connections.begin (); i != _connections.end (); ++i) { + (*i)->_connections.erase (this); + } _connections.clear (); + + /* And JACK connections */ + jack_port_disconnect (_engine->jack(), _jack_port); + _named_connections.clear (); + return 0; } -void -Port::set_latency (nframes_t val) -{ - _latency = val; -} - +/** @param o Port name + * @return true if this port is connected to o, otherwise false. + */ bool -Port::connected() const +ARDOUR::Port::connected_to (std::string const & o) const { - /* caller must hold process lock */ - return !_connections.empty(); -} + if (_jack_port && jack_port_connected_to (_jack_port, o.c_str ())) { + /* connected via JACK */ + return true; + } -bool -Port::connected_to (const string& portname) const -{ - /* caller must hold process lock */ - - for (set::const_iterator p = _connections.begin(); p != _connections.end(); ++p) { - if ((*p)->name() == portname) { + for (std::set::iterator i = _connections.begin (); i != _connections.end (); ++i) { + if ((*i)->name () == o) { + /* connected internally */ return true; } } @@ -120,271 +130,259 @@ Port::connected_to (const string& portname) const } int -Port::get_connections (vector& names) const +ARDOUR::Port::get_connections (std::vector & c) const { - /* caller must hold process lock */ - int i = 0; - set::const_iterator p; + int n = 0; - for (i = 0, p = _connections.begin(); p != _connections.end(); ++p, ++i) { - names.push_back ((*p)->name()); - } - - return i; -} - -void -Port::port_going_away (Port* p) -{ - /* caller must hold process lock */ - - disconnect (*p); -} - - -//------------------------------------- - -int -PortFacade::set_name (const std::string& str) -{ - int ret; - - if (_ext_port) { - if ((ret = _ext_port->set_name (str)) == 0) { - _name = _ext_port->name(); + /* JACK connections */ + if (_jack_port) { + const char** jc = jack_port_get_connections (_jack_port); + if (jc) { + for (int i = 0; jc[i]; ++i) { + c.push_back (jc[i]); + ++n; + } } - } else { - _name = str; - ret = 0; } - return ret; -} - -string -PortFacade::short_name () const -{ - if (_ext_port) { - return _ext_port->short_name(); - } else { - return _name; + /* Internal connections */ + for (std::set::iterator i = _connections.begin (); i != _connections.end (); ++i) { + c.push_back ((*i)->name ()); + ++n; } -} + return n; +} int -PortFacade::reestablish () +ARDOUR::Port::connect (std::string const & other) { - if (_ext_port) { - return _ext_port->reestablish (); + /* caller must hold process lock */ + + Port* p = _engine->get_port_by_name_locked (other); + + int r; + + if (p && !p->external ()) { + /* non-external Ardour port; connect using Port* */ + r = connect (p); } else { - return 0; + /* connect using name */ + + /* for this to work, we must be an external port */ + if (!external ()) { + make_external (); + } + + std::string const this_nr = _engine->make_port_name_non_relative (_name); + std::string const other_nr = _engine->make_port_name_non_relative (other); + + if (sends_output ()) { + r = jack_connect (_engine->jack (), this_nr.c_str (), other_nr.c_str ()); + } else { + r = jack_connect (_engine->jack (), other_nr.c_str (), this_nr.c_str()); + } + + if (r == 0) { + _named_connections.insert (other); + } } + + return r; +} + +int +ARDOUR::Port::disconnect (std::string const & other) +{ + /* caller must hold process lock */ + + Port* p = _engine->get_port_by_name_locked (other); + int r; + + if (p && !p->external ()) { + /* non-external Ardour port; disconnect using Port* */ + r = disconnect (p); + } else { + /* disconnect using name */ + + std::string const this_nr = _engine->make_port_name_non_relative (_name); + std::string const other_nr = _engine->make_port_name_non_relative (other); + + if (sends_output ()) { + r = jack_disconnect (_engine->jack (), this_nr.c_str (), other_nr.c_str ()); + } else { + r = jack_disconnect (_engine->jack (), other_nr.c_str (), this_nr.c_str ()); + } + + if (r == 0) { + _named_connections.erase (other); + } + } + + return r; } -int -PortFacade::reconnect() +bool +ARDOUR::Port::connected_to (Port *o) const { - if (_ext_port) { - return _ext_port->reconnect (); - } else { - return 0; + return connected_to (o->name ()); +} + +int +ARDOUR::Port::connect (Port* o) +{ + /* caller must hold process lock */ + + if (external () && o->external ()) { + /* we're both external; connect using name */ + return connect (o->name ()); } + + /* otherwise connect by Port* */ + _connections.insert (o); + o->_connections.insert (this); + + return 0; +} + +int +ARDOUR::Port::disconnect (Port* o) +{ + if (external () && o->external ()) { + /* we're both external; try disconnecting using name */ + int const r = disconnect (o->name ()); + if (r == 0) { + return 0; + } + } + + _connections.erase (o); + o->_connections.erase (this); + + return 0; } void -PortFacade::set_latency (nframes_t val) +ARDOUR::Port::set_engine (AudioEngine* e) { - if (_ext_port) { - _ext_port->set_latency (val); - } else { - _latency = val; - } + _engine = e; } -nframes_t -PortFacade::latency() const +void +ARDOUR::Port::ensure_monitor_input (bool yn) { - if (_ext_port) { - return _ext_port->latency(); - } else { - return _latency; - } -} - -nframes_t -PortFacade::total_latency() const -{ - if (_ext_port) { - return _ext_port->total_latency(); - } else { - return _latency; + if (_jack_port) { + jack_port_ensure_monitor (_jack_port, yn); } } bool -PortFacade::monitoring_input() const +ARDOUR::Port::monitoring_input () const { - if (_ext_port) { - return _ext_port->monitoring_input (); + if (_jack_port) { + return jack_port_monitoring_input (_jack_port); } else { return false; } } void -PortFacade::ensure_monitor_input (bool yn) +ARDOUR::Port::reset () { - if (_ext_port) { - _ext_port->ensure_monitor_input (yn); - } + _last_monitor = false; + + // XXX + // _metering = 0; + // reset_meters (); } void -PortFacade::request_monitor_input (bool yn) +ARDOUR::Port::recompute_total_latency () const { - if (_ext_port) { - _ext_port->request_monitor_input (yn); - } +#ifdef HAVE_JACK_RECOMPUTE_LATENCY + if (_jack_port) { + jack_recompute_total_latency (_engine->jack (), _jack_port); + } +#endif +} + +nframes_t +ARDOUR::Port::total_latency () const +{ + if (_jack_port) { + return jack_port_get_total_latency (_engine->jack (), _jack_port); + } else { + return _latency; + } } int -PortFacade::connect (Port& other) +ARDOUR::Port::reestablish () { - int ret; + if (!_jack_port) { + return 0; + } + + _jack_port = jack_port_register (_engine->jack(), _name.c_str(), type().to_jack_type(), _flags, 0); + + if (_jack_port == 0) { + PBD::error << string_compose (_("could not reregister %1"), _name) << endmsg; + return -1; + } + + reset (); + + return 0; +} + + +int +ARDOUR::Port::reconnect () +{ + /* caller must hold process lock; intended to be used only after reestablish() */ + + if (!_jack_port) { + return 0; + } - if (_ext_port) { - ret = _ext_port->connect (other); - } else { - ret = 0; + for (std::set::iterator i = _named_connections.begin(); i != _named_connections.end(); ++i) { + if (connect (*i)) { + return -1; + } } - if (ret == 0) { - ret = Port::connect (other); - } - - return ret; -} - -int -PortFacade::connect (const std::string& other) -{ - PortConnectableByName* pcn; - - if (!_ext_port) { - return -1; - } - - pcn = dynamic_cast(_ext_port); - - if (pcn) { - return pcn->connect (other); - } else { - return -1; - } + return 0; } int -PortFacade::disconnect (Port& other) +ARDOUR::Port::set_name (std::string const & n) { - int reta; - int retb; + int r = 0; - if (_ext_port) { - reta = _ext_port->disconnect (other); + if (_jack_port) { + r = jack_port_set_name (_jack_port, n.c_str()); + if (r) { + _name = n; + } } else { - reta = 0; + _name = n; } - retb = Port::disconnect (other); - - return reta || retb; -} - -int -PortFacade::disconnect_all () -{ - int reta = 0; - int retb = 0; - - if (_ext_port) { - reta = _ext_port->disconnect_all (); - } - - retb = Port::disconnect_all (); - - return reta || retb; -} - -int -PortFacade::disconnect (const std::string& other) -{ - PortConnectableByName* pcn; - - if (!_ext_port) { - return -1; - } - - pcn = dynamic_cast(_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& names) const -{ - int i = 0; - - if (_ext_port) { - i = _ext_port->get_connections (names); - } - - i += Port::get_connections (names); - - return i; + return r; } void -PortFacade::reset () +ARDOUR::Port::set_latency (nframes_t n) { - Port::reset (); - - if (_ext_port) { - _ext_port->reset (); - } + _latency = n; } +void +ARDOUR::Port::request_monitor_input (bool yn) +{ + if (_jack_port) { + jack_port_request_monitor (_jack_port, yn); + } +} diff --git a/libs/ardour/port_set.cc b/libs/ardour/port_set.cc index 3182c2b959..12af468d9b 100644 --- a/libs/ardour/port_set.cc +++ b/libs/ardour/port_set.cc @@ -17,6 +17,8 @@ */ #include +#include +#include namespace ARDOUR { diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc index 2b4d264bbb..77d197ced5 100644 --- a/libs/ardour/session.cc +++ b/libs/ardour/session.cc @@ -81,6 +81,7 @@ #include #include #include +#include #include #include "i18n.h" diff --git a/libs/ardour/session_click.cc b/libs/ardour/session_click.cc index fde698803c..71e444893f 100644 --- a/libs/ardour/session_click.cc +++ b/libs/ardour/session_click.cc @@ -25,6 +25,7 @@ #include #include #include +#include #include diff --git a/libs/ardour/track.cc b/libs/ardour/track.cc index ed52fd70a9..ee44ce0c86 100644 --- a/libs/ardour/track.cc +++ b/libs/ardour/track.cc @@ -31,6 +31,7 @@ #include #include #include +#include #include "i18n.h"