🛠️🐜 Antkeeper superbuild with dependencies included https://antkeeper.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

106 lines
2.9 KiB

  1. /**
  2. * OpenAL cross platform audio library
  3. * Copyright (C) 1999-2000 by authors.
  4. * This library is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU Library General Public
  6. * License as published by the Free Software Foundation; either
  7. * version 2 of the License, or (at your option) any later version.
  8. *
  9. * This library is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * Library General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Library General Public
  15. * License along with this library; if not, write to the
  16. * Free Software Foundation, Inc.,
  17. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  18. * Or go to http://www.gnu.org/copyleft/lgpl.html
  19. */
  20. #include "config.h"
  21. #ifdef _WIN32
  22. #define WIN32_LEAN_AND_MEAN
  23. #include <windows.h>
  24. #endif
  25. #include <atomic>
  26. #include <csignal>
  27. #include <cstdarg>
  28. #include <cstdio>
  29. #include <cstring>
  30. #include <mutex>
  31. #include "AL/al.h"
  32. #include "AL/alc.h"
  33. #include "alc/context.h"
  34. #include "almalloc.h"
  35. #include "core/except.h"
  36. #include "core/logging.h"
  37. #include "opthelpers.h"
  38. #include "vector.h"
  39. bool TrapALError{false};
  40. void ALCcontext::setError(ALenum errorCode, const char *msg, ...)
  41. {
  42. auto message = al::vector<char>(256);
  43. va_list args, args2;
  44. va_start(args, msg);
  45. va_copy(args2, args);
  46. int msglen{std::vsnprintf(message.data(), message.size(), msg, args)};
  47. if(msglen >= 0 && static_cast<size_t>(msglen) >= message.size())
  48. {
  49. message.resize(static_cast<size_t>(msglen) + 1u);
  50. msglen = std::vsnprintf(message.data(), message.size(), msg, args2);
  51. }
  52. va_end(args2);
  53. va_end(args);
  54. if(msglen >= 0) msg = message.data();
  55. else msg = "<internal error constructing message>";
  56. WARN("Error generated on context %p, code 0x%04x, \"%s\"\n",
  57. decltype(std::declval<void*>()){this}, errorCode, msg);
  58. if(TrapALError)
  59. {
  60. #ifdef _WIN32
  61. /* DebugBreak will cause an exception if there is no debugger */
  62. if(IsDebuggerPresent())
  63. DebugBreak();
  64. #elif defined(SIGTRAP)
  65. raise(SIGTRAP);
  66. #endif
  67. }
  68. ALenum curerr{AL_NO_ERROR};
  69. mLastError.compare_exchange_strong(curerr, errorCode);
  70. }
  71. AL_API ALenum AL_APIENTRY alGetError(void)
  72. START_API_FUNC
  73. {
  74. ContextRef context{GetContextRef()};
  75. if(unlikely(!context))
  76. {
  77. static constexpr ALenum deferror{AL_INVALID_OPERATION};
  78. WARN("Querying error state on null context (implicitly 0x%04x)\n", deferror);
  79. if(TrapALError)
  80. {
  81. #ifdef _WIN32
  82. if(IsDebuggerPresent())
  83. DebugBreak();
  84. #elif defined(SIGTRAP)
  85. raise(SIGTRAP);
  86. #endif
  87. }
  88. return deferror;
  89. }
  90. return context->mLastError.exchange(AL_NO_ERROR);
  91. }
  92. END_API_FUNC