Ardour  9.0-pre0-582-g084a23a80d
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 #pragma once
21 
22 #include <atomic>
23 #include <cstdint>
24 #include <exception>
25 #include <map>
26 #include <memory>
27 #include <string>
28 #include <vector>
29 
30 #include "pbd/natsort.h"
31 #include "pbd/rcu.h"
32 #include "pbd/ringbuffer.h"
33 
34 #include "ardour/chan_count.h"
36 #include "ardour/monitor_port.h"
37 #include "ardour/port.h"
38 
39 namespace ARDOUR {
40 
41 class PortEngine;
42 class AudioBackend;
43 class Session;
44 
45 class CircularSampleBuffer;
46 class CircularEventBuffer;
47 
49 {
50 public:
51  struct DPM {
52  DPM ()
53  {
54  reset ();
55  }
56  void reset ()
57  {
58  level = 0;
59  peak = 0;
60  }
63  };
64 
65  struct MPM {
66  MPM ()
67  {
68  reset ();
69  }
70  void reset ()
71  {
72  memset (chn_active, 0, sizeof (float) * 17);
73  }
74  bool active (int chn) const {
75  if (chn < 0 || chn > 16) {
76  return false;
77  }
78  return chn_active[chn] > 0.1;
79  }
80  /* 0..15: MIDI Channel Event, 16: System Common Message */
81  float chn_active[17];
82  };
83 
84  struct SortByPortName {
85  bool operator() (std::string const& a, std::string const& b) const {
86  return PBD::naturally_less (a.c_str (), b.c_str ());
87  }
88  };
89 
90  typedef std::map<std::string, std::shared_ptr<Port>, SortByPortName> Ports;
91  typedef std::list<std::shared_ptr<Port> > PortList;
92 
93  typedef std::shared_ptr<CircularSampleBuffer> AudioPortScope;
94  typedef std::shared_ptr<CircularEventBuffer> MIDIPortMonitor;
95  typedef std::shared_ptr<DPM> AudioPortMeter;
96  typedef std::shared_ptr<MPM> MIDIPortMeter;
97 
98  struct AudioInputPort {
102  void apply_falloff (pframes_t, samplecnt_t sr, bool reset = false);
104  void process (Sample const*, pframes_t, bool reset = false);
105  };
106 
107  struct MIDIInputPort {
111  void apply_falloff (pframes_t, samplecnt_t sr, bool reset = false);
112  void process_event (uint8_t const*, size_t);
113  };
114 
115  typedef std::map<std::string, AudioInputPort, SortByPortName> AudioInputPorts;
116  typedef std::map<std::string, MIDIInputPort, SortByPortName> MIDIInputPorts;
117 
119  virtual ~PortManager () {}
120 
122 
124 
125  uint32_t port_name_size () const;
126  std::string my_name () const;
127 
128  size_t total_port_count () const { return _ports.reader ()->size (); }
129  size_t session_port_count () const;
130 
131 #ifndef NDEBUG
132  void list_cycle_ports () const;
133  void list_all_ports () const;
134 #endif
135 
136  /* Port registration */
137 
138  std::shared_ptr<Port> register_input_port (DataType, const std::string& portname, bool async = false, PortFlags extra_flags = PortFlags (0));
139  std::shared_ptr<Port> register_output_port (DataType, const std::string& portname, bool async = false, PortFlags extra_flags = PortFlags (0));
140  int unregister_port (std::shared_ptr<Port>);
141 
142  /* Port connectivity */
143 
144  int connect (const std::string& source, const std::string& destination);
145  int disconnect (const std::string& source, const std::string& destination);
146  int disconnect (std::shared_ptr<Port>);
147  int disconnect (std::string const&);
150 
151  bool connected (const std::string&);
152  bool physically_connected (const std::string&);
153  int get_connections (const std::string&, std::vector<std::string>&, bool process_context_safe = true);
154 
155  /* Naming */
156 
157  std::shared_ptr<Port> get_port_by_name (const std::string&);
158  void port_renamed (const std::string&, const std::string&);
159  std::string make_port_name_relative (const std::string& name) const;
160  std::string make_port_name_non_relative (const std::string& name) const;
161  std::string get_pretty_name_by_name (const std::string& portname) const;
162  std::string get_hardware_port_name_by_name (const std::string& portname) const;
163  std::string short_port_name_from_port_name (std::string const& full_name) const;
164  bool port_is_mine (const std::string& fullname) const;
165 
166  static bool port_is_virtual_piano (std::string const&);
167  static bool port_is_control_only (std::string const&);
168  static bool port_is_physical_input_monitor_enable (std::string const&);
169 
170  /* other Port management */
171 
172  bool port_is_physical (const std::string&) const;
173  void get_physical_outputs (DataType type, std::vector<std::string>&,
174  MidiPortFlags include = MidiPortFlags (0),
175  MidiPortFlags exclude = MidiPortFlags (0));
176  void get_physical_inputs (DataType type, std::vector<std::string>&,
177  MidiPortFlags include = MidiPortFlags (0),
178  MidiPortFlags exclude = MidiPortFlags (0));
179 
182 
183  int get_ports (const std::string& port_name_pattern, DataType type, PortFlags flags, std::vector<std::string>&);
185 
186  void set_port_pretty_name (std::string const&, std::string const&);
187 
189 
191  void reinit (bool with_ratio = false);
192 
194 
195  virtual void add_pending_port_deletion (Port*) = 0;
196 
198  {
199  return _port_deletions_pending;
200  }
201 
202  bool check_for_ambiguous_latency (bool log = false) const;
203 
204  /* per-Port monitoring */
205 
207  void request_input_monitoring (const std::string&, bool) const;
208  void ensure_input_monitoring (const std::string&, bool) const;
209 
210  class PortRegistrationFailure : public std::exception
211  {
212  public:
213  PortRegistrationFailure (std::string const& why = "")
214  : reason (why) {}
215 
217 
218  const char* what () const throw ()
219  {
220  return reason.c_str ();
221  }
222 
223  private:
224  std::string reason;
225  };
226 
227  /* the port engine will invoke these callbacks when the time is right */
228 
231  void connect_callback (const std::string&, const std::string&, bool connection);
232 
234  {
235  return _port_remove_in_progress;
236  }
237 
238  MidiPortFlags midi_port_metadata (std::string const&);
239 
240  void get_configurable_midi_ports (std::vector<std::string>&, bool for_input);
241  void get_midi_selection_ports (std::vector<std::string>&);
242  void add_midi_port_flags (std::string const&, MidiPortFlags);
243  void remove_midi_port_flags (std::string const&, MidiPortFlags);
244 
250  PBD::Signal<void(std::string)> PortPrettyNameChanged;
251 
254 
257 
263  PBD::Signal<void(std::weak_ptr<Port>, std::string, std::weak_ptr<Port>, std::string, bool)> PortConnectedOrDisconnected;
264 
265  PBD::Signal<void(DataType, std::vector<std::string>, bool)> PhysInputChanged;
266 
267  /* Input port meters and monitors */
269 
272 
274  return _monitor_port;
275  }
276 
277 protected:
278  std::shared_ptr<AudioBackend> _backend;
279 
281 
284 
285  std::shared_ptr<Port> register_port (DataType type, const std::string& portname, bool input, bool async = false, PortFlags extra_flags = PortFlags (0));
286  void port_registration_failure (const std::string& portname);
287 
289  std::shared_ptr<Ports const> _cycle_ports;
290 
291  void silence (pframes_t nframes, Session* s = 0);
292  void silence_outputs (pframes_t nframes);
298  void cycle_start (pframes_t nframes, Session* s = 0);
299 
305  void cycle_end (pframes_t nframes, Session* s = 0);
306 
308 
309  static std::string port_info_file ();
310  static std::string midi_port_info_file ();
311 
312  void filter_midi_ports (std::vector<std::string>&, MidiPortFlags, MidiPortFlags);
313 
315 
316 private:
318  void set_pretty_names (std::vector<std::string> const&, DataType, bool);
320  void load_port_info ();
321  void save_port_info ();
322  void update_input_ports (bool);
323 
325 
326  struct PortID {
327  PortID (std::shared_ptr<AudioBackend>, DataType, bool, std::string const&);
328  PortID (XMLNode const&, bool old_midi_format = false);
329 
330  std::string backend;
331  std::string device_name;
332  std::string port_name;
334  bool input;
335 
336  XMLNode& state () const;
337 
338  bool operator< (PortID const& o) const {
339  if (backend != o.backend) {
340  return backend < o.backend;
341  }
342  if (device_name != o.device_name) {
343  return device_name < o.device_name;
344  }
345  if (port_name != o.port_name) {
346  return PBD::naturally_less (port_name.c_str (), o.port_name.c_str ());
347  }
348  if (input != o.input) {
349  return input;
350  }
351  return (uint32_t) data_type < (uint32_t) o.data_type;
352  }
353 
354  bool operator== (PortID const& o) const {
355  if (backend != o.backend) {
356  return false;
357  }
358  if (device_name != o.device_name) {
359  return false;
360  }
361  if (port_name != o.port_name) {
362  return false;
363  }
364  if (input != o.input) {
365  return false;
366  }
367  if (data_type != o.data_type) {
368  return false;
369  }
370  return true;
371  }
372  };
373 
374  struct PortMetaData {
375  PortMetaData () : properties (MidiPortFlags (0)) {}
377 
378  std::string pretty_name;
380  };
381 
382  typedef std::map<PortID, PortMetaData> PortInfo;
383 
384  mutable Glib::Threads::Mutex _port_info_mutex;
387 
390  std::atomic<int> _reset_meters;
391 };
392 
393 } // namespace ARDOUR
394 
PortRegistrationFailure(std::string const &why="")
Definition: port_manager.h:213
int disconnect(const std::string &source, const std::string &destination)
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:91
PBD::Signal< void()> PortRegisteredOrUnregistered
Definition: port_manager.h:256
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::Signal< void(std::string)> PortPrettyNameChanged
Definition: port_manager.h:250
AudioInputPorts audio_input_ports() const
std::map< PortID, PortMetaData > PortInfo
Definition: port_manager.h:382
virtual ~PortManager()
Definition: port_manager.h:119
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:93
PBD::Signal< void(DataType, std::vector< std::string >, bool)> PhysInputChanged
Definition: port_manager.h:265
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:233
PBD::Signal< void()> MidiPortInfoChanged
Definition: port_manager.h:248
static std::string port_info_file()
PBD::RingBuffer< Port * > & port_deletions_pending()
Definition: port_manager.h:197
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:278
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:324
size_t total_port_count() const
Definition: port_manager.h:128
void ensure_input_monitoring(const std::string &, bool) const
void add_midi_port_flags(std::string const &, MidiPortFlags)
PBD::Signal< void(std::weak_ptr< Port >, std::string, std::weak_ptr< Port >, std::string, bool)> PortConnectedOrDisconnected
Definition: port_manager.h:263
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:94
SerializedRCUManager< MIDIInputPorts > _midi_input_ports
Definition: port_manager.h:389
std::map< std::string, AudioInputPort, SortByPortName > AudioInputPorts
Definition: port_manager.h:115
SerializedRCUManager< AudioInputPorts > _audio_input_ports
Definition: port_manager.h:388
bool check_for_ambiguous_latency(bool log=false) const
PBD::Signal< void()> MidiSelectionPortsChanged
Definition: port_manager.h:246
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:384
int get_ports(DataType, PortList &)
void set_port_buffer_sizes(pframes_t)
SerializedRCUManager< Ports > _ports
Definition: port_manager.h:280
void get_configurable_midi_ports(std::vector< std::string > &, bool for_input)
MonitorPort & monitor_port()
Definition: port_manager.h:273
std::map< std::string, MIDIInputPort, SortByPortName > MIDIInputPorts
Definition: port_manager.h:116
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
ChanCount n_physical_outputs() const
bool port_is_physical(const std::string &) const
std::shared_ptr< Ports const > _cycle_ports
Definition: port_manager.h:289
void remove_midi_port_flags(std::string const &, MidiPortFlags)
std::map< std::string, std::shared_ptr< Port >, SortByPortName > Ports
Definition: port_manager.h:90
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:95
uint32_t port_name_size() const
int unregister_port(std::shared_ptr< Port >)
void cycle_end_fade_out(gain_t, gain_t, pframes_t, Session *s=0)
static bool port_is_virtual_piano(std::string const &)
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:390
std::shared_ptr< MPM > MIDIPortMeter
Definition: port_manager.h:96
int connect(const std::string &source, const std::string &destination)
PBD::Signal< void()> GraphReordered
Definition: port_manager.h:253
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:283
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:74
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