diff --git a/src/asio-input.cpp b/src/asio-input.cpp
index 0d22dc3..6a57f19 100644
--- a/src/asio-input.cpp
+++ b/src/asio-input.cpp
@@ -25,6 +25,7 @@ along with this program. If not, see .
#include
#include
#include
+#include
//#include
#include
#include
@@ -159,12 +160,14 @@ class AudioCB : public juce::AudioIODeviceCallback {
public:
class AudioListener : public TimeSliceClient {
private:
+ static constexpr unsigned int client_mask = 0x1;
+ static constexpr unsigned int device_mask = 0x2;
std::vector _route;
std::vector _route_out;
obs_source_audio in;
obs_source_t *source;
- bool active;
+ unsigned int active;
int read_index = 0;
int wait_time = 4;
AudioCB *callback;
@@ -205,7 +208,7 @@ class AudioCB : public juce::AudioIODeviceCallback {
public:
AudioListener(obs_source_t *source, AudioCB *cb) : source(source), callback(cb)
{
- active = true;
+ active = client_mask | device_mask;
}
~AudioListener()
@@ -215,12 +218,20 @@ class AudioCB : public juce::AudioIODeviceCallback {
void disconnect()
{
- active = false;
+ active &= device_mask;
}
void reconnect()
{
- active = true;
+ active |= client_mask;
+ }
+
+ void device_disconnect() {
+ active &= client_mask;
+ }
+
+ void device_reconnect() {
+ active |= device_mask;
}
void setOutput(obs_source_audio o)
@@ -257,7 +268,7 @@ class AudioCB : public juce::AudioIODeviceCallback {
int useTimeSlice()
{
- if (!active || callback != current_callback)
+ if ((active & client_mask) == 0 || (active & device_mask) == 0 || callback != current_callback)
return -1;
int write_index = callback->write_index();
if (read_index == write_index)
@@ -281,6 +292,9 @@ class AudioCB : public juce::AudioIODeviceCallback {
return wait_time;
}
};
+private:
+ std::vector _clients;
+public:
AudioIODevice *getDevice()
{
@@ -333,6 +347,17 @@ class AudioCB : public juce::AudioIODeviceCallback {
if (!_thread)
_thread = global_thread;
+ bool found_client = false;
+ for (auto known_client : _clients) {
+ if (known_client == client) {
+ found_client = true;
+ break;
+ }
+ }
+
+ if (!found_client)
+ _clients.push_back(client);
+
client->setCurrentCallback(this);
client->setReadIndex(_write_index);
_thread->addTimeSliceClient(client);
@@ -340,6 +365,9 @@ class AudioCB : public juce::AudioIODeviceCallback {
void remove_client(AudioListener *client)
{
+ auto it = std::remove(_clients.begin(), _clients.end(), client);
+ _clients.erase(it, _clients.end());
+
if (_thread)
_thread->removeTimeSliceClient(client);
}
@@ -383,10 +411,26 @@ class AudioCB : public juce::AudioIODeviceCallback {
if (!_thread) {
_thread = global_thread;
} else {
+ /*
+ // update clients with this device to use this callback
+ // BUGFIX: when pkv modified the source code to use one global thread
+ // this became bugged, originally
for (int i = 0; i < _thread->getNumClients(); i++) {
AudioListener *l = static_cast(_thread->getClient(i));
+ // this is one of this device's known clients
l->setCurrentCallback(this);
}
+ // was ok because _thread was unique to each AudioCB (the this pointer)
+ // I'm adding a redundant struct to keep track of the clients inside the AudioCB
+ */
+ for (auto known_client : _clients) {
+ known_client->setCurrentCallback(this);
+ // if the device for whatever reason stopped, or errored out
+ // the clients will have been disabled by the device disconnecting
+ // since we're here, we can mark the device as being ok
+ known_client->device_reconnect();
+ }
+
}
if (!_thread->isThreadRunning())
_thread->startThread(10);
@@ -394,6 +438,10 @@ class AudioCB : public juce::AudioIODeviceCallback {
void audioDeviceStopped()
{
+ for (auto known_client : _clients) {
+ known_client->device_disconnect();
+ }
+
blog(LOG_INFO, "Stopped (%s)", _device->getName().toStdString().c_str());
std::string timestamp_string = std::to_string(last_audio_ts);
@@ -403,8 +451,19 @@ class AudioCB : public juce::AudioIODeviceCallback {
void audioDeviceError(const juce::String &errorMessage)
{
+ /* BUGFIX: when pkv modified the source code to use one global thread
+ // this became bugged, originally
if (_thread)
_thread->stopThread(200);
+ // was ok because _thread was unique to each AudioCB (the this pointer)
+ // now any device that sends an error effectively nukes all other processing
+ // which likely will cause problems
+ */
+ // Instead we'll mark all clients as having the device disconnected
+ for (auto known_client : _clients) {
+ known_client->device_disconnect();
+ }
+
std::string error = errorMessage.toStdString();
blog(LOG_ERROR, "Device Error!\n%s", error.c_str());