Use a map for API names
authorStephen Sinclair <radarsat1@gmail.com>
Wed, 8 Aug 2018 15:55:39 +0000 (11:55 -0400)
committerStephen Sinclair <radarsat1@gmail.com>
Wed, 8 Aug 2018 15:55:39 +0000 (11:55 -0400)
RtAudio.cpp
RtAudio.h
tests/CMakeLists.txt
tests/apinames.cpp

index 728b4a3b34b9c5c975b7b3bd496d3bbc082f64da..7b7c8efd3701a76aece071013885a43d96cb5dc6 100644 (file)
@@ -98,180 +98,91 @@ std::string RtAudio :: getVersion( void )
   return RTAUDIO_VERSION;
 }
 
-void RtAudio :: getCompiledApi( std::vector<RtAudio::Api> &apis )
-{
-  apis.clear();
-
-  // The order here will control the order of RtAudio's API search in
-  // the constructor.
+// Define API names.
+// TODO: replace with initializer list in C++11.
+// 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;
 #if defined(__UNIX_JACK__)
-  apis.push_back( UNIX_JACK );
+  names["jack"] = std::pair<RtAudio::Api, std::string>(RtAudio::UNIX_JACK, "Jack");
+  apis.push_back(RtAudio::UNIX_JACK);
 #endif
 #if defined(__LINUX_PULSE__)
-  apis.push_back( LINUX_PULSE );
+  names["pulse"] = std::pair<RtAudio::Api, std::string>(RtAudio::LINUX_PULSE, "Pulse");
+  apis.push_back(RtAudio::LINUX_PULSE);
 #endif
 #if defined(__LINUX_ALSA__)
-  apis.push_back( LINUX_ALSA );
+  names["alsa"] = std::pair<RtAudio::Api, std::string>(RtAudio::LINUX_ALSA, "ALSA");
+  apis.push_back(RtAudio::LINUX_ALSA);
 #endif
 #if defined(__LINUX_OSS__)
-  apis.push_back( LINUX_OSS );
+  names["oss"] = std::pair<RtAudio::Api, std::string>(RtAudio::LINUX_OSS, "OSS");
+  apis.push_back(RtAudio::LINUX_OSS);
 #endif
 #if defined(__WINDOWS_ASIO__)
-  apis.push_back( WINDOWS_ASIO );
+  names["asio"] = std::pair<RtAudio::Api, std::string>(RtAudio::WINDOWS_ASIO, "ASIO");
+  apis.push_back(RtAudio::WINDOWS_ASIO);
 #endif
 #if defined(__WINDOWS_WASAPI__)
-  apis.push_back( WINDOWS_WASAPI );
+  names["wasapi"] = std::pair<RtAudio::Api, std::string>(RtAudio::WINDOWS_WASAPI, "WASAPI");
+  apis.push_back(RtAudio::WINDOWS_WASAPI);
 #endif
 #if defined(__WINDOWS_DS__)
-  apis.push_back( WINDOWS_DS );
+  names["ds"] = std::pair<RtAudio::Api, std::string>(RtAudio::WINDOWS_DS, "DirectSound");
+  apis.push_back(RtAudio::WINDOWS_DS);
 #endif
 #if defined(__MACOSX_CORE__)
-  apis.push_back( MACOSX_CORE );
+  names["core"] = std::pair<RtAudio::Api, std::string>(RtAudio::MACOSX_CORE, "CoreAudio");
+  apis.push_back(RtAudio::MACOSX_CORE);
 #endif
 #if defined(__RTAUDIO_DUMMY__)
-  apis.push_back( RTAUDIO_DUMMY );
+  names["dummy"] = std::pair<RtAudio::Api, std::string>(RtAudio::RTAUDIO_DUMMY, "Dummy");
+  apis.push_back(RtAudio::RTAUDIO_DUMMY);
 #endif
+  return std::make_pair(names, apis);
 }
 
-const std::string &RtAudio :: getCompiledApiName( RtAudio::Api api )
+const RtAudio::ApiNameMap RtAudio::apiNames(init_ApiNames().first);
+const std::vector<RtAudio::Api> RtAudio::compiledApis(init_ApiNames().second);
+
+void RtAudio :: getCompiledApi( std::vector<RtAudio::Api> &apis )
 {
-#if defined(__UNIX_JACK__)
-  if ( api == UNIX_JACK ) {
-    static std::string name( "jack" );
-    return name;
-  }
-#endif
-#if defined(__LINUX_PULSE__)
-  if ( api == LINUX_PULSE ) {
-    static std::string name( "pulse" );
-    return name;
-  }
-#endif
-#if defined(__LINUX_ALSA__)
-  if ( api == LINUX_ALSA ) {
-    static std::string name( "alsa" );
-    return name;
-  }
-#endif
-#if defined(__LINUX_OSS__)
-  if ( api == LINUX_OSS ) {
-    static std::string name( "oss" );
-    return name;
-  }
-#endif
-#if defined(__WINDOWS_ASIO__)
-  if ( api == WINDOWS_ASIO ) {
-    static std::string name( "asio" );
-    return name;
-  }
-#endif
-#if defined(__WINDOWS_WASAPI__)
-  if ( api == WINDOWS_WASAPI ) {
-    static std::string name( "wasapi" );
-    return name;
-  }
-#endif
-#if defined(__WINDOWS_DS__)
-  if ( api == WINDOWS_DS ) {
-    static std::string name( "ds" );
-    return name;
-  }
-#endif
-#if defined(__MACOSX_CORE__)
-  if ( api == MACOSX_CORE ) {
-    static std::string name( "core" );
-    return name;
-  }
-#endif
-#if defined(__RTAUDIO_DUMMY__)
-  if ( api == RTAUDIO_DUMMY ) {
-    static std::string name( "dummy" );
-    return name;
-  }
-#endif
-  static std::string name;
-  return name;
+  apis = compiledApis;
 }
 
-const std::string &RtAudio :: getCompiledApiDisplayName( RtAudio::Api api )
+const std::vector<RtAudio::Api>& RtAudio :: getCompiledApi()
 {
-#if defined(__UNIX_JACK__)
-  if ( api == UNIX_JACK ) {
-    static std::string name( "JACK" );
-    return name;
-  }
-#endif
-#if defined(__LINUX_PULSE__)
-  if ( api == LINUX_PULSE ) {
-    static std::string name( "PulseAudio" );
-    return name;
-  }
-#endif
-#if defined(__LINUX_ALSA__)
-  if ( api == LINUX_ALSA ) {
-    static std::string name( "ALSA" );
-    return name;
-  }
-#endif
-#if defined(__LINUX_OSS__)
-  if ( api == LINUX_OSS ) {
-    static std::string name( "OSS" );
-    return name;
-  }
-#endif
-#if defined(__WINDOWS_ASIO__)
-  if ( api == WINDOWS_ASIO ) {
-    static std::string name( "ASIO" );
-    return name;
-  }
-#endif
-#if defined(__WINDOWS_WASAPI__)
-  if ( api == WINDOWS_WASAPI ) {
-    static std::string name( "WASAPI" );
-    return name;
-  }
-#endif
-#if defined(__WINDOWS_DS__)
-  if ( api == WINDOWS_DS ) {
-    static std::string name( "DirectSound" );
-    return name;
-  }
-#endif
-#if defined(__MACOSX_CORE__)
-  if ( api == MACOSX_CORE ) {
-    static std::string name( "Core Audio" );
-    return name;
-  }
-#endif
-#if defined(__RTAUDIO_DUMMY__)
-  if ( api == RTAUDIO_DUMMY ) {
-    static std::string name( "RtAudio Dummy" );
-    return name;
-  }
-#endif
-  static std::string name;
-  return name;
+  return compiledApis;
 }
 
-RtAudio::Api RtAudio :: getCompiledApiByName( const std::string &name )
+const std::string RtAudio :: getCompiledApiName( RtAudio::Api api )
 {
-  unsigned int api_number = RtAudio::UNSPECIFIED;
-  size_t nameLength = name.size();
-
-  if ( nameLength == 0 )
-    return RtAudio::UNSPECIFIED;
-
-  while ( api_number <= RtAudio::RTAUDIO_DUMMY ) {
-    const std::string &otherName =
-      getCompiledApiName((RtAudio::Api)api_number);
-
-    if ( name == otherName )
-      return (RtAudio::Api)api_number;
+  ApiNameMap::const_iterator it;
+  for (it = apiNames.begin(); it != apiNames.end(); it++)
+    if (it->second.first == api)
+      return it->first;
+  return "";
+}
 
-    ++api_number;
-  }
+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";
+}
 
-  return RtAudio::UNSPECIFIED;
+RtAudio::Api RtAudio :: getCompiledApiByName( const std::string &name )
+{
+  if (apiNames.find(name) == apiNames.end())
+    return RtAudio::UNSPECIFIED;
+  return apiNames.at(name).first;
 }
 
 void RtAudio :: openRtApi( RtAudio::Api api )
index 449e0d7dcc9323b47b955ebc7c23a8b2187f4c45..78d96a91ed4490c873eaaa2336c353a1ad74229a 100644 (file)
--- a/RtAudio.h
+++ b/RtAudio.h
@@ -61,6 +61,7 @@
 #include <vector>
 #include <stdexcept>
 #include <iostream>
+#include <map>
 
 /*! \typedef typedef unsigned long RtAudioFormat;
     \brief RtAudio data format type.
@@ -288,6 +289,9 @@ class RTAUDIO_DLL_PUBLIC RtAudio
     RTAUDIO_DUMMY   /*!< A compilable but non-functional API. */
   };
 
+  //! 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. */
@@ -397,6 +401,14 @@ class RTAUDIO_DLL_PUBLIC RtAudio
   */
   static void getCompiledApi( std::vector<RtAudio::Api> &apis );
 
+  //! A static function to determine the available compiled audio APIs.
+  /*!
+    The values returned in the std::vector can be compared against
+    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();
+
   //! Return the name of a specified compiled audio API.
   /*!
     This obtains a short lower-case name used for identification purposes.
@@ -404,7 +416,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.
   /*!
@@ -412,7 +424,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.
   /*!
@@ -606,6 +618,12 @@ 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;
+
   void openRtApi( RtAudio::Api api );
   RtApi *rtapi_;
 };
index 0040065b164a41e0065c4877c88c22001306bc7f..5847027bcdbbe605f0c4fd2e830355cd2d3a406d 100644 (file)
@@ -21,7 +21,7 @@ add_executable(duplex duplex.cpp)
 target_link_libraries(duplex ${LIBRTAUDIO} ${LINKLIBS})
 
 add_executable(apinames apinames.cpp)
-target_link_libraries(apinames rtaudio_static ${LINKLIBS})
+target_link_libraries(apinames ${LIBRTAUDIO} ${LINKLIBS})
 
 add_executable(testall testall.cpp)
 target_link_libraries(testall ${LIBRTAUDIO} ${LINKLIBS})
index db7a2582a5f19d84412bb14644757d34328e7072..81a3d7dd153570303391308a47047170e82dd870 100644 (file)
@@ -38,12 +38,12 @@ int main() {
     {
         const std::string &name = RtAudio::getCompiledApiName((RtAudio::Api)-1);
         if (!name.empty()) {
-            std::cerr << "Bad string for invalid API\n";
+            std::cerr << "Bad string for invalid API '" << name << "'\n";
             exit(1);
         }
         const std::string &displayName = RtAudio::getCompiledApiDisplayName((RtAudio::Api)-1);
-        if (!displayName.empty()) {
-            std::cerr << "Bad display string for invalid API\n";
+        if (displayName!="Unknown") {
+            std::cerr << "Bad display string for invalid API '" << displayName << "'\n";
             exit(1);
         }
     }