]> git.tdb.fi Git - ext/openal.git/blob - al/error.cpp
Import OpenAL Soft 1.23.1 sources
[ext/openal.git] / al / error.cpp
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
21 #include "config.h"
22
23 #ifdef _WIN32
24 #define WIN32_LEAN_AND_MEAN
25 #include <windows.h>
26 #endif
27
28 #include <atomic>
29 #include <csignal>
30 #include <cstdarg>
31 #include <cstdio>
32 #include <cstring>
33 #include <mutex>
34
35 #include "AL/al.h"
36 #include "AL/alc.h"
37
38 #include "alc/context.h"
39 #include "almalloc.h"
40 #include "core/except.h"
41 #include "core/logging.h"
42 #include "opthelpers.h"
43 #include "vector.h"
44
45
46 bool TrapALError{false};
47
48 void ALCcontext::setError(ALenum errorCode, const char *msg, ...)
49 {
50     auto message = al::vector<char>(256);
51
52     va_list args, args2;
53     va_start(args, msg);
54     va_copy(args2, args);
55     int msglen{std::vsnprintf(message.data(), message.size(), msg, args)};
56     if(msglen >= 0 && static_cast<size_t>(msglen) >= message.size())
57     {
58         message.resize(static_cast<size_t>(msglen) + 1u);
59         msglen = std::vsnprintf(message.data(), message.size(), msg, args2);
60     }
61     va_end(args2);
62     va_end(args);
63
64     if(msglen >= 0) msg = message.data();
65     else msg = "<internal error constructing message>";
66
67     WARN("Error generated on context %p, code 0x%04x, \"%s\"\n",
68         decltype(std::declval<void*>()){this}, errorCode, msg);
69     if(TrapALError)
70     {
71 #ifdef _WIN32
72         /* DebugBreak will cause an exception if there is no debugger */
73         if(IsDebuggerPresent())
74             DebugBreak();
75 #elif defined(SIGTRAP)
76         raise(SIGTRAP);
77 #endif
78     }
79
80     ALenum curerr{AL_NO_ERROR};
81     mLastError.compare_exchange_strong(curerr, errorCode);
82 }
83
84 AL_API ALenum AL_APIENTRY alGetError(void)
85 START_API_FUNC
86 {
87     ContextRef context{GetContextRef()};
88     if(!context) UNLIKELY
89     {
90         static constexpr ALenum deferror{AL_INVALID_OPERATION};
91         WARN("Querying error state on null context (implicitly 0x%04x)\n", deferror);
92         if(TrapALError)
93         {
94 #ifdef _WIN32
95             if(IsDebuggerPresent())
96                 DebugBreak();
97 #elif defined(SIGTRAP)
98             raise(SIGTRAP);
99 #endif
100         }
101         return deferror;
102     }
103
104     return context->mLastError.exchange(AL_NO_ERROR);
105 }
106 END_API_FUNC