1 /* 2 * Copyright (C) 2014-2019 Robin Gareus <robin@gareus.org> 3 * Copyright (C) 2015-2020 Paul Davis <paul@linuxaudiosystems.com> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License along 16 * with this program; if not, write to the Free Software Foundation, Inc., 17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 18 */ 19 20 #ifndef _libardour_port_engine_shared_h_ 21 #define _libardour_port_engine_shared_h_ 22 23 #include <map> 24 #include <set> 25 #include <string> 26 #include <vector> 27 28 #include <boost/shared_ptr.hpp> 29 30 #include "pbd/natsort.h" 31 #include "pbd/rcu.h" 32 33 #include "ardour/libardour_visibility.h" 34 #include "ardour/port_engine.h" 35 #include "ardour/types.h" 36 37 namespace ARDOUR { 38 39 class PortEngineSharedImpl; 40 class PortManager; 41 42 class BackendPort; 43 44 typedef boost::shared_ptr<BackendPort> BackendPortPtr; 45 typedef boost::shared_ptr<BackendPort> const & BackendPortHandle; 46 47 class LIBARDOUR_API BackendPort : public ProtoPort 48 { 49 protected: 50 BackendPort (PortEngineSharedImpl& b, const std::string&, PortFlags); 51 52 public: 53 virtual ~BackendPort (); 54 name()55 const std::string& name () const { return _name; } pretty_name()56 const std::string& pretty_name () const { return _pretty_name; } hw_port_name()57 const std::string& hw_port_name () const { return _hw_port_name; } 58 set_name(const std::string & name)59 int set_name (const std::string& name) { 60 _name = name; 61 return 0; 62 } 63 64 /* called from PortEngineSharedImpl */ set_pretty_name(const std::string & name)65 int set_pretty_name (const std::string& name) { 66 _pretty_name = name; 67 return 0; 68 } 69 70 /* called from backends only */ set_hw_port_name(const std::string & name)71 int set_hw_port_name (const std::string& name) { 72 _hw_port_name = name; 73 return 0; 74 } 75 76 virtual DataType type () const = 0; 77 flags()78 PortFlags flags () const { return _flags; } is_input()79 bool is_input () const { return flags () & IsInput; } is_output()80 bool is_output () const { return flags () & IsOutput; } is_physical()81 bool is_physical () const { return flags () & IsPhysical; } is_terminal()82 bool is_terminal () const { return flags () & IsTerminal; } is_connected()83 bool is_connected () const { return _connections.size () != 0; } 84 85 bool is_connected (BackendPortHandle port) const; 86 bool is_physically_connected () const; 87 get_connections()88 const std::set<BackendPortPtr>& get_connections () const { 89 return _connections; 90 } 91 92 int connect (BackendPortHandle port, BackendPortHandle self); 93 int disconnect (BackendPortHandle port, BackendPortHandle self); 94 void disconnect_all (BackendPortHandle self); 95 96 virtual void* get_buffer (pframes_t nframes) = 0; 97 latency_range(bool for_playback)98 const LatencyRange latency_range (bool for_playback) const 99 { 100 return for_playback ? _playback_latency_range : _capture_latency_range; 101 } 102 103 void set_latency_range (const LatencyRange& latency_range, bool for_playback); 104 105 void update_connected_latency (bool for_playback); 106 107 protected: 108 PortEngineSharedImpl& _backend; 109 110 private: 111 std::string _name; 112 std::string _pretty_name; 113 std::string _hw_port_name; 114 const PortFlags _flags; 115 LatencyRange _capture_latency_range; 116 LatencyRange _playback_latency_range; 117 std::set<BackendPortPtr> _connections; 118 119 void store_connection (BackendPortHandle); 120 void remove_connection (BackendPortHandle); 121 122 }; // class BackendPort 123 124 class LIBARDOUR_API PortEngineSharedImpl 125 { 126 public: 127 PortEngineSharedImpl (PortManager& mgr, std::string const& instance_name); 128 virtual ~PortEngineSharedImpl (); 129 130 /* Discovering physical ports */ 131 132 bool port_is_physical (PortEngine::PortHandle) const; 133 void get_physical_outputs (DataType type, std::vector<std::string>&); 134 void get_physical_inputs (DataType type, std::vector<std::string>&); 135 ChanCount n_physical_outputs () const; 136 ChanCount n_physical_inputs () const; 137 138 uint32_t port_name_size () const; 139 140 int set_port_name (PortEngine::PortHandle, const std::string&); 141 std::string get_port_name (PortEngine::PortHandle) const; 142 PortFlags get_port_flags (PortEngine::PortHandle) const; 143 PortEngine::PortPtr get_port_by_name (const std::string&) const; 144 145 int get_port_property (PortEngine::PortHandle, const std::string& key, std::string& value, std::string& type) const; 146 int set_port_property (PortEngine::PortHandle, const std::string& key, const std::string& value, const std::string& type); 147 148 int get_ports (const std::string& port_name_pattern, DataType type, PortFlags flags, std::vector<std::string>&) const; 149 150 DataType port_data_type (PortEngine::PortHandle) const; 151 152 PortEngine::PortPtr register_port (const std::string& shortname, ARDOUR::DataType, ARDOUR::PortFlags); 153 virtual void unregister_port (PortEngine::PortHandle); 154 155 int connect (const std::string& src, const std::string& dst); 156 int disconnect (const std::string& src, const std::string& dst); 157 int connect (PortEngine::PortHandle, const std::string&); 158 int disconnect (PortEngine::PortHandle, const std::string&); 159 int disconnect_all (PortEngine::PortHandle); 160 161 bool connected (PortEngine::PortHandle, bool process_callback_safe); 162 bool connected_to (PortEngine::PortHandle, const std::string&, bool process_callback_safe); 163 bool physically_connected (PortEngine::PortHandle, bool process_callback_safe); 164 int get_connections (PortEngine::PortHandle, std::vector<std::string>&, bool process_callback_safe); 165 166 protected: 167 friend class BackendPort; 168 std::string _instance_name; 169 170 std::vector<BackendPortPtr> _system_inputs; 171 std::vector<BackendPortPtr> _system_outputs; 172 std::vector<BackendPortPtr> _system_midi_in; 173 std::vector<BackendPortPtr> _system_midi_out; 174 175 struct PortConnectData { 176 std::string a; 177 std::string b; 178 bool c; 179 PortConnectDataPortConnectData180 PortConnectData (const std::string& a, const std::string& b, bool c) 181 : a (a) , b (b) , c (c) {} 182 }; 183 184 std::vector<PortConnectData *> _port_connection_queue; 185 pthread_mutex_t _port_callback_mutex; 186 187 GATOMIC_QUAL gint _port_change_flag; /* atomic */ 188 port_connect_callback(const std::string & a,const std::string & b,bool conn)189 void port_connect_callback (const std::string& a, const std::string& b, bool conn) { 190 pthread_mutex_lock (&_port_callback_mutex); 191 _port_connection_queue.push_back(new PortConnectData(a, b, conn)); 192 pthread_mutex_unlock (&_port_callback_mutex); 193 } 194 port_connect_add_remove_callback()195 void port_connect_add_remove_callback () { 196 g_atomic_int_set (&_port_change_flag, 1); 197 } 198 199 virtual void update_system_port_latencies (); 200 201 void clear_ports (); 202 203 BackendPortPtr add_port (const std::string& shortname, ARDOUR::DataType, ARDOUR::PortFlags); 204 void unregister_ports (bool system_only = false); 205 206 struct SortByPortName { operatorSortByPortName207 bool operator() (BackendPortHandle lhs, BackendPortHandle rhs) const { 208 return PBD::naturally_less (lhs->name ().c_str (), rhs->name ().c_str ()); 209 } 210 }; 211 212 typedef std::map<std::string, BackendPortPtr> PortMap; // fast lookup in _ports 213 typedef std::set<BackendPortPtr, SortByPortName> PortIndex; // fast lookup in _ports 214 SerializedRCUManager<PortMap> _portmap; 215 SerializedRCUManager<PortIndex> _ports; 216 valid_port(BackendPortHandle port)217 bool valid_port (BackendPortHandle port) const { 218 boost::shared_ptr<PortIndex> p = _ports.reader (); 219 return std::find (p->begin (), p->end (), port) != p->end (); 220 } 221 find_port(const std::string & port_name)222 BackendPortPtr find_port (const std::string& port_name) const { 223 boost::shared_ptr<PortMap> p = _portmap.reader (); 224 PortMap::const_iterator it = p->find (port_name); 225 if (it == p->end ()) { 226 return BackendPortPtr(); 227 } 228 return (*it).second; 229 } 230 231 virtual BackendPort* port_factory (std::string const& name, ARDOUR::DataType dt, ARDOUR::PortFlags flags) = 0; 232 233 #ifndef NDEBUG 234 void list_ports () const; 235 #endif 236 }; 237 238 } /* namespace ARDOUR */ 239 240 #endif 241