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