Browse Source

Fix api name functions for C, replace map with array.

tags/5.1.0
Stephen Sinclair 6 years ago
parent
commit
e92130e9e1
5 changed files with 165 additions and 101 deletions
  1. +66
    -47
      RtAudio.cpp
  2. +5
    -11
      RtAudio.h
  3. +10
    -36
      rtaudio_c.cpp
  4. +1
    -0
      rtaudio_c.h
  5. +83
    -7
      tests/apinames.cpp

+ 66
- 47
RtAudio.cpp View File

@@ -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 )


+ 5
- 11
RtAudio.h View File

@@ -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;




+ 10
- 36
rtaudio_c.cpp View File

@@ -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) {


+ 1
- 0
rtaudio_c.h View File

@@ -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


+ 83
- 7
tests/apinames.cpp View File

@@ -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();
}

Loading…
Cancel
Save