aboutsummaryrefslogtreecommitdiffstats
path: root/Alc/backends/jack.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Alc/backends/jack.cpp')
-rw-r--r--Alc/backends/jack.cpp199
1 files changed, 87 insertions, 112 deletions
diff --git a/Alc/backends/jack.cpp b/Alc/backends/jack.cpp
index 26086bf9..77bbf487 100644
--- a/Alc/backends/jack.cpp
+++ b/Alc/backends/jack.cpp
@@ -148,9 +148,9 @@ ALCboolean jack_load(void)
}
-struct ALCjackPlayback final : public ALCbackend {
- ALCjackPlayback(ALCdevice *device) noexcept : ALCbackend{device} { }
- ~ALCjackPlayback() override;
+struct JackPlayback final : public BackendBase {
+ JackPlayback(ALCdevice *device) noexcept : BackendBase{device} { }
+ ~JackPlayback() override;
static int bufferSizeNotifyC(jack_nframes_t numframes, void *arg);
int bufferSizeNotify(jack_nframes_t numframes);
@@ -160,6 +160,12 @@ struct ALCjackPlayback final : public ALCbackend {
int mixerProc();
+ ALCenum open(const ALCchar *name) override;
+ ALCboolean reset() override;
+ ALCboolean start() override;
+ void stop() override;
+ ClockLatency getClockLatency() override;
+
jack_client_t *mClient{nullptr};
jack_port_t *mPort[MAX_OUTPUT_CHANNELS]{};
@@ -168,34 +174,12 @@ struct ALCjackPlayback final : public ALCbackend {
std::atomic<bool> mKillNow{true};
std::thread mThread;
-};
-
-void ALCjackPlayback_Construct(ALCjackPlayback *self, ALCdevice *device);
-void ALCjackPlayback_Destruct(ALCjackPlayback *self);
-ALCenum ALCjackPlayback_open(ALCjackPlayback *self, const ALCchar *name);
-ALCboolean ALCjackPlayback_reset(ALCjackPlayback *self);
-ALCboolean ALCjackPlayback_start(ALCjackPlayback *self);
-void ALCjackPlayback_stop(ALCjackPlayback *self);
-DECLARE_FORWARD2(ALCjackPlayback, ALCbackend, ALCenum, captureSamples, void*, ALCuint)
-DECLARE_FORWARD(ALCjackPlayback, ALCbackend, ALCuint, availableSamples)
-ClockLatency ALCjackPlayback_getClockLatency(ALCjackPlayback *self);
-DECLARE_FORWARD(ALCjackPlayback, ALCbackend, void, lock)
-DECLARE_FORWARD(ALCjackPlayback, ALCbackend, void, unlock)
-DECLARE_DEFAULT_ALLOCATORS(ALCjackPlayback)
-
-DEFINE_ALCBACKEND_VTABLE(ALCjackPlayback);
+ static constexpr inline const char *CurrentPrefix() noexcept { return "JackPlayback::"; }
+ DEF_NEWDEL(JackPlayback)
+};
-void ALCjackPlayback_Construct(ALCjackPlayback *self, ALCdevice *device)
-{
- new (self) ALCjackPlayback{device};
- SET_VTABLE2(ALCjackPlayback, ALCbackend, self);
-}
-
-void ALCjackPlayback_Destruct(ALCjackPlayback *self)
-{ self->~ALCjackPlayback(); }
-
-ALCjackPlayback::~ALCjackPlayback()
+JackPlayback::~JackPlayback()
{
if(!mClient)
return;
@@ -210,12 +194,12 @@ ALCjackPlayback::~ALCjackPlayback()
}
-int ALCjackPlayback::bufferSizeNotifyC(jack_nframes_t numframes, void *arg)
-{ return static_cast<ALCjackPlayback*>(arg)->bufferSizeNotify(numframes); }
+int JackPlayback::bufferSizeNotifyC(jack_nframes_t numframes, void *arg)
+{ return static_cast<JackPlayback*>(arg)->bufferSizeNotify(numframes); }
-int ALCjackPlayback::bufferSizeNotify(jack_nframes_t numframes)
+int JackPlayback::bufferSizeNotify(jack_nframes_t numframes)
{
- ALCjackPlayback_lock(this);
+ lock();
mDevice->UpdateSize = numframes;
mDevice->NumUpdates = 2;
@@ -233,15 +217,15 @@ int ALCjackPlayback::bufferSizeNotify(jack_nframes_t numframes)
ERR("Failed to reallocate ringbuffer\n");
aluHandleDisconnect(mDevice, "Failed to reallocate %u-sample buffer", bufsize);
}
- ALCjackPlayback_unlock(this);
+ unlock();
return 0;
}
-int ALCjackPlayback::processC(jack_nframes_t numframes, void *arg)
-{ return static_cast<ALCjackPlayback*>(arg)->process(numframes); }
+int JackPlayback::processC(jack_nframes_t numframes, void *arg)
+{ return static_cast<JackPlayback*>(arg)->process(numframes); }
-int ALCjackPlayback::process(jack_nframes_t numframes)
+int JackPlayback::process(jack_nframes_t numframes)
{
jack_default_audio_sample_t *out[MAX_OUTPUT_CHANNELS];
ALsizei numchans{0};
@@ -311,20 +295,20 @@ int ALCjackPlayback::process(jack_nframes_t numframes)
return 0;
}
-int ALCjackPlayback::mixerProc()
+int JackPlayback::mixerProc()
{
SetRTPriority();
althrd_setname(MIXER_THREAD_NAME);
- ALCjackPlayback_lock(this);
+ lock();
while(!mKillNow.load(std::memory_order_acquire) &&
mDevice->Connected.load(std::memory_order_acquire))
{
if(mRing->writeSpace() < mDevice->UpdateSize)
{
- ALCjackPlayback_unlock(this);
+ unlock();
mSem.wait();
- ALCjackPlayback_lock(this);
+ lock();
continue;
}
@@ -340,13 +324,13 @@ int ALCjackPlayback::mixerProc()
aluMixData(mDevice, data.second.buf, len2);
mRing->writeAdvance(todo);
}
- ALCjackPlayback_unlock(this);
+ unlock();
return 0;
}
-ALCenum ALCjackPlayback_open(ALCjackPlayback *self, const ALCchar *name)
+ALCenum JackPlayback::open(const ALCchar *name)
{
if(!name)
name = jackDevice;
@@ -355,8 +339,8 @@ ALCenum ALCjackPlayback_open(ALCjackPlayback *self, const ALCchar *name)
const char *client_name{"alsoft"};
jack_status_t status;
- self->mClient = jack_client_open(client_name, ClientOptions, &status, nullptr);
- if(self->mClient == nullptr)
+ mClient = jack_client_open(client_name, ClientOptions, &status, nullptr);
+ if(mClient == nullptr)
{
ERR("jack_client_open() failed, status = 0x%02x\n", status);
return ALC_INVALID_VALUE;
@@ -365,104 +349,102 @@ ALCenum ALCjackPlayback_open(ALCjackPlayback *self, const ALCchar *name)
TRACE("JACK server started\n");
if((status&JackNameNotUnique))
{
- client_name = jack_get_client_name(self->mClient);
+ client_name = jack_get_client_name(mClient);
TRACE("Client name not unique, got `%s' instead\n", client_name);
}
- jack_set_process_callback(self->mClient, &ALCjackPlayback::processC, self);
- jack_set_buffer_size_callback(self->mClient, &ALCjackPlayback::bufferSizeNotifyC, self);
+ jack_set_process_callback(mClient, &JackPlayback::processC, this);
+ jack_set_buffer_size_callback(mClient, &JackPlayback::bufferSizeNotifyC, this);
- ALCdevice *device{self->mDevice};
- device->DeviceName = name;
+ mDevice->DeviceName = name;
return ALC_NO_ERROR;
}
-ALCboolean ALCjackPlayback_reset(ALCjackPlayback *self)
+ALCboolean JackPlayback::reset()
{
- std::for_each(std::begin(self->mPort), std::end(self->mPort),
- [self](jack_port_t *port) -> void
- { if(port) jack_port_unregister(self->mClient, port); }
+ std::for_each(std::begin(mPort), std::end(mPort),
+ [this](jack_port_t *port) -> void
+ { if(port) jack_port_unregister(mClient, port); }
);
- std::fill(std::begin(self->mPort), std::end(self->mPort), nullptr);
+ std::fill(std::begin(mPort), std::end(mPort), nullptr);
/* Ignore the requested buffer metrics and just keep one JACK-sized buffer
* ready for when requested.
*/
- ALCdevice *device{self->mDevice};
- device->Frequency = jack_get_sample_rate(self->mClient);
- device->UpdateSize = jack_get_buffer_size(self->mClient);
- device->NumUpdates = 2;
+ mDevice->Frequency = jack_get_sample_rate(mClient);
+ mDevice->UpdateSize = jack_get_buffer_size(mClient);
+ mDevice->NumUpdates = 2;
- ALuint bufsize{device->UpdateSize};
- if(ConfigValueUInt(device->DeviceName.c_str(), "jack", "buffer-size", &bufsize))
- bufsize = maxu(NextPowerOf2(bufsize), device->UpdateSize);
- device->NumUpdates = (bufsize+device->UpdateSize) / device->UpdateSize;
+ ALuint bufsize{mDevice->UpdateSize};
+ if(ConfigValueUInt(mDevice->DeviceName.c_str(), "jack", "buffer-size", &bufsize))
+ bufsize = maxu(NextPowerOf2(bufsize), mDevice->UpdateSize);
+ mDevice->NumUpdates = (bufsize+mDevice->UpdateSize) / mDevice->UpdateSize;
/* Force 32-bit float output. */
- device->FmtType = DevFmtFloat;
+ mDevice->FmtType = DevFmtFloat;
- ALsizei numchans{device->channelsFromFmt()};
- auto ports_end = std::begin(self->mPort) + numchans;
- auto bad_port = std::find_if_not(std::begin(self->mPort), ports_end,
- [self](jack_port_t *&port) -> bool
+ ALsizei numchans{mDevice->channelsFromFmt()};
+ auto ports_end = std::begin(mPort) + numchans;
+ auto bad_port = std::find_if_not(std::begin(mPort), ports_end,
+ [this](jack_port_t *&port) -> bool
{
- std::string name{"channel_" + std::to_string(&port - self->mPort + 1)};
- port = jack_port_register(self->mClient, name.c_str(), JACK_DEFAULT_AUDIO_TYPE,
+ std::string name{"channel_" + std::to_string(&port - mPort + 1)};
+ port = jack_port_register(mClient, name.c_str(), JACK_DEFAULT_AUDIO_TYPE,
JackPortIsOutput, 0);
return port != nullptr;
}
);
if(bad_port != ports_end)
{
- ERR("Not enough JACK ports available for %s output\n", DevFmtChannelsString(device->FmtChans));
- if(bad_port == std::begin(self->mPort)) return ALC_FALSE;
+ ERR("Not enough JACK ports available for %s output\n", DevFmtChannelsString(mDevice->FmtChans));
+ if(bad_port == std::begin(mPort)) return ALC_FALSE;
- if(bad_port == std::begin(self->mPort)+1)
- device->FmtChans = DevFmtMono;
+ if(bad_port == std::begin(mPort)+1)
+ mDevice->FmtChans = DevFmtMono;
else
{
- ports_end = self->mPort+2;
+ ports_end = mPort+2;
while(bad_port != ports_end)
{
- jack_port_unregister(self->mClient, *(--bad_port));
+ jack_port_unregister(mClient, *(--bad_port));
*bad_port = nullptr;
}
- device->FmtChans = DevFmtStereo;
+ mDevice->FmtChans = DevFmtStereo;
}
- numchans = std::distance(std::begin(self->mPort), bad_port);
+ numchans = std::distance(std::begin(mPort), bad_port);
}
- self->mRing = nullptr;
- self->mRing = CreateRingBuffer(bufsize, device->frameSizeFromFmt(), true);
- if(!self->mRing)
+ mRing = nullptr;
+ mRing = CreateRingBuffer(bufsize, mDevice->frameSizeFromFmt(), true);
+ if(!mRing)
{
ERR("Failed to allocate ringbuffer\n");
return ALC_FALSE;
}
- SetDefaultChannelOrder(device);
+ SetDefaultChannelOrder(mDevice);
return ALC_TRUE;
}
-ALCboolean ALCjackPlayback_start(ALCjackPlayback *self)
+ALCboolean JackPlayback::start()
{
- if(jack_activate(self->mClient))
+ if(jack_activate(mClient))
{
ERR("Failed to activate client\n");
return ALC_FALSE;
}
- const char **ports{jack_get_ports(self->mClient, nullptr, nullptr,
+ const char **ports{jack_get_ports(mClient, nullptr, nullptr,
JackPortIsPhysical|JackPortIsInput)};
if(ports == nullptr)
{
ERR("No physical playback ports found\n");
- jack_deactivate(self->mClient);
+ jack_deactivate(mClient);
return ALC_FALSE;
}
- std::mismatch(std::begin(self->mPort), std::end(self->mPort), ports,
- [self](const jack_port_t *port, const char *pname) -> bool
+ std::mismatch(std::begin(mPort), std::end(mPort), ports,
+ [this](const jack_port_t *port, const char *pname) -> bool
{
if(!port) return false;
if(!pname)
@@ -470,7 +452,7 @@ ALCboolean ALCjackPlayback_start(ALCjackPlayback *self)
ERR("No physical playback port for \"%s\"\n", jack_port_name(port));
return false;
}
- if(jack_connect(self->mClient, jack_port_name(port), pname))
+ if(jack_connect(mClient, jack_port_name(port), pname))
ERR("Failed to connect output port \"%s\" to \"%s\"\n", jack_port_name(port),
pname);
return true;
@@ -479,8 +461,8 @@ ALCboolean ALCjackPlayback_start(ALCjackPlayback *self)
jack_free(ports);
try {
- self->mKillNow.store(false, std::memory_order_release);
- self->mThread = std::thread(std::mem_fn(&ALCjackPlayback::mixerProc), self);
+ mKillNow.store(false, std::memory_order_release);
+ mThread = std::thread{std::mem_fn(&JackPlayback::mixerProc), this};
return ALC_TRUE;
}
catch(std::exception& e) {
@@ -488,33 +470,31 @@ ALCboolean ALCjackPlayback_start(ALCjackPlayback *self)
}
catch(...) {
}
- jack_deactivate(self->mClient);
+ jack_deactivate(mClient);
return ALC_FALSE;
}
-void ALCjackPlayback_stop(ALCjackPlayback *self)
+void JackPlayback::stop()
{
- if(self->mKillNow.exchange(true, std::memory_order_acq_rel) || !self->mThread.joinable())
+ if(mKillNow.exchange(true, std::memory_order_acq_rel) || !mThread.joinable())
return;
- self->mSem.post();
- self->mThread.join();
+ mSem.post();
+ mThread.join();
- jack_deactivate(self->mClient);
+ jack_deactivate(mClient);
}
-ClockLatency ALCjackPlayback_getClockLatency(ALCjackPlayback *self)
+ClockLatency JackPlayback::getClockLatency()
{
ClockLatency ret;
- ALCjackPlayback_lock(self);
- ALCdevice *device{self->mDevice};
- RingBuffer *ring{self->mRing.get()};
- ret.ClockTime = GetDeviceClockTime(device);
- ret.Latency = std::chrono::seconds{ring->readSpace()};
- ret.Latency /= device->Frequency;
- ALCjackPlayback_unlock(self);
+ lock();
+ ret.ClockTime = GetDeviceClockTime(mDevice);
+ ret.Latency = std::chrono::seconds{mRing->readSpace()};
+ ret.Latency /= mDevice->Frequency;
+ unlock();
return ret;
}
@@ -578,15 +558,10 @@ void JackBackendFactory::probe(DevProbe type, std::string *outnames)
}
}
-ALCbackend *JackBackendFactory::createBackend(ALCdevice *device, ALCbackend_Type type)
+BackendBase *JackBackendFactory::createBackend(ALCdevice *device, ALCbackend_Type type)
{
if(type == ALCbackend_Playback)
- {
- ALCjackPlayback *backend;
- NEW_OBJ(backend, ALCjackPlayback)(device);
- return backend;
- }
-
+ return new JackPlayback{device};
return nullptr;
}