@@ -98,57 +98,76 @@ std::string RtAudio :: getVersion( void ) | |||||
return RTAUDIO_VERSION; | return RTAUDIO_VERSION; | ||||
} | } | ||||
// Define API names. | |||||
// TODO: replace with initializer list in C++11. | |||||
// 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 order here will control the order of RtAudio's API search in | ||||
// the constructor. | // the constructor. | ||||
// Have to maintain a separate list of API enum identifiers since map | |||||
// doesn't preserve insertion order. | |||||
static std::pair< RtAudio::ApiNameMap, std::vector<RtAudio::Api> > init_ApiNames() | |||||
{ | |||||
RtAudio::ApiNameMap names; | |||||
std::vector<RtAudio::Api> apis; | |||||
RtAudio::Api rtaudio_compiled_apis[] = { | |||||
#if defined(__UNIX_JACK__) | #if defined(__UNIX_JACK__) | ||||
names["jack"] = std::pair<RtAudio::Api, std::string>(RtAudio::UNIX_JACK, "Jack"); | |||||
apis.push_back(RtAudio::UNIX_JACK); | |||||
RtAudio::UNIX_JACK, | |||||
#endif | #endif | ||||
#if defined(__LINUX_PULSE__) | #if defined(__LINUX_PULSE__) | ||||
names["pulse"] = std::pair<RtAudio::Api, std::string>(RtAudio::LINUX_PULSE, "Pulse"); | |||||
apis.push_back(RtAudio::LINUX_PULSE); | |||||
RtAudio::LINUX_PULSE, | |||||
#endif | #endif | ||||
#if defined(__LINUX_ALSA__) | #if defined(__LINUX_ALSA__) | ||||
names["alsa"] = std::pair<RtAudio::Api, std::string>(RtAudio::LINUX_ALSA, "ALSA"); | |||||
apis.push_back(RtAudio::LINUX_ALSA); | |||||
RtAudio::LINUX_ALSA, | |||||
#endif | #endif | ||||
#if defined(__LINUX_OSS__) | #if defined(__LINUX_OSS__) | ||||
names["oss"] = std::pair<RtAudio::Api, std::string>(RtAudio::LINUX_OSS, "OSS"); | |||||
apis.push_back(RtAudio::LINUX_OSS); | |||||
RtAudio::LINUX_OSS, | |||||
#endif | #endif | ||||
#if defined(__WINDOWS_ASIO__) | #if defined(__WINDOWS_ASIO__) | ||||
names["asio"] = std::pair<RtAudio::Api, std::string>(RtAudio::WINDOWS_ASIO, "ASIO"); | |||||
apis.push_back(RtAudio::WINDOWS_ASIO); | |||||
RtAudio::WINDOWS_ASIO, | |||||
#endif | #endif | ||||
#if defined(__WINDOWS_WASAPI__) | #if defined(__WINDOWS_WASAPI__) | ||||
names["wasapi"] = std::pair<RtAudio::Api, std::string>(RtAudio::WINDOWS_WASAPI, "WASAPI"); | |||||
apis.push_back(RtAudio::WINDOWS_WASAPI); | |||||
RtAudio::WINDOWS_WASAPI, | |||||
#endif | #endif | ||||
#if defined(__WINDOWS_DS__) | #if defined(__WINDOWS_DS__) | ||||
names["ds"] = std::pair<RtAudio::Api, std::string>(RtAudio::WINDOWS_DS, "DirectSound"); | |||||
apis.push_back(RtAudio::WINDOWS_DS); | |||||
RtAudio::WINDOWS_DS, | |||||
#endif | #endif | ||||
#if defined(__MACOSX_CORE__) | #if defined(__MACOSX_CORE__) | ||||
names["core"] = std::pair<RtAudio::Api, std::string>(RtAudio::MACOSX_CORE, "CoreAudio"); | |||||
apis.push_back(RtAudio::MACOSX_CORE); | |||||
RtAudio::MACOSX_CORE, | |||||
#endif | #endif | ||||
#if defined(__RTAUDIO_DUMMY__) | #if defined(__RTAUDIO_DUMMY__) | ||||
names["dummy"] = std::pair<RtAudio::Api, std::string>(RtAudio::RTAUDIO_DUMMY, "Dummy"); | |||||
apis.push_back(RtAudio::RTAUDIO_DUMMY); | |||||
RtAudio::RTAUDIO_DUMMY, | |||||
#endif | #endif | ||||
return std::make_pair(names, apis); | |||||
RtAudio::UNSPECIFIED, | |||||
}; | |||||
const unsigned int rtaudio_num_compiled_apis = | |||||
sizeof(rtaudio_compiled_apis)/sizeof(rtaudio_compiled_apis[0])-1; | |||||
} | } | ||||
const RtAudio::ApiNameMap RtAudio::apiNames(init_ApiNames().first); | |||||
const std::vector<RtAudio::Api> RtAudio::compiledApis(init_ApiNames().second); | |||||
// TODO: replace this with something nicer (C++11) | |||||
static const std::vector<RtAudio::Api> init_compiledApis() { | |||||
std::vector<RtAudio::Api> apis; | |||||
for (unsigned int i=0; i<rtaudio_num_compiled_apis; i++) | |||||
apis.push_back(rtaudio_compiled_apis[i]); | |||||
return apis; | |||||
} | |||||
const std::vector<RtAudio::Api> RtAudio::compiledApis(init_compiledApis()); | |||||
// 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 ) | void RtAudio :: getCompiledApi( std::vector<RtAudio::Api> &apis ) | ||||
{ | { | ||||
@@ -160,32 +179,32 @@ const std::vector<RtAudio::Api>& RtAudio :: getCompiledApi() | |||||
return compiledApis; | return compiledApis; | ||||
} | } | ||||
static const std::string unknown_api_name = ""; | |||||
static const std::string unknown_api_display_name = "Unknown"; | |||||
const std::string& RtAudio :: getCompiledApiName( RtAudio::Api api ) | |||||
const std::string RtAudio :: getCompiledApiName( RtAudio::Api api ) | |||||
{ | { | ||||
ApiNameMap::const_iterator it; | |||||
for (it = apiNames.begin(); it != apiNames.end(); it++) | |||||
if (it->second.first == api) | |||||
return it->first; | |||||
return unknown_api_name; | |||||
if (api < 0 || api > RtAudio::NUM_APIS | |||||
|| (std::find(RtAudio::compiledApis.begin(), | |||||
RtAudio::compiledApis.end(), api) == RtAudio::compiledApis.end())) | |||||
return ""; | |||||
return rtaudio_api_names[api][0]; | |||||
} | } | ||||
const std::string& RtAudio :: getCompiledApiDisplayName( RtAudio::Api api ) | |||||
const std::string RtAudio :: getCompiledApiDisplayName( RtAudio::Api api ) | |||||
{ | { | ||||
ApiNameMap::const_iterator it; | |||||
for (it = apiNames.begin(); it != apiNames.end(); it++) | |||||
if (it->second.first == api) | |||||
return it->second.second; | |||||
return unknown_api_display_name; | |||||
if (api < 0 || api > RtAudio::NUM_APIS | |||||
|| (std::find(RtAudio::compiledApis.begin(), | |||||
RtAudio::compiledApis.end(), api) == RtAudio::compiledApis.end())) | |||||
return "Unknown"; | |||||
return rtaudio_api_names[api][1]; | |||||
} | } | ||||
RtAudio::Api RtAudio :: getCompiledApiByName( const std::string &name ) | RtAudio::Api RtAudio :: getCompiledApiByName( const std::string &name ) | ||||
{ | { | ||||
if (apiNames.find(name) == apiNames.end()) | |||||
return RtAudio::UNSPECIFIED; | |||||
return apiNames.at(name).first; | |||||
unsigned int i=0; | |||||
std::vector<RtAudio::Api>::const_iterator it; | |||||
for (it = compiledApis.begin(); it != compiledApis.end(); ++it, ++i) | |||||
if (name == rtaudio_api_names[*it][0]) | |||||
return *it; | |||||
return RtAudio::UNSPECIFIED; | |||||
} | } | ||||
void RtAudio :: openRtApi( RtAudio::Api api ) | void RtAudio :: openRtApi( RtAudio::Api api ) | ||||
@@ -61,7 +61,6 @@ | |||||
#include <vector> | #include <vector> | ||||
#include <stdexcept> | #include <stdexcept> | ||||
#include <iostream> | #include <iostream> | ||||
#include <map> | |||||
/*! \typedef typedef unsigned long RtAudioFormat; | /*! \typedef typedef unsigned long RtAudioFormat; | ||||
\brief RtAudio data format type. | \brief RtAudio data format type. | ||||
@@ -286,12 +285,10 @@ 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. */ | |||||
}; | }; | ||||
//! Map string identifiers for APIs to enum identifiers and display names | |||||
typedef std::map< std::string, std::pair<RtAudio::Api, std::string> > ApiNameMap; | |||||
//! The public device information structure for returning queried values. | //! The public device information structure for returning queried values. | ||||
struct DeviceInfo { | struct DeviceInfo { | ||||
bool probed; /*!< true if the device capabilities were successfully probed. */ | bool probed; /*!< true if the device capabilities were successfully probed. */ | ||||
@@ -407,7 +404,7 @@ class RTAUDIO_DLL_PUBLIC RtAudio | |||||
the enumerated list values. Note that there can be more than one | the enumerated list values. Note that there can be more than one | ||||
API compiled for certain operating systems. | API compiled for certain operating systems. | ||||
*/ | */ | ||||
static const std::vector<RtAudio::Api>& getCompiledApi(); | |||||
static const std::vector<RtAudio::Api>& getCompiledApis(); | |||||
//! Return the name of a specified compiled audio API. | //! Return the name of a specified compiled audio API. | ||||
/*! | /*! | ||||
@@ -416,7 +413,7 @@ class RTAUDIO_DLL_PUBLIC RtAudio | |||||
If the API is unknown or not compiled, this function will return | If the API is unknown or not compiled, this function will return | ||||
the empty string. | the empty string. | ||||
*/ | */ | ||||
static const std::string& getCompiledApiName( RtAudio::Api api ); | |||||
static const std::string getCompiledApiName( RtAudio::Api api ); | |||||
//! Return the display name of a specified compiled audio API. | //! Return the display name of a specified compiled audio API. | ||||
/*! | /*! | ||||
@@ -424,7 +421,7 @@ class RTAUDIO_DLL_PUBLIC RtAudio | |||||
If the API is unknown or not compiled, this function will return | If the API is unknown or not compiled, this function will return | ||||
the empty string. | the empty string. | ||||
*/ | */ | ||||
static const std::string& getCompiledApiDisplayName( RtAudio::Api api ); | |||||
static const std::string getCompiledApiDisplayName( RtAudio::Api api ); | |||||
//! Return the compiled audio API having the given name. | //! Return the compiled audio API having the given name. | ||||
/*! | /*! | ||||
@@ -618,9 +615,6 @@ class RTAUDIO_DLL_PUBLIC RtAudio | |||||
protected: | protected: | ||||
//! Storage for API name map | |||||
static const ApiNameMap apiNames; | |||||
//! Storage for compiled API list | //! Storage for compiled API list | ||||
static const std::vector<RtAudio::Api> compiledApis; | static const std::vector<RtAudio::Api> compiledApis; | ||||
@@ -15,50 +15,24 @@ 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" 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_compiled_api_name(rtaudio_api_t api) { | const char *rtaudio_compiled_api_name(rtaudio_api_t api) { | ||||
const std::string &name = RtAudio::getCompiledApiName((RtAudio::Api)api); | |||||
return name.empty() ? NULL : name.c_str(); | |||||
if (api < 0 || api >= RTAUDIO_API_NUM) | |||||
return NULL; | |||||
return rtaudio_api_names[api][0]; | |||||
} | } | ||||
const char *rtaudio_compiled_api_display_name(rtaudio_api_t api) | const char *rtaudio_compiled_api_display_name(rtaudio_api_t api) | ||||
{ | { | ||||
const std::string &name = RtAudio::getCompiledApiDisplayName((RtAudio::Api)api); | |||||
return name.empty() ? NULL : name.c_str(); | |||||
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_t rtaudio_compiled_api_by_name(const char *name) { | ||||
@@ -68,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 | ||||
@@ -14,19 +14,19 @@ | |||||
#include <cstdlib> | #include <cstdlib> | ||||
#include <iostream> | #include <iostream> | ||||
int main() { | |||||
int test_cpp() { | |||||
std::vector<RtAudio::Api> apis; | std::vector<RtAudio::Api> apis; | ||||
RtAudio::getCompiledApi( apis ); | RtAudio::getCompiledApi( apis ); | ||||
// ensure the known APIs return valid names | // ensure the known APIs return valid names | ||||
std::cout << "API names by identifier:\n"; | |||||
std::cout << "API names by identifier (C++):\n"; | |||||
for ( size_t i = 0; i < apis.size() ; ++i ) { | for ( size_t i = 0; i < apis.size() ; ++i ) { | ||||
const std::string &name = RtAudio::getCompiledApiName(apis[i]); | |||||
const std::string name = RtAudio::getCompiledApiName(apis[i]); | |||||
if (name.empty()) { | if (name.empty()) { | ||||
std::cerr << "Invalid name for API " << (int)apis[i] << "\n"; | std::cerr << "Invalid name for API " << (int)apis[i] << "\n"; | ||||
exit(1); | exit(1); | ||||
} | } | ||||
const std::string &displayName = RtAudio::getCompiledApiDisplayName(apis[i]); | |||||
const std::string displayName = RtAudio::getCompiledApiDisplayName(apis[i]); | |||||
if (displayName.empty()) { | if (displayName.empty()) { | ||||
std::cerr << "Invalid display name for API " << (int)apis[i] << "\n"; | std::cerr << "Invalid display name for API " << (int)apis[i] << "\n"; | ||||
exit(1); | exit(1); | ||||
@@ -36,12 +36,12 @@ int main() { | |||||
// ensure unknown APIs return the empty string | // ensure unknown APIs return the empty string | ||||
{ | { | ||||
const std::string &name = RtAudio::getCompiledApiName((RtAudio::Api)-1); | |||||
const std::string name = RtAudio::getCompiledApiName((RtAudio::Api)-1); | |||||
if (!name.empty()) { | if (!name.empty()) { | ||||
std::cerr << "Bad string for invalid API '" << name << "'\n"; | std::cerr << "Bad string for invalid API '" << name << "'\n"; | ||||
exit(1); | exit(1); | ||||
} | } | ||||
const std::string &displayName = RtAudio::getCompiledApiDisplayName((RtAudio::Api)-1); | |||||
const std::string displayName = RtAudio::getCompiledApiDisplayName((RtAudio::Api)-1); | |||||
if (displayName!="Unknown") { | if (displayName!="Unknown") { | ||||
std::cerr << "Bad display string for invalid API '" << displayName << "'\n"; | std::cerr << "Bad display string for invalid API '" << displayName << "'\n"; | ||||
exit(1); | exit(1); | ||||
@@ -49,7 +49,7 @@ int main() { | |||||
} | } | ||||
// try getting API identifier by name | // try getting API identifier by name | ||||
std::cout << "API identifiers by name:\n"; | |||||
std::cout << "API identifiers by name (C++):\n"; | |||||
for ( size_t i = 0; i < apis.size() ; ++i ) { | for ( size_t i = 0; i < apis.size() ; ++i ) { | ||||
std::string name = RtAudio::getCompiledApiName(apis[i]); | std::string name = RtAudio::getCompiledApiName(apis[i]); | ||||
if ( RtAudio::getCompiledApiByName(name) != apis[i] ) { | if ( RtAudio::getCompiledApiByName(name) != apis[i] ) { | ||||
@@ -79,3 +79,79 @@ int main() { | |||||
return 0; | 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_compiled_api_name(apis[i]); | |||||
if (name.empty()) { | |||||
std::cerr << "Invalid name for API " << (int)apis[i] << "\n"; | |||||
exit(1); | |||||
} | |||||
const std::string displayName = rtaudio_compiled_api_display_name(apis[i]); | |||||
if (displayName.empty()) { | |||||
std::cerr << "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_compiled_api_name((rtaudio_api_t)-1); | |||||
const std::string name(s?s:""); | |||||
if (!name.empty()) { | |||||
std::cerr << "Bad string for invalid API '" << name << "'\n"; | |||||
exit(1); | |||||
} | |||||
s = rtaudio_compiled_api_display_name((rtaudio_api_t)-1); | |||||
const std::string displayName(s?s:""); | |||||
if (displayName!="Unknown") { | |||||
std::cerr << "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_compiled_api_name(apis[i]); | |||||
std::string name(s?s:""); | |||||
if ( rtaudio_compiled_api_by_name(name.c_str()) != apis[i] ) { | |||||
std::cerr << "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::cerr << "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::cerr << "Bad identifier for unknown API name\n"; | |||||
exit( 1 ); | |||||
} | |||||
} | |||||
return 0; | |||||
} | |||||
int main() | |||||
{ | |||||
test_cpp(); | |||||
test_c(); | |||||
} |