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

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


+ 5
- 11
RtAudio.h View File

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



+ 10
- 36
rtaudio_c.cpp View File

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


+ 1
- 0
rtaudio_c.h View File

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


+ 83
- 7
tests/apinames.cpp View File

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

Loading…
Cancel
Save