|
@@ -35,6 +35,7 @@
|
|
|
#include <cerrno>
|
|
|
#include <chrono>
|
|
|
#include <ctime>
|
|
|
+#include <functional>
|
|
|
#include <iterator>
|
|
|
#include <memory>
|
|
|
#include <mutex>
|
|
@@ -54,6 +55,8 @@
|
|
|
#include "core/helpers.h"
|
|
|
#include "core/logging.h"
|
|
|
#include "dynload.h"
|
|
|
+#include "fmt/core.h"
|
|
|
+#include "fmt/ranges.h"
|
|
|
#include "opthelpers.h"
|
|
|
#include "ringbuffer.h"
|
|
|
|
|
@@ -132,6 +135,9 @@ _Pragma("GCC diagnostic pop")
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
+template<typename T> [[nodiscard]] constexpr
|
|
|
+auto as_const_ptr(T *ptr) noexcept -> std::add_const_t<T>* { return ptr; }
|
|
|
+
|
|
|
struct PodDynamicBuilder {
|
|
|
private:
|
|
|
std::vector<std::byte> mStorage;
|
|
@@ -143,7 +149,7 @@ private:
|
|
|
mStorage.resize(size);
|
|
|
}
|
|
|
catch(...) {
|
|
|
- ERR("Failed to resize POD storage\n");
|
|
|
+ ERR("Failed to resize POD storage");
|
|
|
return -ENOMEM;
|
|
|
}
|
|
|
mPod.data = mStorage.data();
|
|
@@ -152,7 +158,7 @@ private:
|
|
|
}
|
|
|
|
|
|
public:
|
|
|
- PodDynamicBuilder(uint32_t initSize=0) : mStorage(initSize)
|
|
|
+ explicit PodDynamicBuilder(uint32_t initSize=1024) : mStorage(initSize)
|
|
|
, mPod{make_pod_builder(mStorage.data(), initSize)}
|
|
|
{
|
|
|
static constexpr auto callbacks{[]
|
|
@@ -189,12 +195,13 @@ bool check_version(const char *version)
|
|
|
* future.
|
|
|
*/
|
|
|
int major{0}, minor{0}, revision{0};
|
|
|
+ /* NOLINTNEXTLINE(cert-err34-c,cppcoreguidelines-pro-type-vararg) */
|
|
|
int ret{sscanf(version, "%d.%d.%d", &major, &minor, &revision)};
|
|
|
return ret == 3 && (major > PW_MAJOR || (major == PW_MAJOR && minor > PW_MINOR)
|
|
|
|| (major == PW_MAJOR && minor == PW_MINOR && revision >= PW_MICRO));
|
|
|
}
|
|
|
|
|
|
-#ifdef HAVE_DYNLOAD
|
|
|
+#if HAVE_DYNLOAD
|
|
|
#define PWIRE_FUNCS(MAGIC) \
|
|
|
MAGIC(pw_context_connect) \
|
|
|
MAGIC(pw_context_destroy) \
|
|
@@ -251,7 +258,7 @@ bool pwire_load()
|
|
|
pwire_handle = LoadLib(pwire_library);
|
|
|
if(!pwire_handle)
|
|
|
{
|
|
|
- WARN("Failed to load %s\n", pwire_library);
|
|
|
+ WARN("Failed to load {}", pwire_library);
|
|
|
return false;
|
|
|
}
|
|
|
|
|
@@ -265,7 +272,7 @@ bool pwire_load()
|
|
|
|
|
|
if(!missing_funcs.empty())
|
|
|
{
|
|
|
- WARN("Missing expected functions:%s\n", missing_funcs.c_str());
|
|
|
+ WARN("Missing expected functions:{}", missing_funcs);
|
|
|
CloseLib(pwire_handle);
|
|
|
pwire_handle = nullptr;
|
|
|
return false;
|
|
@@ -411,9 +418,10 @@ struct PwStreamDeleter {
|
|
|
};
|
|
|
using PwStreamPtr = std::unique_ptr<pw_stream,PwStreamDeleter>;
|
|
|
|
|
|
-/* Enums for bitflags... again... *sigh* */
|
|
|
+/* NOLINTBEGIN(*EnumCastOutOfRange) Enums for bitflags... again... *sigh* */
|
|
|
constexpr pw_stream_flags operator|(pw_stream_flags lhs, pw_stream_flags rhs) noexcept
|
|
|
{ return static_cast<pw_stream_flags>(lhs | al::to_underlying(rhs)); }
|
|
|
+/* NOLINTEND(*EnumCastOutOfRange) */
|
|
|
|
|
|
constexpr pw_stream_flags& operator|=(pw_stream_flags &lhs, pw_stream_flags rhs) noexcept
|
|
|
{ lhs = lhs | rhs; return lhs; }
|
|
@@ -497,7 +505,7 @@ struct NodeProxy {
|
|
|
|
|
|
uint32_t mId{};
|
|
|
|
|
|
- PwNodePtr mNode{};
|
|
|
+ PwNodePtr mNode;
|
|
|
spa_hook mListener{};
|
|
|
|
|
|
NodeProxy(uint32_t id, PwNodePtr node)
|
|
@@ -532,7 +540,7 @@ struct MetadataProxy {
|
|
|
|
|
|
uint32_t mId{};
|
|
|
|
|
|
- PwMetadataPtr mMetadata{};
|
|
|
+ PwMetadataPtr mMetadata;
|
|
|
spa_hook mListener{};
|
|
|
|
|
|
MetadataProxy(uint32_t id, PwMetadataPtr mdata)
|
|
@@ -553,10 +561,10 @@ struct MetadataProxy {
|
|
|
* to objects being added to or removed from the registry.
|
|
|
*/
|
|
|
struct EventManager {
|
|
|
- ThreadMainloop mLoop{};
|
|
|
- PwContextPtr mContext{};
|
|
|
- PwCorePtr mCore{};
|
|
|
- PwRegistryPtr mRegistry{};
|
|
|
+ ThreadMainloop mLoop;
|
|
|
+ PwContextPtr mContext;
|
|
|
+ PwCorePtr mCore;
|
|
|
+ PwRegistryPtr mRegistry;
|
|
|
spa_hook mRegistryListener{};
|
|
|
spa_hook mCoreListener{};
|
|
|
|
|
@@ -585,8 +593,8 @@ struct EventManager {
|
|
|
auto lock() const { return mLoop.lock(); }
|
|
|
auto unlock() const { return mLoop.unlock(); }
|
|
|
|
|
|
- [[nodiscard]] inline
|
|
|
- bool initIsDone(std::memory_order m=std::memory_order_seq_cst) const noexcept
|
|
|
+ [[nodiscard]]
|
|
|
+ auto initIsDone(std::memory_order m=std::memory_order_seq_cst) const noexcept -> bool
|
|
|
{ return mInitDone.load(m); }
|
|
|
|
|
|
/**
|
|
@@ -759,7 +767,7 @@ void DeviceNode::Remove(uint32_t id)
|
|
|
{
|
|
|
if(n.mId != id)
|
|
|
return false;
|
|
|
- TRACE("Removing device \"%s\"\n", n.mDevName.c_str());
|
|
|
+ TRACE("Removing device \"{}\"", n.mDevName);
|
|
|
if(gEventHandler.initIsDone(std::memory_order_relaxed))
|
|
|
{
|
|
|
const std::string msg{"Device removed: "+n.mName};
|
|
@@ -828,7 +836,7 @@ void DeviceNode::parseSampleRate(const spa_pod *value, bool force_update) noexce
|
|
|
const uint podType{get_pod_type(value)};
|
|
|
if(podType != SPA_TYPE_Int)
|
|
|
{
|
|
|
- WARN(" Unhandled sample rate POD type: %u\n", podType);
|
|
|
+ WARN(" Unhandled sample rate POD type: {}", podType);
|
|
|
return;
|
|
|
}
|
|
|
|
|
@@ -836,13 +844,13 @@ void DeviceNode::parseSampleRate(const spa_pod *value, bool force_update) noexce
|
|
|
{
|
|
|
if(nvals != 3)
|
|
|
{
|
|
|
- WARN(" Unexpected SPA_CHOICE_Range count: %u\n", nvals);
|
|
|
+ WARN(" Unexpected SPA_CHOICE_Range count: {}", nvals);
|
|
|
return;
|
|
|
}
|
|
|
auto srates = get_pod_body<int32_t,3>(value);
|
|
|
|
|
|
/* [0] is the default, [1] is the min, and [2] is the max. */
|
|
|
- TRACE(" sample rate: %d (range: %d -> %d)\n", srates[0], srates[1], srates[2]);
|
|
|
+ TRACE(" sample rate: {}, range: {}", srates[0], srates.subspan<1>());
|
|
|
if(!mSampleRate || force_update)
|
|
|
mSampleRate = static_cast<uint>(std::clamp<int>(srates[0], MinOutputRate,
|
|
|
MaxOutputRate));
|
|
@@ -853,19 +861,13 @@ void DeviceNode::parseSampleRate(const spa_pod *value, bool force_update) noexce
|
|
|
{
|
|
|
if(nvals == 0)
|
|
|
{
|
|
|
- WARN(" Unexpected SPA_CHOICE_Enum count: %u\n", nvals);
|
|
|
+ WARN(" Unexpected SPA_CHOICE_Enum count: {}", nvals);
|
|
|
return;
|
|
|
}
|
|
|
auto srates = get_pod_body<int32_t>(value, nvals);
|
|
|
|
|
|
/* [0] is the default, [1...size()-1] are available selections. */
|
|
|
- std::string others{(srates.size() > 1) ? std::to_string(srates[1]) : std::string{}};
|
|
|
- for(size_t i{2};i < srates.size();++i)
|
|
|
- {
|
|
|
- others += ", ";
|
|
|
- others += std::to_string(srates[i]);
|
|
|
- }
|
|
|
- TRACE(" sample rate: %d (%s)\n", srates[0], others.c_str());
|
|
|
+ TRACE(" sample rate: {}, list: {}", srates[0], srates.subspan(1));
|
|
|
/* Pick the first rate listed that's within the allowed range (default
|
|
|
* rate if possible).
|
|
|
*/
|
|
@@ -885,19 +887,19 @@ void DeviceNode::parseSampleRate(const spa_pod *value, bool force_update) noexce
|
|
|
{
|
|
|
if(nvals != 1)
|
|
|
{
|
|
|
- WARN(" Unexpected SPA_CHOICE_None count: %u\n", nvals);
|
|
|
+ WARN(" Unexpected SPA_CHOICE_None count: {}", nvals);
|
|
|
return;
|
|
|
}
|
|
|
auto srates = get_pod_body<int32_t,1>(value);
|
|
|
|
|
|
- TRACE(" sample rate: %d\n", srates[0]);
|
|
|
+ TRACE(" sample rate: {}", srates[0]);
|
|
|
if(!mSampleRate || force_update)
|
|
|
mSampleRate = static_cast<uint>(std::clamp<int>(srates[0], MinOutputRate,
|
|
|
MaxOutputRate));
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- WARN(" Unhandled sample rate choice type: %u\n", choiceType);
|
|
|
+ WARN(" Unhandled sample rate choice type: {}", choiceType);
|
|
|
}
|
|
|
|
|
|
void DeviceNode::parsePositions(const spa_pod *value, bool force_update) noexcept
|
|
@@ -907,7 +909,7 @@ void DeviceNode::parsePositions(const spa_pod *value, bool force_update) noexcep
|
|
|
|
|
|
if(choiceType != SPA_CHOICE_None || choiceCount != 1)
|
|
|
{
|
|
|
- ERR(" Unexpected positions choice: type=%u, count=%u\n", choiceType, choiceCount);
|
|
|
+ ERR(" Unexpected positions choice: type={}, count={}", choiceType, choiceCount);
|
|
|
return;
|
|
|
}
|
|
|
|
|
@@ -938,7 +940,7 @@ void DeviceNode::parsePositions(const spa_pod *value, bool force_update) noexcep
|
|
|
else
|
|
|
mChannels = DevFmtMono;
|
|
|
}
|
|
|
- TRACE(" %zu position%s for %s%s\n", chanmap.size(), (chanmap.size()==1)?"":"s",
|
|
|
+ TRACE(" {} position{} for {}{}", chanmap.size(), (chanmap.size()==1)?"":"s",
|
|
|
DevFmtChannelsString(mChannels), mIs51Rear?"(rear)":"");
|
|
|
}
|
|
|
|
|
@@ -950,7 +952,7 @@ void DeviceNode::parseChannelCount(const spa_pod *value, bool force_update) noex
|
|
|
|
|
|
if(choiceType != SPA_CHOICE_None || choiceCount != 1)
|
|
|
{
|
|
|
- ERR(" Unexpected positions choice: type=%u, count=%u\n", choiceType, choiceCount);
|
|
|
+ ERR(" Unexpected positions choice: type={}, count={}", choiceType, choiceCount);
|
|
|
return;
|
|
|
}
|
|
|
|
|
@@ -966,7 +968,7 @@ void DeviceNode::parseChannelCount(const spa_pod *value, bool force_update) noex
|
|
|
else if(*chancount >= 1)
|
|
|
mChannels = DevFmtMono;
|
|
|
}
|
|
|
- TRACE(" %d channel%s for %s\n", *chancount, (*chancount==1)?"":"s",
|
|
|
+ TRACE(" {} channel{} for {}", *chancount, (*chancount==1)?"":"s",
|
|
|
DevFmtChannelsString(mChannels));
|
|
|
}
|
|
|
|
|
@@ -1005,7 +1007,7 @@ void NodeProxy::infoCallback(void*, const pw_node_info *info) noexcept
|
|
|
ntype = NodeType::Duplex;
|
|
|
else
|
|
|
{
|
|
|
- TRACE("Dropping device node %u which became type \"%s\"\n", info->id, media_class);
|
|
|
+ TRACE("Dropping device node {} which became type \"{}\"", info->id, media_class);
|
|
|
DeviceNode::Remove(info->id);
|
|
|
return;
|
|
|
}
|
|
@@ -1024,20 +1026,23 @@ void NodeProxy::infoCallback(void*, const pw_node_info *info) noexcept
|
|
|
serial_id = std::strtoull(serial_str, &serial_end, 0);
|
|
|
if(*serial_end != '\0' || errno == ERANGE)
|
|
|
{
|
|
|
- ERR("Unexpected object serial: %s\n", serial_str);
|
|
|
+ ERR("Unexpected object serial: {}", serial_str);
|
|
|
serial_id = info->id;
|
|
|
}
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
- std::string name;
|
|
|
- if(nodeName && *nodeName) name = nodeName;
|
|
|
- else name = "PipeWire node #"+std::to_string(info->id);
|
|
|
+ auto name = std::invoke([nodeName,info]() -> std::string
|
|
|
+ {
|
|
|
+ if(nodeName && *nodeName)
|
|
|
+ return std::string{nodeName};
|
|
|
+ return fmt::format("PipeWire node #{}", info->id);
|
|
|
+ });
|
|
|
|
|
|
const char *form_factor{spa_dict_lookup(info->props, PW_KEY_DEVICE_FORM_FACTOR)};
|
|
|
- TRACE("Got %s device \"%s\"%s%s%s\n", AsString(ntype), devName ? devName : "(nil)",
|
|
|
+ TRACE("Got {} device \"{}\"{}{}{}", AsString(ntype), devName ? devName : "(nil)",
|
|
|
form_factor?" (":"", form_factor?form_factor:"", form_factor?")":"");
|
|
|
- TRACE(" \"%s\" = ID %" PRIu64 "\n", name.c_str(), serial_id);
|
|
|
+ TRACE(" \"{}\" = ID {}", name, serial_id);
|
|
|
|
|
|
DeviceNode &node = DeviceNode::Add(info->id);
|
|
|
node.mSerial = serial_id;
|
|
@@ -1087,7 +1092,7 @@ void NodeProxy::paramCallback(int, uint32_t id, uint32_t, uint32_t, const spa_po
|
|
|
DeviceNode *node{DeviceNode::Find(mId)};
|
|
|
if(!node) UNLIKELY return;
|
|
|
|
|
|
- TRACE("Device ID %" PRIu64 " %s format%s:\n", node->mSerial,
|
|
|
+ TRACE("Device ID {} {} format{}:", node->mSerial,
|
|
|
(id == SPA_PARAM_EnumFormat) ? "available" : "current",
|
|
|
(id == SPA_PARAM_EnumFormat) ? "s" : "");
|
|
|
|
|
@@ -1122,14 +1127,14 @@ auto MetadataProxy::propertyCallback(void*, uint32_t id, const char *key, const
|
|
|
|
|
|
if(!type)
|
|
|
{
|
|
|
- TRACE("Default %s device cleared\n", isCapture ? "capture" : "playback");
|
|
|
+ TRACE("Default {} device cleared", isCapture ? "capture" : "playback");
|
|
|
if(!isCapture) DefaultSinkDevice.clear();
|
|
|
else DefaultSourceDevice.clear();
|
|
|
return 0;
|
|
|
}
|
|
|
if("Spa:String:JSON"sv != type)
|
|
|
{
|
|
|
- ERR("Unexpected %s property type: %s\n", key, type);
|
|
|
+ ERR("Unexpected {} property type: {}", key, type);
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -1160,8 +1165,8 @@ auto MetadataProxy::propertyCallback(void*, uint32_t id, const char *key, const
|
|
|
auto propValue = get_json_string(&std::get<1>(it));
|
|
|
if(!propValue) break;
|
|
|
|
|
|
- TRACE("Got default %s device \"%s\"\n", isCapture ? "capture" : "playback",
|
|
|
- propValue->c_str());
|
|
|
+ TRACE("Got default {} device \"{}\"", isCapture ? "capture" : "playback",
|
|
|
+ *propValue);
|
|
|
if(!isCapture && DefaultSinkDevice != *propValue)
|
|
|
{
|
|
|
if(gEventHandler.mInitDone.load(std::memory_order_relaxed))
|
|
@@ -1203,28 +1208,28 @@ bool EventManager::init()
|
|
|
mLoop = ThreadMainloop::Create("PWEventThread");
|
|
|
if(!mLoop)
|
|
|
{
|
|
|
- ERR("Failed to create PipeWire event thread loop (errno: %d)\n", errno);
|
|
|
+ ERR("Failed to create PipeWire event thread loop (errno: {})", errno);
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
mContext = mLoop.newContext();
|
|
|
if(!mContext)
|
|
|
{
|
|
|
- ERR("Failed to create PipeWire event context (errno: %d)\n", errno);
|
|
|
+ ERR("Failed to create PipeWire event context (errno: {})", errno);
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
mCore = PwCorePtr{pw_context_connect(mContext.get(), nullptr, 0)};
|
|
|
if(!mCore)
|
|
|
{
|
|
|
- ERR("Failed to connect PipeWire event context (errno: %d)\n", errno);
|
|
|
+ ERR("Failed to connect PipeWire event context (errno: {})", errno);
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
mRegistry = PwRegistryPtr{pw_core_get_registry(mCore.get(), PW_VERSION_REGISTRY, 0)};
|
|
|
if(!mRegistry)
|
|
|
{
|
|
|
- ERR("Failed to get PipeWire event registry (errno: %d)\n", errno);
|
|
|
+ ERR("Failed to get PipeWire event registry (errno: {})", errno);
|
|
|
return false;
|
|
|
}
|
|
|
|
|
@@ -1241,7 +1246,7 @@ bool EventManager::init()
|
|
|
|
|
|
if(int res{mLoop.start()})
|
|
|
{
|
|
|
- ERR("Failed to start PipeWire event thread loop (res: %d)\n", res);
|
|
|
+ ERR("Failed to start PipeWire event thread loop (res: {})", res);
|
|
|
return false;
|
|
|
}
|
|
|
|
|
@@ -1279,7 +1284,7 @@ void EventManager::addCallback(uint32_t id, uint32_t, const char *type, uint32_t
|
|
|
if(!isGood)
|
|
|
{
|
|
|
if(!al::contains(className, "/Video"sv) && !al::starts_with(className, "Stream/"sv))
|
|
|
- TRACE("Ignoring node class %s\n", media_class);
|
|
|
+ TRACE("Ignoring node class {}", media_class);
|
|
|
return;
|
|
|
}
|
|
|
|
|
@@ -1288,7 +1293,7 @@ void EventManager::addCallback(uint32_t id, uint32_t, const char *type, uint32_t
|
|
|
version, 0))};
|
|
|
if(!node)
|
|
|
{
|
|
|
- ERR("Failed to create node proxy object (errno: %d)\n", errno);
|
|
|
+ ERR("Failed to create node proxy object (errno: {})", errno);
|
|
|
return;
|
|
|
}
|
|
|
|
|
@@ -1311,13 +1316,13 @@ void EventManager::addCallback(uint32_t id, uint32_t, const char *type, uint32_t
|
|
|
|
|
|
if("default"sv != data_class)
|
|
|
{
|
|
|
- TRACE("Ignoring metadata \"%s\"\n", data_class);
|
|
|
+ TRACE("Ignoring metadata \"{}\"", data_class);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
if(mDefaultMetadata)
|
|
|
{
|
|
|
- ERR("Duplicate default metadata\n");
|
|
|
+ ERR("Duplicate default metadata");
|
|
|
return;
|
|
|
}
|
|
|
|
|
@@ -1325,7 +1330,7 @@ void EventManager::addCallback(uint32_t id, uint32_t, const char *type, uint32_t
|
|
|
type, version, 0))};
|
|
|
if(!mdata)
|
|
|
{
|
|
|
- ERR("Failed to create metadata proxy object (errno: %d)\n", errno);
|
|
|
+ ERR("Failed to create metadata proxy object (errno: {})", errno);
|
|
|
return;
|
|
|
}
|
|
|
|
|
@@ -1382,7 +1387,7 @@ spa_audio_info_raw make_spa_info(DeviceBase *device, bool is51rear, use_f32p_e u
|
|
|
case DevFmtFloat: info.format = SPA_AUDIO_FORMAT_F32; break;
|
|
|
}
|
|
|
|
|
|
- info.rate = device->Frequency;
|
|
|
+ info.rate = device->mSampleRate;
|
|
|
|
|
|
al::span<const spa_audio_channel> map{};
|
|
|
switch(device->FmtChans)
|
|
@@ -1432,7 +1437,7 @@ class PipeWirePlayback final : public BackendBase {
|
|
|
PwStreamPtr mStream;
|
|
|
spa_hook mStreamListener{};
|
|
|
spa_io_rate_match *mRateMatch{};
|
|
|
- std::vector<float*> mChannelPtrs;
|
|
|
+ std::vector<void*> mChannelPtrs;
|
|
|
|
|
|
static constexpr pw_stream_events CreateEvents()
|
|
|
{
|
|
@@ -1448,7 +1453,7 @@ class PipeWirePlayback final : public BackendBase {
|
|
|
}
|
|
|
|
|
|
public:
|
|
|
- PipeWirePlayback(DeviceBase *device) noexcept : BackendBase{device} { }
|
|
|
+ explicit PipeWirePlayback(DeviceBase *device) noexcept : BackendBase{device} { }
|
|
|
~PipeWirePlayback() final
|
|
|
{
|
|
|
/* Stop the mainloop so the stream can be properly destroyed. */
|
|
@@ -1492,7 +1497,7 @@ void PipeWirePlayback::outputCallback() noexcept
|
|
|
uint length{mRateMatch ? mRateMatch->size : 0u};
|
|
|
#endif
|
|
|
/* If no length is specified, use the device's update size as a fallback. */
|
|
|
- if(!length) UNLIKELY length = mDevice->UpdateSize;
|
|
|
+ if(!length) UNLIKELY length = mDevice->mUpdateSize;
|
|
|
|
|
|
/* For planar formats, each datas[] seems to contain one channel, so store
|
|
|
* the pointers in an array. Limit the render length in case the available
|
|
@@ -1503,7 +1508,7 @@ void PipeWirePlayback::outputCallback() noexcept
|
|
|
for(const auto &data : datas)
|
|
|
{
|
|
|
length = std::min(length, data.maxsize/uint{sizeof(float)});
|
|
|
- *chanptr_end = static_cast<float*>(data.data);
|
|
|
+ *chanptr_end = data.data;
|
|
|
++chanptr_end;
|
|
|
|
|
|
data.chunk->offset = 0;
|
|
@@ -1560,7 +1565,7 @@ void PipeWirePlayback::open(std::string_view name)
|
|
|
auto match = std::find_if(devlist.cbegin(), devlist.cend(), match_name);
|
|
|
if(match == devlist.cend())
|
|
|
throw al::backend_exception{al::backend_error::NoDevice,
|
|
|
- "Device name \"%.*s\" not found", al::sizei(name), name.data()};
|
|
|
+ "Device name \"{}\" not found", name};
|
|
|
|
|
|
targetid = match->mSerial;
|
|
|
devname = match->mName;
|
|
@@ -1568,15 +1573,15 @@ void PipeWirePlayback::open(std::string_view name)
|
|
|
|
|
|
if(!mLoop)
|
|
|
{
|
|
|
- const uint count{OpenCount.fetch_add(1, std::memory_order_relaxed)};
|
|
|
- const std::string thread_name{"ALSoftP" + std::to_string(count)};
|
|
|
+ const auto count = OpenCount.fetch_add(1u, std::memory_order_relaxed);
|
|
|
+ const auto thread_name = fmt::format("ALSoftP{}", count);
|
|
|
mLoop = ThreadMainloop::Create(thread_name.c_str());
|
|
|
if(!mLoop)
|
|
|
throw al::backend_exception{al::backend_error::DeviceError,
|
|
|
- "Failed to create PipeWire mainloop (errno: %d)", errno};
|
|
|
+ "Failed to create PipeWire mainloop (errno: {})", errno};
|
|
|
if(int res{mLoop.start()})
|
|
|
throw al::backend_exception{al::backend_error::DeviceError,
|
|
|
- "Failed to start PipeWire mainloop (res: %d)", res};
|
|
|
+ "Failed to start PipeWire mainloop (res: {})", res};
|
|
|
}
|
|
|
MainloopUniqueLock mlock{mLoop};
|
|
|
if(!mContext)
|
|
@@ -1585,14 +1590,14 @@ void PipeWirePlayback::open(std::string_view name)
|
|
|
mContext = mLoop.newContext(cprops);
|
|
|
if(!mContext)
|
|
|
throw al::backend_exception{al::backend_error::DeviceError,
|
|
|
- "Failed to create PipeWire event context (errno: %d)\n", errno};
|
|
|
+ "Failed to create PipeWire event context (errno: {})\n", errno};
|
|
|
}
|
|
|
if(!mCore)
|
|
|
{
|
|
|
mCore = PwCorePtr{pw_context_connect(mContext.get(), nullptr, 0)};
|
|
|
if(!mCore)
|
|
|
throw al::backend_exception{al::backend_error::DeviceError,
|
|
|
- "Failed to connect PipeWire event context (errno: %d)\n", errno};
|
|
|
+ "Failed to connect PipeWire event context (errno: {})\n", errno};
|
|
|
}
|
|
|
mlock.unlock();
|
|
|
|
|
@@ -1600,9 +1605,9 @@ void PipeWirePlayback::open(std::string_view name)
|
|
|
|
|
|
mTargetId = targetid;
|
|
|
if(!devname.empty())
|
|
|
- mDevice->DeviceName = std::move(devname);
|
|
|
+ mDeviceName = std::move(devname);
|
|
|
else
|
|
|
- mDevice->DeviceName = "PipeWire Output"sv;
|
|
|
+ mDeviceName = "PipeWire Output"sv;
|
|
|
}
|
|
|
|
|
|
bool PipeWirePlayback::reset()
|
|
@@ -1634,13 +1639,13 @@ bool PipeWirePlayback::reset()
|
|
|
if(!mDevice->Flags.test(FrequencyRequest) && match->mSampleRate > 0)
|
|
|
{
|
|
|
/* Scale the update size if the sample rate changes. */
|
|
|
- const double scale{static_cast<double>(match->mSampleRate) / mDevice->Frequency};
|
|
|
- const double updatesize{std::round(mDevice->UpdateSize * scale)};
|
|
|
- const double buffersize{std::round(mDevice->BufferSize * scale)};
|
|
|
+ const double scale{static_cast<double>(match->mSampleRate) / mDevice->mSampleRate};
|
|
|
+ const double updatesize{std::round(mDevice->mUpdateSize * scale)};
|
|
|
+ const double buffersize{std::round(mDevice->mBufferSize * scale)};
|
|
|
|
|
|
- mDevice->Frequency = match->mSampleRate;
|
|
|
- mDevice->UpdateSize = static_cast<uint>(std::clamp(updatesize, 64.0, 8192.0));
|
|
|
- mDevice->BufferSize = static_cast<uint>(std::max(buffersize, 128.0));
|
|
|
+ mDevice->mSampleRate = match->mSampleRate;
|
|
|
+ mDevice->mUpdateSize = static_cast<uint>(std::clamp(updatesize, 64.0, 8192.0));
|
|
|
+ mDevice->mBufferSize = static_cast<uint>(std::max(buffersize, 128.0));
|
|
|
}
|
|
|
if(!mDevice->Flags.test(ChannelsRequest) && match->mChannels != InvalidChannelConfig)
|
|
|
mDevice->FmtChans = match->mChannels;
|
|
@@ -1652,12 +1657,10 @@ bool PipeWirePlayback::reset()
|
|
|
/* Force planar 32-bit float output for playback. This is what PipeWire
|
|
|
* handles internally, and it's easier for us too.
|
|
|
*/
|
|
|
- spa_audio_info_raw info{make_spa_info(mDevice, is51rear, ForceF32Planar)};
|
|
|
+ auto info = spa_audio_info_raw{make_spa_info(mDevice, is51rear, ForceF32Planar)};
|
|
|
|
|
|
- static constexpr uint32_t pod_buffer_size{1024};
|
|
|
- PodDynamicBuilder b(pod_buffer_size);
|
|
|
-
|
|
|
- const spa_pod *params{spa_format_audio_raw_build(b.get(), SPA_PARAM_EnumFormat, &info)};
|
|
|
+ auto b = PodDynamicBuilder{};
|
|
|
+ auto params = as_const_ptr(spa_format_audio_raw_build(b.get(), SPA_PARAM_EnumFormat, &info));
|
|
|
if(!params)
|
|
|
throw al::backend_exception{al::backend_error::DeviceError,
|
|
|
"Failed to set PipeWire audio format parameters"};
|
|
@@ -1666,7 +1669,7 @@ bool PipeWirePlayback::reset()
|
|
|
* be useful?
|
|
|
*/
|
|
|
auto&& binary = GetProcBinary();
|
|
|
- const char *appname{binary.fname.length() ? binary.fname.c_str() : "OpenAL Soft"};
|
|
|
+ const char *appname{!binary.fname.empty() ? binary.fname.c_str() : "OpenAL Soft"};
|
|
|
pw_properties *props{pw_properties_new(PW_KEY_NODE_NAME, appname,
|
|
|
PW_KEY_NODE_DESCRIPTION, appname,
|
|
|
PW_KEY_MEDIA_TYPE, "Audio",
|
|
@@ -1676,11 +1679,11 @@ bool PipeWirePlayback::reset()
|
|
|
nullptr)};
|
|
|
if(!props)
|
|
|
throw al::backend_exception{al::backend_error::DeviceError,
|
|
|
- "Failed to create PipeWire stream properties (errno: %d)", errno};
|
|
|
+ "Failed to create PipeWire stream properties (errno: {})", errno};
|
|
|
|
|
|
- pw_properties_setf(props, PW_KEY_NODE_LATENCY, "%u/%u", mDevice->UpdateSize,
|
|
|
- mDevice->Frequency);
|
|
|
- pw_properties_setf(props, PW_KEY_NODE_RATE, "1/%u", mDevice->Frequency);
|
|
|
+ pw_properties_setf(props, PW_KEY_NODE_LATENCY, "%u/%u", mDevice->mUpdateSize,
|
|
|
+ mDevice->mSampleRate);
|
|
|
+ pw_properties_setf(props, PW_KEY_NODE_RATE, "1/%u", mDevice->mSampleRate);
|
|
|
#ifdef PW_KEY_TARGET_OBJECT
|
|
|
pw_properties_setf(props, PW_KEY_TARGET_OBJECT, "%" PRIu64, mTargetId);
|
|
|
#else
|
|
@@ -1692,17 +1695,17 @@ bool PipeWirePlayback::reset()
|
|
|
mStream = PwStreamPtr{pw_stream_new(mCore.get(), "Playback Stream", props)};
|
|
|
if(!mStream)
|
|
|
throw al::backend_exception{al::backend_error::NoDevice,
|
|
|
- "Failed to create PipeWire stream (errno: %d)", errno};
|
|
|
+ "Failed to create PipeWire stream (errno: {})", errno};
|
|
|
static constexpr pw_stream_events streamEvents{CreateEvents()};
|
|
|
pw_stream_add_listener(mStream.get(), &mStreamListener, &streamEvents, this);
|
|
|
|
|
|
pw_stream_flags flags{PW_STREAM_FLAG_AUTOCONNECT | PW_STREAM_FLAG_INACTIVE
|
|
|
| PW_STREAM_FLAG_MAP_BUFFERS};
|
|
|
- if(GetConfigValueBool(mDevice->DeviceName, "pipewire", "rt-mix", false))
|
|
|
+ if(GetConfigValueBool(mDevice->mDeviceName, "pipewire", "rt-mix", false))
|
|
|
flags |= PW_STREAM_FLAG_RT_PROCESS;
|
|
|
if(int res{pw_stream_connect(mStream.get(), PW_DIRECTION_OUTPUT, PwIdAny, flags, ¶ms, 1)})
|
|
|
throw al::backend_exception{al::backend_error::DeviceError,
|
|
|
- "Error connecting PipeWire stream (res: %d)", res};
|
|
|
+ "Error connecting PipeWire stream (res: {})", res};
|
|
|
|
|
|
/* Wait for the stream to become paused (ready to start streaming). */
|
|
|
plock.wait([stream=mStream.get()]()
|
|
@@ -1711,12 +1714,12 @@ bool PipeWirePlayback::reset()
|
|
|
pw_stream_state state{pw_stream_get_state(stream, &error)};
|
|
|
if(state == PW_STREAM_STATE_ERROR)
|
|
|
throw al::backend_exception{al::backend_error::DeviceError,
|
|
|
- "Error connecting PipeWire stream: \"%s\"", error};
|
|
|
+ "Error connecting PipeWire stream: \"{}\"", error};
|
|
|
return state == PW_STREAM_STATE_PAUSED;
|
|
|
});
|
|
|
|
|
|
- /* TODO: Update mDevice->UpdateSize with the stream's quantum, and
|
|
|
- * mDevice->BufferSize with the total known buffering delay from the head
|
|
|
+ /* TODO: Update mDevice->mUpdateSize with the stream's quantum, and
|
|
|
+ * mDevice->mBufferSize with the total known buffering delay from the head
|
|
|
* of this playback stream to the tail of the device output.
|
|
|
*
|
|
|
* This info is apparently not available until after the stream starts.
|
|
@@ -1735,7 +1738,7 @@ void PipeWirePlayback::start()
|
|
|
MainloopUniqueLock plock{mLoop};
|
|
|
if(int res{pw_stream_set_active(mStream.get(), true)})
|
|
|
throw al::backend_exception{al::backend_error::DeviceError,
|
|
|
- "Failed to start PipeWire stream (res: %d)", res};
|
|
|
+ "Failed to start PipeWire stream (res: {})", res};
|
|
|
|
|
|
/* Wait for the stream to start playing (would be nice to not, but we need
|
|
|
* the actual update size which is only available after starting).
|
|
@@ -1746,7 +1749,7 @@ void PipeWirePlayback::start()
|
|
|
pw_stream_state state{pw_stream_get_state(stream, &error)};
|
|
|
if(state == PW_STREAM_STATE_ERROR)
|
|
|
throw al::backend_exception{al::backend_error::DeviceError,
|
|
|
- "PipeWire stream error: %s", error ? error : "(unknown)"};
|
|
|
+ "PipeWire stream error: {}", error ? error : "(unknown)"};
|
|
|
return state == PW_STREAM_STATE_STREAMING;
|
|
|
});
|
|
|
|
|
@@ -1761,7 +1764,7 @@ void PipeWirePlayback::start()
|
|
|
pw_time ptime{};
|
|
|
if(int res{pw_stream_get_time_n(mStream.get(), &ptime, sizeof(ptime))})
|
|
|
{
|
|
|
- ERR("Failed to get PipeWire stream time (res: %d)\n", res);
|
|
|
+ ERR("Failed to get PipeWire stream time (res: {})", res);
|
|
|
break;
|
|
|
}
|
|
|
|
|
@@ -1776,11 +1779,11 @@ void PipeWirePlayback::start()
|
|
|
const uint totalbuffers{ptime.avail_buffers + ptime.queued_buffers};
|
|
|
|
|
|
/* Ensure the delay is in sample frames. */
|
|
|
- const uint64_t delay{static_cast<uint64_t>(ptime.delay) * mDevice->Frequency *
|
|
|
+ const uint64_t delay{static_cast<uint64_t>(ptime.delay) * mDevice->mSampleRate *
|
|
|
ptime.rate.num / ptime.rate.denom};
|
|
|
|
|
|
- mDevice->UpdateSize = updatesize;
|
|
|
- mDevice->BufferSize = static_cast<uint>(ptime.buffered + delay +
|
|
|
+ mDevice->mUpdateSize = updatesize;
|
|
|
+ mDevice->mBufferSize = static_cast<uint>(ptime.buffered + delay +
|
|
|
uint64_t{totalbuffers}*updatesize);
|
|
|
break;
|
|
|
}
|
|
@@ -1791,17 +1794,17 @@ void PipeWirePlayback::start()
|
|
|
if(ptime.rate.denom > 0 && updatesize > 0)
|
|
|
{
|
|
|
/* Ensure the delay is in sample frames. */
|
|
|
- const uint64_t delay{static_cast<uint64_t>(ptime.delay) * mDevice->Frequency *
|
|
|
+ const uint64_t delay{static_cast<uint64_t>(ptime.delay) * mDevice->mSampleRate *
|
|
|
ptime.rate.num / ptime.rate.denom};
|
|
|
|
|
|
- mDevice->UpdateSize = updatesize;
|
|
|
- mDevice->BufferSize = static_cast<uint>(delay + updatesize);
|
|
|
+ mDevice->mUpdateSize = updatesize;
|
|
|
+ mDevice->mBufferSize = static_cast<uint>(delay + updatesize);
|
|
|
break;
|
|
|
}
|
|
|
#endif
|
|
|
if(!--wait_count)
|
|
|
{
|
|
|
- ERR("Timeout getting PipeWire stream buffering info\n");
|
|
|
+ ERR("Timeout getting PipeWire stream buffering info");
|
|
|
break;
|
|
|
}
|
|
|
|
|
@@ -1815,7 +1818,7 @@ void PipeWirePlayback::stop()
|
|
|
{
|
|
|
MainloopUniqueLock plock{mLoop};
|
|
|
if(int res{pw_stream_set_active(mStream.get(), false)})
|
|
|
- ERR("Failed to stop PipeWire stream (res: %d)\n", res);
|
|
|
+ ERR("Failed to stop PipeWire stream (res: {})", res);
|
|
|
|
|
|
/* Wait for the stream to stop playing. */
|
|
|
plock.wait([stream=mStream.get()]()
|
|
@@ -1836,7 +1839,7 @@ ClockLatency PipeWirePlayback::getClockLatency()
|
|
|
{
|
|
|
MainloopLockGuard looplock{mLoop};
|
|
|
if(int res{pw_stream_get_time_n(mStream.get(), &ptime, sizeof(ptime))})
|
|
|
- ERR("Failed to get PipeWire stream time (res: %d)\n", res);
|
|
|
+ ERR("Failed to get PipeWire stream time (res: {})", res);
|
|
|
}
|
|
|
|
|
|
/* Now get the mixer time and the CLOCK_MONOTONIC time atomically (i.e. the
|
|
@@ -1864,7 +1867,7 @@ ClockLatency PipeWirePlayback::getClockLatency()
|
|
|
*/
|
|
|
ptime.now = monoclock.count();
|
|
|
curtic = mixtime;
|
|
|
- delay = nanoseconds{seconds{mDevice->BufferSize}} / mDevice->Frequency;
|
|
|
+ delay = nanoseconds{seconds{mDevice->mBufferSize}} / mDevice->mSampleRate;
|
|
|
}
|
|
|
else
|
|
|
{
|
|
@@ -1924,7 +1927,7 @@ class PipeWireCapture final : public BackendBase {
|
|
|
PwStreamPtr mStream;
|
|
|
spa_hook mStreamListener{};
|
|
|
|
|
|
- RingBufferPtr mRing{};
|
|
|
+ RingBufferPtr mRing;
|
|
|
|
|
|
static constexpr pw_stream_events CreateEvents()
|
|
|
{
|
|
@@ -1938,7 +1941,7 @@ class PipeWireCapture final : public BackendBase {
|
|
|
}
|
|
|
|
|
|
public:
|
|
|
- PipeWireCapture(DeviceBase *device) noexcept : BackendBase{device} { }
|
|
|
+ explicit PipeWireCapture(DeviceBase *device) noexcept : BackendBase{device} { }
|
|
|
~PipeWireCapture() final { if(mLoop) mLoop.stop(); }
|
|
|
};
|
|
|
|
|
@@ -2025,7 +2028,7 @@ void PipeWireCapture::open(std::string_view name)
|
|
|
}
|
|
|
if(match == devlist.cend())
|
|
|
throw al::backend_exception{al::backend_error::NoDevice,
|
|
|
- "Device name \"%.*s\" not found", al::sizei(name), name.data()};
|
|
|
+ "Device name \"{}\" not found", name};
|
|
|
|
|
|
targetid = match->mSerial;
|
|
|
if(match->mType != NodeType::Sink) devname = match->mName;
|
|
@@ -2034,15 +2037,15 @@ void PipeWireCapture::open(std::string_view name)
|
|
|
|
|
|
if(!mLoop)
|
|
|
{
|
|
|
- const uint count{OpenCount.fetch_add(1, std::memory_order_relaxed)};
|
|
|
- const std::string thread_name{"ALSoftC" + std::to_string(count)};
|
|
|
+ const auto count = OpenCount.fetch_add(1u, std::memory_order_relaxed);
|
|
|
+ const auto thread_name = fmt::format("ALSoftC{}", count);
|
|
|
mLoop = ThreadMainloop::Create(thread_name.c_str());
|
|
|
if(!mLoop)
|
|
|
throw al::backend_exception{al::backend_error::DeviceError,
|
|
|
- "Failed to create PipeWire mainloop (errno: %d)", errno};
|
|
|
+ "Failed to create PipeWire mainloop (errno: {})", errno};
|
|
|
if(int res{mLoop.start()})
|
|
|
throw al::backend_exception{al::backend_error::DeviceError,
|
|
|
- "Failed to start PipeWire mainloop (res: %d)", res};
|
|
|
+ "Failed to start PipeWire mainloop (res: {})", res};
|
|
|
}
|
|
|
MainloopUniqueLock mlock{mLoop};
|
|
|
if(!mContext)
|
|
@@ -2051,14 +2054,14 @@ void PipeWireCapture::open(std::string_view name)
|
|
|
mContext = mLoop.newContext(cprops);
|
|
|
if(!mContext)
|
|
|
throw al::backend_exception{al::backend_error::DeviceError,
|
|
|
- "Failed to create PipeWire event context (errno: %d)\n", errno};
|
|
|
+ "Failed to create PipeWire event context (errno: {})\n", errno};
|
|
|
}
|
|
|
if(!mCore)
|
|
|
{
|
|
|
mCore = PwCorePtr{pw_context_connect(mContext.get(), nullptr, 0)};
|
|
|
if(!mCore)
|
|
|
throw al::backend_exception{al::backend_error::DeviceError,
|
|
|
- "Failed to connect PipeWire event context (errno: %d)\n", errno};
|
|
|
+ "Failed to connect PipeWire event context (errno: {})\n", errno};
|
|
|
}
|
|
|
mlock.unlock();
|
|
|
|
|
@@ -2066,9 +2069,9 @@ void PipeWireCapture::open(std::string_view name)
|
|
|
|
|
|
mTargetId = targetid;
|
|
|
if(!devname.empty())
|
|
|
- mDevice->DeviceName = std::move(devname);
|
|
|
+ mDeviceName = std::move(devname);
|
|
|
else
|
|
|
- mDevice->DeviceName = "PipeWire Input"sv;
|
|
|
+ mDeviceName = "PipeWire Input"sv;
|
|
|
|
|
|
|
|
|
bool is51rear{false};
|
|
@@ -2083,19 +2086,16 @@ void PipeWireCapture::open(std::string_view name)
|
|
|
if(match != devlist.cend())
|
|
|
is51rear = match->mIs51Rear;
|
|
|
}
|
|
|
- spa_audio_info_raw info{make_spa_info(mDevice, is51rear, UseDevType)};
|
|
|
-
|
|
|
- static constexpr uint32_t pod_buffer_size{1024};
|
|
|
- PodDynamicBuilder b(pod_buffer_size);
|
|
|
+ auto info = spa_audio_info_raw{make_spa_info(mDevice, is51rear, UseDevType)};
|
|
|
|
|
|
- std::array params{static_cast<const spa_pod*>(spa_format_audio_raw_build(b.get(),
|
|
|
- SPA_PARAM_EnumFormat, &info))};
|
|
|
- if(!params[0])
|
|
|
+ auto b = PodDynamicBuilder{};
|
|
|
+ auto params = as_const_ptr(spa_format_audio_raw_build(b.get(), SPA_PARAM_EnumFormat, &info));
|
|
|
+ if(!params)
|
|
|
throw al::backend_exception{al::backend_error::DeviceError,
|
|
|
"Failed to set PipeWire audio format parameters"};
|
|
|
|
|
|
auto&& binary = GetProcBinary();
|
|
|
- const char *appname{binary.fname.length() ? binary.fname.c_str() : "OpenAL Soft"};
|
|
|
+ const char *appname{!binary.fname.empty() ? binary.fname.c_str() : "OpenAL Soft"};
|
|
|
pw_properties *props{pw_properties_new(
|
|
|
PW_KEY_NODE_NAME, appname,
|
|
|
PW_KEY_NODE_DESCRIPTION, appname,
|
|
@@ -2106,15 +2106,15 @@ void PipeWireCapture::open(std::string_view name)
|
|
|
nullptr)};
|
|
|
if(!props)
|
|
|
throw al::backend_exception{al::backend_error::DeviceError,
|
|
|
- "Failed to create PipeWire stream properties (errno: %d)", errno};
|
|
|
+ "Failed to create PipeWire stream properties (errno: {})", errno};
|
|
|
|
|
|
/* We don't actually care what the latency/update size is, as long as it's
|
|
|
* reasonable. Unfortunately, when unspecified PipeWire seems to default to
|
|
|
* around 40ms, which isn't great. So request 20ms instead.
|
|
|
*/
|
|
|
- pw_properties_setf(props, PW_KEY_NODE_LATENCY, "%u/%u", (mDevice->Frequency+25) / 50,
|
|
|
- mDevice->Frequency);
|
|
|
- pw_properties_setf(props, PW_KEY_NODE_RATE, "1/%u", mDevice->Frequency);
|
|
|
+ pw_properties_setf(props, PW_KEY_NODE_LATENCY, "%u/%u", (mDevice->mSampleRate+25) / 50,
|
|
|
+ mDevice->mSampleRate);
|
|
|
+ pw_properties_setf(props, PW_KEY_NODE_RATE, "1/%u", mDevice->mSampleRate);
|
|
|
#ifdef PW_KEY_TARGET_OBJECT
|
|
|
pw_properties_setf(props, PW_KEY_TARGET_OBJECT, "%" PRIu64, mTargetId);
|
|
|
#else
|
|
@@ -2125,15 +2125,15 @@ void PipeWireCapture::open(std::string_view name)
|
|
|
mStream = PwStreamPtr{pw_stream_new(mCore.get(), "Capture Stream", props)};
|
|
|
if(!mStream)
|
|
|
throw al::backend_exception{al::backend_error::NoDevice,
|
|
|
- "Failed to create PipeWire stream (errno: %d)", errno};
|
|
|
+ "Failed to create PipeWire stream (errno: {})", errno};
|
|
|
static constexpr pw_stream_events streamEvents{CreateEvents()};
|
|
|
pw_stream_add_listener(mStream.get(), &mStreamListener, &streamEvents, this);
|
|
|
|
|
|
constexpr pw_stream_flags Flags{PW_STREAM_FLAG_AUTOCONNECT | PW_STREAM_FLAG_INACTIVE
|
|
|
| PW_STREAM_FLAG_MAP_BUFFERS | PW_STREAM_FLAG_RT_PROCESS};
|
|
|
- if(int res{pw_stream_connect(mStream.get(), PW_DIRECTION_INPUT, PwIdAny, Flags, params.data(), 1)})
|
|
|
+ if(int res{pw_stream_connect(mStream.get(), PW_DIRECTION_INPUT, PwIdAny, Flags, ¶ms, 1)})
|
|
|
throw al::backend_exception{al::backend_error::DeviceError,
|
|
|
- "Error connecting PipeWire stream (res: %d)", res};
|
|
|
+ "Error connecting PipeWire stream (res: {})", res};
|
|
|
|
|
|
/* Wait for the stream to become paused (ready to start streaming). */
|
|
|
plock.wait([stream=mStream.get()]()
|
|
@@ -2142,7 +2142,7 @@ void PipeWireCapture::open(std::string_view name)
|
|
|
pw_stream_state state{pw_stream_get_state(stream, &error)};
|
|
|
if(state == PW_STREAM_STATE_ERROR)
|
|
|
throw al::backend_exception{al::backend_error::DeviceError,
|
|
|
- "Error connecting PipeWire stream: \"%s\"", error};
|
|
|
+ "Error connecting PipeWire stream: \"{}\"", error};
|
|
|
return state == PW_STREAM_STATE_PAUSED;
|
|
|
});
|
|
|
plock.unlock();
|
|
@@ -2150,7 +2150,7 @@ void PipeWireCapture::open(std::string_view name)
|
|
|
setDefaultWFXChannelOrder();
|
|
|
|
|
|
/* Ensure at least a 100ms capture buffer. */
|
|
|
- mRing = RingBuffer::Create(std::max(mDevice->Frequency/10u, mDevice->BufferSize),
|
|
|
+ mRing = RingBuffer::Create(std::max(mDevice->mSampleRate/10u, mDevice->mBufferSize),
|
|
|
mDevice->frameSizeFromFmt(), false);
|
|
|
}
|
|
|
|
|
@@ -2160,7 +2160,7 @@ void PipeWireCapture::start()
|
|
|
MainloopUniqueLock plock{mLoop};
|
|
|
if(int res{pw_stream_set_active(mStream.get(), true)})
|
|
|
throw al::backend_exception{al::backend_error::DeviceError,
|
|
|
- "Failed to start PipeWire stream (res: %d)", res};
|
|
|
+ "Failed to start PipeWire stream (res: {})", res};
|
|
|
|
|
|
plock.wait([stream=mStream.get()]()
|
|
|
{
|
|
@@ -2168,7 +2168,7 @@ void PipeWireCapture::start()
|
|
|
pw_stream_state state{pw_stream_get_state(stream, &error)};
|
|
|
if(state == PW_STREAM_STATE_ERROR)
|
|
|
throw al::backend_exception{al::backend_error::DeviceError,
|
|
|
- "PipeWire stream error: %s", error ? error : "(unknown)"};
|
|
|
+ "PipeWire stream error: {}", error ? error : "(unknown)"};
|
|
|
return state == PW_STREAM_STATE_STREAMING;
|
|
|
});
|
|
|
}
|
|
@@ -2177,7 +2177,7 @@ void PipeWireCapture::stop()
|
|
|
{
|
|
|
MainloopUniqueLock plock{mLoop};
|
|
|
if(int res{pw_stream_set_active(mStream.get(), false)})
|
|
|
- ERR("Failed to stop PipeWire stream (res: %d)\n", res);
|
|
|
+ ERR("Failed to stop PipeWire stream (res: {})", res);
|
|
|
|
|
|
plock.wait([stream=mStream.get()]()
|
|
|
{ return pw_stream_get_state(stream, nullptr) != PW_STREAM_STATE_STREAMING; });
|
|
@@ -2200,11 +2200,11 @@ bool PipeWireBackendFactory::init()
|
|
|
const char *version{pw_get_library_version()};
|
|
|
if(!check_version(version))
|
|
|
{
|
|
|
- WARN("PipeWire version \"%s\" too old (%s or newer required)\n", version,
|
|
|
+ WARN("PipeWire version \"{}\" too old ({} or newer required)", version,
|
|
|
pw_get_headers_version());
|
|
|
return false;
|
|
|
}
|
|
|
- TRACE("Found PipeWire version \"%s\" (%s or newer)\n", version, pw_get_headers_version());
|
|
|
+ TRACE("Found PipeWire version \"{}\" ({} or newer)", version, pw_get_headers_version());
|
|
|
|
|
|
pw_init(nullptr, nullptr);
|
|
|
if(!gEventHandler.init())
|
|
@@ -2217,7 +2217,7 @@ bool PipeWireBackendFactory::init()
|
|
|
/* TODO: Temporary warning, until PipeWire gets a proper way to report
|
|
|
* audio support.
|
|
|
*/
|
|
|
- WARN("No audio support detected in PipeWire. See the PipeWire options in alsoftrc.sample if this is wrong.\n");
|
|
|
+ WARN("No audio support detected in PipeWire. See the PipeWire options in alsoftrc.sample if this is wrong.");
|
|
|
return false;
|
|
|
}
|
|
|
return true;
|