#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.
*/
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.
/* 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
*/
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,
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
* 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;
};
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