Update thirdparty libs

This commit is contained in:
halx99 2023-02-04 15:03:54 +08:00
parent 09b32e26d5
commit c44c84a1ca
281 changed files with 10186 additions and 8458 deletions

20
thirdparty/README.md vendored
View File

@ -6,7 +6,7 @@
## astc
- [![Upstream](https://img.shields.io/github/v/release/ARM-software/astc-encoder?label=Upstream)](https://github.com/ARM-software/astc-encoder)
- Version: 4.3.0
- Version: 4.3.1
- License: Apache-2.0
## Box2D
@ -21,13 +21,13 @@
## Bullet
- [![Upstream](https://img.shields.io/github/v/release/bulletphysics/bullet3?label=Upstream)](https://github.com/bulletphysics/bullet3)
- Version: 3.24
- Version: 3.25
- License: zlib
- Update method: Compare `axmol/thirdparty/bullet` with `bullet3/src`
## c-ares
- [![Upstream](https://img.shields.io/github/v/release/c-ares/c-ares?label=Upstream)](https://github.com/c-ares/c-ares)
- Version: git 1.18.1-c25d4eb (2138)
- Version: git 1.19.0-bb8f5bb (2184)
- License: MIT
## Chipmunk2D
@ -161,7 +161,7 @@
## OpenAL Soft
- [![Upstream](https://img.shields.io/github/v/tag/kcat/openal-soft?label=Upstream)](https://github.com/kcat/openal-soft)
- Version: 1.22.2
- Version: 1.23.0
- License: LGPL-2.1
## OpenSSL
@ -180,8 +180,10 @@
- License: BSD-3-Clause
## pugixml
- [![Upstream](https://img.shields.io/github/v/tag/zeux/pugixml?label=Upstream)](https://github.com/zeux/pugixml)
- Version: 1.12.1
- [![Upstream](https://img.shields.io/github/v/tag/halx99/pugixml?label=Upstream)](https://github.com/halx99/pugixml) by halx99 for string_view support
- original repo: https://github.com/zeux/pugixml
- all tests passed: https://github.com/halx99/pugixml/actions/runs/4090401630
- Version: 1.13
- License: MIT
## rapidjson
@ -203,7 +205,7 @@
## stb (stb_image)
- Upstream: https://github.com/nothings/stb
- Version: 2.27
- Version: 2.28
- License: MIT
## unzip (minizip-1.2)
@ -218,7 +220,7 @@
## webp
- [![Upstream](https://img.shields.io/github/v/tag/webmproject/libwebp?label=Upstream)](https://github.com/webmproject/libwebp)
- Version: 1.2.4
- Version: 1.3.0
- License: Google Inc
## xsbase
@ -248,7 +250,7 @@
## ntcvt
- [![Upstream](https://img.shields.io/github/v/tag/simdsoft/ntcvt?label=Upstream)](https://github.com/simdsoft/ntcvt)
- Version: git-8422188 (7)
- Version: 0.0.2
- License: Apache-2.0
## Some third party libs supporting axmol too:

View File

@ -48,8 +48,6 @@
#define ASTCENC_SSE 42
#elif defined(__SSE4_1__)
#define ASTCENC_SSE 41
#elif defined(__SSE3__)
#define ASTCENC_SSE 30
#elif defined(__SSE2__)
#define ASTCENC_SSE 20
#else

View File

@ -1046,7 +1046,7 @@ ASTCENC_SIMD_INLINE void vtable_prepare(vint4 t0, vint4& t0p)
*/
ASTCENC_SIMD_INLINE void vtable_prepare(vint4 t0, vint4 t1, vint4& t0p, vint4& t1p)
{
#if ASTCENC_SSE >= 30
#if ASTCENC_SSE >= 41
t0p = t0;
t1p = t0 ^ t1;
#else
@ -1062,7 +1062,7 @@ ASTCENC_SIMD_INLINE void vtable_prepare(
vint4 t0, vint4 t1, vint4 t2, vint4 t3,
vint4& t0p, vint4& t1p, vint4& t2p, vint4& t3p)
{
#if ASTCENC_SSE >= 30
#if ASTCENC_SSE >= 41
t0p = t0;
t1p = t0 ^ t1;
t2p = t1 ^ t2;
@ -1080,7 +1080,7 @@ ASTCENC_SIMD_INLINE void vtable_prepare(
*/
ASTCENC_SIMD_INLINE vint4 vtable_8bt_32bi(vint4 t0, vint4 idx)
{
#if ASTCENC_SSE >= 30
#if ASTCENC_SSE >= 41
// Set index byte MSB to 1 for unused bytes so shuffle returns zero
__m128i idxx = _mm_or_si128(idx.m, _mm_set1_epi32(static_cast<int>(0xFFFFFF00)));
@ -1102,7 +1102,7 @@ ASTCENC_SIMD_INLINE vint4 vtable_8bt_32bi(vint4 t0, vint4 idx)
*/
ASTCENC_SIMD_INLINE vint4 vtable_8bt_32bi(vint4 t0, vint4 t1, vint4 idx)
{
#if ASTCENC_SSE >= 30
#if ASTCENC_SSE >= 41
// Set index byte MSB to 1 for unused bytes so shuffle returns zero
__m128i idxx = _mm_or_si128(idx.m, _mm_set1_epi32(static_cast<int>(0xFFFFFF00)));
@ -1130,7 +1130,7 @@ ASTCENC_SIMD_INLINE vint4 vtable_8bt_32bi(vint4 t0, vint4 t1, vint4 idx)
*/
ASTCENC_SIMD_INLINE vint4 vtable_8bt_32bi(vint4 t0, vint4 t1, vint4 t2, vint4 t3, vint4 idx)
{
#if ASTCENC_SSE >= 30
#if ASTCENC_SSE >= 41
// Set index byte MSB to 1 for unused bytes so shuffle returns zero
__m128i idxx = _mm_or_si128(idx.m, _mm_set1_epi32(static_cast<int>(0xFFFFFF00)));

View File

@ -103,7 +103,8 @@ void btConvexTriangleCallback::processTriangle(btVector3* triangle, int partId,
if (m_convexBodyWrap->getCollisionShape()->isConvex())
{
#ifndef BT_DISABLE_CONVEX_CONCAVE_EARLY_OUT
#ifdef BT_ENABLE_CONVEX_CONCAVE_EARLY_OUT
//todo: check this issue https://github.com/bulletphysics/bullet3/issues/4263
//an early out optimisation if the object is separated from the triangle
//projected on the triangle normal)
{
@ -139,7 +140,7 @@ void btConvexTriangleCallback::processTriangle(btVector3* triangle, int partId,
if (dist > contact_threshold)
return;
}
#endif //BT_DISABLE_CONVEX_CONCAVE_EARLY_OUT
#endif //BT_ENABLE_CONVEX_CONCAVE_EARLY_OUT
btTriangleShape tm(triangle[0], triangle[1], triangle[2]);
tm.setMargin(m_collisionMarginTriangle);

View File

@ -229,10 +229,12 @@ public:
m_min[0] = BT_MIN3(V1[0], V2[0], V3[0]);
m_min[1] = BT_MIN3(V1[1], V2[1], V3[1]);
m_min[2] = BT_MIN3(V1[2], V2[2], V3[2]);
m_min[3] = 0.f;
m_max[0] = BT_MAX3(V1[0], V2[0], V3[0]);
m_max[1] = BT_MAX3(V1[1], V2[1], V3[1]);
m_max[2] = BT_MAX3(V1[2], V2[2], V3[2]);
m_max[3] = 0.f;
}
btAABB(const btVector3 &V1,
@ -243,10 +245,12 @@ public:
m_min[0] = BT_MIN3(V1[0], V2[0], V3[0]);
m_min[1] = BT_MIN3(V1[1], V2[1], V3[1]);
m_min[2] = BT_MIN3(V1[2], V2[2], V3[2]);
m_min[3] = 0.f;
m_max[0] = BT_MAX3(V1[0], V2[0], V3[0]);
m_max[1] = BT_MAX3(V1[1], V2[1], V3[1]);
m_max[2] = BT_MAX3(V1[2], V2[2], V3[2]);
m_max[3] = 0.f;
m_min[0] -= margin;
m_min[1] -= margin;
@ -275,9 +279,11 @@ public:
m_min[0] = SIMD_INFINITY;
m_min[1] = SIMD_INFINITY;
m_min[2] = SIMD_INFINITY;
m_min[3] = 0.f;
m_max[0] = -SIMD_INFINITY;
m_max[1] = -SIMD_INFINITY;
m_max[2] = -SIMD_INFINITY;
m_max[3] = 0.f;
}
SIMD_FORCE_INLINE void increment_margin(btScalar margin)
@ -295,10 +301,12 @@ public:
m_min[0] = other.m_min[0] - margin;
m_min[1] = other.m_min[1] - margin;
m_min[2] = other.m_min[2] - margin;
m_min[3] = 0.f;
m_max[0] = other.m_max[0] + margin;
m_max[1] = other.m_max[1] + margin;
m_max[2] = other.m_max[2] + margin;
m_max[3] = 0.f;
}
template <typename CLASS_POINT>
@ -310,10 +318,12 @@ public:
m_min[0] = BT_MIN3(V1[0], V2[0], V3[0]);
m_min[1] = BT_MIN3(V1[1], V2[1], V3[1]);
m_min[2] = BT_MIN3(V1[2], V2[2], V3[2]);
m_min[3] = 0.f;
m_max[0] = BT_MAX3(V1[0], V2[0], V3[0]);
m_max[1] = BT_MAX3(V1[1], V2[1], V3[1]);
m_max[2] = BT_MAX3(V1[2], V2[2], V3[2]);
m_max[3] = 0.f;
}
template <typename CLASS_POINT>
@ -325,10 +335,12 @@ public:
m_min[0] = BT_MIN3(V1[0], V2[0], V3[0]);
m_min[1] = BT_MIN3(V1[1], V2[1], V3[1]);
m_min[2] = BT_MIN3(V1[2], V2[2], V3[2]);
m_min[3] = 0.f;
m_max[0] = BT_MAX3(V1[0], V2[0], V3[0]);
m_max[1] = BT_MAX3(V1[1], V2[1], V3[1]);
m_max[2] = BT_MAX3(V1[2], V2[2], V3[2]);
m_max[3] = 0.f;
m_min[0] -= margin;
m_min[1] -= margin;

View File

@ -19,8 +19,10 @@ subject to the following restrictions:
#include "btPointCollector.h"
#include "LinearMath/btTransformUtil.h"
#ifdef MAX_ITERATIONS
#ifdef BT_USE_DOUBLE_PRECISION
#define MAX_ITERATIONS 64
#else
#define MAX_ITERATIONS 32
#endif
btGjkConvexCast::btGjkConvexCast(const btConvexShape* convexA, const btConvexShape* convexB, btSimplexSolverInterface* simplexSolver)

View File

@ -169,9 +169,12 @@ btVectorXu btLemkeAlgorithm::solve(unsigned int maxloops /* = 0*/)
/*the column becomes part of the basis*/
basis[pivotRowIndex] = pivotColIndexOld;
pivotRowIndex = findLexicographicMinimum(A, pivotColIndex);
bool isRayTermination = false;
pivotRowIndex = findLexicographicMinimum(A, pivotColIndex, z0Row, isRayTermination);
if (isRayTermination)
{
break; // ray termination
}
if (z0Row == pivotRowIndex)
{ //if z0 leaves the basis the solution is found --> one last elimination step is necessary
GaussJordanEliminationStep(A, pivotRowIndex, pivotColIndex, basis);
@ -217,79 +220,100 @@ btVectorXu btLemkeAlgorithm::solve(unsigned int maxloops /* = 0*/)
return solutionVector;
}
int btLemkeAlgorithm::findLexicographicMinimum(const btMatrixXu& A, const int& pivotColIndex)
int btLemkeAlgorithm::findLexicographicMinimum(const btMatrixXu& A, const int& pivotColIndex, const int& z0Row, bool& isRayTermination)
{
int RowIndex = 0;
isRayTermination = false;
btAlignedObjectArray<int> activeRows;
bool firstRow = true;
btScalar currentMin = 0.0;
int dim = A.rows();
btAlignedObjectArray<btVectorXu> Rows;
for (int row = 0; row < dim; row++)
{
btVectorXu vec(dim + 1);
vec.setZero(); //, INIT, 0.)
Rows.push_back(vec);
btScalar a = A(row, pivotColIndex);
if (a > 0)
{
Rows[row][0] = A(row, 2 * dim + 1) / a;
Rows[row][1] = A(row, 2 * dim) / a;
for (int j = 2; j < dim + 1; j++)
Rows[row][j] = A(row, j - 1) / a;
const btScalar denom = A(row, pivotColIndex);
#ifdef BT_DEBUG_OSTREAM
// if (DEBUGLEVEL) {
// cout << "Rows(" << row << ") = " << Rows[row] << endl;
// }
#endif
if (denom > btMachEps())
{
const btScalar q = A(row, dim + dim + 1) / denom;
if (firstRow)
{
currentMin = q;
activeRows.push_back(row);
firstRow = false;
}
else if (fabs(currentMin - q) < btMachEps())
{
activeRows.push_back(row);
}
for (int i = 0; i < Rows.size(); i++)
else if (currentMin > q)
{
if (Rows[i].nrm2() > 0.)
{
int j = 0;
for (; j < Rows.size(); j++)
{
if (i != j)
{
if (Rows[j].nrm2() > 0.)
{
btVectorXu test(dim + 1);
for (int ii = 0; ii < dim + 1; ii++)
{
test[ii] = Rows[j][ii] - Rows[i][ii];
}
//=Rows[j] - Rows[i]
if (!LexicographicPositive(test))
break;
currentMin = q;
activeRows.clear();
activeRows.push_back(row);
}
}
}
if (j == Rows.size())
if (activeRows.size() == 0)
{
RowIndex += i;
break;
}
isRayTermination = true;
return 0;
}
else if (activeRows.size() == 1)
{
return activeRows[0];
}
return RowIndex;
}
// if there are multiple rows, check if they contain the row for z_0.
for (int i = 0; i < activeRows.size(); i++)
{
if (activeRows[i] == z0Row)
{
return z0Row;
}
}
bool btLemkeAlgorithm::LexicographicPositive(const btVectorXu& v)
{
int i = 0;
// if (DEBUGLEVEL)
// cout << "v " << v << endl;
// look through the columns of the inverse of the basic matrix from left to right until the tie is broken.
for (int col = 0; col < dim ; col++)
{
btAlignedObjectArray<int> activeRowsCopy(activeRows);
activeRows.clear();
firstRow = true;
for (int i = 0; i<activeRowsCopy.size();i++)
{
const int row = activeRowsCopy[i];
while (i < v.size() - 1 && fabs(v[i]) < btMachEps())
i++;
if (v[i] > 0)
return true;
// denom is positive here as an invariant.
const btScalar denom = A(row, pivotColIndex);
const btScalar ratio = A(row, col) / denom;
if (firstRow)
{
currentMin = ratio;
activeRows.push_back(row);
firstRow = false;
}
else if (fabs(currentMin - ratio) < btMachEps())
{
activeRows.push_back(row);
}
else if (currentMin > ratio)
{
currentMin = ratio;
activeRows.clear();
activeRows.push_back(row);
}
}
return false;
if (activeRows.size() == 1)
{
return activeRows[0];
}
}
// must not reach here.
isRayTermination = true;
return 0;
}
void btLemkeAlgorithm::GaussJordanEliminationStep(btMatrixXu& A, int pivotRowIndex, int pivotColumnIndex, const btAlignedObjectArray<int>& basis)

View File

@ -71,8 +71,7 @@ public:
}
protected:
int findLexicographicMinimum(const btMatrixXu& A, const int& pivotColIndex);
bool LexicographicPositive(const btVectorXu& v);
int findLexicographicMinimum(const btMatrixXu& A, const int& pivotColIndex, const int& z0Row, bool& isRayTermination);
void GaussJordanEliminationStep(btMatrixXu& A, int pivotRowIndex, int pivotColumnIndex, const btAlignedObjectArray<int>& basis);
bool greaterZero(const btVectorXu& vector);
bool validBasis(const btAlignedObjectArray<int>& basis);

View File

@ -678,7 +678,9 @@ HullError HullLibrary::CreateConvexHull(const HullDesc &desc, // describes the
if (vcount < 8) vcount = 8;
btAlignedObjectArray<btVector3> vertexSource;
vertexSource.resize(static_cast<int>(vcount));
btVector3 zero;
zero.setZero();
vertexSource.resize(static_cast<int>(vcount), zero);
btVector3 scale;

View File

@ -25,7 +25,7 @@ subject to the following restrictions:
#include <float.h>
/* SVN $Revision$ on $Date$ from http://bullet.googlecode.com*/
#define BT_BULLET_VERSION 324
#define BT_BULLET_VERSION 325
inline int btGetVersion()
{

View File

@ -481,7 +481,7 @@ public:
buffer[9] = '3';
buffer[10] = '2';
buffer[11] = '4';
buffer[11] = '5';
}
virtual void startSerialization()
@ -512,7 +512,7 @@ public:
currentPtr += BT_HEADER_LENGTH;
for (int i = 0; i < m_chunkPtrs.size(); i++)
{
int curLength = sizeof(btChunk) + m_chunkPtrs[i]->m_length;
int curLength = (int)sizeof(btChunk) + m_chunkPtrs[i]->m_length;
memcpy(currentPtr, m_chunkPtrs[i], curLength);
btAlignedFree(m_chunkPtrs[i]);
currentPtr += curLength;

View File

@ -8,7 +8,7 @@ INCLUDE (CheckCSourceCompiles)
INCLUDE (CheckStructHasMember)
INCLUDE (CheckLibraryExists)
PROJECT (c-ares LANGUAGES C VERSION "1.18.0" )
PROJECT (c-ares LANGUAGES C VERSION "1.19.0" )
# Set this version before release
SET (CARES_VERSION "${PROJECT_VERSION}")
@ -26,7 +26,7 @@ INCLUDE (GNUInstallDirs) # include this *AFTER* PROJECT(), otherwise paths are w
# For example, a version of 4:0:2 would generate output such as:
# libname.so -> libname.so.2
# libname.so.2 -> libname.so.2.2.0
SET (CARES_LIB_VERSIONINFO "7:1:5")
SET (CARES_LIB_VERSIONINFO "8:0:6")
OPTION (CARES_STATIC "Build as a static library" OFF)
@ -82,9 +82,14 @@ SET (TARGETS_INST_DEST
# Function in Library
# CHECK_LIBRARY_EXISTS can't be used as it will return true if the function
# is found in a different dependent library.
# is found in a different required/dependent library.
MACRO (CARES_FUNCTION_IN_LIBRARY func lib var)
SET (_ORIG_CMAKE_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES}")
SET (CMAKE_REQUIRED_LIBRARIES )
CHECK_FUNCTION_EXISTS ("${func}" "_CARES_FUNC_IN_LIB_GLOBAL_${func}")
SET (CMAKE_REQUIRED_LIBRARIES "${_ORIG_CMAKE_REQUIRED_LIBRARIES}")
IF ("${_CARES_FUNC_IN_LIB_GLOBAL_${func}}")
SET (${var} FALSE)
ELSE ()
@ -689,6 +694,12 @@ IF (CARES_INSTALL)
if( ${CMAKE_SYSTEM_NAME} STREQUAL "Linux" )
if ( "${CPACK_PACKAGE_ARCHITECTURE}" STREQUAL "" )
set( CPACK_PACKAGE_ARCHITECTURE "${CMAKE_SYSTEM_PROCESSOR}" )
endif()
if ( "${CPACK_PACKAGE_ARCHITECTURE}" STREQUAL "" )
if ( "${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Windows" )
message( FATAL_ERROR "Failed to determine CPACK_PACKAGE_ARCHITECTURE. Is CMAKE_SYSTEM_PROCESSOR set?" )
endif()
# Note: the architecture should default to the local architecture, but it
# in fact comes up empty. We call `uname -m` to ask the kernel instead.
EXECUTE_PROCESS( COMMAND uname -m COMMAND tr -d '\n' OUTPUT_VARIABLE CPACK_PACKAGE_ARCHITECTURE )

View File

@ -3,7 +3,7 @@ c-ares
[![Build Status](https://api.cirrus-ci.com/github/c-ares/c-ares.svg)](https://cirrus-ci.com/github/c-ares/c-ares)
[![Windows Build Status](https://ci.appveyor.com/api/projects/status/aevgc5914tm72pvs/branch/master?svg=true)](https://ci.appveyor.com/project/c-ares/c-ares/branch/master)
[![Coverage Status](https://coveralls.io/repos/c-ares/c-ares/badge.svg?branch=master&service=github)](https://coveralls.io/github/c-ares/c-ares?branch=master)
[![Coverage Status](https://coveralls.io/repos/github/c-ares/c-ares/badge.svg)](https://coveralls.io/github/c-ares/c-ares)
[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/291/badge)](https://bestpractices.coreinfrastructure.org/projects/291)
[![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/c-ares.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:c-ares)
[![Releases](https://coderelease.io/badge/c-ares/c-ares)](https://coderelease.io/github/repository/c-ares/c-ares)

View File

@ -17,7 +17,7 @@ This utility comes with the \fBc\-ares\fR asynchronous resolver library.
\fB\-d\fR
Print some extra debugging output.
.TP
\fB\-h\fR, \fB\-\-help\fR
\fB\-h\fR, \fB\-?\fR
Display this help and exit.
.TP
\fB\-v\fR

View File

@ -18,34 +18,40 @@ This utility comes with the \fBc\-ares\fR asynchronous resolver library.
\fB\-c\fR class
Set the query class.
Possible values for class are
NY, CHAOS, HS, IN (default).
ANY, CHAOS, HS and IN (default).
.TP
\fB\-d\fR
Print some extra debugging output.
.TP
\fB\-f\fR flag
Add a flag.
Add a behavior control flag.
Possible values for flag are
igntc, noaliases, norecurse, primary, stayopen, usevc.
igntc - ignore to query in TCP to get truncated UDP answer,
noaliases - don't honor the HOSTALIASES environment variable,
norecurse - don't query upstream servers recursively,
primary - use the first server,
stayopen - don't close the communication sockets, and
usevc - always use TCP.
.TP
\fB\-h\fR, \fB\-\-help\fR
\fB\-h\fR, \fB\-?\fR
Display this help and exit.
.TP
\fB\-T\fR port
Use specified TCP port to connect to DNS server.
.TP
\fB\-s\fR server
Connect to specified DNS server, instead of the system's default one(s).
Servers are tried in round-robin, if the previous one failed.
.TP
\fB\-t\fR type
Query records of specified type.
Possible values for type are
A (default), AAAA, AFSDB, ANY, AXFR, CNAME, GPOS, HINFO, ISDN, KEY, LOC, MAILA,
MAILB, MB, MD, MF, MG, MINFO, MR, MX, NAPTR, NS, NSAP, NSAP_PTR, NULL,
PTR, PX, RP, RT, SIG, SOA, SRV, TXT, URI, WKS, X25,
PTR, PX, RP, RT, SIG, SOA, SRV, TXT, URI, WKS and X25.
.TP
\fB\-T\fR port
Connect to the specified TCP port of DNS server.
.TP
\fB\-U\fR port
Use specified UDP port to connect to DNS server.
Connect to the specified UDP port of DNS server.
.TP
\fB\-x\fR
For an IPv4 \fB-t PTR a.b.c.d\fR lookup, query for

View File

@ -17,7 +17,7 @@ This utility comes with the \fBc\-ares\fR asynchronous resolver library.
\fB\-d\fR
Print some extra debugging output.
.TP
\fB\-h\fR, \fB\-\-help\fR
\fB\-h\fR, \fB\-?\fR
Display this help and exit.
.TP
\fB\-t\fR type

View File

@ -18,9 +18,9 @@
ares_destroy_options \- Destroy options initialized with ares_save_options
.SH SYNOPSIS
.nf
.B #include <ares.h>
.PP
.B void ares_destroy_options(struct ares_options *\fIoptions\fP)
#include <ares.h>
void ares_destroy_options(struct ares_options *\fIoptions\fP)
.fi
.SH DESCRIPTION
The \fBares_destroy_options(3)\fP function destroys the options struct

View File

@ -18,9 +18,9 @@
ares_dup \- Duplicate a resolver channel
.SH SYNOPSIS
.nf
.B #include <ares.h>
.PP
.B int ares_dup(ares_channel *\fIdest\fP, ares_channel \fIsource\fP)
#include <ares.h>
int ares_dup(ares_channel *\fIdest\fP, ares_channel \fIsource\fP)
.fi
.SH DESCRIPTION
The \fBares_dup(3)\fP function duplicates an existing communications channel

View File

@ -18,11 +18,11 @@
ares_expand_name \- Expand a DNS-encoded domain name
.SH SYNOPSIS
.nf
.B #include <ares.h>
.PP
.B int ares_expand_name(const unsigned char *\fIencoded\fP,
.B const unsigned char *\fIabuf\fP, int \fIalen\fP, char **\fIs\fP,
.B long *\fIenclen\fP)
#include <ares.h>
int ares_expand_name(const unsigned char *\fIencoded\fP,
const unsigned char *\fIabuf\fP, int \fIalen\fP,
char **\fIs\fP, long *\fIenclen\fP)
.fi
.SH DESCRIPTION
The

View File

@ -18,11 +18,11 @@
ares_expand_string \- Expand a length encoded string
.SH SYNOPSIS
.nf
.B #include <ares.h>
.PP
.B int ares_expand_string(const unsigned char *\fIencoded\fP,
.B const unsigned char *\fIabuf\fP, int \fIalen\fP, unsigned char **\fIs\fP,
.B long *\fIenclen\fP)
#include <ares.h>
int ares_expand_string(const unsigned char *\fIencoded\fP,
const unsigned char *\fIabuf\fP, int \fIalen\fP,
unsigned char **\fIs\fP, long *\fIenclen\fP)
.fi
.SH DESCRIPTION
The

View File

@ -19,11 +19,9 @@
ares_free_data \- Free data allocated by several c-ares functions
.SH SYNOPSIS
.nf
.B #include <ares.h>
.PP
.B void ares_free_data(void *\fIdataptr\fP)
.PP
.B cc file.c -lcares
#include <ares.h>
void ares_free_data(void *\fIdataptr\fP)
.fi
.SH DESCRIPTION
.PP

View File

@ -18,9 +18,9 @@
ares_free_hostent \- Free host structure allocated by ares functions
.SH SYNOPSIS
.nf
.B #include <ares.h>
.PP
.B void ares_free_hostent(struct hostent *\fIhost\fP)
#include <ares.h>
void ares_free_hostent(struct hostent *\fIhost\fP)
.fi
.SH DESCRIPTION
The

View File

@ -18,9 +18,9 @@
ares_free_string \- Free strings allocated by ares functions
.SH SYNOPSIS
.nf
.B #include <ares.h>
.PP
.B void ares_free_string(void *\fIstr\fP)
#include <ares.h>
void ares_free_string(void *\fIstr\fP)
.fi
.SH DESCRIPTION
The \fIares_free_string(3)\fP function frees a string allocated by an ares

View File

@ -19,10 +19,13 @@
ares_get_servers, ares_get_servers_ports \- Retrieve name servers from an initialized ares_channel
.SH SYNOPSIS
.nf
.B #include <ares.h>
.PP
.B int ares_get_servers(ares_channel \fIchannel\fP, struct ares_addr_node **\fIservers\fP)
.B int ares_get_servers_ports(ares_channel \fIchannel\fP, struct ares_addr_port_node **\fIservers\fP)
#include <ares.h>
int ares_get_servers(ares_channel \fIchannel\fP,
struct ares_addr_node **\fIservers\fP)
int ares_get_servers_ports(ares_channel \fIchannel\fP,
struct ares_addr_port_node **\fIservers\fP)
.fi
.SH DESCRIPTION
The \fBares_get_servers(3)\fP function retrieves name servers configuration

View File

@ -18,14 +18,16 @@
ares_getaddrinfo \- Initiate a host query by name and service
.SH SYNOPSIS
.nf
.B #include <ares.h>
.PP
.B typedef void (*ares_addrinfo_callback)(void *\fIarg\fP, int \fIstatus\fP,
.B int \fItimeouts\fP, struct ares_addrinfo *\fIresult\fP)
.PP
.B void ares_getaddrinfo(ares_channel \fIchannel\fP, const char *\fIname\fP,
.B const char* \fIservice\fP, const struct ares_addrinfo_hints *\fIhints\fP,
.B ares_addrinfo_callback \fIcallback\fP, void *\fIarg\fP)
#include <ares.h>
typedef void (*ares_addrinfo_callback)(void *\fIarg\fP, int \fIstatus\fP,
int \fItimeouts\fP,
struct ares_addrinfo *\fIresult\fP)
void ares_getaddrinfo(ares_channel \fIchannel\fP, const char *\fIname\fP,
const char* \fIservice\fP,
const struct ares_addrinfo_hints *\fIhints\fP,
ares_addrinfo_callback \fIcallback\fP, void *\fIarg\fP)
.fi
.SH DESCRIPTION
The

View File

@ -18,14 +18,15 @@
ares_gethostbyaddr \- Initiate a host query by address
.SH SYNOPSIS
.nf
.B #include <ares.h>
.PP
.B typedef void (*ares_host_callback)(void *\fIarg\fP, int \fIstatus\fP,
.B int \fItimeouts\fP, struct hostent *\fIhostent\fP)
.PP
.B void ares_gethostbyaddr(ares_channel \fIchannel\fP, const void *\fIaddr\fP,
.B int \fIaddrlen\fP, int \fIfamily\fP, ares_host_callback \fIcallback\fP,
.B void *\fIarg\fP)
#include <ares.h>
typedef void (*ares_host_callback)(void *\fIarg\fP, int \fIstatus\fP,
int \fItimeouts\fP,
struct hostent *\fIhostent\fP)
void ares_gethostbyaddr(ares_channel \fIchannel\fP, const void *\fIaddr\fP,
int \fIaddrlen\fP, int \fIfamily\fP,
ares_host_callback \fIcallback\fP, void *\fIarg\fP)
.fi
.SH DESCRIPTION
The

View File

@ -18,13 +18,15 @@
ares_gethostbyname \- Initiate a host query by name
.SH SYNOPSIS
.nf
.B #include <ares.h>
.PP
.B typedef void (*ares_host_callback)(void *\fIarg\fP, int \fIstatus\fP,
.B int \fItimeouts\fP, struct hostent *\fIhostent\fP)
.PP
.B void ares_gethostbyname(ares_channel \fIchannel\fP, const char *\fIname\fP,
.B int \fIfamily\fP, ares_host_callback \fIcallback\fP, void *\fIarg\fP)
#include <ares.h>
typedef void (*ares_host_callback)(void *\fIarg\fP, int \fIstatus\fP,
int \fItimeouts\fP,
struct hostent *\fIhostent\fP)
void ares_gethostbyname(ares_channel \fIchannel\fP, const char *\fIname\fP,
int \fIfamily\fP, ares_host_callback \fIcallback\fP,
void *\fIarg\fP)
.fi
.SH DESCRIPTION
The

View File

@ -18,10 +18,10 @@
ares_gethostbyname_file \- Lookup a name in the system's hosts file
.SH SYNOPSIS
.nf
.B #include <ares.h>
.PP
.B int ares_gethostbyname_file(ares_channel \fIchannel\fP, const char *\fIname\fP,
.B int \fIfamily\fP, struct hostent **host)
#include <ares.h>
int ares_gethostbyname_file(ares_channel \fIchannel\fP, const char *\fIname\fP,
int \fIfamily\fP, struct hostent **host)
.fi
.SH DESCRIPTION
The

View File

@ -18,14 +18,15 @@
ares_getnameinfo \- Address-to-nodename translation in protocol-independent manner
.SH SYNOPSIS
.nf
.B #include <ares.h>
.PP
.B typedef void (*ares_nameinfo_callback)(void *\fIarg\fP, int \fIstatus\fP,
.B int \fItimeouts\fP, char *\fInode\fP, char *\fIservice\fP)
.PP
.B void ares_getnameinfo(ares_channel \fIchannel\fP, const struct sockaddr *\fIsa\fP,
.B ares_socklen_t \fIsalen\fP, int \fIflags\fP, ares_nameinfo_callback \fIcallback\fP,
.B void *\fIarg\fP)
#include <ares.h>
typedef void (*ares_nameinfo_callback)(void *\fIarg\fP, int \fIstatus\fP,
int \fItimeouts\fP, char *\fInode\fP,
char *\fIservice\fP)
void ares_getnameinfo(ares_channel \fIchannel\fP, const struct sockaddr *\fIsa\fP,
ares_socklen_t \fIsalen\fP, int \fIflags\fP,
ares_nameinfo_callback \fIcallback\fP, void *\fIarg\fP)
.fi
.SH DESCRIPTION
The

View File

@ -18,10 +18,10 @@
ares_getsock \- get socket descriptors to wait on
.SH SYNOPSIS
.nf
.B #include <ares.h>
.PP
.B int ares_getsock(ares_channel \fIchannel\fP, ares_socket_t *\fIsocks\fP,
.B int \fInumsocks\fP);
#include <ares.h>
int ares_getsock(ares_channel \fIchannel\fP, ares_socket_t *\fIsocks\fP,
int \fInumsocks\fP);
.fi
.SH DESCRIPTION
The

View File

@ -18,10 +18,10 @@
ares_inet_ntop \- convert a network format address to presentation format
.SH SYNOPSIS
.nf
.B #include <ares.h>
.PP
.B const char *
.B ares_inet_ntop(int af, const void *src, char *dst, ares_socklen_t size);
#include <ares.h>
const char *ares_inet_ntop(int \fIaf\fP, const void *\fIsrc\fP, char *\fIdst\fP,
ares_socklen_t \fIsize\fP);
.fi
.SH DESCRIPTION
This is a portable version with the identical functionality of the commonly

View File

@ -18,9 +18,9 @@
ares_inet_pton \- convert an IPv4 or IPv6 address from text to binary form
.SH SYNOPSIS
.nf
.B #include <ares.h>
.PP
.B const char *ares_inet_pton(int af, const char *src, void *dst);
#include <ares.h>
const char *ares_inet_pton(int \fIaf\fP, const char *\fIsrc\fP, void *\fIdst\fP);
.fi
.SH DESCRIPTION
This is a portable version with the identical functionality of the commonly

View File

@ -41,6 +41,7 @@ struct ares_options {
int nsort;
int ednspsz;
char *resolvconf_path;
char *hosts_path;
};
int ares_init_options(ares_channel *\fIchannelptr\fP,
@ -101,16 +102,14 @@ resolv.conf or the RES_OPTIONS environment variable.
.B ARES_OPT_UDP_PORT
.B unsigned short \fIudp_port\fP;
.br
The port to use for queries over UDP, in network byte order.
The default value is 53 (in network byte order), the standard name
service port.
The port to use for queries over UDP, in host byte order.
The default value is 53, the standard name service port.
.TP 18
.B ARES_OPT_TCP_PORT
.B unsigned short \fItcp_port\fP;
.br
The port to use for queries over TCP, in network byte order.
The default value is 53 (in network byte order), the standard name
service port.
The port to use for queries over TCP, in host byte order.
The default value is 53, the standard name service port.
.TP 18
.B ARES_OPT_SERVERS
.B struct in_addr *\fIservers\fP;
@ -195,6 +194,16 @@ should be set to a path string, and will be honoured on *nix like systems. The
default is
.B /etc/resolv.conf
.br
.TP 18
.B ARES_OPT_HOSTS_FILE
.B char *\fIhosts_path\fP;
.br
The path to use for reading the hosts file. The
.I hosts_path
should be set to a path string, and will be honoured on *nix like systems. The
default is
.B /etc/hosts
.br
.PP
The \fIoptmask\fP parameter also includes options without a corresponding
field in the

View File

@ -79,7 +79,8 @@ DllMain function. Doing so will produce deadlocks and other problems.
Initialize everything possible. This sets all known bits.
.TP
.B ARES_LIB_INIT_WIN32
Initialize Win32/64 specific libraries.
Initialize Win32/64 specific libraries. As of c-ares 1.19.0, this is ignored
as there are no currently dynamically loaded libraries.
.TP
.B ARES_LIB_INIT_NONE
Initialize nothing extra. This sets no bit.

View File

@ -18,11 +18,11 @@
ares_mkquery \- Compose a single-question DNS query buffer
.SH SYNOPSIS
.nf
.B #include <ares.h>
.PP
.B int ares_mkquery(const char *\fIname\fP, int \fIdnsclass\fP, int \fItype\fP,
.B unsigned short \fIid\fP, int \fIrd\fP, unsigned char **\fIbuf\fP,
.B int *\fIbuflen\fP)
#include <ares.h>
int ares_mkquery(const char *\fIname\fP, int \fIdnsclass\fP, int \fItype\fP,
unsigned short \fIid\fP, int \fIrd\fP, unsigned char **\fIbuf\fP,
int *\fIbuflen\fP)
.fi
.SH DESCRIPTION
Deprecated function. See \fIares_create_query(3)\fP instead!

View File

@ -18,11 +18,11 @@
ares_parse_a_reply \- Parse a reply to a DNS query of type A
.SH SYNOPSIS
.nf
.B #include <ares.h>
.PP
.B int ares_parse_a_reply(const unsigned char *\fIabuf\fP, int \fIalen\fP,
.B struct hostent **\fIhost\fP,
.B struct ares_addrttl *\fIaddrttls\fP, int *\fInaddrttls\fP);
#include <ares.h>
int ares_parse_a_reply(const unsigned char *\fIabuf\fP, int \fIalen\fP,
struct hostent **\fIhost\fP,
struct ares_addrttl *\fIaddrttls\fP, int *\fInaddrttls\fP);
.fi
.SH DESCRIPTION
The

View File

@ -18,11 +18,11 @@
ares_parse_aaaa_reply \- Parse a reply to a DNS query of type AAAA
.SH SYNOPSIS
.nf
.B #include <ares.h>
.PP
.B int ares_parse_aaaa_reply(const unsigned char *\fIabuf\fP, int \fIalen\fP,
.B struct hostent **\fIhost\fP,
.B struct ares_addr6ttl *\fIaddrttls\fP, int *\fInaddrttls\fP);
#include <ares.h>
int ares_parse_aaaa_reply(const unsigned char *\fIabuf\fP, int \fIalen\fP,
struct hostent **\fIhost\fP,
struct ares_addr6ttl *\fIaddrttls\fP, int *\fInaddrttls\fP);
.fi
.SH DESCRIPTION
The

View File

@ -17,11 +17,10 @@
.SH NAME
ares_parse_mx_reply \- Parse a reply to a DNS query of type MX
.SH SYNOPSIS
.nf
.B #include <ares.h>
.PP
.B int ares_parse_mx_reply(const unsigned char* \fIabuf\fP, int \fIalen\fP,
.B struct ares_mx_reply** \fImx_out\fP);
#include <ares.h>
int ares_parse_mx_reply(const unsigned char* \fIabuf\fP, int \fIalen\fP,
struct ares_mx_reply** \fImx_out\fP);
.fi
.SH DESCRIPTION
The

View File

@ -18,10 +18,10 @@
ares_parse_naptr_reply \- Parse a reply to a DNS query of type NAPTR
.SH SYNOPSIS
.nf
.B #include <ares.h>
.PP
.B int ares_parse_naptr_reply(const unsigned char* \fIabuf\fP, int \fIalen\fP,
.B struct ares_naptr_reply** \fInaptr_out\fP);
#include <ares.h>
int ares_parse_naptr_reply(const unsigned char* \fIabuf\fP, int \fIalen\fP,
struct ares_naptr_reply** \fInaptr_out\fP);
.fi
.SH DESCRIPTION
The

View File

@ -18,10 +18,10 @@
ares_parse_ns_reply \- Parse a reply to a DNS query of type NS into a hostent
.SH SYNOPSIS
.nf
.B #include <ares.h>
.PP
.B int ares_parse_ns_reply(const unsigned char *\fIabuf\fP, int \fIalen\fP,
.B struct hostent **\fIhost\fP);
#include <ares.h>
int ares_parse_ns_reply(const unsigned char *\fIabuf\fP, int \fIalen\fP,
struct hostent **\fIhost\fP);
.fi
.SH DESCRIPTION
The

View File

@ -18,11 +18,11 @@
ares_parse_ptr_reply \- Parse a reply to a DNS query of type PTR into a hostent
.SH SYNOPSIS
.nf
.B #include <ares.h>
.PP
.B int ares_parse_ptr_reply(const unsigned char *\fIabuf\fP, int \fIalen\fP,
.B const void *\fIaddr\fP, int \fIaddrlen\fP, int \fIfamily\fP,
.B struct hostent **\fIhost\fP);
#include <ares.h>
int ares_parse_ptr_reply(const unsigned char *\fIabuf\fP, int \fIalen\fP,
const void *\fIaddr\fP, int \fIaddrlen\fP,
int \fIfamily\fP, struct hostent **\fIhost\fP);
.fi
.SH DESCRIPTION
The

View File

@ -18,10 +18,10 @@
ares_parse_soa_reply \- Parse a reply to a DNS query of type SOA
.SH SYNOPSIS
.nf
.B #include <ares.h>
.PP
.B int ares_parse_soa_reply(const unsigned char* \fIabuf\fP, int \fIalen\fP,
.B struct ares_soa_reply** \fIsoa_out\fP);
#include <ares.h>
int ares_parse_soa_reply(const unsigned char* \fIabuf\fP, int \fIalen\fP,
struct ares_soa_reply** \fIsoa_out\fP);
.fi
.SH DESCRIPTION
The

View File

@ -18,10 +18,10 @@
ares_parse_srv_reply \- Parse a reply to a DNS query of type SRV
.SH SYNOPSIS
.nf
.B #include <ares.h>
.PP
.B int ares_parse_srv_reply(const unsigned char* \fIabuf\fP, int \fIalen\fP,
.B struct ares_srv_reply** \fIsrv_out\fP);
#include <ares.h>
int ares_parse_srv_reply(const unsigned char* \fIabuf\fP, int \fIalen\fP,
struct ares_srv_reply** \fIsrv_out\fP);
.fi
.SH DESCRIPTION
The

View File

@ -18,13 +18,13 @@
ares_parse_txt_reply \- Parse a reply to a DNS query of type TXT
.SH SYNOPSIS
.nf
.B #include <ares.h>
.PP
.B int ares_parse_txt_reply(const unsigned char* \fIabuf\fP, int \fIalen\fP,
.B struct ares_txt_reply **\fItxt_out\fP);
.PP
.B int ares_parse_txt_reply_ext(const unsigned char* \fIabuf\fP, int \fIalen\fP,
.B struct ares_txt_ext **\fItxt_out\fP);
#include <ares.h>
int ares_parse_txt_reply(const unsigned char* \fIabuf\fP, int \fIalen\fP,
struct ares_txt_reply **\fItxt_out\fP);
int ares_parse_txt_reply_ext(const unsigned char* \fIabuf\fP, int \fIalen\fP,
struct ares_txt_ext **\fItxt_out\fP);
.fi
.SH DESCRIPTION
The

View File

@ -18,10 +18,10 @@
ares_parse_uri_reply \- Parse a reply to a DNS query of type URI
.SH SYNOPSIS
.nf
.B #include <ares.h>
.PP
.B int ares_parse_uri_reply(const unsigned char* \fIabuf\fP, int \fIalen\fP,
.B struct ares_uri_reply** \fIuri_out\fP);
#include <ares.h>
int ares_parse_uri_reply(const unsigned char* \fIabuf\fP, int \fIalen\fP,
struct ares_uri_reply** \fIuri_out\fP);
.fi
.SH DESCRIPTION
The

View File

@ -44,7 +44,7 @@ if they complete successfully or fail.
\fBares_process_fd(3)\fP works the same way but acts and operates only on the
specific file descriptors (sockets) you pass in to the function. Use
ARES_SOCKET_BAD for "no action". This function is provided to allow users of
c-ares to void \fIselect(3)\fP in their applications and within c-ares.
c-ares to avoid \fIselect(3)\fP in their applications and within c-ares.
To only process possible timeout conditions without a socket event occurring,
one may pass NULL as the values for both \fIread_fds\fP and \fIwrite_fds\fP for

View File

@ -18,14 +18,15 @@
ares_query \- Initiate a single-question DNS query
.SH SYNOPSIS
.nf
.B #include <ares.h>
.PP
.B typedef void (*ares_callback)(void *\fIarg\fP, int \fIstatus\fP,
.B int \fItimeouts\fP, unsigned char *\fIabuf\fP, int \fIalen\fP)
.PP
.B void ares_query(ares_channel \fIchannel\fP, const char *\fIname\fP,
.B int \fIdnsclass\fP, int \fItype\fP, ares_callback \fIcallback\fP,
.B void *\fIarg\fP)
#include <ares.h>
typedef void (*ares_callback)(void *\fIarg\fP, int \fIstatus\fP,
int \fItimeouts\fP, unsigned char *\fIabuf\fP,
int \fIalen\fP)
void ares_query(ares_channel \fIchannel\fP, const char *\fIname\fP,
int \fIdnsclass\fP, int \fItype\fP,
ares_callback \fIcallback\fP, void *\fIarg\fP)
.fi
.SH DESCRIPTION
The

View File

@ -18,9 +18,10 @@
ares_save_options \- Save configuration values obtained from initialized ares_channel
.SH SYNOPSIS
.nf
.B #include <ares.h>
.PP
.B int ares_save_options(ares_channel \fIchannel\fP, struct ares_options *\fIoptions\fP, int *\fIoptmask\fP)
#include <ares.h>
int ares_save_options(ares_channel \fIchannel\fP,
struct ares_options *\fIoptions\fP, int *\fIoptmask\fP)
.fi
.SH DESCRIPTION
The \fBares_save_options(3)\fP function saves the channel data identified by

View File

@ -18,14 +18,15 @@
ares_search \- Initiate a DNS query with domain search
.SH SYNOPSIS
.nf
.B #include <ares.h>
.PP
.B typedef void (*ares_callback)(void *\fIarg\fP, int \fIstatus\fP,
.B int \fItimeouts\fP, unsigned char *\fIabuf\fP, int \fIalen\fP)
.PP
.B void ares_search(ares_channel \fIchannel\fP, const char *\fIname\fP,
.B int \fIdnsclass\fP, int \fItype\fP, ares_callback \fIcallback\fP,
.B void *\fIarg\fP)
#include <ares.h>
typedef void (*ares_callback)(void *\fIarg\fP, int \fIstatus\fP,
int \fItimeouts\fP, unsigned char *\fIabuf\fP,
int \fIalen\fP)
void ares_search(ares_channel \fIchannel\fP, const char *\fIname\fP,
int \fIdnsclass\fP, int \fItype\fP,
ares_callback \fIcallback\fP, void *\fIarg\fP)
.fi
.SH DESCRIPTION
The

View File

@ -18,13 +18,14 @@
ares_send \- Initiate a DNS query
.SH SYNOPSIS
.nf
.B #include <ares.h>
.PP
.B typedef void (*ares_callback)(void *\fIarg\fP, int \fIstatus\fP,
.B int \fItimeouts\fP, unsigned char *\fIabuf\fP, int \fIalen\fP)
.PP
.B void ares_send(ares_channel \fIchannel\fP, const unsigned char *\fIqbuf\fP,
.B int \fIqlen\fP, ares_callback \fIcallback\fP, void *\fIarg\fP)
#include <ares.h>
typedef void (*ares_callback)(void *\fIarg\fP, int \fIstatus\fP,
int \fItimeouts\fP, unsigned char *\fIabuf\fP,
int \fIalen\fP)
void ares_send(ares_channel \fIchannel\fP, const unsigned char *\fIqbuf\fP,
int \fIqlen\fP, ares_callback \fIcallback\fP, void *\fIarg\fP)
.fi
.SH DESCRIPTION
The

View File

@ -18,9 +18,9 @@
ares_set_local_dev \- Bind to a specific network device when creating sockets.
.SH SYNOPSIS
.nf
.B #include <ares.h>
.PP
.B void ares_set_local_dev(ares_channel \fIchannel\fP, const char* \fIlocal_dev_name\fP)
#include <ares.h>
void ares_set_local_dev(ares_channel \fIchannel\fP, const char* \fIlocal_dev_name\fP)
.fi
.SH DESCRIPTION
The \fBares_set_local_dev\fP function causes all future sockets

View File

@ -18,9 +18,9 @@
ares_set_local_ip4 \- Set local IPv4 address outgoing requests.
.SH SYNOPSIS
.nf
.B #include <ares.h>
.PP
.B void ares_set_local_ip4(ares_channel \fIchannel\fP, unsigned int \fIlocal_ip\fP)
#include <ares.h>
void ares_set_local_ip4(ares_channel \fIchannel\fP, unsigned int \fIlocal_ip\fP)
.fi
.SH DESCRIPTION
The \fBares_set_local_ip4\fP function sets the IP address for outbound

View File

@ -18,15 +18,15 @@
ares_set_local_ip6 \- Set local IPv6 address outgoing requests.
.SH SYNOPSIS
.nf
.B #include <ares.h>
.PP
.B void ares_set_local_ip6(ares_channel \fIchannel\fP, const unsigned char* \fIlocal_ip6\fP)
#include <ares.h>
void ares_set_local_ip6(ares_channel \fIchannel\fP, const unsigned char* \fIlocal_ip6\fP)
.fi
.SH DESCRIPTION
The \fBares_set_local_ip6\fP function sets the IPv6 address for outbound
IPv6 requests. The parameter \fIlocal_ip6\fP is specified in network byte
order. This allows users to specify outbound interfaces when used on
multi-homed systems. The local_ip6 argument must be 16 bytes in length.
The \fBares_set_local_ip6\fP function sets the IPv6 address for outbound IPv6
requests. The parameter \fIlocal_ip6\fP is specified in network byte order.
This allows users to specify outbound interfaces when used on multi-homed
systems. The \fIlocal_ip6\fP argument must be 16 bytes in length.
.SH SEE ALSO
.BR ares_set_local_ip4 (3)
.SH NOTES

View File

@ -18,10 +18,13 @@
ares_set_servers, ares_set_servers_ports \- Initialize an ares_channel name servers configuration
.SH SYNOPSIS
.nf
.B #include <ares.h>
.PP
.B int ares_set_servers(ares_channel \fIchannel\fP, struct ares_addr_node *\fIservers\fP)
.B int ares_set_servers_ports(ares_channel \fIchannel\fP, struct ares_addr_port_node *\fIservers\fP)
#include <ares.h>
int ares_set_servers(ares_channel \fIchannel\fP,
struct ares_addr_node *\fIservers\fP)
int ares_set_servers_ports(ares_channel \fIchannel\fP,
struct ares_addr_port_node *\fIservers\fP)
.fi
.SH DESCRIPTION
The \fBares_set_servers(3)\fP function initializes name servers configuration

View File

@ -18,10 +18,11 @@
ares_set_servers_csv, ares_set_servers_ports_csv \- Set list of DNS servers to be used.
.SH SYNOPSIS
.nf
.B #include <ares.h>
.PP
.B int ares_set_servers_csv(ares_channel \fIchannel\fP, const char* \fIservers\fP)
.B int ares_set_servers_ports_csv(ares_channel \fIchannel\fP, const char* \fIservers\fP)
#include <ares.h>
int ares_set_servers_csv(ares_channel \fIchannel\fP, const char* \fIservers\fP)
int ares_set_servers_ports_csv(ares_channel \fIchannel\fP, const char* \fIservers\fP)
.fi
.SH DESCRIPTION
The \fBares_set_servers_csv\fP and \fBares_set_servers_ports_csv\fPfunctions set

View File

@ -4,13 +4,13 @@
ares_set_socket_callback \- Set a socket creation callback
.SH SYNOPSIS
.nf
.B #include <ares.h>
.PP
.B typedef int (*ares_sock_create_callback)(ares_socket_t \fIsocket_fd\fP,
#include <ares.h>
typedef int (*ares_sock_create_callback)(ares_socket_t \fIsocket_fd\fP,
int \fItype\fP,
void *\fIuserdata\fP)
.PP
.B void ares_set_socket_callback(ares_channel \fIchannel\fP,
void ares_set_socket_callback(ares_channel \fIchannel\fP,
ares_sock_create_callback \fIcallback\fP,
void *\fIuserdata\fP)
.PP

View File

@ -4,17 +4,15 @@
ares_set_socket_configure_callback \- Set a socket configuration callback
.SH SYNOPSIS
.nf
.B #include <ares.h>
.PP
.B typedef int (*ares_sock_config_callback)(ares_socket_t \fIsocket_fd\fP,
#include <ares.h>
typedef int (*ares_sock_config_callback)(ares_socket_t \fIsocket_fd\fP,
int \fItype\fP,
void *\fIuserdata\fP)
.PP
.B void ares_set_socket_configure_callback(ares_channel \fIchannel\fP,
void ares_set_socket_configure_callback(ares_channel \fIchannel\fP,
ares_sock_config_callback \fIcallback\fP,
void *\fIuserdata\fP)
.PP
.B cc file.c -lcares
.fi
.SH DESCRIPTION
.PP

View File

@ -4,21 +4,20 @@
ares_set_socket_functions \- Set socket io callbacks
.SH SYNOPSIS
.nf
.B #include <ares.h>
.PP
.B struct ares_socket_functions {
ares_socket_t(*\fIasocket\fP)(int, int, int, void *);
int(*\fIaclose\fP)(ares_socket_t, void *);
int(*\fIaconnect\fP)(ares_socket_t, const struct sockaddr *, ares_socklen_t, void *);
ares_ssize_t(*\fIarecvfrom\fP)(ares_socket_t, void *, size_t, int, struct sockaddr *, ares_socklen_t *, void *);
ares_ssize_t(*\fIasendv\fP)(ares_socket_t, const struct iovec *, int, void *);
};
#include <ares.h>
.PP
.B void ares_set_socket_functions(ares_channel \fIchannel\fP,
struct ares_socket_functions {
ares_socket_t (*\fIasocket\fP)(int, int, int, void *);
int (*\fIaclose\fP)(ares_socket_t, void *);
int (*\fIaconnect\fP)(ares_socket_t, const struct sockaddr *, ares_socklen_t, void *);
ares_ssize_t (*\fIarecvfrom\fP)(ares_socket_t, void *, size_t, int,
struct sockaddr *, ares_socklen_t *, void *);
ares_ssize_t (*\fIasendv\fP)(ares_socket_t, const struct iovec *, int, void *);
};
void ares_set_socket_functions(ares_channel \fIchannel\fP,
const struct ares_socket_functions * \fIfunctions\fP,
void *\fIuser_data\fP);
.fi
.SH DESCRIPTION
.PP

View File

@ -16,9 +16,9 @@
ares_set_sortlist \- Initialize an ares_channel sortlist configuration
.SH SYNOPSIS
.nf
.B #include <ares.h>
.PP
.B int ares_set_sortlist(ares_channel \fIchannel\fP, const char *\fIsortstr\fP)
#include <ares.h>
int ares_set_sortlist(ares_channel \fIchannel\fP, const char *\fIsortstr\fP)
.fi
.SH DESCRIPTION
The \fBares_set_sortlist(3)\fP function initializes an address sortlist configuration

View File

@ -18,9 +18,9 @@
ares_strerror \- Get the description of an ares library error code
.SH SYNOPSIS
.nf
.B #include <ares.h>
.PP
.B const char *ares_strerror(int \fIcode\fP)
#include <ares.h>
const char *ares_strerror(int \fIcode\fP)
.fi
.SH DESCRIPTION
The

View File

@ -63,6 +63,13 @@
# include <windows.h>
# include <winsock2.h>
# include <ws2tcpip.h>
/* To aid with linking against a static c-ares build, lets tell the microsoft
* compiler to pull in needed dependencies */
# ifdef _MSC_VER
# pragma comment(lib, "ws2_32")
# pragma comment(lib, "advapi32")
# pragma comment(lib, "iphlpapi")
# endif
#else
# include <sys/socket.h>
# include <netinet/in.h>
@ -168,6 +175,7 @@ extern "C" {
#define ARES_OPT_EDNSPSZ (1 << 15)
#define ARES_OPT_NOROTATE (1 << 16)
#define ARES_OPT_RESOLVCONF (1 << 17)
#define ARES_OPT_HOSTS_FILE (1 << 18)
/* Nameinfo flag values */
#define ARES_NI_NOFQDN (1 << 0)
@ -277,6 +285,7 @@ struct ares_options {
int nsort;
int ednspsz;
char *resolvconf_path;
char *hosts_path;
};
struct hostent;

View File

@ -6,12 +6,12 @@
#define ARES_COPYRIGHT "2004 - 2021 Daniel Stenberg, <daniel@haxx.se>."
#define ARES_VERSION_MAJOR 1
#define ARES_VERSION_MINOR 18
#define ARES_VERSION_PATCH 1
#define ARES_VERSION_MINOR 19
#define ARES_VERSION_PATCH 0
#define ARES_VERSION ((ARES_VERSION_MAJOR<<16)|\
(ARES_VERSION_MINOR<<8)|\
(ARES_VERSION_PATCH))
#define ARES_VERSION_STR "1.18.1"
#define ARES_VERSION_STR "1.19.0"
#if (ARES_VERSION >= 0x010700)
# define CARES_HAVE_ARES_LIBRARY_INIT 1

View File

@ -10,6 +10,11 @@ CONFIGURE_FILE (ares_config.h.cmake ${PROJECT_BINARY_DIR}/ares_config.h)
IF (CARES_SHARED)
ADD_LIBRARY (${PROJECT_NAME} SHARED ${CSOURCES})
# Include resource file in windows builds for versioned DLLs
IF (WIN32)
TARGET_SOURCES (${PROJECT_NAME} PRIVATE cares.rc)
ENDIF()
# Convert CARES_LIB_VERSIONINFO libtool version format into VERSION and SOVERSION
# Convert from ":" separated into CMake list format using ";"
STRING (REPLACE ":" ";" CARES_LIB_VERSIONINFO ${CARES_LIB_VERSIONINFO})

View File

@ -65,7 +65,6 @@ HHEADERS = ares_android.h \
ares_inet_net_pton.h \
ares_iphlpapi.h \
ares_ipv6.h \
ares_library_init.h \
ares_llist.h \
ares_nowarn.h \
ares_platform.h \

View File

@ -1,3 +1,6 @@
#ifndef __ARES_DATA_H
#define __ARES_DATA_H
/* Copyright (C) 2009-2013 by Daniel Stenberg
*
@ -74,3 +77,5 @@ struct ares_data {
void *ares_malloc_data(ares_datatype type);
#endif // __ARES_DATA_H

View File

@ -38,6 +38,8 @@ void ares_destroy_options(struct ares_options *options)
ares_free(options->lookups);
if(options->resolvconf_path)
ares_free(options->resolvconf_path);
if(options->hosts_path)
ares_free(options->hosts_path);
}
void ares_destroy(ares_channel channel)
@ -90,6 +92,9 @@ void ares_destroy(ares_channel channel)
if (channel->resolvconf_path)
ares_free(channel->resolvconf_path);
if (channel->hosts_path)
ares_free(channel->hosts_path);
ares_free(channel);
}

View File

@ -64,6 +64,8 @@ static int ares__isprint(int ch)
* - underscores which are used in SRV records.
* - Forward slashes such as are used for classless in-addr.arpa
* delegation (CNAMEs)
* - Asterisks may be used for wildcard domains in CNAMEs as seen in the
* real world.
* While RFC 2181 section 11 does state not to do validation,
* that applies to servers, not clients. Vulnerabilities have been
* reported when this validation is not performed. Security is more
@ -71,7 +73,7 @@ static int ares__isprint(int ch)
* anyhow). */
static int is_hostnamech(int ch)
{
/* [A-Za-z0-9-._/]
/* [A-Za-z0-9-*._/]
* Don't use isalnum() as it is locale-specific
*/
if (ch >= 'A' && ch <= 'Z')
@ -80,7 +82,7 @@ static int is_hostnamech(int ch)
return 1;
if (ch >= '0' && ch <= '9')
return 1;
if (ch == '-' || ch == '.' || ch == '_' || ch == '/')
if (ch == '-' || ch == '.' || ch == '_' || ch == '/' || ch == '*')
return 1;
return 0;

View File

@ -326,7 +326,7 @@ static int fake_addrinfo(const char *name,
}
}
if (family == AF_INET6 || family == AF_UNSPEC)
if (!result && (family == AF_INET6 || family == AF_UNSPEC))
{
struct ares_in6_addr addr6;
result = ares_inet_pton(AF_INET6, name, &addr6) < 1 ? 0 : 1;
@ -404,16 +404,46 @@ static void end_hquery(struct host_query *hquery, int status)
ares_free(hquery);
}
static int is_localhost(const char *name)
{
/* RFC6761 6.3 says : The domain "localhost." and any names falling within ".localhost." */
size_t len;
if (name == NULL)
return 0;
if (strcmp(name, "localhost") == 0)
return 1;
len = strlen(name);
if (len < 10 /* strlen(".localhost") */)
return 0;
if (strcmp(name + (len - 10 /* strlen(".localhost") */), ".localhost") == 0)
return 1;
return 0;
}
static int file_lookup(struct host_query *hquery)
{
FILE *fp;
int error;
int status;
const char *path_hosts = NULL;
char *path_hosts = NULL;
if (hquery->hints.ai_flags & ARES_AI_ENVHOSTS)
{
path_hosts = getenv("CARES_HOSTS");
path_hosts = ares_strdup(getenv("CARES_HOSTS"));
if (!path_hosts)
return ARES_ENOMEM;
}
if (hquery->channel->hosts_path)
{
path_hosts = ares_strdup(hquery->channel->hosts_path);
if (!path_hosts)
return ARES_ENOMEM;
}
if (!path_hosts)
@ -447,15 +477,15 @@ static int file_lookup(struct host_query *hquery)
return ARES_ENOTFOUND;
strcat(PATH_HOSTS, WIN_PATH_HOSTS);
path_hosts = PATH_HOSTS;
#elif defined(WATT32)
const char *PATH_HOSTS = _w32_GetHostsFile();
if (!PATH_HOSTS)
return ARES_ENOTFOUND;
#endif
path_hosts = PATH_HOSTS;
path_hosts = ares_strdup(PATH_HOSTS);
if (!path_hosts)
return ARES_ENOMEM;
}
fp = fopen(path_hosts, "r");
@ -466,21 +496,29 @@ static int file_lookup(struct host_query *hquery)
{
case ENOENT:
case ESRCH:
return ARES_ENOTFOUND;
status = ARES_ENOTFOUND;
break;
default:
DEBUGF(fprintf(stderr, "fopen() failed with error: %d %s\n", error,
strerror(error)));
DEBUGF(fprintf(stderr, "Error opening file: %s\n", path_hosts));
return ARES_EFILE;
status = ARES_EFILE;
break;
}
}
else
{
status = ares__readaddrinfo(fp, hquery->name, hquery->port, &hquery->hints, hquery->ai);
fclose(fp);
}
ares_free(path_hosts);
/* RFC6761 section 6.3 #3 states that "Name resolution APIs and libraries
* SHOULD recognize localhost names as special and SHOULD always return the
* IP loopback address for address queries" */
if (status == ARES_ENOTFOUND && strcmp(hquery->name, "localhost") == 0)
* IP loopback address for address queries".
* We will also ignore ALL errors when trying to resolve localhost, such
* as permissions errors reading /etc/hosts or a malformed /etc/hosts */
if (status != ARES_SUCCESS && is_localhost(hquery->name))
{
return ares__addrinfo_localhost(hquery->name, hquery->port,
&hquery->hints, hquery->ai);
@ -497,7 +535,7 @@ static void next_lookup(struct host_query *hquery, int status)
/* RFC6761 section 6.3 #3 says "Name resolution APIs SHOULD NOT send
* queries for localhost names to their configured caching DNS
* server(s)." */
if (strcmp(hquery->name, "localhost") != 0)
if (!is_localhost(hquery->name))
{
/* DNS lookup */
if (next_dns_lookup(hquery))
@ -543,8 +581,17 @@ static void host_callback(void *arg, int status, int timeouts,
if (addinfostatus != ARES_SUCCESS && addinfostatus != ARES_ENODATA)
{
/* error in parsing result e.g. no memory */
if (addinfostatus == ARES_EBADRESP && hquery->ai->nodes)
{
/* We got a bad response from server, but at least one query
* ended with ARES_SUCCESS */
end_hquery(hquery, ARES_SUCCESS);
}
else
{
end_hquery(hquery, addinfostatus);
}
}
else if (hquery->ai->nodes)
{
/* at least one query ended with ARES_SUCCESS */

View File

@ -47,9 +47,12 @@
#include <resolv.h>
#endif
#if defined(USE_WINSOCK)
# include <iphlpapi.h>
#endif
#include "ares.h"
#include "ares_inet_net_pton.h"
#include "ares_library_init.h"
#include "ares_nowarn.h"
#include "ares_platform.h"
#include "ares_private.h"
@ -58,6 +61,18 @@
#undef WIN32 /* Redefined in MingW/MSVC headers */
#endif
/* Define RtlGenRandom = SystemFunction036. This is in advapi32.dll. There is
* no need to dynamically load this, other software used widely does not.
* http://blogs.msdn.com/michael_howard/archive/2005/01/14/353379.aspx
* https://docs.microsoft.com/en-us/windows/win32/api/ntsecapi/nf-ntsecapi-rtlgenrandom
*/
#ifdef _WIN32
BOOLEAN WINAPI SystemFunction036(PVOID RandomBuffer, ULONG RandomBufferLength);
# ifndef RtlGenRandom
# define RtlGenRandom(a,b) SystemFunction036(a,b)
# endif
#endif
static int init_by_options(ares_channel channel,
const struct ares_options *options,
int optmask);
@ -149,6 +164,7 @@ int ares_init_options(ares_channel *channelptr, struct ares_options *options,
channel->sock_funcs = NULL;
channel->sock_func_cb_data = NULL;
channel->resolvconf_path = NULL;
channel->hosts_path = NULL;
channel->last_server = 0;
channel->last_timeout_processed = (time_t)now.tv_sec;
@ -217,13 +233,15 @@ done:
if (channel->servers)
ares_free(channel->servers);
if (channel->ndomains != -1)
ares_strsplit_free(channel->domains, channel->ndomains);
ares__strsplit_free(channel->domains, channel->ndomains);
if (channel->sortlist)
ares_free(channel->sortlist);
if(channel->lookups)
ares_free(channel->lookups);
if(channel->resolvconf_path)
ares_free(channel->resolvconf_path);
if(channel->hosts_path)
ares_free(channel->hosts_path);
ares_free(channel);
return status;
}
@ -335,6 +353,9 @@ int ares_save_options(ares_channel channel, struct ares_options *options,
if (channel->resolvconf_path)
(*optmask) |= ARES_OPT_RESOLVCONF;
if (channel->hosts_path)
(*optmask) |= ARES_OPT_HOSTS_FILE;
/* Copy easy stuff */
options->flags = channel->flags;
@ -414,6 +435,13 @@ int ares_save_options(ares_channel channel, struct ares_options *options,
return ARES_ENOMEM;
}
/* copy path for hosts file */
if (channel->hosts_path) {
options->hosts_path = ares_strdup(channel->hosts_path);
if (!options->hosts_path)
return ARES_ENOMEM;
}
return ARES_SUCCESS;
}
@ -530,6 +558,14 @@ static int init_by_options(ares_channel channel,
return ARES_ENOMEM;
}
/* Set path for hosts file, if given. */
if ((optmask & ARES_OPT_HOSTS_FILE) && !channel->hosts_path)
{
channel->hosts_path = ares_strdup(options->hosts_path);
if (!channel->hosts_path && options->hosts_path)
return ARES_ENOMEM;
}
channel->optmask = optmask;
return ARES_SUCCESS;
@ -608,227 +644,6 @@ static int get_REG_SZ(HKEY hKey, const char *leafKeyName, char **outptr)
return 1;
}
/*
* get_REG_SZ_9X()
*
* Functionally identical to get_REG_SZ()
*
* Supported on Windows 95, 98 and ME.
*/
static int get_REG_SZ_9X(HKEY hKey, const char *leafKeyName, char **outptr)
{
DWORD dataType = 0;
DWORD size = 0;
int res;
*outptr = NULL;
/* Find out size of string stored in registry */
res = RegQueryValueExA(hKey, leafKeyName, 0, &dataType, NULL, &size);
if ((res != ERROR_SUCCESS && res != ERROR_MORE_DATA) || !size)
return 0;
/* Allocate buffer of indicated size plus one given that string
might have been stored without null termination */
*outptr = ares_malloc(size+1);
if (!*outptr)
return 0;
/* Get the value for real */
res = RegQueryValueExA(hKey, leafKeyName, 0, &dataType,
(unsigned char *)*outptr, &size);
if ((res != ERROR_SUCCESS) || (size == 1))
{
ares_free(*outptr);
*outptr = NULL;
return 0;
}
/* Null terminate buffer allways */
*(*outptr + size) = '\0';
return 1;
}
/*
* get_enum_REG_SZ()
*
* Given a 'hKeyParent' handle to an open registry key and a 'leafKeyName'
* pointer to the name of the registry leaf key to be queried, parent key
* is enumerated searching in child keys for given leaf key name and its
* associated string value. When located, this returns a pointer in *outptr
* to a newly allocated memory area holding it as a null-terminated string.
*
* Returns 0 and nullifies *outptr upon inability to return a string value.
*
* Returns 1 and sets *outptr when returning a dynamically allocated string.
*
* Supported on Windows NT 3.5 and newer.
*/
static int get_enum_REG_SZ(HKEY hKeyParent, const char *leafKeyName,
char **outptr)
{
char enumKeyName[256];
DWORD enumKeyNameBuffSize;
DWORD enumKeyIdx = 0;
HKEY hKeyEnum;
int gotString;
int res;
*outptr = NULL;
for(;;)
{
enumKeyNameBuffSize = sizeof(enumKeyName);
res = RegEnumKeyExA(hKeyParent, enumKeyIdx++, enumKeyName,
&enumKeyNameBuffSize, 0, NULL, NULL, NULL);
if (res != ERROR_SUCCESS)
break;
res = RegOpenKeyExA(hKeyParent, enumKeyName, 0, KEY_QUERY_VALUE,
&hKeyEnum);
if (res != ERROR_SUCCESS)
continue;
gotString = get_REG_SZ(hKeyEnum, leafKeyName, outptr);
RegCloseKey(hKeyEnum);
if (gotString)
break;
}
if (!*outptr)
return 0;
return 1;
}
/*
* get_DNS_Registry_9X()
*
* Functionally identical to get_DNS_Registry()
*
* Implementation supports Windows 95, 98 and ME.
*/
static int get_DNS_Registry_9X(char **outptr)
{
HKEY hKey_VxD_MStcp;
int gotString;
int res;
*outptr = NULL;
res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, WIN_NS_9X, 0, KEY_READ,
&hKey_VxD_MStcp);
if (res != ERROR_SUCCESS)
return 0;
gotString = get_REG_SZ_9X(hKey_VxD_MStcp, NAMESERVER, outptr);
RegCloseKey(hKey_VxD_MStcp);
if (!gotString || !*outptr)
return 0;
return 1;
}
/*
* get_DNS_Registry_NT()
*
* Functionally identical to get_DNS_Registry()
*
* Refs: Microsoft Knowledge Base articles KB120642 and KB314053.
*
* Implementation supports Windows NT 3.5 and newer.
*/
static int get_DNS_Registry_NT(char **outptr)
{
HKEY hKey_Interfaces = NULL;
HKEY hKey_Tcpip_Parameters;
int gotString;
int res;
*outptr = NULL;
res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, WIN_NS_NT_KEY, 0, KEY_READ,
&hKey_Tcpip_Parameters);
if (res != ERROR_SUCCESS)
return 0;
/*
** Global DNS settings override adapter specific parameters when both
** are set. Additionally static DNS settings override DHCP-configured
** parameters when both are set.
*/
/* Global DNS static parameters */
gotString = get_REG_SZ(hKey_Tcpip_Parameters, NAMESERVER, outptr);
if (gotString)
goto done;
/* Global DNS DHCP-configured parameters */
gotString = get_REG_SZ(hKey_Tcpip_Parameters, DHCPNAMESERVER, outptr);
if (gotString)
goto done;
/* Try adapter specific parameters */
res = RegOpenKeyExA(hKey_Tcpip_Parameters, "Interfaces", 0,
KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS,
&hKey_Interfaces);
if (res != ERROR_SUCCESS)
{
hKey_Interfaces = NULL;
goto done;
}
/* Adapter specific DNS static parameters */
gotString = get_enum_REG_SZ(hKey_Interfaces, NAMESERVER, outptr);
if (gotString)
goto done;
/* Adapter specific DNS DHCP-configured parameters */
gotString = get_enum_REG_SZ(hKey_Interfaces, DHCPNAMESERVER, outptr);
done:
if (hKey_Interfaces)
RegCloseKey(hKey_Interfaces);
RegCloseKey(hKey_Tcpip_Parameters);
if (!gotString || !*outptr)
return 0;
return 1;
}
/*
* get_DNS_Registry()
*
* Locates DNS info in the registry. When located, this returns a pointer
* in *outptr to a newly allocated memory area holding a null-terminated
* string with a space or comma seperated list of DNS IP addresses.
*
* Returns 0 and nullifies *outptr upon inability to return DNSes string.
*
* Returns 1 and sets *outptr when returning a dynamically allocated string.
*/
static int get_DNS_Registry(char **outptr)
{
win_platform platform;
int gotString = 0;
*outptr = NULL;
platform = ares__getplatform();
if (platform == WIN_NT)
gotString = get_DNS_Registry_NT(outptr);
else if (platform == WIN_9X)
gotString = get_DNS_Registry_9X(outptr);
if (!gotString)
return 0;
return 1;
}
static void commanjoin(char** dst, const char* const src, const size_t len)
{
char *newbuf;
@ -857,106 +672,6 @@ static void commajoin(char **dst, const char *src)
commanjoin(dst, src, strlen(src));
}
/*
* get_DNS_NetworkParams()
*
* Locates DNS info using GetNetworkParams() function from the Internet
* Protocol Helper (IP Helper) API. When located, this returns a pointer
* in *outptr to a newly allocated memory area holding a null-terminated
* string with a space or comma seperated list of DNS IP addresses.
*
* Returns 0 and nullifies *outptr upon inability to return DNSes string.
*
* Returns 1 and sets *outptr when returning a dynamically allocated string.
*
* Implementation supports Windows 98 and newer.
*
* Note: Ancient PSDK required in order to build a W98 target.
*/
static int get_DNS_NetworkParams(char **outptr)
{
FIXED_INFO *fi, *newfi;
struct ares_addr namesrvr;
char *txtaddr;
IP_ADDR_STRING *ipAddr;
int res;
DWORD size = sizeof (*fi);
*outptr = NULL;
/* Verify run-time availability of GetNetworkParams() */
if (ares_fpGetNetworkParams == ZERO_NULL)
return 0;
fi = ares_malloc(size);
if (!fi)
return 0;
res = (*ares_fpGetNetworkParams) (fi, &size);
if ((res != ERROR_BUFFER_OVERFLOW) && (res != ERROR_SUCCESS))
goto done;
newfi = ares_realloc(fi, size);
if (!newfi)
goto done;
fi = newfi;
res = (*ares_fpGetNetworkParams) (fi, &size);
if (res != ERROR_SUCCESS)
goto done;
for (ipAddr = &fi->DnsServerList; ipAddr; ipAddr = ipAddr->Next)
{
txtaddr = &ipAddr->IpAddress.String[0];
/* Validate converting textual address to binary format. */
if (ares_inet_pton(AF_INET, txtaddr, &namesrvr.addrV4) == 1)
{
if ((namesrvr.addrV4.S_un.S_addr == INADDR_ANY) ||
(namesrvr.addrV4.S_un.S_addr == INADDR_NONE))
continue;
}
else if (ares_inet_pton(AF_INET6, txtaddr, &namesrvr.addrV6) == 1)
{
if (memcmp(&namesrvr.addrV6, &ares_in6addr_any,
sizeof(namesrvr.addrV6)) == 0)
continue;
}
else
continue;
commajoin(outptr, txtaddr);
if (!*outptr)
break;
}
done:
if (fi)
ares_free(fi);
if (!*outptr)
return 0;
return 1;
}
static BOOL ares_IsWindowsVistaOrGreater(void)
{
OSVERSIONINFO vinfo;
memset(&vinfo, 0, sizeof(vinfo));
vinfo.dwOSVersionInfoSize = sizeof(vinfo);
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable:4996) /* warning C4996: 'GetVersionExW': was declared deprecated */
#endif
if (!GetVersionEx(&vinfo) || vinfo.dwMajorVersion < 6)
return FALSE;
return TRUE;
#ifdef _MSC_VER
#pragma warning(pop)
#endif
}
/* A structure to hold the string form of IPv4 and IPv6 addresses so we can
* sort them by a metric.
@ -1033,8 +748,7 @@ static ULONG getBestRouteMetric(IF_LUID * const luid, /* Can't be const :( */
/* On this interface, get the best route to that destination. */
MIB_IPFORWARD_ROW2 row;
SOCKADDR_INET ignored;
if(!ares_fpGetBestRoute2 ||
ares_fpGetBestRoute2(/* The interface to use. The index is ignored since we are
if(GetBestRoute2(/* The interface to use. The index is ignored since we are
* passing a LUID.
*/
luid, 0,
@ -1067,7 +781,7 @@ static ULONG getBestRouteMetric(IF_LUID * const luid, /* Can't be const :( */
}
/*
* get_DNS_AdaptersAddresses()
* get_DNS_Windows()
*
* Locates DNS info using GetAdaptersAddresses() function from the Internet
* Protocol Helper (IP Helper) API. When located, this returns a pointer
@ -1082,7 +796,7 @@ static ULONG getBestRouteMetric(IF_LUID * const luid, /* Can't be const :( */
*/
#define IPAA_INITIAL_BUF_SZ 15 * 1024
#define IPAA_MAX_TRIES 3
static int get_DNS_AdaptersAddresses(char **outptr)
static int get_DNS_Windows(char **outptr)
{
IP_ADAPTER_DNS_SERVER_ADDRESS *ipaDNSAddr;
IP_ADAPTER_ADDRESSES *ipaa, *newipaa, *ipaaEntry;
@ -1107,10 +821,6 @@ static int get_DNS_AdaptersAddresses(char **outptr)
*outptr = NULL;
/* Verify run-time availability of GetAdaptersAddresses() */
if (ares_fpGetAdaptersAddresses == ZERO_NULL)
return 0;
ipaa = ares_malloc(Bufsz);
if (!ipaa)
return 0;
@ -1127,8 +837,7 @@ static int get_DNS_AdaptersAddresses(char **outptr)
}
/* Usually this call suceeds with initial buffer size */
res = (*ares_fpGetAdaptersAddresses) (AF_UNSPEC, AddrFlags, NULL,
ipaa, &ReqBufsz);
res = GetAdaptersAddresses(AF_UNSPEC, AddrFlags, NULL, ipaa, &ReqBufsz);
if ((res != ERROR_BUFFER_OVERFLOW) && (res != ERROR_SUCCESS))
goto done;
@ -1142,8 +851,7 @@ static int get_DNS_AdaptersAddresses(char **outptr)
Bufsz = ReqBufsz;
ipaa = newipaa;
}
res = (*ares_fpGetAdaptersAddresses) (AF_UNSPEC, AddrFlags, NULL,
ipaa, &ReqBufsz);
res = GetAdaptersAddresses(AF_UNSPEC, AddrFlags, NULL, ipaa, &ReqBufsz);
if (res == ERROR_SUCCESS)
break;
}
@ -1185,24 +893,15 @@ static int get_DNS_AdaptersAddresses(char **outptr)
addressesSize = newSize;
}
/* Vista required for Luid or Ipv4Metric */
if (ares_IsWindowsVistaOrGreater())
{
/* Save the address as the next element in addresses. */
addresses[addressesIndex].metric =
getBestRouteMetric(&ipaaEntry->Luid,
(SOCKADDR_INET*)(namesrvr.sa),
ipaaEntry->Ipv4Metric);
}
else
{
addresses[addressesIndex].metric = (ULONG)-1;
}
/* Record insertion index to make qsort stable */
addresses[addressesIndex].orig_idx = addressesIndex;
if (! ares_inet_ntop(AF_INET, &namesrvr.sa4->sin_addr,
if (!ares_inet_ntop(AF_INET, &namesrvr.sa4->sin_addr,
addresses[addressesIndex].text,
sizeof(addresses[0].text))) {
continue;
@ -1227,24 +926,15 @@ static int get_DNS_AdaptersAddresses(char **outptr)
addressesSize = newSize;
}
/* Vista required for Luid or Ipv4Metric */
if (ares_IsWindowsVistaOrGreater())
{
/* Save the address as the next element in addresses. */
addresses[addressesIndex].metric =
getBestRouteMetric(&ipaaEntry->Luid,
(SOCKADDR_INET*)(namesrvr.sa),
ipaaEntry->Ipv6Metric);
}
else
{
addresses[addressesIndex].metric = (ULONG)-1;
}
/* Record insertion index to make qsort stable */
addresses[addressesIndex].orig_idx = addressesIndex;
if (! ares_inet_ntop(AF_INET6, &namesrvr.sa6->sin6_addr,
if (!ares_inet_ntop(AF_INET6, &namesrvr.sa6->sin6_addr,
addresses[addressesIndex].text,
sizeof(addresses[0].text))) {
continue;
@ -1294,35 +984,6 @@ done:
return 1;
}
/*
* get_DNS_Windows()
*
* Locates DNS info from Windows employing most suitable methods available at
* run-time no matter which Windows version it is. When located, this returns
* a pointer in *outptr to a newly allocated memory area holding a string with
* a space or comma seperated list of DNS IP addresses, null-terminated.
*
* Returns 0 and nullifies *outptr upon inability to return DNSes string.
*
* Returns 1 and sets *outptr when returning a dynamically allocated string.
*
* Implementation supports Windows 95 and newer.
*/
static int get_DNS_Windows(char **outptr)
{
/* Try using IP helper API GetAdaptersAddresses(). IPv4 + IPv6, also sorts
* DNS servers by interface route metrics to try to use the best DNS server. */
if (get_DNS_AdaptersAddresses(outptr))
return 1;
/* Try using IP helper API GetNetworkParams(). IPv4 only. */
if (get_DNS_NetworkParams(outptr))
return 1;
/* Fall-back to registry information */
return get_DNS_Registry(outptr);
}
/*
* get_SuffixList_Windows()
*
@ -1686,8 +1347,12 @@ static int init_by_resolv_conf(ares_channel channel)
channel->tries = res.retry;
if (channel->rotate == -1)
channel->rotate = res.options & RES_ROTATE;
if (channel->timeout == -1)
if (channel->timeout == -1) {
channel->timeout = res.retrans * 1000;
#ifdef __APPLE__
channel->timeout /= (res.retry + 1) * (res.nscount > 0 ? res.nscount : 1);
#endif
}
res_ndestroy(&res);
}
@ -2021,6 +1686,11 @@ static int init_by_defaults(ares_channel channel)
ares_free(channel->resolvconf_path);
channel->resolvconf_path = NULL;
}
if(channel->hosts_path) {
ares_free(channel->hosts_path);
channel->hosts_path = NULL;
}
}
if(hostname)
@ -2243,6 +1913,8 @@ static int config_sortlist(struct apattern **sortlist, int *nsort,
q = str;
while (*q && *q != '/' && *q != ';' && !ISSPACE(*q))
q++;
if (q-str >= 16)
return ARES_EBADSTR;
memcpy(ipbuf, str, q-str);
ipbuf[q-str] = '\0';
/* Find the prefix */
@ -2251,6 +1923,8 @@ static int config_sortlist(struct apattern **sortlist, int *nsort,
const char *str2 = q+1;
while (*q && *q != ';' && !ISSPACE(*q))
q++;
if (q-str >= 32)
return ARES_EBADSTR;
memcpy(ipbufpfx, str, q-str);
ipbufpfx[q-str] = '\0';
str = str2;
@ -2325,12 +1999,12 @@ static int set_search(ares_channel channel, const char *str)
if(channel->ndomains != -1) {
/* LCOV_EXCL_START: all callers check ndomains == -1 */
/* if we already have some domains present, free them first */
ares_strsplit_free(channel->domains, channel->ndomains);
ares__strsplit_free(channel->domains, channel->ndomains);
channel->domains = NULL;
channel->ndomains = -1;
} /* LCOV_EXCL_STOP */
channel->domains = ares_strsplit(str, ", ", 1, &cnt);
channel->domains = ares__strsplit(str, ", ", &cnt);
channel->ndomains = (int)cnt;
if (channel->domains == NULL || channel->ndomains == 0) {
channel->domains = NULL;
@ -2495,12 +2169,10 @@ static int sortlist_alloc(struct apattern **sortlist, int *nsort,
return 1;
}
/* initialize an rc4 key. If possible a cryptographically secure random key
is generated using a suitable function (for example win32's RtlGenRandom as
described in
http://blogs.msdn.com/michael_howard/archive/2005/01/14/353379.aspx
otherwise the code defaults to cross-platform albeit less secure mechanism
using rand
is generated using a suitable function otherwise the code defaults to
cross-platform albeit less secure mechanism using rand
*/
static void randomize_key(unsigned char* key,int key_data_len)
{
@ -2508,21 +2180,20 @@ static void randomize_key(unsigned char* key,int key_data_len)
int counter=0;
#ifdef WIN32
BOOLEAN res;
if (ares_fpSystemFunction036)
{
res = (*ares_fpSystemFunction036) (key, key_data_len);
res = RtlGenRandom(key, key_data_len);
if (res)
randomized = 1;
}
#else /* !WIN32 */
#ifdef CARES_RANDOM_FILE
# ifdef CARES_RANDOM_FILE
FILE *f = fopen(CARES_RANDOM_FILE, "rb");
if(f) {
setvbuf(f, NULL, _IONBF, 0);
counter = aresx_uztosi(fread(key, 1, key_data_len, f));
fclose(f);
}
#endif
# endif
#endif /* WIN32 */
if (!randomized) {

View File

@ -18,18 +18,10 @@
#include "ares_setup.h"
#include "ares.h"
#include "ares_library_init.h"
#include "ares_private.h"
/* library-private global and unique instance vars */
#ifdef USE_WINSOCK
fpGetNetworkParams_t ares_fpGetNetworkParams = ZERO_NULL;
fpSystemFunction036_t ares_fpSystemFunction036 = ZERO_NULL;
fpGetAdaptersAddresses_t ares_fpGetAdaptersAddresses = ZERO_NULL;
fpGetBestRoute2_t ares_fpGetBestRoute2 = ZERO_NULL;
#endif
#if defined(ANDROID) || defined(__ANDROID__)
#include "ares_android.h"
#endif
@ -59,81 +51,8 @@ void *(*ares_malloc)(size_t size) = default_malloc;
void *(*ares_realloc)(void *ptr, size_t size) = default_realloc;
void (*ares_free)(void *ptr) = default_free;
#ifdef USE_WINSOCK
static HMODULE hnd_iphlpapi;
static HMODULE hnd_advapi32;
#endif
static int ares_win32_init(void)
{
#ifdef USE_WINSOCK
hnd_iphlpapi = 0;
hnd_iphlpapi = LoadLibraryW(L"iphlpapi.dll");
if (!hnd_iphlpapi)
return ARES_ELOADIPHLPAPI;
ares_fpGetNetworkParams = (fpGetNetworkParams_t)
GetProcAddress(hnd_iphlpapi, "GetNetworkParams");
if (!ares_fpGetNetworkParams)
{
FreeLibrary(hnd_iphlpapi);
return ARES_EADDRGETNETWORKPARAMS;
}
ares_fpGetAdaptersAddresses = (fpGetAdaptersAddresses_t)
GetProcAddress(hnd_iphlpapi, "GetAdaptersAddresses");
if (!ares_fpGetAdaptersAddresses)
{
/* This can happen on clients before WinXP, I don't
think it should be an error, unless we don't want to
support Windows 2000 anymore */
}
ares_fpGetBestRoute2 = (fpGetBestRoute2_t)
GetProcAddress(hnd_iphlpapi, "GetBestRoute2");
if (!ares_fpGetBestRoute2)
{
/* This can happen on clients before Vista, I don't
think it should be an error, unless we don't want to
support Windows XP anymore */
}
/*
* When advapi32.dll is unavailable or advapi32.dll has no SystemFunction036,
* also known as RtlGenRandom, which is the case for Windows versions prior
* to WinXP then c-ares uses portable rand() function. Then don't error here.
*/
hnd_advapi32 = 0;
hnd_advapi32 = LoadLibraryW(L"advapi32.dll");
if (hnd_advapi32)
{
ares_fpSystemFunction036 = (fpSystemFunction036_t)
GetProcAddress(hnd_advapi32, "SystemFunction036");
}
#endif
return ARES_SUCCESS;
}
static void ares_win32_cleanup(void)
{
#ifdef USE_WINSOCK
if (hnd_advapi32)
FreeLibrary(hnd_advapi32);
if (hnd_iphlpapi)
FreeLibrary(hnd_iphlpapi);
#endif
}
int ares_library_init(int flags)
{
int res;
if (ares_initialized)
{
ares_initialized++;
@ -141,12 +60,7 @@ int ares_library_init(int flags)
}
ares_initialized++;
if (flags & ARES_LIB_INIT_WIN32)
{
res = ares_win32_init();
if (res != ARES_SUCCESS)
return res; /* LCOV_EXCL_LINE: can't test Win32 init failure */
}
/* NOTE: ARES_LIB_INIT_WIN32 flag no longer used */
ares_init_flags = flags;
@ -176,8 +90,7 @@ void ares_library_cleanup(void)
if (ares_initialized)
return;
if (ares_init_flags & ARES_LIB_INIT_WIN32)
ares_win32_cleanup();
/* NOTE: ARES_LIB_INIT_WIN32 flag no longer used */
#if defined(ANDROID) || defined(__ANDROID__)
ares_library_cleanup_android();

View File

@ -1,43 +0,0 @@
#ifndef HEADER_CARES_LIBRARY_INIT_H
#define HEADER_CARES_LIBRARY_INIT_H
/* Copyright 1998 by the Massachusetts Institute of Technology.
* Copyright (C) 2004-2011 by Daniel Stenberg
*
* Permission to use, copy, modify, and distribute this
* software and its documentation for any purpose and without
* fee is hereby granted, provided that the above copyright
* notice appear in all copies and that both that copyright
* notice and this permission notice appear in supporting
* documentation, and that the name of M.I.T. not be used in
* advertising or publicity pertaining to distribution of the
* software without specific, written prior permission.
* M.I.T. makes no representations about the suitability of
* this software for any purpose. It is provided "as is"
* without express or implied warranty.
*/
#include "ares_setup.h"
#ifdef USE_WINSOCK
#include <iphlpapi.h>
#include "ares_iphlpapi.h"
typedef DWORD (WINAPI *fpGetNetworkParams_t) (FIXED_INFO*, DWORD*);
typedef BOOLEAN (APIENTRY *fpSystemFunction036_t) (void*, ULONG);
typedef ULONG (WINAPI *fpGetAdaptersAddresses_t) ( ULONG, ULONG, void*, IP_ADAPTER_ADDRESSES*, ULONG* );
typedef NETIO_STATUS (WINAPI *fpGetBestRoute2_t) ( NET_LUID *, NET_IFINDEX, const SOCKADDR_INET *, const SOCKADDR_INET *, ULONG, PMIB_IPFORWARD_ROW2, SOCKADDR_INET * );
/* Forward-declaration of variables defined in ares_library_init.c */
/* that are global and unique instances for whole c-ares library. */
extern fpGetNetworkParams_t ares_fpGetNetworkParams;
extern fpSystemFunction036_t ares_fpSystemFunction036;
extern fpGetAdaptersAddresses_t ares_fpGetAdaptersAddresses;
extern fpGetBestRoute2_t ares_fpGetBestRoute2;
#endif /* USE_WINSOCK */
#endif /* HEADER_CARES_LIBRARY_INIT_H */

View File

@ -339,6 +339,9 @@ struct ares_channeldata {
/* Path for resolv.conf file, configurable via ares_options */
char *resolvconf_path;
/* Path for hosts file, configurable via ares_options */
char *hosts_path;
};
/* Does the domain end in ".onion" or ".onion."? Case-insensitive. */

View File

@ -209,6 +209,17 @@ static void write_tcp_data(ares_channel channel,
ares_ssize_t scount;
ares_ssize_t wcount;
size_t n;
/* From writev manpage: An implementation can advertise its limit by defining
IOV_MAX in <limits.h> or at run time via the return value from
sysconf(_SC_IOV_MAX). On modern Linux systems, the limit is 1024. Back in
Linux 2.0 days, this limit was 16. */
#if defined(IOV_MAX)
const size_t maxn = IOV_MAX; /* FreeBSD */
#elif defined(_SC_IOV_MAX)
const size_t maxn = sysconf(_SC_IOV_MAX); /* Linux */
#else
const size_t maxn = 16; /* Safe default */
#endif
if(!write_fds && (write_fd == ARES_SOCKET_BAD))
/* no possible action */
@ -256,6 +267,8 @@ static void write_tcp_data(ares_channel channel,
vec[n].iov_base = (char *) sendreq->data;
vec[n].iov_len = sendreq->len;
n++;
if(n >= maxn)
break;
}
wcount = socket_writev(channel, server->tcp_socket, vec, (int)n);
ares_free(vec);

View File

@ -22,47 +22,7 @@
#include "ares.h"
#include "ares_private.h"
static int list_contains(char * const *list, size_t num_elem, const char *str, int insensitive)
{
size_t len;
size_t i;
len = strlen(str);
for (i=0; i<num_elem; i++)
{
if (insensitive)
{
#ifdef WIN32
if (strnicmp(list[i], str, len) == 0)
#else
if (strncasecmp(list[i], str, len) == 0)
#endif
return 1;
}
else
{
if (strncmp(list[i], str, len) == 0)
return 1;
}
}
return 0;
}
static int is_delim(char c, const char *delims, size_t num_delims)
{
size_t i;
for (i=0; i<num_delims; i++)
{
if (c == delims[i])
return 1;
}
return 0;
}
void ares_strsplit_free(char **elms, size_t num_elm)
void ares__strsplit_free(char **elms, size_t num_elm)
{
size_t i;
@ -74,105 +34,67 @@ void ares_strsplit_free(char **elms, size_t num_elm)
ares_free(elms);
}
char **ares_strsplit(const char *in, const char *delms, int make_set, size_t *num_elm)
{
char *parsestr;
char **temp;
char **out;
size_t cnt;
size_t nelms;
size_t in_len;
size_t num_delims;
size_t i;
char **ares__strsplit(const char *in, const char *delms, size_t *num_elm) {
const char *p;
char **table;
void *tmp;
size_t i, j, k, count;
if (in == NULL || delms == NULL || num_elm == NULL)
return NULL;
*num_elm = 0;
in_len = strlen(in);
num_delims = strlen(delms);
/* Figure out how many elements. */
nelms = 1;
for (i=0; i<in_len; i++)
{
if (is_delim(in[i], delms, num_delims))
{
nelms++;
}
/* count non-empty delimited substrings */
count = 0;
p = in;
do {
i = strcspn(p, delms);
if (i != 0) {
/* string is non-empty */
count++;
p += i;
}
} while(*p++ != 0);
/* Copy of input so we can cut it up. */
parsestr = ares_strdup(in);
if (parsestr == NULL)
if (count == 0)
return NULL;
table = ares_malloc(count * sizeof(*table));
if (table == NULL)
return NULL;
/* Temporary array to store locations of start of each element
* within parsestr. */
temp = ares_malloc(nelms * sizeof(*temp));
if (temp == NULL)
{
ares_free(parsestr);
j = 0; /* current table entry */
/* re-calculate indices and allocate new strings for table */
for (p = in; j < count; p += i + 1) {
i = strcspn(p, delms);
if (i != 0) {
for (k = 0; k < j; k++) {
#ifdef WIN32
if (strnicmp(table[k], p, i) == 0 && table[k][i] == 0)
break;
#else
if (strncasecmp(table[k], p, i) == 0 && table[k][i] == 0)
break;
#endif
}
if (k == j) {
/* copy unique strings only */
table[j] = ares_malloc(i + 1);
if (table[j] == NULL) {
ares__strsplit_free(table, j);
return NULL;
}
temp[0] = parsestr;
cnt = 1;
for (i=0; i<in_len && cnt<nelms; i++)
{
if (!is_delim(parsestr[i], delms, num_delims))
continue;
/* Replace sep with NULL. */
parsestr[i] = '\0';
/* Add the pointer to the array of elements */
temp[cnt] = parsestr+i+1;
cnt++;
strncpy(table[j], p, i);
table[j++][i] = 0;
} else
count--;
}
}
/* Copy each element to our output array. */
out = ares_malloc(nelms * sizeof(*out));
if (out == NULL)
{
ares_free(parsestr);
ares_free(temp);
return NULL;
}
tmp = ares_realloc(table, count * sizeof (*table));
if (tmp != NULL)
table = tmp;
nelms = 0;
for (i=0; i<cnt; i++)
{
if (temp[i][0] == '\0')
continue;
if (make_set && list_contains(out, nelms, temp[i], 1))
continue;
out[nelms] = ares_strdup(temp[i]);
if (out[nelms] == NULL)
{
ares_strsplit_free(out, nelms);
ares_free(parsestr);
ares_free(temp);
return NULL;
}
nelms++;
}
/* If there are no elements don't return an empty allocated
* array. */
if (nelms == 0)
{
ares_strsplit_free(out, nelms);
out = NULL;
}
/* Get the true number of elements (recalculated because of make_set) */
*num_elm = nelms;
ares_free(parsestr);
ares_free(temp);
return out;
*num_elm = count;
return table;
}

View File

@ -18,25 +18,24 @@
#include "ares_setup.h"
/* Split a string on delem skipping empty elements.
/* Split a string on delms skipping empty or duplicate elements.
*
* param in String to split.
* param delims String of characters to treat as a delimitor.
* param delms String of characters to treat as a delimitor.
* Each character in the string is a delimitor so
* there can be multiple delimitors to split on.
* E.g. ", " will split on all comma's and spaces.
* param make_set Have the list be a Set where there are no
* duplicate entries. 1 for true, 0 or false.
* Duplicate entries are removed.
* param num_elm Return parameter of the number of elements
* in the result array.
*
* returns an allocated array of allocated string elements.
*
*/
char **ares_strsplit(const char *in, const char *delms, int make_set, size_t *num_elm);
char **ares__strsplit(const char *in, const char *delms, size_t *num_elm);
/* Frees the result returned from ares_strsplit(). */
void ares_strsplit_free(char **elms, size_t num_elm);
/* Frees the result returned from ares__strsplit(). */
void ares__strsplit_free(char **elms, size_t num_elm);
#endif /* HEADER_CARES_STRSPLIT_H */

View File

@ -1,3 +1,4 @@
// require C++17+
#ifndef SIMDSOFT__NTCVT_HPP
#define SIMDSOFT__NTCVT_HPP
@ -40,7 +41,7 @@ public:
// std::string: use memset (usually implemented with SIMD)
// std::wstring: for loop (slow performance)
// only works on msvc currently
_Elem* resize_nofill(size_t len)
_Elem* resize_for_overwrite(size_t len)
{
this->reserve(len);
#if _MSC_VER >= 1920 // VS2019+
@ -62,7 +63,7 @@ auto prepare(_Cont& str, size_t size)
{
using _Elem = typename _Cont::value_type;
intrusive_string<_Elem>& helper = (intrusive_string<_Elem>&)str;
return helper.resize_nofill(size);
return helper.resize_for_overwrite(size);
}
#if defined(_AFX)
template <> inline
@ -130,12 +131,12 @@ inline wchar_t* mcbs2wdup(const char* mcb, int len, int* wbuf_len, UINT cp = NTC
#if _HAS_CXX17
inline std::string from_chars(const std::wstring_view& wcb, UINT cp = NTCVT_CP_DEFAULT)
{
return wcbs2a<std::string>(wcb.data(), wcb.length(), cp);
return wcbs2a<std::string>(wcb.data(), static_cast<int>(wcb.length()), cp);
}
inline std::wstring from_chars(const std::string_view& mcb, UINT cp = NTCVT_CP_DEFAULT)
{
return mcbs2w<std::wstring>(mcb.data(), mcb.length(), cp);
return mcbs2w<std::wstring>(mcb.data(), static_cast<int>(mcb.length()), cp);
}
#else
inline std::string from_chars(const std::wstring& wcb, UINT cp = NTCVT_CP_DEFAULT)
@ -170,7 +171,7 @@ namespace afx
# if _HAS_CXX17
inline CStringW from_chars(std::string_view mcb, UINT cp = NTCVT_CP_DEFAULT)
{
return mcbs2w<CStringW>(mcb.data(), mcb.length(), cp);
return mcbs2w<CStringW>(mcb.data(), static_cast<int>(mcb.length()), cp);
}
# else
inline CStringW from_chars(const char* str, UINT cp = NTCVT_CP_DEFAULT)
@ -179,7 +180,7 @@ inline CStringW from_chars(const char* str, UINT cp = NTCVT_CP_DEFAULT)
}
inline CStringW from_chars(const std::string& mcb, UINT cp = NTCVT_CP_DEFAULT)
{
return mcbs2w<CStringW>(mcb.c_str(), mcb.length(), cp);
return mcbs2w<CStringW>(mcb.c_str(), static_cast<int>(mcb.length()), cp);
}
# endif
} // namespace afx

View File

@ -30,6 +30,9 @@ if(CMAKE_SYSTEM_NAME STREQUAL "iOS")
endif()
endif()
set(CMAKE_C_VISIBILITY_PRESET hidden)
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
if(COMMAND CMAKE_POLICY)
cmake_policy(SET CMP0003 NEW)
cmake_policy(SET CMP0005 NEW)
@ -42,6 +45,12 @@ if(COMMAND CMAKE_POLICY)
if(POLICY CMP0054)
cmake_policy(SET CMP0054 NEW)
endif(POLICY CMP0054)
if(POLICY CMP0058)
cmake_policy(SET CMP0058 NEW)
endif(POLICY CMP0058)
if(POLICY CMP0063)
cmake_policy(SET CMP0063 NEW)
endif(POLICY CMP0063)
if(POLICY CMP0075)
cmake_policy(SET CMP0075 NEW)
endif(POLICY CMP0075)
@ -161,8 +170,8 @@ if(NOT LIBTYPE)
endif()
set(LIB_MAJOR_VERSION "1")
set(LIB_MINOR_VERSION "22")
set(LIB_REVISION "2")
set(LIB_MINOR_VERSION "23")
set(LIB_REVISION "0")
set(LIB_VERSION "${LIB_MAJOR_VERSION}.${LIB_MINOR_VERSION}.${LIB_REVISION}")
set(LIB_VERSION_NUM ${LIB_MAJOR_VERSION},${LIB_MINOR_VERSION},${LIB_REVISION},0)
@ -170,7 +179,7 @@ set(EXPORT_DECL "")
# Require C++14
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
# Prefer C11, but support C99 and C90 too.
@ -230,7 +239,7 @@ if(MSVC)
if(HAVE_PERMISSIVE_SWITCH)
set(C_FLAGS ${C_FLAGS} $<$<COMPILE_LANGUAGE:CXX>:/permissive->)
endif()
set(C_FLAGS ${C_FLAGS} /W4 /w14640 /wd4065 /wd4127 /wd4268 /wd4324 /wd5030)
set(C_FLAGS ${C_FLAGS} /W4 /w14640 /wd4065 /wd4127 /wd4268 /wd4324 /wd5030 /wd5051)
if(NOT DXSDK_DIR)
string(REGEX REPLACE "\\\\" "/" DXSDK_DIR "$ENV{DXSDK_DIR}")
@ -258,6 +267,16 @@ else()
-Wpedantic
$<$<COMPILE_LANGUAGE:CXX>:-Wold-style-cast -Wnon-virtual-dtor -Woverloaded-virtual>)
check_cxx_compiler_flag(-Wno-c++20-attribute-extensions HAVE_WNO_CXX20_ATTR_EXT)
if(HAVE_WNO_CXX20_ATTR_EXT)
set(C_FLAGS ${C_FLAGS} $<$<COMPILE_LANGUAGE:CXX>:-Wno-c++20-attribute-extensions>)
else()
check_cxx_compiler_flag(-Wno-c++20-extensions HAVE_WNO_CXX20_EXT)
if(HAVE_WNO_CXX20_EXT)
set(C_FLAGS ${C_FLAGS} $<$<COMPILE_LANGUAGE:CXX>:-Wno-c++20-extensions>)
endif()
endif()
if(ALSOFT_WERROR)
set(C_FLAGS ${C_FLAGS} -Werror)
endif()
@ -346,13 +365,6 @@ else()
endif()
endif()
if(HAVE_GCC_PROTECTED_VISIBILITY OR HAVE_GCC_DEFAULT_VISIBILITY)
check_c_compiler_flag(-fvisibility=hidden HAVE_VISIBILITY_HIDDEN_SWITCH)
if(HAVE_VISIBILITY_HIDDEN_SWITCH)
set(C_FLAGS ${C_FLAGS} -fvisibility=hidden)
endif()
endif()
set(CMAKE_REQUIRED_FLAGS "${OLD_REQUIRED_FLAGS}")
endif()
@ -472,7 +484,7 @@ if(CMAKE_SIZEOF_VOID_P MATCHES "4" AND HAVE_SSE2)
# assumes the stack is suitably aligned. Older Linux code or other
# OSs don't guarantee this on 32-bit, so externally-callable
# functions need to ensure an aligned stack.
set(EXPORT_DECL "${EXPORT_DECL} __attribute__((force_align_arg_pointer))")
set(EXPORT_DECL "${EXPORT_DECL}__attribute__((force_align_arg_pointer))")
endif()
endif()
endif()
@ -1051,8 +1063,8 @@ if(PULSEAUDIO_FOUND)
set(HAVE_PULSEAUDIO 1)
set(BACKENDS "${BACKENDS} PulseAudio${IS_LINKED},")
set(ALC_OBJS ${ALC_OBJS} alc/backends/pulseaudio.cpp alc/backends/pulseaudio.h)
add_backend_libs(${PULSEAUDIO_LIBRARIES})
set(INC_PATHS ${INC_PATHS} ${PULSEAUDIO_INCLUDE_DIRS})
add_backend_libs(${PULSEAUDIO_LIBRARY})
set(INC_PATHS ${INC_PATHS} ${PULSEAUDIO_INCLUDE_DIR})
endif()
endif()
if(ALSOFT_REQUIRE_PULSEAUDIO AND NOT HAVE_PULSEAUDIO)
@ -1086,19 +1098,22 @@ if(COREAUDIO_FRAMEWORK AND AUDIOUNIT_INCLUDE_DIR)
set(HAVE_COREAUDIO 1)
set(ALC_OBJS ${ALC_OBJS} alc/backends/coreaudio.cpp alc/backends/coreaudio.h)
set(BACKENDS "${BACKENDS} CoreAudio,")
set(EXTRA_LIBS -Wl,-framework,CoreAudio ${EXTRA_LIBS})
if(CMAKE_SYSTEM_NAME MATCHES "^(iOS|tvOS)$")
find_library(COREFOUNDATION_FRAMEWORK NAMES CoreFoundation)
set(EXTRA_LIBS ${COREAUDIO_FRAMEWORK} ${COREFOUNDATION_FRAMEWORK} ${EXTRA_LIBS})
if(COREFOUNDATION_FRAMEWORK)
set(EXTRA_LIBS -Wl,-framework,CoreFoundation ${EXTRA_LIBS})
endif()
else()
set(EXTRA_LIBS ${COREAUDIO_FRAMEWORK} /System/Library/Frameworks/AudioUnit.framework
/System/Library/Frameworks/ApplicationServices.framework ${EXTRA_LIBS})
set(EXTRA_LIBS -Wl,-framework,AudioUnit,-framework,ApplicationServices ${EXTRA_LIBS})
endif()
# Some versions of OSX may need the AudioToolbox framework. Add it if
# it's found.
find_library(AUDIOTOOLBOX_LIBRARY NAMES AudioToolbox)
if(AUDIOTOOLBOX_LIBRARY)
set(EXTRA_LIBS ${AUDIOTOOLBOX_LIBRARY} ${EXTRA_LIBS})
set(EXTRA_LIBS -Wl,-framework,AudioToolbox ${EXTRA_LIBS})
endif()
set(INC_PATHS ${INC_PATHS} ${AUDIOUNIT_INCLUDE_DIR})
@ -1129,17 +1144,7 @@ set(OBOE_TARGET )
if(ANDROID)
set(OBOE_SOURCE "" CACHE STRING "Source directory for Oboe.")
if(OBOE_SOURCE)
# Force Oboe to build with hidden symbols. Don't want to be exporting
# them from OpenAL.
set(OLD_CXX_FLAGS ${CMAKE_CXX_FLAGS})
check_cxx_compiler_flag(-fvisibility=hidden HAVE_VISIBILITY_HIDDEN_SWITCH)
if(HAVE_VISIBILITY_HIDDEN_SWITCH)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden")
endif()
add_subdirectory(${OBOE_SOURCE} ./oboe)
set(CMAKE_CXX_FLAGS ${OLD_CXX_FLAGS})
unset(OLD_CXX_FLAGS)
set(OBOE_TARGET oboe)
else()
find_package(oboe CONFIG)
@ -1168,7 +1173,7 @@ endif()
# Check for SDL2 backend
option(ALSOFT_REQUIRE_SDL2 "Require SDL2 backend" OFF)
find_package(SDL2)
find_package(SDL2 QUIET)
if(SDL2_FOUND)
# Off by default, since it adds a runtime dependency
option(ALSOFT_BACKEND_SDL2 "Enable SDL2 backend" OFF)
@ -1176,9 +1181,10 @@ if(SDL2_FOUND)
set(HAVE_SDL2 1)
set(ALC_OBJS ${ALC_OBJS} alc/backends/sdl2.cpp alc/backends/sdl2.h)
set(BACKENDS "${BACKENDS} SDL2,")
set(EXTRA_LIBS ${SDL2_LIBRARY} ${EXTRA_LIBS})
set(INC_PATHS ${INC_PATHS} ${SDL2_INCLUDE_DIR})
set(EXTRA_LIBS ${EXTRA_LIBS} SDL2::SDL2)
endif()
else()
message(STATUS "Could NOT find SDL2")
endif()
if(ALSOFT_REQUIRE_SDL2 AND NOT SDL2_FOUND)
message(FATAL_ERROR "Failed to enabled required SDL2 backend")
@ -1199,13 +1205,19 @@ set(BACKENDS "${BACKENDS} Null")
find_package(Git)
if(ALSOFT_UPDATE_BUILD_VERSION AND GIT_FOUND AND EXISTS "${OpenAL_SOURCE_DIR}/.git")
# Get the current working branch and its latest abbreviated commit hash
add_custom_target(build_version
${CMAKE_COMMAND} -D GIT_EXECUTABLE=${GIT_EXECUTABLE} -D LIB_VERSION=${LIB_VERSION}
add_custom_command(OUTPUT "${OpenAL_BINARY_DIR}/version_witness.txt"
BYPRODUCTS "${OpenAL_BINARY_DIR}/version.h"
COMMAND ${CMAKE_COMMAND} -D GIT_EXECUTABLE=${GIT_EXECUTABLE} -D LIB_VERSION=${LIB_VERSION}
-D LIB_VERSION_NUM=${LIB_VERSION_NUM} -D SRC=${OpenAL_SOURCE_DIR}/version.h.in
-D DST=${OpenAL_BINARY_DIR}/version.h -P ${OpenAL_SOURCE_DIR}/version.cmake
COMMAND ${CMAKE_COMMAND} -E touch "${OpenAL_BINARY_DIR}/version_witness.txt"
WORKING_DIRECTORY "${OpenAL_SOURCE_DIR}"
MAIN_DEPENDENCY "${OpenAL_SOURCE_DIR}/version.h.in"
DEPENDS "${OpenAL_SOURCE_DIR}/.git/index" "${OpenAL_SOURCE_DIR}/version.cmake"
VERBATIM
)
add_custom_target(build_version DEPENDS "${OpenAL_BINARY_DIR}/version_witness.txt")
else()
set(GIT_BRANCH "UNKNOWN")
set(GIT_COMMIT_HASH "unknown")
@ -1219,11 +1231,11 @@ option(ALSOFT_EMBED_HRTF_DATA "Embed the HRTF data files (increases library foot
if(ALSOFT_EMBED_HRTF_DATA)
macro(make_hrtf_header FILENAME VARNAME)
set(infile "${OpenAL_SOURCE_DIR}/hrtf/${FILENAME}")
set(outfile "${OpenAL_BINARY_DIR}/${VARNAME}.h")
set(outfile "${OpenAL_BINARY_DIR}/${VARNAME}.txt")
add_custom_command(OUTPUT "${outfile}"
COMMAND ${CMAKE_COMMAND} -D "INPUT_FILE=${infile}" -D "OUTPUT_FILE=${outfile}"
-D "VARIABLE_NAME=${VARNAME}" -P "${CMAKE_MODULE_PATH}/bin2h.script.cmake"
-P "${CMAKE_MODULE_PATH}/bin2h.script.cmake"
WORKING_DIRECTORY "${OpenAL_SOURCE_DIR}"
DEPENDS "${infile}" "${CMAKE_MODULE_PATH}/bin2h.script.cmake"
VERBATIM
@ -1231,7 +1243,7 @@ if(ALSOFT_EMBED_HRTF_DATA)
set(ALC_OBJS ${ALC_OBJS} "${outfile}")
endmacro()
make_hrtf_header("Default HRTF.mhr" "hrtf_default")
make_hrtf_header("Default HRTF.mhr" "default_hrtf")
endif()
@ -1246,7 +1258,6 @@ if(ALSOFT_UTILS)
endif()
if(ALSOFT_UTILS OR ALSOFT_EXAMPLES)
find_package(SndFile)
find_package(SDL2)
if(SDL2_FOUND)
find_package(FFmpeg COMPONENTS AVFORMAT AVCODEC AVUTIL SWSCALE SWRESAMPLE)
endif()
@ -1271,9 +1282,12 @@ if(LIBTYPE STREQUAL "STATIC")
set(PKG_CONFIG_CFLAGS -DAL_LIBTYPE_STATIC)
foreach(FLAG ${LINKER_FLAGS} ${EXTRA_LIBS} ${MATH_LIB})
# If this is already a linker flag, or is a full path+file, add it
# as-is. Otherwise, it's a name intended to be dressed as -lname.
# as-is. If it's an SDL2 target, add the link flag for it. Otherwise,
# it's a name intended to be dressed as -lname.
if(FLAG MATCHES "^-.*" OR EXISTS "${FLAG}")
set(PKG_CONFIG_PRIVATE_LIBS "${PKG_CONFIG_PRIVATE_LIBS} ${FLAG}")
elseif(FLAG MATCHES "^SDL2::SDL2")
set(PKG_CONFIG_PRIVATE_LIBS "${PKG_CONFIG_PRIVATE_LIBS} -lSDL2")
else()
set(PKG_CONFIG_PRIVATE_LIBS "${PKG_CONFIG_PRIVATE_LIBS} -l${FLAG}")
endif()
@ -1352,7 +1366,8 @@ else()
# !important: for osx framework public header works, the headers must be in
# the project
set(TARGET_PUBLIC_HEADERS include/AL/al.h include/AL/alc.h include/AL/alext.h include/AL/efx.h)
set(TARGET_PUBLIC_HEADERS include/AL/al.h include/AL/alc.h include/AL/alext.h include/AL/efx.h
include/AL/efx-presets.h)
add_library(${IMPL_TARGET} SHARED ${OPENAL_OBJS} ${ALC_OBJS} ${CORE_OBJS} ${RC_CONFIG}
${TARGET_PUBLIC_HEADERS})
if(WIN32)
@ -1364,7 +1379,7 @@ else()
# Sets framework name to soft_oal to avoid ambiguity with the system OpenAL.framework
set(LIBNAME "soft_oal")
if(GIT_FOUND)
EXECUTE_PROCESS(COMMAND ${GIT_EXECUTABLE} rev-list --count head
EXECUTE_PROCESS(COMMAND ${GIT_EXECUTABLE} rev-list --count HEAD
TIMEOUT 5
OUTPUT_VARIABLE BUNDLE_VERSION
OUTPUT_STRIP_TRAILING_WHITESPACE)
@ -1385,8 +1400,8 @@ else()
FRAMEWORK_VERSION C
MACOSX_FRAMEWORK_NAME "${IMPL_TARGET}"
MACOSX_FRAMEWORK_IDENTIFIER "org.openal-soft.openal"
MACOSX_FRAMEWORK_SHORT_VERSION_STRING ${LIB_VERSION}
MACOSX_FRAMEWORK_BUNDLE_VERSION ${BUNDLE_VERSION}
MACOSX_FRAMEWORK_SHORT_VERSION_STRING "${LIB_VERSION}"
MACOSX_FRAMEWORK_BUNDLE_VERSION "${BUNDLE_VERSION}"
XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY ""
XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED "NO"
XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED "NO"
@ -1438,6 +1453,11 @@ if(WIN32 AND MINGW AND ALSOFT_BUILD_IMPORT_LIB AND NOT LIBTYPE STREQUAL "STATIC"
add_custom_command(TARGET OpenAL POST_BUILD
COMMAND "${SED_EXECUTABLE}" -i -e "s/ @[^ ]*//" OpenAL32.def
COMMAND "${CMAKE_DLLTOOL}" -d OpenAL32.def -l OpenAL32.lib -D OpenAL32.dll
# Technically OpenAL32.def was created by the build, but cmake
# doesn't recognize it due to -Wl,--output-def,OpenAL32.def being
# manually specified. But declaring the file here allows it to be
# properly cleaned, e.g. during make clean.
BYPRODUCTS OpenAL32.def OpenAL32.lib
COMMENT "Stripping ordinals from OpenAL32.def and generating OpenAL32.lib..."
VERBATIM
)
@ -1668,9 +1688,8 @@ if(ALSOFT_EXAMPLES)
if(SDL2_FOUND)
add_executable(alloopback examples/alloopback.c)
target_include_directories(alloopback PRIVATE ${SDL2_INCLUDE_DIR})
target_link_libraries(alloopback
PRIVATE ${LINKER_FLAGS} ${SDL2_LIBRARY} ex-common ${MATH_LIB})
PRIVATE ${LINKER_FLAGS} SDL2::SDL2 ex-common ${MATH_LIB})
if(ALSOFT_INSTALL_EXAMPLES)
set(EXTRA_INSTALLS ${EXTRA_INSTALLS} alloopback)
@ -1681,33 +1700,32 @@ if(ALSOFT_EXAMPLES)
set(FFVER_OK FALSE)
if(FFMPEG_FOUND)
set(FFVER_OK TRUE)
if(AVFORMAT_VERSION VERSION_LESS "57.56.101")
message(STATUS "libavformat is too old! (${AVFORMAT_VERSION}, wanted 57.56.101)")
if(AVFORMAT_VERSION VERSION_LESS "59.27.100")
message(STATUS "libavformat is too old! (${AVFORMAT_VERSION}, wanted 59.27.100)")
set(FFVER_OK FALSE)
endif()
if(AVCODEC_VERSION VERSION_LESS "57.64.101")
message(STATUS "libavcodec is too old! (${AVCODEC_VERSION}, wanted 57.64.101)")
if(AVCODEC_VERSION VERSION_LESS "59.37.100")
message(STATUS "libavcodec is too old! (${AVCODEC_VERSION}, wanted 59.37.100)")
set(FFVER_OK FALSE)
endif()
if(AVUTIL_VERSION VERSION_LESS "55.34.101")
message(STATUS "libavutil is too old! (${AVUTIL_VERSION}, wanted 55.34.101)")
if(AVUTIL_VERSION VERSION_LESS "57.28.100")
message(STATUS "libavutil is too old! (${AVUTIL_VERSION}, wanted 57.28.100)")
set(FFVER_OK FALSE)
endif()
if(SWSCALE_VERSION VERSION_LESS "4.2.100")
message(STATUS "libswscale is too old! (${SWSCALE_VERSION}, wanted 4.2.100)")
if(SWSCALE_VERSION VERSION_LESS "6.7.100")
message(STATUS "libswscale is too old! (${SWSCALE_VERSION}, wanted 6.7.100)")
set(FFVER_OK FALSE)
endif()
if(SWRESAMPLE_VERSION VERSION_LESS "2.3.100")
message(STATUS "libswresample is too old! (${SWRESAMPLE_VERSION}, wanted 2.3.100)")
if(SWRESAMPLE_VERSION VERSION_LESS "4.7.100")
message(STATUS "libswresample is too old! (${SWRESAMPLE_VERSION}, wanted 4.7.100)")
set(FFVER_OK FALSE)
endif()
endif()
if(FFVER_OK)
add_executable(alffplay examples/alffplay.cpp)
target_include_directories(alffplay
PRIVATE ${SDL2_INCLUDE_DIR} ${FFMPEG_INCLUDE_DIRS})
target_include_directories(alffplay PRIVATE ${FFMPEG_INCLUDE_DIRS})
target_link_libraries(alffplay
PRIVATE ${LINKER_FLAGS} ${SDL2_LIBRARY} ${FFMPEG_LIBRARIES} ex-common)
PRIVATE ${LINKER_FLAGS} SDL2::SDL2 ${FFMPEG_LIBRARIES} ex-common)
if(ALSOFT_INSTALL_EXAMPLES)
set(EXTRA_INSTALLS ${EXTRA_INSTALLS} alffplay)

View File

@ -1,3 +1,55 @@
openal-soft-1.23.0:
Fixed CoreAudio capture support.
Fixed handling per-version EAX properties.
Fixed interpolating changes to the Super Stereo width source property.
Fixed detection of the update and buffer size from PipeWire.
Fixed resuming playback devices with OpenSL.
Fixed support for certain OpenAL implementations with the router.
Improved reverb environment transitions.
Improved performance of convolution reverb.
Improved quality and performance of the pitch shifter effect slightly.
Improved sub-sample precision for resampled sources.
Improved blending spatialized multi-channel sources that use the source
radius property.
Improved mixing 2D ambisonic sources for higher-order 3D ambisonic mixing.
Improved quadraphonic and 7.1 surround sound output slightly.
Added config options for UHJ encoding/decoding quality. Including Super
Stereo processing.
Added a config option for specifying the speaker distance.
Added a compatibility config option for specifying the NFC distance
scaling.
Added a config option for mixing on PipeWire's non-real-time thread.
Added support for virtual source nodes with PipeWire capture.
Added the ability for the WASAPI backend to use different playback rates.
Added support for SOFA files that define per-response delays in makemhr.
Changed the default fallback playback sample rate to 48khz. This doesn't
affect most backends, which can detect a default rate from the system.
Changed the default resampler to cubic.
Changed the default HRTF size from 32 to 64 points.
openal-soft-1.22.2:
Fixed PipeWire version check.

View File

@ -1,12 +1,12 @@
OpenAL soft
OpenAL Soft
===========
`master` branch CI status : [![Build Status](https://travis-ci.org/kcat/openal-soft.svg?branch=master)](https://travis-ci.org/kcat/openal-soft) [![Windows Build Status](https://ci.appveyor.com/api/projects/status/github/kcat/openal-soft?branch=master&svg=true)](https://ci.appveyor.com/api/projects/status/github/kcat/openal-soft?branch=master&svg=true)
`master` branch CI status : [![GitHub Actions Status](https://github.com/kcat/openal-soft/actions/workflows/ci.yml/badge.svg)](https://github.com/kcat/openal-soft/actions) [![Windows Build Status](https://ci.appveyor.com/api/projects/status/github/kcat/openal-soft?branch=master&svg=true)](https://ci.appveyor.com/api/projects/status/github/kcat/openal-soft?branch=master&svg=true)
OpenAL Soft is an LGPL-licensed, cross-platform, software implementation of the OpenAL 3D audio API. It's forked from the open-sourced Windows version available originally from openal.org's SVN repository (now defunct).
OpenAL provides capabilities for playing audio in a virtual 3D environment. Distance attenuation, doppler shift, and directional sound emitters are among the features handled by the API. More advanced effects, including air absorption, occlusion, and environmental reverb, are available through the EFX extension. It also facilitates streaming audio, multi-channel buffers, and audio capture.
More information is available on the [official website](http://openal-soft.org/)
More information is available on the [official website](http://openal-soft.org/).
Source Install
-------------
@ -17,20 +17,37 @@ directory, and run:
cmake ..
```
Assuming configuration went well, you can then build it, typically using GNU
Make (KDevelop, MSVC, and others are possible depending on your system setup
and CMake configuration).
Alternatively, you can use any available CMake front-end, like cmake-gui,
ccmake, or your preferred IDE's CMake project parser.
Assuming configuration went well, you can then build it. The command
`cmake --build .` will instruct CMake to build the project with the toolchain
chosen during configuration (often GNU Make or NMake, although others are
possible).
Please Note: Double check that the appropriate backends were detected. Often,
complaints of no sound, crashing, and missing devices can be solved by making
sure the correct backends are being used. CMake's output will identify which
backends were enabled.
For most systems, you will likely want to make sure ALSA, OSS, and PulseAudio
were detected (if your target system uses them). For Windows, make sure
DirectSound was detected.
For most systems, you will likely want to make sure PipeWire, PulseAudio, and
ALSA were detected (if your target system uses them). For Windows, make sure
WASAPI was detected.
Building openal-soft - Using vcpkg
----------------------------------
You can download and install openal-soft using the [vcpkg](https://github.com/Microsoft/vcpkg) dependency manager:
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.sh
./vcpkg integrate install
./vcpkg install openal-soft
The openal-soft port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository.
Utilities
---------
The source package comes with an informational utility, openal-info, and is

File diff suppressed because it is too large Load Diff

View File

@ -20,13 +20,23 @@
#include <memory>
#include "eax/call.h"
#include "eax/effect.h"
#include "eax/exception.h"
#include "eax/fx_slot_index.h"
#include "eax/utils.h"
#endif // ALSOFT_EAX
struct ALbuffer;
struct ALeffect;
struct WetBuffer;
#ifdef ALSOFT_EAX
class EaxFxSlotException : public EaxException {
public:
explicit EaxFxSlotException(const char* message)
: EaxException{"EAX_FX_SLOT", message}
{}
};
#endif // ALSOFT_EAX
enum class SlotState : ALenum {
Initial = AL_INITIAL,
@ -53,12 +63,12 @@ struct ALeffectslot {
RefCount ref{0u};
EffectSlot mSlot;
EffectSlot *mSlot{nullptr};
/* Self ID */
ALuint id{};
ALeffectslot();
ALeffectslot(ALCcontext *context);
ALeffectslot(const ALeffectslot&) = delete;
ALeffectslot& operator=(const ALeffectslot&) = delete;
~ALeffectslot();
@ -72,169 +82,289 @@ struct ALeffectslot {
#ifdef ALSOFT_EAX
public:
void eax_initialize(
const EaxCall& call,
ALCcontext& al_context,
EaxFxSlotIndexValue index);
void eax_initialize(ALCcontext& al_context, EaxFxSlotIndexValue index);
const EAX50FXSLOTPROPERTIES& eax_get_eax_fx_slot() const noexcept;
EaxFxSlotIndexValue eax_get_index() const noexcept { return eax_fx_slot_index_; }
const EAX50FXSLOTPROPERTIES& eax_get_eax_fx_slot() const noexcept
{ return eax_; }
// [[nodiscard]]
// Returns `true` if all sources should be updated, or `false` otherwise.
bool eax_dispatch(const EaxCall& call)
{ return call.is_get() ? eax_get(call) : eax_set(call); }
void eax_unlock_legacy() noexcept;
void eax_commit() { eax_apply_deferred(); }
void eax_commit();
private:
static constexpr auto eax_load_effect_dirty_bit = EaxDirtyFlags{1} << 0;
static constexpr auto eax_volume_dirty_bit = EaxDirtyFlags{1} << 1;
static constexpr auto eax_lock_dirty_bit = EaxDirtyFlags{1} << 2;
static constexpr auto eax_flags_dirty_bit = EaxDirtyFlags{1} << 3;
static constexpr auto eax_occlusion_dirty_bit = EaxDirtyFlags{1} << 4;
static constexpr auto eax_occlusion_lf_ratio_dirty_bit = EaxDirtyFlags{1} << 5;
using Exception = EaxFxSlotException;
using Eax4Props = EAX40FXSLOTPROPERTIES;
struct Eax4State {
Eax4Props i; // Immediate.
};
using Eax5Props = EAX50FXSLOTPROPERTIES;
struct Eax5State {
Eax5Props i; // Immediate.
};
struct EaxRangeValidator {
template<typename TValue>
void operator()(
const char* name,
const TValue& value,
const TValue& min_value,
const TValue& max_value) const
{
eax_validate_range<Exception>(name, value, min_value, max_value);
}
};
struct Eax4GuidLoadEffectValidator {
void operator()(const GUID& guidLoadEffect) const
{
if (guidLoadEffect != EAX_NULL_GUID &&
guidLoadEffect != EAX_REVERB_EFFECT &&
guidLoadEffect != EAX_AGCCOMPRESSOR_EFFECT &&
guidLoadEffect != EAX_AUTOWAH_EFFECT &&
guidLoadEffect != EAX_CHORUS_EFFECT &&
guidLoadEffect != EAX_DISTORTION_EFFECT &&
guidLoadEffect != EAX_ECHO_EFFECT &&
guidLoadEffect != EAX_EQUALIZER_EFFECT &&
guidLoadEffect != EAX_FLANGER_EFFECT &&
guidLoadEffect != EAX_FREQUENCYSHIFTER_EFFECT &&
guidLoadEffect != EAX_VOCALMORPHER_EFFECT &&
guidLoadEffect != EAX_PITCHSHIFTER_EFFECT &&
guidLoadEffect != EAX_RINGMODULATOR_EFFECT)
{
eax_fail_unknown_effect_id();
}
}
};
struct Eax4VolumeValidator {
void operator()(long lVolume) const
{
EaxRangeValidator{}(
"Volume",
lVolume,
EAXFXSLOT_MINVOLUME,
EAXFXSLOT_MAXVOLUME);
}
};
struct Eax4LockValidator {
void operator()(long lLock) const
{
EaxRangeValidator{}(
"Lock",
lLock,
EAXFXSLOT_MINLOCK,
EAXFXSLOT_MAXLOCK);
}
};
struct Eax4FlagsValidator {
void operator()(unsigned long ulFlags) const
{
EaxRangeValidator{}(
"Flags",
ulFlags,
0UL,
~EAX40FXSLOTFLAGS_RESERVED);
}
};
struct Eax4AllValidator {
void operator()(const EAX40FXSLOTPROPERTIES& all) const
{
Eax4GuidLoadEffectValidator{}(all.guidLoadEffect);
Eax4VolumeValidator{}(all.lVolume);
Eax4LockValidator{}(all.lLock);
Eax4FlagsValidator{}(all.ulFlags);
}
};
struct Eax5OcclusionValidator {
void operator()(long lOcclusion) const
{
EaxRangeValidator{}(
"Occlusion",
lOcclusion,
EAXFXSLOT_MINOCCLUSION,
EAXFXSLOT_MAXOCCLUSION);
}
};
struct Eax5OcclusionLfRatioValidator {
void operator()(float flOcclusionLFRatio) const
{
EaxRangeValidator{}(
"Occlusion LF Ratio",
flOcclusionLFRatio,
EAXFXSLOT_MINOCCLUSIONLFRATIO,
EAXFXSLOT_MAXOCCLUSIONLFRATIO);
}
};
struct Eax5FlagsValidator {
void operator()(unsigned long ulFlags) const
{
EaxRangeValidator{}(
"Flags",
ulFlags,
0UL,
~EAX50FXSLOTFLAGS_RESERVED);
}
};
struct Eax5AllValidator {
void operator()(const EAX50FXSLOTPROPERTIES& all) const
{
Eax4AllValidator{}(static_cast<const EAX40FXSLOTPROPERTIES&>(all));
Eax5OcclusionValidator{}(all.lOcclusion);
Eax5OcclusionLfRatioValidator{}(all.flOcclusionLFRatio);
}
};
ALCcontext* eax_al_context_{};
EaxFxSlotIndexValue eax_fx_slot_index_{};
EAX50FXSLOTPROPERTIES eax_eax_fx_slot_{};
int eax_version_{}; // Current EAX version.
EaxDirtyFlags eax_df_{}; // Dirty flags for the current EAX version.
EaxEffectUPtr eax_effect_{};
bool eax_is_locked_{};
Eax5State eax123_{}; // EAX1/EAX2/EAX3 state.
Eax4State eax4_{}; // EAX4 state.
Eax5State eax5_{}; // EAX5 state.
Eax5Props eax_{}; // Current EAX state.
[[noreturn]] static void eax_fail(const char* message);
[[noreturn]] static void eax_fail_unknown_effect_id();
[[noreturn]] static void eax_fail_unknown_property_id();
[[noreturn]] static void eax_fail_unknown_version();
[[noreturn]]
static void eax_fail(
const char* message);
// Gets a new value from EAX call,
// validates it,
// sets a dirty flag only if the new value differs form the old one,
// and assigns the new value.
template<typename TValidator, EaxDirtyFlags TDirtyBit, typename TProperties>
static void eax_fx_slot_set(const EaxCall& call, TProperties& dst, EaxDirtyFlags& dirty_flags)
{
const auto& src = call.get_value<Exception, const TProperties>();
TValidator{}(src);
dirty_flags |= (dst != src ? TDirtyBit : EaxDirtyFlags{});
dst = src;
}
// Gets a new value from EAX call,
// validates it,
// sets a dirty flag without comparing the values,
// and assigns the new value.
template<typename TValidator, EaxDirtyFlags TDirtyBit, typename TProperties>
static void eax_fx_slot_set_dirty(const EaxCall& call, TProperties& dst,
EaxDirtyFlags& dirty_flags)
{
const auto& src = call.get_value<Exception, const TProperties>();
TValidator{}(src);
dirty_flags |= TDirtyBit;
dst = src;
}
GUID eax_get_eax_default_effect_guid() const noexcept;
constexpr bool eax4_fx_slot_is_legacy() const noexcept
{ return eax_fx_slot_index_ < 2; }
void eax4_fx_slot_ensure_unlocked() const;
static ALenum eax_get_efx_effect_type(const GUID& guid);
const GUID& eax_get_eax_default_effect_guid() const noexcept;
long eax_get_eax_default_lock() const noexcept;
void eax_set_eax_fx_slot_defaults();
void eax4_fx_slot_set_defaults(Eax4Props& props) noexcept;
void eax5_fx_slot_set_defaults(Eax5Props& props) noexcept;
void eax4_fx_slot_set_current_defaults(const Eax4Props& props) noexcept;
void eax5_fx_slot_set_current_defaults(const Eax5Props& props) noexcept;
void eax_fx_slot_set_current_defaults();
void eax_fx_slot_set_defaults();
void eax_initialize_eax();
void eax_initialize_lock();
void eax_initialize_effects(const EaxCall& call);
void eax_get_fx_slot_all(const EaxCall& call) const;
void eax_get_fx_slot(const EaxCall& call) const;
// [[nodiscard]]
void eax4_fx_slot_get(const EaxCall& call, const Eax4Props& props) const;
void eax5_fx_slot_get(const EaxCall& call, const Eax5Props& props) const;
void eax_fx_slot_get(const EaxCall& call) const;
// Returns `true` if all sources should be updated, or `false` otherwise.
bool eax_get(const EaxCall& call);
void eax_fx_slot_load_effect();
void eax_fx_slot_set_volume();
void eax_fx_slot_set_environment_flag();
void eax_fx_slot_set_flags();
void eax_set_fx_slot_effect(const EaxCall& call, ALenum effect_type);
void eax4_fx_slot_set_all(const EaxCall& call);
void eax5_fx_slot_set_all(const EaxCall& call);
void eax_set_fx_slot_effect(const EaxCall& call);
bool eax_fx_slot_should_update_sources() const noexcept;
void eax_set_efx_effect_slot_gain();
void eax_set_fx_slot_volume();
void eax_set_effect_slot_send_auto();
void eax_set_fx_slot_flags();
void eax_ensure_is_unlocked() const;
void eax_validate_fx_slot_effect(const GUID& eax_effect_id);
void eax_validate_fx_slot_volume(long eax_volume);
void eax_validate_fx_slot_lock(long eax_lock);
void eax_validate_fx_slot_flags(const EaxCall& call, unsigned long eax_flags);
void eax_validate_fx_slot_occlusion(long eax_occlusion);
void eax_validate_fx_slot_occlusion_lf_ratio(float eax_occlusion_lf_ratio);
void eax_validate_fx_slot_all(const EaxCall& call, const EAX40FXSLOTPROPERTIES& fx_slot);
void eax_validate_fx_slot_all(const EaxCall& call, const EAX50FXSLOTPROPERTIES& fx_slot);
void eax_set_fx_slot_effect(const EaxCall& call, const GUID& eax_effect_id);
void eax_set_fx_slot_volume(
long eax_volume);
void eax_set_fx_slot_lock(
long eax_lock);
void eax_set_fx_slot_flags(
unsigned long eax_flags);
// [[nodiscard]]
bool eax_set_fx_slot_occlusion(
long eax_occlusion);
// [[nodiscard]]
bool eax_set_fx_slot_occlusion_lf_ratio(
float eax_occlusion_lf_ratio);
void eax_set_fx_slot_all(const EaxCall& call, const EAX40FXSLOTPROPERTIES& eax_fx_slot);
// [[nodiscard]]
bool eax_set_fx_slot_all(const EaxCall& call, const EAX50FXSLOTPROPERTIES& eax_fx_slot);
void eax_defer_fx_slot_effect(const EaxCall& call);
void eax_defer_fx_slot_volume(const EaxCall& call);
void eax_defer_fx_slot_lock(const EaxCall& call);
void eax_defer_fx_slot_flags(const EaxCall& call);
// [[nodiscard]]
bool eax_defer_fx_slot_occlusion(const EaxCall& call);
// [[nodiscard]]
bool eax_defer_fx_slot_occlusion_lf_ratio(const EaxCall& call);
// [[nodiscard]]
bool eax_defer_fx_slot_all(const EaxCall& call);
bool eax_set_fx_slot(const EaxCall& call);
void eax_apply_deferred();
// [[nodiscard]]
// Returns `true` if all sources should be updated, or `false` otherwise.
bool eax4_fx_slot_set(const EaxCall& call);
// Returns `true` if all sources should be updated, or `false` otherwise.
bool eax5_fx_slot_set(const EaxCall& call);
// Returns `true` if all sources should be updated, or `false` otherwise.
bool eax_fx_slot_set(const EaxCall& call);
// Returns `true` if all sources should be updated, or `false` otherwise.
bool eax_set(const EaxCall& call);
template<
EaxDirtyFlags TDirtyBit,
typename TMemberResult,
typename TProps,
typename TState>
void eax_fx_slot_commit_property(TState& state, EaxDirtyFlags& dst_df,
TMemberResult TProps::*member) noexcept
{
auto& src_i = state.i;
auto& dst_i = eax_;
if((eax_df_ & TDirtyBit) != EaxDirtyFlags{})
{
dst_df |= TDirtyBit;
dst_i.*member = src_i.*member;
}
}
void eax4_fx_slot_commit(EaxDirtyFlags& dst_df);
void eax5_fx_slot_commit(Eax5State& state, EaxDirtyFlags& dst_df);
void eax_dispatch_effect(const EaxCall& call);
// `alAuxiliaryEffectSloti(effect_slot, AL_EFFECTSLOT_EFFECT, effect)`
void eax_set_effect_slot_effect(EaxEffect &effect);
void eax_set_efx_slot_effect(EaxEffect &effect);
// `alAuxiliaryEffectSloti(effect_slot, AL_EFFECTSLOT_AUXILIARY_SEND_AUTO, value)`
void eax_set_effect_slot_send_auto(bool is_send_auto);
void eax_set_efx_slot_send_auto(bool is_send_auto);
// `alAuxiliaryEffectSlotf(effect_slot, AL_EFFECTSLOT_GAIN, gain)`
void eax_set_effect_slot_gain(ALfloat gain);
void eax_set_efx_slot_gain(ALfloat gain);
public:
class EaxDeleter {
public:
void operator()(ALeffectslot *effect_slot);
}; // EaxAlEffectSlotDeleter
};
#endif // ALSOFT_EAX
};
void UpdateAllEffectSlotProps(ALCcontext *context);
#ifdef ALSOFT_EAX
using EaxAlEffectSlotUPtr = std::unique_ptr<ALeffectslot, ALeffectslot::EaxDeleter>;
EaxAlEffectSlotUPtr eax_create_al_effect_slot(
ALCcontext& context);
void eax_delete_al_effect_slot(
ALCcontext& context,
ALeffectslot& effect_slot);
EaxAlEffectSlotUPtr eax_create_al_effect_slot(ALCcontext& context);
void eax_delete_al_effect_slot(ALCcontext& context, ALeffectslot& effect_slot);
#endif // ALSOFT_EAX
#endif

View File

@ -288,8 +288,8 @@ al::optional<AmbiLayout> AmbiLayoutFromEnum(ALenum layout)
{
switch(layout)
{
case AL_FUMA_SOFT: return al::make_optional(AmbiLayout::FuMa);
case AL_ACN_SOFT: return al::make_optional(AmbiLayout::ACN);
case AL_FUMA_SOFT: return AmbiLayout::FuMa;
case AL_ACN_SOFT: return AmbiLayout::ACN;
}
return al::nullopt;
}
@ -307,9 +307,9 @@ al::optional<AmbiScaling> AmbiScalingFromEnum(ALenum scale)
{
switch(scale)
{
case AL_FUMA_SOFT: return al::make_optional(AmbiScaling::FuMa);
case AL_SN3D_SOFT: return al::make_optional(AmbiScaling::SN3D);
case AL_N3D_SOFT: return al::make_optional(AmbiScaling::N3D);
case AL_FUMA_SOFT: return AmbiScaling::FuMa;
case AL_SN3D_SOFT: return AmbiScaling::SN3D;
case AL_N3D_SOFT: return AmbiScaling::N3D;
}
return al::nullopt;
}
@ -329,18 +329,18 @@ al::optional<FmtChannels> FmtFromUserFmt(UserFmtChannels chans)
{
switch(chans)
{
case UserFmtMono: return al::make_optional(FmtMono);
case UserFmtStereo: return al::make_optional(FmtStereo);
case UserFmtRear: return al::make_optional(FmtRear);
case UserFmtQuad: return al::make_optional(FmtQuad);
case UserFmtX51: return al::make_optional(FmtX51);
case UserFmtX61: return al::make_optional(FmtX61);
case UserFmtX71: return al::make_optional(FmtX71);
case UserFmtBFormat2D: return al::make_optional(FmtBFormat2D);
case UserFmtBFormat3D: return al::make_optional(FmtBFormat3D);
case UserFmtUHJ2: return al::make_optional(FmtUHJ2);
case UserFmtUHJ3: return al::make_optional(FmtUHJ3);
case UserFmtUHJ4: return al::make_optional(FmtUHJ4);
case UserFmtMono: return FmtMono;
case UserFmtStereo: return FmtStereo;
case UserFmtRear: return FmtRear;
case UserFmtQuad: return FmtQuad;
case UserFmtX51: return FmtX51;
case UserFmtX61: return FmtX61;
case UserFmtX71: return FmtX71;
case UserFmtBFormat2D: return FmtBFormat2D;
case UserFmtBFormat3D: return FmtBFormat3D;
case UserFmtUHJ2: return FmtUHJ2;
case UserFmtUHJ3: return FmtUHJ3;
case UserFmtUHJ4: return FmtUHJ4;
}
return al::nullopt;
}
@ -348,12 +348,12 @@ al::optional<FmtType> FmtFromUserFmt(UserFmtType type)
{
switch(type)
{
case UserFmtUByte: return al::make_optional(FmtUByte);
case UserFmtShort: return al::make_optional(FmtShort);
case UserFmtFloat: return al::make_optional(FmtFloat);
case UserFmtDouble: return al::make_optional(FmtDouble);
case UserFmtMulaw: return al::make_optional(FmtMulaw);
case UserFmtAlaw: return al::make_optional(FmtAlaw);
case UserFmtUByte: return FmtUByte;
case UserFmtShort: return FmtShort;
case UserFmtFloat: return FmtFloat;
case UserFmtDouble: return FmtDouble;
case UserFmtMulaw: return FmtMulaw;
case UserFmtAlaw: return FmtAlaw;
/* ADPCM not handled here. */
case UserFmtIMA4: break;
case UserFmtMSADPCM: break;
@ -411,14 +411,14 @@ bool EnsureBuffers(ALCdevice *device, size_t needed)
while(needed > count)
{
if UNLIKELY(device->BufferList.size() >= 1<<25)
if(device->BufferList.size() >= 1<<25) [[unlikely]]
return false;
device->BufferList.emplace_back();
auto sublist = device->BufferList.end() - 1;
sublist->FreeMask = ~0_u64;
sublist->Buffers = static_cast<ALbuffer*>(al_calloc(alignof(ALbuffer), sizeof(ALbuffer)*64));
if UNLIKELY(!sublist->Buffers)
if(!sublist->Buffers) [[unlikely]]
{
device->BufferList.pop_back();
return false;
@ -467,10 +467,10 @@ inline ALbuffer *LookupBuffer(ALCdevice *device, ALuint id)
const size_t lidx{(id-1) >> 6};
const ALuint slidx{(id-1) & 0x3f};
if UNLIKELY(lidx >= device->BufferList.size())
if(lidx >= device->BufferList.size()) [[unlikely]]
return nullptr;
BufferSubList &sublist = device->BufferList[lidx];
if UNLIKELY(sublist.FreeMask & (1_u64 << slidx))
if(sublist.FreeMask & (1_u64 << slidx)) [[unlikely]]
return nullptr;
return sublist.Buffers + slidx;
}
@ -531,14 +531,14 @@ void LoadData(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq, ALuint size,
UserFmtChannels SrcChannels, UserFmtType SrcType, const al::byte *SrcData,
ALbitfieldSOFT access)
{
if UNLIKELY(ReadRef(ALBuf->ref) != 0 || ALBuf->MappedAccess != 0)
SETERR_RETURN(context, AL_INVALID_OPERATION,, "Modifying storage for in-use buffer %u",
if(ReadRef(ALBuf->ref) != 0 || ALBuf->MappedAccess != 0) [[unlikely]]
return context->setError(AL_INVALID_OPERATION, "Modifying storage for in-use buffer %u",
ALBuf->id);
/* Currently no channel configurations need to be converted. */
auto DstChannels = FmtFromUserFmt(SrcChannels);
if UNLIKELY(!DstChannels)
SETERR_RETURN(context, AL_INVALID_ENUM, , "Invalid format");
if(!DstChannels) [[unlikely]]
return context->setError(AL_INVALID_ENUM, "Invalid format");
/* IMA4 and MSADPCM convert to 16-bit short.
*
@ -548,19 +548,19 @@ void LoadData(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq, ALuint size,
*/
if((access&MAP_READ_WRITE_FLAGS))
{
if UNLIKELY(SrcType == UserFmtIMA4 || SrcType == UserFmtMSADPCM)
SETERR_RETURN(context, AL_INVALID_VALUE,, "%s samples cannot be mapped",
if(SrcType == UserFmtIMA4 || SrcType == UserFmtMSADPCM) [[unlikely]]
return context->setError(AL_INVALID_VALUE, "%s samples cannot be mapped",
NameFromUserFmtType(SrcType));
}
auto DstType = (SrcType == UserFmtIMA4 || SrcType == UserFmtMSADPCM)
? al::make_optional(FmtShort) : FmtFromUserFmt(SrcType);
if UNLIKELY(!DstType)
SETERR_RETURN(context, AL_INVALID_ENUM, , "Invalid format");
if(!DstType) [[unlikely]]
return context->setError(AL_INVALID_ENUM, "Invalid format");
const ALuint unpackalign{ALBuf->UnpackAlign};
const ALuint align{SanitizeAlignment(SrcType, unpackalign)};
if UNLIKELY(align < 1)
SETERR_RETURN(context, AL_INVALID_VALUE,, "Invalid unpack alignment %u for %s samples",
if(align < 1) [[unlikely]]
return context->setError(AL_INVALID_VALUE, "Invalid unpack alignment %u for %s samples",
unpackalign, NameFromUserFmtType(SrcType));
const ALuint ambiorder{IsBFormat(*DstChannels) ? ALBuf->UnpackAmbiOrder :
@ -569,12 +569,12 @@ void LoadData(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq, ALuint size,
if((access&AL_PRESERVE_DATA_BIT_SOFT))
{
/* Can only preserve data with the same format and alignment. */
if UNLIKELY(ALBuf->mChannels != *DstChannels || ALBuf->OriginalType != SrcType)
SETERR_RETURN(context, AL_INVALID_VALUE,, "Preserving data of mismatched format");
if UNLIKELY(ALBuf->OriginalAlign != align)
SETERR_RETURN(context, AL_INVALID_VALUE,, "Preserving data of mismatched alignment");
if(ALBuf->mAmbiOrder != ambiorder)
SETERR_RETURN(context, AL_INVALID_VALUE,, "Preserving data of mismatched order");
if(ALBuf->mChannels != *DstChannels || ALBuf->OriginalType != SrcType) [[unlikely]]
return context->setError(AL_INVALID_VALUE, "Preserving data of mismatched format");
if(ALBuf->OriginalAlign != align) [[unlikely]]
return context->setError(AL_INVALID_VALUE, "Preserving data of mismatched alignment");
if(ALBuf->mAmbiOrder != ambiorder) [[unlikely]]
return context->setError(AL_INVALID_VALUE, "Preserving data of mismatched order");
}
/* Convert the input/source size in bytes to sample frames using the unpack
@ -584,13 +584,13 @@ void LoadData(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq, ALuint size,
((SrcType == UserFmtIMA4) ? (align-1)/2 + 4 :
(SrcType == UserFmtMSADPCM) ? (align-2)/2 + 7 :
(align * BytesFromUserFmt(SrcType)))};
if UNLIKELY((size%SrcByteAlign) != 0)
SETERR_RETURN(context, AL_INVALID_VALUE,,
if((size%SrcByteAlign) != 0) [[unlikely]]
return context->setError(AL_INVALID_VALUE,
"Data size %d is not a multiple of frame size %d (%d unpack alignment)",
size, SrcByteAlign, align);
if UNLIKELY(size/SrcByteAlign > std::numeric_limits<ALsizei>::max()/align)
SETERR_RETURN(context, AL_OUT_OF_MEMORY,,
if(size/SrcByteAlign > std::numeric_limits<ALsizei>::max()/align) [[unlikely]]
return context->setError(AL_OUT_OF_MEMORY,
"Buffer size overflow, %d blocks x %d samples per block", size/SrcByteAlign, align);
const ALuint frames{size / SrcByteAlign * align};
@ -599,8 +599,8 @@ void LoadData(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq, ALuint size,
*/
ALuint NumChannels{ChannelsFromFmt(*DstChannels, ambiorder)};
ALuint FrameSize{NumChannels * BytesFromFmt(*DstType)};
if UNLIKELY(frames > std::numeric_limits<size_t>::max()/FrameSize)
SETERR_RETURN(context, AL_OUT_OF_MEMORY,,
if(frames > std::numeric_limits<size_t>::max()/FrameSize) [[unlikely]]
return context->setError(AL_OUT_OF_MEMORY,
"Buffer size overflow, %d frames x %d bytes per frame", frames, FrameSize);
size_t newsize{static_cast<size_t>(frames) * FrameSize};
@ -609,7 +609,7 @@ void LoadData(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq, ALuint size,
{
ALCdevice &device = *context->mALDevice;
if(!eax_x_ram_check_availability(device, *ALBuf, size))
SETERR_RETURN(context, AL_OUT_OF_MEMORY,,
return context->setError(AL_OUT_OF_MEMORY,
"Out of X-RAM memory (avail: %u, needed: %u)", device.eax_x_ram_free_size, size);
}
#endif
@ -631,6 +631,9 @@ void LoadData(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq, ALuint size,
}
newdata.swap(ALBuf->mData);
}
#ifdef ALSOFT_EAX
eax_x_ram_clear(*context->mALDevice, *ALBuf);
#endif
if(SrcType == UserFmtIMA4)
{
@ -683,19 +686,19 @@ void PrepareCallback(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq,
UserFmtChannels SrcChannels, UserFmtType SrcType, ALBUFFERCALLBACKTYPESOFT callback,
void *userptr)
{
if UNLIKELY(ReadRef(ALBuf->ref) != 0 || ALBuf->MappedAccess != 0)
SETERR_RETURN(context, AL_INVALID_OPERATION,, "Modifying callback for in-use buffer %u",
if(ReadRef(ALBuf->ref) != 0 || ALBuf->MappedAccess != 0) [[unlikely]]
return context->setError(AL_INVALID_OPERATION, "Modifying callback for in-use buffer %u",
ALBuf->id);
/* Currently no channel configurations need to be converted. */
auto DstChannels = FmtFromUserFmt(SrcChannels);
if UNLIKELY(!DstChannels)
SETERR_RETURN(context, AL_INVALID_ENUM,, "Invalid format");
if(!DstChannels) [[unlikely]]
return context->setError(AL_INVALID_ENUM, "Invalid format");
/* IMA4 and MSADPCM convert to 16-bit short. Not supported with callbacks. */
auto DstType = FmtFromUserFmt(SrcType);
if UNLIKELY(!DstType)
SETERR_RETURN(context, AL_INVALID_ENUM,, "Unsupported callback format");
if(!DstType) [[unlikely]]
return context->setError(AL_INVALID_ENUM, "Unsupported callback format");
const ALuint ambiorder{IsBFormat(*DstChannels) ? ALBuf->UnpackAmbiOrder :
(IsUHJ(*DstChannels) ? 1 : 0)};
@ -820,11 +823,11 @@ AL_API void AL_APIENTRY alGenBuffers(ALsizei n, ALuint *buffers)
START_API_FUNC
{
ContextRef context{GetContextRef()};
if UNLIKELY(!context) return;
if(!context) [[unlikely]] return;
if UNLIKELY(n < 0)
if(n < 0) [[unlikely]]
context->setError(AL_INVALID_VALUE, "Generating %d buffers", n);
if UNLIKELY(n <= 0) return;
if(n <= 0) [[unlikely]] return;
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock};
@ -834,7 +837,7 @@ START_API_FUNC
return;
}
if LIKELY(n == 1)
if(n == 1) [[likely]]
{
/* Special handling for the easy and normal case. */
ALbuffer *buffer{AllocBuffer(device)};
@ -860,11 +863,11 @@ AL_API void AL_APIENTRY alDeleteBuffers(ALsizei n, const ALuint *buffers)
START_API_FUNC
{
ContextRef context{GetContextRef()};
if UNLIKELY(!context) return;
if(!context) [[unlikely]] return;
if UNLIKELY(n < 0)
if(n < 0) [[unlikely]]
context->setError(AL_INVALID_VALUE, "Deleting %d buffers", n);
if UNLIKELY(n <= 0) return;
if(n <= 0) [[unlikely]] return;
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock};
@ -874,12 +877,12 @@ START_API_FUNC
{
if(!bid) return true;
ALbuffer *ALBuf{LookupBuffer(device, bid)};
if UNLIKELY(!ALBuf)
if(!ALBuf) [[unlikely]]
{
context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", bid);
return false;
}
if UNLIKELY(ReadRef(ALBuf->ref) != 0)
if(ReadRef(ALBuf->ref) != 0) [[unlikely]]
{
context->setError(AL_INVALID_OPERATION, "Deleting in-use buffer %u", bid);
return false;
@ -888,7 +891,7 @@ START_API_FUNC
};
const ALuint *buffers_end = buffers + n;
auto invbuf = std::find_if_not(buffers, buffers_end, validate_buffer);
if UNLIKELY(invbuf != buffers_end) return;
if(invbuf != buffers_end) [[unlikely]] return;
/* All good. Delete non-0 buffer IDs. */
auto delete_buffer = [device](const ALuint bid) -> void
@ -904,7 +907,7 @@ AL_API ALboolean AL_APIENTRY alIsBuffer(ALuint buffer)
START_API_FUNC
{
ContextRef context{GetContextRef()};
if LIKELY(context)
if(context) [[likely]]
{
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock};
@ -925,28 +928,28 @@ AL_API void AL_APIENTRY alBufferStorageSOFT(ALuint buffer, ALenum format, const
START_API_FUNC
{
ContextRef context{GetContextRef()};
if UNLIKELY(!context) return;
if(!context) [[unlikely]] return;
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock};
ALbuffer *albuf = LookupBuffer(device, buffer);
if UNLIKELY(!albuf)
if(!albuf) [[unlikely]]
context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else if UNLIKELY(size < 0)
else if(size < 0) [[unlikely]]
context->setError(AL_INVALID_VALUE, "Negative storage size %d", size);
else if UNLIKELY(freq < 1)
else if(freq < 1) [[unlikely]]
context->setError(AL_INVALID_VALUE, "Invalid sample rate %d", freq);
else if UNLIKELY((flags&INVALID_STORAGE_MASK) != 0)
else if((flags&INVALID_STORAGE_MASK) != 0) [[unlikely]]
context->setError(AL_INVALID_VALUE, "Invalid storage flags 0x%x",
flags&INVALID_STORAGE_MASK);
else if UNLIKELY((flags&AL_MAP_PERSISTENT_BIT_SOFT) && !(flags&MAP_READ_WRITE_FLAGS))
else if((flags&AL_MAP_PERSISTENT_BIT_SOFT) && !(flags&MAP_READ_WRITE_FLAGS)) [[unlikely]]
context->setError(AL_INVALID_VALUE,
"Declaring persistently mapped storage without read or write access");
else
{
auto usrfmt = DecomposeUserFormat(format);
if UNLIKELY(!usrfmt)
if(!usrfmt) [[unlikely]]
context->setError(AL_INVALID_ENUM, "Invalid format 0x%04x", format);
else
{
@ -961,39 +964,40 @@ AL_API void* AL_APIENTRY alMapBufferSOFT(ALuint buffer, ALsizei offset, ALsizei
START_API_FUNC
{
ContextRef context{GetContextRef()};
if UNLIKELY(!context) return nullptr;
if(!context) [[unlikely]] return nullptr;
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock};
ALbuffer *albuf = LookupBuffer(device, buffer);
if UNLIKELY(!albuf)
if(!albuf) [[unlikely]]
context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else if UNLIKELY((access&INVALID_MAP_FLAGS) != 0)
else if((access&INVALID_MAP_FLAGS) != 0) [[unlikely]]
context->setError(AL_INVALID_VALUE, "Invalid map flags 0x%x", access&INVALID_MAP_FLAGS);
else if UNLIKELY(!(access&MAP_READ_WRITE_FLAGS))
else if(!(access&MAP_READ_WRITE_FLAGS)) [[unlikely]]
context->setError(AL_INVALID_VALUE, "Mapping buffer %u without read or write access",
buffer);
else
{
ALbitfieldSOFT unavailable = (albuf->Access^access) & access;
if UNLIKELY(ReadRef(albuf->ref) != 0 && !(access&AL_MAP_PERSISTENT_BIT_SOFT))
if(ReadRef(albuf->ref) != 0 && !(access&AL_MAP_PERSISTENT_BIT_SOFT)) [[unlikely]]
context->setError(AL_INVALID_OPERATION,
"Mapping in-use buffer %u without persistent mapping", buffer);
else if UNLIKELY(albuf->MappedAccess != 0)
else if(albuf->MappedAccess != 0) [[unlikely]]
context->setError(AL_INVALID_OPERATION, "Mapping already-mapped buffer %u", buffer);
else if UNLIKELY((unavailable&AL_MAP_READ_BIT_SOFT))
else if((unavailable&AL_MAP_READ_BIT_SOFT)) [[unlikely]]
context->setError(AL_INVALID_VALUE,
"Mapping buffer %u for reading without read access", buffer);
else if UNLIKELY((unavailable&AL_MAP_WRITE_BIT_SOFT))
else if((unavailable&AL_MAP_WRITE_BIT_SOFT)) [[unlikely]]
context->setError(AL_INVALID_VALUE,
"Mapping buffer %u for writing without write access", buffer);
else if UNLIKELY((unavailable&AL_MAP_PERSISTENT_BIT_SOFT))
else if((unavailable&AL_MAP_PERSISTENT_BIT_SOFT)) [[unlikely]]
context->setError(AL_INVALID_VALUE,
"Mapping buffer %u persistently without persistent access", buffer);
else if UNLIKELY(offset < 0 || length <= 0
else if(offset < 0 || length <= 0
|| static_cast<ALuint>(offset) >= albuf->OriginalSize
|| static_cast<ALuint>(length) > albuf->OriginalSize - static_cast<ALuint>(offset))
[[unlikely]]
context->setError(AL_INVALID_VALUE, "Mapping invalid range %d+%d for buffer %u",
offset, length, buffer);
else
@ -1014,15 +1018,15 @@ AL_API void AL_APIENTRY alUnmapBufferSOFT(ALuint buffer)
START_API_FUNC
{
ContextRef context{GetContextRef()};
if UNLIKELY(!context) return;
if(!context) [[unlikely]] return;
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock};
ALbuffer *albuf = LookupBuffer(device, buffer);
if UNLIKELY(!albuf)
if(!albuf) [[unlikely]]
context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else if UNLIKELY(albuf->MappedAccess == 0)
else if(albuf->MappedAccess == 0) [[unlikely]]
context->setError(AL_INVALID_OPERATION, "Unmapping unmapped buffer %u", buffer);
else
{
@ -1037,20 +1041,20 @@ AL_API void AL_APIENTRY alFlushMappedBufferSOFT(ALuint buffer, ALsizei offset, A
START_API_FUNC
{
ContextRef context{GetContextRef()};
if UNLIKELY(!context) return;
if(!context) [[unlikely]] return;
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock};
ALbuffer *albuf = LookupBuffer(device, buffer);
if UNLIKELY(!albuf)
if(!albuf) [[unlikely]]
context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else if UNLIKELY(!(albuf->MappedAccess&AL_MAP_WRITE_BIT_SOFT))
else if(!(albuf->MappedAccess&AL_MAP_WRITE_BIT_SOFT)) [[unlikely]]
context->setError(AL_INVALID_OPERATION, "Flushing buffer %u while not mapped for writing",
buffer);
else if UNLIKELY(offset < albuf->MappedOffset || length <= 0
else if(offset < albuf->MappedOffset || length <= 0
|| offset >= albuf->MappedOffset+albuf->MappedSize
|| length > albuf->MappedOffset+albuf->MappedSize-offset)
|| length > albuf->MappedOffset+albuf->MappedSize-offset) [[unlikely]]
context->setError(AL_INVALID_VALUE, "Flushing invalid range %d+%d on buffer %u", offset,
length, buffer);
else
@ -1069,20 +1073,20 @@ AL_API void AL_APIENTRY alBufferSubDataSOFT(ALuint buffer, ALenum format, const
START_API_FUNC
{
ContextRef context{GetContextRef()};
if UNLIKELY(!context) return;
if(!context) [[unlikely]] return;
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock};
ALbuffer *albuf = LookupBuffer(device, buffer);
if UNLIKELY(!albuf)
if(!albuf) [[unlikely]]
{
context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
return;
}
auto usrfmt = DecomposeUserFormat(format);
if UNLIKELY(!usrfmt)
if(!usrfmt) [[unlikely]]
{
context->setError(AL_INVALID_ENUM, "Invalid format 0x%04x", format);
return;
@ -1090,18 +1094,18 @@ START_API_FUNC
ALuint unpack_align{albuf->UnpackAlign};
ALuint align{SanitizeAlignment(usrfmt->type, unpack_align)};
if UNLIKELY(align < 1)
if(align < 1) [[unlikely]]
context->setError(AL_INVALID_VALUE, "Invalid unpack alignment %u", unpack_align);
else if UNLIKELY(long{usrfmt->channels} != long{albuf->mChannels}
|| usrfmt->type != albuf->OriginalType)
else if(al::to_underlying(usrfmt->channels) != al::to_underlying(albuf->mChannels)
|| usrfmt->type != albuf->OriginalType) [[unlikely]]
context->setError(AL_INVALID_ENUM, "Unpacking data with mismatched format");
else if UNLIKELY(align != albuf->OriginalAlign)
else if(align != albuf->OriginalAlign) [[unlikely]]
context->setError(AL_INVALID_VALUE,
"Unpacking data with alignment %u does not match original alignment %u", align,
albuf->OriginalAlign);
else if UNLIKELY(albuf->isBFormat() && albuf->UnpackAmbiOrder != albuf->mAmbiOrder)
else if(albuf->isBFormat() && albuf->UnpackAmbiOrder != albuf->mAmbiOrder) [[unlikely]]
context->setError(AL_INVALID_VALUE, "Unpacking data with mismatched ambisonic order");
else if UNLIKELY(albuf->MappedAccess != 0)
else if(albuf->MappedAccess != 0) [[unlikely]]
context->setError(AL_INVALID_OPERATION, "Unpacking data into mapped buffer %u", buffer);
else
{
@ -1113,15 +1117,16 @@ START_API_FUNC
(align * frame_size)
};
if UNLIKELY(offset < 0 || length < 0 || static_cast<ALuint>(offset) > albuf->OriginalSize
if(offset < 0 || length < 0 || static_cast<ALuint>(offset) > albuf->OriginalSize
|| static_cast<ALuint>(length) > albuf->OriginalSize-static_cast<ALuint>(offset))
[[unlikely]]
context->setError(AL_INVALID_VALUE, "Invalid data sub-range %d+%d on buffer %u",
offset, length, buffer);
else if UNLIKELY((static_cast<ALuint>(offset)%byte_align) != 0)
else if((static_cast<ALuint>(offset)%byte_align) != 0) [[unlikely]]
context->setError(AL_INVALID_VALUE,
"Sub-range offset %d is not a multiple of frame size %d (%d unpack alignment)",
offset, byte_align, align);
else if UNLIKELY((static_cast<ALuint>(length)%byte_align) != 0)
else if((static_cast<ALuint>(length)%byte_align) != 0) [[unlikely]]
context->setError(AL_INVALID_VALUE,
"Sub-range length %d is not a multiple of frame size %d (%d unpack alignment)",
length, byte_align, align);
@ -1140,7 +1145,7 @@ START_API_FUNC
static_cast<const al::byte*>(data), num_chans, samplen, align);
else
{
assert(long{usrfmt->type} == long{albuf->mType});
assert(al::to_underlying(usrfmt->type) == al::to_underlying(albuf->mType));
memcpy(dst, data, size_t{samplen} * frame_size);
}
}
@ -1155,7 +1160,7 @@ AL_API void AL_APIENTRY alBufferSamplesSOFT(ALuint /*buffer*/, ALuint /*samplera
START_API_FUNC
{
ContextRef context{GetContextRef()};
if UNLIKELY(!context) return;
if(!context) [[unlikely]] return;
context->setError(AL_INVALID_OPERATION, "alBufferSamplesSOFT not supported");
}
@ -1166,7 +1171,7 @@ AL_API void AL_APIENTRY alBufferSubSamplesSOFT(ALuint /*buffer*/, ALsizei /*offs
START_API_FUNC
{
ContextRef context{GetContextRef()};
if UNLIKELY(!context) return;
if(!context) [[unlikely]] return;
context->setError(AL_INVALID_OPERATION, "alBufferSubSamplesSOFT not supported");
}
@ -1177,7 +1182,7 @@ AL_API void AL_APIENTRY alGetBufferSamplesSOFT(ALuint /*buffer*/, ALsizei /*offs
START_API_FUNC
{
ContextRef context{GetContextRef()};
if UNLIKELY(!context) return;
if(!context) [[unlikely]] return;
context->setError(AL_INVALID_OPERATION, "alGetBufferSamplesSOFT not supported");
}
@ -1187,7 +1192,7 @@ AL_API ALboolean AL_APIENTRY alIsBufferFormatSupportedSOFT(ALenum /*format*/)
START_API_FUNC
{
ContextRef context{GetContextRef()};
if UNLIKELY(!context) return AL_FALSE;
if(!context) [[unlikely]] return AL_FALSE;
context->setError(AL_INVALID_OPERATION, "alIsBufferFormatSupportedSOFT not supported");
return AL_FALSE;
@ -1199,12 +1204,12 @@ AL_API void AL_APIENTRY alBufferf(ALuint buffer, ALenum param, ALfloat /*value*/
START_API_FUNC
{
ContextRef context{GetContextRef()};
if UNLIKELY(!context) return;
if(!context) [[unlikely]] return;
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock};
if UNLIKELY(LookupBuffer(device, buffer) == nullptr)
if(LookupBuffer(device, buffer) == nullptr) [[unlikely]]
context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else switch(param)
{
@ -1219,12 +1224,12 @@ AL_API void AL_APIENTRY alBuffer3f(ALuint buffer, ALenum param,
START_API_FUNC
{
ContextRef context{GetContextRef()};
if UNLIKELY(!context) return;
if(!context) [[unlikely]] return;
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock};
if UNLIKELY(LookupBuffer(device, buffer) == nullptr)
if(LookupBuffer(device, buffer) == nullptr) [[unlikely]]
context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else switch(param)
{
@ -1238,14 +1243,14 @@ AL_API void AL_APIENTRY alBufferfv(ALuint buffer, ALenum param, const ALfloat *v
START_API_FUNC
{
ContextRef context{GetContextRef()};
if UNLIKELY(!context) return;
if(!context) [[unlikely]] return;
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock};
if UNLIKELY(LookupBuffer(device, buffer) == nullptr)
if(LookupBuffer(device, buffer) == nullptr) [[unlikely]]
context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else if UNLIKELY(!values)
else if(!values) [[unlikely]]
context->setError(AL_INVALID_VALUE, "NULL pointer");
else switch(param)
{
@ -1260,52 +1265,53 @@ AL_API void AL_APIENTRY alBufferi(ALuint buffer, ALenum param, ALint value)
START_API_FUNC
{
ContextRef context{GetContextRef()};
if UNLIKELY(!context) return;
if(!context) [[unlikely]] return;
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock};
ALbuffer *albuf = LookupBuffer(device, buffer);
if UNLIKELY(!albuf)
if(!albuf) [[unlikely]]
context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else switch(param)
{
case AL_UNPACK_BLOCK_ALIGNMENT_SOFT:
if UNLIKELY(value < 0)
if(value < 0) [[unlikely]]
context->setError(AL_INVALID_VALUE, "Invalid unpack block alignment %d", value);
else
albuf->UnpackAlign = static_cast<ALuint>(value);
break;
case AL_PACK_BLOCK_ALIGNMENT_SOFT:
if UNLIKELY(value < 0)
if(value < 0) [[unlikely]]
context->setError(AL_INVALID_VALUE, "Invalid pack block alignment %d", value);
else
albuf->PackAlign = static_cast<ALuint>(value);
break;
case AL_AMBISONIC_LAYOUT_SOFT:
if UNLIKELY(ReadRef(albuf->ref) != 0)
if(ReadRef(albuf->ref) != 0) [[unlikely]]
context->setError(AL_INVALID_OPERATION, "Modifying in-use buffer %u's ambisonic layout",
buffer);
else if UNLIKELY(value != AL_FUMA_SOFT && value != AL_ACN_SOFT)
else if(value != AL_FUMA_SOFT && value != AL_ACN_SOFT) [[unlikely]]
context->setError(AL_INVALID_VALUE, "Invalid unpack ambisonic layout %04x", value);
else
albuf->mAmbiLayout = AmbiLayoutFromEnum(value).value();
break;
case AL_AMBISONIC_SCALING_SOFT:
if UNLIKELY(ReadRef(albuf->ref) != 0)
if(ReadRef(albuf->ref) != 0) [[unlikely]]
context->setError(AL_INVALID_OPERATION, "Modifying in-use buffer %u's ambisonic scaling",
buffer);
else if UNLIKELY(value != AL_FUMA_SOFT && value != AL_SN3D_SOFT && value != AL_N3D_SOFT)
else if(value != AL_FUMA_SOFT && value != AL_SN3D_SOFT && value != AL_N3D_SOFT)
[[unlikely]]
context->setError(AL_INVALID_VALUE, "Invalid unpack ambisonic scaling %04x", value);
else
albuf->mAmbiScaling = AmbiScalingFromEnum(value).value();
break;
case AL_UNPACK_AMBISONIC_ORDER_SOFT:
if UNLIKELY(value < 1 || value > 14)
if(value < 1 || value > 14) [[unlikely]]
context->setError(AL_INVALID_VALUE, "Invalid unpack ambisonic order %d", value);
else
albuf->UnpackAmbiOrder = static_cast<ALuint>(value);
@ -1322,12 +1328,12 @@ AL_API void AL_APIENTRY alBuffer3i(ALuint buffer, ALenum param,
START_API_FUNC
{
ContextRef context{GetContextRef()};
if UNLIKELY(!context) return;
if(!context) [[unlikely]] return;
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock};
if UNLIKELY(LookupBuffer(device, buffer) == nullptr)
if(LookupBuffer(device, buffer) == nullptr) [[unlikely]]
context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else switch(param)
{
@ -1355,24 +1361,24 @@ START_API_FUNC
}
ContextRef context{GetContextRef()};
if UNLIKELY(!context) return;
if(!context) [[unlikely]] return;
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock};
ALbuffer *albuf = LookupBuffer(device, buffer);
if UNLIKELY(!albuf)
if(!albuf) [[unlikely]]
context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else if UNLIKELY(!values)
else if(!values) [[unlikely]]
context->setError(AL_INVALID_VALUE, "NULL pointer");
else switch(param)
{
case AL_LOOP_POINTS_SOFT:
if UNLIKELY(ReadRef(albuf->ref) != 0)
if(ReadRef(albuf->ref) != 0) [[unlikely]]
context->setError(AL_INVALID_OPERATION, "Modifying in-use buffer %u's loop points",
buffer);
else if UNLIKELY(values[0] < 0 || values[0] >= values[1]
|| static_cast<ALuint>(values[1]) > albuf->mSampleLen)
else if(values[0] < 0 || values[0] >= values[1]
|| static_cast<ALuint>(values[1]) > albuf->mSampleLen) [[unlikely]]
context->setError(AL_INVALID_VALUE, "Invalid loop point range %d -> %d on buffer %u",
values[0], values[1], buffer);
else
@ -1393,15 +1399,15 @@ AL_API void AL_APIENTRY alGetBufferf(ALuint buffer, ALenum param, ALfloat *value
START_API_FUNC
{
ContextRef context{GetContextRef()};
if UNLIKELY(!context) return;
if(!context) [[unlikely]] return;
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock};
ALbuffer *albuf = LookupBuffer(device, buffer);
if UNLIKELY(!albuf)
if(!albuf) [[unlikely]]
context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else if UNLIKELY(!value)
else if(!value) [[unlikely]]
context->setError(AL_INVALID_VALUE, "NULL pointer");
else switch(param)
{
@ -1415,14 +1421,14 @@ AL_API void AL_APIENTRY alGetBuffer3f(ALuint buffer, ALenum param, ALfloat *valu
START_API_FUNC
{
ContextRef context{GetContextRef()};
if UNLIKELY(!context) return;
if(!context) [[unlikely]] return;
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock};
if UNLIKELY(LookupBuffer(device, buffer) == nullptr)
if(LookupBuffer(device, buffer) == nullptr) [[unlikely]]
context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else if UNLIKELY(!value1 || !value2 || !value3)
else if(!value1 || !value2 || !value3) [[unlikely]]
context->setError(AL_INVALID_VALUE, "NULL pointer");
else switch(param)
{
@ -1443,14 +1449,14 @@ START_API_FUNC
}
ContextRef context{GetContextRef()};
if UNLIKELY(!context) return;
if(!context) [[unlikely]] return;
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock};
if UNLIKELY(LookupBuffer(device, buffer) == nullptr)
if(LookupBuffer(device, buffer) == nullptr) [[unlikely]]
context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else if UNLIKELY(!values)
else if(!values) [[unlikely]]
context->setError(AL_INVALID_VALUE, "NULL pointer");
else switch(param)
{
@ -1465,14 +1471,14 @@ AL_API void AL_APIENTRY alGetBufferi(ALuint buffer, ALenum param, ALint *value)
START_API_FUNC
{
ContextRef context{GetContextRef()};
if UNLIKELY(!context) return;
if(!context) [[unlikely]] return;
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock};
ALbuffer *albuf = LookupBuffer(device, buffer);
if UNLIKELY(!albuf)
if(!albuf) [[unlikely]]
context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else if UNLIKELY(!value)
else if(!value) [[unlikely]]
context->setError(AL_INVALID_VALUE, "NULL pointer");
else switch(param)
{
@ -1522,13 +1528,13 @@ AL_API void AL_APIENTRY alGetBuffer3i(ALuint buffer, ALenum param, ALint *value1
START_API_FUNC
{
ContextRef context{GetContextRef()};
if UNLIKELY(!context) return;
if(!context) [[unlikely]] return;
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock};
if UNLIKELY(LookupBuffer(device, buffer) == nullptr)
if(LookupBuffer(device, buffer) == nullptr) [[unlikely]]
context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else if UNLIKELY(!value1 || !value2 || !value3)
else if(!value1 || !value2 || !value3) [[unlikely]]
context->setError(AL_INVALID_VALUE, "NULL pointer");
else switch(param)
{
@ -1560,14 +1566,14 @@ START_API_FUNC
}
ContextRef context{GetContextRef()};
if UNLIKELY(!context) return;
if(!context) [[unlikely]] return;
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock};
ALbuffer *albuf = LookupBuffer(device, buffer);
if UNLIKELY(!albuf)
if(!albuf) [[unlikely]]
context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else if UNLIKELY(!values)
else if(!values) [[unlikely]]
context->setError(AL_INVALID_VALUE, "NULL pointer");
else switch(param)
{
@ -1588,22 +1594,22 @@ AL_API void AL_APIENTRY alBufferCallbackSOFT(ALuint buffer, ALenum format, ALsiz
START_API_FUNC
{
ContextRef context{GetContextRef()};
if UNLIKELY(!context) return;
if(!context) [[unlikely]] return;
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock};
ALbuffer *albuf = LookupBuffer(device, buffer);
if UNLIKELY(!albuf)
if(!albuf) [[unlikely]]
context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else if UNLIKELY(freq < 1)
else if(freq < 1) [[unlikely]]
context->setError(AL_INVALID_VALUE, "Invalid sample rate %d", freq);
else if UNLIKELY(callback == nullptr)
else if(callback == nullptr) [[unlikely]]
context->setError(AL_INVALID_VALUE, "NULL callback");
else
{
auto usrfmt = DecomposeUserFormat(format);
if UNLIKELY(!usrfmt)
if(!usrfmt) [[unlikely]]
context->setError(AL_INVALID_ENUM, "Invalid format 0x%04x", format);
else
PrepareCallback(context.get(), albuf, freq, usrfmt->channels, usrfmt->type, callback,
@ -1616,14 +1622,14 @@ AL_API void AL_APIENTRY alGetBufferPtrSOFT(ALuint buffer, ALenum param, ALvoid *
START_API_FUNC
{
ContextRef context{GetContextRef()};
if UNLIKELY(!context) return;
if(!context) [[unlikely]] return;
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock};
ALbuffer *albuf = LookupBuffer(device, buffer);
if UNLIKELY(!albuf)
if(!albuf) [[unlikely]]
context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else if UNLIKELY(!value)
else if(!value) [[unlikely]]
context->setError(AL_INVALID_VALUE, "NULL pointer");
else switch(param)
{
@ -1644,13 +1650,13 @@ AL_API void AL_APIENTRY alGetBuffer3PtrSOFT(ALuint buffer, ALenum param, ALvoid
START_API_FUNC
{
ContextRef context{GetContextRef()};
if UNLIKELY(!context) return;
if(!context) [[unlikely]] return;
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock};
if UNLIKELY(LookupBuffer(device, buffer) == nullptr)
if(LookupBuffer(device, buffer) == nullptr) [[unlikely]]
context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else if UNLIKELY(!value1 || !value2 || !value3)
else if(!value1 || !value2 || !value3) [[unlikely]]
context->setError(AL_INVALID_VALUE, "NULL pointer");
else switch(param)
{
@ -1672,13 +1678,13 @@ START_API_FUNC
}
ContextRef context{GetContextRef()};
if UNLIKELY(!context) return;
if(!context) [[unlikely]] return;
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->BufferLock};
if UNLIKELY(LookupBuffer(device, buffer) == nullptr)
if(LookupBuffer(device, buffer) == nullptr) [[unlikely]]
context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer);
else if UNLIKELY(!values)
else if(!values) [[unlikely]]
context->setError(AL_INVALID_VALUE, "NULL pointer");
else switch(param)
{
@ -1763,7 +1769,7 @@ START_API_FUNC
continue;
const auto al_buffer = LookupBuffer(device, buffer);
if (!al_buffer)
if(!al_buffer) [[unlikely]]
{
ERR(EAX_PREFIX "Invalid buffer ID %u.\n", buffer);
return ALC_FALSE;
@ -1779,7 +1785,7 @@ START_API_FUNC
* buffer ID is specified multiple times in the provided list, it
* counts each instance as more memory that needs to fit in X-RAM.
*/
if(unlikely(std::numeric_limits<size_t>::max()-al_buffer->OriginalSize < total_needed))
if(std::numeric_limits<size_t>::max()-al_buffer->OriginalSize < total_needed) [[unlikely]]
{
context->setError(AL_OUT_OF_MEMORY, EAX_PREFIX "Buffer size overflow (%u + %zu)\n",
al_buffer->OriginalSize, total_needed);

View File

@ -269,7 +269,8 @@ const GUID EAX_RINGMODULATOR_EFFECT =
};
const GUID EAXCONTEXT_DEFAULTPRIMARYFXSLOTID = EAXPROPERTYID_EAX40_FXSlot0;
const GUID EAX40CONTEXT_DEFAULTPRIMARYFXSLOTID = EAXPROPERTYID_EAX40_FXSlot0;
const GUID EAX50CONTEXT_DEFAULTPRIMARYFXSLOTID = EAXPROPERTYID_EAX50_FXSlot0;
const EAX40ACTIVEFXSLOTS EAX40SOURCE_DEFAULTACTIVEFXSLOTID = EAX40ACTIVEFXSLOTS
{{

View File

@ -28,11 +28,14 @@ typedef struct _GUID {
std::uint8_t Data4[8];
} GUID;
#ifndef _SYS_GUID_OPERATOR_EQ_
#define _SYS_GUID_OPERATOR_EQ_
inline bool operator==(const GUID& lhs, const GUID& rhs) noexcept
{ return std::memcmp(&lhs, &rhs, sizeof(GUID)) == 0; }
inline bool operator!=(const GUID& lhs, const GUID& rhs) noexcept
{ return !(lhs == rhs); }
#endif // _SYS_GUID_OPERATOR_EQ_
#endif // GUID_DEFINED
@ -287,21 +290,19 @@ extern const GUID EAXPROPERTYID_EAX40_Context;
extern const GUID EAXPROPERTYID_EAX50_Context;
// EAX50
enum : unsigned long
{
HEADPHONES = 0,
SPEAKERS_2,
SPEAKERS_4,
SPEAKERS_5, // 5.1 speakers
SPEAKERS_6, // 6.1 speakers
SPEAKERS_7, // 7.1 speakers
};
constexpr auto HEADPHONES = 0UL;
constexpr auto SPEAKERS_2 = 1UL;
constexpr auto SPEAKERS_4 = 2UL;
constexpr auto SPEAKERS_5 = 3UL; // 5.1 speakers
constexpr auto SPEAKERS_6 = 4UL; // 6.1 speakers
constexpr auto SPEAKERS_7 = 5UL; // 7.1 speakers
constexpr auto EAXCONTEXT_MINSPEAKERCONFIG = HEADPHONES;
constexpr auto EAXCONTEXT_MAXSPEAKERCONFIG = SPEAKERS_7;
// EAX50
enum : unsigned long {
EAX_40 = 5, // EAX 4.0
EAX_50 = 6, // EAX 5.0
};
constexpr auto EAX_40 = 5UL; // EAX 4.0
constexpr auto EAX_50 = 6UL; // EAX 5.0
constexpr auto EAXCONTEXT_MINEAXSESSION = EAX_40;
constexpr auto EAXCONTEXT_MAXEAXSESSION = EAX_50;
@ -370,7 +371,8 @@ extern const GUID EAXPROPERTYID_EAX50_FXSlot2;
extern const GUID EAXPROPERTYID_EAX40_FXSlot3;
extern const GUID EAXPROPERTYID_EAX50_FXSlot3;
extern const GUID EAXCONTEXT_DEFAULTPRIMARYFXSLOTID;
extern const GUID EAX40CONTEXT_DEFAULTPRIMARYFXSLOTID;
extern const GUID EAX50CONTEXT_DEFAULTPRIMARYFXSLOTID;
enum EAXFXSLOT_PROPERTY : unsigned int {
EAXFXSLOT_PARAMETER = 0,

View File

@ -23,6 +23,7 @@ EaxCall::EaxCall(
ALvoid* property_buffer,
ALuint property_size)
: type_{type}, version_{0}, property_set_id_{EaxCallPropertySetId::none}
, is_deferred_{(property_id & deferred_flag) != 0}
, property_id_{property_id & ~deferred_flag}, property_source_id_{property_source_id}
, property_buffer_{property_buffer}, property_size_{property_size}
{
@ -150,7 +151,28 @@ EaxCall::EaxCall(
fail("EAX version out of range.");
}
if(!(property_id&deferred_flag))
switch(property_id)
{
case EAXCONTEXT_LASTERROR:
case EAXCONTEXT_SPEAKERCONFIG:
case EAXCONTEXT_EAXSESSION:
case EAXFXSLOT_NONE:
case EAXFXSLOT_ALLPARAMETERS:
case EAXFXSLOT_LOADEFFECT:
case EAXFXSLOT_VOLUME:
case EAXFXSLOT_LOCK:
case EAXFXSLOT_FLAGS:
case EAXFXSLOT_OCCLUSION:
case EAXFXSLOT_OCCLUSIONLFRATIO:
// EAX allow to set "defer" flag on immediate-only properties.
// If we don't clear our flag then "applyAllUpdates" in EAX context won't be called.
is_deferred_ = false;
break;
default:
break;
}
if(!is_deferred_)
{
if(property_set_id_ != EaxCallPropertySetId::fx_slot && property_id_ != 0)
{

View File

@ -32,6 +32,7 @@ public:
ALuint property_size);
bool is_get() const noexcept { return type_ == EaxCallType::get; }
bool is_deferred() const noexcept { return is_deferred_; }
int get_version() const noexcept { return version_; }
EaxCallPropertySetId get_property_set_id() const noexcept { return property_set_id_; }
ALuint get_property_id() const noexcept { return property_id_; }
@ -76,6 +77,7 @@ private:
int version_;
EaxFxSlotIndex fx_slot_index_;
EaxCallPropertySetId property_set_id_;
bool is_deferred_;
ALuint property_id_;
ALuint property_source_id_;

View File

@ -35,8 +35,8 @@ template<typename TException, typename TProps>
class EaxEffect4 : public EaxEffect
{
public:
EaxEffect4(ALenum type, const EaxCall& call)
: EaxEffect{type}, version_{clamp(call.get_version(), 4, 5)}
EaxEffect4(ALenum type, int eax_version)
: EaxEffect{type}, version_{clamp(eax_version, 4, 5)}
{}
void initialize()
@ -70,10 +70,10 @@ protected:
Props d; // Deferred.
}; // State
int version_;
Props props_;
State state4_;
State state5_;
int version_{};
Props props_{};
State state4_{};
State state5_{};
template<typename TValidator, typename TProperty>
static void defer(const EaxCall& call, TProperty& property)
@ -149,25 +149,25 @@ using EaxEffectUPtr = std::unique_ptr<EaxEffect>;
// Creates EAX4+ effect.
template<typename TEffect>
EaxEffectUPtr eax_create_eax4_effect(const EaxCall& call)
EaxEffectUPtr eax_create_eax4_effect(int eax_version)
{
auto effect = std::make_unique<TEffect>(call);
auto effect = std::make_unique<TEffect>(eax_version);
effect->initialize();
return effect;
}
EaxEffectUPtr eax_create_eax_null_effect();
EaxEffectUPtr eax_create_eax_chorus_effect(const EaxCall& call);
EaxEffectUPtr eax_create_eax_distortion_effect(const EaxCall& call);
EaxEffectUPtr eax_create_eax_echo_effect(const EaxCall& call);
EaxEffectUPtr eax_create_eax_flanger_effect(const EaxCall& call);
EaxEffectUPtr eax_create_eax_frequency_shifter_effect(const EaxCall& call);
EaxEffectUPtr eax_create_eax_vocal_morpher_effect(const EaxCall& call);
EaxEffectUPtr eax_create_eax_pitch_shifter_effect(const EaxCall& call);
EaxEffectUPtr eax_create_eax_ring_modulator_effect(const EaxCall& call);
EaxEffectUPtr eax_create_eax_auto_wah_effect(const EaxCall& call);
EaxEffectUPtr eax_create_eax_compressor_effect(const EaxCall& call);
EaxEffectUPtr eax_create_eax_equalizer_effect(const EaxCall& call);
EaxEffectUPtr eax_create_eax_reverb_effect(const EaxCall& call);
EaxEffectUPtr eax_create_eax_chorus_effect(int eax_version);
EaxEffectUPtr eax_create_eax_distortion_effect(int eax_version);
EaxEffectUPtr eax_create_eax_echo_effect(int eax_version);
EaxEffectUPtr eax_create_eax_flanger_effect(int eax_version);
EaxEffectUPtr eax_create_eax_frequency_shifter_effect(int eax_version);
EaxEffectUPtr eax_create_eax_vocal_morpher_effect(int eax_version);
EaxEffectUPtr eax_create_eax_pitch_shifter_effect(int eax_version);
EaxEffectUPtr eax_create_eax_ring_modulator_effect(int eax_version);
EaxEffectUPtr eax_create_eax_auto_wah_effect(int eax_version);
EaxEffectUPtr eax_create_eax_compressor_effect(int eax_version);
EaxEffectUPtr eax_create_eax_equalizer_effect(int eax_version);
EaxEffectUPtr eax_create_eax_reverb_effect(int eax_version);
#endif // !EAX_EFFECT_INCLUDED

View File

@ -6,17 +6,14 @@
#include <string>
EaxException::EaxException(
const char* context,
const char* message)
:
std::runtime_error{make_message(context, message)}
EaxException::EaxException(const char *context, const char *message)
: std::runtime_error{make_message(context, message)}
{
}
EaxException::~EaxException() = default;
std::string EaxException::make_message(
const char* context,
const char* message)
std::string EaxException::make_message(const char *context, const char *message)
{
const auto context_size = (context ? std::string::traits_type::length(context) : 0);
const auto has_contex = (context_size > 0);

View File

@ -6,19 +6,12 @@
#include <string>
class EaxException :
public std::runtime_error
{
class EaxException : public std::runtime_error {
static std::string make_message(const char *context, const char *message);
public:
EaxException(
const char* context,
const char* message);
private:
static std::string make_message(
const char* context,
const char* message);
EaxException(const char *context, const char *message);
~EaxException() override;
}; // EaxException

View File

@ -28,11 +28,9 @@ public:
} // namespace
void EaxFxSlots::initialize(
const EaxCall& call,
ALCcontext& al_context)
void EaxFxSlots::initialize(ALCcontext& al_context)
{
initialize_fx_slots(call, al_context);
initialize_fx_slots(al_context);
}
void EaxFxSlots::uninitialize() noexcept
@ -57,12 +55,6 @@ ALeffectslot& EaxFxSlots::get(EaxFxSlotIndex index)
return *fx_slots_[index.value()];
}
void EaxFxSlots::unlock_legacy() noexcept
{
fx_slots_[0]->eax_unlock_legacy();
fx_slots_[1]->eax_unlock_legacy();
}
[[noreturn]]
void EaxFxSlots::fail(
const char* message)
@ -70,16 +62,14 @@ void EaxFxSlots::fail(
throw EaxFxSlotsException{message};
}
void EaxFxSlots::initialize_fx_slots(
const EaxCall& call,
ALCcontext& al_context)
void EaxFxSlots::initialize_fx_slots(ALCcontext& al_context)
{
auto fx_slot_index = EaxFxSlotIndexValue{};
for (auto& fx_slot : fx_slots_)
{
fx_slot = eax_create_al_effect_slot(al_context);
fx_slot->eax_initialize(call, al_context, fx_slot_index);
fx_slot->eax_initialize(al_context, fx_slot_index);
fx_slot_index += 1;
}
}

View File

@ -14,9 +14,7 @@
class EaxFxSlots
{
public:
void initialize(
const EaxCall& call,
ALCcontext& al_context);
void initialize(ALCcontext& al_context);
void uninitialize() noexcept;
@ -33,9 +31,6 @@ public:
ALeffectslot& get(
EaxFxSlotIndex index);
void unlock_legacy() noexcept;
private:
using Items = std::array<EaxAlEffectSlotUPtr, EAX_MAX_FXSLOTS>;
@ -47,9 +42,7 @@ private:
static void fail(
const char* message);
void initialize_fx_slots(
const EaxCall& call,
ALCcontext& al_context);
void initialize_fx_slots(ALCcontext& al_context);
}; // EaxFxSlots

View File

@ -8,29 +8,19 @@
#include "core/logging.h"
void eax_log_exception(
const char* message) noexcept
void eax_log_exception(const char *message) noexcept
{
const auto exception_ptr = std::current_exception();
assert(exception_ptr);
if (message)
{
ERR("%s\n", message);
}
try
{
try {
std::rethrow_exception(exception_ptr);
}
catch (const std::exception& ex)
{
catch(const std::exception& ex) {
const auto ex_message = ex.what();
ERR("%s\n", ex_message);
ERR("%s %s\n", message ? message : "", ex_message);
}
catch (...)
{
ERR("%s\n", "Generic exception.");
catch(...) {
ERR("%s %s\n", message ? message : "", "Generic exception.");
}
}

View File

@ -6,12 +6,14 @@
#include <string>
#include <type_traits>
using EaxDirtyFlags = unsigned int;
struct EaxAlLowPassParam {
float gain;
float gain_hf;
};
void eax_log_exception(const char* message = nullptr) noexcept;
void eax_log_exception(const char *message) noexcept;
template<typename TException, typename TValue>
void eax_validate_range(

View File

@ -86,6 +86,7 @@ effect_exception::effect_exception(ALenum code, const char *msg, ...) : mErrorCo
setMessage(msg, args);
va_end(args);
}
effect_exception::~effect_exception() = default;
namespace {
@ -139,7 +140,7 @@ const EffectPropsItem *getEffectPropsItemByType(ALenum type)
auto iter = std::find_if(std::begin(EffectPropsList), std::end(EffectPropsList),
[type](const EffectPropsItem &item) noexcept -> bool
{ return item.Type == type; });
return (iter != std::end(EffectPropsList)) ? std::addressof(*iter) : nullptr;
return (iter != std::end(EffectPropsList)) ? al::to_address(iter) : nullptr;
}
void InitEffectParams(ALeffect *effect, ALenum type)
@ -166,14 +167,14 @@ bool EnsureEffects(ALCdevice *device, size_t needed)
while(needed > count)
{
if UNLIKELY(device->EffectList.size() >= 1<<25)
if(device->EffectList.size() >= 1<<25) [[unlikely]]
return false;
device->EffectList.emplace_back();
auto sublist = device->EffectList.end() - 1;
sublist->FreeMask = ~0_u64;
sublist->Effects = static_cast<ALeffect*>(al_calloc(alignof(ALeffect), sizeof(ALeffect)*64));
if UNLIKELY(!sublist->Effects)
if(!sublist->Effects) [[unlikely]]
{
device->EffectList.pop_back();
return false;
@ -219,10 +220,10 @@ inline ALeffect *LookupEffect(ALCdevice *device, ALuint id)
const size_t lidx{(id-1) >> 6};
const ALuint slidx{(id-1) & 0x3f};
if UNLIKELY(lidx >= device->EffectList.size())
if(lidx >= device->EffectList.size()) [[unlikely]]
return nullptr;
EffectSubList &sublist = device->EffectList[lidx];
if UNLIKELY(sublist.FreeMask & (1_u64 << slidx))
if(sublist.FreeMask & (1_u64 << slidx)) [[unlikely]]
return nullptr;
return sublist.Effects + slidx;
}
@ -233,11 +234,11 @@ AL_API void AL_APIENTRY alGenEffects(ALsizei n, ALuint *effects)
START_API_FUNC
{
ContextRef context{GetContextRef()};
if UNLIKELY(!context) return;
if(!context) [[unlikely]] return;
if UNLIKELY(n < 0)
if(n < 0) [[unlikely]]
context->setError(AL_INVALID_VALUE, "Generating %d effects", n);
if UNLIKELY(n <= 0) return;
if(n <= 0) [[unlikely]] return;
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->EffectLock};
@ -247,7 +248,7 @@ START_API_FUNC
return;
}
if LIKELY(n == 1)
if(n == 1) [[likely]]
{
/* Special handling for the easy and normal case. */
ALeffect *effect{AllocEffect(device)};
@ -273,11 +274,11 @@ AL_API void AL_APIENTRY alDeleteEffects(ALsizei n, const ALuint *effects)
START_API_FUNC
{
ContextRef context{GetContextRef()};
if UNLIKELY(!context) return;
if(!context) [[unlikely]] return;
if UNLIKELY(n < 0)
if(n < 0) [[unlikely]]
context->setError(AL_INVALID_VALUE, "Deleting %d effects", n);
if UNLIKELY(n <= 0) return;
if(n <= 0) [[unlikely]] return;
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->EffectLock};
@ -288,7 +289,7 @@ START_API_FUNC
const ALuint *effects_end = effects + n;
auto inveffect = std::find_if_not(effects, effects_end, validate_effect);
if UNLIKELY(inveffect != effects_end)
if(inveffect != effects_end) [[unlikely]]
{
context->setError(AL_INVALID_NAME, "Invalid effect ID %u", *inveffect);
return;
@ -308,7 +309,7 @@ AL_API ALboolean AL_APIENTRY alIsEffect(ALuint effect)
START_API_FUNC
{
ContextRef context{GetContextRef()};
if LIKELY(context)
if(context) [[likely]]
{
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->EffectLock};
@ -323,13 +324,13 @@ AL_API void AL_APIENTRY alEffecti(ALuint effect, ALenum param, ALint value)
START_API_FUNC
{
ContextRef context{GetContextRef()};
if UNLIKELY(!context) return;
if(!context) [[unlikely]] return;
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->EffectLock};
ALeffect *aleffect{LookupEffect(device, effect)};
if UNLIKELY(!aleffect)
if(!aleffect) [[unlikely]]
context->setError(AL_INVALID_NAME, "Invalid effect ID %u", effect);
else if(param == AL_EFFECT_TYPE)
{
@ -373,13 +374,13 @@ START_API_FUNC
}
ContextRef context{GetContextRef()};
if UNLIKELY(!context) return;
if(!context) [[unlikely]] return;
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->EffectLock};
ALeffect *aleffect{LookupEffect(device, effect)};
if UNLIKELY(!aleffect)
if(!aleffect) [[unlikely]]
context->setError(AL_INVALID_NAME, "Invalid effect ID %u", effect);
else try
{
@ -396,13 +397,13 @@ AL_API void AL_APIENTRY alEffectf(ALuint effect, ALenum param, ALfloat value)
START_API_FUNC
{
ContextRef context{GetContextRef()};
if UNLIKELY(!context) return;
if(!context) [[unlikely]] return;
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->EffectLock};
ALeffect *aleffect{LookupEffect(device, effect)};
if UNLIKELY(!aleffect)
if(!aleffect) [[unlikely]]
context->setError(AL_INVALID_NAME, "Invalid effect ID %u", effect);
else try
{
@ -419,13 +420,13 @@ AL_API void AL_APIENTRY alEffectfv(ALuint effect, ALenum param, const ALfloat *v
START_API_FUNC
{
ContextRef context{GetContextRef()};
if UNLIKELY(!context) return;
if(!context) [[unlikely]] return;
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->EffectLock};
ALeffect *aleffect{LookupEffect(device, effect)};
if UNLIKELY(!aleffect)
if(!aleffect) [[unlikely]]
context->setError(AL_INVALID_NAME, "Invalid effect ID %u", effect);
else try
{
@ -442,13 +443,13 @@ AL_API void AL_APIENTRY alGetEffecti(ALuint effect, ALenum param, ALint *value)
START_API_FUNC
{
ContextRef context{GetContextRef()};
if UNLIKELY(!context) return;
if(!context) [[unlikely]] return;
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->EffectLock};
const ALeffect *aleffect{LookupEffect(device, effect)};
if UNLIKELY(!aleffect)
if(!aleffect) [[unlikely]]
context->setError(AL_INVALID_NAME, "Invalid effect ID %u", effect);
else if(param == AL_EFFECT_TYPE)
*value = aleffect->type;
@ -474,13 +475,13 @@ START_API_FUNC
}
ContextRef context{GetContextRef()};
if UNLIKELY(!context) return;
if(!context) [[unlikely]] return;
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->EffectLock};
const ALeffect *aleffect{LookupEffect(device, effect)};
if UNLIKELY(!aleffect)
if(!aleffect) [[unlikely]]
context->setError(AL_INVALID_NAME, "Invalid effect ID %u", effect);
else try
{
@ -497,13 +498,13 @@ AL_API void AL_APIENTRY alGetEffectf(ALuint effect, ALenum param, ALfloat *value
START_API_FUNC
{
ContextRef context{GetContextRef()};
if UNLIKELY(!context) return;
if(!context) [[unlikely]] return;
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->EffectLock};
const ALeffect *aleffect{LookupEffect(device, effect)};
if UNLIKELY(!aleffect)
if(!aleffect) [[unlikely]]
context->setError(AL_INVALID_NAME, "Invalid effect ID %u", effect);
else try
{
@ -520,13 +521,13 @@ AL_API void AL_APIENTRY alGetEffectfv(ALuint effect, ALenum param, ALfloat *valu
START_API_FUNC
{
ContextRef context{GetContextRef()};
if UNLIKELY(!context) return;
if(!context) [[unlikely]] return;
ALCdevice *device{context->mALDevice.get()};
std::lock_guard<std::mutex> _{device->EffectLock};
const ALeffect *aleffect{LookupEffect(device, effect)};
if UNLIKELY(!aleffect)
if(!aleffect) [[unlikely]]
context->setError(AL_INVALID_NAME, "Invalid effect ID %u", effect);
else try
{

View File

@ -127,7 +127,7 @@ public:
class EaxAutoWahEffect final : public EaxEffect4<EaxAutoWahEffectException, EAXAUTOWAHPROPERTIES> {
public:
EaxAutoWahEffect(const EaxCall& call);
EaxAutoWahEffect(int eax_version);
private:
struct AttackTimeValidator {
@ -197,8 +197,8 @@ private:
bool commit_props(const Props& props) override;
}; // EaxAutoWahEffect
EaxAutoWahEffect::EaxAutoWahEffect(const EaxCall& call)
: EaxEffect4{AL_EFFECT_AUTOWAH, call}
EaxAutoWahEffect::EaxAutoWahEffect(int eax_version)
: EaxEffect4{AL_EFFECT_AUTOWAH, eax_version}
{}
void EaxAutoWahEffect::set_defaults(Props& props)
@ -310,9 +310,9 @@ bool EaxAutoWahEffect::commit_props(const Props& props)
} // namespace
EaxEffectUPtr eax_create_eax_auto_wah_effect(const EaxCall& call)
EaxEffectUPtr eax_create_eax_auto_wah_effect(int eax_version)
{
return eax_create_eax4_effect<EaxAutoWahEffect>(call);
return eax_create_eax4_effect<EaxAutoWahEffect>(eax_version);
}
#endif // ALSOFT_EAX

View File

@ -31,8 +31,8 @@ inline al::optional<ChorusWaveform> WaveformFromEnum(ALenum type)
{
switch(type)
{
case AL_CHORUS_WAVEFORM_SINUSOID: return al::make_optional(ChorusWaveform::Sinusoid);
case AL_CHORUS_WAVEFORM_TRIANGLE: return al::make_optional(ChorusWaveform::Triangle);
case AL_CHORUS_WAVEFORM_SINUSOID: return ChorusWaveform::Sinusoid;
case AL_CHORUS_WAVEFORM_TRIANGLE: return ChorusWaveform::Triangle;
}
return al::nullopt;
}
@ -149,7 +149,7 @@ void Chorus_getParamf(const EffectProps *props, ALenum param, float *val)
void Chorus_getParamfv(const EffectProps *props, ALenum param, float *vals)
{ Chorus_getParamf(props, param, vals); }
const EffectProps genDefaultChorusProps() noexcept
EffectProps genDefaultChorusProps() noexcept
{
EffectProps props{};
props.Chorus.Waveform = *WaveformFromEnum(AL_CHORUS_DEFAULT_WAVEFORM);
@ -433,8 +433,8 @@ public:
using typename Base::State;
using Base::defer;
EaxChorusFlangerEffect(const EaxCall& call)
: Base{Traits::efx_effect(), call}
EaxChorusFlangerEffect(int eax_version)
: Base{Traits::efx_effect(), eax_version}
{}
private:
@ -712,23 +712,23 @@ private:
}; // EaxChorusFlangerEffect
template<typename TTraits>
EaxEffectUPtr eax_create_eax_chorus_flanger_effect(const EaxCall& call)
EaxEffectUPtr eax_create_eax_chorus_flanger_effect(int eax_version)
{
return eax_create_eax4_effect<EaxChorusFlangerEffect<TTraits>>(call);
return eax_create_eax4_effect<EaxChorusFlangerEffect<TTraits>>(eax_version);
}
} // namespace
// ==========================================================================
EaxEffectUPtr eax_create_eax_chorus_effect(const EaxCall& call)
EaxEffectUPtr eax_create_eax_chorus_effect(int eax_version)
{
return eax_create_eax_chorus_flanger_effect<EaxChorusTraits>(call);
return eax_create_eax_chorus_flanger_effect<EaxChorusTraits>(eax_version);
}
EaxEffectUPtr eax_create_eax_flanger_effect(const EaxCall& call)
EaxEffectUPtr eax_create_eax_flanger_effect(int eax_version)
{
return eax_create_eax_chorus_flanger_effect<EaxFlangerTraits>(call);
return eax_create_eax_chorus_flanger_effect<EaxFlangerTraits>(eax_version);
}
#endif // ALSOFT_EAX

View File

@ -91,7 +91,7 @@ public:
class EaxCompressorEffect final : public EaxEffect4<EaxCompressorEffectException, EAXAGCCOMPRESSORPROPERTIES>
{
public:
EaxCompressorEffect(const EaxCall& call);
EaxCompressorEffect(int eax_version);
private:
struct OnOffValidator {
@ -122,8 +122,8 @@ private:
bool commit_props(const Props& props) override;
}; // EaxCompressorEffect
EaxCompressorEffect::EaxCompressorEffect(const EaxCall& call)
: EaxEffect4{AL_EFFECT_COMPRESSOR, call}
EaxCompressorEffect::EaxCompressorEffect(int eax_version)
: EaxEffect4{AL_EFFECT_COMPRESSOR, eax_version}
{}
void EaxCompressorEffect::set_defaults(Props& props)
@ -182,9 +182,9 @@ bool EaxCompressorEffect::commit_props(const Props& props)
} // namespace
EaxEffectUPtr eax_create_eax_compressor_effect(const EaxCall& call)
EaxEffectUPtr eax_create_eax_compressor_effect(int eax_version)
{
return eax_create_eax4_effect<EaxCompressorEffect>(call);
return eax_create_eax4_effect<EaxCompressorEffect>(eax_version);
}
#endif // ALSOFT_EAX

View File

@ -133,7 +133,7 @@ public:
class EaxDistortionEffect final : public EaxEffect4<EaxDistortionEffectException, EAXDISTORTIONPROPERTIES>
{
public:
EaxDistortionEffect(const EaxCall& call);
EaxDistortionEffect(int eax_version);
private:
struct EdgeValidator {
@ -216,8 +216,8 @@ private:
bool commit_props(const Props& props) override;
}; // EaxDistortionEffect
EaxDistortionEffect::EaxDistortionEffect(const EaxCall& call)
: EaxEffect4{AL_EFFECT_DISTORTION, call}
EaxDistortionEffect::EaxDistortionEffect(int eax_version)
: EaxEffect4{AL_EFFECT_DISTORTION, eax_version}
{}
void EaxDistortionEffect::set_defaults(Props& props)
@ -347,9 +347,9 @@ bool EaxDistortionEffect::commit_props(const Props& props)
} // namespace
EaxEffectUPtr eax_create_eax_distortion_effect(const EaxCall& call)
EaxEffectUPtr eax_create_eax_distortion_effect(int eax_version)
{
return eax_create_eax4_effect<EaxDistortionEffect>(call);
return eax_create_eax4_effect<EaxDistortionEffect>(eax_version);
}
#endif // ALSOFT_EAX

View File

@ -130,7 +130,7 @@ public:
class EaxEchoEffect final : public EaxEffect4<EaxEchoEffectException, EAXECHOPROPERTIES>
{
public:
EaxEchoEffect(const EaxCall& call);
EaxEchoEffect(int eax_version);
private:
struct DelayValidator {
@ -213,8 +213,8 @@ private:
bool commit_props(const Props& props) override;
}; // EaxEchoEffect
EaxEchoEffect::EaxEchoEffect(const EaxCall& call)
: EaxEffect4{AL_EFFECT_ECHO, call}
EaxEchoEffect::EaxEchoEffect(int eax_version)
: EaxEffect4{AL_EFFECT_ECHO, eax_version}
{}
void EaxEchoEffect::set_defaults(Props& props)
@ -344,9 +344,9 @@ bool EaxEchoEffect::commit_props(const Props& props)
} // namespace
EaxEffectUPtr eax_create_eax_echo_effect(const EaxCall& call)
EaxEffectUPtr eax_create_eax_echo_effect(int eax_version)
{
return eax_create_eax4_effect<EaxEchoEffect>(call);
return eax_create_eax4_effect<EaxEchoEffect>(eax_version);
}
#endif // ALSOFT_EAX

View File

@ -1,16 +1,12 @@
#include "config.h"
#ifdef ALSOFT_EAX
#include <cassert>
#include "AL/efx.h"
#include "effects.h"
#include <cassert>
#include "AL/efx.h"
EaxEffectUPtr eax_create_eax_effect(ALenum al_effect_type, const EaxCall& call)
EaxEffectUPtr eax_create_eax_effect(ALenum al_effect_type, int eax_version)
{
#define EAX_PREFIX "[EAX_MAKE_EAX_EFFECT] "
@ -20,40 +16,40 @@ EaxEffectUPtr eax_create_eax_effect(ALenum al_effect_type, const EaxCall& call)
return eax_create_eax_null_effect();
case AL_EFFECT_CHORUS:
return eax_create_eax_chorus_effect(call);
return eax_create_eax_chorus_effect(eax_version);
case AL_EFFECT_DISTORTION:
return eax_create_eax_distortion_effect(call);
return eax_create_eax_distortion_effect(eax_version);
case AL_EFFECT_ECHO:
return eax_create_eax_echo_effect(call);
return eax_create_eax_echo_effect(eax_version);
case AL_EFFECT_FLANGER:
return eax_create_eax_flanger_effect(call);
return eax_create_eax_flanger_effect(eax_version);
case AL_EFFECT_FREQUENCY_SHIFTER:
return eax_create_eax_frequency_shifter_effect(call);
return eax_create_eax_frequency_shifter_effect(eax_version);
case AL_EFFECT_VOCAL_MORPHER:
return eax_create_eax_vocal_morpher_effect(call);
return eax_create_eax_vocal_morpher_effect(eax_version);
case AL_EFFECT_PITCH_SHIFTER:
return eax_create_eax_pitch_shifter_effect(call);
return eax_create_eax_pitch_shifter_effect(eax_version);
case AL_EFFECT_RING_MODULATOR:
return eax_create_eax_ring_modulator_effect(call);
return eax_create_eax_ring_modulator_effect(eax_version);
case AL_EFFECT_AUTOWAH:
return eax_create_eax_auto_wah_effect(call);
return eax_create_eax_auto_wah_effect(eax_version);
case AL_EFFECT_COMPRESSOR:
return eax_create_eax_compressor_effect(call);
return eax_create_eax_compressor_effect(eax_version);
case AL_EFFECT_EQUALIZER:
return eax_create_eax_equalizer_effect(call);
return eax_create_eax_equalizer_effect(eax_version);
case AL_EFFECT_EAXREVERB:
return eax_create_eax_reverb_effect(call);
return eax_create_eax_reverb_effect(eax_version);
default:
assert(false && "Unsupported AL effect type.");

Some files were not shown because too many files have changed in this diff Show More