Store the DeviceManagerImpl as a reference
[alure.git] / src / devicemanager.cpp
bloba2eb5ecc76a21c52ef1859946446ba29325710d8
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"
15 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 ALCboolean (ALC_APIENTRY*DeviceManagerImpl::SetThreadContext)(ALCcontext*);
57 DeviceManager DeviceManager::get()
58 { return DeviceManager(DeviceManagerImpl::get()); }
59 DeviceManagerImpl &DeviceManagerImpl::get()
61 static DeviceManagerImpl singleton;
62 return singleton;
66 DeviceManagerImpl::DeviceManagerImpl()
68 if(alcIsExtensionPresent(0, "ALC_EXT_thread_local_context"))
69 GetDeviceProc(&SetThreadContext, 0, "alcSetThreadContext");
72 DeviceManagerImpl::~DeviceManagerImpl()
77 bool DeviceManager::queryExtension(const String &name) const
78 { return pImpl.queryExtension(name.c_str()); }
79 bool DeviceManager::queryExtension(const char *name) const
80 { return pImpl.queryExtension(name); }
81 bool DeviceManagerImpl::queryExtension(const char *name) const
83 return alcIsExtensionPresent(nullptr, name);
86 Vector<String> DeviceManager::enumerate(DeviceEnumeration type) const
87 { return pImpl.enumerate(type); }
88 Vector<String> DeviceManagerImpl::enumerate(DeviceEnumeration type) const
90 Vector<String> list;
91 if(type == DeviceEnumeration::Full && !alcIsExtensionPresent(nullptr, "ALC_ENUMERATE_ALL_EXT"))
92 type = DeviceEnumeration::Basic;
93 const ALCchar *names = alcGetString(nullptr, (ALenum)type);
94 while(names && *names)
96 list.emplace_back(names);
97 names += strlen(names)+1;
99 return list;
102 String DeviceManager::defaultDeviceName(DefaultDeviceType type) const
103 { return pImpl.defaultDeviceName(type); }
104 String DeviceManagerImpl::defaultDeviceName(DefaultDeviceType type) const
106 if(type == DefaultDeviceType::Full && !alcIsExtensionPresent(nullptr, "ALC_ENUMERATE_ALL_EXT"))
107 type = DefaultDeviceType::Basic;
108 const ALCchar *name = alcGetString(nullptr, (ALenum)type);
109 return name ? String(name) : String();
113 Device DeviceManager::openPlayback(const String &name)
114 { return pImpl.openPlayback(name.c_str()); }
115 Device DeviceManager::openPlayback(const char *name)
116 { return pImpl.openPlayback(name); }
117 Device DeviceManagerImpl::openPlayback(const char *name)
119 ALCdevice *dev = alcOpenDevice(name);
120 if(!dev) throw alc_error(alcGetError(nullptr), "alcOpenDevice failed");
122 try {
123 mDevices.emplace_back(MakeUnique<DeviceImpl>(dev));
124 return Device(mDevices.back().get());
126 catch(...) {
127 alcCloseDevice(dev);
128 throw;
132 Device DeviceManager::openPlayback(const String &name, const std::nothrow_t &nt) noexcept
133 { return pImpl.openPlayback(name.c_str(), nt); }
134 Device DeviceManager::openPlayback(const std::nothrow_t&) noexcept
135 { return pImpl.openPlayback(nullptr, std::nothrow); }
136 Device DeviceManager::openPlayback(const char *name, const std::nothrow_t &nt) noexcept
137 { return pImpl.openPlayback(name, nt); }
138 Device DeviceManagerImpl::openPlayback(const char *name, const std::nothrow_t&) noexcept
140 try {
141 return openPlayback(name);
143 catch(...) {
145 return Device();
148 void DeviceManagerImpl::removeDevice(DeviceImpl *dev)
150 auto iter = std::find_if(mDevices.begin(), mDevices.end(),
151 [dev](const UniquePtr<DeviceImpl> &entry) -> bool
152 { return entry.get() == dev; }
154 if(iter != mDevices.end()) mDevices.erase(iter);