1 /* 2 * Copyright (C) 2013-2018 Paul Davis <paul@linuxaudiosystems.com> 3 * Copyright (C) 2015-2018 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_engine_h__ 21 #define __libardour_port_engine_h__ 22 23 #include <vector> 24 #include <string> 25 26 #include <stdint.h> 27 28 #include "ardour/data_type.h" 29 #include "ardour/libardour_visibility.h" 30 #include "ardour/types.h" 31 32 namespace ARDOUR { 33 34 class PortManager; 35 36 /** PortEngine is an abstract base class that defines the functionality 37 * required by Ardour. 38 * 39 * A Port is basically an endpoint for a datastream (which can either be 40 * continuous, like audio, or event-based, like MIDI). Ports have buffers 41 * associated with them into which data can be written (if they are output 42 * ports) and from which data can be read (if they input ports). Ports can be 43 * connected together so that data written to an output port can be read from 44 * an input port. These connections can be 1:1, 1:N OR N:1. 45 * 46 * Ports may be associated with software only, or with hardware. Hardware 47 * related ports are often referred to as physical, and correspond to some 48 * relevant physical entity on a hardware device, such as an audio jack or a 49 * MIDI connector. Physical ports may be potentially asked to monitor their 50 * inputs, though some implementations may not support this. 51 * 52 * Most physical ports will also be considered "terminal", which means that 53 * data delivered there or read from there will go to or comes from a system 54 * outside of the PortEngine implementation's control (e.g. the analog domain 55 * for audio, or external MIDI devices for MIDI). Non-physical ports can also 56 * be considered "terminal". For example, the output port of a software 57 * synthesizer is a terminal port, because the data contained in its buffer 58 * does not and cannot be considered to come from any other port - it is 59 * synthesized by its owner. 60 * 61 * Ports also have latency associated with them. Each port has a playback 62 * latency and a capture latency: 63 * 64 * <b>capture latency</b>: how long since the data read from the buffer of a 65 * port arrived at at a terminal port. The data will have 66 * come from the "outside world" if the terminal port is also 67 * physical, or will have been synthesized by the entity that 68 * owns the terminal port. 69 * 70 * <b>playback latency</b>: how long until the data written to the buffer of 71 * port will reach a terminal port. 72 * 73 * 74 * For more detailed questions about the PortEngine API, consult the JACK API 75 * documentation, on which this entire object is based. 76 */ 77 78 class LIBARDOUR_API ProtoPort { 79 public: ProtoPort()80 ProtoPort() {} ~ProtoPort()81 virtual ~ProtoPort () {} 82 }; 83 84 class LIBARDOUR_API PortEngine 85 { 86 public: PortEngine(PortManager & pm)87 PortEngine (PortManager& pm) : manager (pm) {} ~PortEngine()88 virtual ~PortEngine() {} 89 90 /** Return a private, type-free pointer to any data 91 * that might be useful to a concrete implementation 92 */ 93 virtual void* private_handle() const = 0; 94 95 /** Opaque handle to use as reference for Ports 96 * 97 * The handle needs to be lifetime managed (i.e. a shared_ptr type) 98 * in order to allow RCU to provide lock-free cross-thread operations 99 * on ports and ports containers. 100 * 101 * We could theoretically use a template (PortEngine\<T\>) and define 102 * PortHandle as T, but this complicates the desired inheritance 103 * pattern in which FooPortEngine handles things for the Foo API, 104 * rather than being a derivative of PortEngine\<Foo\>. 105 * 106 * We use this to declare return values and members of structures. 107 */ 108 typedef boost::shared_ptr<ProtoPort> PortPtr; 109 110 /* We use this to declare arguments to methods/functions, in order to 111 * avoid copying shared_ptr<ProtoPort> every time (a practice we use in 112 * other contexts where we pass shared_ptr<T>). 113 */ 114 typedef PortPtr const & PortHandle; 115 116 /** Return the name of this process as used by the port manager 117 * when naming ports. 118 */ 119 virtual const std::string& my_name() const = 0; 120 121 /** Return the maximum size of a port name */ 122 virtual uint32_t port_name_size() const = 0; 123 124 /** Set/rename port 125 * 126 * @param port \ref PortHandle to operate on 127 * @param name new name to use for this port 128 * @return zero if successful, non-zero otherwise 129 */ 130 virtual int set_port_name (PortHandle port, const std::string& name) = 0; 131 132 /** Query port name 133 * 134 * @param port \ref PortHandle 135 * @return the name of the port referred to by @param port . If the port 136 * does not exist, return an empty string. 137 */ 138 virtual std::string get_port_name (PortHandle port) const = 0; 139 140 /** Query port-flags 141 * 142 * @param port \ref PortHandle 143 * @return the flags of the port referred to by \p port . If the port 144 * does not exist, return PortFlags (0) 145 */ 146 virtual PortFlags get_port_flags (PortHandle port) const = 0; 147 148 /** Return the port-property value and type for a given key. 149 * (eg query a human readable port name) 150 * 151 * The API follows jack_get_property(): 152 * 153 * @param key The key of the property to retrieve 154 * @param value Set to the value of the property if found 155 * @param type The type of the property if set ( 156 * Type of data, either a MIME type or URI. 157 * If type is empty, the data is assumed to be a UTF-8 encoded string. 158 * 159 * @return 0 on success, -1 if the @p subject has no @p key property. 160 * 161 * for available keys, see 162 * https://github.com/jackaudio/headers/blob/master/metadata.h 163 * https://github.com/drobilla/jackey/blob/master/jackey.h 164 */ get_port_property(PortHandle,const std::string & key,std::string & value,std::string & type)165 virtual int get_port_property (PortHandle, const std::string& key, std::string& value, std::string& type) const { return -1; } 166 167 /** Set the port-property value and type for a given key 168 * 169 * The API follows jack_set_property(): 170 * @param key The key of the property. 171 * @param value The value of the property. 172 * @param type The type of the property. 173 * 174 * @return 0 on success, -1 on error 175 */ set_port_property(PortHandle,const std::string & key,const std::string & value,const std::string & type)176 virtual int set_port_property (PortHandle, const std::string& key, const std::string& value, const std::string& type) { return -1; } 177 178 /** Return a reference to a port with the fullname \p name . 179 * 180 * @param name Full port-name to lookup 181 * @return PortHandle if lookup was successful, or an "empty" PortHandle (analogous to a null pointer) if no such port exists. 182 */ 183 virtual PortPtr get_port_by_name (const std::string& name) const = 0; 184 185 /** Find the set of ports whose names, types and flags match 186 * specified values, place the names of each port into \p ports . 187 * 188 * @param port_name_pattern match by given pattern. To avoid selecting by name, pass an empty string. 189 * @param type filter by given type; pass DataType::NIL to match all types. 190 * @param flags filter by flags, pass PortFlags (0) to avoid selecting by flags. 191 * @param ports array filled with matching port-names 192 * @return the count of the number found 193 */ 194 virtual int get_ports (const std::string& port_name_pattern, DataType type, PortFlags flags, std::vector<std::string>& ports) const = 0; 195 196 /** Lookup data type of a port 197 * 198 * @param port \ref PortHandle of the port to lookup. 199 * @return the Ardour data type handled by the port referred to by \p port . 200 * DataType::NIL is returned if the port does not exist. 201 */ 202 virtual DataType port_data_type (PortHandle port) const = 0; 203 204 /** Create a new port whose fullname will be the conjunction of my_name(), 205 * ":" and \p shortname . The port will handle data specified by \p type 206 * and will have the flags given by \p flags . If successful, 207 * 208 * @param shortname Name of port to create 209 * @param type type of port to create 210 * @param flags flags of the port to create 211 * @return a reference to the port, otherwise return a null pointer. 212 */ 213 virtual PortPtr register_port (const std::string& shortname, ARDOUR::DataType type, ARDOUR::PortFlags flags) = 0; 214 215 /* Destroy the port referred to by \p port, including all resources 216 * associated with it. This will also disconnect \p port from any ports it 217 * is connected to. 218 * 219 * @param port \ref PortHandle of the port to destroy 220 */ 221 virtual void unregister_port (PortHandle port) = 0; 222 223 /* Connection management */ 224 225 /** Ensure that data written to the port named by \p src will be 226 * readable from the port named by \p dst 227 * 228 * @param src name of source port to connect 229 * @param dst name of destination (sink) port 230 * @return zero on success, non-zero otherwise. 231 */ 232 virtual int connect (const std::string& src, const std::string& dst) = 0; 233 234 /** Remove any existing connection between the ports named by \p src and 235 * \p dst 236 * 237 * @param src name of source port to dis-connect to disconnect from 238 * @param dst name of destination (sink) port to disconnect 239 * @return zero on success, non-zero otherwise. 240 */ 241 virtual int disconnect (const std::string& src, const std::string& dst) = 0; 242 243 /** Ensure that data written to the port referenced by \p src will be 244 * readable from the port named by \p dst 245 * 246 * @param src \ref PortHandle of source port to connect 247 * @param dst \ref PortHandle of destination (sink) port 248 * @return zero on success, non-zero otherwise. 249 */ 250 virtual int connect (PortHandle src, const std::string& dst) = 0; 251 252 /** Remove any existing connection between the port referenced by \p src and 253 * the port named \p dst 254 * 255 * @param src \ref PortHandle of source port to disconnect from 256 * @param dst \ref PortHandle of destination (sink) port to disconnect 257 * @return zero on success, non-zero otherwise. 258 */ 259 virtual int disconnect (PortHandle src, const std::string& dst) = 0; 260 261 /** Remove all connections between the port referred to by \p port and 262 * any other ports. 263 * 264 * @param port \ref PortHandle of port to disconnect 265 * @return zero on success, non-zero otherwise. 266 */ 267 virtual int disconnect_all (PortHandle port) = 0; 268 269 /** Test if given \p port is connected 270 * 271 * @param port \ref PortHandle of port to test 272 * @param process_callback_safe true if this method is not called from rt-context of backend callbacks 273 * @return true if the port referred to by \p port has any connections to other ports. Return false otherwise. 274 */ 275 virtual bool connected (PortHandle port, bool process_callback_safe = true) = 0; 276 277 /** Test port connection 278 * 279 * @param port \ref PortHandle of source port to test 280 * @param name name of destination to test 281 * @param process_callback_safe true if this method is not called from rt-context of backend callbacks 282 * @return true if the port referred to by \p port is connected to the port named by \p name . Return false otherwise. 283 */ 284 virtual bool connected_to (PortHandle port, const std::string& name, bool process_callback_safe = true) = 0; 285 286 /** Test if given \p port is is connected to physical I/O ports. 287 * 288 * @param port \ref PortHandle of source port to test 289 * @param process_callback_safe true if this method is not called from rt-context of backend callbacks 290 * @return true if the port referred to by \p port has any connections 291 * to ports marked with the PortFlag IsPhysical. Return false otherwise. 292 */ 293 virtual bool physically_connected (PortHandle port, bool process_callback_safe = true) = 0; 294 295 /** Test if given \p port is has external connections. 296 * 297 * @param port \ref PortHandle of port to test 298 * @param process_callback_safe true if this method is not called from rt-context of backend callbacks 299 * @return true if the port referred to by \p port has any connections 300 * to external, not-ardour owned, ports. 301 */ 302 virtual bool externally_connected (PortHandle port, bool process_callback_safe = true) { 303 /* only with JACK, provides client ports that are not physical */ 304 return physically_connected (port, process_callback_safe); 305 } 306 307 /** Place the names of all ports connected to the port named by 308 * \p port into \p names . 309 * 310 * @param port \ref PortHandle 311 * @param names array or returned port-names 312 * @param process_callback_safe true if this method is not called from rt-context of backend callbacks 313 * @return number of connections found 314 */ 315 virtual int get_connections (PortHandle port, std::vector<std::string>& names, bool process_callback_safe = true) = 0; 316 317 /* MIDI */ 318 319 /** Retrieve a MIDI event from the data at \p port_buffer . The event 320 * number to be retrieved is given by \p event_index (a value of zero 321 * indicates that the first event in the port_buffer should be retrieved). 322 * 323 * The data associated with the event will be copied into the buffer at 324 * \p buf and the number of bytes written will be stored in \p size . 325 * The timestamp of the event (which is always relative to the start 326 * of the current process cycle, in samples) will be stored in \p timestamp . 327 * 328 * @param timestamp time in samples relative to the current cycle start 329 * @param size number of bytes read into \p buf 330 * @param buf raw MIDI data 331 * @param port_buffer the midi-port buffer 332 * @param event_index index of event to retrieve 333 * @return 0 on success, -1 otherwise 334 */ 335 virtual int midi_event_get (pframes_t& timestamp, size_t& size, uint8_t const** buf, void* port_buffer, uint32_t event_index) = 0; 336 337 /** Place a MIDI event consisting of \p size bytes copied from the data 338 * at \p buffer into the port buffer referred to by \p port_buffer . 339 * The MIDI event will be marked with a time given by \p timestamp . 340 * 341 * Events must be added monotonically to a port buffer. An attempt to 342 * add a non-monotonic event (e.g. out-of-order) will cause this method 343 * to return a failure status. 344 * 345 * @param port_buffer the midi-port buffer 346 * @param timestamp time in samples relative to the current cycle start 347 * @param buffer raw MIDI data to emplace 348 * @param size number of bytes of \p buffer 349 * @return zero on success, non-zero otherwise. 350 */ 351 virtual int midi_event_put (void* port_buffer, pframes_t timestamp, const uint8_t* buffer, size_t size) = 0; 352 353 /** Query the number of MIDI events in the data at \p port_buffer 354 * 355 * @param port_buffer the midi-port buffer 356 * @return the number of MIDI events in the data at \p port_buffer 357 */ 358 virtual uint32_t get_midi_event_count (void* port_buffer) = 0; 359 360 /** Clear the buffer at \p port_buffer of all MIDI events. 361 * 362 * After a call to this method, an immediate, subsequent call to 363 * \ref get_midi_event_count with the same \p port_buffer argument must 364 * return zero. 365 * 366 * @param port_buffer the buffer to clear 367 */ 368 virtual void midi_clear (void* port_buffer) = 0; 369 370 /* Monitoring */ 371 372 /** Return true if the implementation can offer input monitoring. 373 * 374 * Input monitoring involves the (selective) routing of incoming data 375 * to an outgoing data stream, without the data being passed to the CPU. 376 * 377 * Only certain audio hardware can provide this, and only certain audio 378 * APIs can offer it. 379 */ 380 virtual bool can_monitor_input() const = 0; 381 382 /** Increment or decrement the number of requests to monitor the input 383 * of the hardware channel represented by the port referred to by 384 * \p port . 385 * 386 * If the number of requests rises above zero, input monitoring will 387 * be enabled (if can_monitor_input() returns true for the implementation). 388 * 389 * If the number of requests falls to zero, input monitoring will be 390 * disabled (if can_monitor_input() returns true for the implementation) 391 * 392 * @param port \ref PortHandle 393 * @param yn true to enable hardware monitoring, false to disable 394 * @return 0 on success, -1 otherwise 395 */ 396 virtual int request_input_monitoring (PortHandle port, bool yn) = 0; 397 398 /* Force input monitoring of the hardware channel represented by the port 399 * referred to by \p port to be on or off, depending on the true/false 400 * status of \p yn. The request count is ignored when using this 401 * method, so if this is called with \p yn set to false, input monitoring will 402 * be disabled regardless of the number of requests to enable it. 403 * 404 * @param port \ref PortHandle 405 * @param yn true to enable hardware monitoring, false to disable 406 * @return 0 on success, -1 otherwise 407 */ 408 virtual int ensure_input_monitoring (PortHandle port, bool yn) = 0; 409 410 /** Query status of hardware monitoring for given \p port 411 * 412 * @param port \ref PortHandle to test 413 * @return true if input monitoring is enabled for the hardware channel 414 * represented by the port referred to by \p port . 415 * Return false otherwise. 416 */ 417 virtual bool monitoring_input (PortHandle port) = 0; 418 419 /* Latency management */ 420 421 /** Set the latency range for the port referred to by \p port to 422 * \p r . The playback range will be set if \p for_playback is true, 423 * otherwise the capture range will be set. 424 * 425 * @param port \ref PortHandle to operate on 426 * @param for_playback When true, playback latency is set: How long will it be 427 * until the signal arrives at the edge of the process graph. 428 * When false the capture latency is set: ow long has it been 429 * since the signal arrived at the edge of the process graph. 430 * @param r min/max latency for given port. 431 */ 432 virtual void set_latency_range (PortHandle port, bool for_playback, LatencyRange r) = 0; 433 434 /** Return the latency range for the port referred to by \p port . 435 * The playback range will be returned if @param for_playback is true, 436 * otherwise the capture range will be returned. 437 * 438 * @param port The PortHandle to query 439 * @param for_playback When true, playback (downstream) latency is queried, 440 * false for capture (upstream) latency. 441 */ 442 virtual LatencyRange get_latency_range (PortHandle port, bool for_playback) = 0; 443 444 /* Discovering physical ports */ 445 446 /** Return true if the port referred to by \p port has the IsPhysical 447 * flag set. Return false otherwise. 448 * 449 * @param port \ref PortHandle to query 450 */ 451 virtual bool port_is_physical (PortHandle port) const = 0; 452 453 /** Store into \p names the names of all ports with the IsOutput and 454 * IsPhysical flag set, that handle data of type \p type . 455 * 456 * This can be used to discover outputs associated with hardware devices. 457 * 458 * @param type Data-type to lookup 459 * @param names return value to populate with names 460 */ 461 virtual void get_physical_outputs (DataType type, std::vector<std::string>& names) = 0; 462 463 /** Store into @param names the names of all ports with the IsInput and 464 * IsPhysical flags set, that handle data of type @param type . 465 * 466 * This can be used to discover inputs associated with hardware devices. 467 */ 468 virtual void get_physical_inputs (DataType type, std::vector<std::string>& names) = 0; 469 470 /** @return the total count (possibly mixed between different data types) 471 * of the number of ports with the IsPhysical and IsOutput flags set. 472 */ 473 virtual ChanCount n_physical_outputs () const = 0; 474 475 /** @return the total count (possibly mixed between different data types) 476 * of the number of ports with the IsPhysical and IsInput flags set. 477 */ 478 virtual ChanCount n_physical_inputs () const = 0; 479 480 /** Return the address of the memory area where data for the port can be 481 * written (if the port has the PortFlag IsOutput set) or read (if the port 482 * has the PortFlag IsInput set). 483 * 484 * The return value is untyped because buffers containing different data 485 * depending on the port type. 486 * 487 * @param port \ref PortHandle 488 * @param off memory offset 489 * @return pointer to raw memory area 490 */ 491 virtual void* get_buffer (PortHandle port, pframes_t off) = 0; 492 493 /* MIDI ports (the ones in libmidi++) need this to be able to correctly 494 * schedule MIDI events within their buffers. It is a bit odd that we 495 * expose this here, because it is also exposed by AudioBackend, but they 496 * only have access to a PortEngine object, not an AudioBackend. 497 * 498 * Return the time according to the sample clock in use when the current 499 * buffer process cycle began. 500 * 501 * XXX to be removed after some more design cleanup. 502 */ 503 virtual samplepos_t sample_time_at_cycle_start () = 0; 504 505 protected: 506 PortManager& manager; 507 }; 508 509 } // namespace 510 511 #endif /* __libardour_port_engine_h__ */ 512