2 Copyright (C) 2013 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #ifndef __libardour_port_engine_h__
21 #define __libardour_port_engine_h__
28 #include "ardour/data_type.h"
29 #include "ardour/types.h"
35 /** PortEngine is an abstract base class that defines the functionality
38 * A Port is basically an endpoint for a datastream (which can either be
39 * continuous, like audio, or event-based, like MIDI). Ports have buffers
40 * associated with them into which data can be written (if they are output
41 * ports) and from which data can be read (if they input ports). Ports can be
42 * connected together so that data written to an output port can be read from
43 * an input port. These connections can be 1:1, 1:N OR N:1.
45 * Ports may be associated with software only, or with hardware. Hardware
46 * related ports are often referred to as physical, and correspond to some
47 * relevant physical entity on a hardware device, such as an audio jack or a
48 * MIDI connector. Physical ports may be potentially asked to monitor their
49 * inputs, though some implementations may not support this.
51 * Most physical ports will also be considered "terminal", which means that
52 * data delivered there or read from there will go to or comes from a system
53 * outside of the PortEngine implementation's control (e.g. the analog domain
54 * for audio, or external MIDI devices for MIDI). Non-physical ports can also
55 * be considered "terminal". For example, the output port of a software
56 * synthesizer is a terminal port, because the data contained in its buffer
57 * does not and cannot be considered to come from any other port - it is
58 * synthesized by its owner.
60 * Ports also have latency associated with them. Each port has a playback
61 * latency and a capture latency:
63 * <b>capture latency</b>: how long since the data read from the buffer of a
64 * port arrived at at a terminal port. The data will have
65 * come from the "outside world" if the terminal port is also
66 * physical, or will have been synthesized by the entity that
67 * owns the terminal port.
69 * <b>playback latency</b>: how long until the data written to the buffer of
70 * port will reach a terminal port.
73 * For more detailed questions about the PortEngine API, consult the JACK API
74 * documentation, on which this entire object is based.
79 PortEngine (PortManager& pm) : manager (pm) {}
80 virtual ~PortEngine() {}
82 /** Return a private, type-free pointer to any data
83 * that might be useful to a concrete implementation
85 virtual void* private_handle() const = 0;
87 /* We use void* here so that the API can be defined for any implementation.
89 * We could theoretically use a template (PortEngine<T>) and define
90 * PortHandle as T, but this complicates the desired inheritance
91 * pattern in which FooPortEngine handles things for the Foo API,
92 * rather than being a derivative of PortEngine<Foo>.
95 typedef void* PortHandle;
97 /** Return the name of this process as used by the port manager
100 virtual const std::string& my_name() const = 0;
102 /** Return true if the underlying mechanism/API is still available
103 * for us to utilize. return false if some or all of the AudioBackend
104 * API can no longer be effectively used.
106 virtual bool available() const = 0;
108 /** Return the maximum size of a port name
110 virtual uint32_t port_name_size() const = 0;
112 /** Returns zero if the port referred to by @param port was set to @param
113 * name. Return non-zero otherwise.
115 virtual int set_port_name (PortHandle port, const std::string& name) = 0;
116 /** Return the name of the port referred to by @param port. If the port
117 * does not exist, return an empty string.
119 virtual std::string get_port_name (PortHandle) const = 0;
120 /** Return a reference to a port with the fullname @param name. Return
121 * a null pointer if no such port exists.
123 virtual PortHandle* get_port_by_name (const std::string&) const = 0;
125 /** Find the set of ports whose names, types and flags match
126 * specified values, place the names of each port into @param ports,
127 * and return the count of the number found.
129 * To avoid selecting by name, pass an empty string for @param
132 * To avoid selecting by type, pass DataType::NIL as @param type.
134 * To avoid selecting by flags, pass PortFlags (0) as @param flags.
136 virtual int get_ports (const std::string& port_name_pattern, DataType type, PortFlags flags, std::vector<std::string>& ports) const = 0;
138 /** Return the Ardour data type handled by the port referred to by @param
139 * port. Returns DataType::NIL if the port does not exist.
141 virtual DataType port_data_type (PortHandle port) const = 0;
143 /** Create a new port whose fullname will be the conjuction of my_name(),
144 * ":" and @param shortname. The port will handle data specified by @param
145 * type and will have the flags given by @param flags. If successfull,
146 * return a reference to the port, otherwise return a null pointer.
148 virtual PortHandle register_port (const std::string& shortname, ARDOUR::DataType type, ARDOUR::PortFlags flags) = 0;
150 /* Destroy the port referred to by @param port, including all resources
151 * associated with it. This will also disconnect @param port from any ports it
154 virtual void unregister_port (PortHandle) = 0;
156 /* Connection management */
158 /** Ensure that data written to the port named by @param src will be
159 * readable from the port named by @param dst. Return zero on success,
160 * non-zero otherwise.
162 virtual int connect (const std::string& src, const std::string& dst) = 0;
164 /** Remove any existing connection between the ports named by @param src and
165 * @param dst. Return zero on success, non-zero otherwise.
167 virtual int disconnect (const std::string& src, const std::string& dst) = 0;
170 /** Ensure that data written to the port referenced by @param portwill be
171 * readable from the port named by @param dst. Return zero on success,
172 * non-zero otherwise.
174 virtual int connect (PortHandle src, const std::string& dst) = 0;
175 /** Remove any existing connection between the port referenced by @param src and
176 * the port named @param dst. Return zero on success, non-zero otherwise.
178 virtual int disconnect (PortHandle src, const std::string& dst) = 0;
180 /** Remove all connections between the port referred to by @param port and
181 * any other ports. Return zero on success, non-zero otherwise.
183 virtual int disconnect_all (PortHandle port) = 0;
185 /** Return true if the port referred to by @param port has any connections
186 * to other ports. Return false otherwise.
188 virtual bool connected (PortHandle port, bool process_callback_safe = true) = 0;
189 /** Return true if the port referred to by @param port is connected to
190 * the port named by @param name. Return false otherwise.
192 virtual bool connected_to (PortHandle, const std::string& name, bool process_callback_safe = true) = 0;
194 /** Return true if the port referred to by @param port has any connections
195 * to ports marked with the PortFlag IsPhysical. Return false otherwise.
197 virtual bool physically_connected (PortHandle port, bool process_callback_safe = true) = 0;
199 /** Place the names of all ports connected to the port named by @param
200 * ports into @param names, and return the number of connections.
202 virtual int get_connections (PortHandle port, std::vector<std::string>& names, bool process_callback_safe = true) = 0;
206 /** Retrieve a MIDI event from the data at @param port_buffer. The event
207 number to be retrieved is given by @param event_index (a value of zero
208 indicates that the first event in the port_buffer should be retrieved).
210 * The data associated with the event will be copied into the buffer at
211 * @param buf and the number of bytes written will be stored in @param
212 * size. The timestamp of the event (which is always relative to the start
213 * of the current process cycle, in samples) will be stored in @param
216 virtual int midi_event_get (pframes_t& timestamp, size_t& size, uint8_t** buf, void* port_buffer, uint32_t event_index) = 0;
218 /** Place a MIDI event consisting of @param size bytes copied from the data
219 * at @param buf into the port buffer referred to by @param
220 * port_buffer. The MIDI event will be marked with a time given by @param
221 * timestamp. Return zero on success, non-zero otherwise.
223 * Events must be added monotonically to a port buffer. An attempt to
224 * add a non-monotonic event (e.g. out-of-order) will cause this method
225 * to return a failure status.
227 virtual int midi_event_put (void* port_buffer, pframes_t timestamp, const uint8_t* buffer, size_t size) = 0;
229 /** Return the number of MIDI events in the data at @param port_buffer
231 virtual uint32_t get_midi_event_count (void* port_buffer) = 0;
233 /** Clear the buffer at @param port_buffer of all MIDI events.
235 * After a call to this method, an immediate, subsequent call to
236 * get_midi_event_count() with the same @param port_buffer argument must
239 virtual void midi_clear (void* port_buffer) = 0;
243 /** Return true if the implementation can offer input monitoring.
245 * Input monitoring involves the (selective) routing of incoming data
246 * to an outgoing data stream, without the data being passed to the CPU.
248 * Only certain audio hardware can provide this, and only certain audio
251 virtual bool can_monitor_input() const = 0;
252 /** Increment or decrement the number of requests to monitor the input
253 * of the hardware channel represented by the port referred to by @param
256 * If the number of requests rises above zero, input monitoring will
257 * be enabled (if can_monitor_input() returns true for the implementation).
259 * If the number of requests falls to zero, input monitoring will be
260 * disabled (if can_monitor_input() returns true for the implementation)
262 virtual int request_input_monitoring (PortHandle port, bool yn) = 0;
263 /* Force input monitoring of the hardware channel represented by the port
264 * referred to by @param port to be on or off, depending on the true/false
265 * status of @param yn. The request count is ignored when using this
266 * method, so if this is called with yn set to false, input monitoring will
267 * be disabled regardless of the number of requests to enable it.
269 virtual int ensure_input_monitoring (PortHandle port, bool yn) = 0;
270 /** Return true if input monitoring is enabled for the hardware channel
271 * represented by the port referred to by @param port. Return false
274 virtual bool monitoring_input (PortHandle port) = 0;
276 /* Latency management
279 /** Set the latency range for the port referred to by @param port to @param
280 * r. The playback range will be set if @param for_playback is true,
281 * otherwise the capture range will be set.
283 virtual void set_latency_range (PortHandle port, bool for_playback, LatencyRange r) = 0;
284 /** Return the latency range for the port referred to by @param port.
285 * The playback range will be returned if @param for_playback is true,
286 * otherwise the capture range will be returned.
288 virtual LatencyRange get_latency_range (PortHandle port, bool for_playback) = 0;
290 /* Discovering physical ports */
292 /** Return true if the port referred to by @param port has the IsPhysical
293 * flag set. Return false otherwise.
295 virtual bool port_is_physical (PortHandle port) const = 0;
297 /** Store into @param names the names of all ports with the IsOutput and
298 * IsPhysical flag set, that handle data of type @param type.
300 * This can be used to discover outputs associated with hardware devices.
302 virtual void get_physical_outputs (DataType type, std::vector<std::string>& names) = 0;
303 /** Store into @param names the names of all ports with the IsInput and
304 * IsPhysical flags set, that handle data of type @param type.
306 * This can be used to discover inputs associated with hardware devices.
308 virtual void get_physical_inputs (DataType type, std::vector<std::string>& names) = 0;
309 /** Return the total count (possibly mixed between different data types)
310 of the number of ports with the IsPhysical and IsOutput flags set.
312 virtual ChanCount n_physical_outputs () const = 0;
313 /** Return the total count (possibly mixed between different data types)
314 of the number of ports with the IsPhysical and IsInput flags set.
316 virtual ChanCount n_physical_inputs () const = 0;
318 /** Return the address of the memory area where data for the port can be
319 * written (if the port has the PortFlag IsOutput set) or read (if the port
320 * has the PortFlag IsInput set).
322 * The return value is untyped because buffers containing different data
323 * depending on the port type.
325 virtual void* get_buffer (PortHandle, pframes_t) = 0;
327 /* MIDI ports (the ones in libmidi++) need this to be able to correctly
328 * schedule MIDI events within their buffers. It is a bit odd that we
329 * expose this here, because it is also exposed by AudioBackend, but they
330 * only have access to a PortEngine object, not an AudioBackend.
332 * Return the time according to the sample clock in use when the current
333 * buffer process cycle began.
335 * XXX to be removed after some more design cleanup.
337 virtual pframes_t sample_time_at_cycle_start () = 0;
340 PortManager& manager;
345 #endif /* __libardour_port_engine_h__ */