Date: Sat, 27 Dec 2025 09:24:30 +0000 From: Jason E. Hale <jhale@FreeBSD.org> To: ports-committers@FreeBSD.org, dev-commits-ports-all@FreeBSD.org, dev-commits-ports-main@FreeBSD.org Subject: git: 70d12b15d60b - main - audio/openal-soft: Add more upstream fixes Message-ID: <694fa5ce.45938.19e8fed5@gitrepo.freebsd.org>
index | next in thread | raw e-mail
The branch main has been updated by jhale: URL: https://cgit.FreeBSD.org/ports/commit/?id=70d12b15d60b192765f3da5c81d3040831641438 commit 70d12b15d60b192765f3da5c81d3040831641438 Author: Jason E. Hale <jhale@FreeBSD.org> AuthorDate: 2025-12-27 09:20:21 +0000 Commit: Jason E. Hale <jhale@FreeBSD.org> CommitDate: 2025-12-27 09:20:21 +0000 audio/openal-soft: Add more upstream fixes The OSS backend is really fixed now. --- audio/openal-soft/Makefile | 1 + audio/openal-soft/files/patch-alc_backends_oss.cpp | 480 ++++++++++++++++++++- 2 files changed, 468 insertions(+), 13 deletions(-) diff --git a/audio/openal-soft/Makefile b/audio/openal-soft/Makefile index bd9233ebee7f..8fd1b304d13f 100644 --- a/audio/openal-soft/Makefile +++ b/audio/openal-soft/Makefile @@ -1,5 +1,6 @@ PORTNAME= openal-soft PORTVERSION= 1.25.0 +PORTREVISION= 1 CATEGORIES= audio MASTER_SITES= https://openal-soft.org/openal-releases/ diff --git a/audio/openal-soft/files/patch-alc_backends_oss.cpp b/audio/openal-soft/files/patch-alc_backends_oss.cpp index b8e75ecf6ec1..5be079686963 100644 --- a/audio/openal-soft/files/patch-alc_backends_oss.cpp +++ b/audio/openal-soft/files/patch-alc_backends_oss.cpp @@ -2,21 +2,118 @@ Backport upstream commits to fix build. https://github.com/kcat/openal-soft/commit/278d1dc4d607b84e4e7b2d93af094d7932588962 https://github.com/kcat/openal-soft/commit/b93a15cc886cda8ce7626e84c637bdaf7c346773 +https://github.com/kcat/openal-soft/commit/5f0bf631d7d43f568f10065aae561c892c02d43e +https://github.com/kcat/openal-soft/commit/78a2ddb791163ae0d603937c88613523d27fa22d https://github.com/kcat/openal-soft/issues/1215 --- alc/backends/oss.cpp.orig 2025-12-22 09:17:45 UTC +++ alc/backends/oss.cpp -@@ -121,7 +121,7 @@ class FileHandle { (public) +@@ -33,6 +33,7 @@ + #include <cerrno> + #include <cstring> + #include <exception> ++#include <functional> + #include <memory> + #include <span> + #include <string> +@@ -65,12 +66,9 @@ + #define SOUND_MIXER_WRITE MIXER_WRITE + #endif + +-#if defined(SOUND_VERSION) && (SOUND_VERSION < 0x040000) ++#if (defined(SOUND_VERSION) && (SOUND_VERSION < 0x040000)) || !defined(SNDCTL_AUDIOINFO) + #define ALC_OSS_COMPAT + #endif +-#ifndef SNDCTL_AUDIOINFO +-#define ALC_OSS_COMPAT +-#endif + + /* + * FreeBSD strongly discourages the use of specific devices, +@@ -98,32 +96,28 @@ std::vector<DevMap> CaptureDevices; + std::vector<DevMap> PlaybackDevices; + std::vector<DevMap> CaptureDevices; + +- +-#ifdef ALC_OSS_COMPAT +- +-#define DSP_CAP_OUTPUT 0x00020000 +-#define DSP_CAP_INPUT 0x00010000 +-void ALCossListPopulate(std::vector<DevMap> &devlist, int type) +-{ +- devlist.emplace_back(std::string{GetDefaultName()}, +- (type==DSP_CAP_INPUT) ? DefaultCapture : DefaultPlayback); +-} +- +-#else +- + class FileHandle { + int mFd{-1}; + + public: + FileHandle() = default; + FileHandle(const FileHandle&) = delete; +- FileHandle& operator=(const FileHandle&) = delete; ++ FileHandle(FileHandle&& rhs) noexcept : mFd{std::exchange(rhs.mFd, -1)} { } ~FileHandle() { if(mFd != -1) ::close(mFd); } ++ auto operator=(const FileHandle&) -> FileHandle& = delete; ++ auto operator=(FileHandle&& rhs) noexcept -> FileHandle& ++ { ++ close(); ++ mFd = std::exchange(rhs.mFd, -1); ++ return *this; ++ } ++ template<typename ...Args> - [[nodiscard]] auto open(const char *fname, Args&& ...args) -> bool + [[nodiscard]] auto open(gsl::czstring const fname, Args&& ...args) -> bool { close(); ++ /* NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg) */ mFd = ::open(fname, std::forward<Args>(args)...); -@@ -149,21 +149,25 @@ void ALCossListAppend(std::vector<DevMap> &list, std:: + return mFd != -1; + } +@@ -134,10 +128,35 @@ class FileHandle { (public) + mFd = -1; + } + +- [[nodiscard]] +- auto get() const noexcept -> int { return mFd; } ++ template<typename ...Args> ++ [[nodiscard]] auto ioctl(Args&& ...args) const ++ { ++ /* NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg) */ ++ return ::ioctl(mFd, std::forward<Args>(args)...); ++ } ++ ++ [[nodiscard]] auto read(std::span<std::byte> const bytes) const ++ { return ::read(mFd, bytes.data(), bytes.size()); } ++ ++ [[nodiscard]] auto write(std::span<std::byte const> const bytes) const ++ { return ::write(mFd, bytes.data(), bytes.size()); } ++ ++ [[nodiscard]] auto get() const noexcept -> int { return mFd; } + }; + ++ ++#ifdef ALC_OSS_COMPAT ++ ++#define DSP_CAP_OUTPUT 0x00020000 ++#define DSP_CAP_INPUT 0x00010000 ++void ALCossListPopulate(std::vector<DevMap> &devlist, int type) ++{ ++ devlist.emplace_back(std::string{GetDefaultName()}, ++ (type==DSP_CAP_INPUT) ? DefaultCapture : DefaultPlayback); ++} ++ ++#else ++ + void ALCossListAppend(std::vector<DevMap> &list, std::string_view handle, std::string_view path) + { + #ifdef ALC_OSS_DEVNODE_TRUC +@@ -149,45 +168,63 @@ void ALCossListAppend(std::vector<DevMap> &list, std:: if(strncmp(path.data() + i, handle.data() + hoffset, path.size() - i) == 0) handle = handle.substr(0, hoffset); path = path.substr(0, i); @@ -41,29 +138,386 @@ https://github.com/kcat/openal-soft/issues/1215 newname = al::format("{} #{}", handle, ++count); - const auto &entry = list.emplace_back(std::move(newname), path); +- TRACE("Got device \"{}\", \"{}\"", entry.name, entry.device_name); + const auto &entry = list.emplace_back(std::move(newname), std::string{path}); - TRACE("Got device \"{}\", \"{}\"", entry.name, entry.device_name); ++ TRACE(R"(Got device "{}", "{}")", entry.name, entry.device_name); } -@@ -208,16 +212,12 @@ done: - done: - file.close(); +-void ALCossListPopulate(std::vector<DevMap> &devlist, int type_flag) ++void ALCossListPopulate(std::vector<DevMap> &devlist, int const type_flag) + { ++ /* Make sure to move the default device to the start of the devlist (or ++ * adding the default if it doesn't exist) before returning. ++ */ ++ auto _ = gsl::finally([&devlist, type_flag] ++ { ++ auto const &defdev = (type_flag == DSP_CAP_INPUT) ? DefaultCapture : DefaultPlayback; ++ if(auto const iter = std::ranges::find(devlist, defdev, &DevMap::device_name); ++ iter != devlist.end()) ++ std::ranges::rotate(devlist.begin(), iter, iter+1); ++ else ++ devlist.insert(devlist.begin(), DevMap{std::string{GetDefaultName()}, defdev}); ++ devlist.shrink_to_fit(); ++ }); ++ + auto si = oss_sysinfo{}; + auto file = FileHandle{}; + if(!file.open("/dev/mixer", O_RDONLY)) + { + TRACE("Could not open /dev/mixer: {}", std::generic_category().message(errno)); +- goto done; ++ return; + } +- if(ioctl(file.get(), SNDCTL_SYSINFO, &si) == -1) ++ if(file.ioctl(SNDCTL_SYSINFO, &si) == -1) + { + TRACE("SNDCTL_SYSINFO failed: {}", std::generic_category().message(errno)); +- goto done; ++ return; + } + +- for(int i{0};i < si.numaudios;i++) ++ for(auto const i : std::views::iota(0, si.numaudios)) + { +- oss_audioinfo ai{}; ++ auto ai = oss_audioinfo{}; + ai.dev = i; +- if(ioctl(file.get(), SNDCTL_AUDIOINFO, &ai) == -1) ++ if(file.ioctl(SNDCTL_AUDIOINFO, &ai) == -1) + { + ERR("SNDCTL_AUDIOINFO ({}) failed: {}", i, std::generic_category().message(errno)); + continue; +@@ -195,30 +232,17 @@ void ALCossListPopulate(std::vector<DevMap> &devlist, + if(!(ai.caps&type_flag) || ai.devnode[0] == '\0') + continue; + +- std::string_view handle; +- if(ai.handle[0] != '\0') +- handle = {ai.handle, strnlen(ai.handle, sizeof(ai.handle))}; +- else +- handle = {ai.name, strnlen(ai.name, sizeof(ai.name))}; +- const std::string_view devnode{ai.devnode, strnlen(ai.devnode, sizeof(ai.devnode))}; ++ auto const handle = std::invoke([&ai]() -> std::string_view ++ { ++ if(ai.handle[0] != '\0') ++ return {std::data(ai.handle), strnlen(std::data(ai.handle), std::size(ai.handle))}; ++ return {std::data(ai.name), strnlen(std::data(ai.name), std::size(ai.name))}; ++ }); ++ auto const devnode = std::string_view{std::data(ai.devnode), ++ strnlen(std::data(ai.devnode), std::size(ai.devnode))}; + + ALCossListAppend(devlist, handle, devnode); + } +- +-done: +- file.close(); +- - const char *defdev{((type_flag==DSP_CAP_INPUT) ? DefaultCapture : DefaultPlayback).c_str()}; - auto iter = std::ranges::find(devlist, defdev, &DevMap::device_name); - if(iter == devlist.end()) - devlist.insert(devlist.begin(), DevMap{GetDefaultName(), defdev}); -+ auto const &defdev = (type_flag == DSP_CAP_INPUT) ? DefaultCapture : DefaultPlayback; -+ if(auto const iter = std::ranges::find(devlist, defdev, &DevMap::device_name); -+ iter != devlist.end()) -+ std::ranges::rotate(devlist.begin(), iter, iter+1); - else +- else - { - auto entry = DevMap{std::move(*iter)}; - devlist.erase(iter); - devlist.insert(devlist.begin(), std::move(entry)); - } -+ devlist.insert(devlist.begin(), DevMap{std::string{GetDefaultName()}, defdev}); - devlist.shrink_to_fit(); +- devlist.shrink_to_fit(); + } + + #endif +@@ -247,7 +271,7 @@ struct OSSPlayback final : BackendBase { + void start() override; + void stop() override; + +- int mFd{-1}; ++ FileHandle mFd; + + std::vector<std::byte> mMixData; + +@@ -255,12 +279,7 @@ struct OSSPlayback final : BackendBase { + std::thread mThread; + }; + +-OSSPlayback::~OSSPlayback() +-{ +- if(mFd != -1) +- ::close(mFd); +- mFd = -1; +-} ++OSSPlayback::~OSSPlayback() = default; + + + void OSSPlayback::mixerProc() +@@ -275,7 +294,7 @@ void OSSPlayback::mixerProc() + && mDevice->Connected.load(std::memory_order_acquire)) + { + auto pollitem = pollfd{}; +- pollitem.fd = mFd; ++ pollitem.fd = mFd.get(); + pollitem.events = POLLOUT; + + if(const auto pret = poll(&pollitem, 1, 1000); pret < 0) +@@ -298,7 +317,7 @@ void OSSPlayback::mixerProc() + gsl::narrow_cast<u32>(write_buf.size()/frame_size), frame_step); + while(!write_buf.empty() && !mKillNow.load(std::memory_order_acquire)) + { +- const auto wrote = write(mFd, write_buf.data(), write_buf.size()); ++ const auto wrote = mFd.write(write_buf); + if(wrote < 0) + { + if(errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) +@@ -332,15 +351,10 @@ void OSSPlayback::open(std::string_view name) + devname = iter->device_name.c_str(); + } + +- const auto fd = ::open(devname, O_WRONLY); /* NOLINT(cppcoreguidelines-pro-type-vararg) */ +- if(fd == -1) ++ if(not mFd.open(devname, O_WRONLY)) + throw al::backend_exception{al::backend_error::NoDevice, "Could not open {}: {}", devname, + std::generic_category().message(errno)}; + +- if(mFd != -1) +- ::close(mFd); +- mFd = fd; +- + mDeviceName = name; + } + +@@ -349,21 +363,21 @@ auto OSSPlayback::reset() -> bool + auto ossFormat = int{}; + switch(mDevice->FmtType) + { +- case DevFmtByte: +- ossFormat = AFMT_S8; +- break; +- case DevFmtUByte: +- ossFormat = AFMT_U8; +- break; +- case DevFmtUShort: +- case DevFmtInt: +- case DevFmtUInt: +- case DevFmtFloat: +- mDevice->FmtType = DevFmtShort; +- [[fallthrough]]; +- case DevFmtShort: +- ossFormat = AFMT_S16_NE; +- break; ++ case DevFmtByte: ++ ossFormat = AFMT_S8; ++ break; ++ case DevFmtUByte: ++ ossFormat = AFMT_U8; ++ break; ++ case DevFmtUShort: ++ case DevFmtInt: ++ case DevFmtUInt: ++ case DevFmtFloat: ++ mDevice->FmtType = DevFmtShort; ++ [[fallthrough]]; ++ case DevFmtShort: ++ ossFormat = AFMT_S16_NE; ++ break; + } + + auto numChannels = mDevice->channelsFromFmt(); +@@ -373,22 +387,20 @@ auto OSSPlayback::reset() -> bool + auto numFragmentsLogSize = ((mDevice->mBufferSize + mDevice->mUpdateSize/2) + / mDevice->mUpdateSize) << 16u; + /* According to the OSS spec, 16 bytes is the minimum period size. */ +- numFragmentsLogSize |= std::max(log2i(mDevice->mUpdateSize * frameSize), 4u); ++ numFragmentsLogSize |= std::max(log2i(mDevice->mUpdateSize * frameSize), 4_u32); + + auto info = audio_buf_info{}; + #define CHECKERR(func) if((func) < 0) \ + throw al::backend_exception{al::backend_error::DeviceError, #func " failed: {}", \ + std::generic_category().message(errno)}; +- +- /* NOLINTBEGIN(cppcoreguidelines-pro-type-vararg) */ + /* Don't fail if SETFRAGMENT fails. We can handle just about anything +- * that's reported back via GETOSPACE */ +- ioctl(mFd, SNDCTL_DSP_SETFRAGMENT, &numFragmentsLogSize); +- CHECKERR(ioctl(mFd, SNDCTL_DSP_SETFMT, &ossFormat)); +- CHECKERR(ioctl(mFd, SNDCTL_DSP_CHANNELS, &numChannels)); +- CHECKERR(ioctl(mFd, SNDCTL_DSP_SPEED, &ossSpeed)); +- CHECKERR(ioctl(mFd, SNDCTL_DSP_GETOSPACE, &info)); +- /* NOLINTEND(cppcoreguidelines-pro-type-vararg) */ ++ * that's reported back via GETOSPACE. ++ */ ++ std::ignore = mFd.ioctl(SNDCTL_DSP_SETFRAGMENT, &numFragmentsLogSize); ++ CHECKERR(mFd.ioctl(SNDCTL_DSP_SETFMT, &ossFormat)); ++ CHECKERR(mFd.ioctl(SNDCTL_DSP_CHANNELS, &numChannels)); ++ CHECKERR(mFd.ioctl(SNDCTL_DSP_SPEED, &ossSpeed)); ++ CHECKERR(mFd.ioctl(SNDCTL_DSP_GETOSPACE, &info)); + #undef CHECKERR + + if(mDevice->channelsFromFmt() != numChannels) +@@ -436,14 +448,14 @@ void OSSPlayback::stop() + return; + mThread.join(); + +- if(ioctl(mFd, SNDCTL_DSP_RESET) != 0) /* NOLINT(cppcoreguidelines-pro-type-vararg) */ ++ if(mFd.ioctl(SNDCTL_DSP_RESET) != 0) + ERR("Error resetting device: {}", std::generic_category().message(errno)); + } + + +-struct OSScapture final : public BackendBase { +- explicit OSScapture(gsl::not_null<DeviceBase*> device) noexcept : BackendBase{device} { } +- ~OSScapture() override; ++struct OSSCapture final : BackendBase { ++ explicit OSSCapture(gsl::not_null<DeviceBase*> const device) noexcept : BackendBase{device} { } ++ ~OSSCapture() override; + + void recordProc() const; + +@@ -453,7 +465,7 @@ struct OSScapture final : public BackendBase { + void captureSamples(std::span<std::byte> outbuffer) override; + auto availableSamples() -> usize override; + +- int mFd{-1}; ++ FileHandle mFd; + + RingBufferPtr<std::byte> mRing; + +@@ -461,15 +473,10 @@ struct OSScapture final : public BackendBase { + std::thread mThread; + }; + +-OSScapture::~OSScapture() +-{ +- if(mFd != -1) +- close(mFd); +- mFd = -1; +-} ++OSSCapture::~OSSCapture() = default; + + +-void OSScapture::recordProc() const ++void OSSCapture::recordProc() const + { + SetRTPriority(); + althrd_setname(GetRecordThreadName()); +@@ -478,7 +485,7 @@ void OSScapture::recordProc() const + while(!mKillNow.load(std::memory_order_acquire)) + { + auto pollitem = pollfd{}; +- pollitem.fd = mFd; ++ pollitem.fd = mFd.get(); + pollitem.events = POLLIN; + + if(auto const pret = poll(&pollitem, 1, 1000); pret < 0) +@@ -496,10 +503,9 @@ void OSScapture::recordProc() const + continue; + } + +- auto vec = mRing->getWriteVector(); +- if(!vec[0].empty()) ++ if(auto const vec = mRing->getWriteVector(); !vec[0].empty()) + { +- auto amt = read(mFd, vec[0].data(), vec[0].size()); ++ auto const amt = mFd.read(vec[0]); + if(amt < 0) + { + auto const errstr = std::generic_category().message(errno); +@@ -513,7 +519,7 @@ void OSScapture::recordProc() const } + +-void OSScapture::open(std::string_view name) ++void OSSCapture::open(std::string_view name) + { + auto *devname = DefaultCapture.c_str(); + if(name.empty()) +@@ -523,15 +529,14 @@ void OSScapture::open(std::string_view name) + if(CaptureDevices.empty()) + ALCossListPopulate(CaptureDevices, DSP_CAP_INPUT); + +- auto iter = std::ranges::find(CaptureDevices, name, &DevMap::name); ++ auto const iter = std::ranges::find(CaptureDevices, name, &DevMap::name); + if(iter == CaptureDevices.end()) + throw al::backend_exception{al::backend_error::NoDevice, + "Device name \"{}\" not found", name}; + devname = iter->device_name.c_str(); + } + +- mFd = ::open(devname, O_RDONLY); /* NOLINT(cppcoreguidelines-pro-type-vararg) */ +- if(mFd == -1) ++ if(not mFd.open(devname, O_RDONLY)) + throw al::backend_exception{al::backend_error::NoDevice, "Could not open {}: {}", devname, + std::generic_category().message(errno)}; + +@@ -568,13 +573,11 @@ void OSScapture::open(std::string_view name) + throw al::backend_exception{al::backend_error::DeviceError, #func " failed: {}", \ + std::generic_category().message(errno)}; \ + } +- /* NOLINTBEGIN(cppcoreguidelines-pro-type-vararg) */ +- CHECKERR(ioctl(mFd, SNDCTL_DSP_SETFRAGMENT, &numFragmentsLogSize)); +- CHECKERR(ioctl(mFd, SNDCTL_DSP_SETFMT, &ossFormat)); +- CHECKERR(ioctl(mFd, SNDCTL_DSP_CHANNELS, &numChannels)); +- CHECKERR(ioctl(mFd, SNDCTL_DSP_SPEED, &ossSpeed)); +- CHECKERR(ioctl(mFd, SNDCTL_DSP_GETISPACE, &info)); +- /* NOLINTEND(cppcoreguidelines-pro-type-vararg) */ ++ CHECKERR(mFd.ioctl(SNDCTL_DSP_SETFRAGMENT, &numFragmentsLogSize)); ++ CHECKERR(mFd.ioctl(SNDCTL_DSP_SETFMT, &ossFormat)); ++ CHECKERR(mFd.ioctl(SNDCTL_DSP_CHANNELS, &numChannels)); ++ CHECKERR(mFd.ioctl(SNDCTL_DSP_SPEED, &ossSpeed)); ++ CHECKERR(mFd.ioctl(SNDCTL_DSP_GETISPACE, &info)); + #undef CHECKERR + + if(mDevice->channelsFromFmt() != numChannels) +@@ -594,11 +597,11 @@ void OSScapture::open(std::string_view name) + mDeviceName = name; + } + +-void OSScapture::start() ++void OSSCapture::start() + { + try { + mKillNow.store(false, std::memory_order_release); +- mThread = std::thread{&OSScapture::recordProc, this}; ++ mThread = std::thread{&OSSCapture::recordProc, this}; + } + catch(std::exception& e) { + throw al::backend_exception{al::backend_error::DeviceError, +@@ -606,20 +609,20 @@ void OSScapture::start() + } + } + +-void OSScapture::stop() ++void OSSCapture::stop() + { + if(mKillNow.exchange(true, std::memory_order_acq_rel) || !mThread.joinable()) + return; + mThread.join(); + +- if(ioctl(mFd, SNDCTL_DSP_RESET) != 0) /* NOLINT(cppcoreguidelines-pro-type-vararg) */ ++ if(mFd.ioctl(SNDCTL_DSP_RESET) != 0) + ERR("Error resetting device: {}", std::generic_category().message(errno)); + } + +-void OSScapture::captureSamples(std::span<std::byte> outbuffer) ++void OSSCapture::captureSamples(std::span<std::byte> outbuffer) + { std::ignore = mRing->read(outbuffer); } + +-auto OSScapture::availableSamples() -> usize ++auto OSSCapture::availableSamples() -> usize + { return mRing->readSpace(); } + + } // namespace +@@ -672,12 +675,12 @@ auto OSSBackendFactory::createBackend(gsl::not_null<De + if(type == BackendType::Playback) + return BackendPtr{new OSSPlayback{device}}; + if(type == BackendType::Capture) +- return BackendPtr{new OSScapture{device}}; ++ return BackendPtr{new OSSCapture{device}}; + return nullptr; + } + + auto OSSBackendFactory::getFactory() -> BackendFactory& + { +- static OSSBackendFactory factory{}; ++ static auto factory = OSSBackendFactory{}; + return factory; + }home | help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?694fa5ce.45938.19e8fed5>
