14 #include <string_view>
15 #include <unordered_map>
22 #include "alc/context.h"
23 #include "alc/device.h"
24 #include "alc/inprogext.h"
25 #include "alnumeric.h"
28 #include "auxeffectslot.h"
30 #include "core/logging.h"
31 #include "core/voice.h"
32 #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 std::optional
<DebugSource
> GetDebugSource(ALenum source
) noexcept
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 std::optional
<DebugType
> GetDebugType(ALenum type
) noexcept
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 std::optional
<DebugSeverity
> GetDebugSeverity(ALenum severity
) noexcept
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 ALenum
GetDebugSourceEnum(DebugSource source
)
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 ALenum
GetDebugTypeEnum(DebugType type
)
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 ALenum
GetDebugSeverityEnum(DebugSeverity severity
)
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 const char *GetDebugSourceName(DebugSource source
)
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 const char *GetDebugTypeName(DebugType type
)
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 const char *GetDebugSeverityName(DebugSeverity severity
)
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
))
261 if(!message
) UNLIKELY
262 return context
->setError(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
.length() >= MaxDebugMessageLength
) UNLIKELY
267 return context
->setError(AL_INVALID_VALUE
, "Debug message too long (%zu >= %d)",
268 msgview
.length(), MaxDebugMessageLength
);
270 auto dsource
= GetDebugSource(source
);
272 return context
->setError(AL_INVALID_ENUM
, "Invalid debug source 0x%04x", source
);
273 if(*dsource
!= DebugSource::ThirdParty
&& *dsource
!= DebugSource::Application
)
274 return context
->setError(AL_INVALID_ENUM
, "Debug source 0x%04x not allowed", source
);
276 auto dtype
= GetDebugType(type
);
278 return context
->setError(AL_INVALID_ENUM
, "Invalid debug type 0x%04x", type
);
280 auto dseverity
= GetDebugSeverity(severity
);
282 return context
->setError(AL_INVALID_ENUM
, "Invalid debug severity 0x%04x", severity
);
284 context
->debugMessage(*dsource
, *dtype
, id
, *dseverity
, msgview
);
288 FORCE_ALIGN
DECL_FUNCEXT6(void, alDebugMessageControl
,EXT
, ALenum
,source
, ALenum
,type
, ALenum
,severity
, ALsizei
,count
, const ALuint
*,ids
, ALboolean
,enable
)
289 FORCE_ALIGN
void AL_APIENTRY
alDebugMessageControlDirectEXT(ALCcontext
*context
, ALenum source
,
290 ALenum type
, ALenum severity
, ALsizei count
, const ALuint
*ids
, ALboolean enable
) noexcept
295 return context
->setError(AL_INVALID_VALUE
, "IDs is null with non-0 count");
296 if(source
== AL_DONT_CARE_EXT
)
297 return context
->setError(AL_INVALID_OPERATION
,
298 "Debug source cannot be AL_DONT_CARE_EXT with IDs");
299 if(type
== AL_DONT_CARE_EXT
)
300 return context
->setError(AL_INVALID_OPERATION
,
301 "Debug type cannot be AL_DONT_CARE_EXT with IDs");
302 if(severity
!= AL_DONT_CARE_EXT
)
303 return context
->setError(AL_INVALID_OPERATION
,
304 "Debug severity must be AL_DONT_CARE_EXT with IDs");
307 if(enable
!= AL_TRUE
&& enable
!= AL_FALSE
)
308 return context
->setError(AL_INVALID_ENUM
, "Invalid debug enable %d", enable
);
310 static constexpr size_t ElemCount
{DebugSourceCount
+ DebugTypeCount
+ DebugSeverityCount
};
311 static constexpr auto Values
= make_array_sequence
<uint8_t,ElemCount
>();
313 auto srcIndices
= al::span
{Values
}.subspan(DebugSourceBase
,DebugSourceCount
);
314 if(source
!= AL_DONT_CARE_EXT
)
316 auto dsource
= GetDebugSource(source
);
318 return context
->setError(AL_INVALID_ENUM
, "Invalid debug source 0x%04x", source
);
319 srcIndices
= srcIndices
.subspan(al::to_underlying(*dsource
), 1);
322 auto typeIndices
= al::span
{Values
}.subspan(DebugTypeBase
,DebugTypeCount
);
323 if(type
!= AL_DONT_CARE_EXT
)
325 auto dtype
= GetDebugType(type
);
327 return context
->setError(AL_INVALID_ENUM
, "Invalid debug type 0x%04x", type
);
328 typeIndices
= typeIndices
.subspan(al::to_underlying(*dtype
), 1);
331 auto svrIndices
= al::span
{Values
}.subspan(DebugSeverityBase
,DebugSeverityCount
);
332 if(severity
!= AL_DONT_CARE_EXT
)
334 auto dseverity
= GetDebugSeverity(severity
);
336 return context
->setError(AL_INVALID_ENUM
, "Invalid debug severity 0x%04x", severity
);
337 svrIndices
= svrIndices
.subspan(al::to_underlying(*dseverity
), 1);
340 std::lock_guard
<std::mutex
> debuglock
{context
->mDebugCbLock
};
341 DebugGroup
&debug
= context
->mDebugGroups
.back();
344 const uint filterbase
{(1u<<srcIndices
[0]) | (1u<<typeIndices
[0])};
346 for(const uint id
: al::span
{ids
, static_cast<uint
>(count
)})
348 const uint64_t filter
{filterbase
| (uint64_t{id
} << 32)};
350 auto iter
= std::lower_bound(debug
.mIdFilters
.cbegin(), debug
.mIdFilters
.cend(),
352 if(!enable
&& (iter
== debug
.mIdFilters
.cend() || *iter
!= filter
))
353 debug
.mIdFilters
.insert(iter
, filter
);
354 else if(enable
&& iter
!= debug
.mIdFilters
.cend() && *iter
== filter
)
355 debug
.mIdFilters
.erase(iter
);
360 auto apply_filter
= [enable
,&debug
](const uint filter
)
362 auto iter
= std::lower_bound(debug
.mFilters
.cbegin(), debug
.mFilters
.cend(), filter
);
363 if(!enable
&& (iter
== debug
.mFilters
.cend() || *iter
!= filter
))
364 debug
.mFilters
.insert(iter
, filter
);
365 else if(enable
&& iter
!= debug
.mFilters
.cend() && *iter
== filter
)
366 debug
.mFilters
.erase(iter
);
368 auto apply_severity
= [apply_filter
,svrIndices
](const uint filter
)
370 std::for_each(svrIndices
.cbegin(), svrIndices
.cend(),
371 [apply_filter
,filter
](const uint idx
){ apply_filter(filter
| (1<<idx
)); });
373 auto apply_type
= [apply_severity
,typeIndices
](const uint filter
)
375 std::for_each(typeIndices
.cbegin(), typeIndices
.cend(),
376 [apply_severity
,filter
](const uint idx
){ apply_severity(filter
| (1<<idx
)); });
378 std::for_each(srcIndices
.cbegin(), srcIndices
.cend(),
379 [apply_type
](const uint idx
){ apply_type(1<<idx
); });
384 FORCE_ALIGN
DECL_FUNCEXT4(void, alPushDebugGroup
,EXT
, ALenum
,source
, ALuint
,id
, ALsizei
,length
, const ALchar
*,message
)
385 FORCE_ALIGN
void AL_APIENTRY
alPushDebugGroupDirectEXT(ALCcontext
*context
, ALenum source
,
386 ALuint id
, ALsizei length
, const ALchar
*message
) noexcept
390 size_t newlen
{std::strlen(message
)};
391 if(newlen
>= MaxDebugMessageLength
) UNLIKELY
392 return context
->setError(AL_INVALID_VALUE
, "Debug message too long (%zu >= %d)",
393 newlen
, MaxDebugMessageLength
);
394 length
= static_cast<ALsizei
>(newlen
);
396 else if(length
>= MaxDebugMessageLength
) UNLIKELY
397 return context
->setError(AL_INVALID_VALUE
, "Debug message too long (%d >= %d)", length
,
398 MaxDebugMessageLength
);
400 auto dsource
= GetDebugSource(source
);
402 return context
->setError(AL_INVALID_ENUM
, "Invalid debug source 0x%04x", source
);
403 if(*dsource
!= DebugSource::ThirdParty
&& *dsource
!= DebugSource::Application
)
404 return context
->setError(AL_INVALID_ENUM
, "Debug source 0x%04x not allowed", source
);
406 std::unique_lock
<std::mutex
> debuglock
{context
->mDebugCbLock
};
407 if(context
->mDebugGroups
.size() >= MaxDebugGroupDepth
)
410 return context
->setError(AL_STACK_OVERFLOW_EXT
, "Pushing too many debug groups");
413 context
->mDebugGroups
.emplace_back(*dsource
, id
,
414 std::string_view
{message
, static_cast<uint
>(length
)});
415 auto &oldback
= *(context
->mDebugGroups
.end()-2);
416 auto &newback
= context
->mDebugGroups
.back();
418 newback
.mFilters
= oldback
.mFilters
;
419 newback
.mIdFilters
= oldback
.mIdFilters
;
421 if(context
->mContextFlags
.test(ContextFlags::DebugBit
))
422 context
->sendDebugMessage(debuglock
, newback
.mSource
, DebugType::PushGroup
, newback
.mId
,
423 DebugSeverity::Notification
, newback
.mMessage
);
426 FORCE_ALIGN
DECL_FUNCEXT(void, alPopDebugGroup
,EXT
)
427 FORCE_ALIGN
void AL_APIENTRY
alPopDebugGroupDirectEXT(ALCcontext
*context
) noexcept
429 std::unique_lock
<std::mutex
> debuglock
{context
->mDebugCbLock
};
430 if(context
->mDebugGroups
.size() <= 1)
433 return context
->setError(AL_STACK_UNDERFLOW_EXT
,
434 "Attempting to pop the default debug group");
437 DebugGroup
&debug
= context
->mDebugGroups
.back();
438 const auto source
= debug
.mSource
;
439 const auto id
= debug
.mId
;
440 std::string message
{std::move(debug
.mMessage
)};
442 context
->mDebugGroups
.pop_back();
443 if(context
->mContextFlags
.test(ContextFlags::DebugBit
))
444 context
->sendDebugMessage(debuglock
, source
, DebugType::PopGroup
, id
,
445 DebugSeverity::Notification
, message
);
449 FORCE_ALIGN
DECL_FUNCEXT8(ALuint
, alGetDebugMessageLog
,EXT
, ALuint
,count
, ALsizei
,logBufSize
, ALenum
*,sources
, ALenum
*,types
, ALuint
*,ids
, ALenum
*,severities
, ALsizei
*,lengths
, ALchar
*,logBuf
)
450 FORCE_ALIGN ALuint AL_APIENTRY
alGetDebugMessageLogDirectEXT(ALCcontext
*context
, ALuint count
,
451 ALsizei logBufSize
, ALenum
*sources
, ALenum
*types
, ALuint
*ids
, ALenum
*severities
,
452 ALsizei
*lengths
, ALchar
*logBuf
) noexcept
456 context
->setError(AL_INVALID_VALUE
, "Negative debug log buffer size");
459 auto sourcesOut
= al::span
{sources
, sources
? count
: 0u};
460 auto typesOut
= al::span
{types
, types
? count
: 0u};
461 auto idsOut
= al::span
{ids
, ids
? count
: 0u};
462 auto severitiesOut
= al::span
{severities
, severities
? count
: 0u};
463 auto lengthsOut
= al::span
{lengths
, lengths
? count
: 0u};
464 auto logOut
= al::span
{logBuf
, logBuf
? static_cast<ALuint
>(logBufSize
) : 0u};
466 std::lock_guard
<std::mutex
> debuglock
{context
->mDebugCbLock
};
467 for(ALuint i
{0};i
< count
;++i
)
469 if(context
->mDebugLog
.empty())
472 auto &entry
= context
->mDebugLog
.front();
473 const size_t tocopy
{entry
.mMessage
.size() + 1};
474 if(logOut
.data() != nullptr)
476 if(logOut
.size() < tocopy
)
478 std::copy(entry
.mMessage
.cbegin(), entry
.mMessage
.cend(), logOut
.begin());
479 logOut
[entry
.mMessage
.size()] = '\0';
480 logOut
= logOut
.subspan(tocopy
);
483 if(!sourcesOut
.empty())
485 sourcesOut
.front() = GetDebugSourceEnum(entry
.mSource
);
486 sourcesOut
= sourcesOut
.subspan
<1>();
488 if(!typesOut
.empty())
490 typesOut
.front() = GetDebugTypeEnum(entry
.mType
);
491 typesOut
= typesOut
.subspan
<1>();
495 idsOut
.front() = entry
.mId
;
496 idsOut
= idsOut
.subspan
<1>();
498 if(!severitiesOut
.empty())
500 severitiesOut
.front() = GetDebugSeverityEnum(entry
.mSeverity
);
501 severitiesOut
= severitiesOut
.subspan
<1>();
503 if(!lengthsOut
.empty())
505 lengthsOut
.front() = static_cast<ALsizei
>(tocopy
);
506 lengthsOut
= lengthsOut
.subspan
<1>();
509 context
->mDebugLog
.pop_front();
515 FORCE_ALIGN
DECL_FUNCEXT4(void, alObjectLabel
,EXT
, ALenum
,identifier
, ALuint
,name
, ALsizei
,length
, const ALchar
*,label
)
516 FORCE_ALIGN
void AL_APIENTRY
alObjectLabelDirectEXT(ALCcontext
*context
, ALenum identifier
,
517 ALuint name
, ALsizei length
, const ALchar
*label
) noexcept
519 if(!label
&& length
!= 0) UNLIKELY
520 return context
->setError(AL_INVALID_VALUE
, "Null label pointer");
522 auto objname
= (length
< 0) ? std::string_view
{label
}
523 : std::string_view
{label
, static_cast<uint
>(length
)};
524 if(objname
.length() >= MaxObjectLabelLength
) UNLIKELY
525 return context
->setError(AL_INVALID_VALUE
, "Object label length too long (%zu >= %d)",
526 objname
.length(), MaxObjectLabelLength
);
528 if(identifier
== AL_SOURCE_EXT
)
529 return ALsource::SetName(context
, name
, objname
);
530 if(identifier
== AL_BUFFER
)
531 return ALbuffer::SetName(context
, name
, objname
);
532 if(identifier
== AL_FILTER_EXT
)
533 return ALfilter::SetName(context
, name
, objname
);
534 if(identifier
== AL_EFFECT_EXT
)
535 return ALeffect::SetName(context
, name
, objname
);
536 if(identifier
== AL_AUXILIARY_EFFECT_SLOT_EXT
)
537 return ALeffectslot::SetName(context
, name
, objname
);
539 return context
->setError(AL_INVALID_ENUM
, "Invalid name identifier 0x%04x", identifier
);
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
546 if(bufSize
< 0) UNLIKELY
547 return context
->setError(AL_INVALID_VALUE
, "Negative label bufSize");
549 if(!label
&& !length
) UNLIKELY
550 return context
->setError(AL_INVALID_VALUE
, "Null length and label");
551 if(label
&& bufSize
== 0) UNLIKELY
552 return context
->setError(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
.length());
567 const size_t tocopy
{std::min(objname
.size(), labelOut
.size()-1_uz
)};
568 std::copy_n(objname
.cbegin(), tocopy
, labelOut
.begin());
569 labelOut
[tocopy
] = '\0';
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 ALCdevice
*device
{context
->mALDevice
.get()};
583 std::lock_guard buflock
{device
->BufferLock
};
584 copy_name(device
->mBufferNames
);
586 else if(identifier
== AL_FILTER_EXT
)
588 ALCdevice
*device
{context
->mALDevice
.get()};
589 std::lock_guard filterlock
{device
->FilterLock
};
590 copy_name(device
->mFilterNames
);
592 else if(identifier
== AL_EFFECT_EXT
)
594 ALCdevice
*device
{context
->mALDevice
.get()};
595 std::lock_guard effectlock
{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 context
->setError(AL_INVALID_ENUM
, "Invalid name identifier 0x%04x", identifier
);