Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BUGFIX: single thread approach #153

Merged
merged 3 commits into from
May 21, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 64 additions & 5 deletions src/asio-input.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <obs-module.h>
#include <obs-frontend-api.h>
#include <vector>
#include <algorithm>
//#include <JuceHeader.h>
#include <juce_core/juce_core.h>
#include <juce_audio_devices/juce_audio_devices.h>
Expand Down Expand Up @@ -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<short> _route;
std::vector<short> _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;
Expand Down Expand Up @@ -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()
Expand All @@ -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)
Expand Down Expand Up @@ -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)
Expand All @@ -281,6 +292,9 @@ class AudioCB : public juce::AudioIODeviceCallback {
return wait_time;
}
};
private:
std::vector<AudioListener *> _clients;
public:

AudioIODevice *getDevice()
{
Expand Down Expand Up @@ -333,13 +347,27 @@ 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);
}

void remove_client(AudioListener *client)
{
auto it = std::remove(_clients.begin(), _clients.end(), client);
_clients.erase(it, _clients.end());

if (_thread)
_thread->removeTimeSliceClient(client);
}
Expand Down Expand Up @@ -383,17 +411,37 @@ 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<AudioListener *>(_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);
}

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);
Expand All @@ -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());

Expand Down
Loading