Update build instructions
[alure.git] / src / devicemanager.cpp
blob0989037d0034ef5f5e036b0fe09ac7783e3b1ade
2 #include "config.h"
4 #include "devicemanager.h"
5 #include "device.h"
6 #include "main.h"
8 #include <algorithm>
9 #include <stdexcept>
10 #include <iostream>
12 #include "alc.h"
13 #include "al.h"
16 namespace alure {
18 std::string alc_category::message(int condition) const
20 switch(condition)
22 case ALC_NO_ERROR: return "No error";
23 case ALC_INVALID_ENUM: return "Invalid enum";
24 case ALC_INVALID_VALUE: return "Invalid value";
25 case ALC_INVALID_DEVICE: return "Invalid device";
26 case ALC_INVALID_CONTEXT: return "Invalid context";
27 case ALC_OUT_OF_MEMORY: return "Out of memory";
29 return "Unknown ALC error "+std::to_string(condition);
32 std::string al_category::message(int condition) const
34 switch(condition)
36 case AL_NO_ERROR: return "No error";
37 case AL_INVALID_NAME: return "Invalid name";
38 case AL_INVALID_ENUM: return "Invalid enum";
39 case AL_INVALID_VALUE: return "Invalid value";
40 case AL_INVALID_OPERATION: return "Invalid operation";
41 case AL_OUT_OF_MEMORY: return "Out of memory";
43 return "Unknown AL error "+std::to_string(condition);
46 alc_category alc_category::sSingleton;
47 al_category al_category::sSingleton;
50 template<typename T>
51 static inline void GetDeviceProc(T *&func, ALCdevice *device, const char *name)
52 { func = reinterpret_cast<T*>(alcGetProcAddress(device, name)); }
55 WeakPtr<DeviceManagerImpl> DeviceManagerImpl::sInstance;
56 ALCboolean (ALC_APIENTRY*DeviceManagerImpl::SetThreadContext)(ALCcontext*);
58 DeviceManager::DeviceManager(SharedPtr<DeviceManagerImpl>&& impl) noexcept
59 : pImpl(std::move(impl))
60 { }
62 DeviceManager::~DeviceManager() { }
64 DeviceManager DeviceManager::getInstance()
65 { return DeviceManager(DeviceManagerImpl::getInstance()); }
66 SharedPtr<DeviceManagerImpl> DeviceManagerImpl::getInstance()
68 SharedPtr<DeviceManagerImpl> ret = sInstance.lock();
69 if(!ret)
71 ret = MakeShared<DeviceManagerImpl>();
72 sInstance = ret;
74 return ret;
78 DeviceManagerImpl::DeviceManagerImpl()
80 if(alcIsExtensionPresent(nullptr, "ALC_EXT_thread_local_context"))
81 GetDeviceProc(SetThreadContext, nullptr, "alcSetThreadContext");
84 DeviceManagerImpl::~DeviceManagerImpl()
89 bool DeviceManager::queryExtension(const String &name) const
90 { return queryExtension(name.c_str()); }
91 DECL_THUNK1(bool, DeviceManager, queryExtension, const, const char*)
92 bool DeviceManagerImpl::queryExtension(const char *name) const
94 return static_cast<bool>(alcIsExtensionPresent(nullptr, name));
97 DECL_THUNK1(Vector<String>, DeviceManager, enumerate, const, DeviceEnumeration)
98 Vector<String> DeviceManagerImpl::enumerate(DeviceEnumeration type) const
100 Vector<String> list;
101 if(type == DeviceEnumeration::Full && !alcIsExtensionPresent(nullptr, "ALC_ENUMERATE_ALL_EXT"))
102 type = DeviceEnumeration::Basic;
103 const ALCchar *names = alcGetString(nullptr, (ALenum)type);
104 while(names && *names)
106 list.emplace_back(names);
107 names += strlen(names)+1;
109 return list;
112 DECL_THUNK1(String, DeviceManager, defaultDeviceName, const, DefaultDeviceType)
113 String DeviceManagerImpl::defaultDeviceName(DefaultDeviceType type) const
115 if(type == DefaultDeviceType::Full && !alcIsExtensionPresent(nullptr, "ALC_ENUMERATE_ALL_EXT"))
116 type = DefaultDeviceType::Basic;
117 const ALCchar *name = alcGetString(nullptr, (ALenum)type);
118 return name ? String(name) : String();
122 Device DeviceManager::openPlayback(const String &name)
123 { return openPlayback(name.c_str()); }
124 DECL_THUNK1(Device, DeviceManager, openPlayback,, const char*)
125 Device DeviceManagerImpl::openPlayback(const char *name)
127 mDevices.emplace_back(MakeUnique<DeviceImpl>(name));
128 return Device(mDevices.back().get());
131 Device DeviceManager::openPlayback(const String &name, const std::nothrow_t &nt) noexcept
132 { return openPlayback(name.c_str(), nt); }
133 Device DeviceManager::openPlayback(const std::nothrow_t&) noexcept
134 { return openPlayback(nullptr, std::nothrow); }
135 DECL_THUNK2(Device, DeviceManager, openPlayback, noexcept, const char*, const std::nothrow_t&)
136 Device DeviceManagerImpl::openPlayback(const char *name, const std::nothrow_t&) noexcept
138 try {
139 return openPlayback(name);
141 catch(...) {
143 return Device();
146 void DeviceManagerImpl::removeDevice(DeviceImpl *dev)
148 auto iter = std::find_if(mDevices.begin(), mDevices.end(),
149 [dev](const UniquePtr<DeviceImpl> &entry) -> bool
150 { return entry.get() == dev; }
152 if(iter != mDevices.end()) mDevices.erase(iter);