lib/alsa/NonBlock: add common base class
This commit is contained in:
parent
3db8a4f41b
commit
4486b2eded
|
@ -7,6 +7,25 @@
|
||||||
|
|
||||||
namespace Alsa {
|
namespace Alsa {
|
||||||
|
|
||||||
|
std::span<pollfd>
|
||||||
|
NonBlock::CopyReturnedEvents(MultiSocketMonitor &m, std::size_t n) noexcept
|
||||||
|
{
|
||||||
|
const auto pfds = buffer.Get(n), end = pfds + n;
|
||||||
|
|
||||||
|
auto *i = pfds;
|
||||||
|
m.ForEachReturnedEvent([&i, end](SocketDescriptor s, unsigned events){
|
||||||
|
if (i >= end)
|
||||||
|
return;
|
||||||
|
|
||||||
|
i->fd = s.Get();
|
||||||
|
i->events = i->revents = events;
|
||||||
|
++i;
|
||||||
|
});
|
||||||
|
|
||||||
|
return {pfds, static_cast<std::size_t>(i - pfds)};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
Event::Duration
|
Event::Duration
|
||||||
NonBlockPcm::PrepareSockets(MultiSocketMonitor &m, snd_pcm_t *pcm)
|
NonBlockPcm::PrepareSockets(MultiSocketMonitor &m, snd_pcm_t *pcm)
|
||||||
{
|
{
|
||||||
|
@ -18,9 +37,9 @@ NonBlockPcm::PrepareSockets(MultiSocketMonitor &m, snd_pcm_t *pcm)
|
||||||
throw Alsa::MakeError(count, "snd_pcm_poll_descriptors_count() failed");
|
throw Alsa::MakeError(count, "snd_pcm_poll_descriptors_count() failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
struct pollfd *pfds = pfd_buffer.Get(count);
|
const auto pfds = base.Allocate(count);
|
||||||
|
|
||||||
count = snd_pcm_poll_descriptors(pcm, pfds, count);
|
count = snd_pcm_poll_descriptors(pcm, pfds.data(), count);
|
||||||
if (count <= 0) {
|
if (count <= 0) {
|
||||||
if (count == 0)
|
if (count == 0)
|
||||||
throw std::runtime_error("snd_pcm_poll_descriptors() failed");
|
throw std::runtime_error("snd_pcm_poll_descriptors() failed");
|
||||||
|
@ -28,7 +47,7 @@ NonBlockPcm::PrepareSockets(MultiSocketMonitor &m, snd_pcm_t *pcm)
|
||||||
throw Alsa::MakeError(count, "snd_pcm_poll_descriptors() failed");
|
throw Alsa::MakeError(count, "snd_pcm_poll_descriptors() failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
m.ReplaceSocketList({pfds, static_cast<std::size_t>(count)});
|
m.ReplaceSocketList(pfds.first(count));
|
||||||
return Event::Duration(-1);
|
return Event::Duration(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,20 +58,10 @@ NonBlockPcm::DispatchSockets(MultiSocketMonitor &m, snd_pcm_t *pcm)
|
||||||
if (count <= 0)
|
if (count <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const auto pfds = pfd_buffer.Get(count), end = pfds + count;
|
const auto pfds = base.CopyReturnedEvents(m, count);
|
||||||
|
|
||||||
auto *i = pfds;
|
|
||||||
m.ForEachReturnedEvent([&i, end](SocketDescriptor s, unsigned events){
|
|
||||||
if (i >= end)
|
|
||||||
return;
|
|
||||||
|
|
||||||
i->fd = s.Get();
|
|
||||||
i->events = i->revents = events;
|
|
||||||
++i;
|
|
||||||
});
|
|
||||||
|
|
||||||
unsigned short dummy;
|
unsigned short dummy;
|
||||||
int err = snd_pcm_poll_descriptors_revents(pcm, pfds, i - pfds, &dummy);
|
int err = snd_pcm_poll_descriptors_revents(pcm, pfds.data(), pfds.size(), &dummy);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
throw Alsa::MakeError(err, "snd_pcm_poll_descriptors_revents() failed");
|
throw Alsa::MakeError(err, "snd_pcm_poll_descriptors_revents() failed");
|
||||||
}
|
}
|
||||||
|
@ -66,13 +75,13 @@ NonBlockMixer::PrepareSockets(MultiSocketMonitor &m, snd_mixer_t *mixer) noexcep
|
||||||
return Event::Duration(-1);
|
return Event::Duration(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct pollfd *pfds = pfd_buffer.Get(count);
|
const auto pfds = base.Allocate(count);
|
||||||
|
|
||||||
count = snd_mixer_poll_descriptors(mixer, pfds, count);
|
count = snd_mixer_poll_descriptors(mixer, pfds.data(), count);
|
||||||
if (count < 0)
|
if (count < 0)
|
||||||
count = 0;
|
count = 0;
|
||||||
|
|
||||||
m.ReplaceSocketList({pfds, static_cast<std::size_t>(count)});
|
m.ReplaceSocketList(pfds.first(count));
|
||||||
return Event::Duration(-1);
|
return Event::Duration(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,20 +92,10 @@ NonBlockMixer::DispatchSockets(MultiSocketMonitor &m, snd_mixer_t *mixer) noexce
|
||||||
if (count <= 0)
|
if (count <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const auto pfds = pfd_buffer.Get(count), end = pfds + count;
|
const auto pfds = base.CopyReturnedEvents(m, count);
|
||||||
|
|
||||||
auto *i = pfds;
|
|
||||||
m.ForEachReturnedEvent([&i, end](SocketDescriptor s, unsigned events){
|
|
||||||
if (i >= end)
|
|
||||||
return;
|
|
||||||
|
|
||||||
i->fd = s.Get();
|
|
||||||
i->events = i->revents = events;
|
|
||||||
++i;
|
|
||||||
});
|
|
||||||
|
|
||||||
unsigned short dummy;
|
unsigned short dummy;
|
||||||
snd_mixer_poll_descriptors_revents(mixer, pfds, i - pfds, &dummy);
|
snd_mixer_poll_descriptors_revents(mixer, pfds.data(), pfds.size(), &dummy);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Alsa
|
} // namespace Alsa
|
||||||
|
|
|
@ -8,16 +8,30 @@
|
||||||
|
|
||||||
#include <alsa/asoundlib.h>
|
#include <alsa/asoundlib.h>
|
||||||
|
|
||||||
|
#include <span>
|
||||||
|
|
||||||
class MultiSocketMonitor;
|
class MultiSocketMonitor;
|
||||||
|
|
||||||
namespace Alsa {
|
namespace Alsa {
|
||||||
|
|
||||||
|
class NonBlock {
|
||||||
|
ReusableArray<pollfd> buffer;
|
||||||
|
|
||||||
|
public:
|
||||||
|
std::span<pollfd> Allocate(std::size_t n) noexcept {
|
||||||
|
return {buffer.Get(n), n};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::span<pollfd> CopyReturnedEvents(MultiSocketMonitor &m,
|
||||||
|
std::size_t n) noexcept;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper class for #MultiSocketMonitor's virtual methods which
|
* Helper class for #MultiSocketMonitor's virtual methods which
|
||||||
* manages the file descriptors for a #snd_pcm_t.
|
* manages the file descriptors for a #snd_pcm_t.
|
||||||
*/
|
*/
|
||||||
class NonBlockPcm {
|
class NonBlockPcm {
|
||||||
ReusableArray<pollfd> pfd_buffer;
|
NonBlock base;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
|
@ -40,7 +54,7 @@ public:
|
||||||
* manages the file descriptors for a #snd_mixer_t.
|
* manages the file descriptors for a #snd_mixer_t.
|
||||||
*/
|
*/
|
||||||
class NonBlockMixer {
|
class NonBlockMixer {
|
||||||
ReusableArray<pollfd> pfd_buffer;
|
NonBlock base;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Event::Duration PrepareSockets(MultiSocketMonitor &m,
|
Event::Duration PrepareSockets(MultiSocketMonitor &m,
|
||||||
|
|
Loading…
Reference in New Issue