]> git.tdb.fi Git - ext/openal.git/blob - alc/backends/base.h
Import OpenAL Soft 1.23.1 sources
[ext/openal.git] / alc / backends / base.h
1 #ifndef ALC_BACKENDS_BASE_H
2 #define ALC_BACKENDS_BASE_H
3
4 #include <chrono>
5 #include <cstdarg>
6 #include <memory>
7 #include <ratio>
8 #include <string>
9
10 #include "albyte.h"
11 #include "core/device.h"
12 #include "core/except.h"
13
14
15 using uint = unsigned int;
16
17 struct ClockLatency {
18     std::chrono::nanoseconds ClockTime;
19     std::chrono::nanoseconds Latency;
20 };
21
22 struct BackendBase {
23     virtual void open(const char *name) = 0;
24
25     virtual bool reset();
26     virtual void start() = 0;
27     virtual void stop() = 0;
28
29     virtual void captureSamples(al::byte *buffer, uint samples);
30     virtual uint availableSamples();
31
32     virtual ClockLatency getClockLatency();
33
34     DeviceBase *const mDevice;
35
36     BackendBase(DeviceBase *device) noexcept : mDevice{device} { }
37     virtual ~BackendBase() = default;
38
39 protected:
40     /** Sets the default channel order used by most non-WaveFormatEx-based APIs. */
41     void setDefaultChannelOrder();
42     /** Sets the default channel order used by WaveFormatEx. */
43     void setDefaultWFXChannelOrder();
44 };
45 using BackendPtr = std::unique_ptr<BackendBase>;
46
47 enum class BackendType {
48     Playback,
49     Capture
50 };
51
52
53 /* Helper to get the current clock time from the device's ClockBase, and
54  * SamplesDone converted from the sample rate.
55  */
56 inline std::chrono::nanoseconds GetDeviceClockTime(DeviceBase *device)
57 {
58     using std::chrono::seconds;
59     using std::chrono::nanoseconds;
60
61     auto ns = nanoseconds{seconds{device->SamplesDone}} / device->Frequency;
62     return device->ClockBase + ns;
63 }
64
65 /* Helper to get the device latency from the backend, including any fixed
66  * latency from post-processing.
67  */
68 inline ClockLatency GetClockLatency(DeviceBase *device, BackendBase *backend)
69 {
70     ClockLatency ret{backend->getClockLatency()};
71     ret.Latency += device->FixedLatency;
72     return ret;
73 }
74
75
76 struct BackendFactory {
77     virtual bool init() = 0;
78
79     virtual bool querySupport(BackendType type) = 0;
80
81     virtual std::string probe(BackendType type) = 0;
82
83     virtual BackendPtr createBackend(DeviceBase *device, BackendType type) = 0;
84
85 protected:
86     virtual ~BackendFactory() = default;
87 };
88
89 namespace al {
90
91 enum class backend_error {
92     NoDevice,
93     DeviceError,
94     OutOfMemory
95 };
96
97 class backend_exception final : public base_exception {
98     backend_error mErrorCode;
99
100 public:
101 #ifdef __USE_MINGW_ANSI_STDIO
102     [[gnu::format(gnu_printf, 3, 4)]]
103 #else
104     [[gnu::format(printf, 3, 4)]]
105 #endif
106     backend_exception(backend_error code, const char *msg, ...);
107     ~backend_exception() override;
108
109     backend_error errorCode() const noexcept { return mErrorCode; }
110 };
111
112 } // namespace al
113
114 #endif /* ALC_BACKENDS_BASE_H */