ASIO backend, part 6
add support for handling device resets this will be extended to the SDL and PortAudio backends soon
This commit is contained in:
parent
3edf62fc5c
commit
db2f368813
7 changed files with 85 additions and 1 deletions
|
|
@ -37,6 +37,14 @@ void* TAAudio::getContext() {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
TAAudioDeviceStatus TAAudio::getDeviceStatus() {
|
||||
return deviceStatus;
|
||||
}
|
||||
|
||||
void TAAudio::acceptDeviceStatus() {
|
||||
deviceStatus=TA_AUDIO_DEVICE_OK;
|
||||
}
|
||||
|
||||
bool TAAudio::quit() {
|
||||
return true;
|
||||
}
|
||||
|
|
@ -121,4 +129,4 @@ TAMidiIn::~TAMidiIn() {
|
|||
}
|
||||
|
||||
TAMidiOut::~TAMidiOut() {
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,6 +36,36 @@ static void _onSampleRate(ASIOSampleRate rate) {
|
|||
}
|
||||
|
||||
static long _onMessage(long type, long value, void* msg, double* opt) {
|
||||
if (callbackInstance==NULL) return;
|
||||
switch (type) {
|
||||
case kAsioSelectorSupported:
|
||||
switch (value) {
|
||||
case kAsioSelectorSupported:
|
||||
case kAsioEngineVersion:
|
||||
case kAsioResetRequest:
|
||||
case kAsioBufferSizeChange:
|
||||
case kAsioResyncRequest:
|
||||
return 1;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case kAsioEngineVersion:
|
||||
return 2;
|
||||
break;
|
||||
case kAsioResetRequest:
|
||||
callbackInstance->requestDeviceChange();
|
||||
return 1;
|
||||
break;
|
||||
case kAsioBufferSizeChange:
|
||||
callbackInstance->onBufferSize(value);
|
||||
return 1;
|
||||
break;
|
||||
case kAsioResyncRequest:
|
||||
// ignore
|
||||
return 1;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -343,6 +373,10 @@ bool TAAudioASIO::setRun(bool run) {
|
|||
return running;
|
||||
}
|
||||
|
||||
void TAAudioASIO::requestDeviceChange() {
|
||||
deviceStatus=TA_AUDIO_DEVICE_RESET;
|
||||
}
|
||||
|
||||
bool TAAudioASIO::init(TAAudioDesc& request, TAAudioDesc& response) {
|
||||
if (initialized) return false;
|
||||
if (callbackInstance) {
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ class TAAudioASIO: public TAAudio {
|
|||
void onSampleRate(double rate);
|
||||
void onBufferSize(int bufsize);
|
||||
void onProcess(int nframes);
|
||||
void requestDeviceChange();
|
||||
|
||||
String getErrorStr(ASIOError which);
|
||||
String getFormatName(ASIOSampleType which);
|
||||
|
|
|
|||
|
|
@ -36,6 +36,15 @@ struct BufferSizeChangeEvent {
|
|||
bufsize(bs) {}
|
||||
};
|
||||
|
||||
enum TAAudioDeviceStatus {
|
||||
// device is working
|
||||
TA_AUDIO_DEVICE_OK=0,
|
||||
// device has reset - reload audio engine
|
||||
TA_AUDIO_DEVICE_RESET,
|
||||
// device has been removed - reload audio engine with another device
|
||||
TA_AUDIO_DEVICE_REMOVED
|
||||
};
|
||||
|
||||
enum TAAudioFormat {
|
||||
TA_AUDIO_FORMAT_F32=0,
|
||||
TA_AUDIO_FORMAT_F64,
|
||||
|
|
@ -157,6 +166,8 @@ class TAAudio {
|
|||
protected:
|
||||
TAAudioDesc desc;
|
||||
TAAudioFormat outFormat;
|
||||
TAAudioDeviceStatus deviceStatus;
|
||||
|
||||
bool running, initialized;
|
||||
float** inBufs;
|
||||
float** outBufs;
|
||||
|
|
@ -176,12 +187,15 @@ class TAAudio {
|
|||
virtual bool quit();
|
||||
virtual bool setRun(bool run);
|
||||
virtual std::vector<String> listAudioDevices();
|
||||
TAAudioDeviceStatus getDeviceStatus();
|
||||
void acceptDeviceStatus();
|
||||
bool initMidi(bool jack);
|
||||
void quitMidi();
|
||||
virtual bool init(TAAudioDesc& request, TAAudioDesc& response);
|
||||
|
||||
TAAudio():
|
||||
outFormat(TA_AUDIO_FORMAT_F32),
|
||||
deviceStatus(TA_AUDIO_DEVICE_OK),
|
||||
running(false),
|
||||
initialized(false),
|
||||
inBufs(NULL),
|
||||
|
|
|
|||
|
|
@ -3798,6 +3798,16 @@ TAAudioDesc& DivEngine::getAudioDescGot() {
|
|||
return got;
|
||||
}
|
||||
|
||||
TAAudioDeviceStatus DivEngine::getAudioDeviceStatus() {
|
||||
if (output==NULL) return TA_AUDIO_DEVICE_OK;
|
||||
return output->getDeviceStatus();
|
||||
}
|
||||
|
||||
void DivEngine::acceptAudioDeviceStatus() {
|
||||
if (output==NULL) return;
|
||||
output->acceptDeviceStatus();
|
||||
}
|
||||
|
||||
std::vector<String>& DivEngine::getAudioDevices() {
|
||||
return audioDevs;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1403,6 +1403,12 @@ class DivEngine {
|
|||
// get audio desc
|
||||
TAAudioDesc& getAudioDescGot();
|
||||
|
||||
// get audio device status
|
||||
TAAudioDeviceStatus getAudioDeviceStatus();
|
||||
|
||||
// acknowledge an audio device status change
|
||||
void acceptAudioDeviceStatus();
|
||||
|
||||
// init dispatch
|
||||
void initDispatch(bool isRender=false);
|
||||
|
||||
|
|
|
|||
|
|
@ -4333,6 +4333,17 @@ bool FurnaceGUI::loop() {
|
|||
});
|
||||
}
|
||||
|
||||
// recover from audio resets
|
||||
TAAudioDeviceStatus audioStatus=e->getAudioDeviceStatus();
|
||||
if (audioStatus!=TA_AUDIO_DEVICE_OK) {
|
||||
logI("audio device reset!");
|
||||
e->acceptAudioDeviceStatus();
|
||||
|
||||
if (!e->switchMaster(false)) {
|
||||
showError(_("audio device has reset or has been disconnected! check audio settings."));
|
||||
}
|
||||
}
|
||||
|
||||
// recover from dead graphics
|
||||
if (rend->isDead() || killGraphics) {
|
||||
killGraphics=false;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue