more stuff compiles
[ardour.git] / libs / ardour / ardour / audio_backend.h
index d286fbd9c2f92e4f9e32a505d604f89c0ecb7deb..44525c83537015dcac77bcc52961a2ea87a14f5f 100644 (file)
@@ -17,8 +17,8 @@
 
 */
 
-#ifndef __ardour_audiobackend_h__
-#define __ardour_audiobackend_h__
+#ifndef __libardour_audiobackend_h__
+#define __libardour_audiobackend_h__
 
 #include <string>
 #include <vector>
 #include <stdint.h>
 #include <stdlib.h>
 
+#include <boost/function.hpp>
+
+#include "ardour/types.h"
+
 namespace ARDOUR {
 
 class AudioEngine;
+class PortEngine;
+class PortManager;
 
 class AudioBackend {
   public:
 
-    enum State {
-           Stopped = 0x1,
-           Running = 0x2,
-           Paused =  0x4,
-           Freewheeling = 0x8,
-    };
-
-    AudioBackend (AudioEngine& e) : engine (e), _state (Stopped) {}
+    AudioBackend (AudioEngine& e) : engine (e){}
     virtual ~AudioBackend () {}
 
-    /** return true if the underlying mechanism/API is still available
+    /** Return the name of this backend.
+     *
+     * Should use a well-known, unique term. Expected examples
+     * might include "JACK", "CoreAudio", "ASIO" etc.
+     */
+    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
+    /** 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.
     */
@@ -80,24 +91,97 @@ class AudioBackend {
      */
     virtual std::vector<uint32_t> available_buffer_sizes (const std::string& device) const = 0;
 
-    struct Parameters {
-       std::string device_name;
-       float       sample_rate;
-       uint32_t    buffer_size;
-       uint32_t    systemic_input_latency;
-       uint32_t    systemic_output_latency;
-       uint32_t    input_channels;
-       uint32_t    output_channels;
-    };
+    /** 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
+     * the input channel count to use with the name device, but the requested
+     * count may turn out to be unavailable, or become invalid at any time.
+     */
+    virtual uint32_t available_input_channel_count (const std::string& device) const = 0;
+
+    /** Returns the maximum number of output 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
+     * the output channel count to use with the name device, but the requested
+     * count may turn out to be unavailable, or become invalid at any time.
+     */
+    virtual uint32_t available_output_channel_count (const std::string& device) const = 0;
+
+    /* Set the hardware parameters.
+     * 
+     * If called when the current state is stopped or paused,
+     * the changes will not take effect until the state changes to running.
+     *
+     * If called while running, the state will change as fast as the
+     * implementation allows.
+     *
+     * All set_*() methods return zero on success, non-zero otherwise.
+     */
+
+    /** Set the name of the device to be used
+     */
+    virtual int set_device_name (const std::string&) = 0;
+    /** Set the sample rate to be used
+     */
+    virtual int set_sample_rate (float) = 0;
+    /** Set the buffer size to be used.
+     *
+     * The device is assumed to use a double buffering scheme, so that one
+     * buffer's worth of data can be processed by hardware while software works
+     * on the other buffer. All known suitable audio APIs support this model
+     * (though ALSA allows for alternate numbers of buffers, and CoreAudio
+     * 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
+     * samples for a single channel contiguously.
+     * 
+     * Setting this does not change the fact that all data streams
+     * to and from Ports are mono (essentially, non-interleaved)
+     */
+    virtual int set_interleaved (bool yn) = 0;
+    /** Set the number of input channels that should be used
+     */
+    virtual int set_input_channels (uint32_t) = 0;
+    /** Set the number of output channels that should be used
+     */
+    virtual int set_output_channels (uint32_t) = 0;
+    /** Set the (additional) input latency that cannot be determined via 
+     * the implementation's underlying code (e.g. latency from
+     * external D-A/D-A converters. Units are samples.
+     */
+    virtual int set_systemic_input_latency (uint32_t) = 0;
+    /** Set the (additional) output latency that cannot be determined via 
+     * the implementation's underlying code (e.g. latency from
+     * external D-A/D-A converters. Units are samples.
+     */
+    virtual int set_systemic_output_latency (uint32_t) = 0;
+
+    /* Retrieving parameters */
 
-    virtual int set_parameters (const Parameters&) = 0;
-    virtual int get_parameters (Parameters&) const = 0;
+    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;
 
     /* Basic state control */
 
     /** Start using the device named in the most recent call
-     * to set_parameters(), with the parameters also provided
-     * to that call.
+     * to set_device(), with the parameters set by various
+     * the most recent calls to set_sample_rate() etc. etc.
      * 
      * At some undetermined time after this function is successfully called,
      * the backend will start calling the ::process_callback() method of
@@ -108,14 +192,14 @@ class AudioBackend {
      */
     virtual int start () = 0;
 
-    /** Stop using the device named in the most recent call to set_parameters().
+    /** Stop using the device currently in use. 
      *
      * If the function is successfully called, no subsequent calls to the
      * process_callback() of @param engine will be made after the function
-     * returns, until set_parameters() and start() are called again.
+     * returns, until parameters are reset and start() are called again.
      * 
      * The backend is considered to be un-configured after a successful
-     * return, and requires a call to set_parameters() before it can be
+     * return, and requires calls to set hardware parameters before it can be
      * start()-ed again. See pause() for a way to avoid this. stop() should
      * only be used when reconfiguration is required OR when there are no 
      * plans to use the backend in the future with a reconfiguration.
@@ -131,10 +215,8 @@ class AudioBackend {
      * returns, until start() is called again.
      * 
      * The backend will retain its existing parameter configuration after a successful
-     * return, and requires a call to set_parameters() before it can be
-     * start()-ed again. See pause() for a way to avoid this. stop() should
-     * only be used when reconfiguration is required OR when there are no 
-     * plans to use the backend in the future with a reconfiguration.
+     * return, and does NOT require any calls to set hardware parameters before it can be
+     * start()-ed again. 
      *
      * Return zero if successful, 1 if the device is not in use, negative values on error
      */
@@ -142,9 +224,15 @@ class AudioBackend {
 
     /** 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. 
+     * without waiting for the device. Once process_callback() has returned, it
+     * will be called again immediately, thus allowing for faster-than-realtime
+     * processing.
      *
-     * If @param start_stop is true, begin this behaviour, otherwise cease this
+     * All registered ports remain in existence and all connections remain
+     * unaltered. However, any physical ports should NOT be used by the
+     * process_callback() during freewheeling - the data behaviour is undefined.
+     *
+     * If @param start_stop is true, begin this behaviour; otherwise cease this
      * behaviour if it currently occuring, and return to calling
      * process_callback() of @param engine by waiting for the device.
      *
@@ -155,8 +243,14 @@ class AudioBackend {
     /** return the fraction of the time represented by the current buffer
      * size that is being used for each buffer process cycle, as a value
      * from 0.0 to 1.0
-    */
-    virtual float get_cpu_load() const  = 0;
+     *
+     * E.g. if the buffer size represents 5msec and current processing
+     * takes 1msec, the returned value should be 0.2. 
+     * 
+     * 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;
 
     /* Transport Control (JACK is the only audio API that currently offers
        the concept of shared transport control)
@@ -170,18 +264,26 @@ class AudioBackend {
     virtual void transport_stop () {}
     /** return the current transport state
      */
-    virtual TransportState transport_state () { return TransportStopped; }
+    virtual TransportState transport_state () const { return TransportStopped; }
     /** Attempt to locate the transport to @param pos
      */
-    virtual void transport_locate (framepos_t pos) {}
+    virtual void transport_locate (framepos_t /*pos*/) {}
     /** Return the current transport location, in samples measured
      * from the origin (defined by the transport time master)
      */
-    virtual framepos_t transport_frame() { return 0; }
+    virtual framepos_t transport_frame() const { return 0; }
+
+    /** If @param yn is true, become the time master for any inter-application transport
+     * timebase, otherwise cease to be the time master for the same.
+     *
+     * Return zero on success, non-zero otherwise
+     * 
+     * JACK is the only currently known audio API with the concept of a shared
+     * transport timebase.
+     */
+    virtual int set_time_master (bool /*yn*/) { return 0; }
 
-    virtual framecnt_t sample_rate () const;
-    virtual pframes_t  samples_per_cycle () const;
-    virtual int        usecs_per_cycle () const { return _usecs_per_cycle; }
+    virtual int        usecs_per_cycle () const { return 1000000 * (buffer_size() / sample_rate()); }
     virtual size_t     raw_buffer_size (DataType t);
     
     /* Process time */
@@ -228,15 +330,31 @@ class AudioBackend {
      * Can ONLY be called from within a process() callback tree (which implies
      * that it can only be called by a process thread)
      */
-    virtual bool get_sync_offset (pframes_t& offset) const { return 0; }
+    virtual bool get_sync_offset (pframes_t& /*offset*/) const { return false; }
+
+    /** Create a new thread suitable for running part of the buffer process
+     * cycle (i.e. Realtime scheduling, memory allocation, etc. etc are all
+     * correctly setup), with a stack size given in bytes by specified @param
+     * 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;
     
-  private:
+  protected:
     AudioEngine&          engine;
-    Parameters           _last_requested_parameters;
-    State                _state;
 };
 
-}
+struct AudioBackendInfo {
+    const char* name;
+
+    int (*instantiate) (const std::string& arg1, const std::string& arg2);
+    int (*deinstantiate) (void);
+
+    boost::shared_ptr<AudioBackend> (*backend_factory) (AudioEngine&);
+    boost::shared_ptr<PortEngine> (*portengine_factory) (PortManager&);
+};
+
+} // namespace
 
-#endif /* __ardour_audiobackend_h__ */
+#endif /* __libardour_audiobackend_h__ */