Automation of LV2 plugin properties.
[ardour.git] / libs / ardour / ardour / audio_backend.h
index ab37bea526d66cad0e89809840ef22b04b758868..ed29bd3c28a1263fd82498351195fd02856e875e 100644 (file)
 
 #include <boost/function.hpp>
 
+#include "ardour/libardour_visibility.h"
 #include "ardour/types.h"
+#include "ardour/audioengine.h"
+#include "ardour/port_engine.h"
+
+#ifdef ARDOURBACKEND_DLL_EXPORTS // defined if we are building the ARDOUR Panners DLLs (instead of using them)
+    #define ARDOURBACKEND_API LIBARDOUR_DLL_EXPORT
+#else
+    #define ARDOURBACKEND_API LIBARDOUR_DLL_IMPORT
+#endif 
+#define ARDOURBACKEND_LOCAL LIBARDOUR_DLL_LOCAL
 
 namespace ARDOUR {
 
-class AudioEngine;
-class PortEngine;
-class PortManager;
+struct LIBARDOUR_API AudioBackendInfo {
+    const char* name;
+
+    /** Using arg1 and arg2, initialize this audiobackend.
+     * 
+     * Returns zero on success, non-zero otherwise.
+     */
+    int (*instantiate) (const std::string& arg1, const std::string& arg2);
+
+    /** Release all resources associated with this audiobackend
+     */
+    int (*deinstantiate) (void);
+
+    /** Factory method to create an AudioBackend-derived class.
+     * 
+     * Returns a valid shared_ptr to the object if successfull,
+     * or a "null" shared_ptr otherwise.
+     */
+    boost::shared_ptr<AudioBackend> (*factory) (AudioEngine&);
 
-class AudioBackend {
+    /** Return true if the underlying mechanism/API has been
+     * configured and does not need (re)configuration in order
+     * to be usable. Return false otherwise.
+     *
+     * Note that this may return true if (re)configuration, even though
+     * not currently required, is still possible.
+     */
+    bool (*already_configured)();
+
+    /** Return true if the underlying mechanism/API can be
+     * used on the given system.
+     *
+     * If this function returns false, the backend is not
+     * listed in the engine dialog.
+     */
+    bool (*available)();
+};
+
+class LIBARDOUR_API AudioBackend : public PortEngine {
   public:
 
-    AudioBackend (AudioEngine& e) : engine (e){}
+    AudioBackend (AudioEngine& e, AudioBackendInfo& i) : PortEngine (e), _info (i), engine (e) {}
     virtual ~AudioBackend () {}
+    
+    /** Return the AudioBackendInfo object from which this backend
+       was constructed.
+    */
+    AudioBackendInfo& info() const { return _info; }
 
     /** Return the name of this backend.
      *
@@ -49,17 +98,6 @@ class AudioBackend {
      */
     virtual std::string name() const = 0;
 
-    /** Return a private, type-free pointer to any data
-     * that might be useful to a concrete implementation
-     */
-    virtual void* private_handle() const = 0;
-
-    /** Return true if the underlying mechanism/API is still available
-     * for us to utilize. return false if some or all of the AudioBackend
-     * API can no longer be effectively used.
-     */
-    virtual bool connected() const = 0;
-
     /** Return true if the callback from the underlying mechanism/API
      * (CoreAudio, JACK, ASIO etc.) occurs in a thread subject to realtime
      * constraints. Return false otherwise.
@@ -122,6 +160,17 @@ class AudioBackend {
      * at any time.
      */
     virtual std::vector<float> available_sample_rates (const std::string& device) const = 0;
+
+    /* Returns the default sample rate that will be shown to the user when
+     * configuration options are first presented. If the derived class
+     * needs or wants to override this, it can. It also MUST override this
+     * if there is any chance that an SR of 44.1kHz is not in the list
+     * returned by available_sample_rates()
+     */
+    virtual float default_sample_rate () const {
+           return 44100.0;
+    }
+
     /** Returns a collection of uint32 identifying buffer sizes that are
      * potentially usable with the hardware identified by @param device.
      * Any of these values may be supplied in other calls to this backend
@@ -131,6 +180,16 @@ class AudioBackend {
      */
     virtual std::vector<uint32_t> available_buffer_sizes (const std::string& device) const = 0;
 
+    /* Returns the default buffer size that will be shown to the user when
+     * configuration options are first presented. If the derived class
+     * needs or wants to override this, it can. It also MUST override this
+     * if there is any chance that a buffer size of 1024 is not in the list
+     * returned by available_buffer_sizes()
+     */
+    virtual uint32_t default_buffer_size () const {
+           return 1024;
+    }
+
     /** Returns the maximum number of input channels that are potentially
      * usable with the hardware identified by @param device.  Any number from 1
      * to the value returned may be supplied in other calls to this backend as
@@ -172,6 +231,9 @@ class AudioBackend {
     /** Set the name of the device to be used
      */
     virtual int set_device_name (const std::string&) = 0;
+    /** Deinitialize and destroy current device
+     */
+       virtual int drop_device() {return 0;};
     /** Set the sample rate to be used
      */
     virtual int set_sample_rate (float) = 0;
@@ -184,12 +246,6 @@ class AudioBackend {
      * doesn't directly expose the concept).
      */
     virtual int set_buffer_size (uint32_t) = 0;
-    /** Set the preferred underlying hardware sample format
-     *
-     * This does not change the sample format (32 bit float) read and
-     * written to the device via the Port API.
-     */
-    virtual int set_sample_format (SampleFormat) = 0;
     /** Set the preferred underlying hardware data layout.
      * If @param yn is true, then the hardware will interleave
      * samples for successive channels; otherwise, the hardware will store
@@ -215,18 +271,32 @@ class AudioBackend {
      * external D-A/D-A converters. Units are samples.
      */
     virtual int set_systemic_output_latency (uint32_t) = 0;
+    /** Set the (additional) input latency for a specific midi device,
+     * or if the identifier is empty, apply to all midi devices.
+     */
+    virtual int set_systemic_midi_input_latency (std::string const, uint32_t) = 0;
+    /** Set the (additional) output latency for a specific midi device,
+     * or if the identifier is empty, apply to all midi devices.
+     */
+    virtual int set_systemic_midi_output_latency (std::string const, uint32_t) = 0;
 
     /* Retrieving parameters */
 
     virtual std::string  device_name () const = 0;
     virtual float        sample_rate () const = 0;
     virtual uint32_t     buffer_size () const = 0;
-    virtual SampleFormat sample_format () const = 0;
     virtual bool         interleaved () const = 0;
     virtual uint32_t     input_channels () const = 0;
     virtual uint32_t     output_channels () const = 0;
     virtual uint32_t     systemic_input_latency () const = 0;
     virtual uint32_t     systemic_output_latency () const = 0;
+    virtual uint32_t     systemic_midi_input_latency (std::string const) const = 0;
+    virtual uint32_t     systemic_midi_output_latency (std::string const) const = 0;
+
+    /** override this if this implementation returns true from
+     * requires_driver_selection()
+     */
+    virtual std::string  driver_name() const { return std::string(); }
 
     /** Return the name of a control application for the 
      * selected/in-use device. If no such application exists,
@@ -239,8 +309,41 @@ class AudioBackend {
      * app is undefined or cannot be launched.
      */
     virtual void launch_control_app () = 0;
-    /* Basic state control */
 
+    /* @return a vector of strings that describe the available
+     * MIDI options. 
+     *
+     * These can be presented to the user to decide which
+     * MIDI drivers, options etc. can be used. The returned strings
+     * should be thought of as the key to a map of possible
+     * approaches to handling MIDI within the backend. Ensure that
+     * the strings will make sense to the user.
+     */
+    virtual std::vector<std::string> enumerate_midi_options () const = 0;
+
+    /* Request the use of the MIDI option named @param option, which
+     * should be one of the strings returned by enumerate_midi_options()
+     *
+     * @return zero if successful, non-zero otherwise
+     */
+    virtual int set_midi_option (const std::string& option) = 0;
+
+    virtual std::string midi_option () const = 0;
+
+    /** Detailed MIDI device list - if available */
+    virtual std::vector<DeviceStatus> enumerate_midi_devices () const = 0;
+
+    /** mark a midi-devices as enabled */
+    virtual int set_midi_device_enabled (std::string const, bool) = 0;
+
+    /** query if a midi-device is enabled */
+    virtual bool midi_device_enabled (std::string const) const = 0;
+
+    /** if backend supports systemic_midi_[in|ou]tput_latency() */
+    virtual bool can_set_systemic_midi_latencies () const = 0;
+
+    /* State Control */
     /** Start using the device named in the most recent call
      * to set_device(), with the parameters set by various
      * the most recent calls to set_sample_rate() etc. etc.
@@ -250,9 +353,30 @@ class AudioBackend {
      * the AudioEngine referenced by @param engine. These calls will
      * occur in a thread created by and/or under the control of the backend.
      *
+     * @param for_latency_measurement if true, the device is being started
+     *        to carry out latency measurements and the backend should this
+     *        take care to return latency numbers that do not reflect
+     *        any existing systemic latency settings.
+     *
      * Return zero if successful, negative values otherwise.
-     */
-    virtual int start () = 0;
+     *
+     *
+     *
+     *
+     * Why is this non-virtual but ::_start() is virtual ?
+     * Virtual methods with default parameters create possible ambiguity
+     * because a derived class may implement the same method with a different
+     * type or value of default parameter.
+     *
+     * So we make this non-virtual method to avoid possible overrides of
+     * default parameters. See Scott Meyers or other books on C++ to understand
+     * this pattern, or possibly just this:
+     *
+     * http://stackoverflow.com/questions/12139786/good-pratice-default-arguments-for-pure-virtual-method
+     */ 
+    int start (bool for_latency_measurement=false) {
+           return _start (for_latency_measurement);
+    }
 
     /** Stop using the device currently in use. 
      *
@@ -270,19 +394,11 @@ class AudioBackend {
      */
     virtual int stop () = 0;
 
-    /** Temporarily cease using the device named in the most recent call to set_parameters().
-     *
-     * If the function is successfully called, no subsequent calls to the
-     * process_callback() of @param engine will be made after the function
-     * returns, until start() is called again.
-     * 
-     * The backend will retain its existing parameter configuration after a successful
-     * return, and does NOT require any calls to set hardware parameters before it can be
-     * start()-ed again. 
+        /** Reset device. 
      *
-     * Return zero if successful, 1 if the device is not in use, negative values on error
+     * Return zero if successful, negative values on error
      */
-    virtual int pause () = 0;
+       virtual int reset_device() = 0;
 
     /** While remaining connected to the device, and without changing its
      * configuration, start (or stop) calling the process_callback() of @param engine
@@ -312,7 +428,7 @@ class AudioBackend {
      * Implementations can feel free to smooth the values returned over
      * time (e.g. high pass filtering, or its equivalent).
      */
-    virtual float cpu_load() const  = 0;
+    virtual float dsp_load() const  = 0;
 
     /* Transport Control (JACK is the only audio API that currently offers
        the concept of shared transport control)
@@ -399,31 +515,48 @@ class AudioBackend {
      * stacksize. The thread will begin executing @param func, and will exit
      * when that function returns.
      */
-    virtual int create_process_thread (boost::function<void()> func, pthread_t*, size_t stacksize) = 0;
+    virtual int create_process_thread (boost::function<void()> func) = 0;
 
-    virtual void update_latencies () = 0;
+    /** Wait for all processing threads to exit.
+     * 
+     * Return zero on success, non-zero on failure.
+     */
+    virtual int join_process_threads () = 0;
 
-  protected:
-    AudioEngine&          engine;
-};
+    /** Return true if execution context is in a backend thread
+     */
+    virtual bool in_process_thread () = 0;
 
-struct AudioBackendInfo {
-    const char* name;
+    /** Return the minimum stack size of audio threads in bytes
+     */
+    static size_t thread_stack_size () { return 100000; }
 
-    int (*instantiate) (const std::string& arg1, const std::string& arg2);
-    int (*deinstantiate) (void);
+    /** Return number of processing threads
+     */
+    virtual uint32_t process_thread_count () = 0;
 
-    boost::shared_ptr<AudioBackend> (*backend_factory) (AudioEngine&);
-    boost::shared_ptr<PortEngine> (*portengine_factory) (PortManager&);
+    virtual void update_latencies () = 0;
 
-    /** Return true if the underlying mechanism/API has been
-     * configured and does not need (re)configuration in order
-     * to be usable. Return false otherwise.
+    /** Set @param speed and @param position to the current speed and position
+     * indicated by some transport sync signal.  Return whether the current
+     * transport state is pending, or finalized.
      *
-     * Note that this may return true if (re)configuration, even though
-     * not currently required, is still possible.
+     * Derived classes only need implement this if they provide some way to
+     * sync to a transport sync signal (e.g. Sony 9 Pin) that is not
+     * handled by Ardour itself (LTC and MTC are both handled by Ardour).
+     * The canonical example is JACK Transport.
      */
-    bool (*already_configured)();
+     virtual bool speed_and_position (double& speed, framepos_t& position) {
+            speed = 0.0;
+            position = 0;
+            return false;
+     }
+
+  protected:
+     AudioBackendInfo&  _info; 
+     AudioEngine&        engine;
+
+     virtual int _start (bool for_latency_measurement) = 0;
 };
 
 } // namespace