@@ -98,57 +98,76 @@ std::string RtAudio :: getVersion( void ) | |||
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 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__) | |||
names["jack"] = std::pair<RtAudio::Api, std::string>(RtAudio::UNIX_JACK, "Jack"); | |||
apis.push_back(RtAudio::UNIX_JACK); | |||
RtAudio::UNIX_JACK, | |||
#endif | |||
#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 | |||
#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 | |||
#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 | |||
#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 | |||
#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 | |||
#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 | |||
#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 | |||
#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 | |||
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 ) | |||
{ | |||
@@ -160,32 +179,32 @@ const std::vector<RtAudio::Api>& RtAudio :: getCompiledApi() | |||
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 ) | |||
{ | |||
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 ) | |||
@@ -61,7 +61,6 @@ | |||
#include <vector> | |||
#include <stdexcept> | |||
#include <iostream> | |||
#include <map> | |||
/*! \typedef typedef unsigned long RtAudioFormat; | |||
\brief RtAudio data format type. | |||
@@ -286,12 +285,10 @@ class RTAUDIO_DLL_PUBLIC RtAudio | |||
WINDOWS_WASAPI, /*!< The Microsoft WASAPI API. */ | |||
WINDOWS_ASIO, /*!< The Steinberg Audio Stream I/O 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. | |||
struct DeviceInfo { | |||
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 | |||
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. | |||
/*! | |||
@@ -416,7 +413,7 @@ class RTAUDIO_DLL_PUBLIC RtAudio | |||
If the API is unknown or not compiled, this function will return | |||
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. | |||
/*! | |||
@@ -424,7 +421,7 @@ class RTAUDIO_DLL_PUBLIC RtAudio | |||
If the API is unknown or not compiled, this function will return | |||
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. | |||
/*! | |||
@@ -618,9 +615,6 @@ class RTAUDIO_DLL_PUBLIC RtAudio | |||
protected: | |||
//! Storage for API name map | |||
static const ApiNameMap apiNames; | |||
//! Storage for compiled API list | |||
static const std::vector<RtAudio::Api> compiledApis; | |||
@@ -15,50 +15,24 @@ struct rtaudio { | |||
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 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 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 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) { | |||
@@ -68,6 +68,7 @@ typedef enum rtaudio_api { | |||
RTAUDIO_API_WINDOWS_ASIO, | |||
RTAUDIO_API_WINDOWS_DS, | |||
RTAUDIO_API_DUMMY, | |||
RTAUDIO_API_NUM, | |||
} rtaudio_api_t; | |||
#define NUM_SAMPLE_RATES 16 | |||
@@ -14,19 +14,19 @@ | |||
#include <cstdlib> | |||
#include <iostream> | |||
int main() { | |||
int test_cpp() { | |||
std::vector<RtAudio::Api> apis; | |||
RtAudio::getCompiledApi( apis ); | |||
// 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 ) { | |||
const std::string &name = RtAudio::getCompiledApiName(apis[i]); | |||
const std::string name = RtAudio::getCompiledApiName(apis[i]); | |||
if (name.empty()) { | |||
std::cerr << "Invalid name for API " << (int)apis[i] << "\n"; | |||
exit(1); | |||
} | |||
const std::string &displayName = RtAudio::getCompiledApiDisplayName(apis[i]); | |||
const std::string displayName = RtAudio::getCompiledApiDisplayName(apis[i]); | |||
if (displayName.empty()) { | |||
std::cerr << "Invalid display name for API " << (int)apis[i] << "\n"; | |||
exit(1); | |||
@@ -36,12 +36,12 @@ int main() { | |||
// 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()) { | |||
std::cerr << "Bad string for invalid API '" << name << "'\n"; | |||
exit(1); | |||
} | |||
const std::string &displayName = RtAudio::getCompiledApiDisplayName((RtAudio::Api)-1); | |||
const std::string displayName = RtAudio::getCompiledApiDisplayName((RtAudio::Api)-1); | |||
if (displayName!="Unknown") { | |||
std::cerr << "Bad display string for invalid API '" << displayName << "'\n"; | |||
exit(1); | |||
@@ -49,7 +49,7 @@ int main() { | |||
} | |||
// 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 ) { | |||
std::string name = RtAudio::getCompiledApiName(apis[i]); | |||
if ( RtAudio::getCompiledApiByName(name) != apis[i] ) { | |||
@@ -79,3 +79,79 @@ int main() { | |||
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(); | |||
} |