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.

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