14 #include <string_view>
15 #include <unordered_map>
22 #include "alc/context.h"
23 #include "alc/device.h"
24 #include "alnumeric.h"
27 #include "auxeffectslot.h"
29 #include "core/logging.h"
30 #include "core/voice.h"
31 #include "direct_defs.h"
35 #include "intrusive_ptr.h"
36 #include "opthelpers.h"
40 /* Declared here to prevent compilers from thinking it should be inlined, which
41 * GCC warns about increasing code size.
43 DebugGroup::~DebugGroup() = default;
47 static_assert(DebugSeverityBase
+DebugSeverityCount
<= 32, "Too many debug bits");
49 template<typename T
, T
...Vals
>
50 constexpr auto make_array_sequence(std::integer_sequence
<T
, Vals
...>)
51 { return std::array
<T
,sizeof...(Vals
)>{Vals
...}; }
53 template<typename T
, size_t N
>
54 constexpr auto make_array_sequence()
55 { return make_array_sequence(std::make_integer_sequence
<T
,N
>{}); }
58 constexpr auto GetDebugSource(ALenum source
) noexcept
-> std::optional
<DebugSource
>
62 case AL_DEBUG_SOURCE_API_EXT
: return DebugSource::API
;
63 case AL_DEBUG_SOURCE_AUDIO_SYSTEM_EXT
: return DebugSource::System
;
64 case AL_DEBUG_SOURCE_THIRD_PARTY_EXT
: return DebugSource::ThirdParty
;
65 case AL_DEBUG_SOURCE_APPLICATION_EXT
: return DebugSource::Application
;
66 case AL_DEBUG_SOURCE_OTHER_EXT
: return DebugSource::Other
;
71 constexpr auto GetDebugType(ALenum type
) noexcept
-> std::optional
<DebugType
>
75 case AL_DEBUG_TYPE_ERROR_EXT
: return DebugType::Error
;
76 case AL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_EXT
: return DebugType::DeprecatedBehavior
;
77 case AL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_EXT
: return DebugType::UndefinedBehavior
;
78 case AL_DEBUG_TYPE_PORTABILITY_EXT
: return DebugType::Portability
;
79 case AL_DEBUG_TYPE_PERFORMANCE_EXT
: return DebugType::Performance
;
80 case AL_DEBUG_TYPE_MARKER_EXT
: return DebugType::Marker
;
81 case AL_DEBUG_TYPE_PUSH_GROUP_EXT
: return DebugType::PushGroup
;
82 case AL_DEBUG_TYPE_POP_GROUP_EXT
: return DebugType::PopGroup
;
83 case AL_DEBUG_TYPE_OTHER_EXT
: return DebugType::Other
;
88 constexpr auto GetDebugSeverity(ALenum severity
) noexcept
-> std::optional
<DebugSeverity
>
92 case AL_DEBUG_SEVERITY_HIGH_EXT
: return DebugSeverity::High
;
93 case AL_DEBUG_SEVERITY_MEDIUM_EXT
: return DebugSeverity::Medium
;
94 case AL_DEBUG_SEVERITY_LOW_EXT
: return DebugSeverity::Low
;
95 case AL_DEBUG_SEVERITY_NOTIFICATION_EXT
: return DebugSeverity::Notification
;
101 constexpr auto GetDebugSourceEnum(DebugSource source
) -> ALenum
105 case DebugSource::API
: return AL_DEBUG_SOURCE_API_EXT
;
106 case DebugSource::System
: return AL_DEBUG_SOURCE_AUDIO_SYSTEM_EXT
;
107 case DebugSource::ThirdParty
: return AL_DEBUG_SOURCE_THIRD_PARTY_EXT
;
108 case DebugSource::Application
: return AL_DEBUG_SOURCE_APPLICATION_EXT
;
109 case DebugSource::Other
: return AL_DEBUG_SOURCE_OTHER_EXT
;
111 throw std::runtime_error
{"Unexpected debug source value "+std::to_string(al::to_underlying(source
))};
114 constexpr auto GetDebugTypeEnum(DebugType type
) -> ALenum
118 case DebugType::Error
: return AL_DEBUG_TYPE_ERROR_EXT
;
119 case DebugType::DeprecatedBehavior
: return AL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_EXT
;
120 case DebugType::UndefinedBehavior
: return AL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_EXT
;
121 case DebugType::Portability
: return AL_DEBUG_TYPE_PORTABILITY_EXT
;
122 case DebugType::Performance
: return AL_DEBUG_TYPE_PERFORMANCE_EXT
;
123 case DebugType::Marker
: return AL_DEBUG_TYPE_MARKER_EXT
;
124 case DebugType::PushGroup
: return AL_DEBUG_TYPE_PUSH_GROUP_EXT
;
125 case DebugType::PopGroup
: return AL_DEBUG_TYPE_POP_GROUP_EXT
;
126 case DebugType::Other
: return AL_DEBUG_TYPE_OTHER_EXT
;
128 throw std::runtime_error
{"Unexpected debug type value "+std::to_string(al::to_underlying(type
))};
131 constexpr auto GetDebugSeverityEnum(DebugSeverity severity
) -> ALenum
135 case DebugSeverity::High
: return AL_DEBUG_SEVERITY_HIGH_EXT
;
136 case DebugSeverity::Medium
: return AL_DEBUG_SEVERITY_MEDIUM_EXT
;
137 case DebugSeverity::Low
: return AL_DEBUG_SEVERITY_LOW_EXT
;
138 case DebugSeverity::Notification
: return AL_DEBUG_SEVERITY_NOTIFICATION_EXT
;
140 throw std::runtime_error
{"Unexpected debug severity value "+std::to_string(al::to_underlying(severity
))};
144 constexpr auto GetDebugSourceName(DebugSource source
) noexcept
-> const char*
148 case DebugSource::API
: return "API";
149 case DebugSource::System
: return "Audio System";
150 case DebugSource::ThirdParty
: return "Third Party";
151 case DebugSource::Application
: return "Application";
152 case DebugSource::Other
: return "Other";
154 return "<invalid source>";
157 constexpr auto GetDebugTypeName(DebugType type
) noexcept
-> const char*
161 case DebugType::Error
: return "Error";
162 case DebugType::DeprecatedBehavior
: return "Deprecated Behavior";
163 case DebugType::UndefinedBehavior
: return "Undefined Behavior";
164 case DebugType::Portability
: return "Portability";
165 case DebugType::Performance
: return "Performance";
166 case DebugType::Marker
: return "Marker";
167 case DebugType::PushGroup
: return "Push Group";
168 case DebugType::PopGroup
: return "Pop Group";
169 case DebugType::Other
: return "Other";
171 return "<invalid type>";
174 constexpr auto GetDebugSeverityName(DebugSeverity severity
) noexcept
-> const char*
178 case DebugSeverity::High
: return "High";
179 case DebugSeverity::Medium
: return "Medium";
180 case DebugSeverity::Low
: return "Low";
181 case DebugSeverity::Notification
: return "Notification";
183 return "<invalid severity>";
189 void ALCcontext::sendDebugMessage(std::unique_lock
<std::mutex
> &debuglock
, DebugSource source
,
190 DebugType type
, ALuint id
, DebugSeverity severity
, std::string_view message
)
192 if(!mDebugEnabled
.load(std::memory_order_relaxed
)) UNLIKELY
195 if(message
.length() >= MaxDebugMessageLength
) UNLIKELY
197 ERR("Debug message too long (%zu >= %d):\n-> %.*s\n", message
.length(),
198 MaxDebugMessageLength
, al::sizei(message
), message
.data());
202 DebugGroup
&debug
= mDebugGroups
.back();
204 const uint64_t idfilter
{(1_u64
<< (DebugSourceBase
+al::to_underlying(source
)))
205 | (1_u64
<< (DebugTypeBase
+al::to_underlying(type
)))
206 | (uint64_t{id
} << 32)};
207 auto iditer
= std::lower_bound(debug
.mIdFilters
.cbegin(), debug
.mIdFilters
.cend(), idfilter
);
208 if(iditer
!= debug
.mIdFilters
.cend() && *iditer
== idfilter
)
211 const uint filter
{(1u << (DebugSourceBase
+al::to_underlying(source
)))
212 | (1u << (DebugTypeBase
+al::to_underlying(type
)))
213 | (1u << (DebugSeverityBase
+al::to_underlying(severity
)))};
214 auto iter
= std::lower_bound(debug
.mFilters
.cbegin(), debug
.mFilters
.cend(), filter
);
215 if(iter
!= debug
.mFilters
.cend() && *iter
== filter
)
220 auto callback
= mDebugCb
;
221 auto param
= mDebugParam
;
223 callback(GetDebugSourceEnum(source
), GetDebugTypeEnum(type
), id
,
224 GetDebugSeverityEnum(severity
), static_cast<ALsizei
>(message
.length()), message
.data(),
229 if(mDebugLog
.size() < MaxDebugLoggedMessages
)
230 mDebugLog
.emplace_back(source
, type
, id
, severity
, message
);
232 ERR("Debug message log overflow. Lost message:\n"
237 " Message: \"%.*s\"\n",
238 GetDebugSourceName(source
), GetDebugTypeName(type
), id
,
239 GetDebugSeverityName(severity
), al::sizei(message
), message
.data());
244 FORCE_ALIGN
DECL_FUNCEXT2(void, alDebugMessageCallback
,EXT
, ALDEBUGPROCEXT
,callback
, void*,userParam
)
245 FORCE_ALIGN
void AL_APIENTRY
alDebugMessageCallbackDirectEXT(ALCcontext
*context
,
246 ALDEBUGPROCEXT callback
, void *userParam
) noexcept
248 std::lock_guard
<std::mutex
> debuglock
{context
->mDebugCbLock
};
249 context
->mDebugCb
= callback
;
250 context
->mDebugParam
= userParam
;
254 FORCE_ALIGN
DECL_FUNCEXT6(void, alDebugMessageInsert
,EXT
, ALenum
,source
, ALenum
,type
, ALuint
,id
, ALenum
,severity
, ALsizei
,length
, const ALchar
*,message
)
255 FORCE_ALIGN
void AL_APIENTRY
alDebugMessageInsertDirectEXT(ALCcontext
*context
, ALenum source
,
256 ALenum type
, ALuint id
, ALenum severity
, ALsizei length
, const ALchar
*message
) noexcept
258 if(!context
->mContextFlags
.test(ContextFlags::DebugBit
))
262 throw al::context_error
{AL_INVALID_VALUE
, "Null message pointer"};
264 auto msgview
= (length
< 0) ? std::string_view
{message
}
265 : std::string_view
{message
, static_cast<uint
>(length
)};
266 if(msgview
.size() >= MaxDebugMessageLength
)
267 throw al::context_error
{AL_INVALID_VALUE
, "Debug message too long (%zu >= %d)",
268 msgview
.size(), MaxDebugMessageLength
};
270 auto dsource
= GetDebugSource(source
);
272 throw al::context_error
{AL_INVALID_ENUM
, "Invalid debug source 0x%04x", source
};
273 if(*dsource
!= DebugSource::ThirdParty
&& *dsource
!= DebugSource::Application
)
274 throw al::context_error
{AL_INVALID_ENUM
, "Debug source 0x%04x not allowed", source
};
276 auto dtype
= GetDebugType(type
);
278 throw al::context_error
{AL_INVALID_ENUM
, "Invalid debug type 0x%04x", type
};
280 auto dseverity
= GetDebugSeverity(severity
);
282 throw al::context_error
{AL_INVALID_ENUM
, "Invalid debug severity 0x%04x", severity
};
284 context
->debugMessage(*dsource
, *dtype
, id
, *dseverity
, msgview
);
286 catch(al::context_error
& e
) {
287 context
->setError(e
.errorCode(), "%s", e
.what());
291 FORCE_ALIGN
DECL_FUNCEXT6(void, alDebugMessageControl
,EXT
, ALenum
,source
, ALenum
,type
, ALenum
,severity
, ALsizei
,count
, const ALuint
*,ids
, ALboolean
,enable
)
292 FORCE_ALIGN
void AL_APIENTRY
alDebugMessageControlDirectEXT(ALCcontext
*context
, ALenum source
,
293 ALenum type
, ALenum severity
, ALsizei count
, const ALuint
*ids
, ALboolean enable
) noexcept
298 throw al::context_error
{AL_INVALID_VALUE
, "IDs is null with non-0 count"};
299 if(source
== AL_DONT_CARE_EXT
)
300 throw al::context_error
{AL_INVALID_OPERATION
,
301 "Debug source cannot be AL_DONT_CARE_EXT with IDs"};
302 if(type
== AL_DONT_CARE_EXT
)
303 throw al::context_error
{AL_INVALID_OPERATION
,
304 "Debug type cannot be AL_DONT_CARE_EXT with IDs"};
305 if(severity
!= AL_DONT_CARE_EXT
)
306 throw al::context_error
{AL_INVALID_OPERATION
,
307 "Debug severity must be AL_DONT_CARE_EXT with IDs"};
310 if(enable
!= AL_TRUE
&& enable
!= AL_FALSE
)
311 throw al::context_error
{AL_INVALID_ENUM
, "Invalid debug enable %d", enable
};
313 static constexpr size_t ElemCount
{DebugSourceCount
+ DebugTypeCount
+ DebugSeverityCount
};
314 static constexpr auto Values
= make_array_sequence
<uint8_t,ElemCount
>();
316 auto srcIndices
= al::span
{Values
}.subspan(DebugSourceBase
,DebugSourceCount
);
317 if(source
!= AL_DONT_CARE_EXT
)
319 auto dsource
= GetDebugSource(source
);
321 throw al::context_error
{AL_INVALID_ENUM
, "Invalid debug source 0x%04x", source
};
322 srcIndices
= srcIndices
.subspan(al::to_underlying(*dsource
), 1);
325 auto typeIndices
= al::span
{Values
}.subspan(DebugTypeBase
,DebugTypeCount
);
326 if(type
!= AL_DONT_CARE_EXT
)
328 auto dtype
= GetDebugType(type
);
330 throw al::context_error
{AL_INVALID_ENUM
, "Invalid debug type 0x%04x", type
};
331 typeIndices
= typeIndices
.subspan(al::to_underlying(*dtype
), 1);
334 auto svrIndices
= al::span
{Values
}.subspan(DebugSeverityBase
,DebugSeverityCount
);
335 if(severity
!= AL_DONT_CARE_EXT
)
337 auto dseverity
= GetDebugSeverity(severity
);
339 throw al::context_error
{AL_INVALID_ENUM
, "Invalid debug severity 0x%04x", severity
};
340 svrIndices
= svrIndices
.subspan(al::to_underlying(*dseverity
), 1);
343 std::lock_guard
<std::mutex
> debuglock
{context
->mDebugCbLock
};
344 DebugGroup
&debug
= context
->mDebugGroups
.back();
347 const uint filterbase
{(1u<<srcIndices
[0]) | (1u<<typeIndices
[0])};
349 for(const uint id
: al::span
{ids
, static_cast<uint
>(count
)})
351 const uint64_t filter
{filterbase
| (uint64_t{id
} << 32)};
353 auto iter
= std::lower_bound(debug
.mIdFilters
.cbegin(), debug
.mIdFilters
.cend(),
355 if(!enable
&& (iter
== debug
.mIdFilters
.cend() || *iter
!= filter
))
356 debug
.mIdFilters
.insert(iter
, filter
);
357 else if(enable
&& iter
!= debug
.mIdFilters
.cend() && *iter
== filter
)
358 debug
.mIdFilters
.erase(iter
);
363 auto apply_filter
= [enable
,&debug
](const uint filter
)
365 auto iter
= std::lower_bound(debug
.mFilters
.cbegin(), debug
.mFilters
.cend(), filter
);
366 if(!enable
&& (iter
== debug
.mFilters
.cend() || *iter
!= filter
))
367 debug
.mFilters
.insert(iter
, filter
);
368 else if(enable
&& iter
!= debug
.mFilters
.cend() && *iter
== filter
)
369 debug
.mFilters
.erase(iter
);
371 auto apply_severity
= [apply_filter
,svrIndices
](const uint filter
)
373 std::for_each(svrIndices
.cbegin(), svrIndices
.cend(),
374 [apply_filter
,filter
](const uint idx
){ apply_filter(filter
| (1<<idx
)); });
376 auto apply_type
= [apply_severity
,typeIndices
](const uint filter
)
378 std::for_each(typeIndices
.cbegin(), typeIndices
.cend(),
379 [apply_severity
,filter
](const uint idx
){ apply_severity(filter
| (1<<idx
)); });
381 std::for_each(srcIndices
.cbegin(), srcIndices
.cend(),
382 [apply_type
](const uint idx
){ apply_type(1<<idx
); });
385 catch(al::context_error
& e
) {
386 context
->setError(e
.errorCode(), "%s", e
.what());
390 FORCE_ALIGN
DECL_FUNCEXT4(void, alPushDebugGroup
,EXT
, ALenum
,source
, ALuint
,id
, ALsizei
,length
, const ALchar
*,message
)
391 FORCE_ALIGN
void AL_APIENTRY
alPushDebugGroupDirectEXT(ALCcontext
*context
, ALenum source
,
392 ALuint id
, ALsizei length
, const ALchar
*message
) noexcept
396 size_t newlen
{std::strlen(message
)};
397 if(newlen
>= MaxDebugMessageLength
)
398 throw al::context_error
{AL_INVALID_VALUE
, "Debug message too long (%zu >= %d)", newlen
,
399 MaxDebugMessageLength
};
400 length
= static_cast<ALsizei
>(newlen
);
402 else if(length
>= MaxDebugMessageLength
)
403 throw al::context_error
{AL_INVALID_VALUE
, "Debug message too long (%d >= %d)", length
,
404 MaxDebugMessageLength
};
406 auto dsource
= GetDebugSource(source
);
408 throw al::context_error
{AL_INVALID_ENUM
, "Invalid debug source 0x%04x", source
};
409 if(*dsource
!= DebugSource::ThirdParty
&& *dsource
!= DebugSource::Application
)
410 throw al::context_error
{AL_INVALID_ENUM
, "Debug source 0x%04x not allowed", source
};
412 std::unique_lock
<std::mutex
> debuglock
{context
->mDebugCbLock
};
413 if(context
->mDebugGroups
.size() >= MaxDebugGroupDepth
)
414 throw al::context_error
{AL_STACK_OVERFLOW_EXT
, "Pushing too many debug groups"};
416 context
->mDebugGroups
.emplace_back(*dsource
, id
,
417 std::string_view
{message
, static_cast<uint
>(length
)});
418 auto &oldback
= *(context
->mDebugGroups
.end()-2);
419 auto &newback
= context
->mDebugGroups
.back();
421 newback
.mFilters
= oldback
.mFilters
;
422 newback
.mIdFilters
= oldback
.mIdFilters
;
424 if(context
->mContextFlags
.test(ContextFlags::DebugBit
))
425 context
->sendDebugMessage(debuglock
, newback
.mSource
, DebugType::PushGroup
, newback
.mId
,
426 DebugSeverity::Notification
, newback
.mMessage
);
428 catch(al::context_error
& e
) {
429 context
->setError(e
.errorCode(), "%s", e
.what());
432 FORCE_ALIGN
DECL_FUNCEXT(void, alPopDebugGroup
,EXT
)
433 FORCE_ALIGN
void AL_APIENTRY
alPopDebugGroupDirectEXT(ALCcontext
*context
) noexcept
435 std::unique_lock
<std::mutex
> debuglock
{context
->mDebugCbLock
};
436 if(context
->mDebugGroups
.size() <= 1)
437 throw al::context_error
{AL_STACK_UNDERFLOW_EXT
,
438 "Attempting to pop the default debug group"};
440 DebugGroup
&debug
= context
->mDebugGroups
.back();
441 const auto source
= debug
.mSource
;
442 const auto id
= debug
.mId
;
443 std::string message
{std::move(debug
.mMessage
)};
445 context
->mDebugGroups
.pop_back();
446 if(context
->mContextFlags
.test(ContextFlags::DebugBit
))
447 context
->sendDebugMessage(debuglock
, source
, DebugType::PopGroup
, id
,
448 DebugSeverity::Notification
, message
);
450 catch(al::context_error
& e
) {
451 context
->setError(e
.errorCode(), "%s", e
.what());
455 FORCE_ALIGN
DECL_FUNCEXT8(ALuint
, alGetDebugMessageLog
,EXT
, ALuint
,count
, ALsizei
,logBufSize
, ALenum
*,sources
, ALenum
*,types
, ALuint
*,ids
, ALenum
*,severities
, ALsizei
*,lengths
, ALchar
*,logBuf
)
456 FORCE_ALIGN ALuint AL_APIENTRY
alGetDebugMessageLogDirectEXT(ALCcontext
*context
, ALuint count
,
457 ALsizei logBufSize
, ALenum
*sources
, ALenum
*types
, ALuint
*ids
, ALenum
*severities
,
458 ALsizei
*lengths
, ALchar
*logBuf
) noexcept
460 if(logBuf
&& logBufSize
< 0)
461 throw al::context_error
{AL_INVALID_VALUE
, "Negative debug log buffer size"};
463 const auto sourcesSpan
= al::span
{sources
, sources
? count
: 0u};
464 const auto typesSpan
= al::span
{types
, types
? count
: 0u};
465 const auto idsSpan
= al::span
{ids
, ids
? count
: 0u};
466 const auto severitiesSpan
= al::span
{severities
, severities
? count
: 0u};
467 const auto lengthsSpan
= al::span
{lengths
, lengths
? count
: 0u};
468 const auto logSpan
= al::span
{logBuf
, logBuf
? static_cast<ALuint
>(logBufSize
) : 0u};
470 auto sourceiter
= sourcesSpan
.begin();
471 auto typeiter
= typesSpan
.begin();
472 auto iditer
= idsSpan
.begin();
473 auto severityiter
= severitiesSpan
.begin();
474 auto lengthiter
= lengthsSpan
.begin();
475 auto logiter
= logSpan
.begin();
477 auto debuglock
= std::lock_guard
{context
->mDebugCbLock
};
478 for(ALuint i
{0};i
< count
;++i
)
480 if(context
->mDebugLog
.empty())
483 auto &entry
= context
->mDebugLog
.front();
484 const auto tocopy
= size_t{entry
.mMessage
.size() + 1};
485 if(al::to_address(logiter
) != nullptr)
487 if(static_cast<size_t>(std::distance(logiter
, logSpan
.end())) < tocopy
)
489 logiter
= std::copy(entry
.mMessage
.cbegin(), entry
.mMessage
.cend(), logiter
);
493 if(al::to_address(sourceiter
) != nullptr)
494 *(sourceiter
++) = GetDebugSourceEnum(entry
.mSource
);
495 if(al::to_address(typeiter
) != nullptr)
496 *(typeiter
++) = GetDebugTypeEnum(entry
.mType
);
497 if(al::to_address(iditer
) != nullptr)
498 *(iditer
++) = entry
.mId
;
499 if(al::to_address(severityiter
) != nullptr)
500 *(severityiter
++) = GetDebugSeverityEnum(entry
.mSeverity
);
501 if(al::to_address(lengthiter
) != nullptr)
502 *(lengthiter
++) = static_cast<ALsizei
>(tocopy
);
504 context
->mDebugLog
.pop_front();
509 catch(al::context_error
& e
) {
510 context
->setError(e
.errorCode(), "%s", e
.what());
514 FORCE_ALIGN
DECL_FUNCEXT4(void, alObjectLabel
,EXT
, ALenum
,identifier
, ALuint
,name
, ALsizei
,length
, const ALchar
*,label
)
515 FORCE_ALIGN
void AL_APIENTRY
alObjectLabelDirectEXT(ALCcontext
*context
, ALenum identifier
,
516 ALuint name
, ALsizei length
, const ALchar
*label
) noexcept
518 if(!label
&& length
!= 0)
519 throw al::context_error
{AL_INVALID_VALUE
, "Null label pointer"};
521 auto objname
= (length
< 0) ? std::string_view
{label
}
522 : std::string_view
{label
, static_cast<uint
>(length
)};
523 if(objname
.size() >= MaxObjectLabelLength
)
524 throw al::context_error
{AL_INVALID_VALUE
, "Object label length too long (%zu >= %d)",
525 objname
.size(), MaxObjectLabelLength
};
529 case AL_SOURCE_EXT
: ALsource::SetName(context
, name
, objname
); return;
530 case AL_BUFFER
: ALbuffer::SetName(context
, name
, objname
); return;
531 case AL_FILTER_EXT
: ALfilter::SetName(context
, name
, objname
); return;
532 case AL_EFFECT_EXT
: ALeffect::SetName(context
, name
, objname
); return;
533 case AL_AUXILIARY_EFFECT_SLOT_EXT
: ALeffectslot::SetName(context
, name
, objname
); return;
536 throw al::context_error
{AL_INVALID_ENUM
, "Invalid name identifier 0x%04x", identifier
};
538 catch(al::context_error
& e
) {
539 context
->setError(e
.errorCode(), "%s", e
.what());
542 FORCE_ALIGN
DECL_FUNCEXT5(void, alGetObjectLabel
,EXT
, ALenum
,identifier
, ALuint
,name
, ALsizei
,bufSize
, ALsizei
*,length
, ALchar
*,label
)
543 FORCE_ALIGN
void AL_APIENTRY
alGetObjectLabelDirectEXT(ALCcontext
*context
, ALenum identifier
,
544 ALuint name
, ALsizei bufSize
, ALsizei
*length
, ALchar
*label
) noexcept
547 throw al::context_error
{AL_INVALID_VALUE
, "Negative label bufSize"};
549 if(!label
&& !length
)
550 throw al::context_error
{AL_INVALID_VALUE
, "Null length and label"};
551 if(label
&& bufSize
== 0)
552 throw al::context_error
{AL_INVALID_VALUE
, "Zero label bufSize"};
554 const auto labelOut
= al::span
{label
, label
? static_cast<ALuint
>(bufSize
) : 0u};
555 auto copy_name
= [name
,length
,labelOut
](std::unordered_map
<ALuint
,std::string
> &names
)
557 std::string_view objname
;
559 auto iter
= names
.find(name
);
560 if(iter
!= names
.end())
561 objname
= iter
->second
;
564 *length
= static_cast<ALsizei
>(objname
.size());
567 const size_t tocopy
{std::min(objname
.size(), labelOut
.size()-1)};
568 auto oiter
= std::copy_n(objname
.cbegin(), tocopy
, labelOut
.begin());
571 *length
= static_cast<ALsizei
>(tocopy
);
575 if(identifier
== AL_SOURCE_EXT
)
577 std::lock_guard srclock
{context
->mSourceLock
};
578 copy_name(context
->mSourceNames
);
580 else if(identifier
== AL_BUFFER
)
582 auto *device
= context
->mALDevice
.get();
583 auto buflock
= std::lock_guard
{device
->BufferLock
};
584 copy_name(device
->mBufferNames
);
586 else if(identifier
== AL_FILTER_EXT
)
588 auto *device
= context
->mALDevice
.get();
589 auto buflock
= std::lock_guard
{device
->FilterLock
};
590 copy_name(device
->mFilterNames
);
592 else if(identifier
== AL_EFFECT_EXT
)
594 auto *device
= context
->mALDevice
.get();
595 auto buflock
= std::lock_guard
{device
->EffectLock
};
596 copy_name(device
->mEffectNames
);
598 else if(identifier
== AL_AUXILIARY_EFFECT_SLOT_EXT
)
600 std::lock_guard slotlock
{context
->mEffectSlotLock
};
601 copy_name(context
->mEffectSlotNames
);
604 throw al::context_error
{AL_INVALID_ENUM
, "Invalid name identifier 0x%04x", identifier
};
606 catch(al::context_error
& e
) {
607 context
->setError(e
.errorCode(), "%s", e
.what());