Thread View
j
: Next unread message
k
: Previous unread message
j a
: Jump to all threads
j l
: Jump to MailingList overview
The package rpms/firefox.git has added or updated architecture specific content in its
spec file (ExclusiveArch/ExcludeArch or %ifarch/%ifnarch) in commit(s):
https://src.fedoraproject.org/cgit/rpms/firefox.git/commit/?id=3e4bfaceacca….
Change:
+%ifarch x86_64 ppc ppc64 ppc64le
Thanks.
Full change:
============
commit 3e4bfaceacca1e9f5956d2cf29fff73abad01d2c
Author: Kalev Lember <klember(a)redhat.com>
Date: Tue Aug 23 16:31:43 2022 +0200
Fix the build on F35
Add back previous RPM_BUILD_NCPUS limiting code as F35 doesn't have the
new %constrain_build macro.
We can drop the compat code as soon as F35 is EOL.
diff --git a/firefox.spec b/firefox.spec
index 9d407b3..1486383 100644
--- a/firefox.spec
+++ b/firefox.spec
@@ -715,10 +715,34 @@ echo "ac_add_options MOZ_PGO=1" >> .mozconfig
export CCACHE_DISABLE=1
%endif
+%if 0%{?fedora} > 35
# Require 2 GB of RAM per CPU core
%constrain_build -m 2048
-
echo "mk_add_options MOZ_MAKE_FLAGS=\"-j%{_smp_build_ncpus}\"" >> .mozconfig
+%else
+# F35 doesn't have %%constrain_build
+MOZ_SMP_FLAGS=-j1
+# On x86_64 architectures, Mozilla can build up to 4 jobs at once in parallel,
+# however builds tend to fail on other arches when building in parallel.
+%ifarch %{ix86} s390x %{arm} aarch64
+[ -z "$RPM_BUILD_NCPUS" ] && \
+ RPM_BUILD_NCPUS="`/usr/bin/getconf _NPROCESSORS_ONLN`"
+[ "$RPM_BUILD_NCPUS" -ge 2 ] && MOZ_SMP_FLAGS=-j2
+%endif
+%ifarch x86_64 ppc ppc64 ppc64le
+[ -z "$RPM_BUILD_NCPUS" ] && \
+ RPM_BUILD_NCPUS="`/usr/bin/getconf _NPROCESSORS_ONLN`"
+[ "$RPM_BUILD_NCPUS" -ge 2 ] && MOZ_SMP_FLAGS=-j2
+[ "$RPM_BUILD_NCPUS" -ge 4 ] && MOZ_SMP_FLAGS=-j4
+[ "$RPM_BUILD_NCPUS" -ge 8 ] && MOZ_SMP_FLAGS=-j8
+[ "$RPM_BUILD_NCPUS" -ge 16 ] && MOZ_SMP_FLAGS=-j16
+[ "$RPM_BUILD_NCPUS" -ge 24 ] && MOZ_SMP_FLAGS=-j24
+[ "$RPM_BUILD_NCPUS" -ge 32 ] && MOZ_SMP_FLAGS=-j32
+[ "$RPM_BUILD_NCPUS" -ge 64 ] && MOZ_SMP_FLAGS=-j64
+%endif
+echo "mk_add_options MOZ_MAKE_FLAGS=\"$MOZ_SMP_FLAGS\"" >> .mozconfig
+%endif
+
echo "mk_add_options MOZ_SERVICES_SYNC=1" >> .mozconfig
echo "export STRIP=/bin/true" >> .mozconfig
#export MACH_USE_SYSTEM_PYTHON=1
The package rpms/firefox.git has added or updated architecture specific content in its
spec file (ExclusiveArch/ExcludeArch or %ifarch/%ifnarch) in commit(s):
https://src.fedoraproject.org/cgit/rpms/firefox.git/commit/?id=3e4bfaceacca….
Change:
+%ifarch x86_64 ppc ppc64 ppc64le
Thanks.
Full change:
============
commit 3e4bfaceacca1e9f5956d2cf29fff73abad01d2c
Author: Kalev Lember <klember(a)redhat.com>
Date: Tue Aug 23 16:31:43 2022 +0200
Fix the build on F35
Add back previous RPM_BUILD_NCPUS limiting code as F35 doesn't have the
new %constrain_build macro.
We can drop the compat code as soon as F35 is EOL.
diff --git a/firefox.spec b/firefox.spec
index 9d407b3..1486383 100644
--- a/firefox.spec
+++ b/firefox.spec
@@ -715,10 +715,34 @@ echo "ac_add_options MOZ_PGO=1" >> .mozconfig
export CCACHE_DISABLE=1
%endif
+%if 0%{?fedora} > 35
# Require 2 GB of RAM per CPU core
%constrain_build -m 2048
-
echo "mk_add_options MOZ_MAKE_FLAGS=\"-j%{_smp_build_ncpus}\"" >> .mozconfig
+%else
+# F35 doesn't have %%constrain_build
+MOZ_SMP_FLAGS=-j1
+# On x86_64 architectures, Mozilla can build up to 4 jobs at once in parallel,
+# however builds tend to fail on other arches when building in parallel.
+%ifarch %{ix86} s390x %{arm} aarch64
+[ -z "$RPM_BUILD_NCPUS" ] && \
+ RPM_BUILD_NCPUS="`/usr/bin/getconf _NPROCESSORS_ONLN`"
+[ "$RPM_BUILD_NCPUS" -ge 2 ] && MOZ_SMP_FLAGS=-j2
+%endif
+%ifarch x86_64 ppc ppc64 ppc64le
+[ -z "$RPM_BUILD_NCPUS" ] && \
+ RPM_BUILD_NCPUS="`/usr/bin/getconf _NPROCESSORS_ONLN`"
+[ "$RPM_BUILD_NCPUS" -ge 2 ] && MOZ_SMP_FLAGS=-j2
+[ "$RPM_BUILD_NCPUS" -ge 4 ] && MOZ_SMP_FLAGS=-j4
+[ "$RPM_BUILD_NCPUS" -ge 8 ] && MOZ_SMP_FLAGS=-j8
+[ "$RPM_BUILD_NCPUS" -ge 16 ] && MOZ_SMP_FLAGS=-j16
+[ "$RPM_BUILD_NCPUS" -ge 24 ] && MOZ_SMP_FLAGS=-j24
+[ "$RPM_BUILD_NCPUS" -ge 32 ] && MOZ_SMP_FLAGS=-j32
+[ "$RPM_BUILD_NCPUS" -ge 64 ] && MOZ_SMP_FLAGS=-j64
+%endif
+echo "mk_add_options MOZ_MAKE_FLAGS=\"$MOZ_SMP_FLAGS\"" >> .mozconfig
+%endif
+
echo "mk_add_options MOZ_SERVICES_SYNC=1" >> .mozconfig
echo "export STRIP=/bin/true" >> .mozconfig
#export MACH_USE_SYSTEM_PYTHON=1
The package rpms/firefox.git has added or updated architecture specific content in its
spec file (ExclusiveArch/ExcludeArch or %ifarch/%ifnarch) in commit(s):
https://src.fedoraproject.org/cgit/rpms/firefox.git/commit/?id=3e4bfaceacca….
Change:
+%ifarch x86_64 ppc ppc64 ppc64le
Thanks.
Full change:
============
commit 3e4bfaceacca1e9f5956d2cf29fff73abad01d2c
Author: Kalev Lember <klember(a)redhat.com>
Date: Tue Aug 23 16:31:43 2022 +0200
Fix the build on F35
Add back previous RPM_BUILD_NCPUS limiting code as F35 doesn't have the
new %constrain_build macro.
We can drop the compat code as soon as F35 is EOL.
diff --git a/firefox.spec b/firefox.spec
index 9d407b3..1486383 100644
--- a/firefox.spec
+++ b/firefox.spec
@@ -715,10 +715,34 @@ echo "ac_add_options MOZ_PGO=1" >> .mozconfig
export CCACHE_DISABLE=1
%endif
+%if 0%{?fedora} > 35
# Require 2 GB of RAM per CPU core
%constrain_build -m 2048
-
echo "mk_add_options MOZ_MAKE_FLAGS=\"-j%{_smp_build_ncpus}\"" >> .mozconfig
+%else
+# F35 doesn't have %%constrain_build
+MOZ_SMP_FLAGS=-j1
+# On x86_64 architectures, Mozilla can build up to 4 jobs at once in parallel,
+# however builds tend to fail on other arches when building in parallel.
+%ifarch %{ix86} s390x %{arm} aarch64
+[ -z "$RPM_BUILD_NCPUS" ] && \
+ RPM_BUILD_NCPUS="`/usr/bin/getconf _NPROCESSORS_ONLN`"
+[ "$RPM_BUILD_NCPUS" -ge 2 ] && MOZ_SMP_FLAGS=-j2
+%endif
+%ifarch x86_64 ppc ppc64 ppc64le
+[ -z "$RPM_BUILD_NCPUS" ] && \
+ RPM_BUILD_NCPUS="`/usr/bin/getconf _NPROCESSORS_ONLN`"
+[ "$RPM_BUILD_NCPUS" -ge 2 ] && MOZ_SMP_FLAGS=-j2
+[ "$RPM_BUILD_NCPUS" -ge 4 ] && MOZ_SMP_FLAGS=-j4
+[ "$RPM_BUILD_NCPUS" -ge 8 ] && MOZ_SMP_FLAGS=-j8
+[ "$RPM_BUILD_NCPUS" -ge 16 ] && MOZ_SMP_FLAGS=-j16
+[ "$RPM_BUILD_NCPUS" -ge 24 ] && MOZ_SMP_FLAGS=-j24
+[ "$RPM_BUILD_NCPUS" -ge 32 ] && MOZ_SMP_FLAGS=-j32
+[ "$RPM_BUILD_NCPUS" -ge 64 ] && MOZ_SMP_FLAGS=-j64
+%endif
+echo "mk_add_options MOZ_MAKE_FLAGS=\"$MOZ_SMP_FLAGS\"" >> .mozconfig
+%endif
+
echo "mk_add_options MOZ_SERVICES_SYNC=1" >> .mozconfig
echo "export STRIP=/bin/true" >> .mozconfig
#export MACH_USE_SYSTEM_PYTHON=1
The package rpms/libkrun.git has added or updated architecture specific content in its
spec file (ExclusiveArch/ExcludeArch or %ifarch/%ifnarch) in commit(s):
https://src.fedoraproject.org/cgit/rpms/libkrun.git/commit/?id=dcc34889d484….
Change:
+%ifarch x86_64
Thanks.
Full change:
============
commit dcc34889d4840bc0806f92b3c65dd4383a0bddff
Author: Sergio Lopez <slp(a)redhat.com>
Date: Tue Aug 23 17:25:09 2022 +0200
Update to upstream version 1.4.2
- Update to upstream version 1.4.2
- Add the libkrun-sev and libkrun-sev-devel subpackages with the SEV variant of
the library.
Signed-off-by: Sergio Lopez <slp(a)redhat.com>
diff --git a/.gitignore b/.gitignore
index 91a80a8..f2475d6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
/v1.2.2.tar.gz
+/v1.4.2.tar.gz
diff --git a/libkrun-remove-sev-deps.diff b/libkrun-remove-sev-deps.diff
new file mode 100644
index 0000000..ad58d57
--- /dev/null
+++ b/libkrun-remove-sev-deps.diff
@@ -0,0 +1,30 @@
+diff --git a/src/vmm/Cargo.toml b/src/vmm/Cargo.toml
+index 5df6f6e..3315cda 100644
+--- a/src/vmm/Cargo.toml
++++ b/src/vmm/Cargo.toml
+@@ -4,9 +4,6 @@ version = "0.1.0"
+ authors = ["Amazon Firecracker team <firecracker-devel(a)amazon.com>"]
+ edition = "2021"
+
+-[features]
+-amd-sev = [ "codicon", "kbs-types", "procfs", "serde", "serde_json", "sev", "curl" ]
+-
+ [dependencies]
+ env_logger = "0.9.0"
+ libc = ">=0.2.39"
+@@ -19,15 +16,6 @@ kernel = { path = "../kernel" }
+ utils = { path = "../utils"}
+ polly = { path = "../polly" }
+
+-# Dependencies for amd-sev
+-codicon = { version = "3.0.0", optional = true }
+-kbs-types = { path = "../kbs-types", features = ["tee-sev"], optional = true }
+-procfs = { version = "0.12", optional = true }
+-serde = { version = "1.0.125", optional = true }
+-serde_json = { version = "1.0.64", optional = true }
+-sev = { version = "0.2", features = ["openssl"], optional = true }
+-curl = { version = "0.4", optional = true }
+-
+ [target.'cfg(target_arch = "x86_64")'.dependencies]
+ cpuid = { path = "../cpuid" }
+
diff --git a/libkrun-remove-unused-deps.diff b/libkrun-remove-unused-deps.diff
index b6c8a15..3485627 100644
--- a/libkrun-remove-unused-deps.diff
+++ b/libkrun-remove-unused-deps.diff
@@ -10,33 +10,3 @@ index 7dcf978..8fe5cff 100644
nix = "0.24.1"
rand = "0.8.5"
vm-memory = { version = "0.8.0", features = ["backend-mmap"] }
-diff --git a/src/vmm/Cargo.toml b/src/vmm/Cargo.toml
-index a824407..3315cda 100644
---- a/src/vmm/Cargo.toml
-+++ b/src/vmm/Cargo.toml
-@@ -4,9 +4,6 @@ version = "0.1.0"
- authors = ["Amazon Firecracker team <firecracker-devel(a)amazon.com>"]
- edition = "2021"
-
--[features]
--amd-sev = [ "codicon", "procfs", "reqwest", "serde", "serde_json", "sev", "ureq" ]
--
- [dependencies]
- env_logger = "0.9.0"
- libc = ">=0.2.39"
-@@ -19,15 +16,6 @@ kernel = { path = "../kernel" }
- utils = { path = "../utils"}
- polly = { path = "../polly" }
-
--# Dependencies for amd-sev
--codicon = { version = "3.0.0", optional = true }
--procfs = { version = "0.10.1", optional = true }
--reqwest = { version = "0.9.15", optional = true }
--serde = { version = "1.0.125", optional = true }
--serde_json = { version = "1.0.64", optional = true }
--sev = { version = "0.1.0", features = ["openssl"], optional = true }
--ureq = { version = "*", features = ["json"], optional = true }
--
- [target.'cfg(target_arch = "x86_64")'.dependencies]
- cpuid = { path = "../cpuid" }
-
diff --git a/libkrun.spec b/libkrun.spec
index 948f669..9e5b2e5 100644
--- a/libkrun.spec
+++ b/libkrun.spec
@@ -3,8 +3,8 @@
%bcond_with check
Name: libkrun
-Version: 1.2.2
-Release: 2%{?dist}
+Version: 1.4.2
+Release: 1%{?dist}
Summary: Dynamic library providing Virtualization-based process isolation capabilities
# Upstream license specification: Apache-2.0 AND BSD-3-Clause
@@ -14,6 +14,8 @@ Source: https://github.com/containers/libkrun/archive/refs/tags/v%{versi
# Remove references to unused deps so we don't need to install them for
# building this package
Patch0: libkrun-remove-unused-deps.diff
+# For aarch64, remove references to SEV deps which are only available on x86_64
+Patch1: libkrun-remove-sev-deps.diff
# libkrun only supports x86_64 and aarch64
ExclusiveArch: x86_64 aarch64
@@ -32,7 +34,10 @@ BuildRequires: rust-packaging >= 21
BuildRequires: glibc-static
BuildRequires: patchelf
BuildRequires: binutils
-BuildRequires: libkrunfw-devel >= 3.0.0
+BuildRequires: libkrunfw-devel >= 3.6.3
+%ifarch x86_64
+BuildRequires: libkrunfw-sev-devel >= 3.6.3
+%endif
%ifarch aarch64
BuildRequires: libfdt-devel
%endif
@@ -51,29 +56,78 @@ BuildRequires: (crate(nix/default) >= 0.24.1 with crate(nix/default) < 0.25.0~)
BuildRequires: (crate(rand/default) >= 0.8.5 with crate(rand/default) < 0.9.0~)
BuildRequires: (crate(once_cell/default) >= 1.4.1 with crate(once_cell/default) < 2.0.0~)
+%ifarch x86_64
+# SEV variant dependencies
+BuildRequires: (crate(codicon/default) >= 3.0.0 with crate(codicon/default) < 4.0.0~)
+BuildRequires: (crate(curl/default) >= 0.4.0 with crate(curl/default) < 0.5.0~)
+BuildRequires: (crate(procfs/default) >= 0.12.0 with crate(procfs/default) < 0.13.0~)
+BuildRequires: (crate(sev/default) >= 0.2.0 with crate(sev/default) < 0.3.0~)
+BuildRequires: (crate(sev/openssl) >= 0.2.0 with crate(sev/openssl) < 0.3.0~)
+BuildRequires: (crate(serde/default) >= 1.0.0 with crate(serde/default) < 2.0.0~)
+BuildRequires: (crate(serde/derive) >= 1.0.0 with crate(serde/derive) < 2.0.0~)
+BuildRequires: (crate(serde_json/default) >= 1.0.0 with crate(serde_json/default) < 2.0.0~)
+%endif
+
%description
%{summary}.
%package devel
Summary: Header files and libraries for libkrun development
-Requires: %{name}%{?_isa} = %{version}-%{release}
+Requires: %{name}%{?_isa} = %{version}-%{release}
%description devel
The libkrun-devel package containes the libraries and headers needed to
develop programs that use libkrun Virtualization-based process isolation
capabilities.
+# SEV is a feature provided by AMD EPYC processors, so only it's only
+# available on x86_64.
+%ifarch x86_64
+%package sev
+Summary: Dynamic library providing Virtualization-based process isolation capabilities (SEV variant)
+BuildRequires: libkrunfw-sev-devel >= 3.6.0
+
+%description sev
+Dynamic library providing Virtualization-based process isolation
+capabilities, with the ability to use AMD SEV to create a microVM-based
+Trusted Execution Environment (TEE).
+
+%package sev-devel
+Summary: Header files and libraries for libkrun development
+Requires: %{name}-devel%{?_isa} = %{version}-%{release}
+Requires: %{name}-sev%{?_isa} = %{version}-%{release}
+
+%description sev-devel
+The libkrun-sev-devel package containes the libraries and headers needed to
+develop programs that use libkrun-sev Virtualization-based process isolation
+capabilities.
+%endif
+
%prep
-%autosetup -n %{name}-%{version_no_tilde} -p1
+%setup -q -n %{name}-%{version_no_tilde}
+%patch0 -p1
+%ifnarch x86_64
+%patch1 -p1
+%endif
%cargo_prep
%build
%make_build init/init
%cargo_build
patchelf --set-soname libkrun.so.1 --output target/release/libkrun.so.%{version} target/release/libkrun.so
+%ifarch x86_64
+ rm init/init
+ %make_build SEV=1 init/init
+ %cargo_build -f amd-sev
+ mv target/release/libkrun.so target/release/libkrun-sev.so
+ patchelf --set-soname libkrun-sev.so.1 --output target/release/libkrun-sev.so.%{version} target/release/libkrun-sev.so
+%endif
%install
%make_install PREFIX=%{_prefix}
+%ifarch x86_64
+ %make_install SEV=1 PREFIX=%{_prefix}
+%endif
%files
%license LICENSE
@@ -85,12 +139,28 @@ patchelf --set-soname libkrun.so.1 --output target/release/libkrun.so.%{version}
%{_libdir}/libkrun.so
%{_includedir}/libkrun.h
+%ifarch x86_64
+%files sev
+%license LICENSE
+%doc README.md
+%{_libdir}/libkrun-sev.so.%{version}
+%{_libdir}/libkrun-sev.so.1
+
+%files sev-devel
+%{_libdir}/libkrun-sev.so
+%endif
+
%if %{with check}
%check
%cargo_test
%endif
%changelog
+* Wed Aug 17 2022 Sergio Lopez <slp(a)redhat.com> - 1.4.2-1
+- Update to upstream version 1.4.2
+- Add the libkrun-sev and libkrun-sev-devel subpackages with the SEV variant of
+ the library.
+
* Thu Jul 21 2022 Fedora Release Engineering <releng(a)fedoraproject.org> - 1.2.2-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild
diff --git a/sources b/sources
index 32c744b..cf9a688 100644
--- a/sources
+++ b/sources
@@ -1 +1 @@
-SHA512 (v1.2.2.tar.gz) = db233f2ee7ce4d3f6bf71c931a3f27d6bd1c619cf8a3973af7682abc0f9602fe6a5d42c2beeadc5df591aecb4172f51374c3826c1016f2d69f030dc7294ad58c
+SHA512 (v1.4.2.tar.gz) = 4826b70b979e2619bdc5318c20d26ccf0f1affc35e8780098a889c51d2779430d7fbd21908ccf02c40db99e37ea5b3a413fbf3333701ec826dda5fd109874717
The package rpms/google-osconfig-agent.git has added or updated architecture specific content in its
spec file (ExclusiveArch/ExcludeArch or %ifarch/%ifnarch) in commit(s):
https://src.fedoraproject.org/cgit/rpms/google-osconfig-agent.git/commit/?i….
Change:
+ExcludeArch: ppc64le s390x
Thanks.
Full change:
============
commit eef2d8ba8c626664fe07e42eb7add740fb9a4fcb
Author: Major Hayden <major(a)redhat.com>
Date: Tue Aug 23 08:24:27 2022 -0500
Initial import rhbz#2120396
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..b65d29f
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+/osconfig-20220801.00.tar.gz
diff --git a/google-osconfig-agent-remove-containeros.patch b/google-osconfig-agent-remove-containeros.patch
new file mode 100644
index 0000000..06674a2
--- /dev/null
+++ b/google-osconfig-agent-remove-containeros.patch
@@ -0,0 +1,339 @@
+From 117ecf894b1d4eb003c86289e500df156d27924d Mon Sep 17 00:00:00 2001
+From: Major Hayden <major(a)redhat.com>
+Date: Mon, 22 Aug 2022 13:36:38 -0500
+Subject: [PATCH] Remove ContainerOS references
+
+Signed-off-by: Major Hayden <major(a)redhat.com>
+---
+ go.mod | 1 -
+ packages/cos.go | 72 -------------
+ packages/cos_test.go | 204 -------------------------------------
+ packages/packages_linux.go | 10 --
+ 4 files changed, 287 deletions(-)
+ delete mode 100644 packages/cos.go
+ delete mode 100644 packages/cos_test.go
+
+diff --git a/go.mod b/go.mod
+index d12528b..5dee3a0 100644
+--- a/go.mod
++++ b/go.mod
+@@ -7,7 +7,6 @@ require (
+ cloud.google.com/go/logging v1.4.2 // indirect
+ cloud.google.com/go/osconfig v0.2.0
+ cloud.google.com/go/storage v1.16.1
+- cos.googlesource.com/cos/tools.git v0.0.0-20210329212435-a349a79f950d
+ github.com/GoogleCloudPlatform/guest-logging-go v0.0.0-20210621170517-facc9c0d81b9
+ github.com/StackExchange/wmi v1.2.1
+ github.com/go-ole/go-ole v1.2.5
+diff --git a/packages/cos.go b/packages/cos.go
+deleted file mode 100644
+index 505a04c..0000000
+--- a/packages/cos.go
++++ /dev/null
+@@ -1,72 +0,0 @@
+-// Copyright 2020 Google Inc. All Rights Reserved.
+-//
+-// Licensed under the Apache License, Version 2.0 (the "License");
+-// you may not use this file except in compliance with the License.
+-// You may obtain a copy of the License at
+-//
+-// http://www.apache.org/licenses/LICENSE-2.0
+-//
+-// Unless required by applicable law or agreed to in writing, software
+-// distributed under the License is distributed on an "AS IS" BASIS,
+-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-// See the License for the specific language governing permissions and
+-// limitations under the License.
+-
+-// Only build for linux but not on unsupported architectures.
+-
+-//go:build linux && (386 || amd64 || arm64)
+-// +build linux
+-// +build 386 amd64 arm64
+-
+-package packages
+-
+-import (
+- "fmt"
+-
+- "cos.googlesource.com/cos/tools.git/src/pkg/cos"
+- "github.com/GoogleCloudPlatform/osconfig/osinfo"
+-)
+-
+-func init() {
+- COSPkgInfoExists = cos.PackageInfoExists()
+-}
+-
+-var readMachineArch = func() (string, error) {
+- oi, err := osinfo.Get()
+- if err != nil {
+- return "", fmt.Errorf("error getting osinfo: %v", err)
+- }
+- return oi.Architecture, nil
+-}
+-
+-func parseInstalledCOSPackages(cosPkgInfo *cos.PackageInfo) ([]*PkgInfo, error) {
+- arch, err := readMachineArch()
+- if err != nil {
+- return nil, fmt.Errorf("error from readMachineArch: %v", err)
+- }
+-
+- var pkgs = make([]*PkgInfo, len(cosPkgInfo.InstalledPackages))
+- for i, pkg := range cosPkgInfo.InstalledPackages {
+- name := pkg.Category + "/" + pkg.Name
+- version := pkg.Version
+- pkgs[i] = &PkgInfo{Name: name, Arch: arch, Version: version}
+- }
+- return pkgs, nil
+-}
+-
+-var readCOSPackageInfo = func() (*cos.PackageInfo, error) {
+- pkgInfo, err := cos.GetPackageInfo()
+- if err != nil {
+- return nil, err
+- }
+- return &pkgInfo, nil
+-}
+-
+-// InstalledCOSPackages queries for all installed COS packages.
+-func InstalledCOSPackages() ([]*PkgInfo, error) {
+- packageInfo, err := readCOSPackageInfo()
+- if err != nil {
+- return nil, fmt.Errorf("error reading COS package list with args: %v, contents: %v", err, packageInfo)
+- }
+- return parseInstalledCOSPackages(packageInfo)
+-}
+diff --git a/packages/cos_test.go b/packages/cos_test.go
+deleted file mode 100644
+index 7c9ba44..0000000
+--- a/packages/cos_test.go
++++ /dev/null
+@@ -1,204 +0,0 @@
+-// Copyright 2020 Google Inc. All Rights Reserved.
+-//
+-// Licensed under the Apache License, Version 2.0 (the "License");
+-// you may not use this file except in compliance with the License.
+-// You may obtain a copy of the License at
+-//
+-// http://www.apache.org/licenses/LICENSE-2.0
+-//
+-// Unless required by applicable law or agreed to in writing, software
+-// distributed under the License is distributed on an "AS IS" BASIS,
+-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-// See the License for the specific language governing permissions and
+-// limitations under the License.
+-
+-//go:build linux && (386 || amd64)
+-// +build linux
+-// +build 386 amd64
+-
+-package packages
+-
+-import (
+- "errors"
+- "io/ioutil"
+- "os"
+- "reflect"
+- "testing"
+-
+- "cos.googlesource.com/cos/tools.git/src/pkg/cos"
+-)
+-
+-func TestParseInstalledCOSPackages(t *testing.T) {
+- readMachineArch = func() (string, error) {
+- return "", errors.New("failed to obtain machine architecture")
+- }
+- if _, err := parseInstalledCOSPackages(&cos.PackageInfo{}); err == nil {
+- t.Errorf("did not get expected error")
+- }
+-
+- readMachineArch = func() (string, error) {
+- return "x86_64", nil
+- }
+-
+- pkg0 := cos.Package{Category: "dev-util", Name: "foo-x", Version: "1.2.3", EbuildVersion: "someversion"}
+- expect0 := &PkgInfo{"dev-util/foo-x", "x86_64", "1.2.3"}
+- pkg1 := cos.Package{Category: "app-admin", Name: "bar", Version: "0.1"}
+- expect1 := &PkgInfo{"app-admin/bar", "x86_64", "0.1"}
+-
+- pkgInfo := &cos.PackageInfo{InstalledPackages: []cos.Package{pkg0, pkg1}}
+- parsed, err := parseInstalledCOSPackages(pkgInfo)
+- if err != nil {
+- t.Errorf("unexpected error: %v", err)
+- }
+- if !reflect.DeepEqual(parsed[0], expect0) {
+- t.Errorf("parseInstalledCOSPackages pkg0: %v, want: %v", parsed[0], expect0)
+- }
+- if !reflect.DeepEqual(parsed[1], expect1) {
+- t.Errorf("parseInstalledCOSPackages pkg1: %v, want: %v", parsed[1], expect1)
+- }
+-}
+-
+-func TestInstalledCOSPackages(t *testing.T) {
+- testDataJSON := `{
+- "installedPackages": [
+- {
+- "category": "app-arch",
+- "name": "gzip",
+- "version": "1.9",
+- "ebuildverison": "someotherversion"
+- },
+- {
+- "category": "dev-libs",
+- "name": "popt",
+- "version": "1.16"
+- },
+- {
+- "category": "app-emulation",
+- "name": "docker-credential-helpers",
+- "version": "0.6.3"
+- },
+- {
+- "category": "_not.real-category1+",
+- "name": "_not-real_package1",
+- "version": "12.34.56.78"
+- },
+- {
+- "category": "_not.real-category1+",
+- "name": "_not-real_package2",
+- "version": "12.34.56.78"
+- },
+- {
+- "category": "_not.real-category1+",
+- "name": "_not-real_package3",
+- "version": "12.34.56.78_rc3"
+- },
+- {
+- "category": "_not.real-category1+",
+- "name": "_not-real_package4",
+- "version": "12.34.56.78_rc3"
+- },
+- {
+- "category": "_not.real-category1+",
+- "name": "_not-real_package5",
+- "version": "12.34.56.78_pre2_rc3"
+- },
+- {
+- "category": "_not.real-category2+",
+- "name": "_not-real_package1",
+- "version": "12.34.56.78q"
+- },
+- {
+- "category": "_not.real-category2+",
+- "name": "_not-real_package2",
+- "version": "12.34.56.78q"
+- },
+- {
+- "category": "_not.real-category2+",
+- "name": "_not-real_package3",
+- "version": "12.34.56.78q_rc3"
+- },
+- {
+- "category": "_not.real-category2+",
+- "name": "_not-real_package4",
+- "version": "12.34.56.78q_rc3"
+- },
+- {
+- "category": "_not.real-category2+",
+- "name": "_not-real_package5",
+- "version": "12.34.56.78q_pre2_rc3"
+- }
+- ]
+-}`
+-
+- testFile, err := ioutil.TempFile("", "cos_pkg_info_test")
+- if err != nil {
+- t.Fatalf("Failed to create tempfile: %v", err)
+- }
+- defer os.Remove(testFile.Name())
+- _, err = testFile.WriteString(testDataJSON)
+- if err != nil {
+- t.Fatalf("Failed to write test data: %v", err)
+- }
+- err = testFile.Close()
+- if err != nil {
+- t.Fatalf("Failed to close test file: %v", err)
+- }
+-
+- expected := []*PkgInfo{
+- {"app-arch/gzip", "x86_64", "1.9"},
+- {"dev-libs/popt", "x86_64", "1.16"},
+- {"app-emulation/docker-credential-helpers", "x86_64", "0.6.3"},
+- {"_not.real-category1+/_not-real_package1", "x86_64", "12.34.56.78"},
+- {"_not.real-category1+/_not-real_package2", "x86_64", "12.34.56.78"},
+- {"_not.real-category1+/_not-real_package3", "x86_64", "12.34.56.78_rc3"},
+- {"_not.real-category1+/_not-real_package4", "x86_64", "12.34.56.78_rc3"},
+- {"_not.real-category1+/_not-real_package5", "x86_64", "12.34.56.78_pre2_rc3"},
+- {"_not.real-category2+/_not-real_package1", "x86_64", "12.34.56.78q"},
+- {"_not.real-category2+/_not-real_package2", "x86_64", "12.34.56.78q"},
+- {"_not.real-category2+/_not-real_package3", "x86_64", "12.34.56.78q_rc3"},
+- {"_not.real-category2+/_not-real_package4", "x86_64", "12.34.56.78q_rc3"},
+- {"_not.real-category2+/_not-real_package5", "x86_64", "12.34.56.78q_pre2_rc3"},
+- }
+-
+- readMachineArch = func() (string, error) {
+- return "", errors.New("failed to obtain machine architecture")
+- }
+- readCOSPackageInfo = func() (*cos.PackageInfo, error) {
+- info, err := cos.GetPackageInfoFromFile(testFile.Name())
+- return &info, err
+- }
+- if _, err := InstalledCOSPackages(); err == nil {
+- t.Errorf("did not get expected error from readMachineArch")
+- }
+-
+- readMachineArch = func() (string, error) {
+- return "x86_64", nil
+- }
+- readCOSPackageInfo = func() (*cos.PackageInfo, error) {
+- info, err := cos.GetPackageInfoFromFile("_" + testFile.Name())
+- return &info, err
+- }
+- if _, err := InstalledCOSPackages(); err == nil {
+- t.Errorf("did not get expected error fro readCOSPackageInfo")
+- }
+-
+- readMachineArch = func() (string, error) {
+- return "x86_64", nil
+- }
+- readCOSPackageInfo = func() (*cos.PackageInfo, error) {
+- info, err := cos.GetPackageInfoFromFile(testFile.Name())
+- return &info, err
+- }
+- ret, err := InstalledCOSPackages()
+- if err != nil {
+- t.Errorf("unexpected error: %v", err)
+- }
+- if len(ret) != len(expected) {
+- t.Errorf("Length is wrong. want: %d, got: %d",
+- len(expected), len(ret))
+- }
+- if !reflect.DeepEqual(ret, expected) {
+- t.Errorf("InstalledCOSPackages() returned: %v, want: %v", ret, expected)
+- }
+-
+-}
+diff --git a/packages/packages_linux.go b/packages/packages_linux.go
+index b021f15..9b4dfe9 100644
+--- a/packages/packages_linux.go
++++ b/packages/packages_linux.go
+@@ -126,16 +126,6 @@ func GetInstalledPackages(ctx context.Context) (*Packages, error) {
+ pkgs.Deb = deb
+ }
+ }
+- if COSPkgInfoExists {
+- cos, err := InstalledCOSPackages()
+- if err != nil {
+- msg := fmt.Sprintf("error listing installed COS packages: %v", err)
+- clog.Debugf(ctx, "Error: %s", msg)
+- errs = append(errs, msg)
+- } else {
+- pkgs.COS = cos
+- }
+- }
+ if GemExists {
+ gem, err := InstalledGemPackages(ctx)
+ if err != nil {
+--
+2.37.2
+
diff --git a/google-osconfig-agent.spec b/google-osconfig-agent.spec
new file mode 100644
index 0000000..1ad3fa2
--- /dev/null
+++ b/google-osconfig-agent.spec
@@ -0,0 +1,64 @@
+# Generated by go2rpm 1.8.0
+%bcond_without check
+
+# https://github.com/GoogleCloudPlatform/osconfig
+%global goipath github.com/GoogleCloudPlatform/osconfig
+Version: 20220801.00
+%global tag %{version}
+
+%gometa -f
+
+%global common_description %{expand:
+Google OS Config Agent}
+
+Name: google-osconfig-agent
+Release: %autorelease
+Summary: Google OS Config Agent
+
+License: Apache-2.0
+URL: %{gourl}
+Source: %{gosource}
+
+# Remove references to Google's ContainerOS since we're building this for
+# Fedora.
+Patch0: google-osconfig-agent-remove-containeros.patch
+
+# Google Cloud only offers Arm and x86 instances.
+ExcludeArch: ppc64le s390x
+
+%description %{common_description}
+
+%gopkg
+
+%prep
+%goprep
+%patch0 -p1
+
+# e2e_tests require connectivity to Google's APIs and extra packages.
+rm -rf e2e_tests
+
+%generate_buildrequires
+%go_generate_buildrequires
+
+%build
+%gobuild -o %{gobuilddir}/bin/google_osconfig_agent %{goipath}
+
+%install
+%gopkginstall
+install -m 0755 -vd %{buildroot}%{_bindir}
+install -m 0755 -vp %{gobuilddir}/bin/* %{buildroot}%{_bindir}/
+
+%if %{with check}
+%check
+%gocheck
+%endif
+
+%files
+%license LICENSE
+%doc examples CONTRIBUTING.md README.md
+%{_bindir}/google_osconfig_agent
+
+%gopkgfiles
+
+%changelog
+%autochangelog
diff --git a/sources b/sources
new file mode 100644
index 0000000..6ef2430
--- /dev/null
+++ b/sources
@@ -0,0 +1 @@
+SHA512 (osconfig-20220801.00.tar.gz) = 2d3be00db9e1fce6a90e8064bed367e9644fb97fb1d24176ee23a4485155700f9eba6a7438e302e5f3a87e535608772e089053aabac7632fb046e396fc1271dd
The package rpms/firefox.git has added or updated architecture specific content in its
spec file (ExclusiveArch/ExcludeArch or %ifarch/%ifnarch) in commit(s):
https://src.fedoraproject.org/cgit/rpms/firefox.git/commit/?id=f5c2bd2d80a2…
https://src.fedoraproject.org/cgit/rpms/firefox.git/commit/?id=1ad3bd1b2451…
https://src.fedoraproject.org/cgit/rpms/firefox.git/commit/?id=7e1b07c41aea….
Change:
-ExcludeArch: s390x
+%ifarch aarch64 %{ix86}
-%ifarch x86_64 ppc ppc64 ppc64le
Thanks.
Full change:
============
commit f5c2bd2d80a2c69fa7e0f3e5bcda6b16493bf958
Author: Kalev Lember <klember(a)redhat.com>
Date: Wed Aug 17 10:32:01 2022 +0200
Re-enable s390x builds
It builds fine again after latest fixes.
diff --git a/firefox.spec b/firefox.spec
index 26bd17a..9d407b3 100644
--- a/firefox.spec
+++ b/firefox.spec
@@ -28,11 +28,6 @@
%global build_with_clang 0
%endif
-# There are still build problems on s390x, see
-# https://koji.fedoraproject.org/koji/taskinfo?taskID=55048351
-# https://bugzilla.redhat.com/show_bug.cgi?id=1897522
-ExcludeArch: s390x
-
%ifarch armv7hl
%global create_debuginfo 0
@@ -1071,6 +1066,7 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || :
- Drop unused patches
- Use build_ldflags
- Drop hardened_build option
+- Re-enable s390x builds
* Tue Aug 23 2022 Jan Horak <jhorak(a)redhat.com> - 104.0-4
- Rebuild due to ppc64le fixes
commit 73c24a4d458769b6a8560eb855a4f7a2545fe998
Author: Kalev Lember <klember(a)redhat.com>
Date: Wed Aug 17 10:31:20 2022 +0200
Drop hardened_build option
Now that we correctly use Fedora's ldflags (previous commit), there's
no need to do anything special to enable hardened build. All of it is
already included in the default build flags.
diff --git a/firefox.spec b/firefox.spec
index bb7b33f..26bd17a 100644
--- a/firefox.spec
+++ b/firefox.spec
@@ -65,7 +65,6 @@ ExcludeArch: s390x
%else
%global system_libvpx 0
%endif
-%global hardened_build 1
%global system_jpeg 1
%global disable_elfhack 1
%global use_bundled_cbindgen 1
@@ -657,9 +656,6 @@ MOZ_OPT_FLAGS=$(echo "%{optflags}" | %{__sed} -e 's/-Wall//')
# Workaround for mozbz#1531309
MOZ_OPT_FLAGS=$(echo "$MOZ_OPT_FLAGS" | %{__sed} -e 's/-Werror=format-security//')
MOZ_OPT_FLAGS="$MOZ_OPT_FLAGS -fpermissive"
-%if %{?hardened_build}
-MOZ_OPT_FLAGS="$MOZ_OPT_FLAGS -fPIC -Wl,-z,relro -Wl,-z,now"
-%endif
%if %{?debug_build}
MOZ_OPT_FLAGS=$(echo "$MOZ_OPT_FLAGS" | %{__sed} -e 's/-O2//')
%endif
@@ -1074,6 +1070,7 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || :
- Drop obsolete build conditionals
- Drop unused patches
- Use build_ldflags
+- Drop hardened_build option
* Tue Aug 23 2022 Jan Horak <jhorak(a)redhat.com> - 104.0-4
- Rebuild due to ppc64le fixes
commit 078b597b1e74879a6c87fc30ec101b5dd3011057
Author: Kalev Lember <klember(a)redhat.com>
Date: Wed Aug 17 10:30:14 2022 +0200
Use build_ldflags
These are the LDFLAGS that all packages are supposed to use, including
hardening and other flags.
diff --git a/firefox.spec b/firefox.spec
index 221882a..bb7b33f 100644
--- a/firefox.spec
+++ b/firefox.spec
@@ -670,20 +670,16 @@ MOZ_OPT_FLAGS=$(echo "$MOZ_OPT_FLAGS" | %{__sed} -e 's/-O2//')
MOZ_OPT_FLAGS=$(echo "$MOZ_OPT_FLAGS" | %{__sed} -e 's/-g/-g0/')
export MOZ_DEBUG_FLAGS=" "
%endif
+MOZ_LINK_FLAGS="%{build_ldflags}"
%if !%{build_with_clang}
%ifarch aarch64 %{ix86}
-MOZ_LINK_FLAGS="-Wl,--no-keep-memory -Wl,--reduce-memory-overheads"
+MOZ_LINK_FLAGS="$MOZ_LINK_FLAGS -Wl,--no-keep-memory -Wl,--reduce-memory-overheads"
%endif
%ifarch %{arm}
-MOZ_LINK_FLAGS="-Wl,--no-keep-memory -Wl,--strip-debug"
+MOZ_LINK_FLAGS="$MOZ_LINK_FLAGS -Wl,--no-keep-memory -Wl,--strip-debug"
echo "ac_add_options --enable-linker=gold" >> .mozconfig
%endif
%endif
-%if 0%{?flatpak}
-# Make sure the linker can find libraries in /app/lib64 as we don't use
-# __global_ldflags that normally sets this.
-MOZ_LINK_FLAGS="$MOZ_LINK_FLAGS -L%{_libdir}"
-%endif
%ifarch %{arm} %{ix86} %{s390x}
export RUSTFLAGS="-Cdebuginfo=0"
%endif
@@ -1077,6 +1073,7 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || :
- Use constrain_build macro to simplify parallel make handling
- Drop obsolete build conditionals
- Drop unused patches
+- Use build_ldflags
* Tue Aug 23 2022 Jan Horak <jhorak(a)redhat.com> - 104.0-4
- Rebuild due to ppc64le fixes
commit 594959d6f80f090d837c7ca1286459de3aa1769c
Author: Kalev Lember <klember(a)redhat.com>
Date: Wed Aug 17 10:29:03 2022 +0200
Drop unused patches
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<ImageContainer> 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<LIBAV_VER>::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<LIBAV_VER>::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<sandbox::bpf_dsl::Policy> 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<ResultExpr> EvaluateIpcCall(int aCall, int aArgShift) const override {
-@@ -1875,9 +1862,10 @@ UniquePtr<sandbox::bpf_dsl::Policy> 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<sandbox::bpf_dsl::Policy> 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<int> 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<int>(aArgs.args[0]),
-+ static_cast<int>(aArgs.args[1]),
-+ static_cast<int>(aArgs.args[2]));
-+ }
-+
-+ static intptr_t FakeSocketTrapLegacy(ArgsRef aArgs, void* aux) {
-+ const auto innerArgs = reinterpret_cast<unsigned long*>(aArgs.args[1]);
-+
-+ return FakeSocketTrapCommon(static_cast<int>(innerArgs[0]),
-+ static_cast<int>(innerArgs[1]),
-+ static_cast<int>(innerArgs[2]));
-+ }
-+
-+ static Maybe<int> 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<size_t>(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<SandboxBrokerClient*>(aux),
-+ static_cast<int>(aArgs.args[0]),
-+ reinterpret_cast<AddrPtr>(aArgs.args[1]),
-+ static_cast<socklen_t>(aArgs.args[2]));
-+ }
-+
-+ static intptr_t ConnectTrapLegacy(ArgsRef aArgs, void* aux) {
-+ const auto innerArgs = reinterpret_cast<unsigned long*>(aArgs.args[1]);
-+ typedef const struct sockaddr_un* AddrPtr;
-+
-+ return ConnectTrapCommon(static_cast<SandboxBrokerClient*>(aux),
-+ static_cast<int>(innerArgs[0]),
-+ reinterpret_cast<AddrPtr>(innerArgs[1]),
-+ static_cast<socklen_t>(innerArgs[2]));
-+ }
-+
- public:
- ResultExpr InvalidSyscall() const override {
- return Trap(BlockedSyscallTrap, nullptr);
- }
-
-@@ -630,15 +745,37 @@
- return Some(Allow());
- }
- Arg<int> 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<int> 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<int>(aArgs.args[0]),
-- static_cast<int>(aArgs.args[1]),
-- static_cast<int>(aArgs.args[2]));
-- }
--
-- static intptr_t FakeSocketTrapLegacy(ArgsRef aArgs, void* aux) {
-- const auto innerArgs = reinterpret_cast<unsigned long*>(aArgs.args[1]);
--
-- return FakeSocketTrapCommon(static_cast<int>(innerArgs[0]),
-- static_cast<int>(innerArgs[1]),
-- static_cast<int>(innerArgs[2]));
-- }
--
-- static Maybe<int> 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<size_t>(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<SandboxBrokerClient*>(aux),
-- static_cast<int>(aArgs.args[0]),
-- reinterpret_cast<AddrPtr>(aArgs.args[1]),
-- static_cast<socklen_t>(aArgs.args[2]));
-- }
--
-- static intptr_t ConnectTrapLegacy(ArgsRef aArgs, void* aux) {
-- const auto innerArgs = reinterpret_cast<unsigned long*>(aArgs.args[1]);
-- typedef const struct sockaddr_un* AddrPtr;
--
-- return ConnectTrapCommon(static_cast<SandboxBrokerClient*>(aux),
-- static_cast<int>(innerArgs[0]),
-- reinterpret_cast<AddrPtr>(innerArgs[1]),
-- static_cast<socklen_t>(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<ResultExpr> 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<ResultExpr> 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<ResultExpr> 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<ResultExpr> 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 <termios.h>
- # include <sys/resource.h>
- # include <sys/time.h>
- # include <sys/utsname.h>
- # include <sched.h>
-+# include <sys/socket.h>
- # include <sys/syscall.h>
- # include <sys/un.h>
- # include <linux/mempolicy.h>
- # 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<ResultExpr> EvaluateIpcCall(int aCall, int aArgShift) const override {
- // The Intel media driver uses SysV IPC (semaphores and shared
-@@ -1818,15 +1819,15 @@
- #endif
-
- Maybe<ResultExpr> 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<DMABufSurfaceRGBA> CreateDMABufSurface(
- int aWidth, int aHeight, int aDMABufSurfaceFlags);
-
-+ static already_AddRefed<DMABufSurface> 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<EGLint> 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<DMABufSurface> DMABufSurfaceRGBA::CreateDMABufSurface(
-+ mozilla::gl::GLContext* aGLContext, const EGLImageKHR aEGLImage, int aWidth,
-+ int aHeight) {
-+ RefPtr<DMABufSurfaceRGBA> surf = new DMABufSurfaceRGBA();
-+ if (!surf->Create(aGLContext, aEGLImage, aWidth, aHeight)) {
-+ return nullptr;
-+ }
-+ return surf.forget();
-+}
-+
- already_AddRefed<DMABufSurfaceYUV> DMABufSurfaceYUV::CreateYUVSurface(
- const VADRMPRIMESurfaceDescriptor& aDesc, int aWidth, int aHeight) {
- RefPtr<DMABufSurfaceYUV> 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> SharedSurface_DMABUF::Create(
- const SharedSurfaceDesc& desc) {
-- const auto flags = static_cast<DMABufSurfaceFlags>(
-- DMABUF_TEXTURE | DMABUF_USE_MODIFIERS | DMABUF_ALPHA);
-- const RefPtr<DMABufSurface> 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<DMABufSurface> surface;
-+ UniquePtr<MozFramebuffer> 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<DMABufSurfaceFlags>(
-+ 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<EGLClientBuffer>(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<SurfaceFactory_DMABUF> Surface
- }
-
- auto dmabufFactory = MakeUnique<SurfaceFactory_DMABUF>(gl);
-- if (dmabufFactory->CanCreateSurface()) {
-+ if (dmabufFactory->CanCreateSurface(gl)) {
- return dmabufFactory;
- }
-
-@@ -71,8 +104,38 @@ UniquePtr<SurfaceFactory_DMABUF> Surface
- return nullptr;
- }
-
-+bool SurfaceFactory_DMABUF::CanCreateSurface(GLContext& gl) {
-+ UniquePtr<SharedSurface> 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<DMABufSurface> 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<SharedSurface> 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<GfxDriverInfo>& 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> GLContextEGL::Creat
- }
-
- /*static*/
--RefPtr<GLContextEGL> GLContextEGL::CreateEGLSurfacelessContext(
-- const std::shared_ptr<EglDisplay> display, const GLContextCreateDesc& desc,
-- nsACString* const out_failureId) {
-- const EGLConfig config = {};
-- auto fullDesc = GLContextDesc{desc};
-- fullDesc.isOffscreen = true;
-- RefPtr<GLContextEGL> 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<GLContext> GLContextProviderEGL::CreateHeadless(
- const GLContextCreateDesc& desc, nsACString* const out_failureId) {
- const auto display = DefaultEglDisplay(out_failureId);
- if (!display) {
- return nullptr;
- }
-- RefPtr<GLContextEGL> 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> 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<EglDisplay> GetAn
- }
-
- #ifdef MOZ_WAYLAND
-+static std::shared_ptr<EglDisplay> 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<EGLDeviceEXT> 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<EglDisplay> 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<EglDisplay> 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 <dglastonbury(a)mozilla.com>"]
-+
-+[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<T>(...)` 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<CB>(&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::<F>() == 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::<F>()(&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<Self>
-+ where OPT: Into<Option<&'a CStr>>
-+ {
-+ 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<CB>(&self, _: CB, userdata: *mut c_void)
-+ where CB: Fn(&Context, *mut c_void)
-+ {
-+ debug_assert_eq!(::std::mem::size_of::<CB>(), 0);
-+
-+ // See: A note about `wrapped` functions
-+ unsafe extern "C" fn wrapped<F>(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::<F>()(&ctx, userdata);
-+ forget(ctx);
-+
-+ result
-+ }
-+
-+ unsafe {
-+ ffi::pa_context_set_state_callback(self.raw_mut(), Some(wrapped::<CB>), 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<Option<&'a CStr>>
-+ {
-+ 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<CB>(&self, _: CB, userdata: *mut c_void) -> Result<Operation>
-+ where CB: Fn(&Context, *mut c_void)
-+ {
-+ debug_assert_eq!(::std::mem::size_of::<CB>(), 0);
-+
-+ // See: A note about `wrapped` functions
-+ unsafe extern "C" fn wrapped<F>(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::<F>()(&ctx, userdata);
-+ forget(ctx);
-+
-+ result
-+ }
-+
-+ op_or_err!(self,
-+ ffi::pa_context_drain(self.raw_mut(), Some(wrapped::<CB>), userdata))
-+ }
-+
-+ pub fn rttime_new<CB>(&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::<CB>(), 0);
-+
-+ // See: A note about `wrapped` functions
-+ unsafe extern "C" fn wrapped<F>(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::<F>()(&api, e, timeval, userdata);
-+ forget(api);
-+
-+ result
-+ }
-+
-+ unsafe { ffi::pa_context_rttime_new(self.raw_mut(), usec, Some(wrapped::<CB>), userdata) }
-+ }
-+
-+ pub fn get_server_info<CB>(&self, _: CB, userdata: *mut c_void) -> Result<Operation>
-+ where CB: Fn(&Context, &ServerInfo, *mut c_void)
-+ {
-+ debug_assert_eq!(::std::mem::size_of::<CB>(), 0);
-+
-+ // See: A note about `wrapped` functions
-+ unsafe extern "C" fn wrapped<F>(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::<F>()(&ctx, info, userdata);
-+ forget(ctx);
-+
-+ result
-+ }
-+
-+ op_or_err!(self,
-+ ffi::pa_context_get_server_info(self.raw_mut(), Some(wrapped::<CB>), userdata))
-+ }
-+
-+ pub fn get_sink_info_by_name<CB>(&self, name: &CStr, _: CB, userdata: *mut c_void) -> Result<Operation>
-+ where CB: Fn(&Context, *const SinkInfo, i32, *mut c_void)
-+ {
-+ debug_assert_eq!(::std::mem::size_of::<CB>(), 0);
-+
-+ // See: A note about `wrapped` functions
-+ unsafe extern "C" fn wrapped<F>(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::<F>()(&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::<CB>), userdata))
-+ }
-+
-+ pub fn get_sink_info_list<CB>(&self, _: CB, userdata: *mut c_void) -> Result<Operation>
-+ where CB: Fn(&Context, *const SinkInfo, i32, *mut c_void)
-+ {
-+ debug_assert_eq!(::std::mem::size_of::<CB>(), 0);
-+
-+ // See: A note about `wrapped` functions
-+ unsafe extern "C" fn wrapped<F>(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::<F>()(&ctx, info, eol, userdata);
-+ forget(ctx);
-+
-+ result
-+ }
-+
-+ op_or_err!(self,
-+ ffi::pa_context_get_sink_info_list(self.raw_mut(), Some(wrapped::<CB>), userdata))
-+ }
-+
-+ pub fn get_sink_input_info<CB>(&self, idx: u32, _: CB, userdata: *mut c_void) -> Result<Operation>
-+ where CB: Fn(&Context, *const SinkInputInfo, i32, *mut c_void)
-+ {
-+ debug_assert_eq!(::std::mem::size_of::<CB>(), 0);
-+
-+ // See: A note about `wrapped` functions
-+ unsafe extern "C" fn wrapped<F>(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::<F>()(&ctx, info, eol, userdata);
-+ forget(ctx);
-+
-+ result
-+ }
-+
-+ op_or_err!(self,
-+ ffi::pa_context_get_sink_input_info(self.raw_mut(), idx, Some(wrapped::<CB>), userdata))
-+ }
-+
-+ pub fn get_source_info_list<CB>(&self, _: CB, userdata: *mut c_void) -> Result<Operation>
-+ where CB: Fn(&Context, *const SourceInfo, i32, *mut c_void)
-+ {
-+ debug_assert_eq!(::std::mem::size_of::<CB>(), 0);
-+
-+ // See: A note about `wrapped` functions
-+ unsafe extern "C" fn wrapped<F>(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::<F>()(&ctx, info, eol, userdata);
-+ forget(ctx);
-+
-+ result
-+ }
-+
-+ op_or_err!(self,
-+ ffi::pa_context_get_source_info_list(self.raw_mut(), Some(wrapped::<CB>), userdata))
-+ }
-+
-+ pub fn set_sink_input_volume<CB>(&self,
-+ idx: u32,
-+ volume: &CVolume,
-+ _: CB,
-+ userdata: *mut c_void)
-+ -> Result<Operation>
-+ where CB: Fn(&Context, i32, *mut c_void)
-+ {
-+ debug_assert_eq!(::std::mem::size_of::<CB>(), 0);
-+
-+ // See: A note about `wrapped` functions
-+ unsafe extern "C" fn wrapped<F>(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::<F>()(&ctx, success, userdata);
-+ forget(ctx);
-+
-+ result
-+ }
-+
-+ op_or_err!(self,
-+ ffi::pa_context_set_sink_input_volume(self.raw_mut(), idx, volume, Some(wrapped::<CB>), userdata))
-+ }
-+
-+ pub fn subscribe<CB>(&self, m: SubscriptionMask, _: CB, userdata: *mut c_void) -> Result<Operation>
-+ where CB: Fn(&Context, i32, *mut c_void)
-+ {
-+ debug_assert_eq!(::std::mem::size_of::<CB>(), 0);
-+
-+ // See: A note about `wrapped` functions
-+ unsafe extern "C" fn wrapped<F>(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::<F>()(&ctx, success, userdata);
-+ forget(ctx);
-+
-+ result
-+ }
-+
-+ op_or_err!(self,
-+ ffi::pa_context_subscribe(self.raw_mut(), m.into(), Some(wrapped::<CB>), 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<CB>(&self, _: CB, userdata: *mut c_void)
-+ where CB: Fn(&Context, SubscriptionEvent, u32, *mut c_void)
-+ {
-+ debug_assert_eq!(::std::mem::size_of::<CB>(), 0);
-+
-+ // See: A note about `wrapped` functions
-+ unsafe extern "C" fn wrapped<F>(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::<F>()(&ctx, event, idx, userdata);
-+ forget(ctx);
-+
-+ result
-+ }
-+
-+ unsafe {
-+ ffi::pa_context_set_subscribe_callback(self.raw_mut(), Some(wrapped::<CB>), 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<ffi::pa_sample_format_t> 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<Self> {
-+ 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<ffi::pa_context_state_t> 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<Self> {
-+ 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<ffi::pa_stream_state_t> 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<Self> {
-+ if x >= ffi::PA_OPERATION_RUNNING && x <= ffi::PA_OPERATION_CANCELLED {
-+ Some(unsafe { ::std::mem::transmute(x) })
-+ } else {
-+ None
-+ }
-+ }
-+}
-+
-+impl Into<ffi::pa_operation_state_t> 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<ffi::pa_context_flags_t> 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<Self> {
-+ if x >= ffi::PA_DEVICE_TYPE_SINK && x <= ffi::PA_DEVICE_TYPE_SOURCE {
-+ Some(unsafe { ::std::mem::transmute(x) })
-+ } else {
-+ None
-+ }
-+ }
-+}
-+
-+impl Into<ffi::pa_device_type_t> 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<Self> {
-+ if x >= ffi::PA_STREAM_NODIRECTION && x <= ffi::PA_STREAM_UPLOAD {
-+ Some(unsafe { ::std::mem::transmute(x) })
-+ } else {
-+ None
-+ }
-+ }
-+}
-+
-+impl Into<ffi::pa_stream_direction_t> 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<Self> {
-+ 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<ffi::pa_stream_flags_t> 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<Self> {
-+ if (x & !ffi::PA_SUBSCRIPTION_MASK_ALL) == 0 {
-+ Some(unsafe { ::std::mem::transmute(x) })
-+ } else {
-+ None
-+ }
-+ }
-+}
-+
-+impl Into<ffi::pa_subscription_mask_t> 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<Self> {
-+ 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<Self> {
-+ if x >= ffi::PA_SEEK_RELATIVE && x <= ffi::PA_SEEK_RELATIVE_END {
-+ Some(unsafe { ::std::mem::transmute(x) })
-+ } else {
-+ None
-+ }
-+ }
-+}
-+
-+impl Into<ffi::pa_seek_mode_t> 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<SinkFlags> {
-+ 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<ffi::pa_source_flags_t> 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<Self> {
-+ if x >= ffi::PA_PORT_AVAILABLE_UNKNOWN && x <= ffi::PA_PORT_AVAILABLE_YES {
-+ Some(unsafe { ::std::mem::transmute(x) })
-+ } else {
-+ None
-+ }
-+ }
-+}
-+
-+impl Into<ffi::pa_port_available_t> 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<Self> {
-+ 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<ffi::pa_channel_position_t> for ChannelPosition {
-+ fn into(self) -> ffi::pa_channel_position_t {
-+ self as ffi::pa_channel_position_t
-+ }
-+}
-+pub type Result<T> = ::std::result::Result<T, error::ErrorCode>;
-+
-+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<unsafe extern "C" fn(m: *mut ffi::pa_mainloop_api,
-+ userdata: *mut c_void)>;
-+fn wrap_once_cb<F>(_: F) -> pa_once_cb_t
-+ where F: Fn(&MainloopApi, *mut c_void)
-+{
-+ assert!(mem::size_of::<F>() == 0);
-+
-+ unsafe extern "C" fn wrapped<F>(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::<F>)
-+}
-+
-+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<CB>(&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<T>(&self, key: T) -> Option<&CStr>
-+ where T: Into<Vec<u8>>
-+ {
-+ 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<Self>
-+ where CM: Into<Option<&'a ChannelMap>>
-+ {
-+ 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<Context> {
-+ 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<bool> {
-+ let r = unsafe { ffi::pa_stream_is_suspended(self.raw_mut()) };
-+ error_result!(r != 0, r)
-+ }
-+
-+ pub fn is_corked(&self) -> Result<bool> {
-+ 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<Option<&'a CStr>>,
-+ A: Into<Option<&'a BufferAttr>>,
-+ V: Into<Option<&'a CVolume>>,
-+ S: Into<Option<&'a mut Stream>>
-+ {
-+ 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<Option<&'a CStr>>,
-+ A: Into<Option<&'a BufferAttr>>
-+ {
-+ 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<usize> {
-+ 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<usize> {
-+ 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<CB>(&self, _: CB, userdata: *mut c_void) -> Result<Operation>
-+ where CB: Fn(&Stream, i32, *mut c_void)
-+ {
-+ debug_assert_eq!(mem::size_of::<CB>(), 0);
-+
-+ // See: A note about `wrapped` functions
-+ unsafe extern "C" fn wrapped<F>(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::<F>()(&mut stm, success, userdata);
-+ forget(stm);
-+
-+ result
-+ }
-+
-+ let r = unsafe { ffi::pa_stream_update_timing_info(self.raw_mut(), Some(wrapped::<CB>), 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<CB>(&self, _: CB, userdata: *mut c_void)
-+ where CB: Fn(&Stream, *mut c_void)
-+ {
-+ debug_assert_eq!(mem::size_of::<CB>(), 0);
-+
-+ // See: A note about `wrapped` functions
-+ unsafe extern "C" fn wrapped<F>(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::<F>()(&mut stm, userdata);
-+ forget(stm);
-+
-+ result
-+ }
-+
-+ unsafe {
-+ ffi::pa_stream_set_state_callback(self.raw_mut(), Some(wrapped::<CB>), 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<CB>(&self, _: CB, userdata: *mut c_void)
-+ where CB: Fn(&Stream, usize, *mut c_void)
-+ {
-+ debug_assert_eq!(mem::size_of::<CB>(), 0);
-+
-+ // See: A note about `wrapped` functions
-+ unsafe extern "C" fn wrapped<F>(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::<F>()(&mut stm, nbytes, userdata);
-+ forget(stm);
-+
-+ result
-+ }
-+
-+ unsafe {
-+ ffi::pa_stream_set_write_callback(self.raw_mut(), Some(wrapped::<CB>), 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<CB>(&self, _: CB, userdata: *mut c_void)
-+ where CB: Fn(&Stream, usize, *mut c_void)
-+ {
-+ debug_assert_eq!(mem::size_of::<CB>(), 0);
-+
-+ // See: A note about `wrapped` functions
-+ unsafe extern "C" fn wrapped<F>(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::<F>()(&mut stm, nbytes, userdata);
-+ forget(stm);
-+
-+ result
-+ }
-+
-+ unsafe {
-+ ffi::pa_stream_set_read_callback(self.raw_mut(), Some(wrapped::<CB>), userdata);
-+ }
-+ }
-+
-+ pub fn cork<CB>(&self, b: i32, _: CB, userdata: *mut c_void) -> Result<Operation>
-+ where CB: Fn(&Stream, i32, *mut c_void)
-+ {
-+ debug_assert_eq!(mem::size_of::<CB>(), 0);
-+
-+ // See: A note about `wrapped` functions
-+ unsafe extern "C" fn wrapped<F>(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::<F>()(&mut stm, success, userdata);
-+ forget(stm);
-+
-+ result
-+ }
-+
-+ let r = unsafe { ffi::pa_stream_cork(self.raw_mut(), b, Some(wrapped::<CB>), 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<Option<&'a CStr>>
-+{
-+ 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<T, U, F: FnOnce(&T) -> *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>(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 Build Status](https://travis-ci.org/djg/cubeb-pulse-rs.svg?branch=dev)](https://t…
-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<pulse::Context>,
- pub default_sink_info: Option<DefaultInfo>,
-- pub context_name: *const c_char,
-+ pub context_name: Option<CString>,
- 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<Box<Self>> {
-+ fn _new(name: Option<CString>) -> Result<Box<Self>> {
- 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<Box<Self>> {
-+ fn _new(name: Option<CString>) -> Result<Box<Self>> {
- 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<Box<Self>> {
-+ 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<cubeb::StreamParams>,
- output_device: cubeb::DeviceId,
-@@ -178,7 +184,7 @@ impl Context {
- state_callback: cubeb::StateCallback,
- user_ptr: *mut c_void)
- -> Result<Box<Stream>> {
-- 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<cubeb::DeviceCollection> {
-- 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<Option<&'a pulse::Stream>>
-+ {
-+ 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<cubeb::DeviceInfo>,
-- 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<T> = ::std::result::Result<T, i32>;
-
- pub use self::context::Context;
- pub use self::stream::Device;
- pub use self::stream::Stream;
-+
-+// helper to convert *const c_char to Option<CStr>
-+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<pulse::Stream>,
-+ input_stream: Option<pulse::Stream>,
- 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<cubeb::StreamParams>,
- output_device: cubeb::DeviceId,
-@@ -99,83 +101,167 @@ impl<'ctx> Stream<'ctx> {
- user_ptr: *mut c_void)
- -> Result<Box<Stream<'ctx>>> {
-
-+ 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<u64> {
-- 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<u32> {
-- 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<u32> {
-+ 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<Box<cubeb::Device>> {
- 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<pulse::Stream> {
-
-- 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<pa_channel_map> = 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<cubeb::StreamParams> {
-+ 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<GfxDriverInfo>& 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<GfxDriverInfo>& 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 <klember(a)redhat.com> - 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 <jhorak(a)redhat.com> - 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<wr::PipelineId, wr::Epoch> key(aPipelineId, aEpoch);
-- nsTArray<CompositionPayload> 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<ImageCompositeNotificationInfo> notifications;
-- mWrBridge->ExtractImageCompositeNotifications(¬ifications);
-- if (!notifications.IsEmpty()) {
-- Unused << ImageBridgeParent::NotifyImageComposites(notifications);
-- }
-+ if (mIsForcedFirstPaint) {
-+ uiController->NotifyFirstPaint();
-+ mIsForcedFirstPaint = false;
-+ }
-+
-+ std::pair<wr::PipelineId, wr::Epoch> key(aPipelineId, aEpoch);
-+ nsTArray<CompositionPayload> 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<ImageCompositeNotificationInfo> 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<wr::PipelineId, wr::Epoch> key(aPipelineId, aEpoch);
-- nsTArray<CompositionPayload> 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<wr::PipelineId, wr::Epoch> key(aPipelineId, aEpoch);
-+ nsTArray<CompositionPayload> 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 <stransky(a)redhat.com>
-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<nsWaylandDisplay> 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<nsWaylandDisplay> 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<nsWaylandDisplay> 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<WindowBackBuffer*>(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<nsWaylandDisplay> aDisplay, int aSize);
-- ~WaylandShmPool();
--
-- bool Resize(int aSize);
-+ bool Create(RefPtr<nsWaylandDisplay> 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<gfx::DrawTarget> 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=…
-+ // https://source.chromium.org/chromium/chromium/src/+/master:components/cdm/c…
- //
- // Gecko's internal strings can be found at
- // https://searchfox.org/mozilla-central/rev/ea63a0888d406fae720cf24f4727d8756…
-@@ -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 <stransky(a)redhat.com>
-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<LIBAV_VER>::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 <stransky(a)redhat.com>
-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<nsString, 1> 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 =
- "<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection "
- "1.0//EN\"\n"
-- "\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\";>\n"
-+ "\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n"
- "<node>\n"
- " <interface name=\"org.freedesktop.DBus.Introspectable\">\n"
- " <method name=\"Introspect\">\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<nsINSSComponent> 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"}
commit 1ad3bd1b2451eba507ab60632c8e4b5c9325f21e
Author: Kalev Lember <klember(a)redhat.com>
Date: Wed Aug 17 10:26:14 2022 +0200
Drop obsolete build conditionals
This drops ifarch conditionals on architectures that are no longer used
in koji (ppc64, s390, arm on F37+), and conditionals on EOL Fedora
versions.
diff --git a/firefox.spec b/firefox.spec
index ea8a25b..f970fe1 100644
--- a/firefox.spec
+++ b/firefox.spec
@@ -33,18 +33,6 @@
# https://bugzilla.redhat.com/show_bug.cgi?id=1897522
ExcludeArch: s390x
-# Disabled due to
-# https://bugzilla.redhat.com/show_bug.cgi?id=1966949
-%if 0%{?fedora} > 36
-ExcludeArch: armv7hl
-%endif
-
-# Disabled due to
-# https://bugzilla.redhat.com/show_bug.cgi?id=2019160
-%if 0%{?fedora} == 33
-ExcludeArch: aarch64
-%endif
-
%ifarch armv7hl
%global create_debuginfo 0
@@ -96,7 +84,7 @@ ExcludeArch: aarch64
%global build_with_pgo 0
%endif
# Big endian platforms
-%ifarch ppc64 s390x
+%ifarch s390x
%global big_endian 1
%endif
@@ -214,7 +202,6 @@ Source45: run-wayland-compositor
# Build patches
Patch3: mozilla-build-arm.patch
-Patch25: rhbz-1219542-s390-build.patch
Patch32: build-rust-ppc64le.patch
Patch35: build-ppc-jit.patch
# Fixing missing cacheFlush when JS_CODEGEN_NONE is used (s390x)
@@ -391,10 +378,7 @@ BuildRequires: liberation-mono-fonts
BuildRequires: liberation-sans-fonts
BuildRequires: liberation-serif-fonts
# ----------------------------------
-# Missing on f32
-%if 0%{?fedora} > 33
BuildRequires: google-carlito-fonts
-%endif
BuildRequires: google-droid-sans-fonts
BuildRequires: google-noto-fonts-common
BuildRequires: google-noto-cjk-fonts-common
@@ -413,10 +397,7 @@ BuildRequires: lohit-tamil-fonts
BuildRequires: lohit-telugu-fonts
# ----------------------------------
BuildRequires: paktype-naskh-basic-fonts
-# faild to build in Koji / f32
-%if 0%{?fedora} > 33
BuildRequires: pt-sans-fonts
-%endif
BuildRequires: smc-meera-fonts
BuildRequires: stix-fonts
BuildRequires: abattis-cantarell-fonts
@@ -485,9 +466,6 @@ This package contains results of tests executed during build.
# there is a compare of config and js/config directories and .orig suffix is
# ignored during this compare.
-%ifarch s390
-%patch25 -p1 -b .rhbz-1219542-s390
-%endif
%patch40 -p1 -b .aarch64-skia
%if 0%{?disable_elfhack}
%patch41 -p1 -b .disable-elfhack
@@ -612,7 +590,7 @@ echo "ac_add_options --with-system-libvpx" >> .mozconfig
echo "ac_add_options --without-system-libvpx" >> .mozconfig
%endif
-%ifarch s390 s390x
+%ifarch s390x
echo "ac_add_options --disable-jit" >> .mozconfig
%endif
@@ -676,34 +654,24 @@ MOZ_OPT_FLAGS=$(echo "%{optflags}" | %{__sed} -e 's/-Wall//')
# for some sources
# Explicitly force the hardening flags for Firefox so it passes the checksec test;
# See also https://fedoraproject.org/wiki/Changes/Harden_All_Packages
-%if 0%{?fedora} < 30
-MOZ_OPT_FLAGS="$MOZ_OPT_FLAGS -Wformat-security -Wformat -Werror=format-security"
-%else
# Workaround for mozbz#1531309
MOZ_OPT_FLAGS=$(echo "$MOZ_OPT_FLAGS" | %{__sed} -e 's/-Werror=format-security//')
-%endif
-%if 0%{?fedora} > 30
MOZ_OPT_FLAGS="$MOZ_OPT_FLAGS -fpermissive"
-%endif
%if %{?hardened_build}
MOZ_OPT_FLAGS="$MOZ_OPT_FLAGS -fPIC -Wl,-z,relro -Wl,-z,now"
%endif
%if %{?debug_build}
MOZ_OPT_FLAGS=$(echo "$MOZ_OPT_FLAGS" | %{__sed} -e 's/-O2//')
%endif
-%ifarch s390
-MOZ_OPT_FLAGS=$(echo "$MOZ_OPT_FLAGS" | %{__sed} -e 's/-g/-g1/')
# If MOZ_DEBUG_FLAGS is empty, firefox's build will default it to "-g" which
# overrides the -g1 from line above and breaks building on s390/arm
# (OOM when linking, rhbz#1238225)
-export MOZ_DEBUG_FLAGS=" "
-%endif
%ifarch %{arm} %{ix86}
MOZ_OPT_FLAGS=$(echo "$MOZ_OPT_FLAGS" | %{__sed} -e 's/-g/-g0/')
export MOZ_DEBUG_FLAGS=" "
%endif
%if !%{build_with_clang}
-%ifarch s390 ppc aarch64 %{ix86}
+%ifarch aarch64 %{ix86}
MOZ_LINK_FLAGS="-Wl,--no-keep-memory -Wl,--reduce-memory-overheads"
%endif
%ifarch %{arm}
@@ -1107,6 +1075,7 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || :
%changelog
* Tue Aug 23 2022 Kalev Lember <klember(a)redhat.com> - 104.0-5
- Use constrain_build macro to simplify parallel make handling
+- Drop obsolete build conditionals
* Tue Aug 23 2022 Jan Horak <jhorak(a)redhat.com> - 104.0-4
- Rebuild due to ppc64le fixes
diff --git a/rhbz-1219542-s390-build.patch b/rhbz-1219542-s390-build.patch
deleted file mode 100644
index f94e43a..0000000
--- a/rhbz-1219542-s390-build.patch
+++ /dev/null
@@ -1,23 +0,0 @@
-diff -up firefox-55.0/js/src/old-configure.in.rhbz-1219542-s390 firefox-55.0/js/src/old-configure.in
---- firefox-55.0/js/src/old-configure.in.rhbz-1219542-s390 2017-07-31 18:20:48.000000000 +0200
-+++ firefox-55.0/js/src/old-configure.in 2017-08-02 14:31:32.190243669 +0200
-@@ -541,7 +541,7 @@ case "$host" in
-
- *-linux*|*-kfreebsd*-gnu|*-gnu*)
- HOST_CFLAGS="$HOST_CFLAGS -DXP_UNIX"
-- HOST_OPTIMIZE_FLAGS="${HOST_OPTIMIZE_FLAGS=-O3}"
-+ HOST_OPTIMIZE_FLAGS="${HOST_OPTIMIZE_FLAGS=-O1}"
- ;;
-
- *)
-@@ -617,8 +617,8 @@ case "$target" in
-
- *-*linux*)
- if test "$GNU_CC" -o "$GNU_CXX"; then
-- MOZ_PGO_OPTIMIZE_FLAGS="-O3"
-- MOZ_OPTIMIZE_FLAGS="-O3"
-+ MOZ_PGO_OPTIMIZE_FLAGS="-O1"
-+ MOZ_OPTIMIZE_FLAGS="-O1"
- if test -z "$CLANG_CC"; then
- MOZ_OPTIMIZE_FLAGS="-freorder-blocks $MOZ_OPTIMIZE_FLAGS"
- fi
commit 7e1b07c41aea995e1618e073e8c3a1718a6b6249
Author: Kalev Lember <klember(a)redhat.com>
Date: Wed Aug 17 10:25:36 2022 +0200
Use constrain_build macro to simplify parallel make handling
With constrain_build it is possible to just say how much RAM per process
/ CPU core we need to build and it automatically calculates out the
right -jXX number to use.
I've used 2 GB per CPU as the initial setting, but if we run into issues
with gcc running out of memory on e.g. s390x, the number can be easily
increased (which then reduces parallelism on low memory builders).
diff --git a/firefox.spec b/firefox.spec
index b3cfd98..ea8a25b 100644
--- a/firefox.spec
+++ b/firefox.spec
@@ -177,7 +177,7 @@ ExcludeArch: aarch64
Summary: Mozilla Firefox Web browser
Name: firefox
Version: 104.0
-Release: 4%{?pre_tag}%{?dist}
+Release: 5%{?pre_tag}%{?dist}
URL: https://www.mozilla.org/firefox/
License: MPLv1.1 or GPLv2+ or LGPLv2+
Source0: https://archive.mozilla.org/pub/firefox/releases/%{version}%{?pre_version}/…
@@ -760,27 +760,10 @@ echo "ac_add_options MOZ_PGO=1" >> .mozconfig
export CCACHE_DISABLE=1
%endif
-MOZ_SMP_FLAGS=-j1
-# On x86_64 architectures, Mozilla can build up to 4 jobs at once in parallel,
-# however builds tend to fail on other arches when building in parallel.
-%ifarch %{ix86} s390x %{arm} aarch64
-[ -z "$RPM_BUILD_NCPUS" ] && \
- RPM_BUILD_NCPUS="`/usr/bin/getconf _NPROCESSORS_ONLN`"
-[ "$RPM_BUILD_NCPUS" -ge 2 ] && MOZ_SMP_FLAGS=-j2
-%endif
-%ifarch x86_64 ppc ppc64 ppc64le
-[ -z "$RPM_BUILD_NCPUS" ] && \
- RPM_BUILD_NCPUS="`/usr/bin/getconf _NPROCESSORS_ONLN`"
-[ "$RPM_BUILD_NCPUS" -ge 2 ] && MOZ_SMP_FLAGS=-j2
-[ "$RPM_BUILD_NCPUS" -ge 4 ] && MOZ_SMP_FLAGS=-j4
-[ "$RPM_BUILD_NCPUS" -ge 8 ] && MOZ_SMP_FLAGS=-j8
-[ "$RPM_BUILD_NCPUS" -ge 16 ] && MOZ_SMP_FLAGS=-j16
-[ "$RPM_BUILD_NCPUS" -ge 24 ] && MOZ_SMP_FLAGS=-j24
-[ "$RPM_BUILD_NCPUS" -ge 32 ] && MOZ_SMP_FLAGS=-j32
-[ "$RPM_BUILD_NCPUS" -ge 64 ] && MOZ_SMP_FLAGS=-j64
-%endif
+# Require 2 GB of RAM per CPU core
+%constrain_build -m 2048
-echo "mk_add_options MOZ_MAKE_FLAGS=\"$MOZ_SMP_FLAGS\"" >> .mozconfig
+echo "mk_add_options MOZ_MAKE_FLAGS=\"-j%{_smp_build_ncpus}\"" >> .mozconfig
echo "mk_add_options MOZ_SERVICES_SYNC=1" >> .mozconfig
echo "export STRIP=/bin/true" >> .mozconfig
#export MACH_USE_SYSTEM_PYTHON=1
@@ -1122,6 +1105,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || :
#---------------------------------------------------------------------
%changelog
+* Tue Aug 23 2022 Kalev Lember <klember(a)redhat.com> - 104.0-5
+- Use constrain_build macro to simplify parallel make handling
+
* Tue Aug 23 2022 Jan Horak <jhorak(a)redhat.com> - 104.0-4
- Rebuild due to ppc64le fixes
The package rpms/firefox.git has added or updated architecture specific content in its
spec file (ExclusiveArch/ExcludeArch or %ifarch/%ifnarch) in commit(s):
https://src.fedoraproject.org/cgit/rpms/firefox.git/commit/?id=f5c2bd2d80a2…
https://src.fedoraproject.org/cgit/rpms/firefox.git/commit/?id=1ad3bd1b2451…
https://src.fedoraproject.org/cgit/rpms/firefox.git/commit/?id=7e1b07c41aea….
Change:
-ExcludeArch: s390x
+%ifarch aarch64 %{ix86}
-%ifarch x86_64 ppc ppc64 ppc64le
Thanks.
Full change:
============
commit f5c2bd2d80a2c69fa7e0f3e5bcda6b16493bf958
Author: Kalev Lember <klember(a)redhat.com>
Date: Wed Aug 17 10:32:01 2022 +0200
Re-enable s390x builds
It builds fine again after latest fixes.
diff --git a/firefox.spec b/firefox.spec
index 26bd17a..9d407b3 100644
--- a/firefox.spec
+++ b/firefox.spec
@@ -28,11 +28,6 @@
%global build_with_clang 0
%endif
-# There are still build problems on s390x, see
-# https://koji.fedoraproject.org/koji/taskinfo?taskID=55048351
-# https://bugzilla.redhat.com/show_bug.cgi?id=1897522
-ExcludeArch: s390x
-
%ifarch armv7hl
%global create_debuginfo 0
@@ -1071,6 +1066,7 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || :
- Drop unused patches
- Use build_ldflags
- Drop hardened_build option
+- Re-enable s390x builds
* Tue Aug 23 2022 Jan Horak <jhorak(a)redhat.com> - 104.0-4
- Rebuild due to ppc64le fixes
commit 73c24a4d458769b6a8560eb855a4f7a2545fe998
Author: Kalev Lember <klember(a)redhat.com>
Date: Wed Aug 17 10:31:20 2022 +0200
Drop hardened_build option
Now that we correctly use Fedora's ldflags (previous commit), there's
no need to do anything special to enable hardened build. All of it is
already included in the default build flags.
diff --git a/firefox.spec b/firefox.spec
index bb7b33f..26bd17a 100644
--- a/firefox.spec
+++ b/firefox.spec
@@ -65,7 +65,6 @@ ExcludeArch: s390x
%else
%global system_libvpx 0
%endif
-%global hardened_build 1
%global system_jpeg 1
%global disable_elfhack 1
%global use_bundled_cbindgen 1
@@ -657,9 +656,6 @@ MOZ_OPT_FLAGS=$(echo "%{optflags}" | %{__sed} -e 's/-Wall//')
# Workaround for mozbz#1531309
MOZ_OPT_FLAGS=$(echo "$MOZ_OPT_FLAGS" | %{__sed} -e 's/-Werror=format-security//')
MOZ_OPT_FLAGS="$MOZ_OPT_FLAGS -fpermissive"
-%if %{?hardened_build}
-MOZ_OPT_FLAGS="$MOZ_OPT_FLAGS -fPIC -Wl,-z,relro -Wl,-z,now"
-%endif
%if %{?debug_build}
MOZ_OPT_FLAGS=$(echo "$MOZ_OPT_FLAGS" | %{__sed} -e 's/-O2//')
%endif
@@ -1074,6 +1070,7 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || :
- Drop obsolete build conditionals
- Drop unused patches
- Use build_ldflags
+- Drop hardened_build option
* Tue Aug 23 2022 Jan Horak <jhorak(a)redhat.com> - 104.0-4
- Rebuild due to ppc64le fixes
commit 078b597b1e74879a6c87fc30ec101b5dd3011057
Author: Kalev Lember <klember(a)redhat.com>
Date: Wed Aug 17 10:30:14 2022 +0200
Use build_ldflags
These are the LDFLAGS that all packages are supposed to use, including
hardening and other flags.
diff --git a/firefox.spec b/firefox.spec
index 221882a..bb7b33f 100644
--- a/firefox.spec
+++ b/firefox.spec
@@ -670,20 +670,16 @@ MOZ_OPT_FLAGS=$(echo "$MOZ_OPT_FLAGS" | %{__sed} -e 's/-O2//')
MOZ_OPT_FLAGS=$(echo "$MOZ_OPT_FLAGS" | %{__sed} -e 's/-g/-g0/')
export MOZ_DEBUG_FLAGS=" "
%endif
+MOZ_LINK_FLAGS="%{build_ldflags}"
%if !%{build_with_clang}
%ifarch aarch64 %{ix86}
-MOZ_LINK_FLAGS="-Wl,--no-keep-memory -Wl,--reduce-memory-overheads"
+MOZ_LINK_FLAGS="$MOZ_LINK_FLAGS -Wl,--no-keep-memory -Wl,--reduce-memory-overheads"
%endif
%ifarch %{arm}
-MOZ_LINK_FLAGS="-Wl,--no-keep-memory -Wl,--strip-debug"
+MOZ_LINK_FLAGS="$MOZ_LINK_FLAGS -Wl,--no-keep-memory -Wl,--strip-debug"
echo "ac_add_options --enable-linker=gold" >> .mozconfig
%endif
%endif
-%if 0%{?flatpak}
-# Make sure the linker can find libraries in /app/lib64 as we don't use
-# __global_ldflags that normally sets this.
-MOZ_LINK_FLAGS="$MOZ_LINK_FLAGS -L%{_libdir}"
-%endif
%ifarch %{arm} %{ix86} %{s390x}
export RUSTFLAGS="-Cdebuginfo=0"
%endif
@@ -1077,6 +1073,7 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || :
- Use constrain_build macro to simplify parallel make handling
- Drop obsolete build conditionals
- Drop unused patches
+- Use build_ldflags
* Tue Aug 23 2022 Jan Horak <jhorak(a)redhat.com> - 104.0-4
- Rebuild due to ppc64le fixes
commit 594959d6f80f090d837c7ca1286459de3aa1769c
Author: Kalev Lember <klember(a)redhat.com>
Date: Wed Aug 17 10:29:03 2022 +0200
Drop unused patches
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<ImageContainer> 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<LIBAV_VER>::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<LIBAV_VER>::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<sandbox::bpf_dsl::Policy> 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<ResultExpr> EvaluateIpcCall(int aCall, int aArgShift) const override {
-@@ -1875,9 +1862,10 @@ UniquePtr<sandbox::bpf_dsl::Policy> 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<sandbox::bpf_dsl::Policy> 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<int> 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<int>(aArgs.args[0]),
-+ static_cast<int>(aArgs.args[1]),
-+ static_cast<int>(aArgs.args[2]));
-+ }
-+
-+ static intptr_t FakeSocketTrapLegacy(ArgsRef aArgs, void* aux) {
-+ const auto innerArgs = reinterpret_cast<unsigned long*>(aArgs.args[1]);
-+
-+ return FakeSocketTrapCommon(static_cast<int>(innerArgs[0]),
-+ static_cast<int>(innerArgs[1]),
-+ static_cast<int>(innerArgs[2]));
-+ }
-+
-+ static Maybe<int> 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<size_t>(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<SandboxBrokerClient*>(aux),
-+ static_cast<int>(aArgs.args[0]),
-+ reinterpret_cast<AddrPtr>(aArgs.args[1]),
-+ static_cast<socklen_t>(aArgs.args[2]));
-+ }
-+
-+ static intptr_t ConnectTrapLegacy(ArgsRef aArgs, void* aux) {
-+ const auto innerArgs = reinterpret_cast<unsigned long*>(aArgs.args[1]);
-+ typedef const struct sockaddr_un* AddrPtr;
-+
-+ return ConnectTrapCommon(static_cast<SandboxBrokerClient*>(aux),
-+ static_cast<int>(innerArgs[0]),
-+ reinterpret_cast<AddrPtr>(innerArgs[1]),
-+ static_cast<socklen_t>(innerArgs[2]));
-+ }
-+
- public:
- ResultExpr InvalidSyscall() const override {
- return Trap(BlockedSyscallTrap, nullptr);
- }
-
-@@ -630,15 +745,37 @@
- return Some(Allow());
- }
- Arg<int> 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<int> 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<int>(aArgs.args[0]),
-- static_cast<int>(aArgs.args[1]),
-- static_cast<int>(aArgs.args[2]));
-- }
--
-- static intptr_t FakeSocketTrapLegacy(ArgsRef aArgs, void* aux) {
-- const auto innerArgs = reinterpret_cast<unsigned long*>(aArgs.args[1]);
--
-- return FakeSocketTrapCommon(static_cast<int>(innerArgs[0]),
-- static_cast<int>(innerArgs[1]),
-- static_cast<int>(innerArgs[2]));
-- }
--
-- static Maybe<int> 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<size_t>(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<SandboxBrokerClient*>(aux),
-- static_cast<int>(aArgs.args[0]),
-- reinterpret_cast<AddrPtr>(aArgs.args[1]),
-- static_cast<socklen_t>(aArgs.args[2]));
-- }
--
-- static intptr_t ConnectTrapLegacy(ArgsRef aArgs, void* aux) {
-- const auto innerArgs = reinterpret_cast<unsigned long*>(aArgs.args[1]);
-- typedef const struct sockaddr_un* AddrPtr;
--
-- return ConnectTrapCommon(static_cast<SandboxBrokerClient*>(aux),
-- static_cast<int>(innerArgs[0]),
-- reinterpret_cast<AddrPtr>(innerArgs[1]),
-- static_cast<socklen_t>(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<ResultExpr> 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<ResultExpr> 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<ResultExpr> 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<ResultExpr> 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 <termios.h>
- # include <sys/resource.h>
- # include <sys/time.h>
- # include <sys/utsname.h>
- # include <sched.h>
-+# include <sys/socket.h>
- # include <sys/syscall.h>
- # include <sys/un.h>
- # include <linux/mempolicy.h>
- # 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<ResultExpr> EvaluateIpcCall(int aCall, int aArgShift) const override {
- // The Intel media driver uses SysV IPC (semaphores and shared
-@@ -1818,15 +1819,15 @@
- #endif
-
- Maybe<ResultExpr> 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<DMABufSurfaceRGBA> CreateDMABufSurface(
- int aWidth, int aHeight, int aDMABufSurfaceFlags);
-
-+ static already_AddRefed<DMABufSurface> 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<EGLint> 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<DMABufSurface> DMABufSurfaceRGBA::CreateDMABufSurface(
-+ mozilla::gl::GLContext* aGLContext, const EGLImageKHR aEGLImage, int aWidth,
-+ int aHeight) {
-+ RefPtr<DMABufSurfaceRGBA> surf = new DMABufSurfaceRGBA();
-+ if (!surf->Create(aGLContext, aEGLImage, aWidth, aHeight)) {
-+ return nullptr;
-+ }
-+ return surf.forget();
-+}
-+
- already_AddRefed<DMABufSurfaceYUV> DMABufSurfaceYUV::CreateYUVSurface(
- const VADRMPRIMESurfaceDescriptor& aDesc, int aWidth, int aHeight) {
- RefPtr<DMABufSurfaceYUV> 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> SharedSurface_DMABUF::Create(
- const SharedSurfaceDesc& desc) {
-- const auto flags = static_cast<DMABufSurfaceFlags>(
-- DMABUF_TEXTURE | DMABUF_USE_MODIFIERS | DMABUF_ALPHA);
-- const RefPtr<DMABufSurface> 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<DMABufSurface> surface;
-+ UniquePtr<MozFramebuffer> 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<DMABufSurfaceFlags>(
-+ 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<EGLClientBuffer>(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<SurfaceFactory_DMABUF> Surface
- }
-
- auto dmabufFactory = MakeUnique<SurfaceFactory_DMABUF>(gl);
-- if (dmabufFactory->CanCreateSurface()) {
-+ if (dmabufFactory->CanCreateSurface(gl)) {
- return dmabufFactory;
- }
-
-@@ -71,8 +104,38 @@ UniquePtr<SurfaceFactory_DMABUF> Surface
- return nullptr;
- }
-
-+bool SurfaceFactory_DMABUF::CanCreateSurface(GLContext& gl) {
-+ UniquePtr<SharedSurface> 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<DMABufSurface> 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<SharedSurface> 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<GfxDriverInfo>& 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> GLContextEGL::Creat
- }
-
- /*static*/
--RefPtr<GLContextEGL> GLContextEGL::CreateEGLSurfacelessContext(
-- const std::shared_ptr<EglDisplay> display, const GLContextCreateDesc& desc,
-- nsACString* const out_failureId) {
-- const EGLConfig config = {};
-- auto fullDesc = GLContextDesc{desc};
-- fullDesc.isOffscreen = true;
-- RefPtr<GLContextEGL> 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<GLContext> GLContextProviderEGL::CreateHeadless(
- const GLContextCreateDesc& desc, nsACString* const out_failureId) {
- const auto display = DefaultEglDisplay(out_failureId);
- if (!display) {
- return nullptr;
- }
-- RefPtr<GLContextEGL> 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> 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<EglDisplay> GetAn
- }
-
- #ifdef MOZ_WAYLAND
-+static std::shared_ptr<EglDisplay> 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<EGLDeviceEXT> 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<EglDisplay> 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<EglDisplay> 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 <dglastonbury(a)mozilla.com>"]
-+
-+[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<T>(...)` 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<CB>(&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::<F>() == 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::<F>()(&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<Self>
-+ where OPT: Into<Option<&'a CStr>>
-+ {
-+ 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<CB>(&self, _: CB, userdata: *mut c_void)
-+ where CB: Fn(&Context, *mut c_void)
-+ {
-+ debug_assert_eq!(::std::mem::size_of::<CB>(), 0);
-+
-+ // See: A note about `wrapped` functions
-+ unsafe extern "C" fn wrapped<F>(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::<F>()(&ctx, userdata);
-+ forget(ctx);
-+
-+ result
-+ }
-+
-+ unsafe {
-+ ffi::pa_context_set_state_callback(self.raw_mut(), Some(wrapped::<CB>), 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<Option<&'a CStr>>
-+ {
-+ 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<CB>(&self, _: CB, userdata: *mut c_void) -> Result<Operation>
-+ where CB: Fn(&Context, *mut c_void)
-+ {
-+ debug_assert_eq!(::std::mem::size_of::<CB>(), 0);
-+
-+ // See: A note about `wrapped` functions
-+ unsafe extern "C" fn wrapped<F>(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::<F>()(&ctx, userdata);
-+ forget(ctx);
-+
-+ result
-+ }
-+
-+ op_or_err!(self,
-+ ffi::pa_context_drain(self.raw_mut(), Some(wrapped::<CB>), userdata))
-+ }
-+
-+ pub fn rttime_new<CB>(&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::<CB>(), 0);
-+
-+ // See: A note about `wrapped` functions
-+ unsafe extern "C" fn wrapped<F>(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::<F>()(&api, e, timeval, userdata);
-+ forget(api);
-+
-+ result
-+ }
-+
-+ unsafe { ffi::pa_context_rttime_new(self.raw_mut(), usec, Some(wrapped::<CB>), userdata) }
-+ }
-+
-+ pub fn get_server_info<CB>(&self, _: CB, userdata: *mut c_void) -> Result<Operation>
-+ where CB: Fn(&Context, &ServerInfo, *mut c_void)
-+ {
-+ debug_assert_eq!(::std::mem::size_of::<CB>(), 0);
-+
-+ // See: A note about `wrapped` functions
-+ unsafe extern "C" fn wrapped<F>(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::<F>()(&ctx, info, userdata);
-+ forget(ctx);
-+
-+ result
-+ }
-+
-+ op_or_err!(self,
-+ ffi::pa_context_get_server_info(self.raw_mut(), Some(wrapped::<CB>), userdata))
-+ }
-+
-+ pub fn get_sink_info_by_name<CB>(&self, name: &CStr, _: CB, userdata: *mut c_void) -> Result<Operation>
-+ where CB: Fn(&Context, *const SinkInfo, i32, *mut c_void)
-+ {
-+ debug_assert_eq!(::std::mem::size_of::<CB>(), 0);
-+
-+ // See: A note about `wrapped` functions
-+ unsafe extern "C" fn wrapped<F>(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::<F>()(&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::<CB>), userdata))
-+ }
-+
-+ pub fn get_sink_info_list<CB>(&self, _: CB, userdata: *mut c_void) -> Result<Operation>
-+ where CB: Fn(&Context, *const SinkInfo, i32, *mut c_void)
-+ {
-+ debug_assert_eq!(::std::mem::size_of::<CB>(), 0);
-+
-+ // See: A note about `wrapped` functions
-+ unsafe extern "C" fn wrapped<F>(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::<F>()(&ctx, info, eol, userdata);
-+ forget(ctx);
-+
-+ result
-+ }
-+
-+ op_or_err!(self,
-+ ffi::pa_context_get_sink_info_list(self.raw_mut(), Some(wrapped::<CB>), userdata))
-+ }
-+
-+ pub fn get_sink_input_info<CB>(&self, idx: u32, _: CB, userdata: *mut c_void) -> Result<Operation>
-+ where CB: Fn(&Context, *const SinkInputInfo, i32, *mut c_void)
-+ {
-+ debug_assert_eq!(::std::mem::size_of::<CB>(), 0);
-+
-+ // See: A note about `wrapped` functions
-+ unsafe extern "C" fn wrapped<F>(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::<F>()(&ctx, info, eol, userdata);
-+ forget(ctx);
-+
-+ result
-+ }
-+
-+ op_or_err!(self,
-+ ffi::pa_context_get_sink_input_info(self.raw_mut(), idx, Some(wrapped::<CB>), userdata))
-+ }
-+
-+ pub fn get_source_info_list<CB>(&self, _: CB, userdata: *mut c_void) -> Result<Operation>
-+ where CB: Fn(&Context, *const SourceInfo, i32, *mut c_void)
-+ {
-+ debug_assert_eq!(::std::mem::size_of::<CB>(), 0);
-+
-+ // See: A note about `wrapped` functions
-+ unsafe extern "C" fn wrapped<F>(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::<F>()(&ctx, info, eol, userdata);
-+ forget(ctx);
-+
-+ result
-+ }
-+
-+ op_or_err!(self,
-+ ffi::pa_context_get_source_info_list(self.raw_mut(), Some(wrapped::<CB>), userdata))
-+ }
-+
-+ pub fn set_sink_input_volume<CB>(&self,
-+ idx: u32,
-+ volume: &CVolume,
-+ _: CB,
-+ userdata: *mut c_void)
-+ -> Result<Operation>
-+ where CB: Fn(&Context, i32, *mut c_void)
-+ {
-+ debug_assert_eq!(::std::mem::size_of::<CB>(), 0);
-+
-+ // See: A note about `wrapped` functions
-+ unsafe extern "C" fn wrapped<F>(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::<F>()(&ctx, success, userdata);
-+ forget(ctx);
-+
-+ result
-+ }
-+
-+ op_or_err!(self,
-+ ffi::pa_context_set_sink_input_volume(self.raw_mut(), idx, volume, Some(wrapped::<CB>), userdata))
-+ }
-+
-+ pub fn subscribe<CB>(&self, m: SubscriptionMask, _: CB, userdata: *mut c_void) -> Result<Operation>
-+ where CB: Fn(&Context, i32, *mut c_void)
-+ {
-+ debug_assert_eq!(::std::mem::size_of::<CB>(), 0);
-+
-+ // See: A note about `wrapped` functions
-+ unsafe extern "C" fn wrapped<F>(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::<F>()(&ctx, success, userdata);
-+ forget(ctx);
-+
-+ result
-+ }
-+
-+ op_or_err!(self,
-+ ffi::pa_context_subscribe(self.raw_mut(), m.into(), Some(wrapped::<CB>), 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<CB>(&self, _: CB, userdata: *mut c_void)
-+ where CB: Fn(&Context, SubscriptionEvent, u32, *mut c_void)
-+ {
-+ debug_assert_eq!(::std::mem::size_of::<CB>(), 0);
-+
-+ // See: A note about `wrapped` functions
-+ unsafe extern "C" fn wrapped<F>(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::<F>()(&ctx, event, idx, userdata);
-+ forget(ctx);
-+
-+ result
-+ }
-+
-+ unsafe {
-+ ffi::pa_context_set_subscribe_callback(self.raw_mut(), Some(wrapped::<CB>), 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<ffi::pa_sample_format_t> 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<Self> {
-+ 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<ffi::pa_context_state_t> 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<Self> {
-+ 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<ffi::pa_stream_state_t> 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<Self> {
-+ if x >= ffi::PA_OPERATION_RUNNING && x <= ffi::PA_OPERATION_CANCELLED {
-+ Some(unsafe { ::std::mem::transmute(x) })
-+ } else {
-+ None
-+ }
-+ }
-+}
-+
-+impl Into<ffi::pa_operation_state_t> 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<ffi::pa_context_flags_t> 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<Self> {
-+ if x >= ffi::PA_DEVICE_TYPE_SINK && x <= ffi::PA_DEVICE_TYPE_SOURCE {
-+ Some(unsafe { ::std::mem::transmute(x) })
-+ } else {
-+ None
-+ }
-+ }
-+}
-+
-+impl Into<ffi::pa_device_type_t> 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<Self> {
-+ if x >= ffi::PA_STREAM_NODIRECTION && x <= ffi::PA_STREAM_UPLOAD {
-+ Some(unsafe { ::std::mem::transmute(x) })
-+ } else {
-+ None
-+ }
-+ }
-+}
-+
-+impl Into<ffi::pa_stream_direction_t> 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<Self> {
-+ 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<ffi::pa_stream_flags_t> 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<Self> {
-+ if (x & !ffi::PA_SUBSCRIPTION_MASK_ALL) == 0 {
-+ Some(unsafe { ::std::mem::transmute(x) })
-+ } else {
-+ None
-+ }
-+ }
-+}
-+
-+impl Into<ffi::pa_subscription_mask_t> 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<Self> {
-+ 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<Self> {
-+ if x >= ffi::PA_SEEK_RELATIVE && x <= ffi::PA_SEEK_RELATIVE_END {
-+ Some(unsafe { ::std::mem::transmute(x) })
-+ } else {
-+ None
-+ }
-+ }
-+}
-+
-+impl Into<ffi::pa_seek_mode_t> 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<SinkFlags> {
-+ 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<ffi::pa_source_flags_t> 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<Self> {
-+ if x >= ffi::PA_PORT_AVAILABLE_UNKNOWN && x <= ffi::PA_PORT_AVAILABLE_YES {
-+ Some(unsafe { ::std::mem::transmute(x) })
-+ } else {
-+ None
-+ }
-+ }
-+}
-+
-+impl Into<ffi::pa_port_available_t> 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<Self> {
-+ 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<ffi::pa_channel_position_t> for ChannelPosition {
-+ fn into(self) -> ffi::pa_channel_position_t {
-+ self as ffi::pa_channel_position_t
-+ }
-+}
-+pub type Result<T> = ::std::result::Result<T, error::ErrorCode>;
-+
-+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<unsafe extern "C" fn(m: *mut ffi::pa_mainloop_api,
-+ userdata: *mut c_void)>;
-+fn wrap_once_cb<F>(_: F) -> pa_once_cb_t
-+ where F: Fn(&MainloopApi, *mut c_void)
-+{
-+ assert!(mem::size_of::<F>() == 0);
-+
-+ unsafe extern "C" fn wrapped<F>(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::<F>)
-+}
-+
-+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<CB>(&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<T>(&self, key: T) -> Option<&CStr>
-+ where T: Into<Vec<u8>>
-+ {
-+ 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<Self>
-+ where CM: Into<Option<&'a ChannelMap>>
-+ {
-+ 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<Context> {
-+ 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<bool> {
-+ let r = unsafe { ffi::pa_stream_is_suspended(self.raw_mut()) };
-+ error_result!(r != 0, r)
-+ }
-+
-+ pub fn is_corked(&self) -> Result<bool> {
-+ 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<Option<&'a CStr>>,
-+ A: Into<Option<&'a BufferAttr>>,
-+ V: Into<Option<&'a CVolume>>,
-+ S: Into<Option<&'a mut Stream>>
-+ {
-+ 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<Option<&'a CStr>>,
-+ A: Into<Option<&'a BufferAttr>>
-+ {
-+ 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<usize> {
-+ 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<usize> {
-+ 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<CB>(&self, _: CB, userdata: *mut c_void) -> Result<Operation>
-+ where CB: Fn(&Stream, i32, *mut c_void)
-+ {
-+ debug_assert_eq!(mem::size_of::<CB>(), 0);
-+
-+ // See: A note about `wrapped` functions
-+ unsafe extern "C" fn wrapped<F>(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::<F>()(&mut stm, success, userdata);
-+ forget(stm);
-+
-+ result
-+ }
-+
-+ let r = unsafe { ffi::pa_stream_update_timing_info(self.raw_mut(), Some(wrapped::<CB>), 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<CB>(&self, _: CB, userdata: *mut c_void)
-+ where CB: Fn(&Stream, *mut c_void)
-+ {
-+ debug_assert_eq!(mem::size_of::<CB>(), 0);
-+
-+ // See: A note about `wrapped` functions
-+ unsafe extern "C" fn wrapped<F>(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::<F>()(&mut stm, userdata);
-+ forget(stm);
-+
-+ result
-+ }
-+
-+ unsafe {
-+ ffi::pa_stream_set_state_callback(self.raw_mut(), Some(wrapped::<CB>), 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<CB>(&self, _: CB, userdata: *mut c_void)
-+ where CB: Fn(&Stream, usize, *mut c_void)
-+ {
-+ debug_assert_eq!(mem::size_of::<CB>(), 0);
-+
-+ // See: A note about `wrapped` functions
-+ unsafe extern "C" fn wrapped<F>(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::<F>()(&mut stm, nbytes, userdata);
-+ forget(stm);
-+
-+ result
-+ }
-+
-+ unsafe {
-+ ffi::pa_stream_set_write_callback(self.raw_mut(), Some(wrapped::<CB>), 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<CB>(&self, _: CB, userdata: *mut c_void)
-+ where CB: Fn(&Stream, usize, *mut c_void)
-+ {
-+ debug_assert_eq!(mem::size_of::<CB>(), 0);
-+
-+ // See: A note about `wrapped` functions
-+ unsafe extern "C" fn wrapped<F>(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::<F>()(&mut stm, nbytes, userdata);
-+ forget(stm);
-+
-+ result
-+ }
-+
-+ unsafe {
-+ ffi::pa_stream_set_read_callback(self.raw_mut(), Some(wrapped::<CB>), userdata);
-+ }
-+ }
-+
-+ pub fn cork<CB>(&self, b: i32, _: CB, userdata: *mut c_void) -> Result<Operation>
-+ where CB: Fn(&Stream, i32, *mut c_void)
-+ {
-+ debug_assert_eq!(mem::size_of::<CB>(), 0);
-+
-+ // See: A note about `wrapped` functions
-+ unsafe extern "C" fn wrapped<F>(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::<F>()(&mut stm, success, userdata);
-+ forget(stm);
-+
-+ result
-+ }
-+
-+ let r = unsafe { ffi::pa_stream_cork(self.raw_mut(), b, Some(wrapped::<CB>), 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<Option<&'a CStr>>
-+{
-+ 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<T, U, F: FnOnce(&T) -> *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>(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 Build Status](https://travis-ci.org/djg/cubeb-pulse-rs.svg?branch=dev)](https://t…
-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<pulse::Context>,
- pub default_sink_info: Option<DefaultInfo>,
-- pub context_name: *const c_char,
-+ pub context_name: Option<CString>,
- 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<Box<Self>> {
-+ fn _new(name: Option<CString>) -> Result<Box<Self>> {
- 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<Box<Self>> {
-+ fn _new(name: Option<CString>) -> Result<Box<Self>> {
- 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<Box<Self>> {
-+ 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<cubeb::StreamParams>,
- output_device: cubeb::DeviceId,
-@@ -178,7 +184,7 @@ impl Context {
- state_callback: cubeb::StateCallback,
- user_ptr: *mut c_void)
- -> Result<Box<Stream>> {
-- 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<cubeb::DeviceCollection> {
-- 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<Option<&'a pulse::Stream>>
-+ {
-+ 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<cubeb::DeviceInfo>,
-- 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<T> = ::std::result::Result<T, i32>;
-
- pub use self::context::Context;
- pub use self::stream::Device;
- pub use self::stream::Stream;
-+
-+// helper to convert *const c_char to Option<CStr>
-+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<pulse::Stream>,
-+ input_stream: Option<pulse::Stream>,
- 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<cubeb::StreamParams>,
- output_device: cubeb::DeviceId,
-@@ -99,83 +101,167 @@ impl<'ctx> Stream<'ctx> {
- user_ptr: *mut c_void)
- -> Result<Box<Stream<'ctx>>> {
-
-+ 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<u64> {
-- 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<u32> {
-- 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<u32> {
-+ 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<Box<cubeb::Device>> {
- 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<pulse::Stream> {
-
-- 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<pa_channel_map> = 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<cubeb::StreamParams> {
-+ 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<GfxDriverInfo>& 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<GfxDriverInfo>& 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 <klember(a)redhat.com> - 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 <jhorak(a)redhat.com> - 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<wr::PipelineId, wr::Epoch> key(aPipelineId, aEpoch);
-- nsTArray<CompositionPayload> 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<ImageCompositeNotificationInfo> notifications;
-- mWrBridge->ExtractImageCompositeNotifications(¬ifications);
-- if (!notifications.IsEmpty()) {
-- Unused << ImageBridgeParent::NotifyImageComposites(notifications);
-- }
-+ if (mIsForcedFirstPaint) {
-+ uiController->NotifyFirstPaint();
-+ mIsForcedFirstPaint = false;
-+ }
-+
-+ std::pair<wr::PipelineId, wr::Epoch> key(aPipelineId, aEpoch);
-+ nsTArray<CompositionPayload> 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<ImageCompositeNotificationInfo> 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<wr::PipelineId, wr::Epoch> key(aPipelineId, aEpoch);
-- nsTArray<CompositionPayload> 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<wr::PipelineId, wr::Epoch> key(aPipelineId, aEpoch);
-+ nsTArray<CompositionPayload> 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 <stransky(a)redhat.com>
-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<nsWaylandDisplay> 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<nsWaylandDisplay> 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<nsWaylandDisplay> 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<WindowBackBuffer*>(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<nsWaylandDisplay> aDisplay, int aSize);
-- ~WaylandShmPool();
--
-- bool Resize(int aSize);
-+ bool Create(RefPtr<nsWaylandDisplay> 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<gfx::DrawTarget> 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=…
-+ // https://source.chromium.org/chromium/chromium/src/+/master:components/cdm/c…
- //
- // Gecko's internal strings can be found at
- // https://searchfox.org/mozilla-central/rev/ea63a0888d406fae720cf24f4727d8756…
-@@ -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 <stransky(a)redhat.com>
-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<LIBAV_VER>::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 <stransky(a)redhat.com>
-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<nsString, 1> 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 =
- "<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection "
- "1.0//EN\"\n"
-- "\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\";>\n"
-+ "\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n"
- "<node>\n"
- " <interface name=\"org.freedesktop.DBus.Introspectable\">\n"
- " <method name=\"Introspect\">\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<nsINSSComponent> 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"}
commit 1ad3bd1b2451eba507ab60632c8e4b5c9325f21e
Author: Kalev Lember <klember(a)redhat.com>
Date: Wed Aug 17 10:26:14 2022 +0200
Drop obsolete build conditionals
This drops ifarch conditionals on architectures that are no longer used
in koji (ppc64, s390, arm on F37+), and conditionals on EOL Fedora
versions.
diff --git a/firefox.spec b/firefox.spec
index ea8a25b..f970fe1 100644
--- a/firefox.spec
+++ b/firefox.spec
@@ -33,18 +33,6 @@
# https://bugzilla.redhat.com/show_bug.cgi?id=1897522
ExcludeArch: s390x
-# Disabled due to
-# https://bugzilla.redhat.com/show_bug.cgi?id=1966949
-%if 0%{?fedora} > 36
-ExcludeArch: armv7hl
-%endif
-
-# Disabled due to
-# https://bugzilla.redhat.com/show_bug.cgi?id=2019160
-%if 0%{?fedora} == 33
-ExcludeArch: aarch64
-%endif
-
%ifarch armv7hl
%global create_debuginfo 0
@@ -96,7 +84,7 @@ ExcludeArch: aarch64
%global build_with_pgo 0
%endif
# Big endian platforms
-%ifarch ppc64 s390x
+%ifarch s390x
%global big_endian 1
%endif
@@ -214,7 +202,6 @@ Source45: run-wayland-compositor
# Build patches
Patch3: mozilla-build-arm.patch
-Patch25: rhbz-1219542-s390-build.patch
Patch32: build-rust-ppc64le.patch
Patch35: build-ppc-jit.patch
# Fixing missing cacheFlush when JS_CODEGEN_NONE is used (s390x)
@@ -391,10 +378,7 @@ BuildRequires: liberation-mono-fonts
BuildRequires: liberation-sans-fonts
BuildRequires: liberation-serif-fonts
# ----------------------------------
-# Missing on f32
-%if 0%{?fedora} > 33
BuildRequires: google-carlito-fonts
-%endif
BuildRequires: google-droid-sans-fonts
BuildRequires: google-noto-fonts-common
BuildRequires: google-noto-cjk-fonts-common
@@ -413,10 +397,7 @@ BuildRequires: lohit-tamil-fonts
BuildRequires: lohit-telugu-fonts
# ----------------------------------
BuildRequires: paktype-naskh-basic-fonts
-# faild to build in Koji / f32
-%if 0%{?fedora} > 33
BuildRequires: pt-sans-fonts
-%endif
BuildRequires: smc-meera-fonts
BuildRequires: stix-fonts
BuildRequires: abattis-cantarell-fonts
@@ -485,9 +466,6 @@ This package contains results of tests executed during build.
# there is a compare of config and js/config directories and .orig suffix is
# ignored during this compare.
-%ifarch s390
-%patch25 -p1 -b .rhbz-1219542-s390
-%endif
%patch40 -p1 -b .aarch64-skia
%if 0%{?disable_elfhack}
%patch41 -p1 -b .disable-elfhack
@@ -612,7 +590,7 @@ echo "ac_add_options --with-system-libvpx" >> .mozconfig
echo "ac_add_options --without-system-libvpx" >> .mozconfig
%endif
-%ifarch s390 s390x
+%ifarch s390x
echo "ac_add_options --disable-jit" >> .mozconfig
%endif
@@ -676,34 +654,24 @@ MOZ_OPT_FLAGS=$(echo "%{optflags}" | %{__sed} -e 's/-Wall//')
# for some sources
# Explicitly force the hardening flags for Firefox so it passes the checksec test;
# See also https://fedoraproject.org/wiki/Changes/Harden_All_Packages
-%if 0%{?fedora} < 30
-MOZ_OPT_FLAGS="$MOZ_OPT_FLAGS -Wformat-security -Wformat -Werror=format-security"
-%else
# Workaround for mozbz#1531309
MOZ_OPT_FLAGS=$(echo "$MOZ_OPT_FLAGS" | %{__sed} -e 's/-Werror=format-security//')
-%endif
-%if 0%{?fedora} > 30
MOZ_OPT_FLAGS="$MOZ_OPT_FLAGS -fpermissive"
-%endif
%if %{?hardened_build}
MOZ_OPT_FLAGS="$MOZ_OPT_FLAGS -fPIC -Wl,-z,relro -Wl,-z,now"
%endif
%if %{?debug_build}
MOZ_OPT_FLAGS=$(echo "$MOZ_OPT_FLAGS" | %{__sed} -e 's/-O2//')
%endif
-%ifarch s390
-MOZ_OPT_FLAGS=$(echo "$MOZ_OPT_FLAGS" | %{__sed} -e 's/-g/-g1/')
# If MOZ_DEBUG_FLAGS is empty, firefox's build will default it to "-g" which
# overrides the -g1 from line above and breaks building on s390/arm
# (OOM when linking, rhbz#1238225)
-export MOZ_DEBUG_FLAGS=" "
-%endif
%ifarch %{arm} %{ix86}
MOZ_OPT_FLAGS=$(echo "$MOZ_OPT_FLAGS" | %{__sed} -e 's/-g/-g0/')
export MOZ_DEBUG_FLAGS=" "
%endif
%if !%{build_with_clang}
-%ifarch s390 ppc aarch64 %{ix86}
+%ifarch aarch64 %{ix86}
MOZ_LINK_FLAGS="-Wl,--no-keep-memory -Wl,--reduce-memory-overheads"
%endif
%ifarch %{arm}
@@ -1107,6 +1075,7 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || :
%changelog
* Tue Aug 23 2022 Kalev Lember <klember(a)redhat.com> - 104.0-5
- Use constrain_build macro to simplify parallel make handling
+- Drop obsolete build conditionals
* Tue Aug 23 2022 Jan Horak <jhorak(a)redhat.com> - 104.0-4
- Rebuild due to ppc64le fixes
diff --git a/rhbz-1219542-s390-build.patch b/rhbz-1219542-s390-build.patch
deleted file mode 100644
index f94e43a..0000000
--- a/rhbz-1219542-s390-build.patch
+++ /dev/null
@@ -1,23 +0,0 @@
-diff -up firefox-55.0/js/src/old-configure.in.rhbz-1219542-s390 firefox-55.0/js/src/old-configure.in
---- firefox-55.0/js/src/old-configure.in.rhbz-1219542-s390 2017-07-31 18:20:48.000000000 +0200
-+++ firefox-55.0/js/src/old-configure.in 2017-08-02 14:31:32.190243669 +0200
-@@ -541,7 +541,7 @@ case "$host" in
-
- *-linux*|*-kfreebsd*-gnu|*-gnu*)
- HOST_CFLAGS="$HOST_CFLAGS -DXP_UNIX"
-- HOST_OPTIMIZE_FLAGS="${HOST_OPTIMIZE_FLAGS=-O3}"
-+ HOST_OPTIMIZE_FLAGS="${HOST_OPTIMIZE_FLAGS=-O1}"
- ;;
-
- *)
-@@ -617,8 +617,8 @@ case "$target" in
-
- *-*linux*)
- if test "$GNU_CC" -o "$GNU_CXX"; then
-- MOZ_PGO_OPTIMIZE_FLAGS="-O3"
-- MOZ_OPTIMIZE_FLAGS="-O3"
-+ MOZ_PGO_OPTIMIZE_FLAGS="-O1"
-+ MOZ_OPTIMIZE_FLAGS="-O1"
- if test -z "$CLANG_CC"; then
- MOZ_OPTIMIZE_FLAGS="-freorder-blocks $MOZ_OPTIMIZE_FLAGS"
- fi
commit 7e1b07c41aea995e1618e073e8c3a1718a6b6249
Author: Kalev Lember <klember(a)redhat.com>
Date: Wed Aug 17 10:25:36 2022 +0200
Use constrain_build macro to simplify parallel make handling
With constrain_build it is possible to just say how much RAM per process
/ CPU core we need to build and it automatically calculates out the
right -jXX number to use.
I've used 2 GB per CPU as the initial setting, but if we run into issues
with gcc running out of memory on e.g. s390x, the number can be easily
increased (which then reduces parallelism on low memory builders).
diff --git a/firefox.spec b/firefox.spec
index b3cfd98..ea8a25b 100644
--- a/firefox.spec
+++ b/firefox.spec
@@ -177,7 +177,7 @@ ExcludeArch: aarch64
Summary: Mozilla Firefox Web browser
Name: firefox
Version: 104.0
-Release: 4%{?pre_tag}%{?dist}
+Release: 5%{?pre_tag}%{?dist}
URL: https://www.mozilla.org/firefox/
License: MPLv1.1 or GPLv2+ or LGPLv2+
Source0: https://archive.mozilla.org/pub/firefox/releases/%{version}%{?pre_version}/…
@@ -760,27 +760,10 @@ echo "ac_add_options MOZ_PGO=1" >> .mozconfig
export CCACHE_DISABLE=1
%endif
-MOZ_SMP_FLAGS=-j1
-# On x86_64 architectures, Mozilla can build up to 4 jobs at once in parallel,
-# however builds tend to fail on other arches when building in parallel.
-%ifarch %{ix86} s390x %{arm} aarch64
-[ -z "$RPM_BUILD_NCPUS" ] && \
- RPM_BUILD_NCPUS="`/usr/bin/getconf _NPROCESSORS_ONLN`"
-[ "$RPM_BUILD_NCPUS" -ge 2 ] && MOZ_SMP_FLAGS=-j2
-%endif
-%ifarch x86_64 ppc ppc64 ppc64le
-[ -z "$RPM_BUILD_NCPUS" ] && \
- RPM_BUILD_NCPUS="`/usr/bin/getconf _NPROCESSORS_ONLN`"
-[ "$RPM_BUILD_NCPUS" -ge 2 ] && MOZ_SMP_FLAGS=-j2
-[ "$RPM_BUILD_NCPUS" -ge 4 ] && MOZ_SMP_FLAGS=-j4
-[ "$RPM_BUILD_NCPUS" -ge 8 ] && MOZ_SMP_FLAGS=-j8
-[ "$RPM_BUILD_NCPUS" -ge 16 ] && MOZ_SMP_FLAGS=-j16
-[ "$RPM_BUILD_NCPUS" -ge 24 ] && MOZ_SMP_FLAGS=-j24
-[ "$RPM_BUILD_NCPUS" -ge 32 ] && MOZ_SMP_FLAGS=-j32
-[ "$RPM_BUILD_NCPUS" -ge 64 ] && MOZ_SMP_FLAGS=-j64
-%endif
+# Require 2 GB of RAM per CPU core
+%constrain_build -m 2048
-echo "mk_add_options MOZ_MAKE_FLAGS=\"$MOZ_SMP_FLAGS\"" >> .mozconfig
+echo "mk_add_options MOZ_MAKE_FLAGS=\"-j%{_smp_build_ncpus}\"" >> .mozconfig
echo "mk_add_options MOZ_SERVICES_SYNC=1" >> .mozconfig
echo "export STRIP=/bin/true" >> .mozconfig
#export MACH_USE_SYSTEM_PYTHON=1
@@ -1122,6 +1105,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || :
#---------------------------------------------------------------------
%changelog
+* Tue Aug 23 2022 Kalev Lember <klember(a)redhat.com> - 104.0-5
+- Use constrain_build macro to simplify parallel make handling
+
* Tue Aug 23 2022 Jan Horak <jhorak(a)redhat.com> - 104.0-4
- Rebuild due to ppc64le fixes
The package rpms/firefox.git has added or updated architecture specific content in its
spec file (ExclusiveArch/ExcludeArch or %ifarch/%ifnarch) in commit(s):
https://src.fedoraproject.org/cgit/rpms/firefox.git/commit/?id=f5c2bd2d80a2…
https://src.fedoraproject.org/cgit/rpms/firefox.git/commit/?id=1ad3bd1b2451…
https://src.fedoraproject.org/cgit/rpms/firefox.git/commit/?id=7e1b07c41aea….
Change:
-ExcludeArch: s390x
+%ifarch aarch64 %{ix86}
-%ifarch x86_64 ppc ppc64 ppc64le
Thanks.
Full change:
============
commit f5c2bd2d80a2c69fa7e0f3e5bcda6b16493bf958
Author: Kalev Lember <klember(a)redhat.com>
Date: Wed Aug 17 10:32:01 2022 +0200
Re-enable s390x builds
It builds fine again after latest fixes.
diff --git a/firefox.spec b/firefox.spec
index 26bd17a..9d407b3 100644
--- a/firefox.spec
+++ b/firefox.spec
@@ -28,11 +28,6 @@
%global build_with_clang 0
%endif
-# There are still build problems on s390x, see
-# https://koji.fedoraproject.org/koji/taskinfo?taskID=55048351
-# https://bugzilla.redhat.com/show_bug.cgi?id=1897522
-ExcludeArch: s390x
-
%ifarch armv7hl
%global create_debuginfo 0
@@ -1071,6 +1066,7 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || :
- Drop unused patches
- Use build_ldflags
- Drop hardened_build option
+- Re-enable s390x builds
* Tue Aug 23 2022 Jan Horak <jhorak(a)redhat.com> - 104.0-4
- Rebuild due to ppc64le fixes
commit 73c24a4d458769b6a8560eb855a4f7a2545fe998
Author: Kalev Lember <klember(a)redhat.com>
Date: Wed Aug 17 10:31:20 2022 +0200
Drop hardened_build option
Now that we correctly use Fedora's ldflags (previous commit), there's
no need to do anything special to enable hardened build. All of it is
already included in the default build flags.
diff --git a/firefox.spec b/firefox.spec
index bb7b33f..26bd17a 100644
--- a/firefox.spec
+++ b/firefox.spec
@@ -65,7 +65,6 @@ ExcludeArch: s390x
%else
%global system_libvpx 0
%endif
-%global hardened_build 1
%global system_jpeg 1
%global disable_elfhack 1
%global use_bundled_cbindgen 1
@@ -657,9 +656,6 @@ MOZ_OPT_FLAGS=$(echo "%{optflags}" | %{__sed} -e 's/-Wall//')
# Workaround for mozbz#1531309
MOZ_OPT_FLAGS=$(echo "$MOZ_OPT_FLAGS" | %{__sed} -e 's/-Werror=format-security//')
MOZ_OPT_FLAGS="$MOZ_OPT_FLAGS -fpermissive"
-%if %{?hardened_build}
-MOZ_OPT_FLAGS="$MOZ_OPT_FLAGS -fPIC -Wl,-z,relro -Wl,-z,now"
-%endif
%if %{?debug_build}
MOZ_OPT_FLAGS=$(echo "$MOZ_OPT_FLAGS" | %{__sed} -e 's/-O2//')
%endif
@@ -1074,6 +1070,7 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || :
- Drop obsolete build conditionals
- Drop unused patches
- Use build_ldflags
+- Drop hardened_build option
* Tue Aug 23 2022 Jan Horak <jhorak(a)redhat.com> - 104.0-4
- Rebuild due to ppc64le fixes
commit 078b597b1e74879a6c87fc30ec101b5dd3011057
Author: Kalev Lember <klember(a)redhat.com>
Date: Wed Aug 17 10:30:14 2022 +0200
Use build_ldflags
These are the LDFLAGS that all packages are supposed to use, including
hardening and other flags.
diff --git a/firefox.spec b/firefox.spec
index 221882a..bb7b33f 100644
--- a/firefox.spec
+++ b/firefox.spec
@@ -670,20 +670,16 @@ MOZ_OPT_FLAGS=$(echo "$MOZ_OPT_FLAGS" | %{__sed} -e 's/-O2//')
MOZ_OPT_FLAGS=$(echo "$MOZ_OPT_FLAGS" | %{__sed} -e 's/-g/-g0/')
export MOZ_DEBUG_FLAGS=" "
%endif
+MOZ_LINK_FLAGS="%{build_ldflags}"
%if !%{build_with_clang}
%ifarch aarch64 %{ix86}
-MOZ_LINK_FLAGS="-Wl,--no-keep-memory -Wl,--reduce-memory-overheads"
+MOZ_LINK_FLAGS="$MOZ_LINK_FLAGS -Wl,--no-keep-memory -Wl,--reduce-memory-overheads"
%endif
%ifarch %{arm}
-MOZ_LINK_FLAGS="-Wl,--no-keep-memory -Wl,--strip-debug"
+MOZ_LINK_FLAGS="$MOZ_LINK_FLAGS -Wl,--no-keep-memory -Wl,--strip-debug"
echo "ac_add_options --enable-linker=gold" >> .mozconfig
%endif
%endif
-%if 0%{?flatpak}
-# Make sure the linker can find libraries in /app/lib64 as we don't use
-# __global_ldflags that normally sets this.
-MOZ_LINK_FLAGS="$MOZ_LINK_FLAGS -L%{_libdir}"
-%endif
%ifarch %{arm} %{ix86} %{s390x}
export RUSTFLAGS="-Cdebuginfo=0"
%endif
@@ -1077,6 +1073,7 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || :
- Use constrain_build macro to simplify parallel make handling
- Drop obsolete build conditionals
- Drop unused patches
+- Use build_ldflags
* Tue Aug 23 2022 Jan Horak <jhorak(a)redhat.com> - 104.0-4
- Rebuild due to ppc64le fixes
commit 594959d6f80f090d837c7ca1286459de3aa1769c
Author: Kalev Lember <klember(a)redhat.com>
Date: Wed Aug 17 10:29:03 2022 +0200
Drop unused patches
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<ImageContainer> 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<LIBAV_VER>::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<LIBAV_VER>::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<sandbox::bpf_dsl::Policy> 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<ResultExpr> EvaluateIpcCall(int aCall, int aArgShift) const override {
-@@ -1875,9 +1862,10 @@ UniquePtr<sandbox::bpf_dsl::Policy> 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<sandbox::bpf_dsl::Policy> 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<int> 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<int>(aArgs.args[0]),
-+ static_cast<int>(aArgs.args[1]),
-+ static_cast<int>(aArgs.args[2]));
-+ }
-+
-+ static intptr_t FakeSocketTrapLegacy(ArgsRef aArgs, void* aux) {
-+ const auto innerArgs = reinterpret_cast<unsigned long*>(aArgs.args[1]);
-+
-+ return FakeSocketTrapCommon(static_cast<int>(innerArgs[0]),
-+ static_cast<int>(innerArgs[1]),
-+ static_cast<int>(innerArgs[2]));
-+ }
-+
-+ static Maybe<int> 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<size_t>(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<SandboxBrokerClient*>(aux),
-+ static_cast<int>(aArgs.args[0]),
-+ reinterpret_cast<AddrPtr>(aArgs.args[1]),
-+ static_cast<socklen_t>(aArgs.args[2]));
-+ }
-+
-+ static intptr_t ConnectTrapLegacy(ArgsRef aArgs, void* aux) {
-+ const auto innerArgs = reinterpret_cast<unsigned long*>(aArgs.args[1]);
-+ typedef const struct sockaddr_un* AddrPtr;
-+
-+ return ConnectTrapCommon(static_cast<SandboxBrokerClient*>(aux),
-+ static_cast<int>(innerArgs[0]),
-+ reinterpret_cast<AddrPtr>(innerArgs[1]),
-+ static_cast<socklen_t>(innerArgs[2]));
-+ }
-+
- public:
- ResultExpr InvalidSyscall() const override {
- return Trap(BlockedSyscallTrap, nullptr);
- }
-
-@@ -630,15 +745,37 @@
- return Some(Allow());
- }
- Arg<int> 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<int> 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<int>(aArgs.args[0]),
-- static_cast<int>(aArgs.args[1]),
-- static_cast<int>(aArgs.args[2]));
-- }
--
-- static intptr_t FakeSocketTrapLegacy(ArgsRef aArgs, void* aux) {
-- const auto innerArgs = reinterpret_cast<unsigned long*>(aArgs.args[1]);
--
-- return FakeSocketTrapCommon(static_cast<int>(innerArgs[0]),
-- static_cast<int>(innerArgs[1]),
-- static_cast<int>(innerArgs[2]));
-- }
--
-- static Maybe<int> 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<size_t>(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<SandboxBrokerClient*>(aux),
-- static_cast<int>(aArgs.args[0]),
-- reinterpret_cast<AddrPtr>(aArgs.args[1]),
-- static_cast<socklen_t>(aArgs.args[2]));
-- }
--
-- static intptr_t ConnectTrapLegacy(ArgsRef aArgs, void* aux) {
-- const auto innerArgs = reinterpret_cast<unsigned long*>(aArgs.args[1]);
-- typedef const struct sockaddr_un* AddrPtr;
--
-- return ConnectTrapCommon(static_cast<SandboxBrokerClient*>(aux),
-- static_cast<int>(innerArgs[0]),
-- reinterpret_cast<AddrPtr>(innerArgs[1]),
-- static_cast<socklen_t>(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<ResultExpr> 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<ResultExpr> 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<ResultExpr> 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<ResultExpr> 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 <termios.h>
- # include <sys/resource.h>
- # include <sys/time.h>
- # include <sys/utsname.h>
- # include <sched.h>
-+# include <sys/socket.h>
- # include <sys/syscall.h>
- # include <sys/un.h>
- # include <linux/mempolicy.h>
- # 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<ResultExpr> EvaluateIpcCall(int aCall, int aArgShift) const override {
- // The Intel media driver uses SysV IPC (semaphores and shared
-@@ -1818,15 +1819,15 @@
- #endif
-
- Maybe<ResultExpr> 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<DMABufSurfaceRGBA> CreateDMABufSurface(
- int aWidth, int aHeight, int aDMABufSurfaceFlags);
-
-+ static already_AddRefed<DMABufSurface> 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<EGLint> 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<DMABufSurface> DMABufSurfaceRGBA::CreateDMABufSurface(
-+ mozilla::gl::GLContext* aGLContext, const EGLImageKHR aEGLImage, int aWidth,
-+ int aHeight) {
-+ RefPtr<DMABufSurfaceRGBA> surf = new DMABufSurfaceRGBA();
-+ if (!surf->Create(aGLContext, aEGLImage, aWidth, aHeight)) {
-+ return nullptr;
-+ }
-+ return surf.forget();
-+}
-+
- already_AddRefed<DMABufSurfaceYUV> DMABufSurfaceYUV::CreateYUVSurface(
- const VADRMPRIMESurfaceDescriptor& aDesc, int aWidth, int aHeight) {
- RefPtr<DMABufSurfaceYUV> 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> SharedSurface_DMABUF::Create(
- const SharedSurfaceDesc& desc) {
-- const auto flags = static_cast<DMABufSurfaceFlags>(
-- DMABUF_TEXTURE | DMABUF_USE_MODIFIERS | DMABUF_ALPHA);
-- const RefPtr<DMABufSurface> 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<DMABufSurface> surface;
-+ UniquePtr<MozFramebuffer> 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<DMABufSurfaceFlags>(
-+ 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<EGLClientBuffer>(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<SurfaceFactory_DMABUF> Surface
- }
-
- auto dmabufFactory = MakeUnique<SurfaceFactory_DMABUF>(gl);
-- if (dmabufFactory->CanCreateSurface()) {
-+ if (dmabufFactory->CanCreateSurface(gl)) {
- return dmabufFactory;
- }
-
-@@ -71,8 +104,38 @@ UniquePtr<SurfaceFactory_DMABUF> Surface
- return nullptr;
- }
-
-+bool SurfaceFactory_DMABUF::CanCreateSurface(GLContext& gl) {
-+ UniquePtr<SharedSurface> 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<DMABufSurface> 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<SharedSurface> 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<GfxDriverInfo>& 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> GLContextEGL::Creat
- }
-
- /*static*/
--RefPtr<GLContextEGL> GLContextEGL::CreateEGLSurfacelessContext(
-- const std::shared_ptr<EglDisplay> display, const GLContextCreateDesc& desc,
-- nsACString* const out_failureId) {
-- const EGLConfig config = {};
-- auto fullDesc = GLContextDesc{desc};
-- fullDesc.isOffscreen = true;
-- RefPtr<GLContextEGL> 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<GLContext> GLContextProviderEGL::CreateHeadless(
- const GLContextCreateDesc& desc, nsACString* const out_failureId) {
- const auto display = DefaultEglDisplay(out_failureId);
- if (!display) {
- return nullptr;
- }
-- RefPtr<GLContextEGL> 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> 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<EglDisplay> GetAn
- }
-
- #ifdef MOZ_WAYLAND
-+static std::shared_ptr<EglDisplay> 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<EGLDeviceEXT> 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<EglDisplay> 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<EglDisplay> 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 <dglastonbury(a)mozilla.com>"]
-+
-+[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<T>(...)` 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<CB>(&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::<F>() == 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::<F>()(&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<Self>
-+ where OPT: Into<Option<&'a CStr>>
-+ {
-+ 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<CB>(&self, _: CB, userdata: *mut c_void)
-+ where CB: Fn(&Context, *mut c_void)
-+ {
-+ debug_assert_eq!(::std::mem::size_of::<CB>(), 0);
-+
-+ // See: A note about `wrapped` functions
-+ unsafe extern "C" fn wrapped<F>(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::<F>()(&ctx, userdata);
-+ forget(ctx);
-+
-+ result
-+ }
-+
-+ unsafe {
-+ ffi::pa_context_set_state_callback(self.raw_mut(), Some(wrapped::<CB>), 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<Option<&'a CStr>>
-+ {
-+ 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<CB>(&self, _: CB, userdata: *mut c_void) -> Result<Operation>
-+ where CB: Fn(&Context, *mut c_void)
-+ {
-+ debug_assert_eq!(::std::mem::size_of::<CB>(), 0);
-+
-+ // See: A note about `wrapped` functions
-+ unsafe extern "C" fn wrapped<F>(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::<F>()(&ctx, userdata);
-+ forget(ctx);
-+
-+ result
-+ }
-+
-+ op_or_err!(self,
-+ ffi::pa_context_drain(self.raw_mut(), Some(wrapped::<CB>), userdata))
-+ }
-+
-+ pub fn rttime_new<CB>(&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::<CB>(), 0);
-+
-+ // See: A note about `wrapped` functions
-+ unsafe extern "C" fn wrapped<F>(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::<F>()(&api, e, timeval, userdata);
-+ forget(api);
-+
-+ result
-+ }
-+
-+ unsafe { ffi::pa_context_rttime_new(self.raw_mut(), usec, Some(wrapped::<CB>), userdata) }
-+ }
-+
-+ pub fn get_server_info<CB>(&self, _: CB, userdata: *mut c_void) -> Result<Operation>
-+ where CB: Fn(&Context, &ServerInfo, *mut c_void)
-+ {
-+ debug_assert_eq!(::std::mem::size_of::<CB>(), 0);
-+
-+ // See: A note about `wrapped` functions
-+ unsafe extern "C" fn wrapped<F>(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::<F>()(&ctx, info, userdata);
-+ forget(ctx);
-+
-+ result
-+ }
-+
-+ op_or_err!(self,
-+ ffi::pa_context_get_server_info(self.raw_mut(), Some(wrapped::<CB>), userdata))
-+ }
-+
-+ pub fn get_sink_info_by_name<CB>(&self, name: &CStr, _: CB, userdata: *mut c_void) -> Result<Operation>
-+ where CB: Fn(&Context, *const SinkInfo, i32, *mut c_void)
-+ {
-+ debug_assert_eq!(::std::mem::size_of::<CB>(), 0);
-+
-+ // See: A note about `wrapped` functions
-+ unsafe extern "C" fn wrapped<F>(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::<F>()(&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::<CB>), userdata))
-+ }
-+
-+ pub fn get_sink_info_list<CB>(&self, _: CB, userdata: *mut c_void) -> Result<Operation>
-+ where CB: Fn(&Context, *const SinkInfo, i32, *mut c_void)
-+ {
-+ debug_assert_eq!(::std::mem::size_of::<CB>(), 0);
-+
-+ // See: A note about `wrapped` functions
-+ unsafe extern "C" fn wrapped<F>(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::<F>()(&ctx, info, eol, userdata);
-+ forget(ctx);
-+
-+ result
-+ }
-+
-+ op_or_err!(self,
-+ ffi::pa_context_get_sink_info_list(self.raw_mut(), Some(wrapped::<CB>), userdata))
-+ }
-+
-+ pub fn get_sink_input_info<CB>(&self, idx: u32, _: CB, userdata: *mut c_void) -> Result<Operation>
-+ where CB: Fn(&Context, *const SinkInputInfo, i32, *mut c_void)
-+ {
-+ debug_assert_eq!(::std::mem::size_of::<CB>(), 0);
-+
-+ // See: A note about `wrapped` functions
-+ unsafe extern "C" fn wrapped<F>(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::<F>()(&ctx, info, eol, userdata);
-+ forget(ctx);
-+
-+ result
-+ }
-+
-+ op_or_err!(self,
-+ ffi::pa_context_get_sink_input_info(self.raw_mut(), idx, Some(wrapped::<CB>), userdata))
-+ }
-+
-+ pub fn get_source_info_list<CB>(&self, _: CB, userdata: *mut c_void) -> Result<Operation>
-+ where CB: Fn(&Context, *const SourceInfo, i32, *mut c_void)
-+ {
-+ debug_assert_eq!(::std::mem::size_of::<CB>(), 0);
-+
-+ // See: A note about `wrapped` functions
-+ unsafe extern "C" fn wrapped<F>(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::<F>()(&ctx, info, eol, userdata);
-+ forget(ctx);
-+
-+ result
-+ }
-+
-+ op_or_err!(self,
-+ ffi::pa_context_get_source_info_list(self.raw_mut(), Some(wrapped::<CB>), userdata))
-+ }
-+
-+ pub fn set_sink_input_volume<CB>(&self,
-+ idx: u32,
-+ volume: &CVolume,
-+ _: CB,
-+ userdata: *mut c_void)
-+ -> Result<Operation>
-+ where CB: Fn(&Context, i32, *mut c_void)
-+ {
-+ debug_assert_eq!(::std::mem::size_of::<CB>(), 0);
-+
-+ // See: A note about `wrapped` functions
-+ unsafe extern "C" fn wrapped<F>(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::<F>()(&ctx, success, userdata);
-+ forget(ctx);
-+
-+ result
-+ }
-+
-+ op_or_err!(self,
-+ ffi::pa_context_set_sink_input_volume(self.raw_mut(), idx, volume, Some(wrapped::<CB>), userdata))
-+ }
-+
-+ pub fn subscribe<CB>(&self, m: SubscriptionMask, _: CB, userdata: *mut c_void) -> Result<Operation>
-+ where CB: Fn(&Context, i32, *mut c_void)
-+ {
-+ debug_assert_eq!(::std::mem::size_of::<CB>(), 0);
-+
-+ // See: A note about `wrapped` functions
-+ unsafe extern "C" fn wrapped<F>(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::<F>()(&ctx, success, userdata);
-+ forget(ctx);
-+
-+ result
-+ }
-+
-+ op_or_err!(self,
-+ ffi::pa_context_subscribe(self.raw_mut(), m.into(), Some(wrapped::<CB>), 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<CB>(&self, _: CB, userdata: *mut c_void)
-+ where CB: Fn(&Context, SubscriptionEvent, u32, *mut c_void)
-+ {
-+ debug_assert_eq!(::std::mem::size_of::<CB>(), 0);
-+
-+ // See: A note about `wrapped` functions
-+ unsafe extern "C" fn wrapped<F>(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::<F>()(&ctx, event, idx, userdata);
-+ forget(ctx);
-+
-+ result
-+ }
-+
-+ unsafe {
-+ ffi::pa_context_set_subscribe_callback(self.raw_mut(), Some(wrapped::<CB>), 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<ffi::pa_sample_format_t> 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<Self> {
-+ 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<ffi::pa_context_state_t> 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<Self> {
-+ 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<ffi::pa_stream_state_t> 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<Self> {
-+ if x >= ffi::PA_OPERATION_RUNNING && x <= ffi::PA_OPERATION_CANCELLED {
-+ Some(unsafe { ::std::mem::transmute(x) })
-+ } else {
-+ None
-+ }
-+ }
-+}
-+
-+impl Into<ffi::pa_operation_state_t> 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<ffi::pa_context_flags_t> 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<Self> {
-+ if x >= ffi::PA_DEVICE_TYPE_SINK && x <= ffi::PA_DEVICE_TYPE_SOURCE {
-+ Some(unsafe { ::std::mem::transmute(x) })
-+ } else {
-+ None
-+ }
-+ }
-+}
-+
-+impl Into<ffi::pa_device_type_t> 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<Self> {
-+ if x >= ffi::PA_STREAM_NODIRECTION && x <= ffi::PA_STREAM_UPLOAD {
-+ Some(unsafe { ::std::mem::transmute(x) })
-+ } else {
-+ None
-+ }
-+ }
-+}
-+
-+impl Into<ffi::pa_stream_direction_t> 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<Self> {
-+ 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<ffi::pa_stream_flags_t> 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<Self> {
-+ if (x & !ffi::PA_SUBSCRIPTION_MASK_ALL) == 0 {
-+ Some(unsafe { ::std::mem::transmute(x) })
-+ } else {
-+ None
-+ }
-+ }
-+}
-+
-+impl Into<ffi::pa_subscription_mask_t> 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<Self> {
-+ 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<Self> {
-+ if x >= ffi::PA_SEEK_RELATIVE && x <= ffi::PA_SEEK_RELATIVE_END {
-+ Some(unsafe { ::std::mem::transmute(x) })
-+ } else {
-+ None
-+ }
-+ }
-+}
-+
-+impl Into<ffi::pa_seek_mode_t> 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<SinkFlags> {
-+ 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<ffi::pa_source_flags_t> 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<Self> {
-+ if x >= ffi::PA_PORT_AVAILABLE_UNKNOWN && x <= ffi::PA_PORT_AVAILABLE_YES {
-+ Some(unsafe { ::std::mem::transmute(x) })
-+ } else {
-+ None
-+ }
-+ }
-+}
-+
-+impl Into<ffi::pa_port_available_t> 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<Self> {
-+ 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<ffi::pa_channel_position_t> for ChannelPosition {
-+ fn into(self) -> ffi::pa_channel_position_t {
-+ self as ffi::pa_channel_position_t
-+ }
-+}
-+pub type Result<T> = ::std::result::Result<T, error::ErrorCode>;
-+
-+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<unsafe extern "C" fn(m: *mut ffi::pa_mainloop_api,
-+ userdata: *mut c_void)>;
-+fn wrap_once_cb<F>(_: F) -> pa_once_cb_t
-+ where F: Fn(&MainloopApi, *mut c_void)
-+{
-+ assert!(mem::size_of::<F>() == 0);
-+
-+ unsafe extern "C" fn wrapped<F>(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::<F>)
-+}
-+
-+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<CB>(&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<T>(&self, key: T) -> Option<&CStr>
-+ where T: Into<Vec<u8>>
-+ {
-+ 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<Self>
-+ where CM: Into<Option<&'a ChannelMap>>
-+ {
-+ 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<Context> {
-+ 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<bool> {
-+ let r = unsafe { ffi::pa_stream_is_suspended(self.raw_mut()) };
-+ error_result!(r != 0, r)
-+ }
-+
-+ pub fn is_corked(&self) -> Result<bool> {
-+ 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<Option<&'a CStr>>,
-+ A: Into<Option<&'a BufferAttr>>,
-+ V: Into<Option<&'a CVolume>>,
-+ S: Into<Option<&'a mut Stream>>
-+ {
-+ 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<Option<&'a CStr>>,
-+ A: Into<Option<&'a BufferAttr>>
-+ {
-+ 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<usize> {
-+ 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<usize> {
-+ 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<CB>(&self, _: CB, userdata: *mut c_void) -> Result<Operation>
-+ where CB: Fn(&Stream, i32, *mut c_void)
-+ {
-+ debug_assert_eq!(mem::size_of::<CB>(), 0);
-+
-+ // See: A note about `wrapped` functions
-+ unsafe extern "C" fn wrapped<F>(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::<F>()(&mut stm, success, userdata);
-+ forget(stm);
-+
-+ result
-+ }
-+
-+ let r = unsafe { ffi::pa_stream_update_timing_info(self.raw_mut(), Some(wrapped::<CB>), 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<CB>(&self, _: CB, userdata: *mut c_void)
-+ where CB: Fn(&Stream, *mut c_void)
-+ {
-+ debug_assert_eq!(mem::size_of::<CB>(), 0);
-+
-+ // See: A note about `wrapped` functions
-+ unsafe extern "C" fn wrapped<F>(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::<F>()(&mut stm, userdata);
-+ forget(stm);
-+
-+ result
-+ }
-+
-+ unsafe {
-+ ffi::pa_stream_set_state_callback(self.raw_mut(), Some(wrapped::<CB>), 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<CB>(&self, _: CB, userdata: *mut c_void)
-+ where CB: Fn(&Stream, usize, *mut c_void)
-+ {
-+ debug_assert_eq!(mem::size_of::<CB>(), 0);
-+
-+ // See: A note about `wrapped` functions
-+ unsafe extern "C" fn wrapped<F>(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::<F>()(&mut stm, nbytes, userdata);
-+ forget(stm);
-+
-+ result
-+ }
-+
-+ unsafe {
-+ ffi::pa_stream_set_write_callback(self.raw_mut(), Some(wrapped::<CB>), 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<CB>(&self, _: CB, userdata: *mut c_void)
-+ where CB: Fn(&Stream, usize, *mut c_void)
-+ {
-+ debug_assert_eq!(mem::size_of::<CB>(), 0);
-+
-+ // See: A note about `wrapped` functions
-+ unsafe extern "C" fn wrapped<F>(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::<F>()(&mut stm, nbytes, userdata);
-+ forget(stm);
-+
-+ result
-+ }
-+
-+ unsafe {
-+ ffi::pa_stream_set_read_callback(self.raw_mut(), Some(wrapped::<CB>), userdata);
-+ }
-+ }
-+
-+ pub fn cork<CB>(&self, b: i32, _: CB, userdata: *mut c_void) -> Result<Operation>
-+ where CB: Fn(&Stream, i32, *mut c_void)
-+ {
-+ debug_assert_eq!(mem::size_of::<CB>(), 0);
-+
-+ // See: A note about `wrapped` functions
-+ unsafe extern "C" fn wrapped<F>(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::<F>()(&mut stm, success, userdata);
-+ forget(stm);
-+
-+ result
-+ }
-+
-+ let r = unsafe { ffi::pa_stream_cork(self.raw_mut(), b, Some(wrapped::<CB>), 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<Option<&'a CStr>>
-+{
-+ 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<T, U, F: FnOnce(&T) -> *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>(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 Build Status](https://travis-ci.org/djg/cubeb-pulse-rs.svg?branch=dev)](https://t…
-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<pulse::Context>,
- pub default_sink_info: Option<DefaultInfo>,
-- pub context_name: *const c_char,
-+ pub context_name: Option<CString>,
- 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<Box<Self>> {
-+ fn _new(name: Option<CString>) -> Result<Box<Self>> {
- 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<Box<Self>> {
-+ fn _new(name: Option<CString>) -> Result<Box<Self>> {
- 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<Box<Self>> {
-+ 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<cubeb::StreamParams>,
- output_device: cubeb::DeviceId,
-@@ -178,7 +184,7 @@ impl Context {
- state_callback: cubeb::StateCallback,
- user_ptr: *mut c_void)
- -> Result<Box<Stream>> {
-- 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<cubeb::DeviceCollection> {
-- 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<Option<&'a pulse::Stream>>
-+ {
-+ 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<cubeb::DeviceInfo>,
-- 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<T> = ::std::result::Result<T, i32>;
-
- pub use self::context::Context;
- pub use self::stream::Device;
- pub use self::stream::Stream;
-+
-+// helper to convert *const c_char to Option<CStr>
-+fn try_cstr_from<'str>(s: *const c_char) -> Option<&'str CStr> {
-+ if s.is_nul