define more backend error-messages.
[ardour.git] / libs / ardour / ardour / audio_backend.h
index 26ced33885b76f69063a0c6681639b51449dbbcc..a0893b846aba348cefed2da67f795ffde47f6b81 100644 (file)
 
 #include <boost/function.hpp>
 
+#include "ardour/libardour_visibility.h"
 #include "ardour/types.h"
 #include "ardour/audioengine.h"
 #include "ardour/port_engine.h"
-#include "ardour/visibility.h"
 
 #ifdef ARDOURBACKEND_DLL_EXPORTS // defined if we are building the ARDOUR Panners DLLs (instead of using them)
-    #define ARDOURBACKEND_API LIBARDOUR_HELPER_DLL_EXPORT
+    #define ARDOURBACKEND_API LIBARDOUR_DLL_EXPORT
 #else
-    #define ARDOURBACKEND_API LIBARDOUR_HELPER_DLL_IMPORT
+    #define ARDOURBACKEND_API LIBARDOUR_DLL_IMPORT
 #endif 
-#define ARDOURBACKEND_LOCAL LIBARDOUR_HELPER_DLL_LOCAL
+#define ARDOURBACKEND_LOCAL LIBARDOUR_DLL_LOCAL
 
 namespace ARDOUR {
 
-class AudioBackend : public PortEngine {
+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&);
+
+    /** 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) : PortEngine (e), engine (e) {}
+    AudioBackend (AudioEngine& e, AudioBackendInfo& i) : PortEngine (e), _info (i), engine (e) {}
     virtual ~AudioBackend () {}
+    
+       enum ErrorCode {
+               NoError = 0,
+               BackendInitializationError = -64,
+               BackendDeinitializationError,
+               BackendReinitializationError,
+               AudioDeviceOpenError,
+               AudioDeviceCloseError,
+               AudioDeviceInvalidError,
+               AudioDeviceNotAvailableError,
+               AudioDeviceNotConnectedError,
+               AudioDeviceReservationError,
+               AudioDeviceIOError,
+               MidiDeviceOpenError,
+               MidiDeviceCloseError,
+               MidiDeviceNotAvailableError,
+               MidiDeviceNotConnectedError,
+               MidiDeviceIOError,
+               SampleFormatNotSupportedError,
+               SampleRateNotSupportedError,
+               RequestedInputLatencyNotSupportedError,
+               RequestedOutputLatencyNotSupportedError,
+               PeriodSizeNotSupportedError,
+               PeriodCountNotSupportedError,
+               DeviceConfigurationNotSupportedError,
+               ChannelCountNotSupportedError,
+               InputChannelCountNotSupportedError,
+               OutputChannelCountNotSupportedError,
+               AquireRealtimePermissionError,
+               SettingAudioThreadPriorityError,
+               SettingMIDIThreadPriorityError,
+               ProcessThreadStartError,
+               FreewheelThreadStartError,
+               PortRegistrationError,
+               PortReconnectError,
+               OutOfMemoryError,
+       };
+
+       static std::string get_error_string (ErrorCode);
+
+       enum StandardDeviceName {
+               DeviceNone,
+               DeviceDefault
+       };
+
+       static std::string get_standard_device_name (StandardDeviceName);
+
+    /** Return the AudioBackendInfo object from which this backend
+       was constructed.
+    */
+    AudioBackendInfo& info() const { return _info; }
 
     /** Return the name of this backend.
      *
@@ -100,6 +189,16 @@ class AudioBackend : public PortEngine {
        DeviceStatus (const std::string& s, bool avail) : name (s), available (avail) {}
     };
 
+    /** An optional alternate interface for backends to provide a facility to
+     * select separate input and output devices.
+     *
+     * If a backend returns true then enumerate_input_devices() and
+     * enumerate_output_devices() will be used instead of enumerate_devices()
+     * to enumerate devices. Similarly set_input/output_device_name() should
+     * be used to set devices instead of set_device_name().
+     */
+    virtual bool use_separate_input_and_output_devices () const { return false; }
+
     /** Returns a collection of DeviceStatuses identifying devices discovered
      * by this backend since the start of the process.
      *
@@ -109,6 +208,40 @@ class AudioBackend : public PortEngine {
      */
     virtual std::vector<DeviceStatus> enumerate_devices () const = 0;
 
+    /** Returns a collection of DeviceStatuses identifying input devices
+     * discovered by this backend since the start of the process.
+     *
+     * Any of the names in each DeviceStatus may be used to identify a
+     * device in other calls to the backend, though any of them may become
+     * invalid at any time.
+     */
+    virtual std::vector<DeviceStatus> enumerate_input_devices () const
+    { return std::vector<DeviceStatus>(); }
+
+    /** Returns a collection of DeviceStatuses identifying output devices
+     * discovered by this backend since the start of the process.
+     *
+     * Any of the names in each DeviceStatus may be used to identify a
+     * device in other calls to the backend, though any of them may become
+     * invalid at any time.
+     */
+    virtual std::vector<DeviceStatus> enumerate_output_devices () const
+    { return std::vector<DeviceStatus>(); }
+
+       /**
+        * @return true if backend supports requesting an update to the device list
+        * and any cached properties associated with the devices.
+        */
+       virtual bool can_request_update_devices () { return false; }
+
+       /**
+        * Request an update to the list of devices returned in the enumerations.
+        * The Backend must return true from can_request_update_devices to support
+        * this interface.
+        * @return true if the devices were updated
+        */
+       virtual bool update_devices () { return false; }
+
     /** Returns a collection of float identifying sample rates that are
      * potentially usable with the hardware identified by @param device.
      * Any of these values may be supplied in other calls to this backend
@@ -118,6 +251,20 @@ class AudioBackend : public PortEngine {
      */
     virtual std::vector<float> available_sample_rates (const std::string& device) const = 0;
 
+    /* backends that support separate input and output devices should
+     * implement this function and return an intersection (not union) of available
+     * sample rates valid for the given input + output device combination.
+     */
+    virtual std::vector<float> available_sample_rates2 (const std::string& input_device, const std::string& output_device) const {
+           std::vector<float> input_sizes  = available_sample_rates (input_device);
+           std::vector<float> output_sizes = available_sample_rates (output_device);
+           std::vector<float> rv;
+           std::set_union (input_sizes.begin (), input_sizes.end (),
+                           output_sizes.begin (), output_sizes.end (),
+                           std::back_inserter (rv));
+           return rv;
+    }
+
     /* 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
@@ -137,13 +284,26 @@ class AudioBackend : public PortEngine {
      */
     virtual std::vector<uint32_t> available_buffer_sizes (const std::string& device) const = 0;
 
+    /* backends that support separate input and output devices should
+     * implement this function and return an intersection (not union) of available
+     * buffer sizes valid for the given input + output device combination.
+     */
+    virtual std::vector<uint32_t> available_buffer_sizes2 (const std::string& input_device, const std::string& output_device) const {
+           std::vector<uint32_t> input_rates  = available_buffer_sizes (input_device);
+           std::vector<uint32_t> output_rates = available_buffer_sizes (output_device);
+           std::vector<uint32_t> rv;
+           std::set_union (input_rates.begin (), input_rates.end (),
+                           output_rates.begin (), output_rates.end (),
+                           std::back_inserter (rv));
+           return rv;
+    }
     /* 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 {
+    virtual uint32_t default_buffer_size (const std::string& device) const {
            return 1024;
     }
 
@@ -188,6 +348,24 @@ class AudioBackend : public PortEngine {
     /** Set the name of the device to be used
      */
     virtual int set_device_name (const std::string&) = 0;
+
+    /** Set the name of the input device to be used if using separate
+     * input/output devices.
+     *
+     * @see use_separate_input_and_output_devices()
+     */
+    virtual int set_input_device_name (const std::string&) { return 0;}
+
+    /** Set the name of the output device to be used if using separate
+     * input/output devices.
+     *
+     * @see use_separate_input_and_output_devices()
+     */
+    virtual int set_output_device_name (const std::string&) { return 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;
@@ -200,12 +378,6 @@ class AudioBackend : public PortEngine {
      * 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
@@ -231,18 +403,29 @@ class AudioBackend : public PortEngine {
      * 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 std::string  input_device_name () const { return std::string(); }
+    virtual std::string  output_device_name () const { return std::string(); }
     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()
@@ -280,19 +463,21 @@ class AudioBackend : public PortEngine {
     virtual int set_midi_option (const std::string& option) = 0;
 
     virtual std::string midi_option () const = 0;
-    
-    /* State Control */
 
-    /* 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);
-    }
+    /** 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.
@@ -308,8 +493,24 @@ class AudioBackend : public PortEngine {
      *        any existing systemic latency settings.
      *
      * Return zero if successful, negative values otherwise.
-     */
-    virtual int _start (bool for_latency_measurement) = 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. 
      *
@@ -327,6 +528,12 @@ class AudioBackend : public PortEngine {
      */
     virtual int stop () = 0;
 
+        /** Reset device. 
+     *
+     * Return zero if successful, negative values on error
+     */
+       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
      * without waiting for the device. Once process_callback() has returned, it
@@ -355,7 +562,7 @@ class AudioBackend : public PortEngine {
      * 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)
@@ -404,12 +611,12 @@ class AudioBackend : public PortEngine {
      *
      * Can be called from any thread.
      */
-    virtual pframes_t sample_time () = 0;
+    virtual framepos_t sample_time () = 0;
 
     /** Return the time according to the sample clock in use when the most
      * recent buffer process cycle began. Can be called from any thread.
      */
-    virtual pframes_t sample_time_at_cycle_start () = 0;
+    virtual framepos_t sample_time_at_cycle_start () = 0;
 
     /** Return the time since the current buffer process cycle started,
      * in samples, according to the sample clock in use.
@@ -480,37 +687,10 @@ class AudioBackend : public PortEngine {
      }
 
   protected:
-    AudioEngine&          engine;
-};
-
-struct 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);
+     AudioBackendInfo&  _info; 
+     AudioEngine&        engine;
 
-    /** 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&);
-
-    /** 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)();
+     virtual int _start (bool for_latency_measurement) = 0;
 };
 
 } // namespace