rolmodl
C++ API for the Simple Directmedia Library 2 (SDL2)
Base.cpp
1 #include "hpp/Base.hpp"
2 
3 #include <cstring>
4 #include <stdexcept>
5 #include <utility>
6 
7 namespace rolmodl {
8  namespace sys {
9  const char* name() noexcept {
10  return SDL_GetPlatform();
11  }
12 
13  // data from SDL.c
14  Id id() noexcept {
15  const char* str = name();
16 
17  if (strcmp(str, "AIX") == 0)
18  return Id::AIX;
19  if (strcmp(str, "Android") == 0)
20  return Id::android;
21  if (strcmp(str, "BSDI") == 0)
22  return Id::BSDI;
23  if (strcmp(str, "Dreamcast") == 0)
24  return Id::dreamcast;
25  if (strcmp(str, "Emscripten") == 0)
26  return Id::emscripten;
27  if (strcmp(str, "FreeBSD") == 0)
28  return Id::freeBSD;
29  if (strcmp(str, "Haiku") == 0)
30  return Id::haiku;
31  if (strcmp(str, "HP-UX") == 0)
32  return Id::HPUX;
33  if (strcmp(str, "Irix") == 0)
34  return Id::irix;
35  if (strcmp(str, "Linux") == 0)
36  return Id::linux;
37  if (strcmp(str, "Atari MiNT") == 0)
38  return Id::MiNT;
39  if (strcmp(str, "MacOS Classic") == 0)
40  return Id::macOSClassic;
41  if (strcmp(str, "Mac OS X") == 0)
42  return Id::macOSX;
43  if (strcmp(str, "NaCl") == 0)
44  return Id::NaCl;
45  if (strcmp(str, "NetBSD") == 0)
46  return Id::netBSD;
47  if (strcmp(str, "OpenBSD") == 0)
48  return Id::openBSD;
49  if (strcmp(str, "OS/2") == 0)
50  return Id::OS2;
51  if (strcmp(str, "OSF/1") == 0)
52  return Id::OSF;
53  if (strcmp(str, "QNX Neutrino") == 0)
54  return Id::QNXNeutrino;
55  if (strcmp(str, "RISC OS") == 0)
56  return Id::RISCOS;
57  if (strcmp(str, "Solaris") == 0)
58  return Id::solaris;
59  if (strcmp(str, "Windows") == 0)
60  return Id::windows;
61  if (strcmp(str, "WinRT") == 0)
62  return Id::winRT;
63  if (strcmp(str, "tvOS") == 0)
64  return Id::tvOS;
65  if (strcmp(str, "iOS") == 0)
66  return Id::iOS;
67  if (strcmp(str, "PlayStation Portable") == 0)
68  return Id::PSP;
69  return Id::unknown;
70  }
71 
72 
73  unsigned int ram() noexcept {
74  return static_cast<unsigned int>(SDL_GetSystemRAM());
75  }
76  unsigned int logicalCores() noexcept {
77  return static_cast<unsigned int>(SDL_GetCPUCount());
78  }
79 
80  namespace cpu {
81  unsigned int l1Size() noexcept {
82  return static_cast<unsigned int>(SDL_GetCPUCacheLineSize());
83  }
84 
85  bool has3DNow() noexcept {
86  return SDL_Has3DNow() == SDL_TRUE;
87  }
88  bool hasAVX() noexcept {
89  return SDL_HasAVX() == SDL_TRUE;
90  }
91  bool hasAVX2() noexcept {
92  return SDL_HasAVX2() == SDL_TRUE;
93  }
94  bool hasAltiVec() noexcept {
95  return SDL_HasAltiVec() == SDL_TRUE;
96  }
97  bool hasMMX() noexcept {
98  return SDL_HasMMX() == SDL_TRUE;
99  }
100  bool hasRDTSC() noexcept {
101  return SDL_HasRDTSC() == SDL_TRUE;
102  }
103  bool hasSSE() noexcept {
104  return SDL_HasSSE() == SDL_TRUE;
105  }
106  bool hasSSE2() noexcept {
107  return SDL_HasSSE2() == SDL_TRUE;
108  }
109  bool hasSSE3() noexcept {
110  return SDL_HasSSE3() == SDL_TRUE;
111  }
112  bool hasSSE41() noexcept {
113  return SDL_HasSSE41() == SDL_TRUE;
114  }
115  bool hasSSE42() noexcept {
116  return SDL_HasSSE42() == SDL_TRUE;
117  }
118  }
119 
120  namespace pwr {
121  Status::Status() noexcept :
122  state_(State::unknown),
123  time_(),
124  percentage_()
125  {
126  int t = -1; int p = -1;
127  int state = SDL_GetPowerInfo(&t, &p);
128  if (t != -1)
129  time_ = t;
130  if (p != -1)
131  percentage_ = p;
132 
133  if (state == SDL_POWERSTATE_ON_BATTERY)
134  state_ = State::onBattery;
135  else if (state == SDL_POWERSTATE_NO_BATTERY)
136  state_ = State::noBattery;
137  else if (state == SDL_POWERSTATE_CHARGING)
138  state_ = State::charging;
139  else if (state == SDL_POWERSTATE_CHARGED)
140  state_ = State::charged;
141  else if (state == SDL_POWERSTATE_UNKNOWN)
142  state_ = State::unknown;
143  }
144 
145  State Status::state() const noexcept {
146  return state_;
147  }
148  std::optional<int> Status::time() const noexcept {
149  return time_;
150  }
152  return percentage_;
153  }
154 
155  Status status() noexcept {
156  return Status();
157  }
158  }
159 
160  namespace clipboard {
161  bool hasText() noexcept {
162  return SDL_HasClipboardText() == SDL_TRUE;
163  }
165  char* x = SDL_GetClipboardText();
166  if (x == nullptr)
167  throw sdlexception();
168 
169  return SDLString(x);
170  }
171  void setText(const char* x) {
172  detail::throwOnErr(SDL_SetClipboardText(x));
173  }
174  }
175 
176  namespace screensaver {
177  void enable() noexcept {
178  SDL_EnableScreenSaver();
179  }
180  void disable() noexcept {
181  SDL_DisableScreenSaver();
182  }
183  bool enabled() noexcept {
184  return SDL_IsScreenSaverEnabled() == SDL_TRUE;
185  }
186  }
187 
188  namespace driver {
189  unsigned int count() {
190  int res = SDL_GetNumVideoDrivers();
191  if (res < 1)
192  throw sdlexception(res);
193 
194  return static_cast<unsigned int>(res);
195  }
196  const char* name(const unsigned int i) {
197  if (i >= count())
198  throw std::out_of_range("rolmodl::sys::driver::name");
199  return SDL_GetVideoDriver(static_cast<int>(i));
200  }
202  const char* p = SDL_GetCurrentVideoDriver();
203  if (p != nullptr)
204  return p;
205  return {};
206  }
207  }
208 
209  namespace display::unsafe {
210  Display byIndex(unsigned int i) {
211  return Display(i);
212  }
213 
214  unsigned int count() {
215  int res = SDL_GetNumVideoDisplays();
216  if (res < 1)
217  throw sdlexception(res);
218 
219  return static_cast<unsigned int>(res);
220  }
221  const char* name(const unsigned int i) {
222  if (i >= count())
223  throw std::out_of_range("rolmodl::sys::display::unsafe::name");
224  return SDL_GetDisplayName(static_cast<int>(i));
225  }
226 
227  geom::RectWH bounds(const unsigned int i) {
228  if (i >= count())
229  throw std::out_of_range("rolmodl::sys::display::unsafe::bounds");
230 
231  SDL_Rect tmp{};
232  detail::throwOnErr(SDL_GetDisplayBounds(static_cast<int>(i), &tmp));
233 
234  return geom::RectWH(tmp);
235  }
236  geom::RectWH usableBounds(const unsigned int i) {
237  if (i >= count())
238  throw std::out_of_range("rolmodl::sys::display::unsafe::usableBounds");
239 
240  SDL_Rect tmp{};
241  detail::throwOnErr(SDL_GetDisplayUsableBounds(static_cast<int>(i), &tmp));
242 
243  return geom::RectWH(tmp);
244  }
245  }
246 
247 
248  /*explicit*/ Display::Display(const unsigned int i) :
249  name_(display::unsafe::name(i)),
250  bounds_(display::unsafe::bounds(i)), usableBounds_(display::unsafe::usableBounds(i)),
251  ddpi_(0),
252  hdpi_(0),
253  vdpi_(0)
254  {
255  if (i >= display::unsafe::count())
256  throw std::out_of_range("rolmodl::sys::Display::Display");
257 
258  detail::throwOnErr(SDL_GetDisplayDPI(static_cast<int>(i), &ddpi_, &hdpi_, &vdpi_));
259  }
260 
261  const char* Display::name() const noexcept {
262  return name_;
263  }
264 
265  geom::RectWH Display::bounds() const noexcept {
266  return bounds_;
267  }
269  return usableBounds_;
270  }
271 
272  float Display::ddpi() const noexcept {
273  return ddpi_;
274  }
275  float Display::hdpi() const noexcept {
276  return hdpi_;
277  }
278  float Display::vdpi() const noexcept {
279  return vdpi_;
280  }
281 
282 
283  namespace display::mode::unsafe {
284  unsigned int countForDisplayN(unsigned int n) {
285  if (n >= display::unsafe::count())
286  throw std::out_of_range("rolmodl::sys::display::mode::unsafe::countForDisplayN");
287 
288  int res = SDL_GetNumDisplayModes(static_cast<int>(n));
289  if (res < 1)
290  throw sdlexception(res);
291  return static_cast<unsigned int>(res);
292  }
293 
294  DisplayMode fromSDL_DisplayMode(const SDL_DisplayMode x);
295  DisplayMode fromSDL_DisplayMode(const SDL_DisplayMode x) {
296  return DisplayMode{
297  .fmt = pixelfmt::id::unsafe::fromSDLEnum(x.format),
298  .size = geom::Size{x.w, x.h},
299  .refreshRate = x.refresh_rate == 0 ? std::nullopt : std::optional<unsigned int>(static_cast<unsigned int>(x.refresh_rate)),
300  .unsafeDriverData = x.driverdata
301  };
302  }
303 
304  DisplayMode desktopForDisplayN(unsigned int n) {
305  if (n >= display::unsafe::count())
306  throw std::out_of_range("rolmodl::sys::display::mode::unsafe::desktopForDisplayN");
307 
308  SDL_DisplayMode tmp{};
309  detail::throwOnErr(SDL_GetDesktopDisplayMode(static_cast<int>(n), &tmp));
310 
311  return fromSDL_DisplayMode(tmp);
312  }
313  DisplayMode currentForDisplayN(unsigned int n) {
314  if (n >= display::unsafe::count())
315  throw std::out_of_range("rolmodl::sys::display::mode::unsafe::currentForDisplayN");
316 
317  SDL_DisplayMode tmp{};
318  detail::throwOnErr(SDL_GetCurrentDisplayMode(static_cast<int>(n), &tmp));
319 
320  return fromSDL_DisplayMode(tmp);
321  }
322  DisplayMode forDisplayNByIndexI(unsigned int n, unsigned int i) {
323  if (n >= display::unsafe::count())
324  throw std::out_of_range("rolmodl::sys::display::mode::unsafe::forDisplayNByIndexI");
325 
326  if (i >= countForDisplayN(n))
327  throw std::out_of_range("rolmodl::sys::display::mode::unsafe::forDisplayNByIndexI");
328 
329  SDL_DisplayMode tmp{};
330  detail::throwOnErr(SDL_GetDisplayMode(static_cast<int>(n), static_cast<int>(i), &tmp));
331 
332  return fromSDL_DisplayMode(tmp);
333  }
334 
335  DisplayMode closestForDisplayN(unsigned int n, const DisplayMode ideal) {
336  if (n >= display::unsafe::count())
337  throw std::out_of_range("rolmodl::sys::display::mode::unsafe::closestForDisplayN");
338 
339  const SDL_DisplayMode sdl_ideal{
340  .format = pixelfmt::id::unsafe::toSDLEnum(ideal.fmt),
341  .w = ideal.size.w, .h = ideal.size.h,
342  .refresh_rate = ideal.refreshRate.has_value() ? static_cast<int>(*ideal.refreshRate) : 0,
343  .driverdata = ideal.unsafeDriverData
344  };
345 
346  SDL_DisplayMode tmp{};
347  if (SDL_GetClosestDisplayMode(static_cast<int>(n), &sdl_ideal, &tmp) == nullptr)
348  throw sdlexception();
349 
350  return fromSDL_DisplayMode(tmp);
351  }
352  }
353  }
354 
355  /*explicit*/ sdlexception::sdlexception(const int code) noexcept :
356  code_(code),
357  msg_(SDL_GetError())
358  {}
360  sdlexception(0)
361  {}
362 
363  int sdlexception::code() const noexcept {
364  return code_;
365  }
366  const char* sdlexception::what() const noexcept /*override*/ {
367  return msg_;
368  }
369 
370  int detail::throwOnErr(const int code) {
371  if (code < 0)
372  throw sdlexception(code);
373  return code;
374  }
375 
376 
377  SDLString::SDLString() noexcept :
378  raw_(nullptr)
379  {}
380 
381  /*explicit*/ SDLString::SDLString(char* x) noexcept :
382  raw_(x)
383  {
384  assert(raw_ != nullptr);
385  }
386 
388  if (raw_ != nullptr)
389  SDL_free(raw_);
390  raw_ = nullptr;
391  }
392 
393  // SDLString::SDLString(const SDLString& that) = delete;
394  SDLString::SDLString(SDLString&& that) noexcept :
395  SDLString()
396  {
397  swap(*this, that);
398  }
399 
400  // SDLString& SDLString::operator=(const SDLString& that) = delete;
402  swap(*this, that);
403  return *this;
404  }
405 
406  void swap(SDLString& a, SDLString& b) noexcept {
407  using std::swap;
408  swap(a.raw_, b.raw_);
409  }
410 
411  char* SDLString::unsafeRaw() noexcept {
412  assert(raw_ != nullptr);
413  return raw_;
414  }
415  const char* SDLString::unsafeRaw() const noexcept {
416  assert(raw_ != nullptr);
417  return raw_;
418  }
419 }
rolmodl::sys::DisplayMode::refreshRate
std::optional< unsigned int > refreshRate
Display mode refresh rate, might be unspecified.
Definition: Base.hpp:343
rolmodl::sys::DisplayMode::size
geom::Size size
Display mode size.
Definition: Base.hpp:341
rolmodl::sys::DisplayMode::fmt
pixelfmt::Id fmt
Display mode format.
Definition: Base.hpp:339
std::optional::has_value
T has_value(T... args)
rolmodl::detail::throwOnErr
int throwOnErr(const int code)
Throw a rolmodl::sdlexception if code < 0.
Definition: Base.cpp:370
rolmodl::sys::cpu::hasRDTSC
bool hasRDTSC() noexcept
Query whether the CPU supports the RDTSC instruction.
Definition: Base.cpp:100
rolmodl::sys::cpu::l1Size
unsigned int l1Size() noexcept
Get the CPU L1 cache line size in bytes.
Definition: Base.cpp:81
utility
rolmodl::SDLString::operator=
SDLString & operator=(const SDLString &that)
Copying SDLStrings is not allowed as SDL does not provide a way to allocate a new string....
cstring
rolmodl::sys::name
const char * name() noexcept
Human-readable OS name. Use rolmodl::sys::id() for OS identification purposes instead of this method.
Definition: Base.cpp:9
rolmodl::sys::pwr::Status::time
std::optional< int > time() const noexcept
Get the recorded estimated remaining battery charge life time.
Definition: Base.cpp:148
rolmodl::sys::cpu::hasAltiVec
bool hasAltiVec() noexcept
Query whether the CPU supports the AltiVec instruction set.
Definition: Base.cpp:94
rolmodl::sys::logicalCores
unsigned int logicalCores() noexcept
Get the number of available logical CPU cores.
Definition: Base.cpp:76
rolmodl::sys::Display::name
const char * name() const noexcept
Get recorded display name.
Definition: Base.cpp:261
rolmodl::sys::Display
Display information snapshot.
Definition: Base.hpp:258
rolmodl::sys::cpu::has3DNow
bool has3DNow() noexcept
Query whether the CPU supports the 3DNow! extension.
Definition: Base.cpp:85
rolmodl::sys::display::unsafe::name
const char * name(const unsigned int i)
Get the name of the ith display. Sample output: XF250Q for my Acer XF250Q. Unsafe because there is no...
Definition: Base.cpp:221
rolmodl::sys::Display::ddpi
float ddpi() const noexcept
Get recorded display diagonal DPI (dots per inch).
Definition: Base.cpp:272
rolmodl::sys::cpu::hasSSE42
bool hasSSE42() noexcept
Query whether the CPU supports the SSE4.2 (Streaming SIMD Extensions) extenstion.
Definition: Base.cpp:115
rolmodl::geom::Size
int dimensions data type. The value is in pixels. Semantically different from rolmodl::geom::Pos.
Definition: Geom.hpp:31
rolmodl::sys::cpu::hasSSE
bool hasSSE() noexcept
Query whether the CPU supports the SSE1 extenstion.
Definition: Base.cpp:103
rolmodl::sys::driver::name
const char * name(const unsigned int i)
Get the name of the ith video driver.
Definition: Base.cpp:196
rolmodl::sys::pwr::Status::Status
Status() noexcept
Initialize from the current system power status.
Definition: Base.cpp:121
rolmodl::sys::screensaver::enable
void enable() noexcept
Enable system screensaver.
Definition: Base.cpp:177
rolmodl::SDLString
Container for SDL-owned strings that must be freed with SDL_free.
Definition: Base.hpp:425
rolmodl::sys::Display::vdpi
float vdpi() const noexcept
Get recorded display vertical DPI (dots per inch).
Definition: Base.cpp:278
rolmodl::sys::clipboard::getText
SDLString getText()
Get clipboard text contents.
Definition: Base.cpp:164
rolmodl::sys::pwr::Status::percentage
std::optional< int > percentage() const noexcept
Get the recorded remaining battery charge percentage.
Definition: Base.cpp:151
rolmodl::sys::display::mode::unsafe::currentForDisplayN
DisplayMode currentForDisplayN(unsigned int n)
Get the current display mode for the nth display. Unsafe because there is no bounds checking on the i...
Definition: Base.cpp:313
rolmodl::sys::DisplayMode
Display mode parameter plain old struct.
Definition: Base.hpp:336
rolmodl::sys::cpu::hasAVX
bool hasAVX() noexcept
Query whether the CPU supports the AVX1 extension.
Definition: Base.cpp:88
rolmodl::sys::pwr::Status::state
State state() const noexcept
Get the recorded battery status/power state.
Definition: Base.cpp:145
stdexcept
rolmodl::sys::Display::usableBounds
geom::RectWH usableBounds() const noexcept
Get recorded display usable bounds. Excludes system decorations such as the menu bar and the dock.
Definition: Base.cpp:268
rolmodl::sys::ram
unsigned int ram() noexcept
Get the amount of system RAM in MB.
Definition: Base.cpp:73
rolmodl::sys::display::unsafe::count
unsigned int count()
Get the number of displays. Unsafe because the return value is unreliable and may lead to out-of-boun...
Definition: Base.cpp:214
rolmodl::sdlexception::code
int code() const noexcept
Get the recorded error code.
Definition: Base.cpp:363
rolmodl::geom::RectWH
Rectangle represented by its top left corner coordinates, width, and height.
Definition: Geom.hpp:59
rolmodl::sys::cpu::hasSSE41
bool hasSSE41() noexcept
Query whether the CPU supports the SSE4.1 extenstion.
Definition: Base.cpp:112
rolmodl::sys::display::unsafe::bounds
geom::RectWH bounds(const unsigned int i)
Get the resolution of the ith display. Unsafe because there is no bounds checking on the index.
Definition: Base.cpp:227
rolmodl::sys::display::unsafe::usableBounds
geom::RectWH usableBounds(const unsigned int i)
Get the bounds of the usable space of the ith display. Excludes system decorations such as the menu b...
Definition: Base.cpp:236
rolmodl::sys::cpu::hasSSE2
bool hasSSE2() noexcept
Query whether the CPU supports the SSE2 extenstion.
Definition: Base.cpp:106
rolmodl::sys::screensaver::enabled
bool enabled() noexcept
Query whether the system screensaver is enabled.
Definition: Base.cpp:183
rolmodl::sys::display::mode::unsafe::desktopForDisplayN
DisplayMode desktopForDisplayN(unsigned int n)
Get the display mode used by the system desktop for the nth display. Unsafe because there is no bound...
Definition: Base.cpp:304
rolmodl::sys::clipboard::setText
void setText(const char *x)
Set clipboard text contents.
Definition: Base.cpp:171
rolmodl::sys::pwr::Status
System power status snapshot.
Definition: Base.hpp:151
std::nullopt
T nullopt
rolmodl::sys::pwr::State
State
Indicates battery status a.k.a. the system power state.
Definition: Base.hpp:138
rolmodl::sys::DisplayMode::unsafeDriverData
void * unsafeDriverData
Unspecified driver-specific data.
Definition: Base.hpp:345
rolmodl
Main namespace.
Definition: Base.cpp:7
rolmodl::sys::clipboard::hasText
bool hasText() noexcept
Query whether thhe clipboard has text contents.
Definition: Base.cpp:161
std::swap
T swap(T... args)
rolmodl::sys::display::mode::unsafe::countForDisplayN
unsigned int countForDisplayN(unsigned int n)
Get the amount of display modes available for the nth display.
Definition: Base.cpp:284
rolmodl::sdlexception
Exception type containing an error code and the last SDL error at the moment of creation.
Definition: Base.hpp:399
rolmodl::sys::driver::count
unsigned int count()
Query the amount of available video drivers.
Definition: Base.cpp:189
rolmodl::sdlexception::sdlexception
sdlexception() noexcept
Initialize with the error code arbitrarily set to 0 if one isn't available and the last SDL error mes...
Definition: Base.cpp:359
rolmodl::sys::cpu::hasSSE3
bool hasSSE3() noexcept
Query whether the CPU supports the SSE3 extenstion.
Definition: Base.cpp:109
rolmodl::sys::Id
Id
OS type enum.
Definition: Base.hpp:28
std::out_of_range
std::optional< int >
rolmodl::sys::display::unsafe::byIndex
Display byIndex(unsigned int i)
Get display information for the ith display. Unsafe because there is no bounds checking on the index.
Definition: Base.cpp:210
rolmodl::sys::display::mode::unsafe::closestForDisplayN
DisplayMode closestForDisplayN(unsigned int n, const DisplayMode ideal)
Get the display mode closest to the one specified for the nth display. Unsafe because there is no bou...
Definition: Base.cpp:335
rolmodl::sys::driver::current
std::optional< const char * > current() noexcept
Query the current video driver name.
Definition: Base.cpp:201
rolmodl::sys::cpu::hasMMX
bool hasMMX() noexcept
Query whether the CPU supports the MMX instruction set.
Definition: Base.cpp:97
rolmodl::sys::Display::bounds
geom::RectWH bounds() const noexcept
Get recorded display resolution.
Definition: Base.cpp:265
rolmodl::SDLString::unsafeRaw
char * unsafeRaw() noexcept
Get the underlying char*. Unsafe because it allows invalidating the pointer by freeing it.
Definition: Base.cpp:411
rolmodl::sdlexception::what
const char * what() const noexcept override
Get the recorded error message.
Definition: Base.cpp:366
rolmodl::SDLString::~SDLString
~SDLString() noexcept
SDL_free the underlying char*.
Definition: Base.cpp:387
rolmodl::sys::cpu::hasAVX2
bool hasAVX2() noexcept
Query whether the CPU supports the AVX2 extension.
Definition: Base.cpp:91
rolmodl::sys::pwr::status
Status status() noexcept
Get a system power status snapshot.
Definition: Base.cpp:155
Base.hpp
rolmodl::sys::id
Id id() noexcept
Get id of the OS on which the code is running. May differ from whatever operating system the code was...
Definition: Base.cpp:14
rolmodl::sys::screensaver::disable
void disable() noexcept
Disable system screensaver.
Definition: Base.cpp:180
rolmodl::sys::Display::hdpi
float hdpi() const noexcept
Get recorded display horizontal DPI (dots per inch).
Definition: Base.cpp:275
rolmodl::sys::display::mode::unsafe::forDisplayNByIndexI
DisplayMode forDisplayNByIndexI(unsigned int n, unsigned int i)
Get the ith display mode for the nth display. Unsafe because there is no bounds checking on either in...
Definition: Base.cpp:322