Ardour  8.12
port_manager.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2013-2019 Paul Davis <paul@linuxaudiosystems.com>
3  * Copyright (C) 2015-2017 Robin Gareus <robin@gareus.org>
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_manager_h__
21 #define __libardour_port_manager_h__
22 
23 #include <atomic>
24 #include <cstdint>
25 #include <exception>
26 #include <map>
27 #include <memory>
28 #include <string>
29 #include <vector>
30 
31 #include "pbd/natsort.h"
32 #include "pbd/rcu.h"
33 #include "pbd/ringbuffer.h"
34 
35 #include "ardour/chan_count.h"
37 #include "ardour/monitor_port.h"
38 #include "ardour/port.h"
39 
40 namespace ARDOUR {
41 
42 class PortEngine;
43 class AudioBackend;
44 class Session;
45 
46 class CircularSampleBuffer;
47 class CircularEventBuffer;
48 
50 {
51 public:
52  struct DPM {
53  DPM ()
54  {
55  reset ();
56  }
57  void reset ()
58  {
59  level = 0;
60  peak = 0;
61  }
64  };
65 
66  struct MPM {
67  MPM ()
68  {
69  reset ();
70  }
71  void reset ()
72  {
73  memset (chn_active, 0, sizeof (float) * 17);
74  }
75  bool active (int chn) const {
76  if (chn < 0 || chn > 16) {
77  return false;
78  }
79  return chn_active[chn] > 0.1;
80  }
81  /* 0..15: MIDI Channel Event, 16: System Common Message */
82  float chn_active[17];
83  };
84 
85  struct SortByPortName {
86  bool operator() (std::string const& a, std::string const& b) const {
87  return PBD::naturally_less (a.c_str (), b.c_str ());
88  }
89  };
90 
91  typedef std::map<std::string, std::shared_ptr<Port>, SortByPortName> Ports;
92  typedef std::list<std::shared_ptr<Port> > PortList;
93 
94  typedef std::shared_ptr<CircularSampleBuffer> AudioPortScope;
95  typedef std::shared_ptr<CircularEventBuffer> MIDIPortMonitor;
96  typedef std::shared_ptr<DPM> AudioPortMeter;
97  typedef std::shared_ptr<MPM> MIDIPortMeter;
98 
99  struct AudioInputPort {
103  void apply_falloff (pframes_t, samplecnt_t sr, bool reset = false);
105  void process (Sample const*, pframes_t, bool reset = false);
106  };
107 
108  struct MIDIInputPort {
112  void apply_falloff (pframes_t, samplecnt_t sr, bool reset = false);
113  void process_event (uint8_t const*, size_t);
114  };
115 
116  typedef std::map<std::string, AudioInputPort, SortByPortName> AudioInputPorts;
117  typedef std::map<std::string, MIDIInputPort, SortByPortName> MIDIInputPorts;
118 
120  virtual ~PortManager () {}
121 
123 
125 
126  uint32_t port_name_size () const;
127  std::string my_name () const;
128 
129  size_t total_port_count () const { return _ports.reader ()->size (); }
130  size_t session_port_count () const;
131 
132 #ifndef NDEBUG
133  void list_cycle_ports () const;
134  void list_all_ports () const;
135 #endif
136 
137  /* Port registration */
138 
139  std::shared_ptr<Port> register_input_port (DataType, const std::string& portname, bool async = false, PortFlags extra_flags = PortFlags (0));
140  std::shared_ptr<Port> register_output_port (DataType, const std::string& portname, bool async = false, PortFlags extra_flags = PortFlags (0));
141  int unregister_port (std::shared_ptr<Port>);
142 
143  /* Port connectivity */
144 
145  int connect (const std::string& source, const std::string& destination);
146  int disconnect (const std::string& source, const std::string& destination);
147  int disconnect (std::shared_ptr<Port>);
148  int disconnect (std::string const&);
151 
152  bool connected (const std::string&);
153  bool physically_connected (const std::string&);
154  int get_connections (const std::string&, std::vector<std::string>&, bool process_context_safe = true);
155 
156  /* Naming */
157 
158  std::shared_ptr<Port> get_port_by_name (const std::string&);
159  void port_renamed (const std::string&, const std::string&);
160  std::string make_port_name_relative (const std::string& name) const;
161  std::string make_port_name_non_relative (const std::string& name) const;
162  std::string get_pretty_name_by_name (const std::string& portname) const;
163  std::string get_hardware_port_name_by_name (const std::string& portname) const;
164  std::string short_port_name_from_port_name (std::string const& full_name) const;
165  bool port_is_mine (const std::string& fullname) const;
166 
167  static bool port_is_virtual_piano (std::string const&);
168  static bool port_is_control_only (std::string const&);
169  static bool port_is_physical_input_monitor_enable (std::string const&);
170 
171  /* other Port management */
172 
173  bool port_is_physical (const std::string&) const;
174  void get_physical_outputs (DataType type, std::vector<std::string>&,
175  MidiPortFlags include = MidiPortFlags (0),
176  MidiPortFlags exclude = MidiPortFlags (0));
177  void get_physical_inputs (DataType type, std::vector<std::string>&,
178  MidiPortFlags include = MidiPortFlags (0),
179  MidiPortFlags exclude = MidiPortFlags (0));
180 
183 
184  int get_ports (const std::string& port_name_pattern, DataType type, PortFlags flags, std::vector<std::string>&);
186 
187  void set_port_pretty_name (std::string const&, std::string const&);
188 
190 
192  void reinit (bool with_ratio = false);
193 
195 
196  virtual void add_pending_port_deletion (Port*) = 0;
197 
199  {
200  return _port_deletions_pending;
201  }
202 
203  bool check_for_ambiguous_latency (bool log = false) const;
204 
205  /* per-Port monitoring */
206 
208  void request_input_monitoring (const std::string&, bool) const;
209  void ensure_input_monitoring (const std::string&, bool) const;
210 
211  class PortRegistrationFailure : public std::exception
212  {
213  public:
214  PortRegistrationFailure (std::string const& why = "")
215  : reason (why) {}
216 
218 
219  const char* what () const throw ()
220  {
221  return reason.c_str ();
222  }
223 
224  private:
225  std::string reason;
226  };
227 
228  /* the port engine will invoke these callbacks when the time is right */
229 
232  void connect_callback (const std::string&, const std::string&, bool connection);
233 
235  {
236  return _port_remove_in_progress;
237  }
238 
239  MidiPortFlags midi_port_metadata (std::string const&);
240 
241  void get_configurable_midi_ports (std::vector<std::string>&, bool for_input);
242  void get_midi_selection_ports (std::vector<std::string>&);
243  void add_midi_port_flags (std::string const&, MidiPortFlags);
244  void remove_midi_port_flags (std::string const&, MidiPortFlags);
245 
247  PBD::Signal0<void> MidiSelectionPortsChanged;
249  PBD::Signal0<void> MidiPortInfoChanged;
251  PBD::Signal1<void, std::string> PortPrettyNameChanged;
252 
254  PBD::Signal0<void> GraphReordered;
255 
257  PBD::Signal0<void> PortRegisteredOrUnregistered;
258 
264  PBD::Signal5<void, std::weak_ptr<Port>, std::string, std::weak_ptr<Port>, std::string, bool> PortConnectedOrDisconnected;
265 
266  PBD::Signal3<void, DataType, std::vector<std::string>, bool> PhysInputChanged;
267 
268  /* Input port meters and monitors */
270 
273 
275  return _monitor_port;
276  }
277 
278 protected:
279  std::shared_ptr<AudioBackend> _backend;
280 
282 
285 
286  std::shared_ptr<Port> register_port (DataType type, const std::string& portname, bool input, bool async = false, PortFlags extra_flags = PortFlags (0));
287  void port_registration_failure (const std::string& portname);
288 
290  std::shared_ptr<Ports const> _cycle_ports;
291 
292  void silence (pframes_t nframes, Session* s = 0);
293  void silence_outputs (pframes_t nframes);
299  void cycle_start (pframes_t nframes, Session* s = 0);
300 
306  void cycle_end (pframes_t nframes, Session* s = 0);
307 
309 
310  static std::string port_info_file ();
311  static std::string midi_port_info_file ();
312 
313  void filter_midi_ports (std::vector<std::string>&, MidiPortFlags, MidiPortFlags);
314 
316 
317 private:
319  void set_pretty_names (std::vector<std::string> const&, DataType, bool);
321  void load_port_info ();
322  void save_port_info ();
323  void update_input_ports (bool);
324 
326 
327  struct PortID {
328  PortID (std::shared_ptr<AudioBackend>, DataType, bool, std::string const&);
329  PortID (XMLNode const&, bool old_midi_format = false);
330 
331  std::string backend;
332  std::string device_name;
333  std::string port_name;
335  bool input;
336 
337  XMLNode& state () const;
338 
339  bool operator< (PortID const& o) const {
340  if (backend != o.backend) {
341  return backend < o.backend;
342  }
343  if (device_name != o.device_name) {
344  return device_name < o.device_name;
345  }
346  if (port_name != o.port_name) {
347  return PBD::naturally_less (port_name.c_str (), o.port_name.c_str ());
348  }
349  if (input != o.input) {
350  return input;
351  }
352  return (uint32_t) data_type < (uint32_t) o.data_type;
353  }
354 
355  bool operator== (PortID const& o) const {
356  if (backend != o.backend) {
357  return false;
358  }
359  if (device_name != o.device_name) {
360  return false;
361  }
362  if (port_name != o.port_name) {
363  return false;
364  }
365  if (input != o.input) {
366  return false;
367  }
368  if (data_type != o.data_type) {
369  return false;
370  }
371  return true;
372  }
373  };
374 
375  struct PortMetaData {
376  PortMetaData () : properties (MidiPortFlags (0)) {}
378 
379  std::string pretty_name;
381  };
382 
383  typedef std::map<PortID, PortMetaData> PortInfo;
384 
385  mutable Glib::Threads::Mutex _port_info_mutex;
388 
391  std::atomic<int> _reset_meters;
392 };
393 
394 } // namespace ARDOUR
395 
396 #endif /* __libardour_port_manager_h__ */
PortRegistrationFailure(std::string const &why="")
Definition: port_manager.h:214
int disconnect(const std::string &source, const std::string &destination)
PBD::Signal3< void, DataType, std::vector< std::string >, bool > PhysInputChanged
Definition: port_manager.h:266
void request_input_monitoring(const std::string &, bool) const
std::string get_pretty_name_by_name(const std::string &portname) const
static bool port_is_control_only(std::string const &)
std::list< std::shared_ptr< Port > > PortList
Definition: port_manager.h:92
void connect_callback(const std::string &, const std::string &, bool connection)
void set_port_pretty_name(std::string const &, std::string const &)
void silence_outputs(pframes_t nframes)
static void falloff_cache_calc(pframes_t, samplecnt_t)
PBD::Signal0< void > PortRegisteredOrUnregistered
Definition: port_manager.h:257
AudioInputPorts audio_input_ports() const
std::map< PortID, PortMetaData > PortInfo
Definition: port_manager.h:383
virtual ~PortManager()
Definition: port_manager.h:120
static bool port_is_physical_input_monitor_enable(std::string const &)
void cycle_end(pframes_t nframes, Session *s=0)
void run_input_meters(pframes_t, samplecnt_t)
std::string my_name() const
bool connected(const std::string &)
std::shared_ptr< CircularSampleBuffer > AudioPortScope
Definition: port_manager.h:94
int get_connections(const std::string &, std::vector< std::string > &, bool process_context_safe=true)
std::string make_port_name_non_relative(const std::string &name) const
void update_input_ports(bool)
std::shared_ptr< Port > get_port_by_name(const std::string &)
bool port_remove_in_progress() const
Definition: port_manager.h:234
static std::string port_info_file()
PBD::RingBuffer< Port * > & port_deletions_pending()
Definition: port_manager.h:198
void set_pretty_names(std::vector< std::string > const &, DataType, bool)
std::string get_hardware_port_name_by_name(const std::string &portname) const
std::shared_ptr< AudioBackend > _backend
Definition: port_manager.h:279
std::shared_ptr< Port > register_input_port(DataType, const std::string &portname, bool async=false, PortFlags extra_flags=PortFlags(0))
MonitorPort _monitor_port
Definition: port_manager.h:325
size_t total_port_count() const
Definition: port_manager.h:129
void ensure_input_monitoring(const std::string &, bool) const
void add_midi_port_flags(std::string const &, MidiPortFlags)
void get_physical_inputs(DataType type, std::vector< std::string > &, MidiPortFlags include=MidiPortFlags(0), MidiPortFlags exclude=MidiPortFlags(0))
MidiPortFlags midi_port_metadata(std::string const &)
void list_cycle_ports() const
void fill_midi_port_info_locked()
void cycle_start(pframes_t nframes, Session *s=0)
int disconnect(std::string const &)
void registration_callback()
void filter_midi_ports(std::vector< std::string > &, MidiPortFlags, MidiPortFlags)
std::shared_ptr< Port > register_port(DataType type, const std::string &portname, bool input, bool async=false, PortFlags extra_flags=PortFlags(0))
bool physically_connected(const std::string &)
virtual void add_pending_port_deletion(Port *)=0
ChanCount n_physical_inputs() const
std::shared_ptr< CircularEventBuffer > MIDIPortMonitor
Definition: port_manager.h:95
SerializedRCUManager< MIDIInputPorts > _midi_input_ports
Definition: port_manager.h:390
std::map< std::string, AudioInputPort, SortByPortName > AudioInputPorts
Definition: port_manager.h:116
SerializedRCUManager< AudioInputPorts > _audio_input_ports
Definition: port_manager.h:389
bool check_for_ambiguous_latency(bool log=false) const
void get_midi_selection_ports(std::vector< std::string > &)
int get_ports(const std::string &port_name_pattern, DataType type, PortFlags flags, std::vector< std::string > &)
bool port_is_mine(const std::string &fullname) const
Glib::Threads::Mutex _port_info_mutex
Definition: port_manager.h:385
int get_ports(DataType, PortList &)
void set_port_buffer_sizes(pframes_t)
SerializedRCUManager< Ports > _ports
Definition: port_manager.h:281
void get_configurable_midi_ports(std::vector< std::string > &, bool for_input)
MonitorPort & monitor_port()
Definition: port_manager.h:274
std::map< std::string, MIDIInputPort, SortByPortName > MIDIInputPorts
Definition: port_manager.h:117
std::shared_ptr< Port > register_output_port(DataType, const std::string &portname, bool async=false, PortFlags extra_flags=PortFlags(0))
void clear_pending_port_deletions()
std::string short_port_name_from_port_name(std::string const &full_name) const
PortEngine & port_engine()
MIDIInputPorts midi_input_ports() const
PBD::Signal0< void > GraphReordered
Definition: port_manager.h:254
ChanCount n_physical_outputs() const
bool port_is_physical(const std::string &) const
std::shared_ptr< Ports const > _cycle_ports
Definition: port_manager.h:290
void remove_midi_port_flags(std::string const &, MidiPortFlags)
std::map< std::string, std::shared_ptr< Port >, SortByPortName > Ports
Definition: port_manager.h:91
bool can_request_input_monitoring() const
int disconnect(std::shared_ptr< Port >)
void port_renamed(const std::string &, const std::string &)
static std::string midi_port_info_file()
std::shared_ptr< DPM > AudioPortMeter
Definition: port_manager.h:96
uint32_t port_name_size() const
int unregister_port(std::shared_ptr< Port >)
PBD::Signal0< void > MidiSelectionPortsChanged
Definition: port_manager.h:247
void cycle_end_fade_out(gain_t, gain_t, pframes_t, Session *s=0)
static bool port_is_virtual_piano(std::string const &)
PBD::Signal5< void, std::weak_ptr< Port >, std::string, std::weak_ptr< Port >, std::string, bool > PortConnectedOrDisconnected
Definition: port_manager.h:264
PBD::Signal0< void > MidiPortInfoChanged
Definition: port_manager.h:249
void get_physical_outputs(DataType type, std::vector< std::string > &, MidiPortFlags include=MidiPortFlags(0), MidiPortFlags exclude=MidiPortFlags(0))
void silence(pframes_t nframes, Session *s=0)
void list_all_ports() const
void reinit(bool with_ratio=false)
std::atomic< int > _reset_meters
Definition: port_manager.h:391
std::shared_ptr< MPM > MIDIPortMeter
Definition: port_manager.h:97
int connect(const std::string &source, const std::string &destination)
PBD::Signal1< void, std::string > PortPrettyNameChanged
Definition: port_manager.h:251
size_t session_port_count() const
void port_registration_failure(const std::string &portname)
std::string make_port_name_relative(const std::string &name) const
PBD::RingBuffer< Port * > _port_deletions_pending
Definition: port_manager.h:284
Definition: xml++.h:114
GtkImageIconNameData name
Definition: gtkimage.h:6
#define LIBARDOUR_API
void memset(float *data, const float val, const uint32_t n_samples)
uint32_t pframes_t
Temporal::samplecnt_t samplecnt_t
bool naturally_less(const char *a, const char *b)
Definition: natsort.h:174
bool operator==(const ProcessorSelection &a, const ProcessorSelection &b)
void apply_falloff(pframes_t, samplecnt_t sr, bool reset=false)
void process(Sample const *, pframes_t, bool reset=false)
void apply_falloff(pframes_t, samplecnt_t sr, bool reset=false)
void process_event(uint8_t const *, size_t)
bool active(int chn) const
Definition: port_manager.h:75
XMLNode & state() const
PortID(std::shared_ptr< AudioBackend >, DataType, bool, std::string const &)
PortID(XMLNode const &, bool old_midi_format=false)
link region and track false waveform clip level