Ardour  9.0-pre0-582-g084a23a80d
port_engine_shared.h
Go to the documentation of this file.
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 <atomic>
24 #include <map>
25 #include <memory>
26 #include <set>
27 #include <string>
28 #include <vector>
29 
30 #include "pbd/natsort.h"
31 #include "pbd/rcu.h"
32 
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 std::shared_ptr<BackendPort> BackendPortPtr;
45 typedef std::shared_ptr<BackendPort> const & BackendPortHandle;
46 
48 {
49  protected:
50  BackendPort (PortEngineSharedImpl& b, const std::string&, PortFlags);
51 
52  public:
53  virtual ~BackendPort ();
54 
55  const std::string& name () const { return _name; }
56  const std::string& pretty_name () const { return _pretty_name; }
57  const std::string& hw_port_name () const { return _hw_port_name; }
58 
59  int set_name (const std::string& name) {
60  _name = name;
61  return 0;
62  }
63 
64  /* called from PortEngineSharedImpl */
65  int set_pretty_name (const std::string& name) {
66  _pretty_name = name;
67  return 0;
68  }
69 
70  /* called from backends only */
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 
78  PortFlags flags () const { return _flags; }
79  bool is_input () const { return flags () & IsInput; }
80  bool is_output () const { return flags () & IsOutput; }
81  bool is_physical () const { return flags () & IsPhysical; }
82  bool is_terminal () const { return flags () & IsTerminal; }
83  bool is_connected () const { return _connections.size () != 0; }
84 
85  bool is_connected (BackendPortHandle port) const;
86  bool is_physically_connected () const;
87 
88  const std::set<BackendPortPtr>& get_connections () const {
89  return _connections;
90  }
91 
95 
96  virtual void* get_buffer (pframes_t nframes) = 0;
97 
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:
109 
110 private:
111  std::string _name;
112  std::string _pretty_name;
113  std::string _hw_port_name;
117  std::set<BackendPortPtr> _connections;
118 
121 
122 }; // class BackendPort
123 
125 {
126 public:
127  virtual ~BackendMIDIEvent () {}
128  virtual size_t size () const = 0;
129  virtual pframes_t timestamp () const = 0;
130  virtual const uint8_t* data () const = 0;
131  bool operator< (const BackendMIDIEvent &other) const;
132 };
133 
135 {
136 public:
137  PortEngineSharedImpl (PortManager& mgr, std::string const& instance_name);
139 
140  /* Discovering physical ports */
141 
143  void get_physical_outputs (DataType type, std::vector<std::string>&);
144  void get_physical_inputs (DataType type, std::vector<std::string>&);
147 
148  uint32_t port_name_size () const;
149 
150  int set_port_name (PortEngine::PortHandle, const std::string&);
153  PortEngine::PortPtr get_port_by_name (const std::string&) const;
154 
155  int get_port_property (PortEngine::PortHandle, const std::string& key, std::string& value, std::string& type) const;
156  int set_port_property (PortEngine::PortHandle, const std::string& key, const std::string& value, const std::string& type);
157 
158  int get_ports (const std::string& port_name_pattern, DataType type, PortFlags flags, std::vector<std::string>&) const;
159 
161 
164 
165  int connect (const std::string& src, const std::string& dst);
166  int disconnect (const std::string& src, const std::string& dst);
167  int connect (PortEngine::PortHandle, const std::string&);
168  int disconnect (PortEngine::PortHandle, const std::string&);
170 
171  bool connected (PortEngine::PortHandle, bool process_callback_safe);
172  bool connected_to (PortEngine::PortHandle, const std::string&, bool process_callback_safe);
173  bool physically_connected (PortEngine::PortHandle, bool process_callback_safe);
174  int get_connections (PortEngine::PortHandle, std::vector<std::string>&, bool process_callback_safe);
175 
176 protected:
177  friend class BackendPort;
178  std::string _instance_name;
179 
180  std::vector<BackendPortPtr> _system_inputs;
181  std::vector<BackendPortPtr> _system_outputs;
182  std::vector<BackendPortPtr> _system_midi_in;
183  std::vector<BackendPortPtr> _system_midi_out;
184 
186  std::string a;
187  std::string b;
188  bool c;
189 
190  PortConnectData (const std::string& a, const std::string& b, bool c)
191  : a (a) , b (b) , c (c) {}
192  };
193 
194  std::vector<PortConnectData *> _port_connection_queue;
195  pthread_mutex_t _port_callback_mutex;
196 
197  std::atomic<int> _port_change_flag; /* atomic */
198 
199  void port_connect_callback (const std::string& a, const std::string& b, bool conn) {
200  pthread_mutex_lock (&_port_callback_mutex);
201  _port_connection_queue.push_back(new PortConnectData(a, b, conn));
202  pthread_mutex_unlock (&_port_callback_mutex);
203  }
204 
206 
208  _port_change_flag.store (1);
209  }
210 
212 
213  void clear_ports ();
214 
215  BackendPortPtr add_port (const std::string& shortname, ARDOUR::DataType, ARDOUR::PortFlags);
216  void unregister_ports (bool system_only = false);
217 
218  struct SortByPortName {
219  bool operator() (BackendPortHandle lhs, BackendPortHandle rhs) const {
220  return PBD::naturally_less (lhs->name ().c_str (), rhs->name ().c_str ());
221  }
222  };
223 
224  typedef std::map<std::string, BackendPortPtr> PortMap; // fast-lookup by name
225  typedef std::set<BackendPortPtr, SortByPortName> PortIndex; // name-based
226  typedef std::set<BackendPortPtr> PortRegistry; // std::less<>, safe during rename
227 
231 
232  bool valid_port (BackendPortHandle port) const {
233  std::shared_ptr<PortRegistry const> p = _portregistry.reader ();
234  return p->find (port) != p->end ();
235  }
236 
237  BackendPortPtr find_port (const std::string& port_name) const {
238  std::shared_ptr<PortMap const> p = _portmap.reader ();
239  PortMap::const_iterator it = p->find (port_name);
240  if (it == p->end ()) {
241  return BackendPortPtr();
242  }
243  return (*it).second;
244  }
245 
246  virtual BackendPort* port_factory (std::string const& name, ARDOUR::DataType dt, ARDOUR::PortFlags flags) = 0;
247 
248 #ifndef NDEBUG
249  void list_ports () const;
250 #endif
251 };
252 
253 } /* namespace ARDOUR */
254 
255 #endif
virtual size_t size() const =0
virtual pframes_t timestamp() const =0
virtual const uint8_t * data() const =0
PortEngineSharedImpl & _backend
bool is_physically_connected() const
int set_pretty_name(const std::string &name)
LatencyRange _capture_latency_range
const std::string & name() const
bool is_connected(BackendPortHandle port) const
int set_name(const std::string &name)
const PortFlags _flags
void set_latency_range(const LatencyRange &latency_range, bool for_playback)
virtual void * get_buffer(pframes_t nframes)=0
void remove_connection(BackendPortHandle)
int connect(BackendPortHandle port, BackendPortHandle self)
PortFlags flags() const
const std::set< BackendPortPtr > & get_connections() const
void store_connection(BackendPortHandle)
LatencyRange _playback_latency_range
virtual DataType type() const =0
void disconnect_all(BackendPortHandle self)
const std::string & pretty_name() const
int disconnect(BackendPortHandle port, BackendPortHandle self)
std::set< BackendPortPtr > _connections
BackendPort(PortEngineSharedImpl &b, const std::string &, PortFlags)
void update_connected_latency(bool for_playback)
const std::string & hw_port_name() const
virtual ~BackendPort()
const LatencyRange latency_range(bool for_playback) const
int set_hw_port_name(const std::string &name)
std::vector< BackendPortPtr > _system_inputs
std::vector< BackendPortPtr > _system_outputs
std::vector< BackendPortPtr > _system_midi_out
int set_port_name(PortEngine::PortHandle, const std::string &)
int connect(PortEngine::PortHandle, const std::string &)
uint32_t port_name_size() const
virtual void unregister_port(PortEngine::PortHandle)
SerializedRCUManager< PortIndex > _ports
bool physically_connected(PortEngine::PortHandle, bool process_callback_safe)
std::set< BackendPortPtr, SortByPortName > PortIndex
virtual void update_system_port_latencies()
BackendPortPtr add_port(const std::string &shortname, ARDOUR::DataType, ARDOUR::PortFlags)
int disconnect(const std::string &src, const std::string &dst)
PortEngine::PortPtr get_port_by_name(const std::string &) const
int get_ports(const std::string &port_name_pattern, DataType type, PortFlags flags, std::vector< std::string > &) const
int connect(const std::string &src, const std::string &dst)
ChanCount n_physical_outputs() const
int disconnect(PortEngine::PortHandle, const std::string &)
PortFlags get_port_flags(PortEngine::PortHandle) const
bool connected_to(PortEngine::PortHandle, const std::string &, bool process_callback_safe)
void port_connect_callback(const std::string &a, const std::string &b, bool conn)
std::vector< BackendPortPtr > _system_midi_in
BackendPortPtr find_port(const std::string &port_name) const
std::atomic< int > _port_change_flag
bool valid_port(BackendPortHandle port) const
bool connected(PortEngine::PortHandle, bool process_callback_safe)
std::map< std::string, BackendPortPtr > PortMap
void process_connection_queue_locked(PortManager &mgr)
int get_connections(PortEngine::PortHandle, std::vector< std::string > &, bool process_callback_safe)
std::string get_port_name(PortEngine::PortHandle) const
ChanCount n_physical_inputs() const
SerializedRCUManager< PortMap > _portmap
PortEngineSharedImpl(PortManager &mgr, std::string const &instance_name)
std::set< BackendPortPtr > PortRegistry
void get_physical_outputs(DataType type, std::vector< std::string > &)
void unregister_ports(bool system_only=false)
SerializedRCUManager< PortRegistry > _portregistry
std::vector< PortConnectData * > _port_connection_queue
void get_physical_inputs(DataType type, std::vector< std::string > &)
DataType port_data_type(PortEngine::PortHandle) const
virtual BackendPort * port_factory(std::string const &name, ARDOUR::DataType dt, ARDOUR::PortFlags flags)=0
int disconnect_all(PortEngine::PortHandle)
bool port_is_physical(PortEngine::PortHandle) const
int get_port_property(PortEngine::PortHandle, const std::string &key, std::string &value, std::string &type) const
int set_port_property(PortEngine::PortHandle, const std::string &key, const std::string &value, const std::string &type)
PortEngine::PortPtr register_port(const std::string &shortname, ARDOUR::DataType, ARDOUR::PortFlags)
PortPtr const & PortHandle
Definition: port_engine.h:113
std::shared_ptr< ProtoPort > PortPtr
Definition: port_engine.h:107
std::shared_ptr< T const > reader() const
Definition: rcu.h:69
GtkImageIconNameData name
Definition: gtkimage.h:6
#define LIBARDOUR_API
uint32_t pframes_t
std::shared_ptr< BackendPort > const & BackendPortHandle
std::shared_ptr< BackendPort > BackendPortPtr
bool naturally_less(const char *a, const char *b)
Definition: natsort.h:174
PortConnectData(const std::string &a, const std::string &b, bool c)