@@ -216,6 +216,7 @@ if(BUILD_SHARED_LIBS) | |||||
# Set compile-time definitions | # Set compile-time definitions | ||||
target_compile_definitions(rtaudio PRIVATE ${API_DEFS}) | target_compile_definitions(rtaudio PRIVATE ${API_DEFS}) | ||||
target_compile_definitions(rtaudio PRIVATE RTAUDIO_EXPORT) | |||||
target_link_libraries(rtaudio ${LINKLIBS}) | target_link_libraries(rtaudio ${LINKLIBS}) | ||||
endif() | endif() | ||||
@@ -6,6 +6,7 @@ endif | |||||
AM_CXXFLAGS = @visibility@ | AM_CXXFLAGS = @visibility@ | ||||
lib_LTLIBRARIES = %D%/librtaudio.la | lib_LTLIBRARIES = %D%/librtaudio.la | ||||
%C%_librtaudio_la_CXXFLAGS = -DRTAUDIO_EXPORT | |||||
%C%_librtaudio_la_LDFLAGS = -no-undefined -export-dynamic -version-info @SO_VERSION@ | %C%_librtaudio_la_LDFLAGS = -no-undefined -export-dynamic -version-info @SO_VERSION@ | ||||
%C%_librtaudio_la_SOURCES = \ | %C%_librtaudio_la_SOURCES = \ | ||||
%D%/RtAudio.cpp \ | %D%/RtAudio.cpp \ | ||||
@@ -98,39 +98,95 @@ std::string RtAudio :: getVersion( void ) | |||||
return RTAUDIO_VERSION; | return RTAUDIO_VERSION; | ||||
} | } | ||||
void RtAudio :: getCompiledApi( std::vector<RtAudio::Api> &apis ) | |||||
{ | |||||
apis.clear(); | |||||
// Define API names and display names. | |||||
// Must be in same order as API enum. | |||||
extern "C" { | |||||
const char* rtaudio_api_names[][2] = { | |||||
{ "unspecified" , "Unknown" }, | |||||
{ "alsa" , "ALSA" }, | |||||
{ "pulse" , "Pulse" }, | |||||
{ "oss" , "OpenSoundSystem" }, | |||||
{ "jack" , "Jack" }, | |||||
{ "core" , "CoreAudio" }, | |||||
{ "wasapi" , "WASAPI" }, | |||||
{ "asio" , "ASIO" }, | |||||
{ "ds" , "DirectSound" }, | |||||
{ "dummy" , "Dummy" }, | |||||
}; | |||||
const unsigned int rtaudio_num_api_names = | |||||
sizeof(rtaudio_api_names)/sizeof(rtaudio_api_names[0]); | |||||
// The order here will control the order of RtAudio's API search in | |||||
// the constructor. | |||||
// The order here will control the order of RtAudio's API search in | |||||
// the constructor. | |||||
extern "C" const RtAudio::Api rtaudio_compiled_apis[] = { | |||||
#if defined(__UNIX_JACK__) | #if defined(__UNIX_JACK__) | ||||
apis.push_back( UNIX_JACK ); | |||||
RtAudio::UNIX_JACK, | |||||
#endif | #endif | ||||
#if defined(__LINUX_PULSE__) | #if defined(__LINUX_PULSE__) | ||||
apis.push_back( LINUX_PULSE ); | |||||
RtAudio::LINUX_PULSE, | |||||
#endif | #endif | ||||
#if defined(__LINUX_ALSA__) | #if defined(__LINUX_ALSA__) | ||||
apis.push_back( LINUX_ALSA ); | |||||
RtAudio::LINUX_ALSA, | |||||
#endif | #endif | ||||
#if defined(__LINUX_OSS__) | #if defined(__LINUX_OSS__) | ||||
apis.push_back( LINUX_OSS ); | |||||
RtAudio::LINUX_OSS, | |||||
#endif | #endif | ||||
#if defined(__WINDOWS_ASIO__) | #if defined(__WINDOWS_ASIO__) | ||||
apis.push_back( WINDOWS_ASIO ); | |||||
RtAudio::WINDOWS_ASIO, | |||||
#endif | #endif | ||||
#if defined(__WINDOWS_WASAPI__) | #if defined(__WINDOWS_WASAPI__) | ||||
apis.push_back( WINDOWS_WASAPI ); | |||||
RtAudio::WINDOWS_WASAPI, | |||||
#endif | #endif | ||||
#if defined(__WINDOWS_DS__) | #if defined(__WINDOWS_DS__) | ||||
apis.push_back( WINDOWS_DS ); | |||||
RtAudio::WINDOWS_DS, | |||||
#endif | #endif | ||||
#if defined(__MACOSX_CORE__) | #if defined(__MACOSX_CORE__) | ||||
apis.push_back( MACOSX_CORE ); | |||||
RtAudio::MACOSX_CORE, | |||||
#endif | #endif | ||||
#if defined(__RTAUDIO_DUMMY__) | #if defined(__RTAUDIO_DUMMY__) | ||||
apis.push_back( RTAUDIO_DUMMY ); | |||||
RtAudio::RTAUDIO_DUMMY, | |||||
#endif | #endif | ||||
RtAudio::UNSPECIFIED, | |||||
}; | |||||
extern "C" const unsigned int rtaudio_num_compiled_apis = | |||||
sizeof(rtaudio_compiled_apis)/sizeof(rtaudio_compiled_apis[0])-1; | |||||
} | |||||
// This is a compile-time check that rtaudio_num_api_names == RtAudio::NUM_APIS. | |||||
// If the build breaks here, check that they match. | |||||
template<bool b> class StaticAssert { private: StaticAssert() {} }; | |||||
template<> class StaticAssert<true>{ public: StaticAssert() {} }; | |||||
class StaticAssertions { StaticAssertions() { | |||||
StaticAssert<rtaudio_num_api_names == RtAudio::NUM_APIS>(); | |||||
}}; | |||||
void RtAudio :: getCompiledApi( std::vector<RtAudio::Api> &apis ) | |||||
{ | |||||
apis = std::vector<RtAudio::Api>(rtaudio_compiled_apis, | |||||
rtaudio_compiled_apis + rtaudio_num_compiled_apis); | |||||
} | |||||
std::string RtAudio :: getApiName( RtAudio::Api api ) | |||||
{ | |||||
if (api < 0 || api >= RtAudio::NUM_APIS) | |||||
return ""; | |||||
return rtaudio_api_names[api][0]; | |||||
} | |||||
std::string RtAudio :: getApiDisplayName( RtAudio::Api api ) | |||||
{ | |||||
if (api < 0 || api >= RtAudio::NUM_APIS) | |||||
return "Unknown"; | |||||
return rtaudio_api_names[api][1]; | |||||
} | |||||
RtAudio::Api RtAudio :: getCompiledApiByName( const std::string &name ) | |||||
{ | |||||
unsigned int i=0; | |||||
for (i = 0; i < rtaudio_num_compiled_apis; ++i) | |||||
if (name == rtaudio_api_names[rtaudio_compiled_apis[i]][0]) | |||||
return rtaudio_compiled_apis[i]; | |||||
return RtAudio::UNSPECIFIED; | |||||
} | } | ||||
void RtAudio :: openRtApi( RtAudio::Api api ) | void RtAudio :: openRtApi( RtAudio::Api api ) | ||||
@@ -48,7 +48,11 @@ | |||||
#define RTAUDIO_VERSION "5.0.0" | #define RTAUDIO_VERSION "5.0.0" | ||||
#if defined _WIN32 || defined __CYGWIN__ | #if defined _WIN32 || defined __CYGWIN__ | ||||
#define RTAUDIO_DLL_PUBLIC | |||||
#if defined(RTAUDIO_EXPORT) | |||||
#define RTAUDIO_DLL_PUBLIC __declspec(dllexport) | |||||
#else | |||||
#define RTAUDIO_DLL_PUBLIC | |||||
#endif | |||||
#else | #else | ||||
#if __GNUC__ >= 4 | #if __GNUC__ >= 4 | ||||
#define RTAUDIO_DLL_PUBLIC __attribute__( (visibility( "default" )) ) | #define RTAUDIO_DLL_PUBLIC __attribute__( (visibility( "default" )) ) | ||||
@@ -285,7 +289,8 @@ class RTAUDIO_DLL_PUBLIC RtAudio | |||||
WINDOWS_WASAPI, /*!< The Microsoft WASAPI API. */ | WINDOWS_WASAPI, /*!< The Microsoft WASAPI API. */ | ||||
WINDOWS_ASIO, /*!< The Steinberg Audio Stream I/O API. */ | WINDOWS_ASIO, /*!< The Steinberg Audio Stream I/O API. */ | ||||
WINDOWS_DS, /*!< The Microsoft Direct Sound API. */ | WINDOWS_DS, /*!< The Microsoft Direct Sound API. */ | ||||
RTAUDIO_DUMMY /*!< A compilable but non-functional API. */ | |||||
RTAUDIO_DUMMY, /*!< A compilable but non-functional API. */ | |||||
NUM_APIS /*!< Number of values in this enum. */ | |||||
}; | }; | ||||
//! The public device information structure for returning queried values. | //! The public device information structure for returning queried values. | ||||
@@ -397,6 +402,29 @@ class RTAUDIO_DLL_PUBLIC RtAudio | |||||
*/ | */ | ||||
static void getCompiledApi( std::vector<RtAudio::Api> &apis ); | static void getCompiledApi( std::vector<RtAudio::Api> &apis ); | ||||
//! Return the name of a specified compiled audio API. | |||||
/*! | |||||
This obtains a short lower-case name used for identification purposes. | |||||
This value is guaranteed to remain identical across library versions. | |||||
If the API is unknown, this function will return the empty string. | |||||
*/ | |||||
static std::string getApiName( RtAudio::Api api ); | |||||
//! Return the display name of a specified compiled audio API. | |||||
/*! | |||||
This obtains a long name used for display purposes. | |||||
If the API is unknown, this function will return the empty string. | |||||
*/ | |||||
static std::string getApiDisplayName( RtAudio::Api api ); | |||||
//! Return the compiled audio API having the given name. | |||||
/*! | |||||
A case insensitive comparison will check the specified name | |||||
against the list of compiled APIs, and return the one which | |||||
matches. On failure, the function returns UNSPECIFIED. | |||||
*/ | |||||
static RtAudio::Api getCompiledApiByName( const std::string &name ); | |||||
//! The class constructor. | //! The class constructor. | ||||
/*! | /*! | ||||
The constructor performs minor initialization tasks. An exception | The constructor performs minor initialization tasks. An exception | ||||
@@ -15,40 +15,33 @@ struct rtaudio { | |||||
char errmsg[MAX_ERROR_MESSAGE_LENGTH]; | char errmsg[MAX_ERROR_MESSAGE_LENGTH]; | ||||
}; | }; | ||||
static const rtaudio_api_t compiled_api[] = { | |||||
#if defined(__UNIX_JACK__) | |||||
RTAUDIO_API_UNIX_JACK, | |||||
#endif | |||||
#if defined(__LINUX_ALSA__) | |||||
RTAUDIO_API_LINUX_ALSA, | |||||
#endif | |||||
#if defined(__LINUX_PULSE__) | |||||
RTAUDIO_API_LINUX_PULSE, | |||||
#endif | |||||
#if defined(__LINUX_OSS__) | |||||
RTAUDIO_API_LINUX_OSS, | |||||
#endif | |||||
#if defined(__WINDOWS_ASIO__) | |||||
RTAUDIO_API_WINDOWS_ASIO, | |||||
#endif | |||||
#if defined(__WINDOWS_WASAPI__) | |||||
RTAUDIO_API_WINDOWS_WASAPI, | |||||
#endif | |||||
#if defined(__WINDOWS_DS__) | |||||
RTAUDIO_API_WINDOWS_DS, | |||||
#endif | |||||
#if defined(__MACOSX_CORE__) | |||||
RTAUDIO_API_MACOSX_CORE, | |||||
#endif | |||||
#if defined(__RTAUDIO_DUMMY__) | |||||
RTAUDIO_API_DUMMY, | |||||
#endif | |||||
RTAUDIO_API_UNSPECIFIED, | |||||
}; | |||||
const char *rtaudio_version() { return RTAUDIO_VERSION; } | const char *rtaudio_version() { return RTAUDIO_VERSION; } | ||||
const rtaudio_api_t *rtaudio_compiled_api() { return compiled_api; } | |||||
extern "C" const rtaudio_api_t rtaudio_compiled_apis[]; // casting from RtAudio::Api[] | |||||
extern "C" const unsigned int rtaudio_num_compiled_apis; | |||||
const rtaudio_api_t *rtaudio_compiled_api() { return rtaudio_compiled_apis; } | |||||
extern "C" const char* rtaudio_api_names[][2]; | |||||
const char *rtaudio_api_name(rtaudio_api_t api) { | |||||
if (api < 0 || api >= RTAUDIO_API_NUM) | |||||
return NULL; | |||||
return rtaudio_api_names[api][0]; | |||||
} | |||||
const char *rtaudio_api_display_name(rtaudio_api_t api) | |||||
{ | |||||
if (api < 0 || api >= RTAUDIO_API_NUM) | |||||
return "Unknown"; | |||||
return rtaudio_api_names[api][1]; | |||||
} | |||||
rtaudio_api_t rtaudio_compiled_api_by_name(const char *name) { | |||||
RtAudio::Api api = RtAudio::UNSPECIFIED; | |||||
if (name) { | |||||
api = RtAudio::getCompiledApiByName(name); | |||||
} | |||||
return (rtaudio_api_t)api; | |||||
} | |||||
const char *rtaudio_error(rtaudio_t audio) { | const char *rtaudio_error(rtaudio_t audio) { | ||||
if (audio->has_error) { | if (audio->has_error) { | ||||
@@ -2,8 +2,12 @@ | |||||
#define RTAUDIO_C_H | #define RTAUDIO_C_H | ||||
#if defined(RTAUDIO_EXPORT) | #if defined(RTAUDIO_EXPORT) | ||||
#if defined _WIN32 || defined __CYGWIN__ | |||||
#define RTAUDIOAPI __declspec(dllexport) | #define RTAUDIOAPI __declspec(dllexport) | ||||
#else | #else | ||||
#define RTAUDIOAPI __attribute__((visibility("default"))) | |||||
#endif | |||||
#else | |||||
#define RTAUDIOAPI //__declspec(dllimport) | #define RTAUDIOAPI //__declspec(dllimport) | ||||
#endif | #endif | ||||
@@ -64,6 +68,7 @@ typedef enum rtaudio_api { | |||||
RTAUDIO_API_WINDOWS_ASIO, | RTAUDIO_API_WINDOWS_ASIO, | ||||
RTAUDIO_API_WINDOWS_DS, | RTAUDIO_API_WINDOWS_DS, | ||||
RTAUDIO_API_DUMMY, | RTAUDIO_API_DUMMY, | ||||
RTAUDIO_API_NUM, | |||||
} rtaudio_api_t; | } rtaudio_api_t; | ||||
#define NUM_SAMPLE_RATES 16 | #define NUM_SAMPLE_RATES 16 | ||||
@@ -102,6 +107,9 @@ typedef struct rtaudio *rtaudio_t; | |||||
RTAUDIOAPI const char *rtaudio_version(void); | RTAUDIOAPI const char *rtaudio_version(void); | ||||
RTAUDIOAPI const rtaudio_api_t *rtaudio_compiled_api(void); | RTAUDIOAPI const rtaudio_api_t *rtaudio_compiled_api(void); | ||||
RTAUDIOAPI const char *rtaudio_api_name(rtaudio_api_t api); | |||||
RTAUDIOAPI const char *rtaudio_api_display_name(rtaudio_api_t api); | |||||
RTAUDIOAPI rtaudio_api_t rtaudio_compiled_api_by_name(const char *name); | |||||
RTAUDIOAPI const char *rtaudio_error(rtaudio_t audio); | RTAUDIOAPI const char *rtaudio_error(rtaudio_t audio); | ||||
@@ -20,6 +20,9 @@ target_link_libraries(record ${LIBRTAUDIO} ${LINKLIBS}) | |||||
add_executable(duplex duplex.cpp) | add_executable(duplex duplex.cpp) | ||||
target_link_libraries(duplex ${LIBRTAUDIO} ${LINKLIBS}) | target_link_libraries(duplex ${LIBRTAUDIO} ${LINKLIBS}) | ||||
add_executable(apinames apinames.cpp) | |||||
target_link_libraries(apinames ${LIBRTAUDIO} ${LINKLIBS}) | |||||
add_executable(testall testall.cpp) | add_executable(testall testall.cpp) | ||||
target_link_libraries(testall ${LIBRTAUDIO} ${LINKLIBS}) | target_link_libraries(testall ${LIBRTAUDIO} ${LINKLIBS}) | ||||
@@ -1,5 +1,5 @@ | |||||
noinst_PROGRAMS = audioprobe playsaw playraw record duplex testall teststops | |||||
noinst_PROGRAMS = audioprobe playsaw playraw record duplex apinames testall teststops | |||||
AM_CXXFLAGS = -Wall -I$(top_srcdir) | AM_CXXFLAGS = -Wall -I$(top_srcdir) | ||||
@@ -18,6 +18,9 @@ record_LDADD = $(top_builddir)/librtaudio.la | |||||
duplex_SOURCES = duplex.cpp | duplex_SOURCES = duplex.cpp | ||||
duplex_LDADD = $(top_builddir)/librtaudio.la | duplex_LDADD = $(top_builddir)/librtaudio.la | ||||
apinames_SOURCES = apinames.cpp | |||||
apinames_LDADD = $(top_builddir)/librtaudio.la | |||||
testall_SOURCES = testall.cpp | testall_SOURCES = testall.cpp | ||||
testall_LDADD = $(top_builddir)/librtaudio.la | testall_LDADD = $(top_builddir)/librtaudio.la | ||||
@@ -0,0 +1,157 @@ | |||||
/******************************************/ | |||||
/* | |||||
apinames.cpp | |||||
by Jean Pierre Cimalando, 2018. | |||||
This program tests parts of RtAudio related | |||||
to API names, the conversion from name to API | |||||
and vice-versa. | |||||
*/ | |||||
/******************************************/ | |||||
#include "RtAudio.h" | |||||
#include <cctype> | |||||
#include <cstdlib> | |||||
#include <iostream> | |||||
int test_cpp() { | |||||
std::vector<RtAudio::Api> apis; | |||||
RtAudio::getCompiledApi( apis ); | |||||
// ensure the known APIs return valid names | |||||
std::cout << "API names by identifier (C++):\n"; | |||||
for ( size_t i = 0; i < apis.size() ; ++i ) { | |||||
const std::string name = RtAudio::getApiName(apis[i]); | |||||
if (name.empty()) { | |||||
std::cout << "Invalid name for API " << (int)apis[i] << "\n"; | |||||
exit(1); | |||||
} | |||||
const std::string displayName = RtAudio::getApiDisplayName(apis[i]); | |||||
if (displayName.empty()) { | |||||
std::cout << "Invalid display name for API " << (int)apis[i] << "\n"; | |||||
exit(1); | |||||
} | |||||
std::cout << "* " << (int)apis[i] << " '" << name << "': '" << displayName << "'\n"; | |||||
} | |||||
// ensure unknown APIs return the empty string | |||||
{ | |||||
const std::string name = RtAudio::getApiName((RtAudio::Api)-1); | |||||
if (!name.empty()) { | |||||
std::cout << "Bad string for invalid API '" << name << "'\n"; | |||||
exit(1); | |||||
} | |||||
const std::string displayName = RtAudio::getApiDisplayName((RtAudio::Api)-1); | |||||
if (displayName!="Unknown") { | |||||
std::cout << "Bad display string for invalid API '" << displayName << "'\n"; | |||||
exit(1); | |||||
} | |||||
} | |||||
// try getting API identifier by name | |||||
std::cout << "API identifiers by name (C++):\n"; | |||||
for ( size_t i = 0; i < apis.size() ; ++i ) { | |||||
std::string name = RtAudio::getApiName(apis[i]); | |||||
if ( RtAudio::getCompiledApiByName(name) != apis[i] ) { | |||||
std::cout << "Bad identifier for API '" << name << "'\n"; | |||||
exit( 1 ); | |||||
} | |||||
std::cout << "* '" << name << "': " << (int)apis[i] << "\n"; | |||||
for ( size_t j = 0; j < name.size(); ++j ) | |||||
name[j] = (j & 1) ? toupper(name[j]) : tolower(name[j]); | |||||
RtAudio::Api api = RtAudio::getCompiledApiByName(name); | |||||
if ( api != RtAudio::UNSPECIFIED ) { | |||||
std::cout << "Identifier " << (int)api << " for invalid API '" << name << "'\n"; | |||||
exit( 1 ); | |||||
} | |||||
} | |||||
// try getting an API identifier by unknown name | |||||
{ | |||||
RtAudio::Api api; | |||||
api = RtAudio::getCompiledApiByName(""); | |||||
if ( api != RtAudio::UNSPECIFIED ) { | |||||
std::cout << "Bad identifier for unknown API name\n"; | |||||
exit( 1 ); | |||||
} | |||||
} | |||||
return 0; | |||||
} | |||||
#include "rtaudio_c.h" | |||||
int test_c() { | |||||
const rtaudio_api_t *apis = rtaudio_compiled_api(); | |||||
// ensure the known APIs return valid names | |||||
std::cout << "API names by identifier (C):\n"; | |||||
for ( size_t i = 0; apis[i] != RTAUDIO_API_UNSPECIFIED; ++i) { | |||||
const std::string name = rtaudio_api_name(apis[i]); | |||||
if (name.empty()) { | |||||
std::cout << "Invalid name for API " << (int)apis[i] << "\n"; | |||||
exit(1); | |||||
} | |||||
const std::string displayName = rtaudio_api_display_name(apis[i]); | |||||
if (displayName.empty()) { | |||||
std::cout << "Invalid display name for API " << (int)apis[i] << "\n"; | |||||
exit(1); | |||||
} | |||||
std::cout << "* " << (int)apis[i] << " '" << name << "': '" << displayName << "'\n"; | |||||
} | |||||
// ensure unknown APIs return the empty string | |||||
{ | |||||
const char *s = rtaudio_api_name((rtaudio_api_t)-1); | |||||
const std::string name(s?s:""); | |||||
if (!name.empty()) { | |||||
std::cout << "Bad string for invalid API '" << name << "'\n"; | |||||
exit(1); | |||||
} | |||||
s = rtaudio_api_display_name((rtaudio_api_t)-1); | |||||
const std::string displayName(s?s:""); | |||||
if (displayName!="Unknown") { | |||||
std::cout << "Bad display string for invalid API '" << displayName << "'\n"; | |||||
exit(1); | |||||
} | |||||
} | |||||
// try getting API identifier by name | |||||
std::cout << "API identifiers by name (C):\n"; | |||||
for ( size_t i = 0; apis[i] != RTAUDIO_API_UNSPECIFIED ; ++i ) { | |||||
const char *s = rtaudio_api_name(apis[i]); | |||||
std::string name(s?s:""); | |||||
if ( rtaudio_compiled_api_by_name(name.c_str()) != apis[i] ) { | |||||
std::cout << "Bad identifier for API '" << name << "'\n"; | |||||
exit( 1 ); | |||||
} | |||||
std::cout << "* '" << name << "': " << (int)apis[i] << "\n"; | |||||
for ( size_t j = 0; j < name.size(); ++j ) | |||||
name[j] = (j & 1) ? toupper(name[j]) : tolower(name[j]); | |||||
rtaudio_api_t api = rtaudio_compiled_api_by_name(name.c_str()); | |||||
if ( api != RTAUDIO_API_UNSPECIFIED ) { | |||||
std::cout << "Identifier " << (int)api << " for invalid API '" << name << "'\n"; | |||||
exit( 1 ); | |||||
} | |||||
} | |||||
// try getting an API identifier by unknown name | |||||
{ | |||||
rtaudio_api_t api; | |||||
api = rtaudio_compiled_api_by_name(""); | |||||
if ( api != RTAUDIO_API_UNSPECIFIED ) { | |||||
std::cout << "Bad identifier for unknown API name\n"; | |||||
exit( 1 ); | |||||
} | |||||
} | |||||
return 0; | |||||
} | |||||
int main() | |||||
{ | |||||
test_cpp(); | |||||
test_c(); | |||||
} |