fork download
  1. #include <memory>
  2. #include <map>
  3. #include <stdio.h>
  4. #include <exception>
  5. using namespace std;
  6.  
  7. namespace ARDOUR {
  8. class AudioBackend;
  9. class AudioEngine;
  10.  
  11. struct AudioBackendInfo {
  12. const char* name;
  13.  
  14. /** Using arg1 and arg2, initialize this audiobackend.
  15.   *
  16.   * Returns zero on success, non-zero otherwise.
  17.   */
  18. int (*instantiate) (const std::string& arg1, const std::string& arg2);
  19.  
  20. /** Release all resources associated with this audiobackend */
  21. int (*deinstantiate) (void);
  22.  
  23. /** Factory method to create an AudioBackend-derived class.
  24.   *
  25.   * Returns a valid shared_ptr to the object if successfull,
  26.   * or a "null" shared_ptr otherwise.
  27.   */
  28. std::shared_ptr<AudioBackend> (*factory) (AudioEngine&);
  29.  
  30. /** Return true if the underlying mechanism/API has been
  31.   * configured and does not need (re)configuration in order
  32.   * to be usable. Return false otherwise.
  33.   *
  34.   * Note that this may return true if (re)configuration, even though
  35.   * not currently required, is still possible.
  36.   */
  37. bool (*already_configured) ();
  38.  
  39. /** Return true if the underlying mechanism/API can be
  40.   * used on the given system.
  41.   *
  42.   * If this function returns false, the backend is not
  43.   * listed in the engine dialog.
  44.   */
  45. bool (*available) ();
  46. };
  47.  
  48. /** AudioBackend is an high-level abstraction for interacting with the operating system's
  49.   * audio and midi I/O.
  50.   */
  51. class AudioBackend {};
  52. };
  53.  
  54. namespace ARDOUR {
  55. class AudioEngine;
  56. class AAudio : public AudioBackend {
  57. public:
  58. std::string _instance_name;
  59. static AudioBackendInfo _descriptor;
  60. static std::shared_ptr<AudioBackend> backend_factory (AudioEngine& e);
  61. static int instantiate (const std::string& arg1, const std::string& /* arg2 */);
  62. static int deinstantiate ();
  63. static bool already_configured ();
  64. static bool available ();
  65. static ARDOUR::AudioBackendInfo* descriptor();
  66. };
  67.  
  68. static std::string s_instance_name;
  69. const size_t _max_buffer_size = 8192;
  70. static std::shared_ptr<AAudio> _instance;
  71.  
  72. #define N_CHANNELS (2)
  73.  
  74. ARDOUR::AudioBackendInfo AAudio::_descriptor = {
  75. "AAudio",
  76. instantiate,
  77. deinstantiate,
  78. backend_factory,
  79. already_configured,
  80. available
  81. };
  82.  
  83. std::shared_ptr<AudioBackend>
  84. AAudio::backend_factory (AudioEngine& e)
  85. {
  86. if (!_instance) {
  87. _instance.reset(new AAudio());
  88. }
  89. return _instance;
  90. }
  91.  
  92. int
  93. AAudio::instantiate (const std::string& arg1, const std::string& /* arg2 */)
  94. {
  95. s_instance_name = arg1;
  96. return 0;
  97. }
  98.  
  99. int
  100. AAudio::deinstantiate ()
  101. {
  102. _instance.reset ();
  103. return 0;
  104. }
  105.  
  106. bool
  107. AAudio::already_configured ()
  108. {
  109. return false;
  110. }
  111.  
  112. bool
  113. AAudio::available ()
  114. {
  115. return true;
  116. }
  117.  
  118. ARDOUR::AudioBackendInfo* AAudio::descriptor ()
  119. {
  120. return &_descriptor;
  121. }
  122. }
  123.  
  124. namespace ARDOUR {
  125. class AudioBackend;
  126. struct AudioBackendInfo;
  127. static std::shared_ptr<AudioBackend> _backend;
  128.  
  129. class AudioEngine {
  130. public:
  131. AudioEngine ();
  132. static AudioEngine* create ();
  133. int discover_backends();
  134. std::shared_ptr<AudioBackend> set_backend (const std::string&, const std::string& arg1, const std::string& arg2);
  135. std::shared_ptr<AudioBackend> current_backend() const { return _backend; }
  136. static AudioEngine* _instance;
  137. typedef std::map<std::string, AudioBackendInfo *> BackendMap;
  138. BackendMap _backends;
  139. void drop_backend();
  140. };
  141.  
  142. AudioEngine* AudioEngine::_instance = 0;
  143.  
  144. AudioEngine::AudioEngine ()
  145. {
  146. discover_backends ();
  147. }
  148.  
  149. AudioEngine*
  150. AudioEngine::create ()
  151. {
  152. if (_instance) {
  153. return _instance;
  154. }
  155.  
  156. _instance = new AudioEngine ();
  157.  
  158. return _instance;
  159. }
  160.  
  161. int
  162. AudioEngine::discover_backends ()
  163. {
  164. _backends.clear ();
  165.  
  166. _backends.insert (make_pair (AAudio::descriptor()->name, AAudio::descriptor()));
  167.  
  168. return _backends.size();
  169. }
  170.  
  171. void
  172. AudioEngine::drop_backend ()
  173. {
  174. if (_backend) {
  175. _backend.reset ();
  176. }
  177. }
  178.  
  179. class failed_constructor : public std::exception {
  180. public:
  181. virtual const char *what() const throw() { return "failed constructor"; }
  182. };
  183.  
  184. std::shared_ptr<AudioBackend>
  185. AudioEngine::set_backend (const std::string& name, const std::string& arg1, const std::string& arg2)
  186. {
  187. BackendMap::iterator b = _backends.find (name);
  188.  
  189. if (b == _backends.end()) {
  190. return std::shared_ptr<AudioBackend>();
  191. }
  192.  
  193. drop_backend ();
  194.  
  195. try {
  196. if (b->second->instantiate (arg1, arg2)) {
  197. throw failed_constructor ();
  198. }
  199.  
  200. _backend = b->second->factory (*this);
  201.  
  202. } catch (exception& e) {
  203. printf("Could not create backend for %s: %s\n", name, e.what());
  204. return std::shared_ptr<AudioBackend>();
  205. }
  206.  
  207. return _backend;
  208. }
  209. }
  210.  
  211. using namespace ARDOUR;
  212.  
  213. int main() {
  214. AudioEngine * engine = nullptr;
  215. engine = AudioEngine::create();
  216. if (!engine->set_backend ("AAudio", "Unit-Test", "")) {
  217. printf("Cannot create Audio/MIDI engine.\n");
  218. abort();
  219. }
  220. if (_backend == nullptr) {
  221. printf("backend dissapeared!\n"); // triggers on android
  222. abort();
  223. }
  224. return 0;
  225. }
Success #stdin #stdout 0s 4456KB
stdin
Standard input is empty
stdout
Standard output is empty