Skip to content

Commit

Permalink
Allow multiple PortAudioRedirector instances
Browse files Browse the repository at this point in the history
Fixes #183
  • Loading branch information
dechamps committed Feb 4, 2023
1 parent ad6ef03 commit c91fe1e
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 18 deletions.
51 changes: 38 additions & 13 deletions src/flexasio/FlexASIOUtil/portaudio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,30 +37,55 @@ typedef struct PaUtilHostApiSpecificStreamInfoHeader

namespace flexasio {

PortAudioDebugRedirector::PortAudioDebugRedirector(Write write) {
write(std::string("PortAudio version: ") + Pa_GetVersionText());
write("Enabling PortAudio debug output redirection");
if (this->write) abort();
this->write = std::move(write);
PaUtil_SetDebugPrintFunction(DebugPrint);
PortAudioDebugRedirector::Singleton::~Singleton() {
Check();
if (write) abort();
}

PortAudioDebugRedirector::~PortAudioDebugRedirector() {
void PortAudioDebugRedirector::Singleton::Start(Write write) {
const std::lock_guard lock(mutex);
Check();

if (referenceCount > 0) {
if (write != this->write) abort();
} else {
this->write = write;
write(std::string("PortAudio version: ") + Pa_GetVersionText());
write("Enabling PortAudio debug output redirection");
PaUtil_SetDebugPrintFunction(DebugPrint);
}

++referenceCount;
}

void PortAudioDebugRedirector::Singleton::Stop() {
const std::lock_guard lock(mutex);
Check();
if (!write) abort();

--referenceCount;
if (referenceCount > 0) return;

this->write("Disabling PortAudio debug output redirection");
PaUtil_SetDebugPrintFunction(NULL);
if (!this->write) abort();
this->write = nullptr;
write = nullptr;
}

void PortAudioDebugRedirector::DebugPrint(const char* str) {
if (!PortAudioDebugRedirector::write) abort();
void PortAudioDebugRedirector::Singleton::DebugPrint(const char* str) {
singleton.Check();
const auto write = singleton.write;
if (!write) abort();

std::string_view line(str);
while (!line.empty() && isspace(static_cast<unsigned char>(line.back()))) line.remove_suffix(1);
PortAudioDebugRedirector::write(line);
write(line);
}

void PortAudioDebugRedirector::Singleton::Check() const {
if ((referenceCount != 0) != !!write) abort();
}

PortAudioDebugRedirector::Write PortAudioDebugRedirector::write;
PortAudioDebugRedirector::Singleton PortAudioDebugRedirector::singleton;

std::string GetHostApiTypeIdString(PaHostApiTypeId hostApiTypeId) {
return ::dechamps_cpputil::EnumToString(hostApiTypeId, {
Expand Down
26 changes: 21 additions & 5 deletions src/flexasio/FlexASIOUtil/portaudio.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,38 @@
#include <MMReg.h>

#include <functional>
#include <mutex>
#include <string>
#include <string_view>

namespace flexasio {

class PortAudioDebugRedirector final {
public:
using Write = std::function<void(std::string_view)>;
using Write = void(std::string_view);

explicit PortAudioDebugRedirector(Write write);
~PortAudioDebugRedirector();
explicit PortAudioDebugRedirector(Write write) { singleton.Start(write); }
~PortAudioDebugRedirector() { singleton.Stop(); };

private:
static void DebugPrint(const char*);
class Singleton final {
public:
~Singleton();

static Write write;
void Start(Write);
void Stop();

private:
std::mutex mutex;
size_t referenceCount = 0;
Write* write = nullptr;

static void DebugPrint(const char*);

void Check() const;
};

static Singleton singleton;
};

std::string GetHostApiTypeIdString(PaHostApiTypeId hostApiTypeId);
Expand Down

0 comments on commit c91fe1e

Please sign in to comment.