add API to get current MIDI option from an audio/MIDI backend
[ardour.git] / libs / ardour / ardour / audio_backend.h
index 44525c83537015dcac77bcc52961a2ea87a14f5f..4f7a153eec290fce7241109d7bccc76ce5270ac1 100644 (file)
 #include <boost/function.hpp>
 
 #include "ardour/types.h"
+#include "ardour/audioengine.h"
+#include "ardour/port_engine.h"
+#include "ardour/visibility.h"
 
-namespace ARDOUR {
+#ifdef ARDOURBACKEND_DLL_EXPORTS // defined if we are building the ARDOUR Panners DLLs (instead of using them)
+    #define ARDOURBACKEND_API LIBARDOUR_HELPER_DLL_EXPORT
+#else
+    #define ARDOURBACKEND_API LIBARDOUR_HELPER_DLL_IMPORT
+#endif 
+#define ARDOURBACKEND_LOCAL LIBARDOUR_HELPER_DLL_LOCAL
 
-class AudioEngine;
-class PortEngine;
-class PortManager;
+namespace ARDOUR {
 
-class AudioBackend {
+class AudioBackend : public PortEngine {
   public:
 
-    AudioBackend (AudioEngine& e) : engine (e){}
+    AudioBackend (AudioEngine& e) : PortEngine (e), engine (e) {}
     virtual ~AudioBackend () {}
 
     /** Return the name of this backend.
@@ -49,17 +55,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.
@@ -68,12 +63,52 @@ class AudioBackend {
 
     /* Discovering devices and parameters */
 
-    /** Returns a collection of strings identifying devices known
-     * to this backend. Any of these strings may be used to identify a
+    /** Return true if this backend requires the selection of a "driver"
+     * before any device can be selected. Return false otherwise.
+     *
+     * Intended mainly to differentiate between meta-APIs like JACK
+     * which can still expose different backends (such as ALSA or CoreAudio 
+     * or FFADO or netjack) and those like ASIO or CoreAudio which
+     * do not.
+     */
+    virtual bool requires_driver_selection() const { return false; }
+
+    /** If the return value of requires_driver_selection() is true,
+     * then this function can return the list of known driver names.
+     *
+     * If the return value of requires_driver_selection() is false,
+     * then this function should not be called. If it is called
+     * its return value is an empty vector of strings.
+     */
+    virtual std::vector<std::string> enumerate_drivers() const { return std::vector<std::string>(); }
+
+    /** Returns zero if the backend can successfully use @param name as the
+     * driver, non-zero otherwise.
+     *
+     * Should not be used unless the backend returns true from
+     * requires_driver_selection()
+     */
+    virtual int set_driver (const std::string& /*drivername*/) { return 0; }
+
+    /** used to list device names along with whether or not they are currently
+     *  available. 
+    */
+    struct DeviceStatus {
+       std::string name;
+       bool        available;
+
+       DeviceStatus (const std::string& s, bool avail) : name (s), available (avail) {}
+    };
+
+    /** Returns a collection of DeviceStatuses identifying 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<std::string> enumerate_devices () const = 0;
+    virtual std::vector<DeviceStatus> enumerate_devices () const = 0;
+
     /** 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
@@ -107,6 +142,17 @@ class AudioBackend {
      */
     virtual uint32_t available_output_channel_count (const std::string& device) const = 0;
 
+    /* Return true if the derived class can change the sample rate of the
+     * device in use while the device is already being used. Return false
+     * otherwise. (example: JACK cannot do this as of September 2013)
+     */
+    virtual bool can_change_sample_rate_when_running () const = 0;
+    /* Return true if the derived class can change the buffer size of the
+     * device in use while the device is already being used. Return false
+     * otherwise. 
+     */
+    virtual bool can_change_buffer_size_when_running () const = 0;
+
     /* Set the hardware parameters.
      * 
      * If called when the current state is stopped or paused,
@@ -177,7 +223,44 @@ class AudioBackend {
     virtual uint32_t     systemic_input_latency () const = 0;
     virtual uint32_t     systemic_output_latency () const = 0;
 
-    /* Basic state control */
+    /** 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,
+     * or if no device has been selected or is in-use,
+     * return an empty string.
+     */
+    virtual std::string control_app_name() const = 0;
+    /** Launch the control app for the currently in-use or
+     * selected device. May do nothing if the control
+     * app is undefined or cannot be launched.
+     */
+    virtual void launch_control_app () = 0;
+
+    /* @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;
+    
+    /* State Control */
 
     /** Start using the device named in the most recent call
      * to set_device(), with the parameters set by various
@@ -284,7 +367,7 @@ class AudioBackend {
     virtual int set_time_master (bool /*yn*/) { return 0; }
 
     virtual int        usecs_per_cycle () const { return 1000000 * (buffer_size() / sample_rate()); }
-    virtual size_t     raw_buffer_size (DataType t);
+    virtual size_t     raw_buffer_size (DataType t) = 0;
     
     /* Process time */
     
@@ -296,18 +379,17 @@ class AudioBackend {
      * It is extremely likely that any implementation will use a DLL, since
      * this function can be called from any thread, at any time, and must be 
      * able to accurately determine the correct sample time.
+     *
+     * Can be called from any thread.
      */
     virtual pframes_t sample_time () = 0;
 
-    /** return the time according to the sample clock in use when the current 
-     * buffer process cycle began. 
-     * 
-     * Can ONLY be called from within a process() callback tree (which
-     * implies that it can only be called by a process thread)
+    /** 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;
 
-    /** return the time since the current buffer process cycle started,
+    /** Return the time since the current buffer process cycle started,
      * in samples, according to the sample clock in use.
      * 
      * Can ONLY be called from within a process() callback tree (which
@@ -315,7 +397,7 @@ class AudioBackend {
      */
     virtual pframes_t samples_since_cycle_start () = 0;
 
-    /** return true if it possible to determine the offset in samples of the
+    /** Return true if it possible to determine the offset in samples of the
      * first video frame that starts within the current buffer process cycle,
      * measured from the first sample of the cycle. If returning true,
      * set @param offset to that offset.
@@ -338,8 +420,28 @@ 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;
+
+    /** Wait for all processing threads to exit.
+     * 
+     * Return zero on success, non-zero on failure.
+     */
+    virtual int join_process_threads () = 0;
+
+    /** Return true if execution context is in a backend thread
+     */
+    virtual bool in_process_thread () = 0;
+
+    /** Return the minimum stack size of audio threads in bytes
+     */
+    static size_t thread_stack_size () { return 100000; }
+
+    /** Return number of processing threads
+     */
+    virtual uint32_t process_thread_count () = 0;
+
+    virtual void update_latencies () = 0;
+
   protected:
     AudioEngine&          engine;
 };
@@ -347,11 +449,31 @@ class AudioBackend {
 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);
 
-    boost::shared_ptr<AudioBackend> (*backend_factory) (AudioEngine&);
-    boost::shared_ptr<PortEngine> (*portengine_factory) (PortManager&);
+    /** 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)();
 };
 
 } // namespace