From 594959d6f80f090d837c7ca1286459de3aa1769c Mon Sep 17 00:00:00 2001 From: Kalev Lember Date: Wed, 17 Aug 2022 10:29:03 +0200 Subject: [PATCH] Drop unused patches --- D145871.diff | 140 - D145966.diff | 20 - D146271.diff | 94 - D146272.diff | 373 -- D146273.diff | 90 - D146274.diff | 158 - D146275.diff | 125 - D147635.diff | 125 - D147636.diff | 278 -- D147637.diff | 139 - D147874.diff | 64 - D148946.diff | 250 -- D149135.diff | 80 - D149238.diff | 34 - build-cubeb-pulse-arm.patch | 4946 ------------------------ fedora-build.patch | 23 - firefox-kde-webrender.patch | 33 - firefox.spec | 1 + mozilla-1640982.patch | 16 - mozilla-1672139.patch | 91 - mozilla-1673313.patch | 351 -- mozilla-1700520.patch | 51 - mozilla-1701089.patch | 23 - mozilla-1753402.patch | 12 - mozilla-1758948.patch | 28 - mozilla-1774271.patch | 31 - mozilla-1885133.patch | 21 - mozilla-440908.patch | 111 - rhbz-1400293-fix-mozilla-1324096.patch | 72 - rust-thirdparty-checksum-fix.patch | 6 - 30 files changed, 1 insertion(+), 7785 deletions(-) delete mode 100644 D145871.diff delete mode 100644 D145966.diff delete mode 100644 D146271.diff delete mode 100644 D146272.diff delete mode 100644 D146273.diff delete mode 100644 D146274.diff delete mode 100644 D146275.diff delete mode 100644 D147635.diff delete mode 100644 D147636.diff delete mode 100644 D147637.diff delete mode 100644 D147874.diff delete mode 100644 D148946.diff delete mode 100644 D149135.diff delete mode 100644 D149238.diff delete mode 100644 build-cubeb-pulse-arm.patch delete mode 100644 fedora-build.patch delete mode 100644 firefox-kde-webrender.patch delete mode 100644 mozilla-1640982.patch delete mode 100644 mozilla-1672139.patch delete mode 100644 mozilla-1673313.patch delete mode 100644 mozilla-1700520.patch delete mode 100644 mozilla-1701089.patch delete mode 100644 mozilla-1753402.patch delete mode 100644 mozilla-1758948.patch delete mode 100644 mozilla-1774271.patch delete mode 100644 mozilla-1885133.patch delete mode 100644 mozilla-440908.patch delete mode 100644 rhbz-1400293-fix-mozilla-1324096.patch delete mode 100644 rust-thirdparty-checksum-fix.patch diff --git a/D145871.diff b/D145871.diff deleted file mode 100644 index 33a2e61..0000000 --- a/D145871.diff +++ /dev/null @@ -1,140 +0,0 @@ -diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h ---- a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h -+++ b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h -@@ -146,10 +146,15 @@ - RefPtr mImageContainer; - VideoInfo mInfo; - int mDecodedFrames; - #if LIBAVCODEC_VERSION_MAJOR >= 58 - int mDecodedFramesLate; -+ // Tracks when decode time of recent frame and averange decode time of -+ // previous frames is bigger than frame interval, -+ // i.e. we fail to decode in time. -+ // We switch to SW decode when we hit HW_DECODE_LATE_FRAMES treshold. -+ int mMissedDecodeInAverangeTime; - #endif - float mAverangeDecodeTime; - - class PtsCorrectionContext { - public: -diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp ---- a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp -+++ b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp -@@ -14,10 +14,13 @@ - #include "VPXDecoder.h" - #include "mozilla/layers/KnowsCompositor.h" - #if LIBAVCODEC_VERSION_MAJOR >= 57 - # include "mozilla/layers/TextureClient.h" - #endif -+#if LIBAVCODEC_VERSION_MAJOR >= 58 -+# include "mozilla/ProfilerMarkers.h" -+#endif - #ifdef MOZ_WAYLAND_USE_VAAPI - # include "H264.h" - # include "mozilla/layers/DMABUFSurfaceImage.h" - # include "mozilla/widget/DMABufLibWrapper.h" - # include "FFmpegVideoFramePool.h" -@@ -56,13 +59,14 @@ - typedef int VAStatus; - # define VA_EXPORT_SURFACE_READ_ONLY 0x0001 - # define VA_EXPORT_SURFACE_SEPARATE_LAYERS 0x0004 - # define VA_STATUS_SUCCESS 0x00000000 - #endif -- - // Use some extra HW frames for potential rendering lags. - #define EXTRA_HW_FRAMES 6 -+// Defines number of delayed frames until we switch back to SW decode. -+#define HW_DECODE_LATE_FRAMES 15 - - #if LIBAVCODEC_VERSION_MAJOR >= 57 && LIBAVUTIL_VERSION_MAJOR >= 56 - # define CUSTOMIZED_BUFFER_ALLOCATION 1 - #endif - -@@ -386,10 +390,11 @@ - mImageContainer(aImageContainer), - mInfo(aConfig), - mDecodedFrames(0), - #if LIBAVCODEC_VERSION_MAJOR >= 58 - mDecodedFramesLate(0), -+ mMissedDecodeInAverangeTime(0), - #endif - mAverangeDecodeTime(0), - mLowLatency(aLowLatency) { - FFMPEG_LOG("FFmpegVideoDecoder::FFmpegVideoDecoder MIME %s Codec ID %d", - aConfig.mMimeType.get(), mCodecID); -@@ -781,22 +786,32 @@ - float decodeTime = (TimeStamp::Now() - aDecodeStart).ToMilliseconds(); - mAverangeDecodeTime = - (mAverangeDecodeTime * (mDecodedFrames - 1) + decodeTime) / - mDecodedFrames; - FFMPEG_LOG( -- " decode time %.2f ms averange decode time %.2f ms decoded frames %d\n", -+ "Frame decode finished, time %.2f ms averange decode time %.2f ms " -+ "decoded %d frames\n", - decodeTime, mAverangeDecodeTime, mDecodedFrames); - #if LIBAVCODEC_VERSION_MAJOR >= 58 -- int frameDuration = mFrame->pkt_duration; -- if (frameDuration > 0 && frameDuration / 1000.0 < decodeTime) { -- mDecodedFramesLate++; -- FFMPEG_LOG( -- " slow decode: failed to decode in time, frame duration %.2f ms, " -- "decode time %.2f\n", -- frameDuration / 1000.0, decodeTime); -- FFMPEG_LOG(" all decoded frames / late decoded frames %d/%d\n", -- mDecodedFrames, mDecodedFramesLate); -+ if (mFrame->pkt_duration > 0) { -+ // Switch frame duration to ms -+ float frameDuration = mFrame->pkt_duration / 1000.0f; -+ if (frameDuration < decodeTime) { -+ PROFILER_MARKER_TEXT("FFmpegVideoDecoder::DoDecode", MEDIA_PLAYBACK, {}, -+ "frame decode takes too long"); -+ mDecodedFramesLate++; -+ if (frameDuration < mAverangeDecodeTime) { -+ mMissedDecodeInAverangeTime++; -+ } -+ FFMPEG_LOG( -+ " slow decode: failed to decode in time, frame duration %.2f ms, " -+ "decode time %.2f\n", -+ frameDuration, decodeTime); -+ FFMPEG_LOG(" frames: all decoded %d late decoded %d over averange %d\n", -+ mDecodedFrames, mDecodedFramesLate, -+ mMissedDecodeInAverangeTime); -+ } - } - #endif - } - - MediaResult FFmpegVideoDecoder::DoDecode( -@@ -866,10 +881,18 @@ - decodeStart = TimeStamp::Now(); - - MediaResult rv; - # ifdef MOZ_WAYLAND_USE_VAAPI - if (IsHardwareAccelerated()) { -+ if (mMissedDecodeInAverangeTime > HW_DECODE_LATE_FRAMES) { -+ PROFILER_MARKER_TEXT("FFmpegVideoDecoder::DoDecode", MEDIA_PLAYBACK, {}, -+ "Fallback to SW decode"); -+ FFMPEG_LOG(" HW decoding is slow, switch back to SW decode"); -+ return MediaResult( -+ NS_ERROR_DOM_MEDIA_DECODE_ERR, -+ RESULT_DETAIL("HW decoding is slow, switch back to SW decode")); -+ } - rv = CreateImageVAAPI(mFrame->pkt_pos, GetFramePts(mFrame), - mFrame->pkt_duration, aResults); - // If VA-API playback failed, just quit. Decoder is going to be restarted - // without VA-API. - if (NS_FAILED(rv)) { -@@ -1129,11 +1152,11 @@ - } - - MediaResult FFmpegVideoDecoder::CreateImageVAAPI( - int64_t aOffset, int64_t aPts, int64_t aDuration, - MediaDataDecoder::DecodedData& aResults) { -- FFMPEG_LOG("VA-API Got one frame output with pts=%" PRId64 "dts=%" PRId64 -+ FFMPEG_LOG("VA-API Got one frame output with pts=%" PRId64 " dts=%" PRId64 - " duration=%" PRId64 " opaque=%" PRId64, - aPts, mFrame->pkt_dts, aDuration, mCodecContext->reordered_opaque); - - VADRMPRIMESurfaceDescriptor vaDesc; - if (!GetVAAPISurfaceDescriptor(&vaDesc)) { - diff --git a/D145966.diff b/D145966.diff deleted file mode 100644 index 2ecfaec..0000000 --- a/D145966.diff +++ /dev/null @@ -1,20 +0,0 @@ -diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp ---- a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp -+++ b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp -@@ -780,12 +780,13 @@ - mDecodedFrames++; - float decodeTime = (TimeStamp::Now() - aDecodeStart).ToMilliseconds(); - mAverangeDecodeTime = - (mAverangeDecodeTime * (mDecodedFrames - 1) + decodeTime) / - mDecodedFrames; -- FFMPEG_LOG(" averange frame decode time %.2f ms decoded frames %d\n", -- mAverangeDecodeTime, mDecodedFrames); -+ FFMPEG_LOG( -+ " decode time %.2f ms averange decode time %.2f ms decoded frames %d\n", -+ decodeTime, mAverangeDecodeTime, mDecodedFrames); - #if LIBAVCODEC_VERSION_MAJOR >= 58 - int frameDuration = mFrame->pkt_duration; - if (frameDuration > 0 && frameDuration / 1000.0 < decodeTime) { - mDecodedFramesLate++; - FFMPEG_LOG( - diff --git a/D146271.diff b/D146271.diff deleted file mode 100644 index fd2e0b0..0000000 --- a/D146271.diff +++ /dev/null @@ -1,94 +0,0 @@ -diff -up firefox-101.0/security/sandbox/linux/SandboxFilter.cpp.D146271.diff firefox-101.0/security/sandbox/linux/SandboxFilter.cpp ---- firefox-101.0/security/sandbox/linux/SandboxFilter.cpp.D146271.diff 2022-05-27 01:16:59.000000000 +0200 -+++ firefox-101.0/security/sandbox/linux/SandboxFilter.cpp 2022-06-09 09:59:35.569235176 +0200 -@@ -125,28 +125,12 @@ namespace mozilla { - // denied if no broker client is provided by the concrete class. - class SandboxPolicyCommon : public SandboxPolicyBase { - protected: -- enum class ShmemUsage : uint8_t { -- MAY_CREATE, -- ONLY_USE, -- }; -- -- enum class AllowUnsafeSocketPair : uint8_t { -- NO, -- YES, -- }; -- -+ // Subclasses can assign these in their constructors to loosen the -+ // default settings. - SandboxBrokerClient* mBroker = nullptr; - bool mMayCreateShmem = false; - bool mAllowUnsafeSocketPair = false; - -- explicit SandboxPolicyCommon(SandboxBrokerClient* aBroker, -- ShmemUsage aShmemUsage, -- AllowUnsafeSocketPair aAllowUnsafeSocketPair) -- : mBroker(aBroker), -- mMayCreateShmem(aShmemUsage == ShmemUsage::MAY_CREATE), -- mAllowUnsafeSocketPair(aAllowUnsafeSocketPair == -- AllowUnsafeSocketPair::YES) {} -- - SandboxPolicyCommon() = default; - - typedef const sandbox::arch_seccomp_data& ArgsRef; -@@ -1228,11 +1212,13 @@ class ContentSandboxPolicy : public Sand - public: - ContentSandboxPolicy(SandboxBrokerClient* aBroker, - ContentProcessSandboxParams&& aParams) -- : SandboxPolicyCommon(aBroker, ShmemUsage::MAY_CREATE, -- AllowUnsafeSocketPair::YES), -- mParams(std::move(aParams)), -+ : mParams(std::move(aParams)), - mAllowSysV(PR_GetEnv("MOZ_SANDBOX_ALLOW_SYSV") != nullptr), -- mUsingRenderDoc(PR_GetEnv("RENDERDOC_CAPTUREOPTS") != nullptr) {} -+ mUsingRenderDoc(PR_GetEnv("RENDERDOC_CAPTUREOPTS") != nullptr) { -+ mBroker = aBroker; -+ mMayCreateShmem = true; -+ mAllowUnsafeSocketPair = true; -+ } - - ~ContentSandboxPolicy() override = default; - -@@ -1762,9 +1748,10 @@ UniquePtr GetM - // segments, so it may need file brokering. - class RDDSandboxPolicy final : public SandboxPolicyCommon { - public: -- explicit RDDSandboxPolicy(SandboxBrokerClient* aBroker) -- : SandboxPolicyCommon(aBroker, ShmemUsage::MAY_CREATE, -- AllowUnsafeSocketPair::NO) {} -+ explicit RDDSandboxPolicy(SandboxBrokerClient* aBroker) { -+ mBroker = aBroker; -+ mMayCreateShmem = true; -+ } - - #ifndef ANDROID - Maybe EvaluateIpcCall(int aCall, int aArgShift) const override { -@@ -1875,9 +1862,10 @@ UniquePtr GetD - // the SocketProcess sandbox looks like. - class SocketProcessSandboxPolicy final : public SandboxPolicyCommon { - public: -- explicit SocketProcessSandboxPolicy(SandboxBrokerClient* aBroker) -- : SandboxPolicyCommon(aBroker, ShmemUsage::MAY_CREATE, -- AllowUnsafeSocketPair::NO) {} -+ explicit SocketProcessSandboxPolicy(SandboxBrokerClient* aBroker) { -+ mBroker = aBroker; -+ mMayCreateShmem = true; -+ } - - static intptr_t FcntlTrap(const sandbox::arch_seccomp_data& aArgs, - void* aux) { -@@ -2013,9 +2001,10 @@ UniquePtr GetS - - class UtilitySandboxPolicy : public SandboxPolicyCommon { - public: -- explicit UtilitySandboxPolicy(SandboxBrokerClient* aBroker) -- : SandboxPolicyCommon(aBroker, ShmemUsage::MAY_CREATE, -- AllowUnsafeSocketPair::NO) {} -+ explicit UtilitySandboxPolicy(SandboxBrokerClient* aBroker) { -+ mBroker = aBroker; -+ mMayCreateShmem = true; -+ } - - ResultExpr PrctlPolicy() const override { - Arg op(0); diff --git a/D146272.diff b/D146272.diff deleted file mode 100644 index 0a2c749..0000000 --- a/D146272.diff +++ /dev/null @@ -1,373 +0,0 @@ -diff --git a/security/sandbox/linux/SandboxFilter.cpp b/security/sandbox/linux/SandboxFilter.cpp ---- a/security/sandbox/linux/SandboxFilter.cpp -+++ b/security/sandbox/linux/SandboxFilter.cpp -@@ -128,10 +128,11 @@ - // Subclasses can assign these in their constructors to loosen the - // default settings. - SandboxBrokerClient* mBroker = nullptr; - bool mMayCreateShmem = false; - bool mAllowUnsafeSocketPair = false; -+ bool mBrokeredConnect = false; // Can connect() be brokered? - - SandboxPolicyCommon() = default; - - typedef const sandbox::arch_seccomp_data& ArgsRef; - -@@ -533,10 +534,124 @@ - MOZ_CRASH("unreachable?"); - return -ENOSYS; - #endif - } - -+ // This just needs to return something to stand in for the -+ // unconnected socket until ConnectTrap, below, and keep track of -+ // the socket type somehow. Half a socketpair *is* a socket, so it -+ // should result in minimal confusion in the caller. -+ static intptr_t FakeSocketTrapCommon(int domain, int type, int protocol) { -+ int fds[2]; -+ // X11 client libs will still try to getaddrinfo() even for a -+ // local connection. Also, WebRTC still has vestigial network -+ // code trying to do things in the content process. Politely tell -+ // them no. -+ if (domain != AF_UNIX) { -+ return -EAFNOSUPPORT; -+ } -+ if (socketpair(domain, type, protocol, fds) != 0) { -+ return -errno; -+ } -+ close(fds[1]); -+ return fds[0]; -+ } -+ -+ static intptr_t FakeSocketTrap(ArgsRef aArgs, void* aux) { -+ return FakeSocketTrapCommon(static_cast(aArgs.args[0]), -+ static_cast(aArgs.args[1]), -+ static_cast(aArgs.args[2])); -+ } -+ -+ static intptr_t FakeSocketTrapLegacy(ArgsRef aArgs, void* aux) { -+ const auto innerArgs = reinterpret_cast(aArgs.args[1]); -+ -+ return FakeSocketTrapCommon(static_cast(innerArgs[0]), -+ static_cast(innerArgs[1]), -+ static_cast(innerArgs[2])); -+ } -+ -+ static Maybe DoGetSockOpt(int fd, int optname) { -+ int optval; -+ socklen_t optlen = sizeof(optval); -+ -+ if (getsockopt(fd, SOL_SOCKET, optname, &optval, &optlen) != 0) { -+ return Nothing(); -+ } -+ MOZ_RELEASE_ASSERT(static_cast(optlen) == sizeof(optval)); -+ return Some(optval); -+ } -+ -+ // Substitute the newly connected socket from the broker for the -+ // original socket. This is meant to be used on a fd from -+ // FakeSocketTrap, above, but it should also work to simulate -+ // re-connect()ing a real connected socket. -+ // -+ // Warning: This isn't quite right if the socket is dup()ed, because -+ // other duplicates will still be the original socket, but hopefully -+ // nothing we're dealing with does that. -+ static intptr_t ConnectTrapCommon(SandboxBrokerClient* aBroker, int aFd, -+ const struct sockaddr_un* aAddr, -+ socklen_t aLen) { -+ if (aFd < 0) { -+ return -EBADF; -+ } -+ const auto maybeDomain = DoGetSockOpt(aFd, SO_DOMAIN); -+ if (!maybeDomain) { -+ return -errno; -+ } -+ if (*maybeDomain != AF_UNIX) { -+ return -EAFNOSUPPORT; -+ } -+ const auto maybeType = DoGetSockOpt(aFd, SO_TYPE); -+ if (!maybeType) { -+ return -errno; -+ } -+ const int oldFlags = fcntl(aFd, F_GETFL); -+ if (oldFlags == -1) { -+ return -errno; -+ } -+ const int newFd = aBroker->Connect(aAddr, aLen, *maybeType); -+ if (newFd < 0) { -+ return newFd; -+ } -+ // Copy over the nonblocking flag. The connect() won't be -+ // nonblocking in that case, but that shouldn't matter for -+ // AF_UNIX. The other fcntl-settable flags are either irrelevant -+ // for sockets (e.g., O_APPEND) or would be blocked by this -+ // seccomp-bpf policy, so they're ignored. -+ if (fcntl(newFd, F_SETFL, oldFlags & O_NONBLOCK) != 0) { -+ close(newFd); -+ return -errno; -+ } -+ if (dup2(newFd, aFd) < 0) { -+ close(newFd); -+ return -errno; -+ } -+ close(newFd); -+ return 0; -+ } -+ -+ static intptr_t ConnectTrap(ArgsRef aArgs, void* aux) { -+ typedef const struct sockaddr_un* AddrPtr; -+ -+ return ConnectTrapCommon(static_cast(aux), -+ static_cast(aArgs.args[0]), -+ reinterpret_cast(aArgs.args[1]), -+ static_cast(aArgs.args[2])); -+ } -+ -+ static intptr_t ConnectTrapLegacy(ArgsRef aArgs, void* aux) { -+ const auto innerArgs = reinterpret_cast(aArgs.args[1]); -+ typedef const struct sockaddr_un* AddrPtr; -+ -+ return ConnectTrapCommon(static_cast(aux), -+ static_cast(innerArgs[0]), -+ reinterpret_cast(innerArgs[1]), -+ static_cast(innerArgs[2])); -+ } -+ - public: - ResultExpr InvalidSyscall() const override { - return Trap(BlockedSyscallTrap, nullptr); - } - -@@ -630,15 +745,37 @@ - return Some(Allow()); - } - Arg level(1), optname(2); - // SO_SNDBUF is used by IPC to avoid constructing - // unnecessarily large gather arrays for `sendmsg`. -- return Some( -- If(AllOf(level == SOL_SOCKET, optname == SO_SNDBUF), Allow()) -- .Else(InvalidSyscall())); -+ // -+ // SO_DOMAIN and SO_TYPE are needed for connect() brokering, -+ // but they're harmless even when it's not enabled. -+ return Some(If(AllOf(level == SOL_SOCKET, -+ AnyOf(optname == SO_SNDBUF, optname == SO_DOMAIN, -+ optname == SO_TYPE)), -+ Allow()) -+ .Else(InvalidSyscall())); - } - -+ // These two cases are for connect() brokering, if enabled. -+ case SYS_SOCKET: -+ if (mBrokeredConnect) { -+ const auto trapFn = aHasArgs ? FakeSocketTrap : FakeSocketTrapLegacy; -+ MOZ_ASSERT(mBroker); -+ return Some(Trap(trapFn, mBroker)); -+ } -+ return Nothing(); -+ -+ case SYS_CONNECT: -+ if (mBrokeredConnect) { -+ const auto trapFn = aHasArgs ? ConnectTrap : ConnectTrapLegacy; -+ MOZ_ASSERT(mBroker); -+ return Some(Trap(trapFn, mBroker)); -+ } -+ return Nothing(); -+ - default: - return Nothing(); - } - } - -@@ -1006,10 +1143,16 @@ - return If(AnyOf(request == TCGETS, request == TIOCGWINSZ), - Error(ENOTTY)) - .Else(SandboxPolicyBase::EvaluateSyscall(sysno)); - } - -+ CASES_FOR_dup2: // See ConnectTrapCommon -+ if (mBrokeredConnect) { -+ return Allow(); -+ } -+ return SandboxPolicyBase::EvaluateSyscall(sysno); -+ - #ifdef MOZ_ASAN - // ASAN's error reporter wants to know if stderr is a tty. - case __NR_ioctl: { - Arg fd(0); - return If(fd == STDERR_FILENO, Error(ENOTTY)).Else(InvalidSyscall()); -@@ -1093,133 +1236,20 @@ - - close(fd); - return rv; - } - -- // This just needs to return something to stand in for the -- // unconnected socket until ConnectTrap, below, and keep track of -- // the socket type somehow. Half a socketpair *is* a socket, so it -- // should result in minimal confusion in the caller. -- static intptr_t FakeSocketTrapCommon(int domain, int type, int protocol) { -- int fds[2]; -- // X11 client libs will still try to getaddrinfo() even for a -- // local connection. Also, WebRTC still has vestigial network -- // code trying to do things in the content process. Politely tell -- // them no. -- if (domain != AF_UNIX) { -- return -EAFNOSUPPORT; -- } -- if (socketpair(domain, type, protocol, fds) != 0) { -- return -errno; -- } -- close(fds[1]); -- return fds[0]; -- } -- -- static intptr_t FakeSocketTrap(ArgsRef aArgs, void* aux) { -- return FakeSocketTrapCommon(static_cast(aArgs.args[0]), -- static_cast(aArgs.args[1]), -- static_cast(aArgs.args[2])); -- } -- -- static intptr_t FakeSocketTrapLegacy(ArgsRef aArgs, void* aux) { -- const auto innerArgs = reinterpret_cast(aArgs.args[1]); -- -- return FakeSocketTrapCommon(static_cast(innerArgs[0]), -- static_cast(innerArgs[1]), -- static_cast(innerArgs[2])); -- } -- -- static Maybe DoGetSockOpt(int fd, int optname) { -- int optval; -- socklen_t optlen = sizeof(optval); -- -- if (getsockopt(fd, SOL_SOCKET, optname, &optval, &optlen) != 0) { -- return Nothing(); -- } -- MOZ_RELEASE_ASSERT(static_cast(optlen) == sizeof(optval)); -- return Some(optval); -- } -- -- // Substitute the newly connected socket from the broker for the -- // original socket. This is meant to be used on a fd from -- // FakeSocketTrap, above, but it should also work to simulate -- // re-connect()ing a real connected socket. -- // -- // Warning: This isn't quite right if the socket is dup()ed, because -- // other duplicates will still be the original socket, but hopefully -- // nothing we're dealing with does that. -- static intptr_t ConnectTrapCommon(SandboxBrokerClient* aBroker, int aFd, -- const struct sockaddr_un* aAddr, -- socklen_t aLen) { -- if (aFd < 0) { -- return -EBADF; -- } -- const auto maybeDomain = DoGetSockOpt(aFd, SO_DOMAIN); -- if (!maybeDomain) { -- return -errno; -- } -- if (*maybeDomain != AF_UNIX) { -- return -EAFNOSUPPORT; -- } -- const auto maybeType = DoGetSockOpt(aFd, SO_TYPE); -- if (!maybeType) { -- return -errno; -- } -- const int oldFlags = fcntl(aFd, F_GETFL); -- if (oldFlags == -1) { -- return -errno; -- } -- const int newFd = aBroker->Connect(aAddr, aLen, *maybeType); -- if (newFd < 0) { -- return newFd; -- } -- // Copy over the nonblocking flag. The connect() won't be -- // nonblocking in that case, but that shouldn't matter for -- // AF_UNIX. The other fcntl-settable flags are either irrelevant -- // for sockets (e.g., O_APPEND) or would be blocked by this -- // seccomp-bpf policy, so they're ignored. -- if (fcntl(newFd, F_SETFL, oldFlags & O_NONBLOCK) != 0) { -- close(newFd); -- return -errno; -- } -- if (dup2(newFd, aFd) < 0) { -- close(newFd); -- return -errno; -- } -- close(newFd); -- return 0; -- } -- -- static intptr_t ConnectTrap(ArgsRef aArgs, void* aux) { -- typedef const struct sockaddr_un* AddrPtr; -- -- return ConnectTrapCommon(static_cast(aux), -- static_cast(aArgs.args[0]), -- reinterpret_cast(aArgs.args[1]), -- static_cast(aArgs.args[2])); -- } -- -- static intptr_t ConnectTrapLegacy(ArgsRef aArgs, void* aux) { -- const auto innerArgs = reinterpret_cast(aArgs.args[1]); -- typedef const struct sockaddr_un* AddrPtr; -- -- return ConnectTrapCommon(static_cast(aux), -- static_cast(innerArgs[0]), -- reinterpret_cast(innerArgs[1]), -- static_cast(innerArgs[2])); -- } -- - public: - ContentSandboxPolicy(SandboxBrokerClient* aBroker, - ContentProcessSandboxParams&& aParams) - : mParams(std::move(aParams)), - mAllowSysV(PR_GetEnv("MOZ_SANDBOX_ALLOW_SYSV") != nullptr), - mUsingRenderDoc(PR_GetEnv("RENDERDOC_CAPTUREOPTS") != nullptr) { - mBroker = aBroker; - mMayCreateShmem = true; - mAllowUnsafeSocketPair = true; -+ mBrokeredConnect = true; - } - - ~ContentSandboxPolicy() override = default; - - Maybe EvaluateSocketCall(int aCall, -@@ -1232,18 +1262,16 @@ - - #ifdef ANDROID - case SYS_SOCKET: - return Some(Error(EACCES)); - #else // #ifdef DESKTOP -- case SYS_SOCKET: { -- const auto trapFn = aHasArgs ? FakeSocketTrap : FakeSocketTrapLegacy; -- return Some(AllowBelowLevel(4, Trap(trapFn, nullptr))); -- } -- case SYS_CONNECT: { -- const auto trapFn = aHasArgs ? ConnectTrap : ConnectTrapLegacy; -- return Some(AllowBelowLevel(4, Trap(trapFn, mBroker))); -- } -+ case SYS_SOCKET: -+ case SYS_CONNECT: -+ if (BelowLevel(4)) { -+ return Some(Allow()); -+ } -+ return SandboxPolicyCommon::EvaluateSocketCall(aCall, aHasArgs); - case SYS_RECV: - case SYS_SEND: - case SYS_GETSOCKOPT: - case SYS_SETSOCKOPT: - case SYS_GETSOCKNAME: -@@ -1458,13 +1486,10 @@ - - case __NR_getrusage: - case __NR_times: - return Allow(); - -- CASES_FOR_dup2: // See ConnectTrapCommon -- return Allow(); -- - case __NR_fsync: - case __NR_msync: - return Allow(); - - case __NR_getpriority: - diff --git a/D146273.diff b/D146273.diff deleted file mode 100644 index 0d838e2..0000000 --- a/D146273.diff +++ /dev/null @@ -1,90 +0,0 @@ -diff --git a/security/sandbox/linux/SandboxFilter.cpp b/security/sandbox/linux/SandboxFilter.cpp ---- a/security/sandbox/linux/SandboxFilter.cpp -+++ b/security/sandbox/linux/SandboxFilter.cpp -@@ -699,10 +699,18 @@ - Maybe EvaluateSocketCall(int aCall, - bool aHasArgs) const override { - switch (aCall) { - case SYS_RECVMSG: - case SYS_SENDMSG: -+ // These next four aren't needed for IPC or other core -+ // functionality at the time of this writing, but they're -+ // subsets of recvmsg/sendmsg so there's nothing gained by not -+ // allowing them here (and simplifying subclasses). -+ case SYS_RECVFROM: -+ case SYS_SENDTO: -+ case SYS_RECV: -+ case SYS_SEND: - return Some(Allow()); - - case SYS_SOCKETPAIR: { - // We try to allow "safe" (always connected) socketpairs when using the - // file broker, or for content processes, but we may need to fall back -@@ -1253,12 +1261,10 @@ - ~ContentSandboxPolicy() override = default; - - Maybe EvaluateSocketCall(int aCall, - bool aHasArgs) const override { - switch (aCall) { -- case SYS_RECVFROM: -- case SYS_SENDTO: - case SYS_SENDMMSG: // libresolv via libasyncns; see bug 1355274 - return Some(Allow()); - - #ifdef ANDROID - case SYS_SOCKET: -@@ -1268,18 +1274,21 @@ - case SYS_CONNECT: - if (BelowLevel(4)) { - return Some(Allow()); - } - return SandboxPolicyCommon::EvaluateSocketCall(aCall, aHasArgs); -- case SYS_RECV: -- case SYS_SEND: -+ -+ // FIXME (bug 1761134): sockopts should be filtered - case SYS_GETSOCKOPT: - case SYS_SETSOCKOPT: -+ // These next 3 were needed for X11; they may not be needed -+ // with X11 lockdown, but there's not much attack surface here. - case SYS_GETSOCKNAME: - case SYS_GETPEERNAME: - case SYS_SHUTDOWN: - return Some(Allow()); -+ - case SYS_ACCEPT: - case SYS_ACCEPT4: - if (mUsingRenderDoc) { - return Some(Allow()); - } -@@ -1908,26 +1917,19 @@ - } - - Maybe EvaluateSocketCall(int aCall, - bool aHasArgs) const override { - switch (aCall) { -+ case SYS_SOCKET: -+ case SYS_CONNECT: - case SYS_BIND: - return Some(Allow()); - -- case SYS_SOCKET: -- return Some(Allow()); -- -- case SYS_CONNECT: -- return Some(Allow()); -- -- case SYS_RECVFROM: -- case SYS_SENDTO: -+ // FIXME(bug 1641401) do we really need this? - case SYS_SENDMMSG: - return Some(Allow()); - -- case SYS_RECV: -- case SYS_SEND: - case SYS_GETSOCKOPT: - case SYS_SETSOCKOPT: - case SYS_GETSOCKNAME: - case SYS_GETPEERNAME: - case SYS_SHUTDOWN: - diff --git a/D146274.diff b/D146274.diff deleted file mode 100644 index 8943ac4..0000000 --- a/D146274.diff +++ /dev/null @@ -1,158 +0,0 @@ -diff --git a/security/sandbox/linux/broker/SandboxBrokerPolicyFactory.cpp b/security/sandbox/linux/broker/SandboxBrokerPolicyFactory.cpp ---- a/security/sandbox/linux/broker/SandboxBrokerPolicyFactory.cpp -+++ b/security/sandbox/linux/broker/SandboxBrokerPolicyFactory.cpp -@@ -325,30 +325,84 @@ - policy->AddDynamic(perms, trimPath.get()); - } - } - } - -+static void AddX11Dependencies(SandboxBroker::Policy* policy) { -+ // Allow Primus to contact the Bumblebee daemon to manage GPU -+ // switching on NVIDIA Optimus systems. -+ const char* bumblebeeSocket = PR_GetEnv("BUMBLEBEE_SOCKET"); -+ if (bumblebeeSocket == nullptr) { -+ bumblebeeSocket = "/var/run/bumblebee.socket"; -+ } -+ policy->AddPath(SandboxBroker::MAY_CONNECT, bumblebeeSocket); -+ -+#if defined(MOZ_WIDGET_GTK) && defined(MOZ_X11) -+ // Allow local X11 connections, for several purposes: -+ // -+ // * for content processes to use WebGL when the browser is in headless -+ // mode, by opening the X display if/when needed -+ // -+ // * if Primus or VirtualGL is used, to contact the secondary X server -+ static const bool kIsX11 = -+ !mozilla::widget::GdkIsWaylandDisplay() && PR_GetEnv("DISPLAY"); -+ if (kIsX11) { -+ policy->AddPrefix(SandboxBroker::MAY_CONNECT, "/tmp/.X11-unix/X"); -+ if (auto* const xauth = PR_GetEnv("XAUTHORITY")) { -+ policy->AddPath(rdonly, xauth); -+ } else if (auto* const home = PR_GetEnv("HOME")) { -+ // This follows the logic in libXau: append "/.Xauthority", -+ // even if $HOME ends in a slash, except in the special case -+ // where HOME=/ because POSIX allows implementations to treat -+ // an initial double slash specially. -+ nsAutoCString xauth(home); -+ if (xauth != "/"_ns) { -+ xauth.Append('/'); -+ } -+ xauth.AppendLiteral(".Xauthority"); -+ policy->AddPath(rdonly, xauth.get()); -+ } -+ } -+#endif -+} -+ -+static void AddGLDependencies(SandboxBroker::Policy* policy) { -+ // Devices -+ policy->AddDir(rdwr, "/dev/dri"); -+ policy->AddFilePrefix(rdwr, "/dev", "nvidia"); -+ -+ // Hardware info -+ AddDriPaths(policy); -+ -+ // /etc and /usr/share (glvnd, libdrm, drirc, ...?) -+ policy->AddDir(rdonly, "/etc"); -+ policy->AddDir(rdonly, "/usr/share"); -+ policy->AddDir(rdonly, "/usr/local/share"); -+ -+ // Note: This function doesn't do anything about Mesa's shader -+ // cache, because the details can vary by process type, including -+ // whether caching is enabled. -+ -+ AddX11Dependencies(policy); -+} -+ - void SandboxBrokerPolicyFactory::InitContentPolicy() { - const bool headless = - StaticPrefs::security_sandbox_content_headless_AtStartup(); - - // Policy entries that are the same in every process go here, and - // are cached over the lifetime of the factory. - SandboxBroker::Policy* policy = new SandboxBroker::Policy; - // Write permssions -- // -- if (!headless) { -- // Bug 1308851: NVIDIA proprietary driver when using WebGL -- policy->AddFilePrefix(rdwr, "/dev", "nvidia"); -- -- // Bug 1312678: Mesa with DRI when using WebGL -- policy->AddDir(rdwr, "/dev/dri"); -- } - - // Bug 1575985: WASM library sandbox needs RW access to /dev/null - policy->AddPath(rdwr, "/dev/null"); - -+ if (!headless) { -+ AddGLDependencies(policy); -+ } -+ - // Read permissions - policy->AddPath(rdonly, "/dev/urandom"); - policy->AddPath(rdonly, "/dev/random"); - policy->AddPath(rdonly, "/proc/sys/crypto/fips_enabled"); - policy->AddPath(rdonly, "/proc/cpuinfo"); -@@ -370,13 +424,10 @@ - policy->AddDir(rdonly, "/run/host/fonts"); - policy->AddDir(rdonly, "/run/host/user-fonts"); - policy->AddDir(rdonly, "/run/host/local-fonts"); - policy->AddDir(rdonly, "/var/cache/fontconfig"); - -- if (!headless) { -- AddDriPaths(policy); -- } - AddLdconfigPaths(policy); - AddLdLibraryEnvPaths(policy); - - if (!headless) { - // Bug 1385715: NVIDIA PRIME support -@@ -569,45 +620,11 @@ - } - } - #endif - - if (!headless) { -- // Allow Primus to contact the Bumblebee daemon to manage GPU -- // switching on NVIDIA Optimus systems. -- const char* bumblebeeSocket = PR_GetEnv("BUMBLEBEE_SOCKET"); -- if (bumblebeeSocket == nullptr) { -- bumblebeeSocket = "/var/run/bumblebee.socket"; -- } -- policy->AddPath(SandboxBroker::MAY_CONNECT, bumblebeeSocket); -- --#if defined(MOZ_WIDGET_GTK) && defined(MOZ_X11) -- // Allow local X11 connections, for several purposes: -- // -- // * for content processes to use WebGL when the browser is in headless -- // mode, by opening the X display if/when needed -- // -- // * if Primus or VirtualGL is used, to contact the secondary X server -- static const bool kIsX11 = -- !mozilla::widget::GdkIsWaylandDisplay() && PR_GetEnv("DISPLAY"); -- if (kIsX11) { -- policy->AddPrefix(SandboxBroker::MAY_CONNECT, "/tmp/.X11-unix/X"); -- if (auto* const xauth = PR_GetEnv("XAUTHORITY")) { -- policy->AddPath(rdonly, xauth); -- } else if (auto* const home = PR_GetEnv("HOME")) { -- // This follows the logic in libXau: append "/.Xauthority", -- // even if $HOME ends in a slash, except in the special case -- // where HOME=/ because POSIX allows implementations to treat -- // an initial double slash specially. -- nsAutoCString xauth(home); -- if (xauth != "/"_ns) { -- xauth.Append('/'); -- } -- xauth.AppendLiteral(".Xauthority"); -- policy->AddPath(rdonly, xauth.get()); -- } -- } --#endif -+ AddX11Dependencies(policy); - } - - // Bug 1732580: when packaged as a strictly confined snap, may need - // read-access to configuration files under $SNAP/. - const char* snap = PR_GetEnv("SNAP"); - diff --git a/D146275.diff b/D146275.diff deleted file mode 100644 index 989b317..0000000 --- a/D146275.diff +++ /dev/null @@ -1,125 +0,0 @@ -diff --git a/ipc/glue/GeckoChildProcessHost.cpp b/ipc/glue/GeckoChildProcessHost.cpp ---- a/ipc/glue/GeckoChildProcessHost.cpp -+++ b/ipc/glue/GeckoChildProcessHost.cpp -@@ -418,10 +418,17 @@ - nsresult rv = NS_GetSpecialDirectory(NS_APP_CONTENT_PROCESS_TEMP_DIR, - getter_AddRefs(contentTempDir)); - if (NS_SUCCEEDED(rv)) { - contentTempDir->GetNativePath(mTmpDirName); - } -+ } else if (aProcessType == GeckoProcessType_RDD) { -+ // The RDD process makes limited use of EGL. If Mesa's shader -+ // cache is enabled and the directory isn't explicitly set, then -+ // it will try to getpwuid() the user which can cause problems -+ // with sandboxing. Because we shouldn't need shader caching in -+ // this process, we just disable the cache to prevent that. -+ mLaunchOptions->env_map["MESA_GLSL_CACHE_DISABLE"] = "true"; - } - #endif - #if defined(MOZ_ENABLE_FORKSERVER) - if (aProcessType == GeckoProcessType_Content && ForkServiceChild::Get()) { - mLaunchOptions->use_forkserver = true; -diff --git a/security/sandbox/common/test/SandboxTestingChildTests.h b/security/sandbox/common/test/SandboxTestingChildTests.h ---- a/security/sandbox/common/test/SandboxTestingChildTests.h -+++ b/security/sandbox/common/test/SandboxTestingChildTests.h -@@ -21,14 +21,16 @@ - # include - # include - # include - # include - # include -+# include - # include - # include - # include - # include "mozilla/ProcInfo_linux.h" -+# include "mozilla/UniquePtrExtensions.h" - # ifdef MOZ_X11 - # include "X11/Xlib.h" - # include "X11UndefineNone.h" - # endif // MOZ_X11 - # endif // XP_LINUX -@@ -595,12 +597,25 @@ - return rv; - }); - - RunTestsSched(child); - -- child->ErrnoTest("socket"_ns, false, -- [] { return socket(AF_UNIX, SOCK_STREAM, 0); }); -+ child->ErrnoTest("socket_inet"_ns, false, -+ [] { return socket(AF_INET, SOCK_STREAM, 0); }); -+ -+ { -+ UniqueFileHandle fd(socket(AF_UNIX, SOCK_STREAM, 0)); -+ child->ErrnoTest("socket_unix"_ns, true, [&] { return fd.get(); }); -+ -+ struct sockaddr_un sun {}; -+ sun.sun_family = AF_UNIX; -+ strncpy(sun.sun_path, "/tmp/forbidden-sock", sizeof(sun.sun_path)); -+ -+ child->ErrnoValueTest("socket_unix_bind"_ns, ENOSYS, [&] { -+ return bind(fd.get(), (struct sockaddr*)&sun, sizeof(sun)); -+ }); -+ } - - child->ErrnoTest("uname"_ns, true, [] { - struct utsname uts; - return uname(&uts); - }); -diff --git a/security/sandbox/linux/SandboxFilter.cpp b/security/sandbox/linux/SandboxFilter.cpp ---- a/security/sandbox/linux/SandboxFilter.cpp -+++ b/security/sandbox/linux/SandboxFilter.cpp -@@ -1783,10 +1783,11 @@ - class RDDSandboxPolicy final : public SandboxPolicyCommon { - public: - explicit RDDSandboxPolicy(SandboxBrokerClient* aBroker) { - mBroker = aBroker; - mMayCreateShmem = true; -+ mBrokeredConnect = true; - } - - #ifndef ANDROID - Maybe EvaluateIpcCall(int aCall, int aArgShift) const override { - // The Intel media driver uses SysV IPC (semaphores and shared -@@ -1818,15 +1819,15 @@ - #endif - - Maybe EvaluateSocketCall(int aCall, - bool aHasArgs) const override { - switch (aCall) { -- // Mesa can call getpwuid_r to get the home dir, which can try -- // to connect to nscd (or maybe servers like NIS or LDAP); this -- // can't be safely allowed, but we can quietly deny it. -- case SYS_SOCKET: -- return Some(Error(EACCES)); -+ // These are for X11. -+ case SYS_GETSOCKNAME: -+ case SYS_GETPEERNAME: -+ case SYS_SHUTDOWN: -+ return Some(Allow()); - - default: - return SandboxPolicyCommon::EvaluateSocketCall(aCall, aHasArgs); - } - } -diff --git a/security/sandbox/linux/broker/SandboxBrokerPolicyFactory.cpp b/security/sandbox/linux/broker/SandboxBrokerPolicyFactory.cpp ---- a/security/sandbox/linux/broker/SandboxBrokerPolicyFactory.cpp -+++ b/security/sandbox/linux/broker/SandboxBrokerPolicyFactory.cpp -@@ -853,13 +853,12 @@ - if (developer_repo_dir) { - policy->AddDir(rdonly, developer_repo_dir); - } - } - -- // VA-API needs DRI and GPU detection -- policy->AddDir(rdwr, "/dev/dri"); -- AddDriPaths(policy.get()); -+ // VA-API needs GPU access and GL context creation -+ AddGLDependencies(policy.get()); - - // FFmpeg and GPU drivers may need general-case library loading - AddLdconfigPaths(policy.get()); - AddLdLibraryEnvPaths(policy.get()); - - diff --git a/D147635.diff b/D147635.diff deleted file mode 100644 index 1d4bb58..0000000 --- a/D147635.diff +++ /dev/null @@ -1,125 +0,0 @@ -diff --git a/gfx/gl/GLLibraryEGL.h b/gfx/gl/GLLibraryEGL.h ---- a/gfx/gl/GLLibraryEGL.h -+++ b/gfx/gl/GLLibraryEGL.h -@@ -106,10 +106,13 @@ - KHR_swap_buffers_with_damage, - EXT_buffer_age, - KHR_partial_update, - NV_robustness_video_memory_purge, - MESA_platform_surfaceless, -+ EXT_image_dma_buf_import, -+ EXT_image_dma_buf_import_modifiers, -+ MESA_image_dma_buf_export, - Max - }; - - // - - -@@ -461,10 +464,23 @@ - // EGL_KHR_partial_update - EGLBoolean fSetDamageRegion(EGLDisplay dpy, EGLSurface surface, - const EGLint* rects, EGLint n_rects) { - WRAP(fSetDamageRegion(dpy, surface, rects, n_rects)); - } -+ // EGL_MESA_image_dma_buf_export -+ EGLBoolean fExportDMABUFImageQuery(EGLDisplay dpy, EGLImage image, -+ int* fourcc, int* num_planes, -+ uint64_t* modifiers) { -+ WRAP( -+ fExportDMABUFImageQueryMESA(dpy, image, fourcc, num_planes, modifiers)); -+ } -+ EGLBoolean fExportDMABUFImage(EGLDisplay dpy, EGLImage image, int* fds, -+ EGLint* strides, EGLint* offsets) { -+ WRAP(fExportDMABUFImageMESA(dpy, image, fds, strides, offsets)); -+ } -+ -+#undef WRAP - - #undef WRAP - #undef PROFILE_CALL - #undef BEFORE_CALL - #undef AFTER_CALL -@@ -593,10 +609,22 @@ - EGLBoolean(GLAPIENTRY* fSetDamageRegion)(EGLDisplay dpy, EGLSurface surface, - const EGLint* rects, - EGLint n_rects); - EGLClientBuffer(GLAPIENTRY* fGetNativeClientBufferANDROID)( - const struct AHardwareBuffer* buffer); -+ -+ // EGL_MESA_image_dma_buf_export -+ EGLBoolean(GLAPIENTRY* fExportDMABUFImageQueryMESA)(EGLDisplay dpy, -+ EGLImage image, -+ int* fourcc, -+ int* num_planes, -+ uint64_t* modifiers); -+ EGLBoolean(GLAPIENTRY* fExportDMABUFImageMESA)(EGLDisplay dpy, -+ EGLImage image, int* fds, -+ EGLint* strides, -+ EGLint* offsets); -+ - } mSymbols = {}; - }; - - class EglDisplay final { - public: -@@ -852,10 +880,23 @@ - EGLBoolean fSetDamageRegion(EGLSurface surface, const EGLint* rects, - EGLint n_rects) { - MOZ_ASSERT(IsExtensionSupported(EGLExtension::KHR_partial_update)); - return mLib->fSetDamageRegion(mDisplay, surface, rects, n_rects); - } -+ -+ EGLBoolean fExportDMABUFImageQuery(EGLImage image, int* fourcc, -+ int* num_planes, -+ uint64_t* modifiers) const { -+ MOZ_ASSERT(IsExtensionSupported(EGLExtension::MESA_image_dma_buf_export)); -+ return mLib->fExportDMABUFImageQuery(mDisplay, image, fourcc, num_planes, -+ modifiers); -+ } -+ EGLBoolean fExportDMABUFImage(EGLImage image, int* fds, EGLint* strides, -+ EGLint* offsets) const { -+ MOZ_ASSERT(IsExtensionSupported(EGLExtension::MESA_image_dma_buf_export)); -+ return mLib->fExportDMABUFImage(mDisplay, image, fds, strides, offsets); -+ } - }; - - } /* namespace gl */ - } /* namespace mozilla */ - -diff --git a/gfx/gl/GLLibraryEGL.cpp b/gfx/gl/GLLibraryEGL.cpp ---- a/gfx/gl/GLLibraryEGL.cpp -+++ b/gfx/gl/GLLibraryEGL.cpp -@@ -82,11 +82,14 @@ - "EGL_EXT_swap_buffers_with_damage", - "EGL_KHR_swap_buffers_with_damage", - "EGL_EXT_buffer_age", - "EGL_KHR_partial_update", - "EGL_NV_robustness_video_memory_purge", -- "EGL_MESA_platform_surfaceless"}; -+ "EGL_MESA_platform_surfaceless", -+ "EGL_EXT_image_dma_buf_import", -+ "EGL_EXT_image_dma_buf_import_modifiers", -+ "EGL_MESA_image_dma_buf_export"}; - - PRLibrary* LoadApitraceLibrary() { - const char* path = nullptr; - - #ifdef ANDROID -@@ -647,10 +650,16 @@ - { - const SymLoadStruct symbols[] = {SYMBOL(GetPlatformDisplay), - END_OF_SYMBOLS}; - (void)fnLoadSymbols(symbols); - } -+ { -+ const SymLoadStruct symbols[] = {SYMBOL(ExportDMABUFImageQueryMESA), -+ SYMBOL(ExportDMABUFImageMESA), -+ END_OF_SYMBOLS}; -+ (void)fnLoadSymbols(symbols); -+ } - - return true; - } - - // - - diff --git a/D147636.diff b/D147636.diff deleted file mode 100644 index 52462f2..0000000 --- a/D147636.diff +++ /dev/null @@ -1,278 +0,0 @@ -diff --git a/widget/gtk/DMABufSurface.h b/widget/gtk/DMABufSurface.h ---- a/widget/gtk/DMABufSurface.h -+++ b/widget/gtk/DMABufSurface.h -@@ -173,13 +173,13 @@ - SurfaceType mSurfaceType; - uint64_t mBufferModifiers[DMABUF_BUFFER_PLANES]; - - int mBufferPlaneCount; - int mDmabufFds[DMABUF_BUFFER_PLANES]; -- uint32_t mDrmFormats[DMABUF_BUFFER_PLANES]; -- uint32_t mStrides[DMABUF_BUFFER_PLANES]; -- uint32_t mOffsets[DMABUF_BUFFER_PLANES]; -+ int32_t mDrmFormats[DMABUF_BUFFER_PLANES]; -+ int32_t mStrides[DMABUF_BUFFER_PLANES]; -+ int32_t mOffsets[DMABUF_BUFFER_PLANES]; - - struct gbm_bo* mGbmBufferObject[DMABUF_BUFFER_PLANES]; - void* mMappedRegion[DMABUF_BUFFER_PLANES]; - void* mMappedRegionData[DMABUF_BUFFER_PLANES]; - uint32_t mMappedRegionStride[DMABUF_BUFFER_PLANES]; -@@ -198,10 +198,14 @@ - class DMABufSurfaceRGBA : public DMABufSurface { - public: - static already_AddRefed CreateDMABufSurface( - int aWidth, int aHeight, int aDMABufSurfaceFlags); - -+ static already_AddRefed CreateDMABufSurface( -+ mozilla::gl::GLContext* aGLContext, const EGLImageKHR aEGLImage, -+ int aWidth, int aHeight); -+ - bool Serialize(mozilla::layers::SurfaceDescriptor& aOutDescriptor); - - DMABufSurfaceRGBA* GetAsDMABufSurfaceRGBA() { return this; } - - void Clear(); -@@ -247,10 +251,12 @@ - private: - ~DMABufSurfaceRGBA(); - - bool Create(int aWidth, int aHeight, int aDMABufSurfaceFlags); - bool Create(const mozilla::layers::SurfaceDescriptor& aDesc); -+ bool Create(mozilla::gl::GLContext* aGLContext, const EGLImageKHR aEGLImage, -+ int aWidth, int aHeight); - - bool ImportSurfaceDescriptor(const mozilla::layers::SurfaceDescriptor& aDesc); - - bool OpenFileDescriptorForPlane(const mozilla::MutexAutoLock& aProofOfLock, - int aPlane); -diff --git a/widget/gtk/DMABufSurface.cpp b/widget/gtk/DMABufSurface.cpp ---- a/widget/gtk/DMABufSurface.cpp -+++ b/widget/gtk/DMABufSurface.cpp -@@ -204,10 +204,12 @@ - } - } - - void DMABufSurface::FenceSet() { - if (!mGL || !mGL->MakeCurrent()) { -+ MOZ_DIAGNOSTIC_ASSERT(mGL, -+ "DMABufSurface::FenceSet(): missing GL context!"); - return; - } - const auto& gle = gl::GLContextEGL::Cast(mGL); - const auto& egl = gle->mEgl; - -@@ -228,21 +230,23 @@ - mGL->fFinish(); - } - - void DMABufSurface::FenceWait() { - if (!mGL || mSyncFd < 0) { -+ MOZ_DIAGNOSTIC_ASSERT(mGL, -+ "DMABufSurface::FenceWait() missing GL context!"); - return; - } - - const auto& gle = gl::GLContextEGL::Cast(mGL); - const auto& egl = gle->mEgl; - - const EGLint attribs[] = {LOCAL_EGL_SYNC_NATIVE_FENCE_FD_ANDROID, mSyncFd, - LOCAL_EGL_NONE}; - EGLSync sync = egl->fCreateSync(LOCAL_EGL_SYNC_NATIVE_FENCE_ANDROID, attribs); - if (!sync) { -- MOZ_ASSERT(false, "Failed to create GLFence!"); -+ MOZ_ASSERT(false, "DMABufSurface::FenceWait(): Failed to create GLFence!"); - // We failed to create GLFence so clear mSyncFd to avoid another try. - close(mSyncFd); - mSyncFd = -1; - return; - } -@@ -338,17 +342,18 @@ - mGmbFormat = GetDMABufDevice()->GetGbmFormat(mSurfaceFlags & DMABUF_ALPHA); - if (!mGmbFormat) { - // Requested DRM format is not supported. - return false; - } -+ mDrmFormats[0] = mGmbFormat->mFormat; - - bool useModifiers = (aDMABufSurfaceFlags & DMABUF_USE_MODIFIERS) && - mGmbFormat->mModifiersCount > 0; - if (useModifiers) { - LOGDMABUF((" Creating with modifiers\n")); - mGbmBufferObject[0] = nsGbmLib::CreateWithModifiers( -- GetDMABufDevice()->GetGbmDevice(), mWidth, mHeight, mGmbFormat->mFormat, -+ GetDMABufDevice()->GetGbmDevice(), mWidth, mHeight, mDrmFormats[0], - mGmbFormat->mModifiers, mGmbFormat->mModifiersCount); - if (mGbmBufferObject[0]) { - mBufferModifiers[0] = nsGbmLib::GetModifier(mGbmBufferObject[0]); - } - } -@@ -356,11 +361,11 @@ - if (!mGbmBufferObject[0]) { - LOGDMABUF((" Creating without modifiers\n")); - mGbmBufferFlags = GBM_BO_USE_LINEAR; - mGbmBufferObject[0] = - nsGbmLib::Create(GetDMABufDevice()->GetGbmDevice(), mWidth, mHeight, -- mGmbFormat->mFormat, mGbmBufferFlags); -+ mDrmFormats[0], mGbmBufferFlags); - mBufferModifiers[0] = DRM_FORMAT_MOD_INVALID; - } - - if (!mGbmBufferObject[0]) { - LOGDMABUF((" Failed to create GbmBufferObject\n")); -@@ -386,22 +391,51 @@ - - LOGDMABUF((" Success\n")); - return true; - } - -+bool DMABufSurfaceRGBA::Create(mozilla::gl::GLContext* aGLContext, -+ const EGLImageKHR aEGLImage, int aWidth, -+ int aHeight) { -+ LOGDMABUF(("DMABufSurfaceRGBA::Create() from EGLImage UID = %d\n", mUID)); -+ if (!aGLContext) { -+ return false; -+ } -+ const auto& gle = gl::GLContextEGL::Cast(aGLContext); -+ const auto& egl = gle->mEgl; -+ -+ mGL = aGLContext; -+ mWidth = aWidth; -+ mHeight = aHeight; -+ mEGLImage = aEGLImage; -+ if (!egl->fExportDMABUFImageQuery(mEGLImage, mDrmFormats, &mBufferPlaneCount, -+ mBufferModifiers)) { -+ LOGDMABUF((" ExportDMABUFImageQueryMESA failed, quit\n")); -+ return false; -+ } -+ if (mBufferPlaneCount > DMABUF_BUFFER_PLANES) { -+ LOGDMABUF((" wrong plane count %d, quit\n", mBufferPlaneCount)); -+ return false; -+ } -+ if (!egl->fExportDMABUFImage(mEGLImage, mDmabufFds, mStrides, mOffsets)) { -+ LOGDMABUF((" ExportDMABUFImageMESA failed, quit\n")); -+ return false; -+ } -+ -+ LOGDMABUF((" imported size %d x %d format %x planes %d", mWidth, mHeight, -+ mDrmFormats[0], mBufferPlaneCount)); -+ return true; -+} -+ - bool DMABufSurfaceRGBA::ImportSurfaceDescriptor( - const SurfaceDescriptor& aDesc) { - const SurfaceDescriptorDMABuf& desc = aDesc.get_SurfaceDescriptorDMABuf(); - - mWidth = desc.width()[0]; - mHeight = desc.height()[0]; - mBufferModifiers[0] = desc.modifier()[0]; -- if (mBufferModifiers[0] != DRM_FORMAT_MOD_INVALID) { -- mGmbFormat = GetDMABufDevice()->GetExactGbmFormat(desc.format()[0]); -- } else { -- mDrmFormats[0] = desc.format()[0]; -- } -+ mDrmFormats[0] = desc.format()[0]; - mBufferPlaneCount = desc.fds().Length(); - mGbmBufferFlags = desc.flags(); - MOZ_RELEASE_ASSERT(mBufferPlaneCount <= DMABUF_BUFFER_PLANES); - mUID = desc.uid(); - -@@ -431,10 +465,12 @@ - - if (desc.refCount().Length() > 0) { - GlobalRefCountImport(desc.refCount()[0].ClonePlatformHandle().release()); - } - -+ LOGDMABUF((" imported size %d x %d format %x planes %d", mWidth, mHeight, -+ mDrmFormats[0], mBufferPlaneCount)); - return true; - } - - bool DMABufSurfaceRGBA::Create(const SurfaceDescriptor& aDesc) { - return ImportSurfaceDescriptor(aDesc); -@@ -460,11 +496,11 @@ - return false; - } - - width.AppendElement(mWidth); - height.AppendElement(mHeight); -- format.AppendElement(mGmbFormat->mFormat); -+ format.AppendElement(mDrmFormats[0]); - modifiers.AppendElement(mBufferModifiers[0]); - for (int i = 0; i < mBufferPlaneCount; i++) { - fds.AppendElement(ipc::FileDescriptor(mDmabufFds[i])); - strides.AppendElement(mStrides[i]); - offsets.AppendElement(mOffsets[i]); -@@ -486,23 +522,20 @@ - fenceFDs, mUID, refCountFDs); - return true; - } - - bool DMABufSurfaceRGBA::CreateTexture(GLContext* aGLContext, int aPlane) { -+ LOGDMABUF(("DMABufSurfaceRGBA::CreateTexture() UID %d\n", mUID)); - MOZ_ASSERT(!mEGLImage && !mTexture, "EGLImage is already created!"); - - nsTArray attribs; - attribs.AppendElement(LOCAL_EGL_WIDTH); - attribs.AppendElement(mWidth); - attribs.AppendElement(LOCAL_EGL_HEIGHT); - attribs.AppendElement(mHeight); - attribs.AppendElement(LOCAL_EGL_LINUX_DRM_FOURCC_EXT); -- if (mGmbFormat) { -- attribs.AppendElement(mGmbFormat->mFormat); -- } else { -- attribs.AppendElement(mDrmFormats[0]); -- } -+ attribs.AppendElement(mDrmFormats[0]); - #define ADD_PLANE_ATTRIBS(plane_idx) \ - { \ - attribs.AppendElement(LOCAL_EGL_DMA_BUF_PLANE##plane_idx##_FD_EXT); \ - attribs.AppendElement(mDmabufFds[plane_idx]); \ - attribs.AppendElement(LOCAL_EGL_DMA_BUF_PLANE##plane_idx##_OFFSET_EXT); \ -@@ -560,10 +593,11 @@ - - return true; - } - - void DMABufSurfaceRGBA::ReleaseTextures() { -+ LOGDMABUF(("DMABufSurfaceRGBA::ReleaseTextures() UID %d\n", mUID)); - FenceDelete(); - - if (!mTexture) { - return; - } -@@ -618,11 +652,11 @@ - zwp_linux_buffer_params_v1_add(params, mDmabufFds[0], 0, mOffsets[0], - mStrides[0], mBufferModifiers[0] >> 32, - mBufferModifiers[0] & 0xffffffff); - - mWlBuffer = zwp_linux_buffer_params_v1_create_immed( -- params, GetWidth(), GetHeight(), mGmbFormat->mFormat, 0); -+ params, GetWidth(), GetHeight(), mDrmFormats[0], 0); - - CloseFileDescriptors(lockFD); - - return mWlBuffer != nullptr; - } -@@ -806,10 +840,20 @@ - return nullptr; - } - return surf.forget(); - } - -+already_AddRefed DMABufSurfaceRGBA::CreateDMABufSurface( -+ mozilla::gl::GLContext* aGLContext, const EGLImageKHR aEGLImage, int aWidth, -+ int aHeight) { -+ RefPtr surf = new DMABufSurfaceRGBA(); -+ if (!surf->Create(aGLContext, aEGLImage, aWidth, aHeight)) { -+ return nullptr; -+ } -+ return surf.forget(); -+} -+ - already_AddRefed DMABufSurfaceYUV::CreateYUVSurface( - const VADRMPRIMESurfaceDescriptor& aDesc, int aWidth, int aHeight) { - RefPtr surf = new DMABufSurfaceYUV(); - LOGDMABUF(("DMABufSurfaceYUV::CreateYUVSurface() UID %d from desc\n", - surf->GetUID())); - diff --git a/D147637.diff b/D147637.diff deleted file mode 100644 index 89bb25e..0000000 --- a/D147637.diff +++ /dev/null @@ -1,139 +0,0 @@ -diff -up firefox-102.0/gfx/gl/SharedSurfaceDMABUF.cpp.D147637.diff firefox-102.0/gfx/gl/SharedSurfaceDMABUF.cpp ---- firefox-102.0/gfx/gl/SharedSurfaceDMABUF.cpp.D147637.diff 2022-06-23 09:08:46.000000000 +0200 -+++ firefox-102.0/gfx/gl/SharedSurfaceDMABUF.cpp 2022-06-28 16:37:52.264835137 +0200 -@@ -9,25 +9,58 @@ - #include "GLContextEGL.h" - #include "MozFramebuffer.h" - #include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor, etc -+#include "mozilla/gfx/gfxVars.h" - - namespace mozilla::gl { - -+static bool HasDmaBufExtensions(const GLContextEGL* gl) { -+ const auto& egl = *(gl->mEgl); -+ return egl.IsExtensionSupported(EGLExtension::EXT_image_dma_buf_import) && -+ egl.IsExtensionSupported( -+ EGLExtension::EXT_image_dma_buf_import_modifiers) && -+ egl.IsExtensionSupported(EGLExtension::MESA_image_dma_buf_export); -+} -+ - /*static*/ - UniquePtr SharedSurface_DMABUF::Create( - const SharedSurfaceDesc& desc) { -- const auto flags = static_cast( -- DMABUF_TEXTURE | DMABUF_USE_MODIFIERS | DMABUF_ALPHA); -- const RefPtr surface = DMABufSurfaceRGBA::CreateDMABufSurface( -- desc.size.width, desc.size.height, flags); -- if (!surface || !surface->CreateTexture(desc.gl)) { -- return nullptr; -+ const auto& gle = GLContextEGL::Cast(desc.gl); -+ const auto& context = gle->mContext; -+ const auto& egl = *(gle->mEgl); -+ -+ RefPtr surface; -+ UniquePtr fb; -+ -+ if (!HasDmaBufExtensions(gle) || !gfx::gfxVars::UseDMABufSurfaceExport()) { -+ // Use MESA_image_dma_buf_export is not supported or it's broken. -+ // Create dmabuf surface directly via. GBM and create -+ // EGLImage/framebuffer over it. -+ const auto flags = static_cast( -+ DMABUF_TEXTURE | DMABUF_USE_MODIFIERS | DMABUF_ALPHA); -+ surface = DMABufSurfaceRGBA::CreateDMABufSurface(desc.size.width, -+ desc.size.height, flags); -+ if (!surface || !surface->CreateTexture(desc.gl)) { -+ return nullptr; -+ } -+ const auto tex = surface->GetTexture(); -+ fb = MozFramebuffer::CreateForBacking(desc.gl, desc.size, 0, false, -+ LOCAL_GL_TEXTURE_2D, tex); -+ if (!fb) return nullptr; -+ } else { -+ // Use MESA_image_dma_buf_export so create EGLImage/framebuffer directly -+ // and derive dmabuf from it. -+ fb = MozFramebuffer::Create(desc.gl, desc.size, 0, false); -+ if (!fb) return nullptr; -+ -+ const auto buffer = reinterpret_cast(fb->ColorTex()); -+ const auto image = -+ egl.fCreateImage(context, LOCAL_EGL_GL_TEXTURE_2D, buffer, nullptr); -+ if (!image) return nullptr; -+ -+ surface = DMABufSurfaceRGBA::CreateDMABufSurface( -+ desc.gl, image, desc.size.width, desc.size.height); -+ if (!surface) return nullptr; - } -- -- const auto tex = surface->GetTexture(); -- auto fb = MozFramebuffer::CreateForBacking(desc.gl, desc.size, 0, false, -- LOCAL_GL_TEXTURE_2D, tex); -- if (!fb) return nullptr; -- - return AsUnique(new SharedSurface_DMABUF(desc, std::move(fb), surface)); - } - -@@ -61,7 +94,7 @@ UniquePtr Surface - } - - auto dmabufFactory = MakeUnique(gl); -- if (dmabufFactory->CanCreateSurface()) { -+ if (dmabufFactory->CanCreateSurface(gl)) { - return dmabufFactory; - } - -@@ -71,8 +104,38 @@ UniquePtr Surface - return nullptr; - } - -+bool SurfaceFactory_DMABUF::CanCreateSurface(GLContext& gl) { -+ UniquePtr test = -+ CreateShared(gfx::IntSize(1, 1), gfx::ColorSpace2::SRGB); -+ if (!test) { -+ LOGDMABUF(( -+ "SurfaceFactory_DMABUF::CanCreateSurface() failed to create surface.")); -+ return false; -+ } -+ auto desc = test->ToSurfaceDescriptor(); -+ if (!desc) { -+ LOGDMABUF( -+ ("SurfaceFactory_DMABUF::CanCreateSurface() failed to serialize " -+ "surface.")); -+ return false; -+ } -+ RefPtr importedSurface = -+ DMABufSurface::CreateDMABufSurface(*desc); -+ if (!importedSurface) { -+ LOGDMABUF(( -+ "SurfaceFactory_DMABUF::CanCreateSurface() failed to import surface.")); -+ return false; -+ } -+ if (!importedSurface->CreateTexture(&gl)) { -+ LOGDMABUF( -+ ("SurfaceFactory_DMABUF::CanCreateSurface() failed to create texture " -+ "over surface.")); -+ return false; -+ } -+ return true; -+} -+ - SurfaceFactory_DMABUF::SurfaceFactory_DMABUF(GLContext& gl) - : SurfaceFactory({&gl, SharedSurfaceType::EGLSurfaceDMABUF, - layers::TextureType::DMABUF, true}) {} -- - } // namespace mozilla::gl -diff -up firefox-102.0/gfx/gl/SharedSurfaceDMABUF.h.D147637.diff firefox-102.0/gfx/gl/SharedSurfaceDMABUF.h ---- firefox-102.0/gfx/gl/SharedSurfaceDMABUF.h.D147637.diff 2022-06-23 09:08:47.000000000 +0200 -+++ firefox-102.0/gfx/gl/SharedSurfaceDMABUF.h 2022-06-28 15:00:20.339991965 +0200 -@@ -59,11 +59,7 @@ class SurfaceFactory_DMABUF : public Sur - return SharedSurface_DMABUF::Create(desc); - } - -- bool CanCreateSurface() { -- UniquePtr test = -- CreateShared(gfx::IntSize(1, 1), gfx::ColorSpace2::SRGB); -- return test != nullptr; -- } -+ bool CanCreateSurface(GLContext& gl); - }; - - } // namespace gl diff --git a/D147874.diff b/D147874.diff deleted file mode 100644 index f0c57dd..0000000 --- a/D147874.diff +++ /dev/null @@ -1,64 +0,0 @@ -diff -up firefox-101.0/gfx/thebes/gfxPlatformGtk.cpp.D147874.diff firefox-101.0/gfx/thebes/gfxPlatformGtk.cpp ---- firefox-101.0/gfx/thebes/gfxPlatformGtk.cpp.D147874.diff 2022-05-27 01:16:54.000000000 +0200 -+++ firefox-101.0/gfx/thebes/gfxPlatformGtk.cpp 2022-06-07 11:16:03.791419558 +0200 -@@ -233,13 +233,7 @@ void gfxPlatformGtk::InitDmabufConfig() - void gfxPlatformGtk::InitVAAPIConfig() { - FeatureState& feature = gfxConfig::GetFeature(Feature::VAAPI); - #ifdef MOZ_WAYLAND -- feature.DisableByDefault(FeatureStatus::Disabled, -- "VAAPI is disabled by default", -- "FEATURE_VAAPI_DISABLED"_ns); -- -- if (StaticPrefs::media_ffmpeg_vaapi_enabled()) { -- feature.UserForceEnable("Force enabled by pref"); -- } -+ feature.EnableByDefault(); - - nsCString failureId; - int32_t status; -@@ -253,6 +247,10 @@ void gfxPlatformGtk::InitVAAPIConfig() { - failureId); - } - -+ if (StaticPrefs::media_ffmpeg_vaapi_enabled()) { -+ feature.UserForceEnable("Force enabled by pref"); -+ } -+ - if (!gfxVars::UseEGL()) { - feature.ForceDisable(FeatureStatus::Unavailable, "Requires EGL", - "FEATURE_FAILURE_REQUIRES_EGL"_ns); -diff -up firefox-101.0/widget/gtk/GfxInfo.cpp.D147874.diff firefox-101.0/widget/gtk/GfxInfo.cpp ---- firefox-101.0/widget/gtk/GfxInfo.cpp.D147874.diff 2022-05-27 01:17:06.000000000 +0200 -+++ firefox-101.0/widget/gtk/GfxInfo.cpp 2022-06-07 09:52:54.416701418 +0200 -@@ -843,6 +843,31 @@ const nsTArray& GfxInfo:: - V(495, 44, 0, 0), "FEATURE_FAILURE_NO_GBM", "495.44.0"); - - //////////////////////////////////// -+ // FEATURE_VAAPI -+ APPEND_TO_DRIVER_BLOCKLIST_EXT( -+ OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All, -+ DesktopEnvironment::All, WindowProtocol::All, DriverVendor::MesaAll, -+ DeviceFamily::All, nsIGfxInfo::FEATURE_VAAPI, -+ nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, DRIVER_LESS_THAN, -+ V(21, 0, 0, 0), "FEATURE_ROLLOUT_VAAPI_MESA", "Mesa 21.0.0.0"); -+ -+ // Disable on all NVIDIA hardware -+ APPEND_TO_DRIVER_BLOCKLIST_EXT( -+ OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All, -+ DesktopEnvironment::All, WindowProtocol::All, DriverVendor::All, -+ DeviceFamily::NvidiaAll, nsIGfxInfo::FEATURE_VAAPI, -+ nsIGfxInfo::FEATURE_BLOCKED_DEVICE, DRIVER_COMPARISON_IGNORED, -+ V(0, 0, 0, 0), "FEATURE_FAILURE_VAAPI_NO_LINUX_NVIDIA", ""); -+ -+ // Disable on all AMD devices not using Mesa. -+ APPEND_TO_DRIVER_BLOCKLIST_EXT( -+ OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All, -+ DesktopEnvironment::All, WindowProtocol::All, DriverVendor::NonMesaAll, -+ DeviceFamily::AtiAll, nsIGfxInfo::FEATURE_VAAPI, -+ nsIGfxInfo::FEATURE_BLOCKED_DEVICE, DRIVER_COMPARISON_IGNORED, -+ V(0, 0, 0, 0), "FEATURE_FAILURE_VAAPI_NO_LINUX_AMD", ""); -+ -+ //////////////////////////////////// - // FEATURE_WEBRENDER_PARTIAL_PRESENT - APPEND_TO_DRIVER_BLOCKLIST_EXT( - OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All, diff --git a/D148946.diff b/D148946.diff deleted file mode 100644 index 0ab7380..0000000 --- a/D148946.diff +++ /dev/null @@ -1,250 +0,0 @@ -diff -up firefox-102.0/gfx/gl/GLContextProviderEGL.cpp.D148946.diff firefox-102.0/gfx/gl/GLContextProviderEGL.cpp ---- firefox-102.0/gfx/gl/GLContextProviderEGL.cpp.D148946.diff 2022-06-23 09:08:47.000000000 +0200 -+++ firefox-102.0/gfx/gl/GLContextProviderEGL.cpp 2022-06-28 14:47:40.904700050 +0200 -@@ -1182,42 +1182,16 @@ RefPtr GLContextEGL::Creat - } - - /*static*/ --RefPtr GLContextEGL::CreateEGLSurfacelessContext( -- const std::shared_ptr display, const GLContextCreateDesc& desc, -- nsACString* const out_failureId) { -- const EGLConfig config = {}; -- auto fullDesc = GLContextDesc{desc}; -- fullDesc.isOffscreen = true; -- RefPtr gl = GLContextEGL::CreateGLContext( -- display, fullDesc, config, EGL_NO_SURFACE, false, out_failureId); -- if (!gl) { -- NS_WARNING("Failed to create surfaceless GL context"); -- return nullptr; -- } -- return gl; --} -- --/*static*/ - already_AddRefed GLContextProviderEGL::CreateHeadless( - const GLContextCreateDesc& desc, nsACString* const out_failureId) { - const auto display = DefaultEglDisplay(out_failureId); - if (!display) { - return nullptr; - } -- RefPtr gl; --#ifdef MOZ_WAYLAND -- if (!gdk_display_get_default() && -- display->IsExtensionSupported(EGLExtension::MESA_platform_surfaceless)) { -- gl = -- GLContextEGL::CreateEGLSurfacelessContext(display, desc, out_failureId); -- } else --#endif -- { -- mozilla::gfx::IntSize dummySize = mozilla::gfx::IntSize(16, 16); -- gl = GLContextEGL::CreateEGLPBufferOffscreenContext( -- display, desc, dummySize, out_failureId); -- } -- return gl.forget(); -+ mozilla::gfx::IntSize dummySize = mozilla::gfx::IntSize(16, 16); -+ auto ret = GLContextEGL::CreateEGLPBufferOffscreenContext( -+ display, desc, dummySize, out_failureId); -+ return ret.forget(); - } - - // Don't want a global context on Android as 1) share groups across 2 threads -diff -up firefox-102.0/gfx/gl/GLDefs.h.D148946.diff firefox-102.0/gfx/gl/GLDefs.h ---- firefox-102.0/gfx/gl/GLDefs.h.D148946.diff 2022-06-23 09:08:47.000000000 +0200 -+++ firefox-102.0/gfx/gl/GLDefs.h 2022-06-28 14:47:40.904700050 +0200 -@@ -104,9 +104,6 @@ bool CheckContextLost(const GLContext* g - // EGL_ANGLE_image_d3d11_texture - #define LOCAL_EGL_D3D11_TEXTURE_ANGLE 0x3484 - --// EGL_MESA_platform_surfaceless --#define LOCAL_EGL_PLATFORM_SURFACELESS_MESA 0x31DD -- - // clang-format on - - #endif -diff -up firefox-102.0/gfx/gl/GLLibraryEGL.cpp.D148946.diff firefox-102.0/gfx/gl/GLLibraryEGL.cpp ---- firefox-102.0/gfx/gl/GLLibraryEGL.cpp.D148946.diff 2022-06-28 14:47:40.900699918 +0200 -+++ firefox-102.0/gfx/gl/GLLibraryEGL.cpp 2022-06-28 14:49:47.810911199 +0200 -@@ -54,9 +54,15 @@ StaticRefPtr GLLibraryEGL: - - // should match the order of EGLExtensions, and be null-terminated. - static const char* sEGLLibraryExtensionNames[] = { -- "EGL_ANDROID_get_native_client_buffer", "EGL_ANGLE_device_creation", -- "EGL_ANGLE_device_creation_d3d11", "EGL_ANGLE_platform_angle", -- "EGL_ANGLE_platform_angle_d3d", "EGL_EXT_device_query"}; -+ "EGL_ANDROID_get_native_client_buffer", -+ "EGL_ANGLE_device_creation", -+ "EGL_ANGLE_device_creation_d3d11", -+ "EGL_ANGLE_platform_angle", -+ "EGL_ANGLE_platform_angle_d3d", -+ "EGL_EXT_device_enumeration", -+ "EGL_EXT_device_query", -+ "EGL_EXT_platform_device", -+ "EGL_MESA_platform_surfaceless"}; - - // should match the order of EGLExtensions, and be null-terminated. - static const char* sEGLExtensionNames[] = { -@@ -84,7 +90,6 @@ static const char* sEGLExtensionNames[] - "EGL_EXT_buffer_age", - "EGL_KHR_partial_update", - "EGL_NV_robustness_video_memory_purge", -- "EGL_MESA_platform_surfaceless", - "EGL_EXT_image_dma_buf_import", - "EGL_EXT_image_dma_buf_import_modifiers", - "EGL_MESA_image_dma_buf_export"}; -@@ -157,8 +162,52 @@ static std::shared_ptr GetAn - } - - #ifdef MOZ_WAYLAND -+static std::shared_ptr GetAndInitDeviceDisplay( -+ GLLibraryEGL& egl, const StaticMutexAutoLock& aProofOfLock) { -+ nsAutoCString drmRenderDevice(gfx::gfxVars::DrmRenderDevice()); -+ if (drmRenderDevice.IsEmpty() || -+ !egl.IsExtensionSupported(EGLLibExtension::EXT_platform_device) || -+ !egl.IsExtensionSupported(EGLLibExtension::EXT_device_enumeration)) { -+ return nullptr; -+ } -+ -+ EGLint maxDevices; -+ if (!egl.fQueryDevicesEXT(0, nullptr, &maxDevices)) { -+ return nullptr; -+ } -+ -+ std::vector devices(maxDevices); -+ EGLint numDevices; -+ if (!egl.fQueryDevicesEXT(devices.size(), devices.data(), &numDevices)) { -+ return nullptr; -+ } -+ devices.resize(numDevices); -+ -+ EGLDisplay display = EGL_NO_DISPLAY; -+ for (const auto& device : devices) { -+ const char* renderNodeString = -+ egl.fQueryDeviceStringEXT(device, LOCAL_EGL_DRM_RENDER_NODE_FILE_EXT); -+ if (renderNodeString && -+ strcmp(renderNodeString, drmRenderDevice.get()) == 0) { -+ const EGLAttrib attrib_list[] = {LOCAL_EGL_NONE}; -+ display = egl.fGetPlatformDisplay(LOCAL_EGL_PLATFORM_DEVICE_EXT, device, -+ attrib_list); -+ break; -+ } -+ } -+ if (!display) { -+ return nullptr; -+ } -+ -+ return EglDisplay::Create(egl, display, true, aProofOfLock); -+} -+ - static std::shared_ptr GetAndInitSurfacelessDisplay( - GLLibraryEGL& egl, const StaticMutexAutoLock& aProofOfLock) { -+ if (!egl.IsExtensionSupported(EGLLibExtension::MESA_platform_surfaceless)) { -+ return nullptr; -+ } -+ - const EGLAttrib attrib_list[] = {LOCAL_EGL_NONE}; - const EGLDisplay display = egl.fGetPlatformDisplay( - LOCAL_EGL_PLATFORM_SURFACELESS_MESA, EGL_DEFAULT_DISPLAY, attrib_list); -@@ -611,9 +660,9 @@ bool GLLibraryEGL::Init(nsACString* cons - (void)fnLoadSymbols(symbols); - } - { -- const SymLoadStruct symbols[] = {SYMBOL(QueryDisplayAttribEXT), -- SYMBOL(QueryDeviceAttribEXT), -- END_OF_SYMBOLS}; -+ const SymLoadStruct symbols[] = { -+ SYMBOL(QueryDisplayAttribEXT), SYMBOL(QueryDeviceAttribEXT), -+ SYMBOL(QueryDeviceStringEXT), END_OF_SYMBOLS}; - (void)fnLoadSymbols(symbols); - } - { -@@ -658,6 +707,10 @@ bool GLLibraryEGL::Init(nsACString* cons - END_OF_SYMBOLS}; - (void)fnLoadSymbols(symbols); - } -+ { -+ const SymLoadStruct symbols[] = {SYMBOL(QueryDevicesEXT), END_OF_SYMBOLS}; -+ (void)fnLoadSymbols(symbols); -+ } - - return true; - } -@@ -835,7 +888,10 @@ std::shared_ptr GLLibraryEGL - #ifdef MOZ_WAYLAND - GdkDisplay* gdkDisplay = gdk_display_get_default(); - if (!gdkDisplay) { -- ret = GetAndInitSurfacelessDisplay(*this, aProofOfLock); -+ ret = GetAndInitDeviceDisplay(*this, aProofOfLock); -+ if (!ret) { -+ ret = GetAndInitSurfacelessDisplay(*this, aProofOfLock); -+ } - } else if (widget::GdkIsWaylandDisplay(gdkDisplay)) { - // Wayland does not support EGL_DEFAULT_DISPLAY - nativeDisplay = widget::WaylandDisplayGetWLDisplay(gdkDisplay); -diff -up firefox-102.0/gfx/gl/GLLibraryEGL.h.D148946.diff firefox-102.0/gfx/gl/GLLibraryEGL.h ---- firefox-102.0/gfx/gl/GLLibraryEGL.h.D148946.diff 2022-06-28 14:47:40.899699885 +0200 -+++ firefox-102.0/gfx/gl/GLLibraryEGL.h 2022-06-28 14:47:40.904700050 +0200 -@@ -71,7 +71,10 @@ enum class EGLLibExtension { - ANGLE_device_creation_d3d11, - ANGLE_platform_angle, - ANGLE_platform_angle_d3d, -+ EXT_device_enumeration, - EXT_device_query, -+ EXT_platform_device, -+ MESA_platform_surfaceless, - Max - }; - -@@ -107,7 +110,6 @@ enum class EGLExtension { - EXT_buffer_age, - KHR_partial_update, - NV_robustness_video_memory_purge, -- MESA_platform_surfaceless, - EXT_image_dma_buf_import, - EXT_image_dma_buf_import_modifiers, - MESA_image_dma_buf_export, -@@ -436,6 +438,10 @@ class GLLibraryEGL final { - WRAP(fQueryDeviceAttribEXT(device, attribute, value)); - } - -+ const char* fQueryDeviceStringEXT(EGLDeviceEXT device, EGLint name) { -+ WRAP(fQueryDeviceStringEXT(device, name)); -+ } -+ - private: - // NV_stream_consumer_gltexture_yuv - EGLBoolean fStreamConsumerGLTextureExternalAttribsNV( -@@ -478,6 +484,13 @@ class GLLibraryEGL final { - WRAP(fExportDMABUFImageMESA(dpy, image, fds, strides, offsets)); - } - -+ public: -+ // EGL_EXT_device_enumeration -+ EGLBoolean fQueryDevicesEXT(EGLint max_devices, EGLDeviceEXT* devices, -+ EGLint* num_devices) { -+ WRAP(fQueryDevicesEXT(max_devices, devices, num_devices)); -+ } -+ - #undef WRAP - - #undef WRAP -@@ -586,6 +599,9 @@ class GLLibraryEGL final { - EGLBoolean(GLAPIENTRY* fQueryDeviceAttribEXT)(EGLDeviceEXT device, - EGLint attribute, - EGLAttrib* value); -+ const char*(GLAPIENTRY* fQueryDeviceStringEXT)(EGLDeviceEXT device, -+ EGLint name); -+ - // NV_stream_consumer_gltexture_yuv - EGLBoolean(GLAPIENTRY* fStreamConsumerGLTextureExternalAttribsNV)( - EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib* attrib_list); -@@ -623,6 +639,10 @@ class GLLibraryEGL final { - EGLint* strides, - EGLint* offsets); - -+ EGLBoolean(GLAPIENTRY* fQueryDevicesEXT)(EGLint max_devices, -+ EGLDeviceEXT* devices, -+ EGLint* num_devices); -+ - } mSymbols = {}; - }; - diff --git a/D149135.diff b/D149135.diff deleted file mode 100644 index 6e93f2b..0000000 --- a/D149135.diff +++ /dev/null @@ -1,80 +0,0 @@ -diff --git a/widget/gtk/DMABufSurface.cpp b/widget/gtk/DMABufSurface.cpp ---- a/widget/gtk/DMABufSurface.cpp -+++ b/widget/gtk/DMABufSurface.cpp -@@ -642,11 +642,11 @@ - - void DMABufSurfaceRGBA::ReleaseTextures() { - LOGDMABUF(("DMABufSurfaceRGBA::ReleaseTextures() UID %d\n", mUID)); - FenceDelete(); - -- if (!mTexture) { -+ if (!mTexture && mEGLImage == LOCAL_EGL_NO_IMAGE) { - return; - } - - if (!mGL) { - #ifdef NIGHTLY -@@ -663,17 +663,17 @@ - const auto& egl = gle->mEgl; - - if (mTexture && mGL->MakeCurrent()) { - mGL->fDeleteTextures(1, &mTexture); - mTexture = 0; -- mGL = nullptr; - } - - if (mEGLImage != LOCAL_EGL_NO_IMAGE) { - egl->fDestroyImage(mEGLImage); - mEGLImage = LOCAL_EGL_NO_IMAGE; - } -+ mGL = nullptr; - } - - void DMABufSurfaceRGBA::ReleaseSurface() { - MOZ_ASSERT(!IsMapped(), "We can't release mapped buffer!"); - -@@ -1325,11 +1325,11 @@ - - FenceDelete(); - - bool textureActive = false; - for (int i = 0; i < mBufferPlaneCount; i++) { -- if (mTexture[i]) { -+ if (mTexture[i] || mEGLImage[i] != LOCAL_EGL_NO_IMAGE) { - textureActive = true; - break; - } - } - -@@ -1346,18 +1346,23 @@ - "leaking textures!"); - return; - #endif - } - -- if (textureActive && mGL->MakeCurrent()) { -- mGL->fDeleteTextures(DMABUF_BUFFER_PLANES, mTexture); -- for (int i = 0; i < DMABUF_BUFFER_PLANES; i++) { -- mTexture[i] = 0; -- } -- ReleaseEGLImages(mGL); -- mGL = nullptr; -+ if (!mGL->MakeCurrent()) { -+ NS_WARNING( -+ "DMABufSurfaceYUV::ReleaseTextures(): Failed to create GL context " -+ "current. We're leaking textures!"); -+ return; - } -+ -+ mGL->fDeleteTextures(DMABUF_BUFFER_PLANES, mTexture); -+ for (int i = 0; i < DMABUF_BUFFER_PLANES; i++) { -+ mTexture[i] = 0; -+ } -+ ReleaseEGLImages(mGL); -+ mGL = nullptr; - } - - bool DMABufSurfaceYUV::VerifyTextureCreation() { - LOGDMABUF(("DMABufSurfaceYUV::VerifyTextureCreation() UID %d", mUID)); - - diff --git a/D149238.diff b/D149238.diff deleted file mode 100644 index e89c1bf..0000000 --- a/D149238.diff +++ /dev/null @@ -1,34 +0,0 @@ -diff -up firefox-102.0/gfx/config/gfxVars.h.D149238.diff firefox-102.0/gfx/config/gfxVars.h ---- firefox-102.0/gfx/config/gfxVars.h.D149238.diff 2022-06-23 09:08:47.000000000 +0200 -+++ firefox-102.0/gfx/config/gfxVars.h 2022-06-28 16:40:54.130895063 +0200 -@@ -91,7 +91,8 @@ class gfxVarReceiver; - _(AllowWebGPU, bool, false) \ - _(UseVP8HwDecode, bool, false) \ - _(UseVP9HwDecode, bool, false) \ -- _(HwDecodedVideoZeroCopy, bool, false) -+ _(HwDecodedVideoZeroCopy, bool, false) \ -+ _(UseDMABufSurfaceExport, bool, true) - - /* Add new entries above this line. */ - -diff -up firefox-102.0/gfx/thebes/gfxPlatform.cpp.D149238.diff firefox-102.0/gfx/thebes/gfxPlatform.cpp ---- firefox-102.0/gfx/thebes/gfxPlatform.cpp.D149238.diff 2022-06-23 09:08:47.000000000 +0200 -+++ firefox-102.0/gfx/thebes/gfxPlatform.cpp 2022-06-28 16:40:54.130895063 +0200 -@@ -2861,6 +2861,17 @@ void gfxPlatform::InitWebGLConfig() { - gfxVars::SetAllowEglRbab(false); - } - } -+ -+ if (kIsWayland || kIsX11) { -+ // Disable EGL_MESA_image_dma_buf_export on mesa/radeonsi due to -+ // https://gitlab.freedesktop.org/mesa/mesa/-/issues/6666 -+ nsString adapterDriverVendor; -+ gfxInfo->GetAdapterDriverVendor(adapterDriverVendor); -+ if (adapterDriverVendor.Find("mesa") != -1 && -+ adapterDriverVendor.Find("radeonsi") != -1) { -+ gfxVars::SetUseDMABufSurfaceExport(false); -+ } -+ } - } - - void gfxPlatform::InitWebGPUConfig() { diff --git a/build-cubeb-pulse-arm.patch b/build-cubeb-pulse-arm.patch deleted file mode 100644 index 008208c..0000000 --- a/build-cubeb-pulse-arm.patch +++ /dev/null @@ -1,4946 +0,0 @@ -diff -up firefox-55.0/media/libcubeb/cubeb-pulse-rs/Cargo.toml.cubeb-pulse-arm firefox-55.0/media/libcubeb/cubeb-pulse-rs/Cargo.toml ---- firefox-55.0/media/libcubeb/cubeb-pulse-rs/Cargo.toml.cubeb-pulse-arm 2017-07-31 18:20:49.000000000 +0200 -+++ firefox-55.0/media/libcubeb/cubeb-pulse-rs/Cargo.toml 2017-08-04 13:37:46.383821740 +0200 -@@ -7,7 +7,11 @@ description = "Cubeb backed for PulseAud - [features] - pulse-dlopen = ["pulse-ffi/dlopen"] - -+[lib] -+crate-type = ["staticlib", "rlib"] -+ - [dependencies] - cubeb-ffi = { path = "cubeb-ffi" } - pulse-ffi = { path = "pulse-ffi" } -+pulse = { path = "pulse-rs" } - semver = "^0.6" -diff -up firefox-55.0/media/libcubeb/cubeb-pulse-rs/cubeb-ffi/src/ffi.rs.cubeb-pulse-arm firefox-55.0/media/libcubeb/cubeb-pulse-rs/cubeb-ffi/src/ffi.rs ---- firefox-55.0/media/libcubeb/cubeb-pulse-rs/cubeb-ffi/src/ffi.rs.cubeb-pulse-arm 2017-07-31 18:20:49.000000000 +0200 -+++ firefox-55.0/media/libcubeb/cubeb-pulse-rs/cubeb-ffi/src/ffi.rs 2017-08-04 13:37:46.384821737 +0200 -@@ -11,45 +11,45 @@ pub enum Context {} - pub enum Stream {} - - // These need to match cubeb_sample_format --pub const SAMPLE_S16LE: c_int = 0; --pub const SAMPLE_S16BE: c_int = 1; --pub const SAMPLE_FLOAT32LE: c_int = 2; --pub const SAMPLE_FLOAT32BE: c_int = 3; - pub type SampleFormat = c_int; -+pub const SAMPLE_S16LE: SampleFormat = 0; -+pub const SAMPLE_S16BE: SampleFormat = 1; -+pub const SAMPLE_FLOAT32LE: SampleFormat = 2; -+pub const SAMPLE_FLOAT32BE: SampleFormat = 3; - - #[cfg(target_endian = "little")] --pub const SAMPLE_S16NE: c_int = SAMPLE_S16LE; -+pub const SAMPLE_S16NE: SampleFormat = SAMPLE_S16LE; - #[cfg(target_endian = "little")] --pub const SAMPLE_FLOAT32NE: c_int = SAMPLE_FLOAT32LE; -+pub const SAMPLE_FLOAT32NE: SampleFormat = SAMPLE_FLOAT32LE; - #[cfg(target_endian = "big")] --pub const SAMPLE_S16NE: c_int = SAMPLE_S16BE; -+pub const SAMPLE_S16NE: SampleFormat = SAMPLE_S16BE; - #[cfg(target_endian = "big")] --pub const SAMPLE_FLOAT32NE: c_int = SAMPLE_FLOAT32BE; -+pub const SAMPLE_FLOAT32NE: SampleFormat = SAMPLE_FLOAT32BE; - - pub type DeviceId = *const c_void; - - // These need to match cubeb_channel_layout --pub const LAYOUT_UNDEFINED: c_int = 0; --pub const LAYOUT_DUAL_MONO: c_int = 1; --pub const LAYOUT_DUAL_MONO_LFE: c_int = 2; --pub const LAYOUT_MONO: c_int = 3; --pub const LAYOUT_MONO_LFE: c_int = 4; --pub const LAYOUT_STEREO: c_int = 5; --pub const LAYOUT_STEREO_LFE: c_int = 6; --pub const LAYOUT_3F: c_int = 7; --pub const LAYOUT_3F_LFE: c_int = 8; --pub const LAYOUT_2F1: c_int = 9; --pub const LAYOUT_2F1_LFE: c_int = 10; --pub const LAYOUT_3F1: c_int = 11; --pub const LAYOUT_3F1_LFE: c_int = 12; --pub const LAYOUT_2F2: c_int = 13; --pub const LAYOUT_2F2_LFE: c_int = 14; --pub const LAYOUT_3F2: c_int = 15; --pub const LAYOUT_3F2_LFE: c_int = 16; --pub const LAYOUT_3F3R_LFE: c_int = 17; --pub const LAYOUT_3F4_LFE: c_int = 18; --pub const LAYOUT_MAX: c_int = 19; - pub type ChannelLayout = c_int; -+pub const LAYOUT_UNDEFINED: ChannelLayout = 0; -+pub const LAYOUT_DUAL_MONO: ChannelLayout = 1; -+pub const LAYOUT_DUAL_MONO_LFE: ChannelLayout = 2; -+pub const LAYOUT_MONO: ChannelLayout = 3; -+pub const LAYOUT_MONO_LFE: ChannelLayout = 4; -+pub const LAYOUT_STEREO: ChannelLayout = 5; -+pub const LAYOUT_STEREO_LFE: ChannelLayout = 6; -+pub const LAYOUT_3F: ChannelLayout = 7; -+pub const LAYOUT_3F_LFE: ChannelLayout = 8; -+pub const LAYOUT_2F1: ChannelLayout = 9; -+pub const LAYOUT_2F1_LFE: ChannelLayout = 10; -+pub const LAYOUT_3F1: ChannelLayout = 11; -+pub const LAYOUT_3F1_LFE: ChannelLayout = 12; -+pub const LAYOUT_2F2: ChannelLayout = 13; -+pub const LAYOUT_2F2_LFE: ChannelLayout = 14; -+pub const LAYOUT_3F2: ChannelLayout = 15; -+pub const LAYOUT_3F2_LFE: ChannelLayout = 16; -+pub const LAYOUT_3F3R_LFE: ChannelLayout = 17; -+pub const LAYOUT_3F4_LFE: ChannelLayout = 18; -+pub const LAYOUT_MAX: ChannelLayout = 256; - - #[repr(C)] - #[derive(Clone, Copy, Debug)] -@@ -77,11 +77,11 @@ impl Default for Device { - } - - // These need to match cubeb_state --pub const STATE_STARTED: c_int = 0; --pub const STATE_STOPPED: c_int = 1; --pub const STATE_DRAINED: c_int = 2; --pub const STATE_ERROR: c_int = 3; - pub type State = c_int; -+pub const STATE_STARTED: State = 0; -+pub const STATE_STOPPED: State = 1; -+pub const STATE_DRAINED: State = 2; -+pub const STATE_ERROR: State = 3; - - pub const OK: i32 = 0; - pub const ERROR: i32 = -1; -@@ -249,32 +249,42 @@ pub struct LayoutMap { - } - - // cubeb_mixer.h -+pub type Channel = c_int; - - // These need to match cubeb_channel --pub const CHANNEL_INVALID: c_int = -1; --pub const CHANNEL_MONO: c_int = 0; --pub const CHANNEL_LEFT: c_int = 1; --pub const CHANNEL_RIGHT: c_int = 2; --pub const CHANNEL_CENTER: c_int = 3; --pub const CHANNEL_LS: c_int = 4; --pub const CHANNEL_RS: c_int = 5; --pub const CHANNEL_RLS: c_int = 6; --pub const CHANNEL_RCENTER: c_int = 7; --pub const CHANNEL_RRS: c_int = 8; --pub const CHANNEL_LFE: c_int = 9; --pub const CHANNEL_MAX: c_int = 256; --pub type Channel = c_int; -+pub const CHANNEL_INVALID: Channel = -1; -+pub const CHANNEL_MONO: Channel = 0; -+pub const CHANNEL_LEFT: Channel = 1; -+pub const CHANNEL_RIGHT: Channel = 2; -+pub const CHANNEL_CENTER: Channel = 3; -+pub const CHANNEL_LS: Channel = 4; -+pub const CHANNEL_RS: Channel = 5; -+pub const CHANNEL_RLS: Channel = 6; -+pub const CHANNEL_RCENTER: Channel = 7; -+pub const CHANNEL_RRS: Channel = 8; -+pub const CHANNEL_LFE: Channel = 9; -+pub const CHANNEL_MAX: Channel = 10; - - #[repr(C)] -+#[derive(Clone, Copy, Debug)] - pub struct ChannelMap { - pub channels: c_uint, -- pub map: [Channel; 256], -+ pub map: [Channel; CHANNEL_MAX as usize], - } - impl ::std::default::Default for ChannelMap { - fn default() -> Self { - ChannelMap { - channels: 0, -- map: unsafe { ::std::mem::zeroed() }, -+ map: [CHANNEL_INVALID, -+ CHANNEL_INVALID, -+ CHANNEL_INVALID, -+ CHANNEL_INVALID, -+ CHANNEL_INVALID, -+ CHANNEL_INVALID, -+ CHANNEL_INVALID, -+ CHANNEL_INVALID, -+ CHANNEL_INVALID, -+ CHANNEL_INVALID], - } - } - } -diff -up firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-ffi/src/ffi_funcs.rs.cubeb-pulse-arm firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-ffi/src/ffi_funcs.rs ---- firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-ffi/src/ffi_funcs.rs.cubeb-pulse-arm 2017-07-31 18:20:49.000000000 +0200 -+++ firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-ffi/src/ffi_funcs.rs 2017-08-04 13:37:46.384821737 +0200 -@@ -8,8 +8,8 @@ macro_rules! cstr { - - #[cfg(not(feature = "dlopen"))] - mod static_fns { -- use std::os::raw::{c_char, c_double, c_int, c_float, c_uint, c_void}; - use super::*; -+ use std::os::raw::{c_char, c_double, c_float, c_int, c_uint, c_void}; - - #[link(name = "pulse")] - extern "C" { -@@ -62,6 +62,7 @@ mod static_fns { - userdata: *mut c_void) - -> *mut pa_operation; - pub fn pa_context_set_state_callback(c: *mut pa_context, cb: pa_context_notify_cb_t, userdata: *mut c_void); -+ pub fn pa_context_errno(c: *mut pa_context) -> c_int; - pub fn pa_context_set_subscribe_callback(c: *mut pa_context, - cb: pa_context_subscribe_cb_t, - userdata: *mut c_void); -@@ -70,6 +71,7 @@ mod static_fns { - cb: pa_context_success_cb_t, - userdata: *mut c_void) - -> *mut pa_operation; -+ pub fn pa_context_ref(c: *mut pa_context) -> *mut pa_context; - pub fn pa_context_unref(c: *mut pa_context); - pub fn pa_cvolume_set(a: *mut pa_cvolume, channels: c_uint, v: pa_volume_t) -> *mut pa_cvolume; - pub fn pa_cvolume_set_balance(v: *mut pa_cvolume, -@@ -80,12 +82,20 @@ mod static_fns { - pub fn pa_mainloop_api_once(m: *mut pa_mainloop_api, - callback: pa_mainloop_api_once_cb_t, - userdata: *mut c_void); -- pub fn pa_operation_get_state(o: *const pa_operation) -> pa_operation_state_t; -+ pub fn pa_strerror(error: pa_error_code_t) -> *const c_char; -+ pub fn pa_operation_ref(o: *mut pa_operation) -> *mut pa_operation; - pub fn pa_operation_unref(o: *mut pa_operation); -+ pub fn pa_operation_cancel(o: *mut pa_operation); -+ pub fn pa_operation_get_state(o: *const pa_operation) -> pa_operation_state_t; -+ pub fn pa_operation_set_state_callback(o: *mut pa_operation, -+ cb: pa_operation_notify_cb_t, -+ userdata: *mut c_void); - pub fn pa_proplist_gets(p: *mut pa_proplist, key: *const c_char) -> *const c_char; - pub fn pa_rtclock_now() -> pa_usec_t; - pub fn pa_stream_begin_write(p: *mut pa_stream, data: *mut *mut c_void, nbytes: *mut usize) -> c_int; - pub fn pa_stream_cancel_write(p: *mut pa_stream) -> c_int; -+ pub fn pa_stream_is_suspended(s: *const pa_stream) -> c_int; -+ pub fn pa_stream_is_corked(s: *const pa_stream) -> c_int; - pub fn pa_stream_connect_playback(s: *mut pa_stream, - dev: *const c_char, - attr: *const pa_buffer_attr, -@@ -112,6 +122,7 @@ mod static_fns { - pub fn pa_stream_get_latency(s: *const pa_stream, r_usec: *mut pa_usec_t, negative: *mut c_int) -> c_int; - pub fn pa_stream_get_sample_spec(s: *const pa_stream) -> *const pa_sample_spec; - pub fn pa_stream_get_state(p: *const pa_stream) -> pa_stream_state_t; -+ pub fn pa_stream_get_context(s: *const pa_stream) -> *mut pa_context; - pub fn pa_stream_get_time(s: *const pa_stream, r_usec: *mut pa_usec_t) -> c_int; - pub fn pa_stream_new(c: *mut pa_context, - name: *const c_char, -@@ -123,6 +134,7 @@ mod static_fns { - pub fn pa_stream_set_state_callback(s: *mut pa_stream, cb: pa_stream_notify_cb_t, userdata: *mut c_void); - pub fn pa_stream_set_write_callback(p: *mut pa_stream, cb: pa_stream_request_cb_t, userdata: *mut c_void); - pub fn pa_stream_set_read_callback(p: *mut pa_stream, cb: pa_stream_request_cb_t, userdata: *mut c_void); -+ pub fn pa_stream_ref(s: *mut pa_stream) -> *mut pa_stream; - pub fn pa_stream_unref(s: *mut pa_stream); - pub fn pa_stream_update_timing_info(p: *mut pa_stream, - cb: pa_stream_success_cb_t, -@@ -148,8 +160,6 @@ mod static_fns { - pub fn pa_threaded_mainloop_unlock(m: *mut pa_threaded_mainloop); - pub fn pa_threaded_mainloop_wait(m: *mut pa_threaded_mainloop); - pub fn pa_usec_to_bytes(t: pa_usec_t, spec: *const pa_sample_spec) -> usize; -- pub fn pa_xfree(ptr: *mut c_void); -- pub fn pa_xstrdup(str: *const c_char) -> *mut c_char; - pub fn pa_xrealloc(ptr: *mut c_void, size: usize) -> *mut c_void; - } - } -@@ -159,9 +169,9 @@ pub use self::static_fns::*; - - #[cfg(feature = "dlopen")] - mod dynamic_fns { -- use std::os::raw::{c_char, c_double, c_int, c_float, c_uint, c_void}; -- use libc::{dlclose, dlopen, dlsym, RTLD_LAZY}; - use super::*; -+ use libc::{RTLD_LAZY, dlclose, dlopen, dlsym}; -+ use std::os::raw::{c_char, c_double, c_float, c_int, c_uint, c_void}; - - #[derive(Debug)] - pub struct LibLoader { -@@ -287,6 +297,13 @@ mod dynamic_fns { - } - fp - }; -+ PA_CONTEXT_ERRNO = { -+ let fp = dlsym(h, cstr!("pa_context_errno")); -+ if fp.is_null() { -+ return None; -+ } -+ fp -+ }; - PA_CONTEXT_SET_SUBSCRIBE_CALLBACK = { - let fp = dlsym(h, cstr!("pa_context_set_subscribe_callback")); - if fp.is_null() { -@@ -301,6 +318,13 @@ mod dynamic_fns { - } - fp - }; -+ PA_CONTEXT_REF = { -+ let fp = dlsym(h, cstr!("pa_context_ref")); -+ if fp.is_null() { -+ return None; -+ } -+ fp -+ }; - PA_CONTEXT_UNREF = { - let fp = dlsym(h, cstr!("pa_context_unref")); - if fp.is_null() { -@@ -336,8 +360,15 @@ mod dynamic_fns { - } - fp - }; -- PA_OPERATION_GET_STATE = { -- let fp = dlsym(h, cstr!("pa_operation_get_state")); -+ PA_STRERROR = { -+ let fp = dlsym(h, cstr!("pa_strerror")); -+ if fp.is_null() { -+ return None; -+ } -+ fp -+ }; -+ PA_OPERATION_REF = { -+ let fp = dlsym(h, cstr!("pa_operation_ref")); - if fp.is_null() { - return None; - } -@@ -350,6 +381,27 @@ mod dynamic_fns { - } - fp - }; -+ PA_OPERATION_CANCEL = { -+ let fp = dlsym(h, cstr!("pa_operation_cancel")); -+ if fp.is_null() { -+ return None; -+ } -+ fp -+ }; -+ PA_OPERATION_GET_STATE = { -+ let fp = dlsym(h, cstr!("pa_operation_get_state")); -+ if fp.is_null() { -+ return None; -+ } -+ fp -+ }; -+ PA_OPERATION_SET_STATE_CALLBACK = { -+ let fp = dlsym(h, cstr!("pa_operation_set_state_callback")); -+ if fp.is_null() { -+ return None; -+ } -+ fp -+ }; - PA_PROPLIST_GETS = { - let fp = dlsym(h, cstr!("pa_proplist_gets")); - if fp.is_null() { -@@ -378,6 +430,20 @@ mod dynamic_fns { - } - fp - }; -+ PA_STREAM_IS_SUSPENDED = { -+ let fp = dlsym(h, cstr!("pa_stream_is_suspended")); -+ if fp.is_null() { -+ return None; -+ } -+ fp -+ }; -+ PA_STREAM_IS_CORKED = { -+ let fp = dlsym(h, cstr!("pa_stream_is_corked")); -+ if fp.is_null() { -+ return None; -+ } -+ fp -+ }; - PA_STREAM_CONNECT_PLAYBACK = { - let fp = dlsym(h, cstr!("pa_stream_connect_playback")); - if fp.is_null() { -@@ -462,6 +528,13 @@ mod dynamic_fns { - } - fp - }; -+ PA_STREAM_GET_CONTEXT = { -+ let fp = dlsym(h, cstr!("pa_stream_get_context")); -+ if fp.is_null() { -+ return None; -+ } -+ fp -+ }; - PA_STREAM_GET_TIME = { - let fp = dlsym(h, cstr!("pa_stream_get_time")); - if fp.is_null() { -@@ -511,6 +584,13 @@ mod dynamic_fns { - } - fp - }; -+ PA_STREAM_REF = { -+ let fp = dlsym(h, cstr!("pa_stream_ref")); -+ if fp.is_null() { -+ return None; -+ } -+ fp -+ }; - PA_STREAM_UNREF = { - let fp = dlsym(h, cstr!("pa_stream_unref")); - if fp.is_null() { -@@ -623,20 +703,6 @@ mod dynamic_fns { - } - fp - }; -- PA_XFREE = { -- let fp = dlsym(h, cstr!("pa_xfree")); -- if fp.is_null() { -- return None; -- } -- fp -- }; -- PA_XSTRDUP = { -- let fp = dlsym(h, cstr!("pa_xstrdup")); -- if fp.is_null() { -- return None; -- } -- fp -- }; - PA_XREALLOC = { - let fp = dlsym(h, cstr!("pa_xrealloc")); - if fp.is_null() { -@@ -837,6 +903,12 @@ mod dynamic_fns { - *mut c_void)>(PA_CONTEXT_SET_STATE_CALLBACK))(c, cb, userdata) - } - -+ static mut PA_CONTEXT_ERRNO: *mut ::libc::c_void = 0 as *mut _; -+ #[inline] -+ pub unsafe fn pa_context_errno(c: *mut pa_context) -> c_int { -+ (::std::mem::transmute::<_, extern "C" fn(*mut pa_context) -> c_int>(PA_CONTEXT_ERRNO))(c) -+ } -+ - static mut PA_CONTEXT_SET_SUBSCRIBE_CALLBACK: *mut ::libc::c_void = 0 as *mut _; - #[inline] - pub unsafe fn pa_context_set_subscribe_callback(c: *mut pa_context, -@@ -863,6 +935,12 @@ mod dynamic_fns { - -> *mut pa_operation>(PA_CONTEXT_SUBSCRIBE))(c, m, cb, userdata) - } - -+ static mut PA_CONTEXT_REF: *mut ::libc::c_void = 0 as *mut _; -+ #[inline] -+ pub unsafe fn pa_context_ref(c: *mut pa_context) -> *mut pa_context { -+ (::std::mem::transmute::<_, extern "C" fn(*mut pa_context) -> *mut pa_context>(PA_CONTEXT_REF))(c) -+ } -+ - static mut PA_CONTEXT_UNREF: *mut ::libc::c_void = 0 as *mut _; - #[inline] - pub unsafe fn pa_context_unref(c: *mut pa_context) { -@@ -907,6 +985,30 @@ mod dynamic_fns { - *mut c_void)>(PA_MAINLOOP_API_ONCE))(m, callback, userdata) - } - -+ static mut PA_STRERROR: *mut ::libc::c_void = 0 as *mut _; -+ #[inline] -+ pub unsafe fn pa_strerror(error: pa_error_code_t) -> *const c_char { -+ (::std::mem::transmute::<_, extern "C" fn(pa_error_code_t) -> *const c_char>(PA_STRERROR))(error) -+ } -+ -+ static mut PA_OPERATION_REF: *mut ::libc::c_void = 0 as *mut _; -+ #[inline] -+ pub unsafe fn pa_operation_ref(o: *mut pa_operation) -> *mut pa_operation { -+ (::std::mem::transmute::<_, extern "C" fn(*mut pa_operation) -> *mut pa_operation>(PA_OPERATION_REF))(o) -+ } -+ -+ static mut PA_OPERATION_UNREF: *mut ::libc::c_void = 0 as *mut _; -+ #[inline] -+ pub unsafe fn pa_operation_unref(o: *mut pa_operation) { -+ (::std::mem::transmute::<_, extern "C" fn(*mut pa_operation)>(PA_OPERATION_UNREF))(o) -+ } -+ -+ static mut PA_OPERATION_CANCEL: *mut ::libc::c_void = 0 as *mut _; -+ #[inline] -+ pub unsafe fn pa_operation_cancel(o: *mut pa_operation) { -+ (::std::mem::transmute::<_, extern "C" fn(*mut pa_operation)>(PA_OPERATION_CANCEL))(o) -+ } -+ - static mut PA_OPERATION_GET_STATE: *mut ::libc::c_void = 0 as *mut _; - #[inline] - pub unsafe fn pa_operation_get_state(o: *const pa_operation) -> pa_operation_state_t { -@@ -915,10 +1017,15 @@ mod dynamic_fns { - -> pa_operation_state_t>(PA_OPERATION_GET_STATE))(o) - } - -- static mut PA_OPERATION_UNREF: *mut ::libc::c_void = 0 as *mut _; -+ static mut PA_OPERATION_SET_STATE_CALLBACK: *mut ::libc::c_void = 0 as *mut _; - #[inline] -- pub unsafe fn pa_operation_unref(o: *mut pa_operation) { -- (::std::mem::transmute::<_, extern "C" fn(*mut pa_operation)>(PA_OPERATION_UNREF))(o) -+ pub unsafe fn pa_operation_set_state_callback(o: *mut pa_operation, -+ cb: pa_operation_notify_cb_t, -+ userdata: *mut c_void) { -+ (::std::mem::transmute::<_, -+ extern "C" fn(*mut pa_operation, -+ pa_operation_notify_cb_t, -+ *mut c_void)>(PA_OPERATION_SET_STATE_CALLBACK))(o, cb, userdata) - } - - static mut PA_PROPLIST_GETS: *mut ::libc::c_void = 0 as *mut _; -@@ -951,6 +1058,18 @@ mod dynamic_fns { - (::std::mem::transmute::<_, extern "C" fn(*mut pa_stream) -> c_int>(PA_STREAM_CANCEL_WRITE))(p) - } - -+ static mut PA_STREAM_IS_SUSPENDED: *mut ::libc::c_void = 0 as *mut _; -+ #[inline] -+ pub unsafe fn pa_stream_is_suspended(s: *const pa_stream) -> c_int { -+ (::std::mem::transmute::<_, extern "C" fn(*const pa_stream) -> c_int>(PA_STREAM_IS_SUSPENDED))(s) -+ } -+ -+ static mut PA_STREAM_IS_CORKED: *mut ::libc::c_void = 0 as *mut _; -+ #[inline] -+ pub unsafe fn pa_stream_is_corked(s: *const pa_stream) -> c_int { -+ (::std::mem::transmute::<_, extern "C" fn(*const pa_stream) -> c_int>(PA_STREAM_IS_CORKED))(s) -+ } -+ - static mut PA_STREAM_CONNECT_PLAYBACK: *mut ::libc::c_void = 0 as *mut _; - #[inline] - pub unsafe fn pa_stream_connect_playback(s: *mut pa_stream, -@@ -1066,6 +1185,12 @@ mod dynamic_fns { - (::std::mem::transmute::<_, extern "C" fn(*const pa_stream) -> pa_stream_state_t>(PA_STREAM_GET_STATE))(p) - } - -+ static mut PA_STREAM_GET_CONTEXT: *mut ::libc::c_void = 0 as *mut _; -+ #[inline] -+ pub unsafe fn pa_stream_get_context(s: *const pa_stream) -> *mut pa_context { -+ (::std::mem::transmute::<_, extern "C" fn(*const pa_stream) -> *mut pa_context>(PA_STREAM_GET_CONTEXT))(s) -+ } -+ - static mut PA_STREAM_GET_TIME: *mut ::libc::c_void = 0 as *mut _; - #[inline] - pub unsafe fn pa_stream_get_time(s: *const pa_stream, r_usec: *mut pa_usec_t) -> c_int { -@@ -1132,6 +1257,12 @@ mod dynamic_fns { - *mut c_void)>(PA_STREAM_SET_READ_CALLBACK))(p, cb, userdata) - } - -+ static mut PA_STREAM_REF: *mut ::libc::c_void = 0 as *mut _; -+ #[inline] -+ pub unsafe fn pa_stream_ref(s: *mut pa_stream) -> *mut pa_stream { -+ (::std::mem::transmute::<_, extern "C" fn(*mut pa_stream) -> *mut pa_stream>(PA_STREAM_REF))(s) -+ } -+ - static mut PA_STREAM_UNREF: *mut ::libc::c_void = 0 as *mut _; - #[inline] - pub unsafe fn pa_stream_unref(s: *mut pa_stream) { -@@ -1253,18 +1384,6 @@ mod dynamic_fns { - spec) - } - -- static mut PA_XFREE: *mut ::libc::c_void = 0 as *mut _; -- #[inline] -- pub unsafe fn pa_xfree(ptr: *mut c_void) { -- (::std::mem::transmute::<_, extern "C" fn(*mut c_void)>(PA_XFREE))(ptr) -- } -- -- static mut PA_XSTRDUP: *mut ::libc::c_void = 0 as *mut _; -- #[inline] -- pub unsafe fn pa_xstrdup(str: *const c_char) -> *mut c_char { -- (::std::mem::transmute::<_, extern "C" fn(*const c_char) -> *mut c_char>(PA_XSTRDUP))(str) -- } -- - static mut PA_XREALLOC: *mut ::libc::c_void = 0 as *mut _; - #[inline] - pub unsafe fn pa_xrealloc(ptr: *mut c_void, size: usize) -> *mut c_void { -diff -up firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-ffi/src/ffi_types.rs.cubeb-pulse-arm firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-ffi/src/ffi_types.rs ---- firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-ffi/src/ffi_types.rs.cubeb-pulse-arm 2017-07-31 18:20:49.000000000 +0200 -+++ firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-ffi/src/ffi_types.rs 2017-08-04 13:37:46.384821737 +0200 -@@ -1,6 +1,6 @@ - #![allow(non_camel_case_types)] - --use std::os::raw::{c_char, c_int, c_long, c_ulong, c_void}; -+use std::os::raw::{c_char, c_int, c_long, c_uint, c_ulong, c_void}; - - /* automatically generated by rust-bindgen */ - pub const PA_RATE_MAX: u32 = 48000 * 8; -@@ -74,10 +74,10 @@ pub const PA_OPERATION_DONE: c_int = 1; - pub const PA_OPERATION_CANCELLED: c_int = 2; - pub type pa_operation_state_t = c_int; - --pub const PA_CONTEXT_NOFLAGS: c_int = 0; --pub const PA_CONTEXT_NOAUTOSPAWN: c_int = 1; --pub const PA_CONTEXT_NOFAIL: c_int = 2; --pub type pa_context_flags_t = c_int; -+pub const PA_CONTEXT_NOFLAGS: c_uint = 0; -+pub const PA_CONTEXT_NOAUTOSPAWN: c_uint = 1; -+pub const PA_CONTEXT_NOFAIL: c_uint = 2; -+pub type pa_context_flags_t = c_uint; - - pub const PA_DIRECTION_OUTPUT: c_int = 1; - pub const PA_DIRECTION_INPUT: c_int = 2; -@@ -93,28 +93,28 @@ pub const PA_STREAM_RECORD: c_int = 2; - pub const PA_STREAM_UPLOAD: c_int = 3; - pub type pa_stream_direction_t = c_int; - --pub const PA_STREAM_NOFLAGS: c_int = 0x0_0000; --pub const PA_STREAM_START_CORKED: c_int = 0x0_0001; --pub const PA_STREAM_INTERPOLATE_TIMING: c_int = 0x0_0002; --pub const PA_STREAM_NOT_MONOTONIC: c_int = 0x0_0004; --pub const PA_STREAM_AUTO_TIMING_UPDATE: c_int = 0x0_0008; --pub const PA_STREAM_NO_REMAP_CHANNELS: c_int = 0x0_0010; --pub const PA_STREAM_NO_REMIX_CHANNELS: c_int = 0x0_0020; --pub const PA_STREAM_FIX_FORMAT: c_int = 0x0_0040; --pub const PA_STREAM_FIX_RATE: c_int = 0x0_0080; --pub const PA_STREAM_FIX_CHANNELS: c_int = 0x0_0100; --pub const PA_STREAM_DONT_MOVE: c_int = 0x0_0200; --pub const PA_STREAM_VARIABLE_RATE: c_int = 0x0_0400; --pub const PA_STREAM_PEAK_DETECT: c_int = 0x0_0800; --pub const PA_STREAM_START_MUTED: c_int = 0x0_1000; --pub const PA_STREAM_ADJUST_LATENCY: c_int = 0x0_2000; --pub const PA_STREAM_EARLY_REQUESTS: c_int = 0x0_4000; --pub const PA_STREAM_DONT_INHIBIT_AUTO_SUSPEND: c_int = 0x0_8000; --pub const PA_STREAM_START_UNMUTED: c_int = 0x1_0000; --pub const PA_STREAM_FAIL_ON_SUSPEND: c_int = 0x2_0000; --pub const PA_STREAM_RELATIVE_VOLUME: c_int = 0x4_0000; --pub const PA_STREAM_PASSTHROUGH: c_int = 0x8_0000; --pub type pa_stream_flags_t = c_int; -+pub const PA_STREAM_NOFLAGS: c_uint = 0x0_0000; -+pub const PA_STREAM_START_CORKED: c_uint = 0x0_0001; -+pub const PA_STREAM_INTERPOLATE_TIMING: c_uint = 0x0_0002; -+pub const PA_STREAM_NOT_MONOTONIC: c_uint = 0x0_0004; -+pub const PA_STREAM_AUTO_TIMING_UPDATE: c_uint = 0x0_0008; -+pub const PA_STREAM_NO_REMAP_CHANNELS: c_uint = 0x0_0010; -+pub const PA_STREAM_NO_REMIX_CHANNELS: c_uint = 0x0_0020; -+pub const PA_STREAM_FIX_FORMAT: c_uint = 0x0_0040; -+pub const PA_STREAM_FIX_RATE: c_uint = 0x0_0080; -+pub const PA_STREAM_FIX_CHANNELS: c_uint = 0x0_0100; -+pub const PA_STREAM_DONT_MOVE: c_uint = 0x0_0200; -+pub const PA_STREAM_VARIABLE_RATE: c_uint = 0x0_0400; -+pub const PA_STREAM_PEAK_DETECT: c_uint = 0x0_0800; -+pub const PA_STREAM_START_MUTED: c_uint = 0x0_1000; -+pub const PA_STREAM_ADJUST_LATENCY: c_uint = 0x0_2000; -+pub const PA_STREAM_EARLY_REQUESTS: c_uint = 0x0_4000; -+pub const PA_STREAM_DONT_INHIBIT_AUTO_SUSPEND: c_uint = 0x0_8000; -+pub const PA_STREAM_START_UNMUTED: c_uint = 0x1_0000; -+pub const PA_STREAM_FAIL_ON_SUSPEND: c_uint = 0x2_0000; -+pub const PA_STREAM_RELATIVE_VOLUME: c_uint = 0x4_0000; -+pub const PA_STREAM_PASSTHROUGH: c_uint = 0x8_0000; -+pub type pa_stream_flags_t = c_uint; - - #[repr(C)] - #[derive(Clone, Copy, Debug)] -@@ -162,19 +162,19 @@ pub const PA_ERR_BUSY: c_int = 26; - pub const PA_ERR_MAX: c_int = 27; - pub type pa_error_code_t = c_int; - --pub const PA_SUBSCRIPTION_MASK_NULL: c_int = 0; --pub const PA_SUBSCRIPTION_MASK_SINK: c_int = 1; --pub const PA_SUBSCRIPTION_MASK_SOURCE: c_int = 2; --pub const PA_SUBSCRIPTION_MASK_SINK_INPUT: c_int = 4; --pub const PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT: c_int = 8; --pub const PA_SUBSCRIPTION_MASK_MODULE: c_int = 16; --pub const PA_SUBSCRIPTION_MASK_CLIENT: c_int = 32; --pub const PA_SUBSCRIPTION_MASK_SAMPLE_CACHE: c_int = 64; --pub const PA_SUBSCRIPTION_MASK_SERVER: c_int = 128; --pub const PA_SUBSCRIPTION_MASK_AUTOLOAD: c_int = 256; --pub const PA_SUBSCRIPTION_MASK_CARD: c_int = 512; --pub const PA_SUBSCRIPTION_MASK_ALL: c_int = 767; --pub type pa_subscription_mask_t = c_int; -+pub const PA_SUBSCRIPTION_MASK_NULL: c_uint = 0x0; -+pub const PA_SUBSCRIPTION_MASK_SINK: c_uint = 0x1; -+pub const PA_SUBSCRIPTION_MASK_SOURCE: c_uint = 0x2; -+pub const PA_SUBSCRIPTION_MASK_SINK_INPUT: c_uint = 0x4; -+pub const PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT: c_uint = 0x8; -+pub const PA_SUBSCRIPTION_MASK_MODULE: c_uint = 0x10; -+pub const PA_SUBSCRIPTION_MASK_CLIENT: c_uint = 0x20; -+pub const PA_SUBSCRIPTION_MASK_SAMPLE_CACHE: c_uint = 0x40; -+pub const PA_SUBSCRIPTION_MASK_SERVER: c_uint = 0x80; -+pub const PA_SUBSCRIPTION_MASK_AUTOLOAD: c_uint = 0x100; -+pub const PA_SUBSCRIPTION_MASK_CARD: c_uint = 0x200; -+pub const PA_SUBSCRIPTION_MASK_ALL: c_uint = 0x3FF; -+pub type pa_subscription_mask_t = c_uint; - - pub const PA_SUBSCRIPTION_EVENT_SINK: c_int = 0; - pub const PA_SUBSCRIPTION_EVENT_SOURCE: c_int = 1; -@@ -244,17 +244,17 @@ pub const PA_SEEK_RELATIVE_ON_READ: c_in - pub const PA_SEEK_RELATIVE_END: c_int = 3; - pub type pa_seek_mode_t = c_int; - --pub const PA_SINK_NOFLAGS: c_int = 0; --pub const PA_SINK_HW_VOLUME_CTRL: c_int = 1; --pub const PA_SINK_LATENCY: c_int = 2; --pub const PA_SINK_HARDWARE: c_int = 4; --pub const PA_SINK_NETWORK: c_int = 8; --pub const PA_SINK_HW_MUTE_CTRL: c_int = 16; --pub const PA_SINK_DECIBEL_VOLUME: c_int = 32; --pub const PA_SINK_FLAT_VOLUME: c_int = 64; --pub const PA_SINK_DYNAMIC_LATENCY: c_int = 128; --pub const PA_SINK_SET_FORMATS: c_int = 256; --pub type pa_sink_flags_t = c_int; -+pub const PA_SINK_NOFLAGS: c_uint = 0x000; -+pub const PA_SINK_HW_VOLUME_CTRL: c_uint = 0x001; -+pub const PA_SINK_LATENCY: c_uint = 0x002; -+pub const PA_SINK_HARDWARE: c_uint = 0x004; -+pub const PA_SINK_NETWORK: c_uint = 0x008; -+pub const PA_SINK_HW_MUTE_CTRL: c_uint = 0x010; -+pub const PA_SINK_DECIBEL_VOLUME: c_uint = 0x020; -+pub const PA_SINK_FLAT_VOLUME: c_uint = 0x040; -+pub const PA_SINK_DYNAMIC_LATENCY: c_uint = 0x080; -+pub const PA_SINK_SET_FORMATS: c_uint = 0x100; -+pub type pa_sink_flags_t = c_uint; - - pub const PA_SINK_INVALID_STATE: c_int = -1; - pub const PA_SINK_RUNNING: c_int = 0; -@@ -264,16 +264,16 @@ pub const PA_SINK_INIT: c_int = -2; - pub const PA_SINK_UNLINKED: c_int = -3; - pub type pa_sink_state_t = c_int; - --pub const PA_SOURCE_NOFLAGS: c_int = 0x00; --pub const PA_SOURCE_HW_VOLUME_CTRL: c_int = 0x01; --pub const PA_SOURCE_LATENCY: c_int = 0x02; --pub const PA_SOURCE_HARDWARE: c_int = 0x04; --pub const PA_SOURCE_NETWORK: c_int = 0x08; --pub const PA_SOURCE_HW_MUTE_CTRL: c_int = 0x10; --pub const PA_SOURCE_DECIBEL_VOLUME: c_int = 0x20; --pub const PA_SOURCE_DYNAMIC_LATENCY: c_int = 0x40; --pub const PA_SOURCE_FLAT_VOLUME: c_int = 0x80; --pub type pa_source_flags_t = c_int; -+pub const PA_SOURCE_NOFLAGS: c_uint = 0x00; -+pub const PA_SOURCE_HW_VOLUME_CTRL: c_uint = 0x01; -+pub const PA_SOURCE_LATENCY: c_uint = 0x02; -+pub const PA_SOURCE_HARDWARE: c_uint = 0x04; -+pub const PA_SOURCE_NETWORK: c_uint = 0x08; -+pub const PA_SOURCE_HW_MUTE_CTRL: c_uint = 0x10; -+pub const PA_SOURCE_DECIBEL_VOLUME: c_uint = 0x20; -+pub const PA_SOURCE_DYNAMIC_LATENCY: c_uint = 0x40; -+pub const PA_SOURCE_FLAT_VOLUME: c_uint = 0x80; -+pub type pa_source_flags_t = c_uint; - - pub const PA_SOURCE_INVALID_STATE: c_int = -1; - pub const PA_SOURCE_RUNNING: c_int = 0; -diff -up firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/Cargo.toml.cubeb-pulse-arm firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/Cargo.toml ---- firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/Cargo.toml.cubeb-pulse-arm 2017-08-04 13:37:46.384821737 +0200 -+++ firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/Cargo.toml 2017-08-04 13:37:46.384821737 +0200 -@@ -0,0 +1,8 @@ -+[package] -+name = "pulse" -+version = "0.1.0" -+authors = ["Dan Glastonbury "] -+ -+[dependencies] -+bitflags = "^0.7.0" -+pulse-ffi = { path = "../pulse-ffi" } -diff -up firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/context.rs.cubeb-pulse-arm firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/context.rs ---- firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/context.rs.cubeb-pulse-arm 2017-08-04 13:37:46.385821734 +0200 -+++ firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/context.rs 2017-08-04 13:37:46.385821734 +0200 -@@ -0,0 +1,394 @@ -+// Copyright © 2017 Mozilla Foundation -+// -+// This program is made available under an ISC-style license. See the -+// accompanying file LICENSE for details. -+ -+use ::*; -+use ffi; -+use std::ffi::CStr; -+use std::os::raw::{c_int, c_void}; -+use std::ptr; -+use util::UnwrapCStr; -+ -+// A note about `wrapped` functions -+// -+// C FFI demands `unsafe extern fn(*mut pa_context, ...) -> i32`, etc, -+// but we want to allow such callbacks to be safe. This means no -+// `unsafe` or `extern`, and callbacks should be called with a safe -+// wrapper of `*mut pa_context`. Since the callback doesn't take -+// ownership, this is `&Context`. `fn wrapped(...)` defines a -+// function that converts from our safe signature to the unsafe -+// signature. -+// -+// Currently, we use a property of Rust, namely that each function -+// gets its own unique type. These unique types can't be written -+// directly, so we use generic and a type parameter, and let the Rust -+// compiler fill in the name for us: -+// -+// fn get_sink_input_info(&self, ..., _: CB, ...) -> ... -+// where CB: Fn(&Context, *const SinkInputInfo, i32, *mut c_void) -+// -+// Because we aren't storing or passing any state, we assert, at run-time :-(, -+// that our functions are zero-sized: -+// -+// assert!(mem::size_of::() == 0); -+// -+// We need to obtain a value of type F in order to call it. Since we -+// can't name the function, we have to unsafely construct that value -+// somehow - we do this using mem::uninitialized. Then, we call that -+// function with a reference to the Context, and save the result: -+// -+// | generate value || call it | -+// let result = ::std::mem::uninitialized::()(&mut object); -+// -+// Lastly, since our Object is an owned type, we need to avoid -+// dropping it, then return the result we just generated. -+// -+// mem::forget(object); -+// result -+ -+// Aid in returning Operation from callbacks -+macro_rules! op_or_err { -+ ($self_:ident, $e:expr) => {{ -+ let o = unsafe { $e }; -+ if o.is_null() { -+ Err(ErrorCode::from_error_code($self_.errno())) -+ } else { -+ Ok(unsafe { operation::from_raw_ptr(o) }) -+ } -+ }} -+} -+ -+#[repr(C)] -+#[derive(Debug)] -+pub struct Context(*mut ffi::pa_context); -+ -+impl Context { -+ pub fn new<'a, OPT>(api: &MainloopApi, name: OPT) -> Option -+ where OPT: Into> -+ { -+ let ptr = unsafe { ffi::pa_context_new(api.raw_mut(), name.unwrap_cstr()) }; -+ if ptr.is_null() { -+ None -+ } else { -+ Some(Context(ptr)) -+ } -+ } -+ -+ #[doc(hidden)] -+ pub fn raw_mut(&self) -> &mut ffi::pa_context { -+ unsafe { &mut *self.0 } -+ } -+ -+ pub fn unref(self) { -+ unsafe { -+ ffi::pa_context_unref(self.raw_mut()); -+ } -+ } -+ -+ pub fn clear_state_callback(&self) { -+ unsafe { -+ ffi::pa_context_set_state_callback(self.raw_mut(), None, ptr::null_mut()); -+ } -+ } -+ -+ pub fn set_state_callback(&self, _: CB, userdata: *mut c_void) -+ where CB: Fn(&Context, *mut c_void) -+ { -+ debug_assert_eq!(::std::mem::size_of::(), 0); -+ -+ // See: A note about `wrapped` functions -+ unsafe extern "C" fn wrapped(c: *mut ffi::pa_context, userdata: *mut c_void) -+ where F: Fn(&Context, *mut c_void) -+ { -+ use std::mem::{forget, uninitialized}; -+ let ctx = context::from_raw_ptr(c); -+ let result = uninitialized::()(&ctx, userdata); -+ forget(ctx); -+ -+ result -+ } -+ -+ unsafe { -+ ffi::pa_context_set_state_callback(self.raw_mut(), Some(wrapped::), userdata); -+ } -+ } -+ -+ pub fn errno(&self) -> ffi::pa_error_code_t { -+ unsafe { ffi::pa_context_errno(self.raw_mut()) } -+ } -+ -+ pub fn get_state(&self) -> ContextState { -+ ContextState::try_from(unsafe { -+ ffi::pa_context_get_state(self.raw_mut()) -+ }).expect("pa_context_get_state returned invalid ContextState") -+ } -+ -+ pub fn connect<'a, OPT>(&self, server: OPT, flags: ContextFlags, api: *const ffi::pa_spawn_api) -> Result<()> -+ where OPT: Into> -+ { -+ let r = unsafe { -+ ffi::pa_context_connect(self.raw_mut(), -+ server.into().unwrap_cstr(), -+ flags.into(), -+ api) -+ }; -+ error_result!((), r) -+ } -+ -+ pub fn disconnect(&self) { -+ unsafe { -+ ffi::pa_context_disconnect(self.raw_mut()); -+ } -+ } -+ -+ -+ pub fn drain(&self, _: CB, userdata: *mut c_void) -> Result -+ where CB: Fn(&Context, *mut c_void) -+ { -+ debug_assert_eq!(::std::mem::size_of::(), 0); -+ -+ // See: A note about `wrapped` functions -+ unsafe extern "C" fn wrapped(c: *mut ffi::pa_context, userdata: *mut c_void) -+ where F: Fn(&Context, *mut c_void) -+ { -+ use std::mem::{forget, uninitialized}; -+ let ctx = context::from_raw_ptr(c); -+ let result = uninitialized::()(&ctx, userdata); -+ forget(ctx); -+ -+ result -+ } -+ -+ op_or_err!(self, -+ ffi::pa_context_drain(self.raw_mut(), Some(wrapped::), userdata)) -+ } -+ -+ pub fn rttime_new(&self, usec: USec, _: CB, userdata: *mut c_void) -> *mut ffi::pa_time_event -+ where CB: Fn(&MainloopApi, *mut ffi::pa_time_event, &TimeVal, *mut c_void) -+ { -+ debug_assert_eq!(::std::mem::size_of::(), 0); -+ -+ // See: A note about `wrapped` functions -+ unsafe extern "C" fn wrapped(a: *mut ffi::pa_mainloop_api, -+ e: *mut ffi::pa_time_event, -+ tv: *const TimeVal, -+ userdata: *mut c_void) -+ where F: Fn(&MainloopApi, *mut ffi::pa_time_event, &TimeVal, *mut c_void) -+ { -+ use std::mem::{forget, uninitialized}; -+ let api = mainloop_api::from_raw_ptr(a); -+ let timeval = &*tv; -+ let result = uninitialized::()(&api, e, timeval, userdata); -+ forget(api); -+ -+ result -+ } -+ -+ unsafe { ffi::pa_context_rttime_new(self.raw_mut(), usec, Some(wrapped::), userdata) } -+ } -+ -+ pub fn get_server_info(&self, _: CB, userdata: *mut c_void) -> Result -+ where CB: Fn(&Context, &ServerInfo, *mut c_void) -+ { -+ debug_assert_eq!(::std::mem::size_of::(), 0); -+ -+ // See: A note about `wrapped` functions -+ unsafe extern "C" fn wrapped(c: *mut ffi::pa_context, i: *const ffi::pa_server_info, userdata: *mut c_void) -+ where F: Fn(&Context, &ServerInfo, *mut c_void) -+ { -+ use std::mem::{forget, uninitialized}; -+ debug_assert_ne!(i, ptr::null_mut()); -+ let info = &*i; -+ let ctx = context::from_raw_ptr(c); -+ let result = uninitialized::()(&ctx, info, userdata); -+ forget(ctx); -+ -+ result -+ } -+ -+ op_or_err!(self, -+ ffi::pa_context_get_server_info(self.raw_mut(), Some(wrapped::), userdata)) -+ } -+ -+ pub fn get_sink_info_by_name(&self, name: &CStr, _: CB, userdata: *mut c_void) -> Result -+ where CB: Fn(&Context, *const SinkInfo, i32, *mut c_void) -+ { -+ debug_assert_eq!(::std::mem::size_of::(), 0); -+ -+ // See: A note about `wrapped` functions -+ unsafe extern "C" fn wrapped(c: *mut ffi::pa_context, -+ info: *const ffi::pa_sink_info, -+ eol: c_int, -+ userdata: *mut c_void) -+ where F: Fn(&Context, *const SinkInfo, i32, *mut c_void) -+ { -+ use std::mem::{forget, uninitialized}; -+ let ctx = context::from_raw_ptr(c); -+ let result = uninitialized::()(&ctx, info, eol, userdata); -+ forget(ctx); -+ -+ result -+ } -+ -+ op_or_err!(self, -+ ffi::pa_context_get_sink_info_by_name(self.raw_mut(), name.as_ptr(), Some(wrapped::), userdata)) -+ } -+ -+ pub fn get_sink_info_list(&self, _: CB, userdata: *mut c_void) -> Result -+ where CB: Fn(&Context, *const SinkInfo, i32, *mut c_void) -+ { -+ debug_assert_eq!(::std::mem::size_of::(), 0); -+ -+ // See: A note about `wrapped` functions -+ unsafe extern "C" fn wrapped(c: *mut ffi::pa_context, -+ info: *const ffi::pa_sink_info, -+ eol: c_int, -+ userdata: *mut c_void) -+ where F: Fn(&Context, *const SinkInfo, i32, *mut c_void) -+ { -+ use std::mem::{forget, uninitialized}; -+ let ctx = context::from_raw_ptr(c); -+ let result = uninitialized::()(&ctx, info, eol, userdata); -+ forget(ctx); -+ -+ result -+ } -+ -+ op_or_err!(self, -+ ffi::pa_context_get_sink_info_list(self.raw_mut(), Some(wrapped::), userdata)) -+ } -+ -+ pub fn get_sink_input_info(&self, idx: u32, _: CB, userdata: *mut c_void) -> Result -+ where CB: Fn(&Context, *const SinkInputInfo, i32, *mut c_void) -+ { -+ debug_assert_eq!(::std::mem::size_of::(), 0); -+ -+ // See: A note about `wrapped` functions -+ unsafe extern "C" fn wrapped(c: *mut ffi::pa_context, -+ info: *const ffi::pa_sink_input_info, -+ eol: c_int, -+ userdata: *mut c_void) -+ where F: Fn(&Context, *const SinkInputInfo, i32, *mut c_void) -+ { -+ use std::mem::{forget, uninitialized}; -+ let ctx = context::from_raw_ptr(c); -+ let result = uninitialized::()(&ctx, info, eol, userdata); -+ forget(ctx); -+ -+ result -+ } -+ -+ op_or_err!(self, -+ ffi::pa_context_get_sink_input_info(self.raw_mut(), idx, Some(wrapped::), userdata)) -+ } -+ -+ pub fn get_source_info_list(&self, _: CB, userdata: *mut c_void) -> Result -+ where CB: Fn(&Context, *const SourceInfo, i32, *mut c_void) -+ { -+ debug_assert_eq!(::std::mem::size_of::(), 0); -+ -+ // See: A note about `wrapped` functions -+ unsafe extern "C" fn wrapped(c: *mut ffi::pa_context, -+ info: *const ffi::pa_source_info, -+ eol: c_int, -+ userdata: *mut c_void) -+ where F: Fn(&Context, *const SourceInfo, i32, *mut c_void) -+ { -+ use std::mem::{forget, uninitialized}; -+ let ctx = context::from_raw_ptr(c); -+ let result = uninitialized::()(&ctx, info, eol, userdata); -+ forget(ctx); -+ -+ result -+ } -+ -+ op_or_err!(self, -+ ffi::pa_context_get_source_info_list(self.raw_mut(), Some(wrapped::), userdata)) -+ } -+ -+ pub fn set_sink_input_volume(&self, -+ idx: u32, -+ volume: &CVolume, -+ _: CB, -+ userdata: *mut c_void) -+ -> Result -+ where CB: Fn(&Context, i32, *mut c_void) -+ { -+ debug_assert_eq!(::std::mem::size_of::(), 0); -+ -+ // See: A note about `wrapped` functions -+ unsafe extern "C" fn wrapped(c: *mut ffi::pa_context, success: c_int, userdata: *mut c_void) -+ where F: Fn(&Context, i32, *mut c_void) -+ { -+ use std::mem::{forget, uninitialized}; -+ let ctx = context::from_raw_ptr(c); -+ let result = uninitialized::()(&ctx, success, userdata); -+ forget(ctx); -+ -+ result -+ } -+ -+ op_or_err!(self, -+ ffi::pa_context_set_sink_input_volume(self.raw_mut(), idx, volume, Some(wrapped::), userdata)) -+ } -+ -+ pub fn subscribe(&self, m: SubscriptionMask, _: CB, userdata: *mut c_void) -> Result -+ where CB: Fn(&Context, i32, *mut c_void) -+ { -+ debug_assert_eq!(::std::mem::size_of::(), 0); -+ -+ // See: A note about `wrapped` functions -+ unsafe extern "C" fn wrapped(c: *mut ffi::pa_context, success: c_int, userdata: *mut c_void) -+ where F: Fn(&Context, i32, *mut c_void) -+ { -+ use std::mem::{forget, uninitialized}; -+ let ctx = context::from_raw_ptr(c); -+ let result = uninitialized::()(&ctx, success, userdata); -+ forget(ctx); -+ -+ result -+ } -+ -+ op_or_err!(self, -+ ffi::pa_context_subscribe(self.raw_mut(), m.into(), Some(wrapped::), userdata)) -+ } -+ -+ pub fn clear_subscribe_callback(&self) { -+ unsafe { -+ ffi::pa_context_set_subscribe_callback(self.raw_mut(), None, ptr::null_mut()); -+ } -+ } -+ -+ pub fn set_subscribe_callback(&self, _: CB, userdata: *mut c_void) -+ where CB: Fn(&Context, SubscriptionEvent, u32, *mut c_void) -+ { -+ debug_assert_eq!(::std::mem::size_of::(), 0); -+ -+ // See: A note about `wrapped` functions -+ unsafe extern "C" fn wrapped(c: *mut ffi::pa_context, -+ t: ffi::pa_subscription_event_type_t, -+ idx: u32, -+ userdata: *mut c_void) -+ where F: Fn(&Context, SubscriptionEvent, u32, *mut c_void) -+ { -+ use std::mem::{forget, uninitialized}; -+ let ctx = context::from_raw_ptr(c); -+ let event = SubscriptionEvent::try_from(t) -+ .expect("pa_context_subscribe_cb_t passed invalid pa_subscription_event_type_t"); -+ let result = uninitialized::()(&ctx, event, idx, userdata); -+ forget(ctx); -+ -+ result -+ } -+ -+ unsafe { -+ ffi::pa_context_set_subscribe_callback(self.raw_mut(), Some(wrapped::), userdata); -+ } -+ } -+} -+ -+#[doc(hidden)] -+pub unsafe fn from_raw_ptr(ptr: *mut ffi::pa_context) -> Context { -+ Context(ptr) -+} -diff -up firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/error.rs.cubeb-pulse-arm firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/error.rs ---- firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/error.rs.cubeb-pulse-arm 2017-08-04 13:37:46.385821734 +0200 -+++ firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/error.rs 2017-08-04 13:37:46.385821734 +0200 -@@ -0,0 +1,56 @@ -+// Copyright © 2017 Mozilla Foundation -+// -+// This program is made available under an ISC-style license. See the -+// accompanying file LICENSE for details. -+ -+use ffi; -+use std::ffi::CStr; -+ -+#[macro_export] -+macro_rules! error_result { -+ ($t:expr, $err:expr) => { -+ if $err >= 0 { -+ Ok($t) -+ } else { -+ Err(ErrorCode::from_error_result($err)) -+ } -+ } -+} -+ -+#[derive(Debug, PartialEq)] -+pub struct ErrorCode { -+ err: ffi::pa_error_code_t, -+} -+ -+impl ErrorCode { -+ pub fn from_error_result(err: i32) -> Self { -+ debug_assert!(err < 0); -+ ErrorCode { -+ err: (-err) as ffi::pa_error_code_t, -+ } -+ } -+ -+ pub fn from_error_code(err: ffi::pa_error_code_t) -> Self { -+ debug_assert!(err > 0); -+ ErrorCode { -+ err: err, -+ } -+ } -+ -+ fn desc(&self) -> &'static str { -+ let cstr = unsafe { CStr::from_ptr(ffi::pa_strerror(self.err)) }; -+ cstr.to_str().unwrap() -+ } -+} -+ -+impl ::std::error::Error for ErrorCode { -+ fn description(&self) -> &str { -+ self.desc() -+ } -+} -+ -+impl ::std::fmt::Display for ErrorCode { -+ fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { -+ write!(f, "{:?}: {}", self, self.desc()) -+ } -+} -diff -up firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/lib.rs.cubeb-pulse-arm firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/lib.rs ---- firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/lib.rs.cubeb-pulse-arm 2017-08-04 13:37:46.385821734 +0200 -+++ firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/lib.rs 2017-08-04 13:37:46.385821734 +0200 -@@ -0,0 +1,653 @@ -+// Copyright © 2017 Mozilla Foundation -+// -+// This program is made available under an ISC-style license. See the -+// accompanying file LICENSE for details. -+ -+#[macro_use] -+extern crate bitflags; -+extern crate pulse_ffi as ffi; -+ -+#[macro_use] -+mod error; -+mod context; -+mod mainloop_api; -+mod operation; -+mod proplist; -+mod stream; -+mod threaded_mainloop; -+mod util; -+ -+pub use context::Context; -+pub use error::ErrorCode; -+pub use ffi::pa_buffer_attr as BufferAttr; -+pub use ffi::pa_channel_map as ChannelMap; -+pub use ffi::pa_cvolume as CVolume; -+pub use ffi::pa_sample_spec as SampleSpec; -+pub use ffi::pa_server_info as ServerInfo; -+pub use ffi::pa_sink_info as SinkInfo; -+pub use ffi::pa_sink_input_info as SinkInputInfo; -+pub use ffi::pa_source_info as SourceInfo; -+pub use ffi::pa_usec_t as USec; -+pub use ffi::pa_volume_t as Volume; -+pub use ffi::timeval as TimeVal; -+pub use mainloop_api::MainloopApi; -+pub use operation::Operation; -+pub use proplist::Proplist; -+use std::os::raw::{c_char, c_uint}; -+pub use stream::Stream; -+pub use threaded_mainloop::ThreadedMainloop; -+ -+#[allow(non_camel_case_types)] -+#[repr(i32)] -+#[derive(Clone, Copy, Debug, PartialEq, Eq)] -+pub enum SampleFormat { -+ Invalid = ffi::PA_SAMPLE_INVALID, -+ U8 = ffi::PA_SAMPLE_U8, -+ Alaw = ffi::PA_SAMPLE_ALAW, -+ Ulaw = ffi::PA_SAMPLE_ULAW, -+ Signed16LE = ffi::PA_SAMPLE_S16LE, -+ Signed16BE = ffi::PA_SAMPLE_S16BE, -+ Float32LE = ffi::PA_SAMPLE_FLOAT32LE, -+ Float32BE = ffi::PA_SAMPLE_FLOAT32BE, -+ Signed32LE = ffi::PA_SAMPLE_S32LE, -+ Signed32BE = ffi::PA_SAMPLE_S32BE, -+ Signed24LE = ffi::PA_SAMPLE_S24LE, -+ Signed24BE = ffi::PA_SAMPLE_S24BE, -+ Signed24_32LE = ffi::PA_SAMPLE_S24_32LE, -+ Signed23_32BE = ffi::PA_SAMPLE_S24_32BE, -+} -+ -+impl Default for SampleFormat { -+ fn default() -> Self { -+ SampleFormat::Invalid -+ } -+} -+ -+impl Into for SampleFormat { -+ fn into(self) -> ffi::pa_sample_format_t { -+ self as ffi::pa_sample_format_t -+ } -+} -+ -+#[repr(i32)] -+#[derive(Clone, Copy, Debug, PartialEq, Eq)] -+pub enum ContextState { -+ Unconnected = ffi::PA_CONTEXT_UNCONNECTED, -+ Connecting = ffi::PA_CONTEXT_CONNECTING, -+ Authorizing = ffi::PA_CONTEXT_AUTHORIZING, -+ SettingName = ffi::PA_CONTEXT_SETTING_NAME, -+ Ready = ffi::PA_CONTEXT_READY, -+ Failed = ffi::PA_CONTEXT_FAILED, -+ Terminated = ffi::PA_CONTEXT_TERMINATED, -+} -+ -+impl ContextState { -+ // This function implements the PA_CONTENT_IS_GOOD macro from pulse/def.h -+ // It must match the version from PA headers. -+ pub fn is_good(self) -> bool { -+ match self { -+ ContextState::Connecting | -+ ContextState::Authorizing | -+ ContextState::SettingName | -+ ContextState::Ready => true, -+ _ => false, -+ } -+ } -+ -+ pub fn try_from(x: ffi::pa_context_state_t) -> Option { -+ if x >= ffi::PA_CONTEXT_UNCONNECTED && x <= ffi::PA_CONTEXT_TERMINATED { -+ Some(unsafe { ::std::mem::transmute(x) }) -+ } else { -+ None -+ } -+ } -+} -+ -+impl Default for ContextState { -+ fn default() -> Self { -+ ContextState::Unconnected -+ } -+} -+ -+impl Into for ContextState { -+ fn into(self) -> ffi::pa_context_state_t { -+ self as ffi::pa_context_state_t -+ } -+} -+ -+#[repr(i32)] -+#[derive(Clone, Copy, Debug, PartialEq, Eq)] -+pub enum StreamState { -+ Unconnected = ffi::PA_STREAM_UNCONNECTED, -+ Creating = ffi::PA_STREAM_CREATING, -+ Ready = ffi::PA_STREAM_READY, -+ Failed = ffi::PA_STREAM_FAILED, -+ Terminated = ffi::PA_STREAM_TERMINATED, -+} -+ -+impl StreamState { -+ // This function implements the PA_STREAM_IS_GOOD macro from pulse/def.h -+ // It must match the version from PA headers. -+ pub fn is_good(self) -> bool { -+ match self { -+ StreamState::Creating | StreamState::Ready => true, -+ _ => false, -+ } -+ } -+ -+ pub fn try_from(x: ffi::pa_stream_state_t) -> Option { -+ if x >= ffi::PA_STREAM_UNCONNECTED && x <= ffi::PA_STREAM_TERMINATED { -+ Some(unsafe { ::std::mem::transmute(x) }) -+ } else { -+ None -+ } -+ } -+} -+ -+impl Default for StreamState { -+ fn default() -> Self { -+ StreamState::Unconnected -+ } -+} -+ -+impl Into for StreamState { -+ fn into(self) -> ffi::pa_stream_state_t { -+ self as ffi::pa_stream_state_t -+ } -+} -+ -+#[repr(i32)] -+#[derive(Clone, Copy, Debug, PartialEq, Eq)] -+pub enum OperationState { -+ Running = ffi::PA_OPERATION_RUNNING, -+ Done = ffi::PA_OPERATION_DONE, -+ Cancelled = ffi::PA_OPERATION_CANCELLED, -+} -+ -+impl OperationState { -+ pub fn try_from(x: ffi::pa_operation_state_t) -> Option { -+ if x >= ffi::PA_OPERATION_RUNNING && x <= ffi::PA_OPERATION_CANCELLED { -+ Some(unsafe { ::std::mem::transmute(x) }) -+ } else { -+ None -+ } -+ } -+} -+ -+impl Into for OperationState { -+ fn into(self) -> ffi::pa_operation_state_t { -+ self as ffi::pa_operation_state_t -+ } -+} -+ -+bitflags! { -+ pub flags ContextFlags: u32 { -+ const CONTEXT_FLAGS_NOAUTOSPAWN = ffi::PA_CONTEXT_NOAUTOSPAWN, -+ const CONTEXT_FLAGS_NOFAIL = ffi::PA_CONTEXT_NOFAIL, -+ } -+} -+ -+impl Into for ContextFlags { -+ fn into(self) -> ffi::pa_context_flags_t { -+ self.bits() as ffi::pa_context_flags_t -+ } -+} -+ -+#[repr(i32)] -+#[derive(Clone, Copy, Debug, PartialEq, Eq)] -+pub enum DeviceType { -+ Sink = ffi::PA_DEVICE_TYPE_SINK, -+ Source = ffi::PA_DEVICE_TYPE_SOURCE, -+} -+ -+impl DeviceType { -+ pub fn try_from(x: ffi::pa_device_type_t) -> Option { -+ if x >= ffi::PA_DEVICE_TYPE_SINK && x <= ffi::PA_DEVICE_TYPE_SOURCE { -+ Some(unsafe { ::std::mem::transmute(x) }) -+ } else { -+ None -+ } -+ } -+} -+ -+impl Into for DeviceType { -+ fn into(self) -> ffi::pa_device_type_t { -+ self as ffi::pa_device_type_t -+ } -+} -+ -+ -+#[repr(i32)] -+#[derive(Clone, Copy, Debug, PartialEq, Eq)] -+pub enum StreamDirection { -+ NoDirection = ffi::PA_STREAM_NODIRECTION, -+ Playback = ffi::PA_STREAM_PLAYBACK, -+ Record = ffi::PA_STREAM_RECORD, -+ StreamUpload = ffi::PA_STREAM_UPLOAD, -+} -+ -+impl StreamDirection { -+ pub fn try_from(x: ffi::pa_stream_direction_t) -> Option { -+ if x >= ffi::PA_STREAM_NODIRECTION && x <= ffi::PA_STREAM_UPLOAD { -+ Some(unsafe { ::std::mem::transmute(x) }) -+ } else { -+ None -+ } -+ } -+} -+ -+impl Into for StreamDirection { -+ fn into(self) -> ffi::pa_stream_direction_t { -+ self as ffi::pa_stream_direction_t -+ } -+} -+ -+bitflags! { -+ pub flags StreamFlags : u32 { -+ const STREAM_START_CORKED = ffi::PA_STREAM_START_CORKED, -+ const STREAM_INTERPOLATE_TIMING = ffi::PA_STREAM_INTERPOLATE_TIMING, -+ const STREAM_NOT_MONOTONIC = ffi::PA_STREAM_NOT_MONOTONIC, -+ const STREAM_AUTO_TIMING_UPDATE = ffi::PA_STREAM_AUTO_TIMING_UPDATE, -+ const STREAM_NO_REMAP_CHANNELS = ffi::PA_STREAM_NO_REMAP_CHANNELS, -+ const STREAM_NO_REMIX_CHANNELS = ffi::PA_STREAM_NO_REMIX_CHANNELS, -+ const STREAM_FIX_FORMAT = ffi::PA_STREAM_FIX_FORMAT, -+ const STREAM_FIX_RATE = ffi::PA_STREAM_FIX_RATE, -+ const STREAM_FIX_CHANNELS = ffi::PA_STREAM_FIX_CHANNELS, -+ const STREAM_DONT_MOVE = ffi::PA_STREAM_DONT_MOVE, -+ const STREAM_VARIABLE_RATE = ffi::PA_STREAM_VARIABLE_RATE, -+ const STREAM_PEAK_DETECT = ffi::PA_STREAM_PEAK_DETECT, -+ const STREAM_START_MUTED = ffi::PA_STREAM_START_MUTED, -+ const STREAM_ADJUST_LATENCY = ffi::PA_STREAM_ADJUST_LATENCY, -+ const STREAM_EARLY_REQUESTS = ffi::PA_STREAM_EARLY_REQUESTS, -+ const STREAM_DONT_INHIBIT_AUTO_SUSPEND = ffi::PA_STREAM_DONT_INHIBIT_AUTO_SUSPEND, -+ const STREAM_START_UNMUTED = ffi::PA_STREAM_START_UNMUTED, -+ const STREAM_FAIL_ON_SUSPEND = ffi::PA_STREAM_FAIL_ON_SUSPEND, -+ const STREAM_RELATIVE_VOLUME = ffi::PA_STREAM_RELATIVE_VOLUME, -+ const STREAM_PASSTHROUGH = ffi::PA_STREAM_PASSTHROUGH, -+ } -+} -+ -+impl StreamFlags { -+ pub fn try_from(x: ffi::pa_stream_flags_t) -> Option { -+ if (x & -+ !(ffi::PA_STREAM_NOFLAGS | ffi::PA_STREAM_START_CORKED | ffi::PA_STREAM_INTERPOLATE_TIMING | -+ ffi::PA_STREAM_NOT_MONOTONIC | ffi::PA_STREAM_AUTO_TIMING_UPDATE | -+ ffi::PA_STREAM_NO_REMAP_CHANNELS | -+ ffi::PA_STREAM_NO_REMIX_CHANNELS | ffi::PA_STREAM_FIX_FORMAT | ffi::PA_STREAM_FIX_RATE | -+ ffi::PA_STREAM_FIX_CHANNELS | -+ ffi::PA_STREAM_DONT_MOVE | ffi::PA_STREAM_VARIABLE_RATE | ffi::PA_STREAM_PEAK_DETECT | -+ ffi::PA_STREAM_START_MUTED | ffi::PA_STREAM_ADJUST_LATENCY | -+ ffi::PA_STREAM_EARLY_REQUESTS | -+ ffi::PA_STREAM_DONT_INHIBIT_AUTO_SUSPEND | -+ ffi::PA_STREAM_START_UNMUTED | ffi::PA_STREAM_FAIL_ON_SUSPEND | -+ ffi::PA_STREAM_RELATIVE_VOLUME | ffi::PA_STREAM_PASSTHROUGH)) == 0 { -+ Some(unsafe { ::std::mem::transmute(x) }) -+ } else { -+ None -+ } -+ } -+} -+ -+impl Into for StreamFlags { -+ fn into(self) -> ffi::pa_stream_flags_t { -+ self.bits() as ffi::pa_stream_flags_t -+ } -+} -+ -+bitflags!{ -+ pub flags SubscriptionMask : u32 { -+ const SUBSCRIPTION_MASK_SINK = ffi::PA_SUBSCRIPTION_MASK_SINK, -+ const SUBSCRIPTION_MASK_SOURCE = ffi::PA_SUBSCRIPTION_MASK_SOURCE, -+ const SUBSCRIPTION_MASK_SINK_INPUT = ffi::PA_SUBSCRIPTION_MASK_SINK_INPUT, -+ const SUBSCRIPTION_MASK_SOURCE_OUTPUT = ffi::PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT, -+ const SUBSCRIPTION_MASK_MODULE = ffi::PA_SUBSCRIPTION_MASK_MODULE, -+ const SUBSCRIPTION_MASK_CLIENT = ffi::PA_SUBSCRIPTION_MASK_CLIENT, -+ const SUBSCRIPTION_MASK_SAMPLE_CACHE = ffi::PA_SUBSCRIPTION_MASK_SAMPLE_CACHE, -+ const SUBSCRIPTION_MASK_SERVER = ffi::PA_SUBSCRIPTION_MASK_SERVER, -+ const SUBSCRIPTION_MASK_AUTOLOAD = ffi::PA_SUBSCRIPTION_MASK_AUTOLOAD, -+ const SUBSCRIPTION_MASK_CARD = ffi::PA_SUBSCRIPTION_MASK_CARD, -+ } -+} -+ -+impl SubscriptionMask { -+ pub fn try_from(x: ffi::pa_subscription_mask_t) -> Option { -+ if (x & !ffi::PA_SUBSCRIPTION_MASK_ALL) == 0 { -+ Some(unsafe { ::std::mem::transmute(x) }) -+ } else { -+ None -+ } -+ } -+} -+ -+impl Into for SubscriptionMask { -+ fn into(self) -> ffi::pa_subscription_mask_t { -+ self.bits() as ffi::pa_subscription_mask_t -+ } -+} -+ -+#[repr(i32)] -+#[derive(Clone, Copy, Debug, PartialEq, Eq)] -+pub enum SubscriptionEventFacility { -+ Sink = ffi::PA_SUBSCRIPTION_EVENT_SINK, -+ Source = ffi::PA_SUBSCRIPTION_EVENT_SOURCE, -+ SinkInput = ffi::PA_SUBSCRIPTION_EVENT_SINK_INPUT, -+ SourceOutput = ffi::PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT, -+ Module = ffi::PA_SUBSCRIPTION_EVENT_MODULE, -+ Client = ffi::PA_SUBSCRIPTION_EVENT_CLIENT, -+ SampleCache = ffi::PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE, -+ Server = ffi::PA_SUBSCRIPTION_EVENT_SERVER, -+ Autoload = ffi::PA_SUBSCRIPTION_EVENT_AUTOLOAD, -+ Card = ffi::PA_SUBSCRIPTION_EVENT_CARD, -+} -+ -+#[repr(C)] -+#[derive(Clone, Copy, Debug, PartialEq, Eq)] -+pub enum SubscriptionEventType { -+ New, -+ Change, -+ Remove, -+} -+ -+#[repr(C)] -+#[derive(Clone, Copy, Debug, PartialEq, Eq)] -+pub struct SubscriptionEvent(ffi::pa_subscription_event_type_t); -+impl SubscriptionEvent { -+ pub fn try_from(x: ffi::pa_subscription_event_type_t) -> Option { -+ if (x & !(ffi::PA_SUBSCRIPTION_EVENT_TYPE_MASK | ffi::PA_SUBSCRIPTION_EVENT_FACILITY_MASK)) == 0 { -+ Some(SubscriptionEvent(x)) -+ } else { -+ None -+ } -+ } -+ -+ pub fn event_facility(self) -> SubscriptionEventFacility { -+ unsafe { ::std::mem::transmute(self.0 & ffi::PA_SUBSCRIPTION_EVENT_FACILITY_MASK) } -+ } -+ -+ pub fn event_type(self) -> SubscriptionEventType { -+ unsafe { ::std::mem::transmute(((self.0 & ffi::PA_SUBSCRIPTION_EVENT_TYPE_MASK) >> 4)) } -+ } -+} -+ -+#[repr(i32)] -+#[derive(Clone, Copy, Debug, PartialEq, Eq)] -+pub enum SeekMode { -+ Relative = ffi::PA_SEEK_RELATIVE, -+ Absolute = ffi::PA_SEEK_ABSOLUTE, -+ RelativeOnRead = ffi::PA_SEEK_RELATIVE_ON_READ, -+ RelativeEnd = ffi::PA_SEEK_RELATIVE_END, -+} -+ -+impl SeekMode { -+ pub fn try_from(x: ffi::pa_seek_mode_t) -> Option { -+ if x >= ffi::PA_SEEK_RELATIVE && x <= ffi::PA_SEEK_RELATIVE_END { -+ Some(unsafe { ::std::mem::transmute(x) }) -+ } else { -+ None -+ } -+ } -+} -+ -+impl Into for SeekMode { -+ fn into(self) -> ffi::pa_seek_mode_t { -+ self as ffi::pa_seek_mode_t -+ } -+} -+ -+bitflags! { -+ pub flags SinkFlags: u32 { -+ const SINK_HW_VOLUME_CTRL = ffi::PA_SINK_HW_VOLUME_CTRL, -+ const SINK_LATENCY = ffi::PA_SINK_LATENCY, -+ const SINK_HARDWARE = ffi::PA_SINK_HARDWARE, -+ const SINK_NETWORK = ffi::PA_SINK_NETWORK, -+ const SINK_HW_MUTE_CTRL = ffi::PA_SINK_HW_MUTE_CTRL, -+ const SINK_DECIBEL_VOLUME = ffi::PA_SINK_DECIBEL_VOLUME, -+ const SINK_FLAT_VOLUME = ffi::PA_SINK_FLAT_VOLUME, -+ const SINK_DYNAMIC_LATENCY = ffi::PA_SINK_DYNAMIC_LATENCY, -+ const SINK_SET_FORMATS = ffi::PA_SINK_SET_FORMATS, -+ } -+} -+ -+impl SinkFlags { -+ pub fn try_from(x: ffi::pa_sink_flags_t) -> Option { -+ if (x & -+ !(ffi::PA_SOURCE_NOFLAGS | ffi::PA_SOURCE_HW_VOLUME_CTRL | ffi::PA_SOURCE_LATENCY | -+ ffi::PA_SOURCE_HARDWARE | ffi::PA_SOURCE_NETWORK | ffi::PA_SOURCE_HW_MUTE_CTRL | -+ ffi::PA_SOURCE_DECIBEL_VOLUME | -+ ffi::PA_SOURCE_DYNAMIC_LATENCY | ffi::PA_SOURCE_FLAT_VOLUME)) == 0 { -+ Some(unsafe { ::std::mem::transmute(x) }) -+ } else { -+ None -+ } -+ } -+} -+ -+#[repr(i32)] -+#[derive(Clone, Copy, Debug, PartialEq, Eq)] -+pub enum SinkState { -+ InvalidState = ffi::PA_SINK_INVALID_STATE, -+ Running = ffi::PA_SINK_RUNNING, -+ Idle = ffi::PA_SINK_IDLE, -+ Suspended = ffi::PA_SINK_SUSPENDED, -+ Init = ffi::PA_SINK_INIT, -+ Unlinked = ffi::PA_SINK_UNLINKED, -+} -+ -+bitflags!{ -+ pub flags SourceFlags: u32 { -+ const SOURCE_FLAGS_HW_VOLUME_CTRL = ffi::PA_SOURCE_HW_VOLUME_CTRL, -+ const SOURCE_FLAGS_LATENCY = ffi::PA_SOURCE_LATENCY, -+ const SOURCE_FLAGS_HARDWARE = ffi::PA_SOURCE_HARDWARE, -+ const SOURCE_FLAGS_NETWORK = ffi::PA_SOURCE_NETWORK, -+ const SOURCE_FLAGS_HW_MUTE_CTRL = ffi::PA_SOURCE_HW_MUTE_CTRL, -+ const SOURCE_FLAGS_DECIBEL_VOLUME = ffi::PA_SOURCE_DECIBEL_VOLUME, -+ const SOURCE_FLAGS_DYNAMIC_LATENCY = ffi::PA_SOURCE_DYNAMIC_LATENCY, -+ const SOURCE_FLAGS_FLAT_VOLUME = ffi::PA_SOURCE_FLAT_VOLUME, -+ } -+} -+ -+impl Into for SourceFlags { -+ fn into(self) -> ffi::pa_source_flags_t { -+ self.bits() as ffi::pa_source_flags_t -+ } -+} -+ -+#[repr(i32)] -+#[derive(Clone, Copy, Debug, PartialEq, Eq)] -+pub enum SourceState { -+ InvalidState = ffi::PA_SOURCE_INVALID_STATE, -+ Running = ffi::PA_SOURCE_RUNNING, -+ Idle = ffi::PA_SOURCE_IDLE, -+ Suspended = ffi::PA_SOURCE_SUSPENDED, -+ Init = ffi::PA_SOURCE_INIT, -+ Unlinked = ffi::PA_SOURCE_UNLINKED, -+} -+ -+#[repr(i32)] -+#[derive(Clone, Copy, Debug, PartialEq, Eq)] -+pub enum PortAvailable { -+ Unknown = ffi::PA_PORT_AVAILABLE_UNKNOWN, -+ No = ffi::PA_PORT_AVAILABLE_NO, -+ Yes = ffi::PA_PORT_AVAILABLE_YES, -+} -+ -+impl PortAvailable { -+ pub fn try_from(x: ffi::pa_port_available_t) -> Option { -+ if x >= ffi::PA_PORT_AVAILABLE_UNKNOWN && x <= ffi::PA_PORT_AVAILABLE_YES { -+ Some(unsafe { ::std::mem::transmute(x) }) -+ } else { -+ None -+ } -+ } -+} -+ -+impl Into for PortAvailable { -+ fn into(self) -> ffi::pa_port_available_t { -+ self as ffi::pa_port_available_t -+ } -+} -+ -+#[repr(i32)] -+#[derive(Clone, Copy, Debug, PartialEq, Eq)] -+pub enum ChannelPosition { -+ Invalid = ffi::PA_CHANNEL_POSITION_INVALID, -+ Mono = ffi::PA_CHANNEL_POSITION_MONO, -+ FrontLeft = ffi::PA_CHANNEL_POSITION_FRONT_LEFT, -+ FrontRight = ffi::PA_CHANNEL_POSITION_FRONT_RIGHT, -+ FrontCenter = ffi::PA_CHANNEL_POSITION_FRONT_CENTER, -+ RearCenter = ffi::PA_CHANNEL_POSITION_REAR_CENTER, -+ RearLeft = ffi::PA_CHANNEL_POSITION_REAR_LEFT, -+ RearRight = ffi::PA_CHANNEL_POSITION_REAR_RIGHT, -+ LowFreqEffects = ffi::PA_CHANNEL_POSITION_LFE, -+ FrontLeftOfCenter = ffi::PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER, -+ FrontRightOfCenter = ffi::PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER, -+ SideLeft = ffi::PA_CHANNEL_POSITION_SIDE_LEFT, -+ SideRight = ffi::PA_CHANNEL_POSITION_SIDE_RIGHT, -+ Aux0 = ffi::PA_CHANNEL_POSITION_AUX0, -+ Aux1 = ffi::PA_CHANNEL_POSITION_AUX1, -+ Aux2 = ffi::PA_CHANNEL_POSITION_AUX2, -+ Aux3 = ffi::PA_CHANNEL_POSITION_AUX3, -+ Aux4 = ffi::PA_CHANNEL_POSITION_AUX4, -+ Aux5 = ffi::PA_CHANNEL_POSITION_AUX5, -+ Aux6 = ffi::PA_CHANNEL_POSITION_AUX6, -+ Aux7 = ffi::PA_CHANNEL_POSITION_AUX7, -+ Aux8 = ffi::PA_CHANNEL_POSITION_AUX8, -+ Aux9 = ffi::PA_CHANNEL_POSITION_AUX9, -+ Aux10 = ffi::PA_CHANNEL_POSITION_AUX10, -+ Aux11 = ffi::PA_CHANNEL_POSITION_AUX11, -+ Aux12 = ffi::PA_CHANNEL_POSITION_AUX12, -+ Aux13 = ffi::PA_CHANNEL_POSITION_AUX13, -+ Aux14 = ffi::PA_CHANNEL_POSITION_AUX14, -+ Aux15 = ffi::PA_CHANNEL_POSITION_AUX15, -+ Aux16 = ffi::PA_CHANNEL_POSITION_AUX16, -+ Aux17 = ffi::PA_CHANNEL_POSITION_AUX17, -+ Aux18 = ffi::PA_CHANNEL_POSITION_AUX18, -+ Aux19 = ffi::PA_CHANNEL_POSITION_AUX19, -+ Aux20 = ffi::PA_CHANNEL_POSITION_AUX20, -+ Aux21 = ffi::PA_CHANNEL_POSITION_AUX21, -+ Aux22 = ffi::PA_CHANNEL_POSITION_AUX22, -+ Aux23 = ffi::PA_CHANNEL_POSITION_AUX23, -+ Aux24 = ffi::PA_CHANNEL_POSITION_AUX24, -+ Aux25 = ffi::PA_CHANNEL_POSITION_AUX25, -+ Aux26 = ffi::PA_CHANNEL_POSITION_AUX26, -+ Aux27 = ffi::PA_CHANNEL_POSITION_AUX27, -+ Aux28 = ffi::PA_CHANNEL_POSITION_AUX28, -+ Aux29 = ffi::PA_CHANNEL_POSITION_AUX29, -+ Aux30 = ffi::PA_CHANNEL_POSITION_AUX30, -+ Aux31 = ffi::PA_CHANNEL_POSITION_AUX31, -+ TopCenter = ffi::PA_CHANNEL_POSITION_TOP_CENTER, -+ TopFrontLeft = ffi::PA_CHANNEL_POSITION_TOP_FRONT_LEFT, -+ TopFrontRight = ffi::PA_CHANNEL_POSITION_TOP_FRONT_RIGHT, -+ TopFrontCenter = ffi::PA_CHANNEL_POSITION_TOP_FRONT_CENTER, -+ TopRearLeft = ffi::PA_CHANNEL_POSITION_TOP_REAR_LEFT, -+ TopRearRight = ffi::PA_CHANNEL_POSITION_TOP_REAR_RIGHT, -+ TopRearCenter = ffi::PA_CHANNEL_POSITION_TOP_REAR_CENTER, -+} -+ -+impl ChannelPosition { -+ pub fn try_from(x: ffi::pa_channel_position_t) -> Option { -+ if x >= ffi::PA_CHANNEL_POSITION_INVALID && x < ffi::PA_CHANNEL_POSITION_MAX { -+ Some(unsafe { ::std::mem::transmute(x) }) -+ } else { -+ None -+ } -+ } -+} -+ -+impl Default for ChannelPosition { -+ fn default() -> Self { -+ ChannelPosition::Invalid -+ } -+} -+ -+impl Into for ChannelPosition { -+ fn into(self) -> ffi::pa_channel_position_t { -+ self as ffi::pa_channel_position_t -+ } -+} -+pub type Result = ::std::result::Result; -+ -+pub trait CVolumeExt { -+ fn set(&mut self, channels: c_uint, v: Volume); -+ fn set_balance(&mut self, map: &ChannelMap, new_balance: f32); -+} -+ -+impl CVolumeExt for CVolume { -+ fn set(&mut self, channels: c_uint, v: Volume) { -+ unsafe { -+ ffi::pa_cvolume_set(self, channels, v); -+ } -+ } -+ -+ fn set_balance(&mut self, map: &ChannelMap, new_balance: f32) { -+ unsafe { -+ ffi::pa_cvolume_set_balance(self, map, new_balance); -+ } -+ } -+} -+ -+pub trait ChannelMapExt { -+ fn init() -> ChannelMap; -+ fn can_balance(&self) -> bool; -+} -+ -+impl ChannelMapExt for ChannelMap { -+ fn init() -> ChannelMap { -+ let mut cm = ChannelMap::default(); -+ unsafe { -+ ffi::pa_channel_map_init(&mut cm); -+ } -+ cm -+ } -+ fn can_balance(&self) -> bool { -+ unsafe { ffi::pa_channel_map_can_balance(self) > 0 } -+ } -+} -+ -+pub trait ProplistExt { -+ fn proplist(&self) -> Proplist; -+} -+ -+impl ProplistExt for SinkInfo { -+ fn proplist(&self) -> Proplist { -+ unsafe { proplist::from_raw_ptr(self.proplist) } -+ } -+} -+ -+impl ProplistExt for SourceInfo { -+ fn proplist(&self) -> Proplist { -+ unsafe { proplist::from_raw_ptr(self.proplist) } -+ } -+} -+ -+pub trait SampleSpecExt { -+ fn frame_size(&self) -> usize; -+} -+ -+impl SampleSpecExt for SampleSpec { -+ fn frame_size(&self) -> usize { -+ unsafe { ffi::pa_frame_size(self) } -+ } -+} -+ -+pub trait USecExt { -+ fn to_bytes(self, spec: &SampleSpec) -> usize; -+} -+ -+impl USecExt for USec { -+ fn to_bytes(self, spec: &SampleSpec) -> usize { -+ unsafe { ffi::pa_usec_to_bytes(self, spec) } -+ } -+} -+ -+pub fn library_version() -> *const c_char { -+ unsafe { ffi::pa_get_library_version() } -+} -+ -+pub fn sw_volume_from_linear(vol: f64) -> Volume { -+ unsafe { ffi::pa_sw_volume_from_linear(vol) } -+} -+ -+pub fn rtclock_now() -> USec { -+ unsafe { ffi::pa_rtclock_now() } -+} -diff -up firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/mainloop_api.rs.cubeb-pulse-arm firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/mainloop_api.rs ---- firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/mainloop_api.rs.cubeb-pulse-arm 2017-08-04 13:37:46.385821734 +0200 -+++ firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/mainloop_api.rs 2017-08-04 13:37:46.385821734 +0200 -@@ -0,0 +1,58 @@ -+// Copyright © 2017 Mozilla Foundation -+// -+// This program is made available under an ISC-style license. See the -+// accompanying file LICENSE for details. -+ -+use ffi; -+use std::mem; -+use std::os::raw::c_void; -+ -+ -+#[allow(non_camel_case_types)] -+type pa_once_cb_t = Option; -+fn wrap_once_cb(_: F) -> pa_once_cb_t -+ where F: Fn(&MainloopApi, *mut c_void) -+{ -+ assert!(mem::size_of::() == 0); -+ -+ unsafe extern "C" fn wrapped(m: *mut ffi::pa_mainloop_api, userdata: *mut c_void) -+ where F: Fn(&MainloopApi, *mut c_void) -+ { -+ let api = from_raw_ptr(m); -+ let result = mem::transmute::<_, &F>(&())(&api, userdata); -+ mem::forget(api); -+ result -+ } -+ -+ Some(wrapped::) -+} -+ -+pub struct MainloopApi(*mut ffi::pa_mainloop_api); -+ -+impl MainloopApi { -+ pub fn raw_mut(&self) -> &mut ffi::pa_mainloop_api { -+ unsafe { &mut *self.0 } -+ } -+ -+ pub fn once(&self, cb: CB, userdata: *mut c_void) -+ where CB: Fn(&MainloopApi, *mut c_void) -+ { -+ let wrapped = wrap_once_cb(cb); -+ unsafe { -+ ffi::pa_mainloop_api_once(self.raw_mut(), wrapped, userdata); -+ } -+ } -+ -+ pub fn time_free(&self, e: *mut ffi::pa_time_event) { -+ unsafe { -+ if let Some(f) = self.raw_mut().time_free { -+ f(e); -+ } -+ } -+ } -+} -+ -+pub unsafe fn from_raw_ptr(raw: *mut ffi::pa_mainloop_api) -> MainloopApi { -+ MainloopApi(raw) -+} -diff -up firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/operation.rs.cubeb-pulse-arm firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/operation.rs ---- firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/operation.rs.cubeb-pulse-arm 2017-08-04 13:37:46.385821734 +0200 -+++ firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/operation.rs 2017-08-04 13:37:46.385821734 +0200 -@@ -0,0 +1,43 @@ -+// Copyright © 2017 Mozilla Foundation -+// -+// This program is made available under an ISC-style license. See the -+// accompanying file LICENSE for details. -+ -+use ffi; -+ -+#[derive(Debug)] -+pub struct Operation(*mut ffi::pa_operation); -+ -+impl Operation { -+ pub unsafe fn from_raw_ptr(raw: *mut ffi::pa_operation) -> Operation { -+ Operation(raw) -+ } -+ -+ pub fn cancel(&mut self) { -+ unsafe { -+ ffi::pa_operation_cancel(self.0); -+ } -+ } -+ -+ pub fn get_state(&self) -> ffi::pa_operation_state_t { -+ unsafe { ffi::pa_operation_get_state(self.0) } -+ } -+} -+ -+impl Clone for Operation { -+ fn clone(&self) -> Self { -+ Operation(unsafe { ffi::pa_operation_ref(self.0) }) -+ } -+} -+ -+impl Drop for Operation { -+ fn drop(&mut self) { -+ unsafe { -+ ffi::pa_operation_unref(self.0); -+ } -+ } -+} -+ -+pub unsafe fn from_raw_ptr(raw: *mut ffi::pa_operation) -> Operation { -+ Operation::from_raw_ptr(raw) -+} -diff -up firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/proplist.rs.cubeb-pulse-arm firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/proplist.rs ---- firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/proplist.rs.cubeb-pulse-arm 2017-08-04 13:37:46.385821734 +0200 -+++ firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/proplist.rs 2017-08-04 13:37:46.385821734 +0200 -@@ -0,0 +1,31 @@ -+// Copyright © 2017 Mozilla Foundation -+// -+// This program is made available under an ISC-style license. See the -+// accompanying file LICENSE for details. -+ -+use ffi; -+use std::ffi::{CStr, CString}; -+ -+#[derive(Debug)] -+pub struct Proplist(*mut ffi::pa_proplist); -+ -+impl Proplist { -+ pub fn gets(&self, key: T) -> Option<&CStr> -+ where T: Into> -+ { -+ let key = match CString::new(key) { -+ Ok(k) => k, -+ _ => return None, -+ }; -+ let r = unsafe { ffi::pa_proplist_gets(self.0, key.as_ptr()) }; -+ if r.is_null() { -+ None -+ } else { -+ Some(unsafe { CStr::from_ptr(r) }) -+ } -+ } -+} -+ -+pub unsafe fn from_raw_ptr(raw: *mut ffi::pa_proplist) -> Proplist { -+ return Proplist(raw); -+} -diff -up firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/stream.rs.cubeb-pulse-arm firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/stream.rs ---- firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/stream.rs.cubeb-pulse-arm 2017-08-04 13:37:46.386821731 +0200 -+++ firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/stream.rs 2017-08-04 13:37:46.386821731 +0200 -@@ -0,0 +1,367 @@ -+// Copyright © 2017 Mozilla Foundation -+// -+// This program is made available under an ISC-style license. See the -+// accompanying file LICENSE for details. -+ -+use ::*; -+use context; -+use ffi; -+use operation; -+use std::ffi::CStr; -+use std::mem; -+use std::os::raw::{c_int, c_void}; -+use std::ptr; -+use util::*; -+ -+#[derive(Debug)] -+pub struct Stream(*mut ffi::pa_stream); -+ -+impl Stream { -+ pub fn new<'a, CM>(c: &Context, name: &::std::ffi::CStr, ss: &SampleSpec, map: CM) -> Option -+ where CM: Into> -+ { -+ let ptr = unsafe { -+ ffi::pa_stream_new(c.raw_mut(), -+ name.as_ptr(), -+ ss as *const _, -+ to_ptr(map.into())) -+ }; -+ if ptr.is_null() { -+ None -+ } else { -+ Some(Stream(ptr)) -+ } -+ } -+ -+ #[doc(hidden)] -+ pub fn raw_mut(&self) -> &mut ffi::pa_stream { -+ unsafe { &mut *self.0 } -+ } -+ -+ pub fn unref(self) { -+ unsafe { -+ ffi::pa_stream_unref(self.raw_mut()); -+ } -+ } -+ -+ pub fn get_state(&self) -> StreamState { -+ StreamState::try_from(unsafe { -+ ffi::pa_stream_get_state(self.raw_mut()) -+ }).expect("pa_stream_get_state returned invalid StreamState") -+ } -+ -+ pub fn get_context(&self) -> Option { -+ let ptr = unsafe { ffi::pa_stream_get_context(self.raw_mut()) }; -+ if ptr.is_null() { -+ return None; -+ } -+ -+ let ctx = unsafe { context::from_raw_ptr(ptr) }; -+ Some(ctx) -+ } -+ -+ pub fn get_index(&self) -> u32 { -+ unsafe { ffi::pa_stream_get_index(self.raw_mut()) } -+ } -+ -+ pub fn get_device_name<'a>(&'a self) -> Result<&'a CStr> { -+ let r = unsafe { ffi::pa_stream_get_device_name(self.raw_mut()) }; -+ if r.is_null() { -+ let err = if let Some(c) = self.get_context() { -+ c.errno() -+ } else { -+ ffi::PA_ERR_UNKNOWN -+ }; -+ return Err(ErrorCode::from_error_code(err)); -+ } -+ Ok(unsafe { CStr::from_ptr(r) }) -+ } -+ -+ pub fn is_suspended(&self) -> Result { -+ let r = unsafe { ffi::pa_stream_is_suspended(self.raw_mut()) }; -+ error_result!(r != 0, r) -+ } -+ -+ pub fn is_corked(&self) -> Result { -+ let r = unsafe { ffi::pa_stream_is_corked(self.raw_mut()) }; -+ error_result!(r != 0, r) -+ } -+ -+ pub fn connect_playback<'a, D, A, V, S>(&self, -+ dev: D, -+ attr: A, -+ flags: StreamFlags, -+ volume: V, -+ sync_stream: S) -+ -> Result<()> -+ where D: Into>, -+ A: Into>, -+ V: Into>, -+ S: Into> -+ { -+ let r = unsafe { -+ ffi::pa_stream_connect_playback(self.raw_mut(), -+ str_to_ptr(dev.into()), -+ to_ptr(attr.into()), -+ flags.into(), -+ to_ptr(volume.into()), -+ map_to_mut_ptr(sync_stream.into(), |p| p.0)) -+ }; -+ error_result!((), r) -+ } -+ -+ pub fn connect_record<'a, D, A>(&self, dev: D, attr: A, flags: StreamFlags) -> Result<()> -+ where D: Into>, -+ A: Into> -+ { -+ let r = unsafe { -+ ffi::pa_stream_connect_record(self.raw_mut(), -+ str_to_ptr(dev.into()), -+ to_ptr(attr.into()), -+ flags.into()) -+ }; -+ error_result!((), r) -+ } -+ -+ pub fn disconnect(&self) -> Result<()> { -+ let r = unsafe { ffi::pa_stream_disconnect(self.raw_mut()) }; -+ error_result!((), r) -+ } -+ -+ pub fn begin_write(&self, req_bytes: usize) -> Result<(*mut c_void, usize)> { -+ let mut data: *mut c_void = ptr::null_mut(); -+ let mut nbytes = req_bytes; -+ let r = unsafe { ffi::pa_stream_begin_write(self.raw_mut(), &mut data, &mut nbytes) }; -+ error_result!((data, nbytes), r) -+ } -+ -+ pub fn cancel_write(&self) -> Result<()> { -+ let r = unsafe { ffi::pa_stream_cancel_write(self.raw_mut()) }; -+ error_result!((), r) -+ } -+ -+ pub fn write(&self, data: *const c_void, nbytes: usize, offset: i64, seek: SeekMode) -> Result<()> { -+ let r = unsafe { ffi::pa_stream_write(self.raw_mut(), data, nbytes, None, offset, seek.into()) }; -+ error_result!((), r) -+ } -+ -+ pub unsafe fn peek(&self, data: *mut *const c_void, length: *mut usize) -> Result<()> { -+ let r = ffi::pa_stream_peek(self.raw_mut(), data, length); -+ error_result!((), r) -+ } -+ -+ pub fn drop(&self) -> Result<()> { -+ let r = unsafe { ffi::pa_stream_drop(self.raw_mut()) }; -+ error_result!((), r) -+ } -+ -+ pub fn writable_size(&self) -> Result { -+ let r = unsafe { ffi::pa_stream_writable_size(self.raw_mut()) }; -+ if r == ::std::usize::MAX { -+ let err = if let Some(c) = self.get_context() { -+ c.errno() -+ } else { -+ ffi::PA_ERR_UNKNOWN -+ }; -+ return Err(ErrorCode::from_error_code(err)); -+ } -+ Ok(r) -+ } -+ -+ pub fn readable_size(&self) -> Result { -+ let r = unsafe { ffi::pa_stream_readable_size(self.raw_mut()) }; -+ if r == ::std::usize::MAX { -+ let err = if let Some(c) = self.get_context() { -+ c.errno() -+ } else { -+ ffi::PA_ERR_UNKNOWN -+ }; -+ return Err(ErrorCode::from_error_code(err)); -+ } -+ Ok(r) -+ } -+ -+ pub fn update_timing_info(&self, _: CB, userdata: *mut c_void) -> Result -+ where CB: Fn(&Stream, i32, *mut c_void) -+ { -+ debug_assert_eq!(mem::size_of::(), 0); -+ -+ // See: A note about `wrapped` functions -+ unsafe extern "C" fn wrapped(s: *mut ffi::pa_stream, success: c_int, userdata: *mut c_void) -+ where F: Fn(&Stream, i32, *mut c_void) -+ { -+ use std::mem::{forget, uninitialized}; -+ let mut stm = stream::from_raw_ptr(s); -+ let result = uninitialized::()(&mut stm, success, userdata); -+ forget(stm); -+ -+ result -+ } -+ -+ let r = unsafe { ffi::pa_stream_update_timing_info(self.raw_mut(), Some(wrapped::), userdata) }; -+ if r.is_null() { -+ let err = if let Some(c) = self.get_context() { -+ c.errno() -+ } else { -+ ffi::PA_ERR_UNKNOWN -+ }; -+ return Err(ErrorCode::from_error_code(err)); -+ } -+ Ok(unsafe { operation::from_raw_ptr(r) }) -+ } -+ -+ pub fn clear_state_callback(&self) { -+ unsafe { -+ ffi::pa_stream_set_state_callback(self.raw_mut(), None, ptr::null_mut()); -+ } -+ } -+ -+ pub fn set_state_callback(&self, _: CB, userdata: *mut c_void) -+ where CB: Fn(&Stream, *mut c_void) -+ { -+ debug_assert_eq!(mem::size_of::(), 0); -+ -+ // See: A note about `wrapped` functions -+ unsafe extern "C" fn wrapped(s: *mut ffi::pa_stream, userdata: *mut c_void) -+ where F: Fn(&Stream, *mut c_void) -+ { -+ use std::mem::{forget, uninitialized}; -+ let mut stm = stream::from_raw_ptr(s); -+ let result = uninitialized::()(&mut stm, userdata); -+ forget(stm); -+ -+ result -+ } -+ -+ unsafe { -+ ffi::pa_stream_set_state_callback(self.raw_mut(), Some(wrapped::), userdata); -+ } -+ } -+ -+ pub fn clear_write_callback(&self) { -+ unsafe { -+ ffi::pa_stream_set_write_callback(self.raw_mut(), None, ptr::null_mut()); -+ } -+ } -+ -+ pub fn set_write_callback(&self, _: CB, userdata: *mut c_void) -+ where CB: Fn(&Stream, usize, *mut c_void) -+ { -+ debug_assert_eq!(mem::size_of::(), 0); -+ -+ // See: A note about `wrapped` functions -+ unsafe extern "C" fn wrapped(s: *mut ffi::pa_stream, nbytes: usize, userdata: *mut c_void) -+ where F: Fn(&Stream, usize, *mut c_void) -+ { -+ use std::mem::{forget, uninitialized}; -+ let mut stm = stream::from_raw_ptr(s); -+ let result = uninitialized::()(&mut stm, nbytes, userdata); -+ forget(stm); -+ -+ result -+ } -+ -+ unsafe { -+ ffi::pa_stream_set_write_callback(self.raw_mut(), Some(wrapped::), userdata); -+ } -+ } -+ -+ pub fn clear_read_callback(&self) { -+ unsafe { -+ ffi::pa_stream_set_read_callback(self.raw_mut(), None, ptr::null_mut()); -+ } -+ } -+ -+ pub fn set_read_callback(&self, _: CB, userdata: *mut c_void) -+ where CB: Fn(&Stream, usize, *mut c_void) -+ { -+ debug_assert_eq!(mem::size_of::(), 0); -+ -+ // See: A note about `wrapped` functions -+ unsafe extern "C" fn wrapped(s: *mut ffi::pa_stream, nbytes: usize, userdata: *mut c_void) -+ where F: Fn(&Stream, usize, *mut c_void) -+ { -+ use std::mem::{forget, uninitialized}; -+ let mut stm = stream::from_raw_ptr(s); -+ let result = uninitialized::()(&mut stm, nbytes, userdata); -+ forget(stm); -+ -+ result -+ } -+ -+ unsafe { -+ ffi::pa_stream_set_read_callback(self.raw_mut(), Some(wrapped::), userdata); -+ } -+ } -+ -+ pub fn cork(&self, b: i32, _: CB, userdata: *mut c_void) -> Result -+ where CB: Fn(&Stream, i32, *mut c_void) -+ { -+ debug_assert_eq!(mem::size_of::(), 0); -+ -+ // See: A note about `wrapped` functions -+ unsafe extern "C" fn wrapped(s: *mut ffi::pa_stream, success: c_int, userdata: *mut c_void) -+ where F: Fn(&Stream, i32, *mut c_void) -+ { -+ use std::mem::{forget, uninitialized}; -+ let mut stm = stream::from_raw_ptr(s); -+ let result = uninitialized::()(&mut stm, success, userdata); -+ forget(stm); -+ -+ result -+ } -+ -+ let r = unsafe { ffi::pa_stream_cork(self.raw_mut(), b, Some(wrapped::), userdata) }; -+ if r.is_null() { -+ let err = if let Some(c) = self.get_context() { -+ c.errno() -+ } else { -+ ffi::PA_ERR_UNKNOWN -+ }; -+ return Err(ErrorCode::from_error_code(err)); -+ } -+ Ok(unsafe { operation::from_raw_ptr(r) }) -+ } -+ -+ pub fn get_time(&self) -> Result<(u64)> { -+ let mut usec: u64 = 0; -+ let r = unsafe { ffi::pa_stream_get_time(self.raw_mut(), &mut usec) }; -+ error_result!(usec, r) -+ } -+ -+ pub fn get_latency(&self) -> Result<(u64, bool)> { -+ let mut usec: u64 = 0; -+ let mut negative: i32 = 0; -+ let r = unsafe { ffi::pa_stream_get_latency(self.raw_mut(), &mut usec, &mut negative) }; -+ error_result!((usec, negative != 0), r) -+ } -+ -+ pub fn get_sample_spec(&self) -> &SampleSpec { -+ unsafe { -+ let ptr = ffi::pa_stream_get_sample_spec(self.raw_mut()); -+ debug_assert!(!ptr.is_null()); -+ &*ptr -+ } -+ } -+ -+ pub fn get_channel_map(&self) -> &ChannelMap { -+ unsafe { -+ let ptr = ffi::pa_stream_get_channel_map(self.raw_mut()); -+ debug_assert!(!ptr.is_null()); -+ &*ptr -+ } -+ } -+ -+ pub fn get_buffer_attr(&self) -> &BufferAttr { -+ unsafe { -+ let ptr = ffi::pa_stream_get_buffer_attr(self.raw_mut()); -+ debug_assert!(!ptr.is_null()); -+ &*ptr -+ } -+ } -+} -+ -+#[doc(hidden)] -+pub unsafe fn from_raw_ptr(ptr: *mut ffi::pa_stream) -> Stream { -+ Stream(ptr) -+} -diff -up firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/threaded_mainloop.rs.cubeb-pulse-arm firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/threaded_mainloop.rs ---- firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/threaded_mainloop.rs.cubeb-pulse-arm 2017-08-04 13:37:46.386821731 +0200 -+++ firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/threaded_mainloop.rs 2017-08-04 13:37:46.386821731 +0200 -@@ -0,0 +1,92 @@ -+// Copyright © 2017 Mozilla Foundation -+// -+// This program is made available under an ISC-style license. See the -+// accompanying file LICENSE for details. -+ -+use ErrorCode; -+use Result; -+use ffi; -+use mainloop_api; -+use mainloop_api::MainloopApi; -+ -+#[derive(Debug)] -+pub struct ThreadedMainloop(*mut ffi::pa_threaded_mainloop); -+ -+impl ThreadedMainloop { -+ pub unsafe fn from_raw_ptr(raw: *mut ffi::pa_threaded_mainloop) -> Self { -+ ThreadedMainloop(raw) -+ } -+ -+ pub fn new() -> Self { -+ unsafe { ThreadedMainloop::from_raw_ptr(ffi::pa_threaded_mainloop_new()) } -+ } -+ -+ pub fn raw_mut(&self) -> &mut ffi::pa_threaded_mainloop { -+ unsafe { &mut *self.0 } -+ } -+ -+ pub fn is_null(&self) -> bool { -+ self.0.is_null() -+ } -+ -+ pub fn start(&self) -> Result<()> { -+ match unsafe { ffi::pa_threaded_mainloop_start(self.raw_mut()) } { -+ 0 => Ok(()), -+ _ => Err(ErrorCode::from_error_code(ffi::PA_ERR_UNKNOWN)), -+ } -+ } -+ -+ pub fn stop(&self) { -+ unsafe { -+ ffi::pa_threaded_mainloop_stop(self.raw_mut()); -+ } -+ } -+ -+ pub fn lock(&self) { -+ unsafe { -+ ffi::pa_threaded_mainloop_lock(self.raw_mut()); -+ } -+ } -+ -+ pub fn unlock(&self) { -+ unsafe { -+ ffi::pa_threaded_mainloop_unlock(self.raw_mut()); -+ } -+ } -+ -+ pub fn wait(&self) { -+ unsafe { -+ ffi::pa_threaded_mainloop_wait(self.raw_mut()); -+ } -+ } -+ -+ pub fn signal(&self) { -+ unsafe { -+ ffi::pa_threaded_mainloop_signal(self.raw_mut(), 0); -+ } -+ } -+ -+ pub fn get_api(&self) -> MainloopApi { -+ unsafe { mainloop_api::from_raw_ptr(ffi::pa_threaded_mainloop_get_api(self.raw_mut())) } -+ } -+ -+ pub fn in_thread(&self) -> bool { -+ unsafe { ffi::pa_threaded_mainloop_in_thread(self.raw_mut()) != 0 } -+ } -+} -+ -+impl ::std::default::Default for ThreadedMainloop { -+ fn default() -> Self { -+ ThreadedMainloop(::std::ptr::null_mut()) -+ } -+} -+ -+impl ::std::ops::Drop for ThreadedMainloop { -+ fn drop(&mut self) { -+ if !self.is_null() { -+ unsafe { -+ ffi::pa_threaded_mainloop_free(self.raw_mut()); -+ } -+ } -+ } -+} -diff -up firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/util.rs.cubeb-pulse-arm firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/util.rs ---- firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/util.rs.cubeb-pulse-arm 2017-08-04 13:37:46.386821731 +0200 -+++ firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/util.rs 2017-08-04 13:37:46.386821731 +0200 -@@ -0,0 +1,41 @@ -+// Copyright © 2017 Mozilla Foundation -+// -+// This program is made available under an ISC-style license. See the -+// accompanying file LICENSE for details. -+ -+use std::ffi::CStr; -+use std::os::raw::c_char; -+use std::ptr; -+ -+pub trait UnwrapCStr { -+ fn unwrap_cstr(self) -> *const c_char; -+} -+ -+impl<'a, U> UnwrapCStr for U -+ where U: Into> -+{ -+ fn unwrap_cstr(self) -> *const c_char { -+ self.into().map(|o| o.as_ptr()).unwrap_or(0 as *const _) -+ } -+} -+ -+pub fn map_to_mut_ptr *mut U>(t: Option<&mut T>, f: F) -> *mut U { -+ match t { -+ Some(x) => f(x), -+ None => ptr::null_mut(), -+ } -+} -+ -+pub fn str_to_ptr(s: Option<&CStr>) -> *const c_char { -+ match s { -+ Some(x) => x.as_ptr(), -+ None => ptr::null(), -+ } -+} -+ -+pub fn to_ptr(t: Option<&T>) -> *const T { -+ match t { -+ Some(x) => x as *const T, -+ None => ptr::null(), -+ } -+} -diff -up firefox-55.0/media/libcubeb/cubeb-pulse-rs/README.md.cubeb-pulse-arm firefox-55.0/media/libcubeb/cubeb-pulse-rs/README.md ---- firefox-55.0/media/libcubeb/cubeb-pulse-rs/README.md.cubeb-pulse-arm 2017-07-31 18:20:49.000000000 +0200 -+++ firefox-55.0/media/libcubeb/cubeb-pulse-rs/README.md 2017-08-04 13:37:46.383821740 +0200 -@@ -3,3 +3,4 @@ - Implementation of PulseAudio backend for Cubeb written in Rust. - - [![Travis Build Status](https://travis-ci.org/djg/cubeb-pulse-rs.svg?branch=master)](https://travis-ci.org/djg/cubeb-pulse-rs) -+[![Travis Build Status](https://travis-ci.org/djg/cubeb-pulse-rs.svg?branch=dev)](https://travis-ci.org/djg/cubeb-pulse-rs) -diff -up firefox-55.0/media/libcubeb/cubeb-pulse-rs/README_MOZILLA.cubeb-pulse-arm firefox-55.0/media/libcubeb/cubeb-pulse-rs/README_MOZILLA ---- firefox-55.0/media/libcubeb/cubeb-pulse-rs/README_MOZILLA.cubeb-pulse-arm 2017-07-31 18:20:49.000000000 +0200 -+++ firefox-55.0/media/libcubeb/cubeb-pulse-rs/README_MOZILLA 2017-08-04 13:37:46.383821740 +0200 -@@ -5,4 +5,4 @@ Makefile.in build files for the Mozilla - - The cubeb-pulse-rs git repository is: https://github.com/djg/cubeb-pulse-rs.git - --The git commit ID used was dbcd7f96aea8d249a4b78f9a7597768c9dff22eb (2017-04-25 11:42:10 +1000) -+The git commit ID used was 64515819cdf54a16626df5dce5f5c7cb1220d53b (2017-06-19 17:41:30 +1000) -diff -up firefox-55.0/media/libcubeb/cubeb-pulse-rs/src/backend/context.rs.cubeb-pulse-arm firefox-55.0/media/libcubeb/cubeb-pulse-rs/src/backend/context.rs ---- firefox-55.0/media/libcubeb/cubeb-pulse-rs/src/backend/context.rs.cubeb-pulse-arm 2017-07-31 18:20:49.000000000 +0200 -+++ firefox-55.0/media/libcubeb/cubeb-pulse-rs/src/backend/context.rs 2017-08-04 13:50:38.145480458 +0200 -@@ -4,67 +4,60 @@ - // accompanying file LICENSE for details. - - use backend::*; --use backend::cork_state::CorkState; - use capi::PULSE_OPS; - use cubeb; -+use pulse::{self, ProplistExt}; - use pulse_ffi::*; - use semver; - use std::default::Default; --use std::ffi::CStr; -+use std::ffi::{CStr, CString}; - use std::mem; --use std::os::raw::{c_char, c_int, c_void}; -+use std::os::raw::{c_char, c_void}; - use std::ptr; - --macro_rules! dup_str { -- ($Dst: expr, $Src: expr) => { -- if !$Dst.is_null() { -- pa_xfree($Dst as *mut _); -- } -- -- $Dst = pa_xstrdup($Src); -- } --} -- --fn pa_channel_to_cubeb_channel(channel: pa_channel_position_t) -> cubeb::Channel { -- assert_ne!(channel, PA_CHANNEL_POSITION_INVALID); -+fn pa_channel_to_cubeb_channel(channel: pulse::ChannelPosition) -> cubeb::Channel { -+ use pulse::ChannelPosition; -+ assert_ne!(channel, ChannelPosition::Invalid); - match channel { -- PA_CHANNEL_POSITION_MONO => cubeb::CHANNEL_MONO, -- PA_CHANNEL_POSITION_FRONT_LEFT => cubeb::CHANNEL_LEFT, -- PA_CHANNEL_POSITION_FRONT_RIGHT => cubeb::CHANNEL_RIGHT, -- PA_CHANNEL_POSITION_FRONT_CENTER => cubeb::CHANNEL_CENTER, -- PA_CHANNEL_POSITION_SIDE_LEFT => cubeb::CHANNEL_LS, -- PA_CHANNEL_POSITION_SIDE_RIGHT => cubeb::CHANNEL_RS, -- PA_CHANNEL_POSITION_REAR_LEFT => cubeb::CHANNEL_RLS, -- PA_CHANNEL_POSITION_REAR_CENTER => cubeb::CHANNEL_RCENTER, -- PA_CHANNEL_POSITION_REAR_RIGHT => cubeb::CHANNEL_RRS, -- PA_CHANNEL_POSITION_LFE => cubeb::CHANNEL_LFE, -+ ChannelPosition::Mono => cubeb::CHANNEL_MONO, -+ ChannelPosition::FrontLeft => cubeb::CHANNEL_LEFT, -+ ChannelPosition::FrontRight => cubeb::CHANNEL_RIGHT, -+ ChannelPosition::FrontCenter => cubeb::CHANNEL_CENTER, -+ ChannelPosition::SideLeft => cubeb::CHANNEL_LS, -+ ChannelPosition::SideRight => cubeb::CHANNEL_RS, -+ ChannelPosition::RearLeft => cubeb::CHANNEL_RLS, -+ ChannelPosition::RearCenter => cubeb::CHANNEL_RCENTER, -+ ChannelPosition::RearRight => cubeb::CHANNEL_RRS, -+ ChannelPosition::LowFreqEffects => cubeb::CHANNEL_LFE, - _ => cubeb::CHANNEL_INVALID, - } - } - --fn channel_map_to_layout(cm: &pa_channel_map) -> cubeb::ChannelLayout { -+fn channel_map_to_layout(cm: &pulse::ChannelMap) -> cubeb::ChannelLayout { -+ use pulse::ChannelPosition; - let mut cubeb_map: cubeb::ChannelMap = Default::default(); - cubeb_map.channels = cm.channels as u32; - for i in 0usize..cm.channels as usize { -- cubeb_map.map[i] = pa_channel_to_cubeb_channel(cm.map[i]); -+ cubeb_map.map[i] = pa_channel_to_cubeb_channel(ChannelPosition::try_from(cm.map[i]) -+ .unwrap_or(ChannelPosition::Invalid)); - } - unsafe { cubeb::cubeb_channel_map_to_layout(&cubeb_map) } - } - - #[derive(Debug)] - pub struct DefaultInfo { -- pub sample_spec: pa_sample_spec, -- pub channel_map: pa_channel_map, -- pub flags: pa_sink_flags_t, -+ pub sample_spec: pulse::SampleSpec, -+ pub channel_map: pulse::ChannelMap, -+ pub flags: pulse::SinkFlags, - } - - #[derive(Debug)] - pub struct Context { - pub ops: *const cubeb::Ops, -- pub mainloop: *mut pa_threaded_mainloop, -- pub context: *mut pa_context, -+ pub mainloop: pulse::ThreadedMainloop, -+ pub context: Option, - pub default_sink_info: Option, -- pub context_name: *const c_char, -+ pub context_name: Option, - pub collection_changed_callback: cubeb::DeviceCollectionChangedCallback, - pub collection_changed_user_ptr: *mut c_void, - pub error: bool, -@@ -82,7 +75,7 @@ impl Drop for Context { - - impl Context { - #[cfg(feature = "pulse-dlopen")] -- fn _new(name: *const i8) -> Result> { -+ fn _new(name: Option) -> Result> { - let libpulse = unsafe { open() }; - if libpulse.is_none() { - return Err(cubeb::ERROR); -@@ -91,12 +84,12 @@ impl Context { - let ctx = Box::new(Context { - ops: &PULSE_OPS, - libpulse: libpulse.unwrap(), -- mainloop: unsafe { pa_threaded_mainloop_new() }, -- context: 0 as *mut _, -+ mainloop: pulse::ThreadedMainloop::new(), -+ context: None, - default_sink_info: None, - context_name: name, - collection_changed_callback: None, -- collection_changed_user_ptr: 0 as *mut _, -+ collection_changed_user_ptr: ptr::null_mut(), - error: true, - version_0_9_8: false, - version_2_0_0: false, -@@ -106,15 +99,15 @@ impl Context { - } - - #[cfg(not(feature = "pulse-dlopen"))] -- fn _new(name: *const i8) -> Result> { -+ fn _new(name: Option) -> Result> { - Ok(Box::new(Context { - ops: &PULSE_OPS, -- mainloop: unsafe { pa_threaded_mainloop_new() }, -- context: 0 as *mut _, -+ mainloop: pulse::ThreadedMainloop::new(), -+ context: None, - default_sink_info: None, - context_name: name, - collection_changed_callback: None, -- collection_changed_user_ptr: 0 as *mut _, -+ collection_changed_user_ptr: ptr::null_mut(), - error: true, - version_0_9_8: false, - version_2_0_0: false, -@@ -122,53 +115,66 @@ impl Context { - } - - pub fn new(name: *const c_char) -> Result> { -+ fn server_info_cb(context: &pulse::Context, info: &pulse::ServerInfo, u: *mut c_void) { -+ fn sink_info_cb(_: &pulse::Context, i: *const pulse::SinkInfo, eol: i32, u: *mut c_void) { -+ let mut ctx = unsafe { &mut *(u as *mut Context) }; -+ if eol == 0 { -+ let info = unsafe { &*i }; -+ let flags = pulse::SinkFlags::try_from(info.flags).expect("SinkInfo contains invalid flags"); -+ ctx.default_sink_info = Some(DefaultInfo { -+ sample_spec: info.sample_spec, -+ channel_map: info.channel_map, -+ flags: flags, -+ }); -+ } -+ ctx.mainloop.signal(); -+ } -+ -+ let _ = context.get_sink_info_by_name(unsafe { CStr::from_ptr(info.default_sink_name) }, -+ sink_info_cb, -+ u); -+ } -+ -+ let name = super::try_cstr_from(name).map(|s| s.to_owned()); - let mut ctx = try!(Context::_new(name)); - -- unsafe { pa_threaded_mainloop_start(ctx.mainloop) }; -+ if ctx.mainloop.start().is_err() { -+ ctx.destroy(); -+ return Err(cubeb::ERROR); -+ } - -- if ctx.pulse_context_init() != cubeb::OK { -+ if ctx.context_init() != cubeb::OK { - ctx.destroy(); - return Err(cubeb::ERROR); - } - -- unsafe { -- /* server_info_callback performs a second async query, -- * which is responsible for initializing default_sink_info -- * and signalling the mainloop to end the wait. */ -- pa_threaded_mainloop_lock(ctx.mainloop); -- let o = pa_context_get_server_info(ctx.context, -- Some(server_info_callback), -- ctx.as_mut() as *mut Context as *mut _); -- if !o.is_null() { -- ctx.operation_wait(ptr::null_mut(), o); -- pa_operation_unref(o); -+ ctx.mainloop.lock(); -+ /* server_info_callback performs a second async query, -+ * which is responsible for initializing default_sink_info -+ * and signalling the mainloop to end the wait. */ -+ let user_data: *mut c_void = ctx.as_mut() as *mut _ as *mut _; -+ if let Some(ref context) = ctx.context { -+ if let Ok(o) = context.get_server_info(server_info_cb, user_data) { -+ ctx.operation_wait(None, &o); - } -- pa_threaded_mainloop_unlock(ctx.mainloop); -- assert!(ctx.default_sink_info.is_some()); - } -+ assert!(ctx.default_sink_info.is_some()); -+ ctx.mainloop.unlock(); - - // Return the result. - Ok(ctx) - } - - pub fn destroy(&mut self) { -- if !self.context.is_null() { -- unsafe { self.pulse_context_destroy() }; -- } -- assert!(self.context.is_null()); -+ self.context_destroy(); - - if !self.mainloop.is_null() { -- unsafe { -- pa_threaded_mainloop_stop(self.mainloop); -- pa_threaded_mainloop_free(self.mainloop); -- self.mainloop = ptr::null_mut(); -- } -+ self.mainloop.stop(); - } -- assert!(self.mainloop.is_null()); - } - - pub fn new_stream(&mut self, -- stream_name: *const c_char, -+ stream_name: &CStr, - input_device: cubeb::DeviceId, - input_stream_params: Option, - output_device: cubeb::DeviceId, -@@ -178,7 +184,7 @@ impl Context { - state_callback: cubeb::StateCallback, - user_ptr: *mut c_void) - -> Result> { -- if self.error && self.pulse_context_init() != 0 { -+ if self.error && self.context_init() != 0 { - return Err(cubeb::ERROR); - } - -@@ -221,41 +227,151 @@ impl Context { - } - - pub fn enumerate_devices(&self, devtype: cubeb::DeviceType) -> Result { -- let mut user_data: PulseDevListData = Default::default(); -- user_data.context = self as *const _ as *mut _; -+ fn add_output_device(_: &pulse::Context, i: *const pulse::SinkInfo, eol: i32, user_data: *mut c_void) { -+ if eol != 0 { -+ return; -+ } - -- unsafe { -- pa_threaded_mainloop_lock(self.mainloop); -+ debug_assert!(!i.is_null()); -+ debug_assert!(!user_data.is_null()); -+ -+ let mut list_data = unsafe { &mut *(user_data as *mut PulseDevListData) }; -+ let info = unsafe { &*i }; -+ -+ let group_id = match info.proplist().gets("sysfs.path") { -+ Some(p) => p.to_owned().into_raw(), -+ _ => ptr::null_mut(), -+ }; -+ -+ let vendor_name = match info.proplist().gets("device.vendor.name") { -+ Some(p) => p.to_owned().into_raw(), -+ _ => ptr::null_mut(), -+ }; -+ -+ let info_name = unsafe { CStr::from_ptr(info.name) }.to_owned(); -+ let info_description = unsafe { CStr::from_ptr(info.description) }.to_owned(); -+ -+ let preferred = if info_name == list_data.default_sink_name { -+ cubeb::DEVICE_PREF_ALL -+ } else { -+ cubeb::DevicePref::empty() -+ }; -+ -+ let ctx = &(*list_data.context); -+ -+ let device_id = info_name.into_raw(); -+ let friendly_name = info_description.into_raw(); -+ let devinfo = cubeb::DeviceInfo { -+ device_id: device_id, -+ devid: device_id as cubeb::DeviceId, -+ friendly_name: friendly_name, -+ group_id: group_id, -+ vendor_name: vendor_name, -+ devtype: cubeb::DEVICE_TYPE_OUTPUT, -+ state: ctx.state_from_port(info.active_port), -+ preferred: preferred, -+ format: cubeb::DeviceFmt::all(), -+ default_format: pulse_format_to_cubeb_format(info.sample_spec.format), -+ max_channels: info.channel_map.channels as u32, -+ min_rate: 1, -+ max_rate: PA_RATE_MAX, -+ default_rate: info.sample_spec.rate, -+ latency_lo: 0, -+ latency_hi: 0, -+ }; -+ list_data.devinfo.push(devinfo); -+ -+ ctx.mainloop.signal(); -+ } -+ -+ fn add_input_device(_: &pulse::Context, i: *const pulse::SourceInfo, eol: i32, user_data: *mut c_void) { -+ if eol != 0 { -+ return; -+ } -+ -+ debug_assert!(!user_data.is_null()); -+ debug_assert!(!i.is_null()); -+ -+ let mut list_data = unsafe { &mut *(user_data as *mut PulseDevListData) }; -+ let info = unsafe { &*i }; -+ -+ let group_id = match info.proplist().gets("sysfs.path") { -+ Some(p) => p.to_owned().into_raw(), -+ _ => ptr::null_mut(), -+ }; -+ -+ let vendor_name = match info.proplist().gets("device.vendor.name") { -+ Some(p) => p.to_owned().into_raw(), -+ _ => ptr::null_mut(), -+ }; - -- let o = pa_context_get_server_info(self.context, -- Some(pulse_server_info_cb), -- &mut user_data as *mut _ as *mut _); -- if !o.is_null() { -- self.operation_wait(ptr::null_mut(), o); -- pa_operation_unref(o); -+ let info_name = unsafe { CStr::from_ptr(info.name) }.to_owned(); -+ let info_description = unsafe { CStr::from_ptr(info.description) }.to_owned(); -+ -+ let preferred = if info_name == list_data.default_source_name { -+ cubeb::DEVICE_PREF_ALL -+ } else { -+ cubeb::DevicePref::empty() -+ }; -+ -+ let ctx = &(*list_data.context); -+ let device_id = info_name.into_raw(); -+ let friendly_name = info_description.into_raw(); -+ let devinfo = cubeb::DeviceInfo { -+ device_id: device_id, -+ devid: device_id as cubeb::DeviceId, -+ friendly_name: friendly_name, -+ group_id: group_id, -+ vendor_name: vendor_name, -+ devtype: cubeb::DEVICE_TYPE_INPUT, -+ state: ctx.state_from_port(info.active_port), -+ preferred: preferred, -+ format: cubeb::DeviceFmt::all(), -+ default_format: pulse_format_to_cubeb_format(info.sample_spec.format), -+ max_channels: info.channel_map.channels as u32, -+ min_rate: 1, -+ max_rate: PA_RATE_MAX, -+ default_rate: info.sample_spec.rate, -+ latency_lo: 0, -+ latency_hi: 0, -+ }; -+ -+ list_data.devinfo.push(devinfo); -+ -+ ctx.mainloop.signal(); -+ } -+ -+ fn default_device_names(_: &pulse::Context, info: &pulse::ServerInfo, user_data: *mut c_void) { -+ let list_data = unsafe { &mut *(user_data as *mut PulseDevListData) }; -+ -+ list_data.default_sink_name = unsafe { CStr::from_ptr(info.default_sink_name) }.to_owned(); -+ list_data.default_source_name = unsafe { CStr::from_ptr(info.default_source_name) }.to_owned(); -+ -+ (*list_data.context).mainloop.signal(); -+ } -+ -+ let mut user_data = PulseDevListData::new(self); -+ -+ if let Some(ref context) = self.context { -+ self.mainloop.lock(); -+ -+ if let Ok(o) = context.get_server_info(default_device_names, &mut user_data as *mut _ as *mut _) { -+ self.operation_wait(None, &o); - } - - if devtype == cubeb::DEVICE_TYPE_OUTPUT { -- let o = pa_context_get_sink_info_list(self.context, -- Some(pulse_sink_info_cb), -- &mut user_data as *mut _ as *mut _); -- if !o.is_null() { -- self.operation_wait(ptr::null_mut(), o); -- pa_operation_unref(o); -+ if let Ok(o) = context.get_sink_info_list(add_output_device, &mut user_data as *mut _ as *mut _) { -+ self.operation_wait(None, &o); - } - } - - if devtype == cubeb::DEVICE_TYPE_INPUT { -- let o = pa_context_get_source_info_list(self.context, -- Some(pulse_source_info_cb), -- &mut user_data as *mut _ as *mut _); -- if !o.is_null() { -- self.operation_wait(ptr::null_mut(), o); -- pa_operation_unref(o); -+ if let Ok(o) = context.get_source_info_list(add_input_device, &mut user_data as *mut _ as *mut _) { -+ self.operation_wait(None, &o); - } - } - -- pa_threaded_mainloop_unlock(self.mainloop); -+ self.mainloop.unlock(); - } - - // Extract the array of cubeb_device_info from -@@ -282,16 +398,16 @@ impl Context { - coll.count); - for dev in devices.iter_mut() { - if !dev.device_id.is_null() { -- pa_xfree(dev.device_id as *mut _); -+ let _ = CString::from_raw(dev.device_id as *mut _); - } - if !dev.group_id.is_null() { -- pa_xfree(dev.group_id as *mut _); -+ let _ = CString::from_raw(dev.group_id as *mut _); - } - if !dev.vendor_name.is_null() { -- pa_xfree(dev.vendor_name as *mut _); -+ let _ = CString::from_raw(dev.vendor_name as *mut _); - } - if !dev.friendly_name.is_null() { -- pa_xfree(dev.friendly_name as *mut _); -+ let _ = CString::from_raw(dev.friendly_name as *mut _); - } - } - } -@@ -302,115 +418,125 @@ impl Context { - cb: cubeb::DeviceCollectionChangedCallback, - user_ptr: *mut c_void) - -> i32 { -- unsafe extern "C" fn subscribe_success(_: *mut pa_context, success: i32, user_data: *mut c_void) { -- let ctx = &*(user_data as *mut Context); -+ fn update_collection(_: &pulse::Context, event: pulse::SubscriptionEvent, index: u32, user_data: *mut c_void) { -+ let mut ctx = unsafe { &mut *(user_data as *mut Context) }; -+ -+ let (f, t) = (event.event_facility(), event.event_type()); -+ match f { -+ pulse::SubscriptionEventFacility::Source | -+ pulse::SubscriptionEventFacility::Sink => { -+ match t { -+ pulse::SubscriptionEventType::Remove | -+ pulse::SubscriptionEventType::New => { -+ if cubeb::log_enabled() { -+ let op = if t == pulse::SubscriptionEventType::New { -+ "Adding" -+ } else { -+ "Removing" -+ }; -+ let dev = if f == pulse::SubscriptionEventFacility::Sink { -+ "sink" -+ } else { -+ "source " -+ }; -+ log!("{} {} index {}", op, dev, index); -+ -+ unsafe { -+ ctx.collection_changed_callback.unwrap()(ctx as *mut _ as *mut _, -+ ctx.collection_changed_user_ptr); -+ } -+ } -+ }, -+ _ => {}, -+ } -+ }, -+ _ => {}, -+ } -+ } -+ -+ fn success(_: &pulse::Context, success: i32, user_data: *mut c_void) { -+ let ctx = unsafe { &*(user_data as *mut Context) }; - debug_assert_ne!(success, 0); -- pa_threaded_mainloop_signal(ctx.mainloop, 0); -+ ctx.mainloop.signal(); - } - - self.collection_changed_callback = cb; - self.collection_changed_user_ptr = user_ptr; - -- unsafe { -- pa_threaded_mainloop_lock(self.mainloop); -+ let user_data: *mut c_void = self as *mut _ as *mut _; -+ if let Some(ref context) = self.context { -+ self.mainloop.lock(); - -- let mut mask: pa_subscription_mask_t = PA_SUBSCRIPTION_MASK_NULL; -+ let mut mask = pulse::SubscriptionMask::empty(); - if self.collection_changed_callback.is_none() { - // Unregister subscription -- pa_context_set_subscribe_callback(self.context, None, ptr::null_mut()); -+ context.clear_subscribe_callback(); - } else { -- pa_context_set_subscribe_callback(self.context, -- Some(pulse_subscribe_callback), -- self as *mut _ as *mut _); -- if devtype == cubeb::DEVICE_TYPE_INPUT { -- mask |= PA_SUBSCRIPTION_MASK_SOURCE -+ context.set_subscribe_callback(update_collection, user_data); -+ if devtype.contains(cubeb::DEVICE_TYPE_INPUT) { -+ mask |= pulse::SUBSCRIPTION_MASK_SOURCE - }; -- if devtype == cubeb::DEVICE_TYPE_OUTPUT { -- mask |= PA_SUBSCRIPTION_MASK_SOURCE -+ if devtype.contains(cubeb::DEVICE_TYPE_OUTPUT) { -+ mask = pulse::SUBSCRIPTION_MASK_SINK - }; - } - -- let o = pa_context_subscribe(self.context, -- mask, -- Some(subscribe_success), -- self as *const _ as *mut _); -- if o.is_null() { -+ if let Ok(o) = context.subscribe(mask, success, self as *const _ as *mut _) { -+ self.operation_wait(None, &o); -+ } else { - log!("Context subscribe failed"); - return cubeb::ERROR; - } -- self.operation_wait(ptr::null_mut(), o); -- pa_operation_unref(o); - -- pa_threaded_mainloop_unlock(self.mainloop); -+ self.mainloop.unlock(); - } - - cubeb::OK - } - -- // -- -- pub fn pulse_stream_cork(&self, stream: *mut pa_stream, state: CorkState) { -- unsafe extern "C" fn cork_success(_: *mut pa_stream, _: i32, u: *mut c_void) { -- let mainloop = u as *mut pa_threaded_mainloop; -- pa_threaded_mainloop_signal(mainloop, 0); -+ pub fn context_init(&mut self) -> i32 { -+ fn error_state(c: &pulse::Context, u: *mut c_void) { -+ let mut ctx = unsafe { &mut *(u as *mut Context) }; -+ if !c.get_state().is_good() { -+ ctx.error = true; -+ } -+ ctx.mainloop.signal(); - } - -- if stream.is_null() { -- return; -+ if self.context.is_some() { -+ debug_assert!(self.error); -+ self.context_destroy(); - } - -- let o = unsafe { -- pa_stream_cork(stream, -- state.is_cork() as i32, -- Some(cork_success), -- self.mainloop as *mut _) -+ self.context = { -+ let name = match self.context_name.as_ref() { -+ Some(s) => Some(s.as_ref()), -+ None => None, -+ }; -+ pulse::Context::new(&self.mainloop.get_api(), name) - }; - -- if !o.is_null() { -- self.operation_wait(stream, o); -- unsafe { pa_operation_unref(o) }; -+ let context_ptr: *mut c_void = self as *mut _ as *mut _; -+ if self.context.is_none() { -+ return cubeb::ERROR; - } -- } - -- pub fn pulse_context_init(&mut self) -> i32 { -- unsafe extern "C" fn error_state(c: *mut pa_context, u: *mut c_void) { -- let mut ctx = &mut *(u as *mut Context); -- if !PA_CONTEXT_IS_GOOD(pa_context_get_state(c)) { -- ctx.error = true; -- } -- pa_threaded_mainloop_signal(ctx.mainloop, 0); -+ self.mainloop.lock(); -+ if let Some(ref context) = self.context { -+ context.set_state_callback(error_state, context_ptr); -+ let _ = context.connect(None, pulse::ContextFlags::empty(), ptr::null()); - } - -- if !self.context.is_null() { -- debug_assert!(self.error); -- unsafe { self.pulse_context_destroy() }; -+ if !self.wait_until_context_ready() { -+ self.mainloop.unlock(); -+ self.context_destroy(); -+ return cubeb::ERROR; - } - -- unsafe { -- self.context = pa_context_new(pa_threaded_mainloop_get_api(self.mainloop), -- self.context_name); -- -- if self.context.is_null() { -- return cubeb::ERROR; -- } -- -- pa_context_set_state_callback(self.context, Some(error_state), self as *mut _ as *mut _); -- -- pa_threaded_mainloop_lock(self.mainloop); -- pa_context_connect(self.context, ptr::null(), 0, ptr::null()); -- -- if !self.wait_until_context_ready() { -- pa_threaded_mainloop_unlock(self.mainloop); -- self.pulse_context_destroy(); -- assert!(self.context.is_null()); -- return cubeb::ERROR; -- } -+ self.mainloop.unlock(); - -- pa_threaded_mainloop_unlock(self.mainloop); -- } -- -- let version_str = unsafe { CStr::from_ptr(pa_get_library_version()) }; -- if let Ok(version) = semver::Version::parse(version_str.to_string_lossy().as_ref()) { -+ let version_str = unsafe { CStr::from_ptr(pulse::library_version()) }; -+ if let Ok(version) = semver::Version::parse(&version_str.to_string_lossy()) { - self.version_0_9_8 = version >= semver::Version::parse("0.9.8").expect("Failed to parse version"); - self.version_2_0_0 = version >= semver::Version::parse("2.0.0").expect("Failed to parse version"); - } -@@ -420,34 +546,42 @@ impl Context { - cubeb::OK - } - -- unsafe fn pulse_context_destroy(&mut self) { -- unsafe extern "C" fn drain_complete(_c: *mut pa_context, u: *mut c_void) { -- let mainloop = u as *mut pa_threaded_mainloop; -- pa_threaded_mainloop_signal(mainloop, 0); -- } -- -- pa_threaded_mainloop_lock(self.mainloop); -- let o = pa_context_drain(self.context, Some(drain_complete), self.mainloop as *mut _); -- if !o.is_null() { -- self.operation_wait(ptr::null_mut(), o); -- pa_operation_unref(o); -- } -- pa_context_set_state_callback(self.context, None, ptr::null_mut()); -- pa_context_disconnect(self.context); -- pa_context_unref(self.context); -- self.context = ptr::null_mut(); -- pa_threaded_mainloop_unlock(self.mainloop); -+ fn context_destroy(&mut self) { -+ fn drain_complete(_: &pulse::Context, u: *mut c_void) { -+ let ctx = unsafe { &*(u as *mut Context) }; -+ ctx.mainloop.signal(); -+ } -+ -+ let context_ptr: *mut c_void = self as *mut _ as *mut _; -+ match self.context.take() { -+ Some(ctx) => { -+ self.mainloop.lock(); -+ if let Ok(o) = ctx.drain(drain_complete, context_ptr) { -+ self.operation_wait(None, &o); -+ } -+ ctx.clear_state_callback(); -+ ctx.disconnect(); -+ ctx.unref(); -+ self.mainloop.unlock(); -+ }, -+ _ => {}, -+ } - } - -- pub fn operation_wait(&self, stream: *mut pa_stream, o: *mut pa_operation) -> bool { -- unsafe { -- while pa_operation_get_state(o) == PA_OPERATION_RUNNING { -- pa_threaded_mainloop_wait(self.mainloop); -- if !PA_CONTEXT_IS_GOOD(pa_context_get_state(self.context)) { -+ pub fn operation_wait<'a, S>(&self, s: S, o: &pulse::Operation) -> bool -+ where S: Into> -+ { -+ let stream = s.into(); -+ while o.get_state() == PA_OPERATION_RUNNING { -+ self.mainloop.wait(); -+ if let Some(ref context) = self.context { -+ if !context.get_state().is_good() { - return false; - } -+ } - -- if !stream.is_null() && !PA_STREAM_IS_GOOD(pa_stream_get_state(stream)) { -+ if let Some(stm) = stream { -+ if !stm.get_state().is_good() { - return false; - } - } -@@ -457,36 +591,23 @@ impl Context { - } - - pub fn wait_until_context_ready(&self) -> bool { -- loop { -- let state = unsafe { pa_context_get_state(self.context) }; -- if !PA_CONTEXT_IS_GOOD(state) { -- return false; -- } -- if state == PA_CONTEXT_READY { -- break; -- } -- unsafe { -- pa_threaded_mainloop_wait(self.mainloop); -+ if let Some(ref context) = self.context { -+ loop { -+ let state = context.get_state(); -+ if !state.is_good() { -+ return false; -+ } -+ if state == pulse::ContextState::Ready { -+ break; -+ } -+ self.mainloop.wait(); - } - } - - true - } - -- fn state_from_sink_port(&self, i: *const pa_port_info) -> cubeb::DeviceState { -- if !i.is_null() { -- let info = unsafe { *i }; -- if self.version_2_0_0 && info.available == PA_PORT_AVAILABLE_NO { -- cubeb::DeviceState::Unplugged -- } else { -- cubeb::DeviceState::Enabled -- } -- } else { -- cubeb::DeviceState::Enabled -- } -- } -- -- fn state_from_source_port(&self, i: *mut pa_port_info) -> cubeb::DeviceState { -+ fn state_from_port(&self, i: *const pa_port_info) -> cubeb::DeviceState { - if !i.is_null() { - let info = unsafe { *i }; - if self.version_2_0_0 && info.available == PA_PORT_AVAILABLE_NO { -@@ -500,62 +621,30 @@ impl Context { - } - } - --// Callbacks --unsafe extern "C" fn server_info_callback(context: *mut pa_context, info: *const pa_server_info, u: *mut c_void) { -- unsafe extern "C" fn sink_info_callback(_context: *mut pa_context, -- info: *const pa_sink_info, -- eol: i32, -- u: *mut c_void) { -- let mut ctx = &mut *(u as *mut Context); -- if eol == 0 { -- let info = *info; -- ctx.default_sink_info = Some(DefaultInfo { -- sample_spec: info.sample_spec, -- channel_map: info.channel_map, -- flags: info.flags, -- }); -- } -- pa_threaded_mainloop_signal(ctx.mainloop, 0); -- } -- -- let o = pa_context_get_sink_info_by_name(context, -- (*info).default_sink_name, -- Some(sink_info_callback), -- u); -- if !o.is_null() { -- pa_operation_unref(o); -- } --} -- --struct PulseDevListData { -- default_sink_name: *mut c_char, -- default_source_name: *mut c_char, -+struct PulseDevListData<'a> { -+ default_sink_name: CString, -+ default_source_name: CString, - devinfo: Vec, -- context: *mut Context, -+ context: &'a Context, - } - --impl Drop for PulseDevListData { -- fn drop(&mut self) { -- if !self.default_sink_name.is_null() { -- unsafe { -- pa_xfree(self.default_sink_name as *mut _); -- } -- } -- if !self.default_source_name.is_null() { -- unsafe { -- pa_xfree(self.default_source_name as *mut _); -- } -+impl<'a> PulseDevListData<'a> { -+ pub fn new<'b>(context: &'b Context) -> Self -+ where 'b: 'a -+ { -+ PulseDevListData { -+ default_sink_name: CString::default(), -+ default_source_name: CString::default(), -+ devinfo: Vec::new(), -+ context: context, - } - } - } - --impl Default for PulseDevListData { -- fn default() -> Self { -- PulseDevListData { -- default_sink_name: ptr::null_mut(), -- default_source_name: ptr::null_mut(), -- devinfo: Vec::new(), -- context: ptr::null_mut(), -+impl<'a> Drop for PulseDevListData<'a> { -+ fn drop(&mut self) { -+ for elem in &mut self.devinfo { -+ let _ = unsafe { Box::from_raw(elem) }; - } - } - } -@@ -566,192 +655,7 @@ fn pulse_format_to_cubeb_format(format: - PA_SAMPLE_S16BE => cubeb::DEVICE_FMT_S16BE, - PA_SAMPLE_FLOAT32LE => cubeb::DEVICE_FMT_F32LE, - PA_SAMPLE_FLOAT32BE => cubeb::DEVICE_FMT_F32BE, -- _ => { -- panic!("Invalid format"); -- }, -+ // Unsupported format, return F32NE -+ _ => cubeb::CUBEB_FMT_F32NE, - } - } -- --unsafe extern "C" fn pulse_sink_info_cb(_context: *mut pa_context, -- i: *const pa_sink_info, -- eol: i32, -- user_data: *mut c_void) { -- if eol != 0 || i.is_null() { -- return; -- } -- -- debug_assert!(!user_data.is_null()); -- -- let info = *i; -- let mut list_data = &mut *(user_data as *mut PulseDevListData); -- -- let device_id = pa_xstrdup(info.name); -- -- let group_id = { -- let prop = pa_proplist_gets(info.proplist, b"sysfs.path\0".as_ptr() as *const c_char); -- if !prop.is_null() { -- pa_xstrdup(prop) -- } else { -- ptr::null_mut() -- } -- }; -- -- let vendor_name = { -- let prop = pa_proplist_gets(info.proplist, -- b"device.vendor.name\0".as_ptr() as *const c_char); -- if !prop.is_null() { -- pa_xstrdup(prop) -- } else { -- ptr::null_mut() -- } -- }; -- -- let preferred = if strcmp(info.name, list_data.default_sink_name) == 0 { -- cubeb::DEVICE_PREF_ALL -- } else { -- cubeb::DevicePref::empty() -- }; -- -- let ctx = &(*list_data.context); -- -- let devinfo = cubeb::DeviceInfo { -- device_id: device_id, -- devid: device_id as cubeb::DeviceId, -- friendly_name: pa_xstrdup(info.description), -- group_id: group_id, -- vendor_name: vendor_name, -- devtype: cubeb::DEVICE_TYPE_OUTPUT, -- state: ctx.state_from_sink_port(info.active_port), -- preferred: preferred, -- format: cubeb::DeviceFmt::all(), -- default_format: pulse_format_to_cubeb_format(info.sample_spec.format), -- max_channels: info.channel_map.channels as u32, -- min_rate: 1, -- max_rate: PA_RATE_MAX, -- default_rate: info.sample_spec.rate, -- latency_lo: 0, -- latency_hi: 0, -- }; -- list_data.devinfo.push(devinfo); -- -- pa_threaded_mainloop_signal(ctx.mainloop, 0); --} -- --unsafe extern "C" fn pulse_source_info_cb(_context: *mut pa_context, -- i: *const pa_source_info, -- eol: i32, -- user_data: *mut c_void) { -- if eol != 0 || i.is_null() { -- return; -- } -- -- debug_assert!(!user_data.is_null()); -- -- let info = *i; -- let mut list_data = &mut *(user_data as *mut PulseDevListData); -- -- let device_id = pa_xstrdup(info.name); -- -- let group_id = { -- let prop = pa_proplist_gets(info.proplist, b"sysfs.path\0".as_ptr() as *mut c_char); -- if !prop.is_null() { -- pa_xstrdup(prop) -- } else { -- ptr::null_mut() -- } -- }; -- -- let vendor_name = { -- let prop = pa_proplist_gets(info.proplist, -- b"device.vendor.name\0".as_ptr() as *mut c_char); -- if !prop.is_null() { -- pa_xstrdup(prop) -- } else { -- ptr::null_mut() -- } -- }; -- -- let preferred = if strcmp(info.name, list_data.default_source_name) == 0 { -- cubeb::DEVICE_PREF_ALL -- } else { -- cubeb::DevicePref::empty() -- }; -- -- let ctx = &(*list_data.context); -- -- let devinfo = cubeb::DeviceInfo { -- device_id: device_id, -- devid: device_id as cubeb::DeviceId, -- friendly_name: pa_xstrdup(info.description), -- group_id: group_id, -- vendor_name: vendor_name, -- devtype: cubeb::DEVICE_TYPE_INPUT, -- state: ctx.state_from_source_port(info.active_port), -- preferred: preferred, -- format: cubeb::DeviceFmt::all(), -- default_format: pulse_format_to_cubeb_format(info.sample_spec.format), -- max_channels: info.channel_map.channels as u32, -- min_rate: 1, -- max_rate: PA_RATE_MAX, -- default_rate: info.sample_spec.rate, -- latency_lo: 0, -- latency_hi: 0, -- }; -- -- list_data.devinfo.push(devinfo); -- -- pa_threaded_mainloop_signal(ctx.mainloop, 0); --} -- --unsafe extern "C" fn pulse_server_info_cb(_context: *mut pa_context, -- i: *const pa_server_info, -- user_data: *mut c_void) { -- assert!(!i.is_null()); -- let info = *i; -- let list_data = &mut *(user_data as *mut PulseDevListData); -- -- dup_str!(list_data.default_sink_name, info.default_sink_name); -- dup_str!(list_data.default_source_name, info.default_source_name); -- -- pa_threaded_mainloop_signal((*list_data.context).mainloop, 0); --} -- --unsafe extern "C" fn pulse_subscribe_callback(_ctx: *mut pa_context, -- t: pa_subscription_event_type_t, -- index: u32, -- user_data: *mut c_void) { -- let mut ctx = &mut *(user_data as *mut Context); -- -- match t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK { -- PA_SUBSCRIPTION_EVENT_SOURCE | -- PA_SUBSCRIPTION_EVENT_SINK => { -- -- if cubeb::log_enabled() { -- if (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SOURCE && -- (t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE { -- log!("Removing sink index %d", index); -- } else if (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SOURCE && -- (t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW { -- log!("Adding sink index %d", index); -- } -- if (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SINK && -- (t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE { -- log!("Removing source index %d", index); -- } else if (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SINK && -- (t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW { -- log!("Adding source index %d", index); -- } -- } -- -- if (t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE || -- (t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW { -- ctx.collection_changed_callback.unwrap()(ctx as *mut _ as *mut _, ctx.collection_changed_user_ptr); -- } -- }, -- _ => {}, -- } --} -- --extern "C" { -- pub fn strcmp(cs: *const c_char, ct: *const c_char) -> c_int; --} -diff -up firefox-55.0/media/libcubeb/cubeb-pulse-rs/src/backend/mod.rs.cubeb-pulse-arm firefox-55.0/media/libcubeb/cubeb-pulse-rs/src/backend/mod.rs ---- firefox-55.0/media/libcubeb/cubeb-pulse-rs/src/backend/mod.rs.cubeb-pulse-arm 2017-07-31 18:20:49.000000000 +0200 -+++ firefox-55.0/media/libcubeb/cubeb-pulse-rs/src/backend/mod.rs 2017-08-04 13:37:46.386821731 +0200 -@@ -7,8 +7,16 @@ mod context; - mod cork_state; - mod stream; - -+use std::os::raw::c_char; -+use std::ffi::CStr; -+ - pub type Result = ::std::result::Result; - - pub use self::context::Context; - pub use self::stream::Device; - pub use self::stream::Stream; -+ -+// helper to convert *const c_char to Option -+fn try_cstr_from<'str>(s: *const c_char) -> Option<&'str CStr> { -+ if s.is_null() { None } else { Some(unsafe { CStr::from_ptr(s) }) } -+} -diff -up firefox-55.0/media/libcubeb/cubeb-pulse-rs/src/backend/stream.rs.cubeb-pulse-arm firefox-55.0/media/libcubeb/cubeb-pulse-rs/src/backend/stream.rs ---- firefox-55.0/media/libcubeb/cubeb-pulse-rs/src/backend/stream.rs.cubeb-pulse-arm 2017-07-31 18:20:49.000000000 +0200 -+++ firefox-55.0/media/libcubeb/cubeb-pulse-rs/src/backend/stream.rs 2017-08-04 13:37:46.387821728 +0200 -@@ -6,8 +6,10 @@ - use backend::*; - use backend::cork_state::CorkState; - use cubeb; -+use pulse::{self, CVolumeExt, ChannelMapExt, SampleSpecExt, USecExt}; - use pulse_ffi::*; --use std::os::raw::{c_char, c_long, c_void}; -+use std::ffi::{CStr, CString}; -+use std::os::raw::{c_long, c_void}; - use std::ptr; - - const PULSE_NO_GAIN: f32 = -1.0; -@@ -36,15 +38,12 @@ fn cubeb_channel_to_pa_channel(channel: - MAP[idx as usize] - } - --fn layout_to_channel_map(layout: cubeb::ChannelLayout) -> pa_channel_map { -+fn layout_to_channel_map(layout: cubeb::ChannelLayout) -> pulse::ChannelMap { - assert_ne!(layout, cubeb::LAYOUT_UNDEFINED); - - let order = cubeb::mixer::channel_index_to_order(layout); - -- let mut cm: pa_channel_map = Default::default(); -- unsafe { -- pa_channel_map_init(&mut cm); -- } -+ let mut cm = pulse::ChannelMap::init(); - cm.channels = order.len() as u8; - for (s, d) in order.iter().zip(cm.map.iter_mut()) { - *d = cubeb_channel_to_pa_channel(*s); -@@ -57,24 +56,27 @@ pub struct Device(cubeb::Device); - impl Drop for Device { - fn drop(&mut self) { - unsafe { -- pa_xfree(self.0.input_name as *mut _); -- pa_xfree(self.0.output_name as *mut _); -+ if !self.0.input_name.is_null() { -+ let _ = CString::from_raw(self.0.input_name); -+ } -+ if !self.0.output_name.is_null() { -+ let _ = CString::from_raw(self.0.output_name); -+ } - } - } - } - -- - #[derive(Debug)] - pub struct Stream<'ctx> { - context: &'ctx Context, -- output_stream: *mut pa_stream, -- input_stream: *mut pa_stream, -+ output_stream: Option, -+ input_stream: Option, - data_callback: cubeb::DataCallback, - state_callback: cubeb::StateCallback, - user_ptr: *mut c_void, - drain_timer: *mut pa_time_event, -- output_sample_spec: pa_sample_spec, -- input_sample_spec: pa_sample_spec, -+ output_sample_spec: pulse::SampleSpec, -+ input_sample_spec: pulse::SampleSpec, - shutdown: bool, - volume: f32, - state: cubeb::State, -@@ -88,7 +90,7 @@ impl<'ctx> Drop for Stream<'ctx> { - - impl<'ctx> Stream<'ctx> { - pub fn new(context: &'ctx Context, -- stream_name: *const c_char, -+ stream_name: &CStr, - input_device: cubeb::DeviceId, - input_stream_params: Option, - output_device: cubeb::DeviceId, -@@ -99,83 +101,167 @@ impl<'ctx> Stream<'ctx> { - user_ptr: *mut c_void) - -> Result>> { - -+ fn check_error(s: &pulse::Stream, u: *mut c_void) { -+ let stm = unsafe { &mut *(u as *mut Stream) }; -+ if !s.get_state().is_good() { -+ stm.state_change_callback(cubeb::STATE_ERROR); -+ } -+ stm.context.mainloop.signal(); -+ } -+ -+ fn read_data(s: &pulse::Stream, nbytes: usize, u: *mut c_void) { -+ fn read_from_input(s: &pulse::Stream, buffer: *mut *const c_void, size: *mut usize) -> i32 { -+ let readable_size: i32 = s.readable_size() -+ .and_then(|s| Ok(s as i32)) -+ .unwrap_or(-1); -+ if readable_size > 0 { -+ if unsafe { s.peek(buffer, size).is_err() } { -+ return -1; -+ } -+ } -+ readable_size -+ } -+ -+ logv!("Input callback buffer size {}", nbytes); -+ let mut stm = unsafe { &mut *(u as *mut Stream) }; -+ if stm.shutdown { -+ return; -+ } -+ -+ let mut read_data: *const c_void = ptr::null(); -+ let mut read_size: usize = 0; -+ while read_from_input(s, &mut read_data, &mut read_size) > 0 { -+ /* read_data can be NULL in case of a hole. */ -+ if !read_data.is_null() { -+ let in_frame_size = stm.input_sample_spec.frame_size(); -+ let read_frames = read_size / in_frame_size; -+ -+ if stm.output_stream.is_some() { -+ // input/capture + output/playback operation -+ let out_frame_size = stm.output_sample_spec.frame_size(); -+ let write_size = read_frames * out_frame_size; -+ // Offer full duplex data for writing -+ stm.trigger_user_callback(read_data, write_size); -+ } else { -+ // input/capture only operation. Call callback directly -+ let got = unsafe { -+ stm.data_callback.unwrap()(stm as *mut _ as *mut _, -+ stm.user_ptr, -+ read_data, -+ ptr::null_mut(), -+ read_frames as c_long) -+ }; -+ -+ if got < 0 || got as usize != read_frames { -+ let _ = s.cancel_write(); -+ stm.shutdown = true; -+ break; -+ } -+ } -+ } -+ -+ if read_size > 0 { -+ let _ = s.drop(); -+ } -+ -+ if stm.shutdown { -+ return; -+ } -+ } -+ } -+ -+ fn write_data(_: &pulse::Stream, nbytes: usize, u: *mut c_void) { -+ logv!("Output callback to be written buffer size {}", nbytes); -+ let mut stm = unsafe { &mut *(u as *mut Stream) }; -+ if stm.shutdown || stm.state != cubeb::STATE_STARTED { -+ return; -+ } -+ -+ if stm.input_stream.is_none() { -+ // Output/playback only operation. -+ // Write directly to output -+ debug_assert!(stm.output_stream.is_some()); -+ stm.trigger_user_callback(ptr::null(), nbytes); -+ } -+ } -+ - let mut stm = Box::new(Stream { - context: context, -- output_stream: ptr::null_mut(), -- input_stream: ptr::null_mut(), -+ output_stream: None, -+ input_stream: None, - data_callback: data_callback, - state_callback: state_callback, - user_ptr: user_ptr, - drain_timer: ptr::null_mut(), -- output_sample_spec: pa_sample_spec::default(), -- input_sample_spec: pa_sample_spec::default(), -+ output_sample_spec: pulse::SampleSpec::default(), -+ input_sample_spec: pulse::SampleSpec::default(), - shutdown: false, - volume: PULSE_NO_GAIN, - state: cubeb::STATE_ERROR, - }); - -- unsafe { -- pa_threaded_mainloop_lock(stm.context.mainloop); -+ if let Some(ref context) = stm.context.context { -+ stm.context.mainloop.lock(); -+ -+ // Setup output stream - if let Some(ref stream_params) = output_stream_params { -- match stm.pulse_stream_init(stream_params, stream_name) { -- Ok(s) => stm.output_stream = s, -+ match Stream::stream_init(context, stream_params, stream_name) { -+ Ok(s) => { -+ stm.output_sample_spec = *s.get_sample_spec(); -+ -+ s.set_state_callback(check_error, stm.as_mut() as *mut _ as *mut _); -+ s.set_write_callback(write_data, stm.as_mut() as *mut _ as *mut _); -+ -+ let battr = set_buffering_attribute(latency_frames, &stm.output_sample_spec); -+ let device_name = super::try_cstr_from(output_device as *const _); -+ let _ = s.connect_playback(device_name, -+ &battr, -+ pulse::STREAM_AUTO_TIMING_UPDATE | pulse::STREAM_INTERPOLATE_TIMING | -+ pulse::STREAM_START_CORKED | -+ pulse::STREAM_ADJUST_LATENCY, -+ None, -+ None); -+ -+ stm.output_stream = Some(s); -+ }, - Err(e) => { -- pa_threaded_mainloop_unlock(stm.context.mainloop); -+ stm.context.mainloop.unlock(); - stm.destroy(); - return Err(e); - }, - } - -- stm.output_sample_spec = *pa_stream_get_sample_spec(stm.output_stream); -- -- pa_stream_set_state_callback(stm.output_stream, -- Some(stream_state_callback), -- stm.as_mut() as *mut _ as *mut _); -- pa_stream_set_write_callback(stm.output_stream, -- Some(stream_write_callback), -- stm.as_mut() as *mut _ as *mut _); -- -- let battr = set_buffering_attribute(latency_frames, &stm.output_sample_spec); -- pa_stream_connect_playback(stm.output_stream, -- output_device as *mut c_char, -- &battr, -- PA_STREAM_AUTO_TIMING_UPDATE | PA_STREAM_INTERPOLATE_TIMING | -- PA_STREAM_START_CORKED | -- PA_STREAM_ADJUST_LATENCY, -- ptr::null(), -- ptr::null_mut()); - } - - // Set up input stream - if let Some(ref stream_params) = input_stream_params { -- match stm.pulse_stream_init(stream_params, stream_name) { -- Ok(s) => stm.input_stream = s, -+ match Stream::stream_init(context, stream_params, stream_name) { -+ Ok(s) => { -+ stm.input_sample_spec = *s.get_sample_spec(); -+ -+ s.set_state_callback(check_error, stm.as_mut() as *mut _ as *mut _); -+ s.set_read_callback(read_data, stm.as_mut() as *mut _ as *mut _); -+ -+ let battr = set_buffering_attribute(latency_frames, &stm.input_sample_spec); -+ let device_name = super::try_cstr_from(input_device as *const _); -+ let _ = s.connect_record(device_name, -+ &battr, -+ pulse::STREAM_AUTO_TIMING_UPDATE | pulse::STREAM_INTERPOLATE_TIMING | -+ pulse::STREAM_START_CORKED | -+ pulse::STREAM_ADJUST_LATENCY); -+ -+ stm.input_stream = Some(s); -+ }, - Err(e) => { -- pa_threaded_mainloop_unlock(stm.context.mainloop); -+ stm.context.mainloop.unlock(); - stm.destroy(); - return Err(e); - }, - } - -- stm.input_sample_spec = *(pa_stream_get_sample_spec(stm.input_stream)); -- -- pa_stream_set_state_callback(stm.input_stream, -- Some(stream_state_callback), -- stm.as_mut() as *mut _ as *mut _); -- pa_stream_set_read_callback(stm.input_stream, -- Some(stream_read_callback), -- stm.as_mut() as *mut _ as *mut _); -- -- let battr = set_buffering_attribute(latency_frames, &stm.input_sample_spec); -- pa_stream_connect_record(stm.input_stream, -- input_device as *mut c_char, -- &battr, -- PA_STREAM_AUTO_TIMING_UPDATE | PA_STREAM_INTERPOLATE_TIMING | -- PA_STREAM_START_CORKED | -- PA_STREAM_ADJUST_LATENCY); - } - -- let r = if stm.wait_until_stream_ready() { -+ let r = if stm.wait_until_ready() { - /* force a timing update now, otherwise timing info does not become valid - until some point after initialization has completed. */ - stm.update_timing_info() -@@ -183,7 +269,7 @@ impl<'ctx> Stream<'ctx> { - false - }; - -- pa_threaded_mainloop_unlock(stm.context.mainloop); -+ stm.context.mainloop.unlock(); - - if !r { - stm.destroy(); -@@ -191,10 +277,10 @@ impl<'ctx> Stream<'ctx> { - } - - if cubeb::log_enabled() { -- if output_stream_params.is_some() { -- let output_att = *pa_stream_get_buffer_attr(stm.output_stream); -- log!("Output buffer attributes maxlength %u, tlength %u, \ -- prebuf %u, minreq %u, fragsize %u", -+ if let Some(ref output_stream) = stm.output_stream { -+ let output_att = output_stream.get_buffer_attr(); -+ log!("Output buffer attributes maxlength {}, tlength {}, \ -+ prebuf {}, minreq {}, fragsize {}", - output_att.maxlength, - output_att.tlength, - output_att.prebuf, -@@ -202,10 +288,10 @@ impl<'ctx> Stream<'ctx> { - output_att.fragsize); - } - -- if input_stream_params.is_some() { -- let input_att = *pa_stream_get_buffer_attr(stm.input_stream); -- log!("Input buffer attributes maxlength %u, tlength %u, \ -- prebuf %u, minreq %u, fragsize %u", -+ if let Some(ref input_stream) = stm.input_stream { -+ let input_att = input_stream.get_buffer_attr(); -+ log!("Input buffer attributes maxlength {}, tlength {}, \ -+ prebuf {}, minreq {}, fragsize {}", - input_att.maxlength, - input_att.tlength, - input_att.prebuf, -@@ -219,224 +305,250 @@ impl<'ctx> Stream<'ctx> { - } - - fn destroy(&mut self) { -- self.stream_cork(CorkState::cork()); -+ self.cork(CorkState::cork()); - -- unsafe { -- pa_threaded_mainloop_lock(self.context.mainloop); -- if !self.output_stream.is_null() { -- if !self.drain_timer.is_null() { -- /* there's no pa_rttime_free, so use this instead. */ -- let ma = pa_threaded_mainloop_get_api(self.context.mainloop); -- if !ma.is_null() { -- (*ma).time_free.unwrap()(self.drain_timer); -+ self.context.mainloop.lock(); -+ { -+ match self.output_stream.take() { -+ Some(stm) => { -+ if !self.drain_timer.is_null() { -+ /* there's no pa_rttime_free, so use this instead. */ -+ self.context -+ .mainloop -+ .get_api() -+ .time_free(self.drain_timer); - } -- } -- -- pa_stream_set_state_callback(self.output_stream, None, ptr::null_mut()); -- pa_stream_set_write_callback(self.output_stream, None, ptr::null_mut()); -- pa_stream_disconnect(self.output_stream); -- pa_stream_unref(self.output_stream); -+ stm.clear_state_callback(); -+ stm.clear_write_callback(); -+ let _ = stm.disconnect(); -+ stm.unref(); -+ }, -+ _ => {}, -+ } -+ -+ match self.input_stream.take() { -+ Some(stm) => { -+ stm.clear_state_callback(); -+ stm.clear_read_callback(); -+ let _ = stm.disconnect(); -+ stm.unref(); -+ }, -+ _ => {}, - } -- -- if !self.input_stream.is_null() { -- pa_stream_set_state_callback(self.input_stream, None, ptr::null_mut()); -- pa_stream_set_read_callback(self.input_stream, None, ptr::null_mut()); -- pa_stream_disconnect(self.input_stream); -- pa_stream_unref(self.input_stream); -- } -- pa_threaded_mainloop_unlock(self.context.mainloop); - } -+ self.context.mainloop.unlock(); - } - - pub fn start(&mut self) -> i32 { -+ fn output_preroll(_: &pulse::MainloopApi, u: *mut c_void) { -+ let mut stm = unsafe { &mut *(u as *mut Stream) }; -+ if !stm.shutdown { -+ let size = stm.output_stream -+ .as_ref() -+ .map_or(0, |s| s.writable_size().unwrap_or(0)); -+ stm.trigger_user_callback(ptr::null_mut(), size); -+ } -+ } -+ - self.shutdown = false; -- self.stream_cork(CorkState::uncork() | CorkState::notify()); -+ self.cork(CorkState::uncork() | CorkState::notify()); - -- if !self.output_stream.is_null() && self.input_stream.is_null() { -- unsafe { -- /* On output only case need to manually call user cb once in order to make -- * things roll. This is done via a defer event in order to execute it -- * from PA server thread. */ -- pa_threaded_mainloop_lock(self.context.mainloop); -- pa_mainloop_api_once(pa_threaded_mainloop_get_api(self.context.mainloop), -- Some(pulse_defer_event_cb), -- self as *mut _ as *mut _); -- pa_threaded_mainloop_unlock(self.context.mainloop); -- } -+ if self.output_stream.is_some() && self.input_stream.is_none() { -+ /* On output only case need to manually call user cb once in order to make -+ * things roll. This is done via a defer event in order to execute it -+ * from PA server thread. */ -+ self.context.mainloop.lock(); -+ self.context -+ .mainloop -+ .get_api() -+ .once(output_preroll, self as *mut _ as *mut _); -+ self.context.mainloop.unlock(); - } - - cubeb::OK - } - - pub fn stop(&mut self) -> i32 { -- unsafe { -- pa_threaded_mainloop_lock(self.context.mainloop); -+ { -+ self.context.mainloop.lock(); - self.shutdown = true; - // If draining is taking place wait to finish - while !self.drain_timer.is_null() { -- pa_threaded_mainloop_wait(self.context.mainloop); -+ self.context.mainloop.wait(); - } -- pa_threaded_mainloop_unlock(self.context.mainloop); -+ self.context.mainloop.unlock(); - } -- self.stream_cork(CorkState::cork() | CorkState::notify()); -+ self.cork(CorkState::cork() | CorkState::notify()); - - cubeb::OK - } - - pub fn position(&self) -> Result { -- if self.output_stream.is_null() { -- return Err(cubeb::ERROR); -- } -+ let in_thread = self.context.mainloop.in_thread(); - -- let position = unsafe { -- let in_thread = pa_threaded_mainloop_in_thread(self.context.mainloop); -- -- if in_thread == 0 { -- pa_threaded_mainloop_lock(self.context.mainloop); -- } -- -- let mut r_usec: pa_usec_t = Default::default(); -- let r = pa_stream_get_time(self.output_stream, &mut r_usec); -- if in_thread == 0 { -- pa_threaded_mainloop_unlock(self.context.mainloop); -- } -- -- if r != 0 { -- return Err(cubeb::ERROR); -- } -+ if !in_thread { -+ self.context.mainloop.lock(); -+ } - -- let bytes = pa_usec_to_bytes(r_usec, &self.output_sample_spec); -- (bytes / pa_frame_size(&self.output_sample_spec)) as u64 -+ let r = match self.output_stream { -+ None => Err(cubeb::ERROR), -+ Some(ref stm) => { -+ match stm.get_time() { -+ Ok(r_usec) => { -+ let bytes = r_usec.to_bytes(&self.output_sample_spec); -+ Ok((bytes / self.output_sample_spec.frame_size()) as u64) -+ }, -+ Err(_) => Err(cubeb::ERROR), -+ } -+ }, - }; -- Ok(position) -- } - -- pub fn latency(&self) -> Result { -- if self.output_stream.is_null() { -- return Err(cubeb::ERROR); -+ if !in_thread { -+ self.context.mainloop.unlock(); - } - -- let mut r_usec: pa_usec_t = 0; -- let mut negative: i32 = 0; -- let r = unsafe { pa_stream_get_latency(self.output_stream, &mut r_usec, &mut negative) }; -+ r -+ } - -- if r != 0 { -- return Err(cubeb::ERROR); -+ pub fn latency(&self) -> Result { -+ match self.output_stream { -+ None => Err(cubeb::ERROR), -+ Some(ref stm) => { -+ match stm.get_latency() { -+ Ok((r_usec, negative)) => { -+ debug_assert!(negative); -+ let latency = (r_usec * self.output_sample_spec.rate as pa_usec_t / PA_USEC_PER_SEC) as u32; -+ Ok(latency) -+ }, -+ Err(_) => Err(cubeb::ERROR), -+ } -+ }, - } -- -- debug_assert_eq!(negative, 0); -- let latency = (r_usec * self.output_sample_spec.rate as pa_usec_t / PA_USEC_PER_SEC) as u32; -- -- Ok(latency) - } - - pub fn set_volume(&mut self, volume: f32) -> i32 { -- if self.output_stream.is_null() { -- return cubeb::ERROR; -- } -- -- unsafe { -- pa_threaded_mainloop_lock(self.context.mainloop); -- -- while self.context.default_sink_info.is_none() { -- pa_threaded_mainloop_wait(self.context.mainloop); -- } -- -- let mut cvol: pa_cvolume = Default::default(); -- -- /* if the pulse daemon is configured to use flat volumes, -- * apply our own gain instead of changing the input volume on the sink. */ -- let flags = { -- match self.context.default_sink_info { -- Some(ref info) => info.flags, -- _ => 0, -- } -- }; -- -- if (flags & PA_SINK_FLAT_VOLUME) != 0 { -- self.volume = volume; -- } else { -- let ss = pa_stream_get_sample_spec(self.output_stream); -- let vol = pa_sw_volume_from_linear(volume as f64); -- pa_cvolume_set(&mut cvol, (*ss).channels as u32, vol); -- -- let index = pa_stream_get_index(self.output_stream); -+ match self.output_stream { -+ None => cubeb::ERROR, -+ Some(ref stm) => { -+ if let Some(ref context) = self.context.context { -+ self.context.mainloop.lock(); -+ -+ let mut cvol: pa_cvolume = Default::default(); -+ -+ /* if the pulse daemon is configured to use flat -+ * volumes, apply our own gain instead of changing -+ * the input volume on the sink. */ -+ let flags = { -+ match self.context.default_sink_info { -+ Some(ref info) => info.flags, -+ _ => pulse::SinkFlags::empty(), -+ } -+ }; -+ -+ if flags.contains(pulse::SINK_FLAT_VOLUME) { -+ self.volume = volume; -+ } else { -+ let channels = stm.get_sample_spec().channels; -+ let vol = pulse::sw_volume_from_linear(volume as f64); -+ cvol.set(channels as u32, vol); -+ -+ let index = stm.get_index(); -+ -+ let context_ptr = self.context as *const _ as *mut _; -+ if let Ok(o) = context.set_sink_input_volume(index, &cvol, context_success, context_ptr) { -+ self.context.operation_wait(stm, &o); -+ } -+ } - -- let op = pa_context_set_sink_input_volume(self.context.context, -- index, -- &cvol, -- Some(volume_success), -- self as *mut _ as *mut _); -- if !op.is_null() { -- self.context.operation_wait(self.output_stream, op); -- pa_operation_unref(op); -+ self.context.mainloop.unlock(); -+ cubeb::OK -+ } else { -+ cubeb::ERROR - } -- } -- -- pa_threaded_mainloop_unlock(self.context.mainloop); -+ }, - } -- cubeb::OK - } - - pub fn set_panning(&mut self, panning: f32) -> i32 { -- if self.output_stream.is_null() { -- return cubeb::ERROR; -- } -+ #[repr(C)] -+ struct SinkInputInfoResult<'a> { -+ pub cvol: pulse::CVolume, -+ pub mainloop: &'a pulse::ThreadedMainloop, -+ } -+ -+ fn get_input_volume(_: &pulse::Context, info: *const pulse::SinkInputInfo, eol: i32, u: *mut c_void) { -+ let mut r = unsafe { &mut *(u as *mut SinkInputInfoResult) }; -+ if eol == 0 { -+ let info = unsafe { *info }; -+ r.cvol = info.volume; -+ } -+ r.mainloop.signal(); -+ } -+ -+ match self.output_stream { -+ None => cubeb::ERROR, -+ Some(ref stm) => { -+ if let Some(ref context) = self.context.context { -+ self.context.mainloop.lock(); -+ -+ let map = stm.get_channel_map(); -+ if !map.can_balance() { -+ self.context.mainloop.unlock(); -+ return cubeb::ERROR; -+ } - -- unsafe { -- pa_threaded_mainloop_lock(self.context.mainloop); -+ let index = stm.get_index(); - -- let map = pa_stream_get_channel_map(self.output_stream); -- if pa_channel_map_can_balance(map) == 0 { -- pa_threaded_mainloop_unlock(self.context.mainloop); -- return cubeb::ERROR; -- } -+ let mut r = SinkInputInfoResult { -+ cvol: pulse::CVolume::default(), -+ mainloop: &self.context.mainloop, -+ }; - -- let index = pa_stream_get_index(self.output_stream); -+ if let Ok(o) = context.get_sink_input_info(index, get_input_volume, &mut r as *mut _ as *mut _) { -+ self.context.operation_wait(stm, &o); -+ } - -- let mut cvol: pa_cvolume = Default::default(); -- let mut r = SinkInputInfoResult { -- cvol: &mut cvol, -- mainloop: self.context.mainloop, -- }; -+ r.cvol.set_balance(map, panning); - -- let op = pa_context_get_sink_input_info(self.context.context, -- index, -- Some(sink_input_info_cb), -- &mut r as *mut _ as *mut _); -- if !op.is_null() { -- self.context.operation_wait(self.output_stream, op); -- pa_operation_unref(op); -- } -- -- pa_cvolume_set_balance(&mut cvol, map, panning); -- -- let op = pa_context_set_sink_input_volume(self.context.context, -- index, -- &cvol, -- Some(volume_success), -- self as *mut _ as *mut _); -- if !op.is_null() { -- self.context.operation_wait(self.output_stream, op); -- pa_operation_unref(op); -- } -+ let context_ptr = self.context as *const _ as *mut _; -+ if let Ok(o) = context.set_sink_input_volume(index, &r.cvol, context_success, context_ptr) { -+ self.context.operation_wait(stm, &o); -+ } - -- pa_threaded_mainloop_unlock(self.context.mainloop); -- } -+ self.context.mainloop.unlock(); - -- cubeb::OK -+ cubeb::OK -+ } else { -+ cubeb::ERROR -+ } -+ }, -+ } - } - - pub fn current_device(&self) -> Result> { - if self.context.version_0_9_8 { - let mut dev = Box::new(cubeb::Device::default()); - -- if !self.input_stream.is_null() { -- dev.input_name = unsafe { pa_xstrdup(pa_stream_get_device_name(self.input_stream)) }; -+ if self.input_stream.is_some() { -+ if let Some(ref stm) = self.input_stream { -+ dev.input_name = match stm.get_device_name() { -+ Ok(name) => name.to_owned().into_raw(), -+ Err(_) => { -+ return Err(cubeb::ERROR); -+ }, -+ } -+ } - } - -- if !self.output_stream.is_null() { -- dev.output_name = unsafe { pa_xstrdup(pa_stream_get_device_name(self.output_stream)) }; -+ if !self.output_stream.is_some() { -+ if let Some(ref stm) = self.output_stream { -+ dev.output_name = match stm.get_device_name() { -+ Ok(name) => name.to_owned().into_raw(), -+ Err(_) => { -+ return Err(cubeb::ERROR); -+ }, -+ } -+ } - } - - Ok(dev) -@@ -445,51 +557,62 @@ impl<'ctx> Stream<'ctx> { - } - } - -- fn pulse_stream_init(&mut self, -- stream_params: &cubeb::StreamParams, -- stream_name: *const c_char) -- -> Result<*mut pa_stream> { -+ fn stream_init(context: &pulse::Context, -+ stream_params: &cubeb::StreamParams, -+ stream_name: &CStr) -+ -> Result { - -- fn to_pulse_format(format: cubeb::SampleFormat) -> pa_sample_format_t { -+ fn to_pulse_format(format: cubeb::SampleFormat) -> pulse::SampleFormat { - match format { -- cubeb::SAMPLE_S16LE => PA_SAMPLE_S16LE, -- cubeb::SAMPLE_S16BE => PA_SAMPLE_S16BE, -- cubeb::SAMPLE_FLOAT32LE => PA_SAMPLE_FLOAT32LE, -- cubeb::SAMPLE_FLOAT32BE => PA_SAMPLE_FLOAT32BE, -- _ => panic!("Invalid format: {:?}", format), -+ cubeb::SAMPLE_S16LE => pulse::SampleFormat::Signed16LE, -+ cubeb::SAMPLE_S16BE => pulse::SampleFormat::Signed16BE, -+ cubeb::SAMPLE_FLOAT32LE => pulse::SampleFormat::Float32LE, -+ cubeb::SAMPLE_FLOAT32BE => pulse::SampleFormat::Float32BE, -+ _ => pulse::SampleFormat::Invalid, - } - } - - let fmt = to_pulse_format(stream_params.format); -- if fmt == PA_SAMPLE_INVALID { -+ if fmt == pulse::SampleFormat::Invalid { - return Err(cubeb::ERROR_INVALID_FORMAT); - } - -- let ss = pa_sample_spec { -+ let ss = pulse::SampleSpec { - channels: stream_params.channels as u8, -- format: fmt, -+ format: fmt.into(), - rate: stream_params.rate, - }; - -- let stream = if stream_params.layout == cubeb::LAYOUT_UNDEFINED { -- unsafe { pa_stream_new(self.context.context, stream_name, &ss, ptr::null_mut()) } -- } else { -- let cm = layout_to_channel_map(stream_params.layout); -- unsafe { pa_stream_new(self.context.context, stream_name, &ss, &cm) } -+ let cm: Option = match stream_params.layout { -+ cubeb::LAYOUT_UNDEFINED => None, -+ _ => Some(layout_to_channel_map(stream_params.layout)), - }; - -- if !stream.is_null() { -- Ok(stream) -- } else { -- Err(cubeb::ERROR) -+ let stream = pulse::Stream::new(context, stream_name, &ss, cm.as_ref()); -+ -+ match stream { -+ None => Err(cubeb::ERROR), -+ Some(stm) => Ok(stm), -+ } -+ } -+ -+ pub fn cork_stream(&self, stream: Option<&pulse::Stream>, state: CorkState) { -+ if let Some(stm) = stream { -+ if let Ok(o) = stm.cork(state.is_cork() as i32, -+ stream_success, -+ self as *const _ as *mut _) { -+ self.context.operation_wait(stream, &o); -+ } - } - } - -- fn stream_cork(&mut self, state: CorkState) { -- unsafe { pa_threaded_mainloop_lock(self.context.mainloop) }; -- self.context.pulse_stream_cork(self.output_stream, state); -- self.context.pulse_stream_cork(self.input_stream, state); -- unsafe { pa_threaded_mainloop_unlock(self.context.mainloop) }; -+ fn cork(&mut self, state: CorkState) { -+ { -+ self.context.mainloop.lock(); -+ self.cork_stream(self.output_stream.as_ref(), state); -+ self.cork_stream(self.input_stream.as_ref(), state); -+ self.context.mainloop.unlock() -+ } - - if state.is_notify() { - self.state_change_callback(if state.is_cork() { -@@ -503,18 +626,9 @@ impl<'ctx> Stream<'ctx> { - fn update_timing_info(&self) -> bool { - let mut r = false; - -- if !self.output_stream.is_null() { -- let o = unsafe { -- pa_stream_update_timing_info(self.output_stream, -- Some(stream_success_callback), -- self as *const _ as *mut _) -- }; -- -- if !o.is_null() { -- r = self.context.operation_wait(self.output_stream, o); -- unsafe { -- pa_operation_unref(o); -- } -+ if let Some(ref stm) = self.output_stream { -+ if let Ok(o) = stm.update_timing_info(stream_success, self as *const _ as *mut _) { -+ r = self.context.operation_wait(stm, &o); - } - - if !r { -@@ -522,18 +636,9 @@ impl<'ctx> Stream<'ctx> { - } - } - -- if !self.input_stream.is_null() { -- let o = unsafe { -- pa_stream_update_timing_info(self.input_stream, -- Some(stream_success_callback), -- self as *const _ as *mut _) -- }; -- -- if !o.is_null() { -- r = self.context.operation_wait(self.input_stream, o); -- unsafe { -- pa_operation_unref(o); -- } -+ if let Some(ref stm) = self.input_stream { -+ if let Ok(o) = stm.update_timing_info(stream_success, self as *const _ as *mut _) { -+ r = self.context.operation_wait(stm, &o); - } - } - -@@ -547,232 +652,162 @@ impl<'ctx> Stream<'ctx> { - } - } - -- fn wait_until_stream_ready(&self) -> bool { -- if !self.output_stream.is_null() && !wait_until_io_stream_ready(self.output_stream, self.context.mainloop) { -- return false; -- } -- -- if !self.input_stream.is_null() && !wait_until_io_stream_ready(self.input_stream, self.context.mainloop) { -- return false; -- } -- -- true -- } -- -- fn trigger_user_callback(&mut self, s: *mut pa_stream, input_data: *const c_void, nbytes: usize) { -- let frame_size = unsafe { pa_frame_size(&self.output_sample_spec) }; -- debug_assert_eq!(nbytes % frame_size, 0); -- -- let mut buffer: *mut c_void = ptr::null_mut(); -- let mut r: i32; -- -- let mut towrite = nbytes; -- let mut read_offset = 0usize; -- while towrite > 0 { -- let mut size = towrite; -- r = unsafe { pa_stream_begin_write(s, &mut buffer, &mut size) }; -- // Note: this has failed running under rr on occassion - needs investigation. -- debug_assert_eq!(r, 0); -- debug_assert!(size > 0); -- debug_assert_eq!(size % frame_size, 0); -- -- logv!("Trigger user callback with output buffer size={}, read_offset={}", -- size, -- read_offset); -- let read_ptr = unsafe { (input_data as *const u8).offset(read_offset as isize) }; -- let got = unsafe { -- self.data_callback.unwrap()(self as *const _ as *mut _, -- self.user_ptr, -- read_ptr as *const _ as *mut _, -- buffer, -- (size / frame_size) as c_long) -- }; -- if got < 0 { -- unsafe { -- pa_stream_cancel_write(s); -- } -- self.shutdown = true; -- return; -- } -- // If more iterations move offset of read buffer -- if !input_data.is_null() { -- let in_frame_size = unsafe { pa_frame_size(&self.input_sample_spec) }; -- read_offset += (size / frame_size) * in_frame_size; -+ fn wait_until_ready(&self) -> bool { -+ fn wait_until_io_stream_ready(stm: &pulse::Stream, mainloop: &pulse::ThreadedMainloop) -> bool { -+ if mainloop.is_null() { -+ return false; - } - -- if self.volume != PULSE_NO_GAIN { -- let samples = (self.output_sample_spec.channels as usize * size / frame_size) as isize; -- -- if self.output_sample_spec.format == PA_SAMPLE_S16BE || -- self.output_sample_spec.format == PA_SAMPLE_S16LE { -- let b = buffer as *mut i16; -- for i in 0..samples { -- unsafe { *b.offset(i) *= self.volume as i16 }; -- } -- } else { -- let b = buffer as *mut f32; -- for i in 0..samples { -- unsafe { *b.offset(i) *= self.volume }; -- } -+ loop { -+ let state = stm.get_state(); -+ if !state.is_good() { -+ return false; -+ } -+ if state == pulse::StreamState::Ready { -+ break; - } -+ mainloop.wait(); - } - -- r = unsafe { -- pa_stream_write(s, -- buffer, -- got as usize * frame_size, -- None, -- 0, -- PA_SEEK_RELATIVE) -- }; -- debug_assert_eq!(r, 0); -+ true -+ } - -- if (got as usize) < size / frame_size { -- let mut latency: pa_usec_t = 0; -- let rr: i32 = unsafe { pa_stream_get_latency(s, &mut latency, ptr::null_mut()) }; -- if rr == -(PA_ERR_NODATA as i32) { -- /* this needs a better guess. */ -- latency = 100 * PA_USEC_PER_MSEC; -- } -- debug_assert!(r == 0 || r == -(PA_ERR_NODATA as i32)); -- /* pa_stream_drain is useless, see PA bug# 866. this is a workaround. */ -- /* arbitrary safety margin: double the current latency. */ -- debug_assert!(self.drain_timer.is_null()); -- self.drain_timer = unsafe { -- pa_context_rttime_new(self.context.context, -- pa_rtclock_now() + 2 * latency, -- Some(stream_drain_callback), -- self as *const _ as *mut _) -- }; -- self.shutdown = true; -- return; -+ if let Some(ref stm) = self.output_stream { -+ if !wait_until_io_stream_ready(stm, &self.context.mainloop) { -+ return false; - } -- -- towrite -= size; - } - -- debug_assert_eq!(towrite, 0); -- } --} -- --unsafe extern "C" fn stream_success_callback(_s: *mut pa_stream, _success: i32, u: *mut c_void) { -- let stm = &*(u as *mut Stream); -- pa_threaded_mainloop_signal(stm.context.mainloop, 0); --} -- --unsafe extern "C" fn stream_drain_callback(a: *mut pa_mainloop_api, -- e: *mut pa_time_event, -- _tv: *const timeval, -- u: *mut c_void) { -- let mut stm = &mut *(u as *mut Stream); -- debug_assert_eq!(stm.drain_timer, e); -- stm.state_change_callback(cubeb::STATE_DRAINED); -- /* there's no pa_rttime_free, so use this instead. */ -- (*a).time_free.unwrap()(stm.drain_timer); -- stm.drain_timer = ptr::null_mut(); -- pa_threaded_mainloop_signal(stm.context.mainloop, 0); --} -- --unsafe extern "C" fn stream_state_callback(s: *mut pa_stream, u: *mut c_void) { -- let stm = &mut *(u as *mut Stream); -- if !PA_STREAM_IS_GOOD(pa_stream_get_state(s)) { -- stm.state_change_callback(cubeb::STATE_ERROR); -- } -- pa_threaded_mainloop_signal(stm.context.mainloop, 0); --} -- --fn read_from_input(s: *mut pa_stream, buffer: *mut *const c_void, size: *mut usize) -> i32 { -- let readable_size = unsafe { pa_stream_readable_size(s) }; -- if readable_size > 0 && unsafe { pa_stream_peek(s, buffer, size) } < 0 { -- return -1; -- } -- -- readable_size as i32 --} -+ if let Some(ref stm) = self.input_stream { -+ if !wait_until_io_stream_ready(stm, &self.context.mainloop) { -+ return false; -+ } -+ } - --unsafe extern "C" fn stream_write_callback(s: *mut pa_stream, nbytes: usize, u: *mut c_void) { -- logv!("Output callback to be written buffer size {}", nbytes); -- let mut stm = &mut *(u as *mut Stream); -- if stm.shutdown || stm.state != cubeb::STATE_STARTED { -- return; -+ true - } - -- if stm.input_stream.is_null() { -- // Output/playback only operation. -- // Write directly to output -- debug_assert!(!stm.output_stream.is_null()); -- stm.trigger_user_callback(s, ptr::null(), nbytes); -- } --} -+ fn trigger_user_callback(&mut self, input_data: *const c_void, nbytes: usize) { -+ fn drained_cb(a: &pulse::MainloopApi, e: *mut pa_time_event, _tv: &pulse::TimeVal, u: *mut c_void) { -+ let mut stm = unsafe { &mut *(u as *mut Stream) }; -+ debug_assert_eq!(stm.drain_timer, e); -+ stm.state_change_callback(cubeb::STATE_DRAINED); -+ /* there's no pa_rttime_free, so use this instead. */ -+ a.time_free(stm.drain_timer); -+ stm.drain_timer = ptr::null_mut(); -+ stm.context.mainloop.signal(); -+ } -+ -+ if let Some(ref stm) = self.output_stream { -+ -+ let frame_size = self.output_sample_spec.frame_size(); -+ debug_assert_eq!(nbytes % frame_size, 0); -+ -+ let mut towrite = nbytes; -+ let mut read_offset = 0usize; -+ while towrite > 0 { -+ match stm.begin_write(towrite) { -+ Err(e) => { -+ panic!("Failed to write data: {}", e); -+ }, -+ Ok((buffer, size)) => { -+ debug_assert!(size > 0); -+ debug_assert_eq!(size % frame_size, 0); -+ -+ logv!("Trigger user callback with output buffer size={}, read_offset={}", -+ size, -+ read_offset); -+ let read_ptr = unsafe { (input_data as *const u8).offset(read_offset as isize) }; -+ let got = unsafe { -+ self.data_callback.unwrap()(self as *const _ as *mut _, -+ self.user_ptr, -+ read_ptr as *const _ as *mut _, -+ buffer, -+ (size / frame_size) as c_long) -+ }; -+ if got < 0 { -+ let _ = stm.cancel_write(); -+ self.shutdown = true; -+ return; -+ } -+ -+ // If more iterations move offset of read buffer -+ if !input_data.is_null() { -+ let in_frame_size = self.input_sample_spec.frame_size(); -+ read_offset += (size / frame_size) * in_frame_size; -+ } -+ -+ if self.volume != PULSE_NO_GAIN { -+ let samples = (self.output_sample_spec.channels as usize * size / frame_size) as isize; -+ -+ if self.output_sample_spec.format == PA_SAMPLE_S16BE || -+ self.output_sample_spec.format == PA_SAMPLE_S16LE { -+ let b = buffer as *mut i16; -+ for i in 0..samples { -+ unsafe { *b.offset(i) *= self.volume as i16 }; -+ } -+ } else { -+ let b = buffer as *mut f32; -+ for i in 0..samples { -+ unsafe { *b.offset(i) *= self.volume }; -+ } -+ } -+ } -+ -+ let r = stm.write(buffer, -+ got as usize * frame_size, -+ 0, -+ pulse::SeekMode::Relative); -+ debug_assert!(r.is_ok()); -+ -+ if (got as usize) < size / frame_size { -+ let latency = match stm.get_latency() { -+ Ok((l, negative)) => { -+ assert_ne!(negative, true); -+ l -+ }, -+ Err(e) => { -+ debug_assert_eq!(e, pulse::ErrorCode::from_error_code(PA_ERR_NODATA)); -+ /* this needs a better guess. */ -+ 100 * PA_USEC_PER_MSEC -+ }, -+ }; -+ -+ /* pa_stream_drain is useless, see PA bug# 866. this is a workaround. */ -+ /* arbitrary safety margin: double the current latency. */ -+ debug_assert!(self.drain_timer.is_null()); -+ let stream_ptr = self as *const _ as *mut _; -+ if let Some(ref context) = self.context.context { -+ self.drain_timer = -+ context.rttime_new(pulse::rtclock_now() + 2 * latency, drained_cb, stream_ptr); -+ } -+ self.shutdown = true; -+ return; -+ } - --unsafe extern "C" fn stream_read_callback(s: *mut pa_stream, nbytes: usize, u: *mut c_void) { -- logv!("Input callback buffer size {}", nbytes); -- let mut stm = &mut *(u as *mut Stream); -- if stm.shutdown { -- return; -- } -- -- let mut read_data: *const c_void = ptr::null(); -- let mut read_size: usize = 0; -- while read_from_input(s, &mut read_data, &mut read_size) > 0 { -- /* read_data can be NULL in case of a hole. */ -- if !read_data.is_null() { -- let in_frame_size = pa_frame_size(&stm.input_sample_spec); -- let read_frames = read_size / in_frame_size; -- -- if !stm.output_stream.is_null() { -- // input/capture + output/playback operation -- let out_frame_size = pa_frame_size(&stm.output_sample_spec); -- let write_size = read_frames * out_frame_size; -- // Offer full duplex data for writing -- let stream = stm.output_stream; -- stm.trigger_user_callback(stream, read_data, write_size); -- } else { -- // input/capture only operation. Call callback directly -- let got = stm.data_callback.unwrap()(stm as *mut _ as *mut _, -- stm.user_ptr, -- read_data, -- ptr::null_mut(), -- read_frames as c_long); -- if got < 0 || got as usize != read_frames { -- pa_stream_cancel_write(s); -- stm.shutdown = true; -- break; -+ towrite -= size; -+ }, - } - } -- } -- -- if read_size > 0 { -- pa_stream_drop(s); -- } -- -- if stm.shutdown { -- return; -+ debug_assert_eq!(towrite, 0); - } - } - } - --fn wait_until_io_stream_ready(stream: *mut pa_stream, mainloop: *mut pa_threaded_mainloop) -> bool { -- if stream.is_null() || mainloop.is_null() { -- return false; -- } -- -- loop { -- let state = unsafe { pa_stream_get_state(stream) }; -- if !PA_STREAM_IS_GOOD(state) { -- return false; -- } -- if state == PA_STREAM_READY { -- break; -- } -- unsafe { pa_threaded_mainloop_wait(mainloop) }; -- } -+fn stream_success(_: &pulse::Stream, success: i32, u: *mut c_void) { -+ let stm = unsafe { &*(u as *mut Stream) }; -+ debug_assert_ne!(success, 0); -+ stm.context.mainloop.signal(); -+} - -- true -+fn context_success(_: &pulse::Context, success: i32, u: *mut c_void) { -+ let ctx = unsafe { &*(u as *mut Context) }; -+ debug_assert_ne!(success, 0); -+ ctx.mainloop.signal(); - } - - fn set_buffering_attribute(latency_frames: u32, sample_spec: &pa_sample_spec) -> pa_buffer_attr { -- let tlength = latency_frames * unsafe { pa_frame_size(sample_spec) } as u32; -+ let tlength = latency_frames * sample_spec.frame_size() as u32; - let minreq = tlength / 4; - let battr = pa_buffer_attr { - maxlength: u32::max_value(), -@@ -791,34 +826,3 @@ fn set_buffering_attribute(latency_frame - - battr - } -- --unsafe extern "C" fn pulse_defer_event_cb(_a: *mut pa_mainloop_api, u: *mut c_void) { -- let mut stm = &mut *(u as *mut Stream); -- if stm.shutdown { -- return; -- } -- let writable_size = pa_stream_writable_size(stm.output_stream); -- let stream = stm.output_stream; -- stm.trigger_user_callback(stream, ptr::null_mut(), writable_size); --} -- --#[repr(C)] --struct SinkInputInfoResult { -- pub cvol: *mut pa_cvolume, -- pub mainloop: *mut pa_threaded_mainloop, --} -- --unsafe extern "C" fn sink_input_info_cb(_c: *mut pa_context, i: *const pa_sink_input_info, eol: i32, u: *mut c_void) { -- let info = &*i; -- let mut r = &mut *(u as *mut SinkInputInfoResult); -- if eol == 0 { -- *r.cvol = info.volume; -- } -- pa_threaded_mainloop_signal(r.mainloop, 0); --} -- --unsafe extern "C" fn volume_success(_c: *mut pa_context, success: i32, u: *mut c_void) { -- let stm = &*(u as *mut Stream); -- debug_assert_ne!(success, 0); -- pa_threaded_mainloop_signal(stm.context.mainloop, 0); --} -diff -up firefox-55.0/media/libcubeb/cubeb-pulse-rs/src/capi.rs.cubeb-pulse-arm firefox-55.0/media/libcubeb/cubeb-pulse-rs/src/capi.rs ---- firefox-55.0/media/libcubeb/cubeb-pulse-rs/src/capi.rs.cubeb-pulse-arm 2017-07-31 18:20:49.000000000 +0200 -+++ firefox-55.0/media/libcubeb/cubeb-pulse-rs/src/capi.rs 2017-08-04 13:37:46.387821728 +0200 -@@ -5,6 +5,7 @@ - - use backend; - use cubeb; -+use std::ffi::CStr; - use std::os::raw::{c_char, c_void}; - - unsafe extern "C" fn capi_init(c: *mut *mut cubeb::Context, context_name: *const c_char) -> i32 { -@@ -114,21 +115,18 @@ unsafe extern "C" fn capi_stream_init(c: - state_callback: cubeb::StateCallback, - user_ptr: *mut c_void) - -> i32 { -+ fn try_stream_params_from(sp: *mut cubeb::StreamParams) -> Option { -+ if sp.is_null() { None } else { Some(unsafe { *sp }) } -+ } -+ - let mut ctx = &mut *(c as *mut backend::Context); -+ let stream_name = CStr::from_ptr(stream_name); - - match ctx.new_stream(stream_name, - input_device, -- if input_stream_params.is_null() { -- None -- } else { -- Some(*input_stream_params) -- }, -+ try_stream_params_from(input_stream_params), - output_device, -- if output_stream_params.is_null() { -- None -- } else { -- Some(*output_stream_params) -- }, -+ try_stream_params_from(output_stream_params), - latency_frames, - data_callback, - state_callback, -diff -up firefox-55.0/media/libcubeb/cubeb-pulse-rs/src/lib.rs.cubeb-pulse-arm firefox-55.0/media/libcubeb/cubeb-pulse-rs/src/lib.rs ---- firefox-55.0/media/libcubeb/cubeb-pulse-rs/src/lib.rs.cubeb-pulse-arm 2017-07-31 18:20:49.000000000 +0200 -+++ firefox-55.0/media/libcubeb/cubeb-pulse-rs/src/lib.rs 2017-08-04 13:37:46.387821728 +0200 -@@ -8,6 +8,7 @@ - #[macro_use] - extern crate cubeb_ffi as cubeb; - extern crate pulse_ffi; -+extern crate pulse; - extern crate semver; - - mod capi; -diff -up firefox-55.0/media/libcubeb/cubeb-pulse-rs/update.sh.cubeb-pulse-arm firefox-55.0/media/libcubeb/cubeb-pulse-rs/update.sh ---- firefox-55.0/media/libcubeb/cubeb-pulse-rs/update.sh.cubeb-pulse-arm 2017-07-31 18:20:49.000000000 +0200 -+++ firefox-55.0/media/libcubeb/cubeb-pulse-rs/update.sh 2017-08-04 13:37:46.383821740 +0200 -@@ -13,6 +13,9 @@ cp -pr $1/cubeb-ffi/src/* cubeb-ffi/src/ - test -d pulse-ffi/src || mkdir -p pulse-ffi/src - cp -pr $1/pulse-ffi/Cargo.toml pulse-ffi/ - cp -pr $1/pulse-ffi/src/* pulse-ffi/src/ -+test -d pulse-rs/src || mkdir -p pulse-rs/src -+cp -pr $1/pulse-rs/Cargo.toml pulse-rs/ -+cp -pr $1/pulse-rs/src/* pulse-rs/src/ - - if [ -d $1/.git ]; then - rev=$(cd $1 && git rev-parse --verify HEAD) -diff -up firefox-55.0/toolkit/library/gtest/rust/Cargo.lock.cubeb-pulse-arm firefox-55.0/toolkit/library/gtest/rust/Cargo.lock ---- firefox-55.0/toolkit/library/gtest/rust/Cargo.lock.cubeb-pulse-arm 2017-08-04 13:37:46.388821725 +0200 -+++ firefox-55.0/toolkit/library/gtest/rust/Cargo.lock 2017-08-04 13:59:15.592940994 +0200 -@@ -252,6 +252,7 @@ name = "cubeb-pulse" - version = "0.0.1" - dependencies = [ - "cubeb-ffi 0.0.1", -+ "pulse 0.1.0", - "pulse-ffi 0.1.0", - "semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - ] -@@ -660,6 +661,14 @@ version = "0.1.1" - source = "registry+https://github.com/rust-lang/crates.io-index" - - [[package]] -+name = "pulse" -+version = "0.1.0" -+dependencies = [ -+ "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "pulse-ffi 0.1.0", -+] -+ -+[[package]] - name = "pulse-ffi" - version = "0.1.0" - dependencies = [ -diff -up firefox-55.0/toolkit/library/rust/Cargo.lock.cubeb-pulse-arm firefox-55.0/toolkit/library/rust/Cargo.lock ---- firefox-55.0/toolkit/library/rust/Cargo.lock.cubeb-pulse-arm 2017-08-04 13:37:46.388821725 +0200 -+++ firefox-55.0/toolkit/library/rust/Cargo.lock 2017-08-04 13:52:24.551163669 +0200 -@@ -250,6 +250,7 @@ name = "cubeb-pulse" - version = "0.0.1" - dependencies = [ - "cubeb-ffi 0.0.1", -+ "pulse 0.1.0", - "pulse-ffi 0.1.0", - "semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - ] -@@ -647,6 +648,14 @@ version = "0.1.1" - source = "registry+https://github.com/rust-lang/crates.io-index" - - [[package]] -+name = "pulse" -+version = "0.1.0" -+dependencies = [ -+ "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "pulse-ffi 0.1.0", -+] -+ -+[[package]] - name = "pulse-ffi" - version = "0.1.0" - dependencies = [ diff --git a/fedora-build.patch b/fedora-build.patch deleted file mode 100644 index 74127ec..0000000 --- a/fedora-build.patch +++ /dev/null @@ -1,23 +0,0 @@ -diff -up firefox-54.0/media/libyuv/libyuv/tools_libyuv/autoroller/unittests/testdata/DEPS.chromium.old firefox-54.0/media/libyuv/libyuv/tools_libyuv/autoroller/unittests/testdata/DEPS.chromium -diff -up firefox-54.0/media/mtransport/third_party/nICEr/nicer.gyp.old firefox-54.0/media/mtransport/third_party/nICEr/nicer.gyp ---- firefox-54.0/media/mtransport/third_party/nICEr/nicer.gyp.old 2017-06-08 14:59:08.786996664 +0200 -+++ firefox-54.0/media/mtransport/third_party/nICEr/nicer.gyp 2017-06-08 14:59:22.642946570 +0200 -@@ -211,7 +211,6 @@ - '-Wno-parentheses', - '-Wno-strict-prototypes', - '-Wmissing-prototypes', -- '-Wno-format', - ], - 'defines' : [ - 'LINUX', -diff -up firefox-54.0/media/mtransport/third_party/nrappkit/nrappkit.gyp.build firefox-54.0/media/mtransport/third_party/nrappkit/nrappkit.gyp ---- firefox-54.0/media/mtransport/third_party/nrappkit/nrappkit.gyp.build 2017-06-08 15:08:03.627063097 +0200 -+++ firefox-54.0/media/mtransport/third_party/nrappkit/nrappkit.gyp 2017-06-08 15:08:15.657019606 +0200 -@@ -206,7 +206,6 @@ - '-Wno-parentheses', - '-Wno-strict-prototypes', - '-Wmissing-prototypes', -- '-Wno-format', - ], - 'defines' : [ - 'LINUX', diff --git a/firefox-kde-webrender.patch b/firefox-kde-webrender.patch deleted file mode 100644 index f5f4ac7..0000000 --- a/firefox-kde-webrender.patch +++ /dev/null @@ -1,33 +0,0 @@ -diff -up firefox-87.0/widget/GfxInfoX11.cpp.firefox-kde-webrender firefox-87.0/widget/GfxInfoX11.cpp ---- firefox-87.0/widget/GfxInfoX11.cpp.firefox-kde-webrender 2021-03-22 19:55:59.169952960 +0100 -+++ firefox-87.0/widget/GfxInfoX11.cpp 2021-03-22 20:04:35.332183657 +0100 -@@ -738,6 +738,14 @@ const nsTArray& GfxInfo:: - DRIVER_GREATER_THAN_OR_EQUAL, V(17, 0, 0, 0), - "FEATURE_ROLLOUT_INTEL_GNOME_WAYLAND_MESA", "Mesa 17.0.0.0"); - -+ APPEND_TO_DRIVER_BLOCKLIST_EXT( -+ OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All, -+ DesktopEnvironment::KDE, WindowProtocol::Wayland, -+ DriverVendor::MesaAll, DeviceFamily::IntelRolloutWebRender, -+ nsIGfxInfo::FEATURE_WEBRENDER, nsIGfxInfo::FEATURE_ALLOW_ALWAYS, -+ DRIVER_GREATER_THAN_OR_EQUAL, V(17, 0, 0, 0), -+ "FEATURE_ROLLOUT_INTEL_GNOME_WAYLAND_MESA", "Mesa 17.0.0.0"); -+ - // ATI Mesa baseline, chosen arbitrarily. - APPEND_TO_DRIVER_BLOCKLIST_EXT( - OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All, -@@ -754,6 +762,14 @@ const nsTArray& GfxInfo:: - DRIVER_GREATER_THAN_OR_EQUAL, V(17, 0, 0, 0), - "FEATURE_ROLLOUT_ATI_GNOME_WAYLAND_MESA", "Mesa 17.0.0.0"); - -+ APPEND_TO_DRIVER_BLOCKLIST_EXT( -+ OperatingSystem::Linux, ScreenSizeStatus::All, BatteryStatus::All, -+ DesktopEnvironment::KDE, WindowProtocol::Wayland, -+ DriverVendor::MesaAll, DeviceFamily::AtiRolloutWebRender, -+ nsIGfxInfo::FEATURE_WEBRENDER, nsIGfxInfo::FEATURE_ALLOW_ALWAYS, -+ DRIVER_GREATER_THAN_OR_EQUAL, V(17, 0, 0, 0), -+ "FEATURE_ROLLOUT_ATI_GNOME_WAYLAND_MESA", "Mesa 17.0.0.0"); -+ - #ifdef EARLY_BETA_OR_EARLIER - // Intel Mesa baseline, chosen arbitrarily. - APPEND_TO_DRIVER_BLOCKLIST_EXT( diff --git a/firefox.spec b/firefox.spec index f970fe1..221882a 100644 --- a/firefox.spec +++ b/firefox.spec @@ -1076,6 +1076,7 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : * Tue Aug 23 2022 Kalev Lember - 104.0-5 - Use constrain_build macro to simplify parallel make handling - Drop obsolete build conditionals +- Drop unused patches * Tue Aug 23 2022 Jan Horak - 104.0-4 - Rebuild due to ppc64le fixes diff --git a/mozilla-1640982.patch b/mozilla-1640982.patch deleted file mode 100644 index b63ba3b..0000000 --- a/mozilla-1640982.patch +++ /dev/null @@ -1,16 +0,0 @@ -diff --git a/config/makefiles/rust.mk b/config/makefiles/rust.mk ---- a/config/makefiles/rust.mk -+++ b/config/makefiles/rust.mk -@@ -61,7 +61,11 @@ - # Enable link-time optimization for release builds, but not when linking - # gkrust_gtest. - ifeq (,$(findstring gkrust_gtest,$(RUST_LIBRARY_FILE))) -+# Pass -Clto for older versions of rust, and CARGO_PROFILE_RELEASE_LTO=true -+# for newer ones that support it. Combining the latter with -Clto works, so -+# set both everywhere. - cargo_rustc_flags += -Clto -+export CARGO_PROFILE_RELEASE_LTO=true - endif - endif - endif - diff --git a/mozilla-1672139.patch b/mozilla-1672139.patch deleted file mode 100644 index efd40cb..0000000 --- a/mozilla-1672139.patch +++ /dev/null @@ -1,91 +0,0 @@ -diff --git a/gfx/layers/ipc/CompositorBridgeParent.cpp b/gfx/layers/ipc/CompositorBridgeParent.cpp ---- a/gfx/layers/ipc/CompositorBridgeParent.cpp -+++ b/gfx/layers/ipc/CompositorBridgeParent.cpp -@@ -2376,30 +2376,28 @@ - if (mWrBridge->PipelineId() == aPipelineId) { - mWrBridge->RemoveEpochDataPriorTo(aEpoch); - -- if (!mPaused) { -- if (mIsForcedFirstPaint) { -- uiController->NotifyFirstPaint(); -- mIsForcedFirstPaint = false; -- } -- -- std::pair key(aPipelineId, aEpoch); -- nsTArray payload = -- mWrBridge->TakePendingScrollPayload(key); -- if (!payload.IsEmpty()) { -- RecordCompositionPayloadsPresented(payload); -- } -- -- TransactionId transactionId = mWrBridge->FlushTransactionIdsForEpoch( -- aEpoch, aCompositeStartId, aCompositeStart, aRenderStart, -- aCompositeEnd, uiController); -- Unused << SendDidComposite(LayersId{0}, transactionId, aCompositeStart, -- aCompositeEnd); -- -- nsTArray notifications; -- mWrBridge->ExtractImageCompositeNotifications(¬ifications); -- if (!notifications.IsEmpty()) { -- Unused << ImageBridgeParent::NotifyImageComposites(notifications); -- } -+ if (mIsForcedFirstPaint) { -+ uiController->NotifyFirstPaint(); -+ mIsForcedFirstPaint = false; -+ } -+ -+ std::pair key(aPipelineId, aEpoch); -+ nsTArray payload = -+ mWrBridge->TakePendingScrollPayload(key); -+ if (!payload.IsEmpty()) { -+ RecordCompositionPayloadsPresented(payload); -+ } -+ -+ TransactionId transactionId = mWrBridge->FlushTransactionIdsForEpoch( -+ aEpoch, aCompositeStartId, aCompositeStart, aRenderStart, aCompositeEnd, -+ uiController); -+ Unused << SendDidComposite(LayersId{0}, transactionId, aCompositeStart, -+ aCompositeEnd); -+ -+ nsTArray notifications; -+ mWrBridge->ExtractImageCompositeNotifications(¬ifications); -+ if (!notifications.IsEmpty()) { -+ Unused << ImageBridgeParent::NotifyImageComposites(notifications); - } - return; - } -@@ -2408,21 +2406,19 @@ - if (wrBridge && wrBridge->GetCompositorBridge()) { - MOZ_ASSERT(!wrBridge->IsRootWebRenderBridgeParent()); - wrBridge->RemoveEpochDataPriorTo(aEpoch); -- if (!mPaused) { -- std::pair key(aPipelineId, aEpoch); -- nsTArray payload = -- wrBridge->TakePendingScrollPayload(key); -- if (!payload.IsEmpty()) { -- RecordCompositionPayloadsPresented(payload); -- } -- -- TransactionId transactionId = wrBridge->FlushTransactionIdsForEpoch( -- aEpoch, aCompositeStartId, aCompositeStart, aRenderStart, -- aCompositeEnd, uiController, aStats, &stats); -- Unused << wrBridge->GetCompositorBridge()->SendDidComposite( -- wrBridge->GetLayersId(), transactionId, aCompositeStart, -- aCompositeEnd); -+ -+ std::pair key(aPipelineId, aEpoch); -+ nsTArray payload = -+ wrBridge->TakePendingScrollPayload(key); -+ if (!payload.IsEmpty()) { -+ RecordCompositionPayloadsPresented(payload); - } -+ -+ TransactionId transactionId = wrBridge->FlushTransactionIdsForEpoch( -+ aEpoch, aCompositeStartId, aCompositeStart, aRenderStart, aCompositeEnd, -+ uiController, aStats, &stats); -+ Unused << wrBridge->GetCompositorBridge()->SendDidComposite( -+ wrBridge->GetLayersId(), transactionId, aCompositeStart, aCompositeEnd); - } - - if (!stats.IsEmpty()) { - diff --git a/mozilla-1673313.patch b/mozilla-1673313.patch deleted file mode 100644 index 549243b..0000000 --- a/mozilla-1673313.patch +++ /dev/null @@ -1,351 +0,0 @@ -changeset: 556172:143b4ca96ec9 -tag: tip -parent: 556169:61c35792ca70 -user: stransky -date: Mon Oct 26 12:15:49 2020 +0100 -files: widget/gtk/WindowSurfaceWayland.cpp widget/gtk/WindowSurfaceWayland.h -description: -Bug 1673313 [Wayland] Don't fail when Shm allocation fails, r?jhorak - -- Make WaylandAllocateShmMemory() fallible. -- Implement WaylandReAllocateShmMemory() to re-allocate Shm pool. -- Remove WaylandShmPool::Resize() and use WaylandShmPool::Create() only. -- Implement and use WaylandShmPool::Release(). -- Make WindowSurfaceWayland::CreateWaylandBuffer() as fallible. - -Differential Revision: https://phabricator.services.mozilla.com/D94735 - - -diff --git a/widget/gtk/WindowSurfaceWayland.cpp b/widget/gtk/WindowSurfaceWayland.cpp ---- a/widget/gtk/WindowSurfaceWayland.cpp -+++ b/widget/gtk/WindowSurfaceWayland.cpp -@@ -209,14 +209,23 @@ RefPtr WindowBackBuffe - } - - static int WaylandAllocateShmMemory(int aSize) { -- static int counter = 0; -- nsPrintfCString shmName("/wayland.mozilla.ipc.%d", counter++); -- int fd = shm_open(shmName.get(), O_CREAT | O_RDWR | O_EXCL, 0600); -- if (fd >= 0) { -- shm_unlink(shmName.get()); -- } else { -- printf_stderr("Unable to SHM memory segment\n"); -- MOZ_CRASH(); -+ int fd = -1; -+ do { -+ static int counter = 0; -+ nsPrintfCString shmName("/wayland.mozilla.ipc.%d", counter++); -+ fd = shm_open(shmName.get(), O_CREAT | O_RDWR | O_EXCL, 0600); -+ if (fd >= 0) { -+ // We don't want to use leaked file -+ if (shm_unlink(shmName.get()) != 0) { -+ NS_WARNING("shm_unlink failed"); -+ return -1; -+ } -+ } -+ } while (fd < 0 && errno == EEXIST); -+ -+ if (fd < 0) { -+ NS_WARNING(nsPrintfCString("shm_open failed: %s", strerror(errno)).get()); -+ return -1; - } - - int ret = 0; -@@ -225,59 +234,103 @@ static int WaylandAllocateShmMemory(int - ret = posix_fallocate(fd, 0, aSize); - } while (ret == EINTR); - if (ret != 0) { -+ NS_WARNING( -+ nsPrintfCString("posix_fallocate() fails to allocate shm memory: %s", -+ strerror(ret)) -+ .get()); - close(fd); -- MOZ_CRASH("posix_fallocate() fails to allocate shm memory"); -+ return -1; - } - #else - do { - ret = ftruncate(fd, aSize); - } while (ret < 0 && errno == EINTR); - if (ret < 0) { -+ NS_WARNING(nsPrintfCString("ftruncate() fails to allocate shm memory: %s", -+ strerror(ret)) -+ .get()); - close(fd); -- MOZ_CRASH("ftruncate() fails to allocate shm memory"); -+ fd = -1; - } - #endif - - return fd; - } - --WaylandShmPool::WaylandShmPool(RefPtr aWaylandDisplay, -- int aSize) -- : mAllocatedSize(aSize) { -- mShmPoolFd = WaylandAllocateShmMemory(mAllocatedSize); -- mImageData = mmap(nullptr, mAllocatedSize, PROT_READ | PROT_WRITE, MAP_SHARED, -- mShmPoolFd, 0); -- MOZ_RELEASE_ASSERT(mImageData != MAP_FAILED, -- "Unable to map drawing surface!"); -+static bool WaylandReAllocateShmMemory(int aFd, int aSize) { -+ if (ftruncate(aFd, aSize) < 0) { -+ return false; -+ } -+#ifdef HAVE_POSIX_FALLOCATE -+ do { -+ errno = posix_fallocate(aFd, 0, aSize); -+ } while (errno == EINTR); -+ if (errno != 0) { -+ return false; -+ } -+#endif -+ return true; -+} - -- mShmPool = -- wl_shm_create_pool(aWaylandDisplay->GetShm(), mShmPoolFd, mAllocatedSize); -+WaylandShmPool::WaylandShmPool() -+ : mShmPool(nullptr), -+ mShmPoolFd(-1), -+ mAllocatedSize(0), -+ mImageData(MAP_FAILED){}; - -- // We set our queue to get mShmPool events at compositor thread. -- wl_proxy_set_queue((struct wl_proxy*)mShmPool, -- aWaylandDisplay->GetEventQueue()); -+void WaylandShmPool::Release() { -+ if (mImageData != MAP_FAILED) { -+ munmap(mImageData, mAllocatedSize); -+ mImageData = MAP_FAILED; -+ } -+ if (mShmPool) { -+ wl_shm_pool_destroy(mShmPool); -+ mShmPool = 0; -+ } -+ if (mShmPoolFd >= 0) { -+ close(mShmPoolFd); -+ mShmPoolFd = -1; -+ } - } - --bool WaylandShmPool::Resize(int aSize) { -+bool WaylandShmPool::Create(RefPtr aWaylandDisplay, -+ int aSize) { - // We do size increase only -- if (aSize <= mAllocatedSize) return true; -- -- if (ftruncate(mShmPoolFd, aSize) < 0) return false; -+ if (aSize <= mAllocatedSize) { -+ return true; -+ } - --#ifdef HAVE_POSIX_FALLOCATE -- do { -- errno = posix_fallocate(mShmPoolFd, 0, aSize); -- } while (errno == EINTR); -- if (errno != 0) return false; --#endif -+ if (mShmPoolFd < 0) { -+ mShmPoolFd = WaylandAllocateShmMemory(aSize); -+ if (mShmPoolFd < 0) { -+ return false; -+ } -+ } else { -+ if (!WaylandReAllocateShmMemory(mShmPoolFd, aSize)) { -+ Release(); -+ return false; -+ } -+ } - -- wl_shm_pool_resize(mShmPool, aSize); -- -- munmap(mImageData, mAllocatedSize); -- -+ if (mImageData != MAP_FAILED) { -+ munmap(mImageData, mAllocatedSize); -+ } - mImageData = - mmap(nullptr, aSize, PROT_READ | PROT_WRITE, MAP_SHARED, mShmPoolFd, 0); -- if (mImageData == MAP_FAILED) return false; -+ if (mImageData == MAP_FAILED) { -+ NS_WARNING("Unable to map drawing surface!"); -+ Release(); -+ return false; -+ } -+ -+ if (mShmPool) { -+ wl_shm_pool_resize(mShmPool, aSize); -+ } else { -+ mShmPool = wl_shm_create_pool(aWaylandDisplay->GetShm(), mShmPoolFd, aSize); -+ // We set our queue to get mShmPool events at compositor thread. -+ wl_proxy_set_queue((struct wl_proxy*)mShmPool, -+ aWaylandDisplay->GetEventQueue()); -+ } - - mAllocatedSize = aSize; - return true; -@@ -289,11 +342,7 @@ void WaylandShmPool::SetImageDataFromPoo - memcpy(mImageData, aSourcePool->GetImageData(), aImageDataSize); - } - --WaylandShmPool::~WaylandShmPool() { -- munmap(mImageData, mAllocatedSize); -- wl_shm_pool_destroy(mShmPool); -- close(mShmPoolFd); --} -+WaylandShmPool::~WaylandShmPool() { Release(); } - - static void buffer_release(void* data, wl_buffer* buffer) { - auto surface = reinterpret_cast(data); -@@ -302,14 +351,14 @@ static void buffer_release(void* data, w - - static const struct wl_buffer_listener buffer_listener = {buffer_release}; - --void WindowBackBufferShm::Create(int aWidth, int aHeight) { -+bool WindowBackBufferShm::Create(int aWidth, int aHeight) { - MOZ_ASSERT(!IsAttached(), "We can't create attached buffers."); -- MOZ_ASSERT(!mWLBuffer, "there is wl_buffer already!"); - -- int newBufferSize = aWidth * aHeight * BUFFER_BPP; -- if (!mShmPool.Resize(newBufferSize)) { -- mWLBuffer = nullptr; -- return; -+ ReleaseShmSurface(); -+ -+ int size = aWidth * aHeight * BUFFER_BPP; -+ if (!mShmPool.Create(GetWaylandDisplay(), size)) { -+ return false; - } - - mWLBuffer = -@@ -325,14 +374,16 @@ void WindowBackBufferShm::Create(int aWi - LOGWAYLAND(("WindowBackBufferShm::Create [%p] wl_buffer %p ID %d\n", - (void*)this, (void*)mWLBuffer, - mWLBuffer ? wl_proxy_get_id((struct wl_proxy*)mWLBuffer) : -1)); -+ return true; - } - - void WindowBackBufferShm::ReleaseShmSurface() { - LOGWAYLAND(("WindowBackBufferShm::Release [%p]\n", (void*)this)); -- -- wl_buffer_destroy(mWLBuffer); -+ if (mWLBuffer) { -+ wl_buffer_destroy(mWLBuffer); -+ mWLBuffer = nullptr; -+ } - mWidth = mHeight = 0; -- mWLBuffer = nullptr; - } - - void WindowBackBufferShm::Clear() { -@@ -340,16 +391,13 @@ void WindowBackBufferShm::Clear() { - } - - WindowBackBufferShm::WindowBackBufferShm( -- WindowSurfaceWayland* aWindowSurfaceWayland, int aWidth, int aHeight) -+ WindowSurfaceWayland* aWindowSurfaceWayland) - : WindowBackBuffer(aWindowSurfaceWayland), -- mShmPool(aWindowSurfaceWayland->GetWaylandDisplay(), -- aWidth * aHeight * BUFFER_BPP), -+ mShmPool(), - mWLBuffer(nullptr), -- mWidth(aWidth), -- mHeight(aHeight), -- mAttached(false) { -- Create(aWidth, aHeight); --} -+ mWidth(0), -+ mHeight(0), -+ mAttached(false) {} - - WindowBackBufferShm::~WindowBackBufferShm() { ReleaseShmSurface(); } - -@@ -357,13 +405,9 @@ bool WindowBackBufferShm::Resize(int aWi - if (aWidth == mWidth && aHeight == mHeight) { - return true; - } -- - LOGWAYLAND(("WindowBackBufferShm::Resize [%p] %d %d\n", (void*)this, aWidth, - aHeight)); -- -- ReleaseShmSurface(); - Create(aWidth, aHeight); -- - return (mWLBuffer != nullptr); - } - -@@ -488,11 +532,13 @@ WindowBackBuffer* WindowSurfaceWayland:: - return nullptr; - } - -- WindowBackBuffer* buffer = new WindowBackBufferShm(this, aWidth, aHeight); -- if (buffer) { -- mShmBackupBuffer[availableBuffer] = buffer; -+ WindowBackBuffer* buffer = new WindowBackBufferShm(this); -+ if (!buffer->Create(aWidth, aHeight)) { -+ delete buffer; -+ return nullptr; - } - -+ mShmBackupBuffer[availableBuffer] = buffer; - return buffer; - } - -diff --git a/widget/gtk/WindowSurfaceWayland.h b/widget/gtk/WindowSurfaceWayland.h ---- a/widget/gtk/WindowSurfaceWayland.h -+++ b/widget/gtk/WindowSurfaceWayland.h -@@ -25,14 +25,14 @@ class WindowSurfaceWayland; - // Allocates and owns shared memory for Wayland drawing surface - class WaylandShmPool { - public: -- WaylandShmPool(RefPtr aDisplay, int aSize); -- ~WaylandShmPool(); -- -- bool Resize(int aSize); -+ bool Create(RefPtr aWaylandDisplay, int aSize); -+ void Release(); - wl_shm_pool* GetShmPool() { return mShmPool; }; - void* GetImageData() { return mImageData; }; - void SetImageDataFromPool(class WaylandShmPool* aSourcePool, - int aImageDataSize); -+ WaylandShmPool(); -+ ~WaylandShmPool(); - - private: - wl_shm_pool* mShmPool; -@@ -53,6 +53,7 @@ class WindowBackBuffer { - virtual bool IsAttached() = 0; - - virtual void Clear() = 0; -+ virtual bool Create(int aWidth, int aHeight) = 0; - virtual bool Resize(int aWidth, int aHeight) = 0; - - virtual int GetWidth() = 0; -@@ -87,8 +88,7 @@ class WindowBackBuffer { - - class WindowBackBufferShm : public WindowBackBuffer { - public: -- WindowBackBufferShm(WindowSurfaceWayland* aWindowSurfaceWayland, int aWidth, -- int aHeight); -+ WindowBackBufferShm(WindowSurfaceWayland* aWindowSurfaceWayland); - ~WindowBackBufferShm(); - - already_AddRefed Lock(); -@@ -100,6 +100,7 @@ class WindowBackBufferShm : public Windo - void SetAttached() { mAttached = true; }; - - void Clear(); -+ bool Create(int aWidth, int aHeight); - bool Resize(int aWidth, int aHeight); - bool SetImageDataFromBuffer(class WindowBackBuffer* aSourceBuffer); - -@@ -109,7 +110,6 @@ class WindowBackBufferShm : public Windo - wl_buffer* GetWlBuffer() { return mWLBuffer; }; - - private: -- void Create(int aWidth, int aHeight); - void ReleaseShmSurface(); - - // WaylandShmPool provides actual shared memory we draw into - diff --git a/mozilla-1700520.patch b/mozilla-1700520.patch deleted file mode 100644 index c93cbe2..0000000 --- a/mozilla-1700520.patch +++ /dev/null @@ -1,51 +0,0 @@ -diff --git a/gfx/wr/swgl/src/blend.h b/gfx/wr/swgl/src/blend.h ---- a/gfx/wr/swgl/src/blend.h -+++ b/gfx/wr/swgl/src/blend.h -@@ -405,7 +405,7 @@ - blend_key = BlendKey(AA_BLEND_KEY_NONE + blend_key); - } - --static ALWAYS_INLINE WideRGBA8 blend_pixels(uint32_t* buf, PackedRGBA8 pdst, -+static PREFER_INLINE WideRGBA8 blend_pixels(uint32_t* buf, PackedRGBA8 pdst, - WideRGBA8 src, int span = 4) { - WideRGBA8 dst = unpack(pdst); - const WideRGBA8 RGB_MASK = {0xFFFF, 0xFFFF, 0xFFFF, 0, 0xFFFF, 0xFFFF, -@@ -686,7 +686,7 @@ - // clang-format on - } - --static ALWAYS_INLINE WideR8 blend_pixels(uint8_t* buf, WideR8 dst, WideR8 src, -+static PREFER_INLINE WideR8 blend_pixels(uint8_t* buf, WideR8 dst, WideR8 src, - int span = 4) { - // clang-format off - #define BLEND_CASE_KEY(key) \ -diff --git a/gfx/wr/swgl/src/gl.cc b/gfx/wr/swgl/src/gl.cc ---- a/gfx/wr/swgl/src/gl.cc -+++ b/gfx/wr/swgl/src/gl.cc -@@ -58,10 +58,24 @@ - } - - #else --# define ALWAYS_INLINE __attribute__((always_inline)) inline -+// GCC is slower when dealing with always_inline, especially in debug builds. -+// When using Clang, use always_inline more aggressively. -+# if defined(__clang__) || defined(NDEBUG) -+# define ALWAYS_INLINE __attribute__((always_inline)) inline -+# else -+# define ALWAYS_INLINE inline -+# endif - # define NO_INLINE __attribute__((noinline)) - #endif - -+// Some functions may cause excessive binary bloat if inlined in debug or with -+// GCC builds, so use PREFER_INLINE on these instead of ALWAYS_INLINE. -+#if defined(__clang__) && defined(NDEBUG) -+# define PREFER_INLINE ALWAYS_INLINE -+#else -+# define PREFER_INLINE inline -+#endif -+ - #define UNREACHABLE __builtin_unreachable() - - #define UNUSED [[maybe_unused]] - diff --git a/mozilla-1701089.patch b/mozilla-1701089.patch deleted file mode 100644 index af431f2..0000000 --- a/mozilla-1701089.patch +++ /dev/null @@ -1,23 +0,0 @@ -diff --git a/dom/media/gmp/GMPParent.cpp b/dom/media/gmp/GMPParent.cpp ---- a/dom/media/gmp/GMPParent.cpp -+++ b/dom/media/gmp/GMPParent.cpp -@@ -884,7 +884,7 @@ - // - // Google's code to parse manifests can be used as a reference for strings - // the manifest may contain -- // https://cs.chromium.org/chromium/src/chrome/common/media/cdm_manifest.cc?l=73&rcl=393e60bfc2299449db7ef374c0ef1c324716e562 -+ // https://source.chromium.org/chromium/chromium/src/+/master:components/cdm/common/cdm_manifest.cc;l=74;drc=775880ced8a989191281e93854c7f2201f25068f - // - // Gecko's internal strings can be found at - // https://searchfox.org/mozilla-central/rev/ea63a0888d406fae720cf24f4727d87569a8cab5/dom/media/eme/MediaKeySystemAccess.cpp#149-155 -@@ -892,7 +892,8 @@ - nsCString codec; - if (chromiumCodec.EqualsASCII("vp8")) { - codec = "vp8"_ns; -- } else if (chromiumCodec.EqualsASCII("vp9.0")) { -+ } else if (chromiumCodec.EqualsASCII("vp9.0") || // Legacy string. -+ chromiumCodec.EqualsASCII("vp09")) { - codec = "vp9"_ns; - } else if (chromiumCodec.EqualsASCII("avc1")) { - codec = "h264"_ns; - diff --git a/mozilla-1753402.patch b/mozilla-1753402.patch deleted file mode 100644 index e53e73b..0000000 --- a/mozilla-1753402.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff --git a/tools/profiler/rust-api/build.rs b/tools/profiler/rust-api/build.rs ---- a/tools/profiler/rust-api/build.rs -+++ b/tools/profiler/rust-api/build.rs -@@ -61,6 +61,7 @@ - let mut builder = Builder::default() - .enable_cxx_namespaces() - .with_codegen_config(CodegenConfig::TYPES | CodegenConfig::VARS | CodegenConfig::FUNCTIONS) -+ .disable_untagged_union() - .size_t_is_usize(true); - - for dir in SEARCH_PATHS.iter() { - diff --git a/mozilla-1758948.patch b/mozilla-1758948.patch deleted file mode 100644 index 7bc99e4..0000000 --- a/mozilla-1758948.patch +++ /dev/null @@ -1,28 +0,0 @@ -changeset: 623785:a6b80ee8c35f -tag: tip -parent: 623782:b1ed2fa50612 -user: stransky -date: Wed Jun 15 14:54:19 2022 +0200 -files: dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp -description: -Bug 1758948 [FFmpeg] Use AVFrame::pts instead of AVFrame::pkt_pts on ffmpeg 4.x r?alwu - -AVFrame::pkt_pts has been deprecated and gives us wrong values for AV1 VA-API. Let's use AVFrame::pts instead on ffmpeg 4.x -as well as we use on ffmpeg 5.0 where AVFrame::pkt_pts is removed. - -Differential Revision: https://phabricator.services.mozilla.com/D149386 - - -diff --git a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp ---- a/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp -+++ b/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp -@@ -774,7 +774,7 @@ void FFmpegVideoDecoder::Init - #endif - - static int64_t GetFramePts(AVFrame* aFrame) { --#if LIBAVCODEC_VERSION_MAJOR > 58 -+#if LIBAVCODEC_VERSION_MAJOR > 57 - return aFrame->pts; - #else - return aFrame->pkt_pts; - diff --git a/mozilla-1774271.patch b/mozilla-1774271.patch deleted file mode 100644 index 6029b22..0000000 --- a/mozilla-1774271.patch +++ /dev/null @@ -1,31 +0,0 @@ -changeset: 623945:6117c9ecd16b -tag: tip -parent: 623941:45e313943df5 -user: stransky -date: Fri Jun 17 12:36:38 2022 +0200 -files: gfx/thebes/gfxPlatform.cpp -description: -Bug 1774271 [Linux] Don't use EGL_MESA_image_dma_buf_export in Mesa/Intel due to https://gitlab.freedesktop.org/mesa/mesa/-/issues/6688 r?jgilbert - -Depends on https://phabricator.services.mozilla.com/D149238 - -Differential Revision: https://phabricator.services.mozilla.com/D149608 - - -diff --git a/gfx/thebes/gfxPlatform.cpp b/gfx/thebes/gfxPlatform.cpp ---- a/gfx/thebes/gfxPlatform.cpp -+++ b/gfx/thebes/gfxPlatform.cpp -@@ -2871,6 +2871,12 @@ void gfxPlatform::InitWebGLConfig() { - adapterDriverVendor.Find("radeonsi") != -1) { - gfxVars::SetUseDMABufSurfaceExport(false); - } -+ // Disable EGL_MESA_image_dma_buf_export on mesa/iris due to -+ // https://gitlab.freedesktop.org/mesa/mesa/-/issues/6688 -+ if (adapterDriverVendor.Find("mesa") != -1 && -+ adapterDriverVendor.Find("iris") != -1) { -+ gfxVars::SetUseDMABufSurfaceExport(false); -+ } - } - } - - diff --git a/mozilla-1885133.patch b/mozilla-1885133.patch deleted file mode 100644 index a73503a..0000000 --- a/mozilla-1885133.patch +++ /dev/null @@ -1,21 +0,0 @@ -diff --git a/browser/components/shell/nsGNOMEShellDBusHelper.cpp b/browser/components/shell/nsGNOMEShellDBusHelper.cpp ---- a/browser/components/shell/nsGNOMEShellDBusHelper.cpp -+++ b/browser/components/shell/nsGNOMEShellDBusHelper.cpp -@@ -29,7 +29,7 @@ static bool GetGnomeSearchTitle(const ch - } - - AutoTArray formatStrings; -- CopyASCIItoUTF16(nsCString(aSearchedTerm), *formatStrings.AppendElement()); -+ CopyUTF8toUTF16(nsCString(aSearchedTerm), *formatStrings.AppendElement()); - - nsAutoString gnomeSearchTitle; - bundle->FormatStringFromName("gnomeSearchProviderSearch", formatStrings, -@@ -41,7 +41,7 @@ static bool GetGnomeSearchTitle(const ch - static const char* introspect_template = - "\n" -+ "\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n" - "\n" - " \n" - " \n" diff --git a/mozilla-440908.patch b/mozilla-440908.patch deleted file mode 100644 index cce5248..0000000 --- a/mozilla-440908.patch +++ /dev/null @@ -1,111 +0,0 @@ -diff -up firefox-56.0/modules/libpref/prefapi.cpp.440908 firefox-56.0/modules/libpref/prefapi.cpp ---- firefox-56.0/modules/libpref/prefapi.cpp.440908 2017-09-14 22:15:52.000000000 +0200 -+++ firefox-56.0/modules/libpref/prefapi.cpp 2017-09-25 10:39:39.266572792 +0200 -@@ -1036,8 +1036,8 @@ void PREF_ReaderCallback(void *clo - PrefValue value, - PrefType type, - bool isDefault, -- bool isStickyDefault) -- -+ bool isStickyDefault, -+ bool isLocked) - { - uint32_t flags = 0; - if (isDefault) { -@@ -1049,4 +1049,6 @@ void PREF_ReaderCallback(void *clo - flags |= kPrefForceSet; - } - pref_HashPref(pref, value, type, flags); -+ if (isLocked) -+ PREF_LockPref(pref, true); - } -diff -up firefox-56.0/modules/libpref/prefapi.h.440908 firefox-56.0/modules/libpref/prefapi.h ---- firefox-56.0/modules/libpref/prefapi.h.440908 2017-07-31 18:20:51.000000000 +0200 -+++ firefox-56.0/modules/libpref/prefapi.h 2017-09-25 10:39:39.267572789 +0200 -@@ -246,8 +246,8 @@ void PREF_ReaderCallback( void *closure, - PrefValue value, - PrefType type, - bool isDefault, -- bool isStickyDefault); -- -+ bool isStickyDefault, -+ bool isLocked); - - /* - * Callback whenever we change a preference -diff -up firefox-56.0/modules/libpref/prefread.cpp.440908 firefox-56.0/modules/libpref/prefread.cpp ---- firefox-56.0/modules/libpref/prefread.cpp.440908 2017-09-14 22:15:52.000000000 +0200 -+++ firefox-56.0/modules/libpref/prefread.cpp 2017-09-25 10:39:39.267572789 +0200 -@@ -43,6 +43,7 @@ enum { - #define BITS_PER_HEX_DIGIT 4 - - static const char kUserPref[] = "user_pref"; -+static const char kLockPref[] = "lockPref"; - static const char kPref[] = "pref"; - static const char kPrefSticky[] = "sticky_pref"; - static const char kTrue[] = "true"; -@@ -146,7 +147,7 @@ pref_DoCallback(PrefParseState *ps) - break; - } - (*ps->reader)(ps->closure, ps->lb, value, ps->vtype, ps->fdefault, -- ps->fstickydefault); -+ ps->fstickydefault, ps->flock); - return true; - } - -@@ -215,6 +216,7 @@ PREF_ParseBuf(PrefParseState *ps, const - ps->vtype = PrefType::Invalid; - ps->fdefault = false; - ps->fstickydefault = false; -+ ps->flock = false; - } - switch (c) { - case '/': /* begin comment block or line? */ -@@ -225,11 +227,14 @@ PREF_ParseBuf(PrefParseState *ps, const - break; - case 'u': /* indicating user_pref */ - case 's': /* indicating sticky_pref */ -+ case 'l': /* indicating lockPref */ - case 'p': /* indicating pref */ - if (c == 'u') { - ps->smatch = kUserPref; - } else if (c == 's') { - ps->smatch = kPrefSticky; -+ } else if (c == 'l') { -+ ps->smatch = kLockPref; - } else { - ps->smatch = kPref; - } -@@ -277,8 +282,10 @@ PREF_ParseBuf(PrefParseState *ps, const - /* name parsing */ - case PREF_PARSE_UNTIL_NAME: - if (c == '\"' || c == '\'') { -- ps->fdefault = (ps->smatch == kPref || ps->smatch == kPrefSticky); -+ ps->fdefault = (ps->smatch == kPref || ps->smatch == kPrefSticky -+ || ps->smatch == kLockPref); - ps->fstickydefault = (ps->smatch == kPrefSticky); -+ ps->flock = (ps->smatch == kLockPref); - ps->quotechar = c; - ps->nextstate = PREF_PARSE_UNTIL_COMMA; /* return here when done */ - state = PREF_PARSE_QUOTED_STRING; -diff -up firefox-56.0/modules/libpref/prefread.h.440908 firefox-56.0/modules/libpref/prefread.h ---- firefox-56.0/modules/libpref/prefread.h.440908 2017-09-14 22:15:52.000000000 +0200 -+++ firefox-56.0/modules/libpref/prefread.h 2017-09-25 10:39:39.267572789 +0200 -@@ -34,7 +34,8 @@ typedef void (*PrefReader)(void *c - PrefValue val, - PrefType type, - bool defPref, -- bool stickyPref); -+ bool stickyPref, -+ bool lockPref); - - /** - * Report any errors or warnings we encounter during parsing. -@@ -62,6 +63,7 @@ typedef struct PrefParseState { - PrefType vtype; /* PREF_STRING,INT,BOOL */ - bool fdefault; /* true if (default) pref */ - bool fstickydefault; /* true if (sticky) pref */ -+ bool flock; /* true if pref to be locked */ - } PrefParseState; - - /** diff --git a/rhbz-1400293-fix-mozilla-1324096.patch b/rhbz-1400293-fix-mozilla-1324096.patch deleted file mode 100644 index 4a2691e..0000000 --- a/rhbz-1400293-fix-mozilla-1324096.patch +++ /dev/null @@ -1,72 +0,0 @@ -diff --git a/security/certverifier/CertVerifier.cpp b/security/certverifier/CertVerifier.cpp ---- a/security/certverifier/CertVerifier.cpp -+++ b/security/certverifier/CertVerifier.cpp -@@ -120,16 +120,20 @@ IsCertChainRootBuiltInRoot(const UniqueC - } - CERTCertificate* root = rootNode->cert; - if (!root) { - return Result::FATAL_ERROR_LIBRARY_FAILURE; - } - return IsCertBuiltInRoot(root, result); - } - -+// The term "builtin root" traditionally refers to a root CA certificate that -+// has been added to the NSS trust store, because it has been approved -+// for inclusion according to the Mozilla CA policy, and might be accepted -+// by Mozilla applications as an issuer for certificates seen on the public web. - Result - IsCertBuiltInRoot(CERTCertificate* cert, bool& result) - { - result = false; - #ifdef DEBUG - nsCOMPtr component(do_GetService(PSM_COMPONENT_CONTRACTID)); - if (!component) { - return Result::FATAL_ERROR_LIBRARY_FAILURE; -@@ -142,25 +146,38 @@ IsCertBuiltInRoot(CERTCertificate* cert, - return Success; - } - #endif // DEBUG - AutoSECMODListReadLock lock; - for (SECMODModuleList* list = SECMOD_GetDefaultModuleList(); list; - list = list->next) { - for (int i = 0; i < list->module->slotCount; i++) { - PK11SlotInfo* slot = list->module->slots[i]; -- // PK11_HasRootCerts should return true if and only if the given slot has -- // an object with a CKA_CLASS of CKO_NETSCAPE_BUILTIN_ROOT_LIST, which -- // should be true only of the builtin root list. -- // If we can find a copy of the given certificate on the slot with the -- // builtin root list, that certificate must be a builtin. -- if (PK11_IsPresent(slot) && PK11_HasRootCerts(slot) && -- PK11_FindCertInSlot(slot, cert, nullptr) != CK_INVALID_HANDLE) { -- result = true; -- return Success; -+ // We're searching for the "builtin root module", which is a module that -+ // contains an object with a CKA_CLASS of CKO_NETSCAPE_BUILTIN_ROOT_LIST. -+ // We use PK11_HasRootCerts() to identify a module with that property. -+ // In the past, we exclusively used the PKCS#11 module named nssckbi, -+ // which is provided by the NSS library. -+ // Nowadays, some distributions use a replacement module, which contains -+ // the builtin roots, but which also contains additional CA certificates, -+ // such as CAs trusted in a local deployment. -+ // We want to be able to distinguish between these two categories, -+ // because a CA, which may issue certificates for the public web, -+ // is expected to comply with additional requirements. -+ // If the certificate has attribute CKA_NSS_MOZILLA_CA_POLICY set to true, -+ // then we treat it as a "builtin root". -+ if (PK11_IsPresent(slot) && PK11_HasRootCerts(slot)) { -+ CK_OBJECT_HANDLE handle = PK11_FindCertInSlot(slot, cert, nullptr); -+ if (handle != CK_INVALID_HANDLE && -+ PK11_HasAttributeSet(slot, handle, CKA_NSS_MOZILLA_CA_POLICY, -+ false)) { -+ // Attribute was found, and is set to true -+ result = true; -+ break; -+ } - } - } - } - return Success; - } - - static Result - BuildCertChainForOneKeyUsage(NSSCertDBTrustDomain& trustDomain, Input certDER, diff --git a/rust-thirdparty-checksum-fix.patch b/rust-thirdparty-checksum-fix.patch deleted file mode 100644 index 8047ea8..0000000 --- a/rust-thirdparty-checksum-fix.patch +++ /dev/null @@ -1,6 +0,0 @@ -diff -up firefox-72.0/third_party/rust/backtrace-sys/.cargo-checksum.json.checksum-fix firefox-72.0/third_party/rust/backtrace-sys/.cargo-checksum.json ---- firefox-72.0/third_party/rust/backtrace-sys/.cargo-checksum.json.checksum-fix 2020-01-07 10:55:14.265047927 +0100 -+++ firefox-72.0/third_party/rust/backtrace-sys/.cargo-checksum.json 2020-01-07 10:55:18.109059804 +0100 -@@ -1 +1 @@ --{"files":{"Cargo.toml":"d7b29a5b7e31bc0ffb83473b2f78041527903740402c1a6394329857045174f7","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","build.rs":"0fe1e551ab35e7589f96979cf1d366561b62925e9c7da6249c25f25684ce9ede","src/lib.rs":"cb45ba047240bceac6ea74da50c2f48ae81a965b578c833a766a3ea0db1075f3","src/libbacktrace/LICENSE":"ef8a9b3247488f8901ca60de9b17b745d7bd67e5ec1e622f80d62364572200d8","src/libbacktrace/Makefile.am":"5353e0ce3a4732b42ccf031c474f7234336992cb23ba76cbfda3aa5262e69988","src/libbacktrace/Makefile.in":"1802d55fa8ef616a407c69311b3fa4e579093d124a215c834149ab1c50b4f3ad","src/libbacktrace/Mark.Twain-Tom.Sawyer.txt":"461eb7cb2d57d293fc680c836464c9125e4382be3596f7d415093ae9db8fcb0e","src/libbacktrace/README.md":"3b27ca2f7ddaf464ad81366a278ed4d34ad513de3766b330a51464828fa3131f","src/libbacktrace/acinclude.m4":"7f1d64805039b0e41d4c4106265618a6f8921d3cf091d64ab31fa7b900dc892f","src/libbacktrace/aclocal.m4":"4899cfe70722ba1de2b42b4e9965c1db1b173b5d6d4522cdc785becd5a5c212c","src/libbacktrace/alloc.c":"33891bbaf755c050058f8fd7dd3708e6062ef65245a0717216af45b78bab0fd0","src/libbacktrace/atomic.c":"82fd23c7ee7154d1ce4fc823637ede9cfa0e469f4073f38fff4dd9081070f1aa","src/libbacktrace/backtrace-supported.h.in":"42277f3c383386b6cfa3d3d889336e92303fac0ae1a9fb8a6a56737245dfb8f3","src/libbacktrace/backtrace.c":"837ea7b781a737d1ed37e4d03c463bcbe1432b2dc3b79b37344b21013cdfcca4","src/libbacktrace/backtrace.h":"9f035b3830c1c6000259c8ecf0bf53144f7c2e6064dfc95975b89f7f612ebf0e","src/libbacktrace/btest.c":"41c774496d58177e408b1dc33d6a792d0940634885978eed73fb192f732cafc5","src/libbacktrace/config.guess":"9be3de218833c076786b919dc34aab691611f4cd73316e7705f2673e2c41921b","src/libbacktrace/config.h.in":"b5002d9f96f6a26f54317f9d23a5ffff71fa3ee520fd8993810891d43b9a9bf7","src/libbacktrace/config.sub":"c8e70ab53f04d2f2b0280aa0e8a5432e90a902bfa2af7b0854168eb1fb3a84c0","src/libbacktrace/config/libtool.m4":"644ce34d5e9fcc544f3ef5c707f4cb29add798bbfc24e29932b55fb251e50353","src/libbacktrace/config/ltoptions.m4":"9d294950c4d97e2c891d472933113f397d410ef2a8ed875d714f81761626bbd8","src/libbacktrace/config/ltsugar.m4":"2c6618a04aa6389a2a528cde2e69ed5de55acc6c50892b486ea3e56e4e5b2c3b","src/libbacktrace/config/ltversion.m4":"8d129a46367fadad9f202dac50e708696d4d628313d01745127388e9c736e996","src/libbacktrace/config/lt~obsolete.m4":"c6c668594337aafef7d59f585bce7010436153815fe341461d81301a2235b959","src/libbacktrace/configure":"59763fc255248b54fba5d0761d61093a73d51fa4cb400b0df1b5f339b9c2f48a","src/libbacktrace/configure.ac":"b9292548330eb4d2cb014e9d9e6cd4df656aed982917365896a8f2534e9732e5","src/libbacktrace/dwarf.c":"c2103af5f94dd135e5df2a98dfc28ef2cbe0f3d56783d21e1487b9f314bfcbbc","src/libbacktrace/edtest.c":"947b9878ae45f6ba95d3b949bb080e9feed4ffdb27536cf5602b81ce79556ccf","src/libbacktrace/edtest2.c":"964bb0bb510a19013fb1cb56552929ed15cf55787eba4369d5820b74be07d249","src/libbacktrace/elf.c":"fe3e10d33c0c0965f016381302128ce82d664071095ad5077932377e3a789679","src/libbacktrace/fileline.c":"7b3b92044648f45becc498d4ed41ddc8ec08f0d11f6491cc05cfccd8a4d7627a","src/libbacktrace/filenames.h":"2c23cde7dd12dd9e0343cb37b5066036112deca703b61178f07c01f3e01398c9","src/libbacktrace/filetype.awk":"aa38776487a77dc13c93efa2a861204b384c3c4333501ed9bdb4ccbde2a784c0","src/libbacktrace/install-sh":"e7064b5e01a8d173409749c337966698fa04661cde1e3ef1a93be250eec0d2c3","src/libbacktrace/internal.h":"88c63ad6acc7e68330df3028675be4d4e3374bd787255fe22dd3febbbbc438b6","src/libbacktrace/ltmain.sh":"873bdcbc8690bd90c0f3632aac40027e880fd95ea45fb5a02ed901fea4afa4fe","src/libbacktrace/macho.c":"9a8864901eede4c34305b05bb6e815b25b76f04b59caf74381ca9dfbe8f1a8c4","src/libbacktrace/missing":"300bea3fb273b763eca2e4bb1576c663605d9b49de385fd375f82be8d912f506","src/libbacktrace/mmap.c":"5be917f3e9eba1fe49eb1bb391e28609e8377b4ce4593cace6012bf17434a33c","src/libbacktrace/mmapio.c":"be5719c4f92e70045fe6014a0493a5b4adc165ecde42c20130ea6e9da1ce978f","src/libbacktrace/move-if-change":"689762b92d23003926ba729acf98b9a109abf46de0698c09ddfa0d20490d8af5","src/libbacktrace/nounwind.c":"5eee9cc7298b7d0d2aea68eef62175541f34f88acf17736e0612056c5bb7318d","src/libbacktrace/pecoff.c":"bb536ae71a1a1c4dad5508d26032e7e81860df6d8ddfc8d696378ebefbc513b1","src/libbacktrace/posix.c":"f5e0ff701a1a1e29a25462ea49f174b049dafc6c25e040ee0eb77dd189353277","src/libbacktrace/print.c":"2d446406c8e2d9a1258d46d119be1c563bd86b6a4039cbf773b6de09c541390d","src/libbacktrace/read.c":"d0d4007f681f265a6c31e27ded45f4007502c90464eefdb4e80b69e4ae2ede28","src/libbacktrace/simple.c":"b0f767d3740195015aeadaa67e84bf6eb255a730f258485ca86bdbe02b066eca","src/libbacktrace/sort.c":"a82f911fc826a353ea5616379748dfa318ad4e57e20791af7ead853f7e73583d","src/libbacktrace/state.c":"a45abbe4077a47d17fb9687057c40828e633df12d21b8ed40b71a78d86918100","src/libbacktrace/stest.c":"7443fe435f1ee5ce49a3e634faf81a4137d66a057577fe88a211cfa819ddb2e2","src/libbacktrace/testlib.c":"a7e096e895b36db7f997a6673ce48f92a032046876511e813a8a52de6079b29a","src/libbacktrace/testlib.h":"02e02404dc89dd4f3dd82635f794a927541dd78d490d777bedf8a5424e5033fc","src/libbacktrace/ttest.c":"380f3b2be164bd6770768181fa05f1778cee8f0322434896d19724ae7cd105df","src/libbacktrace/unknown.c":"d2d148ea045dcad96ba1c5528b7036b000eeb8439ae397bca01deb0d8b287972","src/libbacktrace/xcoff.c":"e70ed97743306f71ea6132a058d68f1bb7be1380a2d38725b5dc877f5e07905d","src/libbacktrace/ztest.c":"7ad8277664e596aecb6af25818b7671e199ef6002ec2c38d9288179c5cad2082","symbol-map":"c81ced08aa32f0edb1d0ed6e4aaf5d3d516f8c158417d2ba3fa36b45b6ae08fd"},"package":"c66d56ac8dabd07f6aacdaf633f4b8262f5b3601a810a0dcddffd5c22c69daa0"} -+{"files":{"Cargo.toml":"d7b29a5b7e31bc0ffb83473b2f78041527903740402c1a6394329857045174f7","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"378f5840b258e2779c39418f3f2d7b2ba96f1c7917dd6be0713f88305dbda397","build.rs":"0fe1e551ab35e7589f96979cf1d366561b62925e9c7da6249c25f25684ce9ede","src/lib.rs":"cb45ba047240bceac6ea74da50c2f48ae81a965b578c833a766a3ea0db1075f3","src/libbacktrace/LICENSE":"ef8a9b3247488f8901ca60de9b17b745d7bd67e5ec1e622f80d62364572200d8","src/libbacktrace/Makefile.am":"5353e0ce3a4732b42ccf031c474f7234336992cb23ba76cbfda3aa5262e69988","src/libbacktrace/Makefile.in":"1802d55fa8ef616a407c69311b3fa4e579093d124a215c834149ab1c50b4f3ad","src/libbacktrace/Mark.Twain-Tom.Sawyer.txt":"461eb7cb2d57d293fc680c836464c9125e4382be3596f7d415093ae9db8fcb0e","src/libbacktrace/README.md":"3b27ca2f7ddaf464ad81366a278ed4d34ad513de3766b330a51464828fa3131f","src/libbacktrace/acinclude.m4":"7f1d64805039b0e41d4c4106265618a6f8921d3cf091d64ab31fa7b900dc892f","src/libbacktrace/aclocal.m4":"4899cfe70722ba1de2b42b4e9965c1db1b173b5d6d4522cdc785becd5a5c212c","src/libbacktrace/alloc.c":"33891bbaf755c050058f8fd7dd3708e6062ef65245a0717216af45b78bab0fd0","src/libbacktrace/atomic.c":"82fd23c7ee7154d1ce4fc823637ede9cfa0e469f4073f38fff4dd9081070f1aa","src/libbacktrace/backtrace-supported.h.in":"42277f3c383386b6cfa3d3d889336e92303fac0ae1a9fb8a6a56737245dfb8f3","src/libbacktrace/backtrace.c":"837ea7b781a737d1ed37e4d03c463bcbe1432b2dc3b79b37344b21013cdfcca4","src/libbacktrace/backtrace.h":"9f035b3830c1c6000259c8ecf0bf53144f7c2e6064dfc95975b89f7f612ebf0e","src/libbacktrace/btest.c":"41c774496d58177e408b1dc33d6a792d0940634885978eed73fb192f732cafc5","src/libbacktrace/config.guess":"0913c6ce799fbfca156ae5fb55fc2e5950808b4d1435e71c6a8b768e54424052","src/libbacktrace/config.h.in":"b5002d9f96f6a26f54317f9d23a5ffff71fa3ee520fd8993810891d43b9a9bf7","src/libbacktrace/config.sub":"c8e70ab53f04d2f2b0280aa0e8a5432e90a902bfa2af7b0854168eb1fb3a84c0","src/libbacktrace/config/libtool.m4":"644ce34d5e9fcc544f3ef5c707f4cb29add798bbfc24e29932b55fb251e50353","src/libbacktrace/config/ltoptions.m4":"9d294950c4d97e2c891d472933113f397d410ef2a8ed875d714f81761626bbd8","src/libbacktrace/config/ltsugar.m4":"2c6618a04aa6389a2a528cde2e69ed5de55acc6c50892b486ea3e56e4e5b2c3b","src/libbacktrace/config/ltversion.m4":"8d129a46367fadad9f202dac50e708696d4d628313d01745127388e9c736e996","src/libbacktrace/config/lt~obsolete.m4":"c6c668594337aafef7d59f585bce7010436153815fe341461d81301a2235b959","src/libbacktrace/configure":"59763fc255248b54fba5d0761d61093a73d51fa4cb400b0df1b5f339b9c2f48a","src/libbacktrace/configure.ac":"b9292548330eb4d2cb014e9d9e6cd4df656aed982917365896a8f2534e9732e5","src/libbacktrace/dwarf.c":"c2103af5f94dd135e5df2a98dfc28ef2cbe0f3d56783d21e1487b9f314bfcbbc","src/libbacktrace/edtest.c":"947b9878ae45f6ba95d3b949bb080e9feed4ffdb27536cf5602b81ce79556ccf","src/libbacktrace/edtest2.c":"964bb0bb510a19013fb1cb56552929ed15cf55787eba4369d5820b74be07d249","src/libbacktrace/elf.c":"fe3e10d33c0c0965f016381302128ce82d664071095ad5077932377e3a789679","src/libbacktrace/fileline.c":"7b3b92044648f45becc498d4ed41ddc8ec08f0d11f6491cc05cfccd8a4d7627a","src/libbacktrace/filenames.h":"2c23cde7dd12dd9e0343cb37b5066036112deca703b61178f07c01f3e01398c9","src/libbacktrace/filetype.awk":"aa38776487a77dc13c93efa2a861204b384c3c4333501ed9bdb4ccbde2a784c0","src/libbacktrace/install-sh":"e7064b5e01a8d173409749c337966698fa04661cde1e3ef1a93be250eec0d2c3","src/libbacktrace/internal.h":"88c63ad6acc7e68330df3028675be4d4e3374bd787255fe22dd3febbbbc438b6","src/libbacktrace/ltmain.sh":"873bdcbc8690bd90c0f3632aac40027e880fd95ea45fb5a02ed901fea4afa4fe","src/libbacktrace/macho.c":"9a8864901eede4c34305b05bb6e815b25b76f04b59caf74381ca9dfbe8f1a8c4","src/libbacktrace/missing":"300bea3fb273b763eca2e4bb1576c663605d9b49de385fd375f82be8d912f506","src/libbacktrace/mmap.c":"5be917f3e9eba1fe49eb1bb391e28609e8377b4ce4593cace6012bf17434a33c","src/libbacktrace/mmapio.c":"be5719c4f92e70045fe6014a0493a5b4adc165ecde42c20130ea6e9da1ce978f","src/libbacktrace/move-if-change":"689762b92d23003926ba729acf98b9a109abf46de0698c09ddfa0d20490d8af5","src/libbacktrace/nounwind.c":"5eee9cc7298b7d0d2aea68eef62175541f34f88acf17736e0612056c5bb7318d","src/libbacktrace/pecoff.c":"bb536ae71a1a1c4dad5508d26032e7e81860df6d8ddfc8d696378ebefbc513b1","src/libbacktrace/posix.c":"f5e0ff701a1a1e29a25462ea49f174b049dafc6c25e040ee0eb77dd189353277","src/libbacktrace/print.c":"2d446406c8e2d9a1258d46d119be1c563bd86b6a4039cbf773b6de09c541390d","src/libbacktrace/read.c":"d0d4007f681f265a6c31e27ded45f4007502c90464eefdb4e80b69e4ae2ede28","src/libbacktrace/simple.c":"b0f767d3740195015aeadaa67e84bf6eb255a730f258485ca86bdbe02b066eca","src/libbacktrace/sort.c":"a82f911fc826a353ea5616379748dfa318ad4e57e20791af7ead853f7e73583d","src/libbacktrace/state.c":"a45abbe4077a47d17fb9687057c40828e633df12d21b8ed40b71a78d86918100","src/libbacktrace/stest.c":"7443fe435f1ee5ce49a3e634faf81a4137d66a057577fe88a211cfa819ddb2e2","src/libbacktrace/testlib.c":"a7e096e895b36db7f997a6673ce48f92a032046876511e813a8a52de6079b29a","src/libbacktrace/testlib.h":"02e02404dc89dd4f3dd82635f794a927541dd78d490d777bedf8a5424e5033fc","src/libbacktrace/ttest.c":"380f3b2be164bd6770768181fa05f1778cee8f0322434896d19724ae7cd105df","src/libbacktrace/unknown.c":"d2d148ea045dcad96ba1c5528b7036b000eeb8439ae397bca01deb0d8b287972","src/libbacktrace/xcoff.c":"e70ed97743306f71ea6132a058d68f1bb7be1380a2d38725b5dc877f5e07905d","src/libbacktrace/ztest.c":"7ad8277664e596aecb6af25818b7671e199ef6002ec2c38d9288179c5cad2082","symbol-map":"c81ced08aa32f0edb1d0ed6e4aaf5d3d516f8c158417d2ba3fa36b45b6ae08fd"},"package":"c66d56ac8dabd07f6aacdaf633f4b8262f5b3601a810a0dcddffd5c22c69daa0"}