summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephen Sinclair <radarsat1@gmail.com>2018-10-16 15:01:30 +0200
committerStephen Sinclair <radarsat1@gmail.com>2018-10-16 15:01:30 +0200
commit4690b26068191afa44dc8a872e250990acb1d175 (patch)
tree0b6b1e4d752315423590e134f72e844760601540
parent154627e9e314bc99d5f29a1675bdbd7a7c80c612 (diff)
parent6919d3578769202957d1ba320ff458e959935e05 (diff)
Merge remote-tracking branch 'upstream/pr/136'
-rw-r--r--CMakeLists.txt1
-rw-r--r--Makefile.am1
-rw-r--r--RtAudio.cpp84
-rw-r--r--RtAudio.h32
-rw-r--r--rtaudio_c.cpp57
-rw-r--r--rtaudio_c.h8
-rw-r--r--tests/CMakeLists.txt3
-rw-r--r--tests/Makefile.am5
-rw-r--r--tests/apinames.cpp157
9 files changed, 299 insertions, 49 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 77ffdb0..d220bc7 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -216,6 +216,7 @@ if(BUILD_SHARED_LIBS)
# Set compile-time definitions
target_compile_definitions(rtaudio PRIVATE ${API_DEFS})
+ target_compile_definitions(rtaudio PRIVATE RTAUDIO_EXPORT)
target_link_libraries(rtaudio ${LINKLIBS})
endif()
diff --git a/Makefile.am b/Makefile.am
index f83007c..2a05035 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -6,6 +6,7 @@ endif
AM_CXXFLAGS = @visibility@
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_SOURCES = \
%D%/RtAudio.cpp \
diff --git a/RtAudio.cpp b/RtAudio.cpp
index 77bd4b6..5bc1055 100644
--- a/RtAudio.cpp
+++ b/RtAudio.cpp
@@ -98,39 +98,95 @@ std::string RtAudio :: getVersion( void )
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__)
- apis.push_back( UNIX_JACK );
+ RtAudio::UNIX_JACK,
#endif
#if defined(__LINUX_PULSE__)
- apis.push_back( LINUX_PULSE );
+ RtAudio::LINUX_PULSE,
#endif
#if defined(__LINUX_ALSA__)
- apis.push_back( LINUX_ALSA );
+ RtAudio::LINUX_ALSA,
#endif
#if defined(__LINUX_OSS__)
- apis.push_back( LINUX_OSS );
+ RtAudio::LINUX_OSS,
#endif
#if defined(__WINDOWS_ASIO__)
- apis.push_back( WINDOWS_ASIO );
+ RtAudio::WINDOWS_ASIO,
#endif
#if defined(__WINDOWS_WASAPI__)
- apis.push_back( WINDOWS_WASAPI );
+ RtAudio::WINDOWS_WASAPI,
#endif
#if defined(__WINDOWS_DS__)
- apis.push_back( WINDOWS_DS );
+ RtAudio::WINDOWS_DS,
#endif
#if defined(__MACOSX_CORE__)
- apis.push_back( MACOSX_CORE );
+ RtAudio::MACOSX_CORE,
#endif
#if defined(__RTAUDIO_DUMMY__)
- apis.push_back( RTAUDIO_DUMMY );
+ RtAudio::RTAUDIO_DUMMY,
#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 )
diff --git a/RtAudio.h b/RtAudio.h
index f37b9c2..d6038db 100644
--- a/RtAudio.h
+++ b/RtAudio.h
@@ -48,7 +48,11 @@
#define RTAUDIO_VERSION "5.0.0"
#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
#if __GNUC__ >= 4
#define RTAUDIO_DLL_PUBLIC __attribute__( (visibility( "default" )) )
@@ -285,7 +289,8 @@ 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. */
};
//! 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 );
+ //! 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 constructor performs minor initialization tasks. An exception
diff --git a/rtaudio_c.cpp b/rtaudio_c.cpp
index 699d2ce..da3ab24 100644
--- a/rtaudio_c.cpp
+++ b/rtaudio_c.cpp
@@ -15,40 +15,33 @@ 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" 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) {
if (audio->has_error) {
diff --git a/rtaudio_c.h b/rtaudio_c.h
index 05015a9..a366117 100644
--- a/rtaudio_c.h
+++ b/rtaudio_c.h
@@ -2,8 +2,12 @@
#define RTAUDIO_C_H
#if defined(RTAUDIO_EXPORT)
+#if defined _WIN32 || defined __CYGWIN__
#define RTAUDIOAPI __declspec(dllexport)
#else
+#define RTAUDIOAPI __attribute__((visibility("default")))
+#endif
+#else
#define RTAUDIOAPI //__declspec(dllimport)
#endif
@@ -64,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
@@ -102,6 +107,9 @@ typedef struct rtaudio *rtaudio_t;
RTAUDIOAPI const char *rtaudio_version(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);
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 5c08f6d..5847027 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -20,6 +20,9 @@ target_link_libraries(record ${LIBRTAUDIO} ${LINKLIBS})
add_executable(duplex duplex.cpp)
target_link_libraries(duplex ${LIBRTAUDIO} ${LINKLIBS})
+add_executable(apinames apinames.cpp)
+target_link_libraries(apinames ${LIBRTAUDIO} ${LINKLIBS})
+
add_executable(testall testall.cpp)
target_link_libraries(testall ${LIBRTAUDIO} ${LINKLIBS})
diff --git a/tests/Makefile.am b/tests/Makefile.am
index e39fdde..c8159da 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -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)
@@ -18,6 +18,9 @@ record_LDADD = $(top_builddir)/librtaudio.la
duplex_SOURCES = duplex.cpp
duplex_LDADD = $(top_builddir)/librtaudio.la
+apinames_SOURCES = apinames.cpp
+apinames_LDADD = $(top_builddir)/librtaudio.la
+
testall_SOURCES = testall.cpp
testall_LDADD = $(top_builddir)/librtaudio.la
diff --git a/tests/apinames.cpp b/tests/apinames.cpp
new file mode 100644
index 0000000..c270764
--- /dev/null
+++ b/tests/apinames.cpp
@@ -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();
+}