Audio plugin host https://kx.studio/carla
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

179 lines
4.6KB

  1. /*
  2. ZynAddSubFX - a software synthesizer
  3. EngineMgr.cpp - MIDI/Audio Factory
  4. Copyright (C) 2016 Mark McCurry
  5. This program is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU General Public License
  7. as published by the Free Software Foundation; either version 2
  8. of the License, or (at your option) any later version.
  9. */
  10. #include "EngineMgr.h"
  11. #include <algorithm>
  12. #include <iostream>
  13. #include <cassert>
  14. #include "Nio.h"
  15. #include "InMgr.h"
  16. #include "OutMgr.h"
  17. #include "AudioOut.h"
  18. #include "MidiIn.h"
  19. #include "NulEngine.h"
  20. using namespace std;
  21. #if OSS
  22. #include "OssEngine.h"
  23. #include "OssMultiEngine.h"
  24. #endif
  25. #if ALSA
  26. #include "AlsaEngine.h"
  27. #endif
  28. #if JACK
  29. #include "JackEngine.h"
  30. #include "JackMultiEngine.h"
  31. #endif
  32. #if PORTAUDIO
  33. #include "PaEngine.h"
  34. #endif
  35. namespace zyncarla {
  36. EngineMgr &EngineMgr::getInstance(const SYNTH_T *synth,
  37. const oss_devs_t *oss_devs)
  38. {
  39. static EngineMgr instance(synth, *oss_devs);
  40. return instance;
  41. }
  42. EngineMgr::EngineMgr(const SYNTH_T *synth, const oss_devs_t& oss_devs)
  43. {
  44. assert(synth);
  45. Engine *defaultEng = new NulEngine(*synth);
  46. //conditional compiling mess (but contained)
  47. engines.push_back(defaultEng);
  48. #if OSS
  49. engines.push_back(new OssEngine(*synth, oss_devs));
  50. engines.push_back(new OssMultiEngine(*synth, oss_devs));
  51. #endif
  52. #if ALSA
  53. engines.push_back(new AlsaEngine(*synth));
  54. #endif
  55. #if JACK
  56. engines.push_back(new JackEngine(*synth));
  57. engines.push_back(new JackMultiEngine(*synth));
  58. #endif
  59. #if PORTAUDIO
  60. engines.push_back(new PaEngine(*synth));
  61. #endif
  62. defaultOut = dynamic_cast<AudioOut *>(defaultEng);
  63. defaultIn = dynamic_cast<MidiIn *>(defaultEng);
  64. //Accept command line/compile time options
  65. if(!Nio::defaultSink.empty())
  66. setOutDefault(Nio::defaultSink);
  67. if(!Nio::defaultSource.empty())
  68. setInDefault(Nio::defaultSource);
  69. }
  70. EngineMgr::~EngineMgr()
  71. {
  72. for(list<Engine *>::iterator itr = engines.begin();
  73. itr != engines.end(); ++itr)
  74. delete *itr;
  75. }
  76. Engine *EngineMgr::getEng(string name)
  77. {
  78. transform(name.begin(), name.end(), name.begin(), ::toupper);
  79. for(list<Engine *>::iterator itr = engines.begin();
  80. itr != engines.end(); ++itr)
  81. if((*itr)->name == name)
  82. return *itr;
  83. return NULL;
  84. }
  85. bool EngineMgr::start()
  86. {
  87. bool expected = true;
  88. if(!(defaultOut && defaultIn)) {
  89. cerr << "ERROR: It looks like someone broke the Nio Output\n"
  90. << " Attempting to recover by defaulting to the\n"
  91. << " Null Engine." << endl;
  92. defaultOut = dynamic_cast<AudioOut *>(getEng("NULL"));
  93. defaultIn = dynamic_cast<MidiIn *>(getEng("NULL"));
  94. }
  95. OutMgr::getInstance(). currentOut = defaultOut;
  96. InMgr::getInstance(). current = defaultIn;
  97. //open up the default output(s)
  98. cout << "Starting Audio: " << defaultOut->name << endl;
  99. defaultOut->setAudioEn(true);
  100. if(defaultOut->getAudioEn())
  101. cout << "Audio Started" << endl;
  102. else {
  103. expected = false;
  104. cerr << "ERROR: The default audio output failed to open!" << endl;
  105. OutMgr::getInstance(). currentOut =
  106. dynamic_cast<AudioOut *>(getEng("NULL"));
  107. OutMgr::getInstance(). currentOut->setAudioEn(true);
  108. }
  109. cout << "Starting MIDI: " << defaultIn->name << endl;
  110. defaultIn->setMidiEn(true);
  111. if(defaultIn->getMidiEn())
  112. cout << "MIDI Started" << endl;
  113. else { //recover
  114. expected = false;
  115. cerr << "ERROR: The default MIDI input failed to open!" << endl;
  116. InMgr::getInstance(). current = dynamic_cast<MidiIn *>(getEng("NULL"));
  117. InMgr::getInstance(). current->setMidiEn(true);
  118. }
  119. //Show if expected drivers were booted
  120. return expected;
  121. }
  122. void EngineMgr::stop()
  123. {
  124. for(list<Engine *>::iterator itr = engines.begin();
  125. itr != engines.end(); ++itr)
  126. (*itr)->Stop();
  127. }
  128. bool EngineMgr::setInDefault(string name)
  129. {
  130. MidiIn *chosen;
  131. if((chosen = dynamic_cast<MidiIn *>(getEng(name)))) { //got the input
  132. defaultIn = chosen;
  133. return true;
  134. }
  135. //Warn user
  136. cerr << "Error: " << name << " is not a recognized MIDI input source"
  137. << endl;
  138. cerr << " Defaulting to the NULL input source" << endl;
  139. return false;
  140. }
  141. bool EngineMgr::setOutDefault(string name)
  142. {
  143. AudioOut *chosen;
  144. if((chosen = dynamic_cast<AudioOut *>(getEng(name)))) { //got the output
  145. defaultOut = chosen;
  146. return true;
  147. }
  148. //Warn user
  149. cerr << "Error: " << name << " is not a recognized audio backend" << endl;
  150. cerr << " Defaulting to the NULL audio backend" << endl;
  151. return false;
  152. }
  153. }